summaryrefslogtreecommitdiffhomepage
path: root/packages/api/src/app.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-22 15:24:13 +0900
committerAdam Malczewski <[email protected]>2026-05-22 15:24:13 +0900
commit9ecaabd87c0e51b8a7408dabb0133a9344586859 (patch)
tree4b5809ab23948a5e3f558f3aa34c52d5038f4e19 /packages/api/src/app.ts
parent8f1dd855f0c4c877bff8d3a4ba193432b268b1c2 (diff)
downloaddispatch-9ecaabd87c0e51b8a7408dabb0133a9344586859.tar.gz
dispatch-9ecaabd87c0e51b8a7408dabb0133a9344586859.zip
feat: agent builder, CWD support, auto-save, UI polish, unavailable tool handling
- Agent Builder: full CRUD with card grid, drag-and-drop model reorder, edit/delete - Auto-save on edit with 600ms debounce, AbortController for concurrency, fieldset disabled until name entered - Agent definitions stored as TOML with cwd field, loaded from global/project dirs - Working directory: per-tab CWD override in Chat Settings, agent default CWD, auto-create on first message - CWD validation: check-dir endpoint with ~ expansion, real-time validity indicator - Subagent CWD validated against parent's effective CWD using path.relative - Unavailable tool calls: caught gracefully, shown as tool call with error badge, model retries - UI: tab bar border radius, sidebar border removed, chat input ghost style, scroll-to-bottom rectangle - Skills dir collapse uses CSS rotation, Model Choice renamed to Chat Settings, System Prompt view removed - Reusable SkillsBrowser/ToolPermissions with external mode for Agent Builder - ModelSelector: Agent/Manual toggle, agent list, Agent Settings link - Page router, skills recursive scanning, bin/up gopass removed, docker volume mounts
Diffstat (limited to 'packages/api/src/app.ts')
-rw-r--r--packages/api/src/app.ts23
1 files changed, 17 insertions, 6 deletions
diff --git a/packages/api/src/app.ts b/packages/api/src/app.ts
index f5588a6..37514c3 100644
--- a/packages/api/src/app.ts
+++ b/packages/api/src/app.ts
@@ -2,9 +2,10 @@ import { Hono } from "hono";
import { cors } from "hono/cors";
import { AgentManager } from "./agent-manager.js";
import { PermissionManager } from "./permission-manager.js";
+import { agentsRoutes } from "./routes/agents.js";
import { configRoutes } from "./routes/config.js";
-import { skillsRoutes } from "./routes/skills.js";
import { modelsRoutes, startWakeScheduler } from "./routes/models.js";
+import { skillsRoutes } from "./routes/skills.js";
import { tabsRoutes } from "./routes/tabs.js";
export const permissionManager = new PermissionManager();
@@ -35,7 +36,14 @@ app.get("/status", (c) => {
});
app.post("/chat", async (c) => {
- const body = await c.req.json<{ tabId?: unknown; message?: unknown; keyId?: unknown; modelId?: unknown; reasoningEffort?: unknown }>();
+ const body = await c.req.json<{
+ tabId?: unknown;
+ message?: unknown;
+ keyId?: unknown;
+ modelId?: unknown;
+ reasoningEffort?: unknown;
+ workingDirectory?: unknown;
+ }>();
const { tabId, message } = body;
if (typeof tabId !== "string" || tabId.trim() === "") {
@@ -52,13 +60,15 @@ app.post("/chat", async (c) => {
const keyId = typeof body.keyId === "string" ? body.keyId : undefined;
const modelId = typeof body.modelId === "string" ? body.modelId : undefined;
+ const workingDirectory = typeof body.workingDirectory === "string" ? body.workingDirectory : undefined;
const validEfforts = ["none", "low", "medium", "high", "max"];
- const reasoningEffort = typeof body.reasoningEffort === "string" && validEfforts.includes(body.reasoningEffort)
- ? (body.reasoningEffort as "none" | "low" | "medium" | "high" | "max")
- : undefined;
+ const reasoningEffort =
+ typeof body.reasoningEffort === "string" && validEfforts.includes(body.reasoningEffort)
+ ? (body.reasoningEffort as "none" | "low" | "medium" | "high" | "max")
+ : undefined;
// Non-blocking — let the agent run in the background
- agentManager.processMessage(tabId, message, keyId, modelId, reasoningEffort).catch(console.error);
+ agentManager.processMessage(tabId, message, keyId, modelId, reasoningEffort, workingDirectory).catch(console.error);
return c.json({ status: "ok" });
});
@@ -67,6 +77,7 @@ app.route("/config", configRoutes);
app.route("/skills", skillsRoutes);
app.route("/models", modelsRoutes);
app.route("/tabs", tabsRoutes);
+app.route("/agents", agentsRoutes);
// Start the wake scheduler on boot (restores persisted schedule)
startWakeScheduler();