@agent-spaces/server 0.3.65 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/agent-runtime.js +8 -0
- package/dist/adapters/codex-function-tool-bridge.js +152 -0
- package/dist/adapters/codex-runtime.js +23 -4
- package/dist/adapters/git.js +25 -3
- package/dist/adapters/hermes-runtime.js +813 -0
- package/dist/adapters/langchain-runtime.js +384 -21
- package/dist/adapters/oh-my-pi-runtime.js +858 -0
- package/dist/adapters/open-agent-sdk-runtime.js +202 -5
- package/dist/adapters/open-agent-sdk-runtime.test.js +35 -0
- package/dist/agents/agent-message-parts.js +52 -2
- package/dist/agents/issue-task-controller.js +71 -2
- package/dist/agents/pull-request-agent.js +115 -0
- package/dist/agents/scheduler-agent.js +1 -1
- package/dist/agents/title-generator-agent.js +120 -0
- package/dist/app.js +61 -4
- package/dist/middleware/auth.js +1 -1
- package/dist/package.json +2 -1
- package/dist/routes/agent-sse.js +70 -6
- package/dist/routes/channel.js +23 -2
- package/dist/routes/chat-run.js +191 -0
- package/dist/routes/chat.js +142 -0
- package/dist/routes/command.js +16 -0
- package/dist/routes/data.js +189 -0
- package/dist/routes/git.js +10 -1
- package/dist/routes/import.js +199 -0
- package/dist/routes/issue.js +17 -5
- package/dist/routes/notification.js +10 -0
- package/dist/routes/plugin.js +69 -0
- package/dist/routes/version.js +95 -0
- package/dist/routes/workflow-hook.js +71 -0
- package/dist/routes/workflow.js +282 -7
- package/dist/routes/workspace.js +13 -4
- package/dist/routes/worktree.js +93 -0
- package/dist/services/agent.js +123 -36
- package/dist/services/ai-text.js +185 -0
- package/dist/services/builtin-tools/index.js +1 -0
- package/dist/services/builtin-tools/workflow-editor-tools.js +509 -0
- package/dist/services/builtin-tools/workflow-exec-tools.js +320 -0
- package/dist/services/chat.js +134 -0
- package/dist/services/command-process-manager.js +16 -0
- package/dist/services/execution-manager.js +1346 -0
- package/dist/services/generated-title.js +59 -0
- package/dist/services/gitignore.js +22 -18
- package/dist/services/interaction-manager.js +114 -0
- package/dist/services/issue-retry.js +25 -0
- package/dist/services/notification-center.js +9 -0
- package/dist/services/output-style.js +8 -1
- package/dist/services/plugin.js +257 -0
- package/dist/services/prompt-template.js +8 -1
- package/dist/services/pty.js +20 -0
- package/dist/services/search.js +16 -6
- package/dist/services/skill.js +2 -0
- package/dist/services/version.js +69 -0
- package/dist/services/workflow-command-runner.js +24 -0
- package/dist/services/workflow-trigger-service.js +137 -0
- package/dist/services/workflow.js +219 -39
- package/dist/services/workspace.js +23 -1
- package/dist/services/worktree.js +207 -0
- package/dist/storage/agent-store.js +8 -0
- package/dist/storage/chat-store.js +151 -0
- package/dist/storage/database-store.js +6 -0
- package/dist/storage/json-store.js +2 -1
- package/dist/storage/kanban-store.js +6 -0
- package/dist/storage/workflow-store.js +386 -22
- package/dist/storage/worktree-store.js +33 -0
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +4 -4
- package/dist/web/__next._full.txt +21 -21
- package/dist/web/__next._head.txt +4 -4
- package/dist/web/__next._index.txt +13 -13
- package/dist/web/__next._tree.txt +2 -2
- package/dist/web/_next/static/chunks/{08x85faoz58i7.js → 0-92u-tiuy40a.js} +4 -4
- package/dist/web/_next/static/chunks/{0db14450oqzhg.js → 0-yizd8osmas2.js} +1 -1
- package/dist/web/_next/static/chunks/0.ln~3mnv8.69.js +1 -0
- package/dist/web/_next/static/chunks/{11cchuwoupmbf.js → 01y3e9pemva7b.js} +10 -10
- package/dist/web/_next/static/chunks/02l~tmzrgny.~.js +1 -0
- package/dist/web/_next/static/chunks/03f1bwuynjdmk.js +1 -0
- package/dist/web/_next/static/chunks/04cb4kc9r2pd1.js +1 -0
- package/dist/web/_next/static/chunks/04de6ha5_e3pp.js +1 -0
- package/dist/web/_next/static/chunks/09he0p79ov1rn.js +1 -0
- package/dist/web/_next/static/chunks/09vpocs4zuc8h.js +1 -0
- package/dist/web/_next/static/chunks/0_o2exgr0e_nh.js +1 -0
- package/dist/web/_next/static/chunks/{0xbaakj0dfc0..js → 0_y9nskc-xt2k.js} +1 -1
- package/dist/web/_next/static/chunks/0clnj-1fi6u8j.js +3 -0
- package/dist/web/_next/static/chunks/0gv40by0zzxs_.js +1 -0
- package/dist/web/_next/static/chunks/0iusr8y88.kjg.js +1 -0
- package/dist/web/_next/static/chunks/{0-a.-hl3wv99k.js → 0j-8418fxvkd1.js} +1 -1
- package/dist/web/_next/static/chunks/0j.wxxyoclma5.js +1 -0
- package/dist/web/_next/static/chunks/{0.6b64sy0g5.3.js → 0jq.16sozqik..js} +1 -1
- package/dist/web/_next/static/chunks/0jw8xdk_fpnp0.css +1 -0
- package/dist/web/_next/static/chunks/0l1lkd-wcotma.js +1 -0
- package/dist/web/_next/static/chunks/{0u6h-hqc_i52e.js → 0ncxf_zr4n839.js} +1 -1
- package/dist/web/_next/static/chunks/0ndo7um~v7vco.js +1 -0
- package/dist/web/_next/static/chunks/0ngk.~kan8wq_.js +1 -0
- package/dist/web/_next/static/chunks/0ppr271hz0xoq.js +1 -0
- package/dist/web/_next/static/chunks/0rt9bofnn6qvn.js +1 -0
- package/dist/web/_next/static/chunks/0t64.9jd00hio.js +3 -0
- package/dist/web/_next/static/chunks/0taui9--5n6-5.js +1 -0
- package/dist/web/_next/static/chunks/0ty39169lh~z3.js +1 -0
- package/dist/web/_next/static/chunks/0v8nof~waedlu.js +1 -0
- package/dist/web/_next/static/chunks/{0-pi.67w.ymsr.js → 0vcfoagnpf.aw.js} +1 -1
- package/dist/web/_next/static/chunks/{0vis~lx0nxgn-.js → 0wwwq.gyyz0vg.js} +3 -3
- package/dist/web/_next/static/chunks/0x5lak8yz7pm7.js +1 -0
- package/dist/web/_next/static/chunks/0xon_.4-o0_zq.js +7 -0
- package/dist/web/_next/static/chunks/0zjnrbt7inime.js +1 -0
- package/dist/web/_next/static/chunks/0zwebpitvpuv1.js +1 -0
- package/dist/web/_next/static/chunks/0~02o4g-o6n~m.js +1 -0
- package/dist/web/_next/static/chunks/{0w7.tb29958zj.js → 0~fjezp.k4qk3.js} +1 -1
- package/dist/web/_next/static/chunks/0~sh93re1-_rp.js +1 -0
- package/dist/web/_next/static/chunks/10_niiq0k6o-p.js +5 -0
- package/dist/web/_next/static/chunks/12tjr0_2ccrtq.js +2 -0
- package/dist/web/_next/static/chunks/12x5.go_x9mfk.js +1 -0
- package/dist/web/_next/static/chunks/{0l2w0qz1ea7ql.js → 12~5dk9i9d16t.js} +2 -2
- package/dist/web/_next/static/chunks/13iye4rv5p31b.js +1 -0
- package/dist/web/_next/static/chunks/{01~quun6sefgl.js → 13~y-b.b9rrw4.js} +1 -1
- package/dist/web/_next/static/chunks/151wzhb5q0lo5.js +1 -0
- package/dist/web/_not-found/__next._full.txt +19 -19
- package/dist/web/_not-found/__next._head.txt +4 -4
- package/dist/web/_not-found/__next._index.txt +13 -13
- package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/dist/web/_not-found/__next._not-found.txt +3 -3
- package/dist/web/_not-found/__next._tree.txt +2 -2
- package/dist/web/_not-found.html +1 -1
- package/dist/web/_not-found.txt +19 -19
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +21 -21
- package/dist/web/login/__next._full.txt +21 -21
- package/dist/web/login/__next._head.txt +4 -4
- package/dist/web/login/__next._index.txt +13 -13
- package/dist/web/login/__next._tree.txt +2 -2
- package/dist/web/login/__next.login.__PAGE__.txt +4 -4
- package/dist/web/login/__next.login.txt +3 -3
- package/dist/web/login.html +1 -1
- package/dist/web/login.txt +21 -21
- package/dist/web/settings/__next._full.txt +23 -23
- package/dist/web/settings/__next._head.txt +4 -4
- package/dist/web/settings/__next._index.txt +13 -13
- package/dist/web/settings/__next._tree.txt +2 -2
- package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
- package/dist/web/settings/__next.settings.txt +5 -5
- package/dist/web/settings/agents/__next._full.txt +23 -23
- package/dist/web/settings/agents/__next._head.txt +4 -4
- package/dist/web/settings/agents/__next._index.txt +13 -13
- package/dist/web/settings/agents/__next._tree.txt +2 -2
- package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
- package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
- package/dist/web/settings/agents/__next.settings.txt +5 -5
- package/dist/web/settings/agents.html +1 -1
- package/dist/web/settings/agents.txt +23 -23
- package/dist/web/settings/mcps/__next._full.txt +23 -23
- package/dist/web/settings/mcps/__next._head.txt +4 -4
- package/dist/web/settings/mcps/__next._index.txt +13 -13
- package/dist/web/settings/mcps/__next._tree.txt +2 -2
- package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
- package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
- package/dist/web/settings/mcps/__next.settings.txt +5 -5
- package/dist/web/settings/mcps.html +1 -1
- package/dist/web/settings/mcps.txt +23 -23
- package/dist/web/settings/models/__next._full.txt +23 -23
- package/dist/web/settings/models/__next._head.txt +4 -4
- package/dist/web/settings/models/__next._index.txt +13 -13
- package/dist/web/settings/models/__next._tree.txt +2 -2
- package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
- package/dist/web/settings/models/__next.settings.models.txt +3 -3
- package/dist/web/settings/models/__next.settings.txt +5 -5
- package/dist/web/settings/models.html +1 -1
- package/dist/web/settings/models.txt +23 -23
- package/dist/web/settings/output-styles/__next._full.txt +23 -23
- package/dist/web/settings/output-styles/__next._head.txt +4 -4
- package/dist/web/settings/output-styles/__next._index.txt +13 -13
- package/dist/web/settings/output-styles/__next._tree.txt +2 -2
- package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +4 -4
- package/dist/web/settings/output-styles/__next.settings.output-styles.txt +3 -3
- package/dist/web/settings/output-styles/__next.settings.txt +5 -5
- package/dist/web/settings/output-styles.html +1 -1
- package/dist/web/settings/output-styles.txt +23 -23
- package/dist/web/settings/prompts/__next._full.txt +23 -23
- package/dist/web/settings/prompts/__next._head.txt +4 -4
- package/dist/web/settings/prompts/__next._index.txt +13 -13
- package/dist/web/settings/prompts/__next._tree.txt +2 -2
- package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +4 -4
- package/dist/web/settings/prompts/__next.settings.prompts.txt +3 -3
- package/dist/web/settings/prompts/__next.settings.txt +5 -5
- package/dist/web/settings/prompts.html +1 -1
- package/dist/web/settings/prompts.txt +23 -23
- package/dist/web/settings/providers/__next._full.txt +23 -23
- package/dist/web/settings/providers/__next._head.txt +4 -4
- package/dist/web/settings/providers/__next._index.txt +13 -13
- package/dist/web/settings/providers/__next._tree.txt +2 -2
- package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
- package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
- package/dist/web/settings/providers/__next.settings.txt +5 -5
- package/dist/web/settings/providers.html +1 -1
- package/dist/web/settings/providers.txt +23 -23
- package/dist/web/settings/skills/__next._full.txt +23 -23
- package/dist/web/settings/skills/__next._head.txt +4 -4
- package/dist/web/settings/skills/__next._index.txt +13 -13
- package/dist/web/settings/skills/__next._tree.txt +2 -2
- package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
- package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
- package/dist/web/settings/skills/__next.settings.txt +5 -5
- package/dist/web/settings/skills.html +1 -1
- package/dist/web/settings/skills.txt +23 -23
- package/dist/web/settings/tools/__next._full.txt +23 -23
- package/dist/web/settings/tools/__next._head.txt +4 -4
- package/dist/web/settings/tools/__next._index.txt +13 -13
- package/dist/web/settings/tools/__next._tree.txt +2 -2
- package/dist/web/settings/tools/__next.settings.tools.__PAGE__.txt +4 -4
- package/dist/web/settings/tools/__next.settings.tools.txt +3 -3
- package/dist/web/settings/tools/__next.settings.txt +5 -5
- package/dist/web/settings/tools.html +1 -1
- package/dist/web/settings/tools.txt +23 -23
- package/dist/web/settings.html +1 -1
- package/dist/web/settings.txt +23 -23
- package/dist/web/workflows/__next._full.txt +22 -22
- package/dist/web/workflows/__next._head.txt +4 -4
- package/dist/web/workflows/__next._index.txt +13 -13
- package/dist/web/workflows/__next._tree.txt +2 -2
- package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
- package/dist/web/workflows/__next.workflows.txt +3 -3
- package/dist/web/workflows.html +1 -1
- package/dist/web/workflows.txt +22 -22
- package/dist/web/workspace/_/__next._full.txt +20 -20
- package/dist/web/workspace/_/__next._head.txt +4 -4
- package/dist/web/workspace/_/__next._index.txt +13 -13
- package/dist/web/workspace/_/__next._tree.txt +2 -2
- package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.txt +3 -3
- package/dist/web/workspace/_.html +1 -1
- package/dist/web/workspace/_.txt +20 -20
- package/dist/web/workspaces/__next._full.txt +21 -21
- package/dist/web/workspaces/__next._head.txt +4 -4
- package/dist/web/workspaces/__next._index.txt +13 -13
- package/dist/web/workspaces/__next._tree.txt +2 -2
- package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
- package/dist/web/workspaces/__next.workspaces.txt +3 -3
- package/dist/web/workspaces.html +1 -1
- package/dist/web/workspaces.txt +21 -21
- package/dist/ws/agent-prompt.js +36 -3
- package/dist/ws/agent-runner.js +30 -18
- package/dist/ws/chat-handler.js +89 -0
- package/dist/ws/connection-manager.js +49 -2
- package/dist/ws/execution-channels.js +88 -0
- package/dist/ws/handler.js +32 -5
- package/dist/ws/message-parts.js +130 -12
- package/dist/ws/terminal-handler.js +26 -0
- package/package.json +13 -1
- package/public/avatars/user.jpg +0 -0
- package/dist/web/_next/static/chunks/0-v_p6j5u3_9l.js +0 -1
- package/dist/web/_next/static/chunks/0.-x29t-8gk0r.js +0 -1
- package/dist/web/_next/static/chunks/0.l5e8~r7_0~p.js +0 -1
- package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +0 -1
- package/dist/web/_next/static/chunks/00-syqzi-6zxr.js +0 -1
- package/dist/web/_next/static/chunks/02j4sr9psucf-.js +0 -1
- package/dist/web/_next/static/chunks/06si8l0doqe8p.js +0 -1
- package/dist/web/_next/static/chunks/08kfx8on9oty~.js +0 -1
- package/dist/web/_next/static/chunks/08ugbvzr20drp.js +0 -2
- package/dist/web/_next/static/chunks/0_cqojbge48kq.js +0 -5
- package/dist/web/_next/static/chunks/0d6~~lv0-6kex.js +0 -3
- package/dist/web/_next/static/chunks/0gdwop9cnpmtu.js +0 -1
- package/dist/web/_next/static/chunks/0ghx3j_.-gdyd.js +0 -1
- package/dist/web/_next/static/chunks/0kbvoxla7f751.js +0 -1
- package/dist/web/_next/static/chunks/0paaat8y96ayc.js +0 -7
- package/dist/web/_next/static/chunks/0pq318f8xgafg.js +0 -1
- package/dist/web/_next/static/chunks/0t6s8of0qr6nc.js +0 -1
- package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +0 -1
- package/dist/web/_next/static/chunks/0yd.m1afqg.2t.js +0 -3
- package/dist/web/_next/static/chunks/0yhbr8hl09b-5.js +0 -1
- package/dist/web/_next/static/chunks/0z~vqzbm_q371.js +0 -1
- package/dist/web/_next/static/chunks/0~~_ltu6dx_ch.js +0 -1
- package/dist/web/_next/static/chunks/12oxcgyhpaxw~.js +0 -1
- package/dist/web/_next/static/chunks/1452eibz62gs6.css +0 -1
- package/dist/web/_next/static/chunks/16zlreiems5cn.js +0 -1
- package/dist/web/_next/static/chunks/18awqjk9-o5m0.js +0 -1
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { BUILT_IN_AGENT_TOOLS, getNodesForExecutionScope } from '@agent-spaces/shared';
|
|
2
|
+
import * as workflowService from '../workflow.js';
|
|
3
|
+
let workflowExecutionManager = null;
|
|
4
|
+
const DEFAULT_SYNC_TIMEOUT_MS = 120_000;
|
|
5
|
+
const MAX_SYNC_TIMEOUT_MS = 600_000;
|
|
6
|
+
const POLL_INTERVAL_MS = 500;
|
|
7
|
+
const pagingInputSchema = schema({
|
|
8
|
+
page: { type: 'number', description: 'Page number, starting from 1. Defaults to 1.' },
|
|
9
|
+
page_size: { type: 'number', description: 'Page size. Defaults to 10, max 50.' },
|
|
10
|
+
});
|
|
11
|
+
const executeWorkflowInputSchema = schema({
|
|
12
|
+
workflow_id: { type: 'string', description: 'Workflow ID. workflowId is also accepted.' },
|
|
13
|
+
workflowId: { type: 'string', description: 'Workflow ID alias.' },
|
|
14
|
+
input: { type: 'object', description: 'Workflow input object.', properties: {} },
|
|
15
|
+
start_node_id: { type: 'string', description: 'Optional start node ID when the workflow has multiple start nodes.' },
|
|
16
|
+
startNodeId: { type: 'string', description: 'Start node ID alias.' },
|
|
17
|
+
max_wait_ms: { type: 'number', description: `Sync execution wait timeout. Defaults to ${DEFAULT_SYNC_TIMEOUT_MS}, max ${MAX_SYNC_TIMEOUT_MS}.` },
|
|
18
|
+
});
|
|
19
|
+
export function setWorkflowExecutionManager(manager) {
|
|
20
|
+
workflowExecutionManager = manager;
|
|
21
|
+
}
|
|
22
|
+
export function createWorkflowExecutionFunctionTools(allowedTools) {
|
|
23
|
+
const allowedToolNames = getAllowedWorkflowToolNames(allowedTools);
|
|
24
|
+
const tools = [
|
|
25
|
+
{
|
|
26
|
+
name: 'list_workflows',
|
|
27
|
+
description: 'List saved workflows, newest updated first. Returns workflow IDs, descriptions, start nodes, and input fields.',
|
|
28
|
+
inputSchema: pagingInputSchema,
|
|
29
|
+
annotations: { readOnly: true, openWorld: false },
|
|
30
|
+
execute: async (input) => listWorkflows(input),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'search_workflow',
|
|
34
|
+
description: 'Search saved workflows by keyword in workflow name or description.',
|
|
35
|
+
inputSchema: schema({
|
|
36
|
+
keyword: { type: 'string', description: 'Keyword to search in workflow name and description.' },
|
|
37
|
+
page: { type: 'number', description: 'Page number, starting from 1. Defaults to 1.' },
|
|
38
|
+
page_size: { type: 'number', description: 'Page size. Defaults to 10, max 50.' },
|
|
39
|
+
}, ['keyword']),
|
|
40
|
+
annotations: { readOnly: true, openWorld: false },
|
|
41
|
+
execute: async (input) => searchWorkflow(input),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'execute_workflow_sync',
|
|
45
|
+
description: 'Start a workflow and wait until it completes, errors, pauses, or reaches max_wait_ms. Returns execution steps.',
|
|
46
|
+
inputSchema: executeWorkflowInputSchema,
|
|
47
|
+
annotations: { destructive: false, openWorld: false },
|
|
48
|
+
execute: async (input) => executeWorkflowSync(input),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'execute_workflow_async',
|
|
52
|
+
description: 'Start a workflow without waiting for completion. Use get_workflow_result with the returned executionId.',
|
|
53
|
+
inputSchema: executeWorkflowInputSchema,
|
|
54
|
+
annotations: { destructive: false, openWorld: false },
|
|
55
|
+
execute: async (input) => executeWorkflowAsync(input),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'get_workflow_result',
|
|
59
|
+
description: 'Read workflow execution result by execution_id. Optionally filter steps by node_id.',
|
|
60
|
+
inputSchema: schema({
|
|
61
|
+
execution_id: { type: 'string', description: 'Execution ID returned by execute_workflow_sync or execute_workflow_async.' },
|
|
62
|
+
workflow_id: { type: 'string', description: 'Optional workflow ID to narrow the lookup.' },
|
|
63
|
+
workflowId: { type: 'string', description: 'Workflow ID alias.' },
|
|
64
|
+
node_id: { type: 'string', description: 'Optional node ID. If provided, only that node step is returned.' },
|
|
65
|
+
}, ['execution_id']),
|
|
66
|
+
annotations: { readOnly: true, openWorld: false },
|
|
67
|
+
execute: async (input) => getWorkflowResult(input),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'get_workflow_latest_result',
|
|
71
|
+
description: 'Read the latest execution result for a workflow. Optionally filter steps by node_id.',
|
|
72
|
+
inputSchema: schema({
|
|
73
|
+
workflow_id: { type: 'string', description: 'Workflow ID. workflowId is also accepted.' },
|
|
74
|
+
workflowId: { type: 'string', description: 'Workflow ID alias.' },
|
|
75
|
+
node_id: { type: 'string', description: 'Optional node ID. If provided, only that node step is returned.' },
|
|
76
|
+
}),
|
|
77
|
+
annotations: { readOnly: true, openWorld: false },
|
|
78
|
+
execute: async (input) => getWorkflowLatestResult(input),
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
return tools.filter((tool) => allowedToolNames.has(tool.name));
|
|
82
|
+
}
|
|
83
|
+
function listWorkflows(input) {
|
|
84
|
+
const record = asRecord(input);
|
|
85
|
+
const { page, pageSize } = pageArgs(record);
|
|
86
|
+
const workflows = workflowService.listWorkflows().sort((a, b) => b.updatedAt - a.updatedAt);
|
|
87
|
+
const total = workflows.length;
|
|
88
|
+
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
89
|
+
const currentPage = Math.min(page, totalPages);
|
|
90
|
+
const items = workflows.slice((currentPage - 1) * pageSize, currentPage * pageSize).map(summarizeWorkflowForTool);
|
|
91
|
+
return {
|
|
92
|
+
success: true,
|
|
93
|
+
message: `Page ${currentPage} of ${totalPages}.`,
|
|
94
|
+
data: { page: currentPage, page_size: pageSize, total, total_pages: totalPages, workflows: items },
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function searchWorkflow(input) {
|
|
98
|
+
const record = asRecord(input);
|
|
99
|
+
const keyword = stringInput(record, 'keyword')?.toLowerCase();
|
|
100
|
+
if (!keyword)
|
|
101
|
+
return { success: false, message: 'keyword is required' };
|
|
102
|
+
const { page, pageSize } = pageArgs(record);
|
|
103
|
+
const matches = workflowService.listWorkflows()
|
|
104
|
+
.filter((workflow) => [workflow.name, workflow.description ?? ''].join('\n').toLowerCase().includes(keyword))
|
|
105
|
+
.sort((a, b) => b.updatedAt - a.updatedAt)
|
|
106
|
+
.map(summarizeWorkflowForTool);
|
|
107
|
+
const total = matches.length;
|
|
108
|
+
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
109
|
+
const currentPage = Math.min(page, totalPages);
|
|
110
|
+
const items = matches.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
|
111
|
+
return {
|
|
112
|
+
success: true,
|
|
113
|
+
message: `Found ${total} matching workflows. Page ${currentPage} of ${totalPages}.`,
|
|
114
|
+
data: { page: currentPage, page_size: pageSize, total, total_pages: totalPages, workflows: items },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function executeWorkflowAsync(input) {
|
|
118
|
+
const manager = requireWorkflowExecutionManager();
|
|
119
|
+
if ('success' in manager)
|
|
120
|
+
return manager;
|
|
121
|
+
const record = asRecord(input);
|
|
122
|
+
const workflowId = resolveWorkflowId(record);
|
|
123
|
+
const validation = validateWorkflowId(workflowId);
|
|
124
|
+
if (validation)
|
|
125
|
+
return validation;
|
|
126
|
+
const result = await manager.execute({
|
|
127
|
+
workflowId,
|
|
128
|
+
input: objectInput(record, 'input'),
|
|
129
|
+
startNodeId: stringInput(record, 'start_node_id') ?? stringInput(record, 'startNodeId'),
|
|
130
|
+
}, 'agent-tools');
|
|
131
|
+
return {
|
|
132
|
+
success: true,
|
|
133
|
+
message: 'Workflow execution started.',
|
|
134
|
+
data: { workflow_id: workflowId, executionId: result.executionId, status: result.status },
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async function executeWorkflowSync(input) {
|
|
138
|
+
const manager = requireWorkflowExecutionManager();
|
|
139
|
+
if ('success' in manager)
|
|
140
|
+
return manager;
|
|
141
|
+
const record = asRecord(input);
|
|
142
|
+
const workflowId = resolveWorkflowId(record);
|
|
143
|
+
const validation = validateWorkflowId(workflowId);
|
|
144
|
+
if (validation)
|
|
145
|
+
return validation;
|
|
146
|
+
const result = await manager.execute({
|
|
147
|
+
workflowId,
|
|
148
|
+
input: objectInput(record, 'input'),
|
|
149
|
+
startNodeId: stringInput(record, 'start_node_id') ?? stringInput(record, 'startNodeId'),
|
|
150
|
+
}, 'agent-tools');
|
|
151
|
+
const timeoutMs = Math.min(MAX_SYNC_TIMEOUT_MS, Math.max(POLL_INTERVAL_MS, numberInput(record, 'max_wait_ms', DEFAULT_SYNC_TIMEOUT_MS)));
|
|
152
|
+
const startedAt = Date.now();
|
|
153
|
+
let log = null;
|
|
154
|
+
let status = result.status;
|
|
155
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
156
|
+
const recovery = manager.getExecutionRecovery({ workflowId, executionId: result.executionId }, 'agent-tools');
|
|
157
|
+
log = recovery.execution?.log ?? workflowService.getExecutionLog(workflowId, result.executionId);
|
|
158
|
+
status = log?.status ?? recovery.execution?.status ?? status;
|
|
159
|
+
if (status !== 'running')
|
|
160
|
+
break;
|
|
161
|
+
await sleep(POLL_INTERVAL_MS);
|
|
162
|
+
}
|
|
163
|
+
log = log ?? workflowService.getExecutionLog(workflowId, result.executionId);
|
|
164
|
+
status = log?.status ?? status;
|
|
165
|
+
const timedOut = status === 'running';
|
|
166
|
+
return {
|
|
167
|
+
success: true,
|
|
168
|
+
message: timedOut ? `Workflow is still running after ${timeoutMs}ms.` : `Workflow finished with status: ${status}.`,
|
|
169
|
+
data: {
|
|
170
|
+
workflow_id: workflowId,
|
|
171
|
+
executionId: result.executionId,
|
|
172
|
+
status,
|
|
173
|
+
timedOut,
|
|
174
|
+
steps: log ? formatExecutionSteps(log) : [],
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function getWorkflowResult(input) {
|
|
179
|
+
const record = asRecord(input);
|
|
180
|
+
const executionId = stringInput(record, 'execution_id');
|
|
181
|
+
if (!executionId)
|
|
182
|
+
return { success: false, message: 'execution_id is required' };
|
|
183
|
+
const workflowId = resolveWorkflowId(record);
|
|
184
|
+
const nodeId = stringInput(record, 'node_id');
|
|
185
|
+
const scopedLog = workflowId ? workflowService.getExecutionLog(workflowId, executionId) : null;
|
|
186
|
+
if (workflowId && scopedLog)
|
|
187
|
+
return executionLogResult(workflowId, scopedLog, nodeId);
|
|
188
|
+
for (const workflow of workflowService.listWorkflows()) {
|
|
189
|
+
const log = workflowService.getExecutionLog(workflow.id, executionId);
|
|
190
|
+
if (log)
|
|
191
|
+
return executionLogResult(workflow.id, log, nodeId);
|
|
192
|
+
}
|
|
193
|
+
return { success: false, message: `Execution log not found: ${executionId}` };
|
|
194
|
+
}
|
|
195
|
+
function getWorkflowLatestResult(input) {
|
|
196
|
+
const record = asRecord(input);
|
|
197
|
+
const workflowId = resolveWorkflowId(record);
|
|
198
|
+
const validation = validateWorkflowId(workflowId);
|
|
199
|
+
if (validation)
|
|
200
|
+
return validation;
|
|
201
|
+
const log = workflowService.listExecutionLogs(workflowId)[0] ?? null;
|
|
202
|
+
if (!log)
|
|
203
|
+
return { success: false, message: `Workflow has no execution logs: ${workflowId}` };
|
|
204
|
+
return executionLogResult(workflowId, log, stringInput(record, 'node_id'), true);
|
|
205
|
+
}
|
|
206
|
+
function executionLogResult(workflowId, log, nodeId, latest = false) {
|
|
207
|
+
return {
|
|
208
|
+
success: true,
|
|
209
|
+
message: `${latest ? 'Latest execution status' : 'Execution status'}: ${log.status}.`,
|
|
210
|
+
data: {
|
|
211
|
+
workflow_id: workflowId,
|
|
212
|
+
executionId: log.id,
|
|
213
|
+
status: log.status,
|
|
214
|
+
startedAt: log.startedAt,
|
|
215
|
+
finishedAt: log.finishedAt,
|
|
216
|
+
steps: formatExecutionSteps(log, nodeId),
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function summarizeWorkflowForTool(workflow) {
|
|
221
|
+
const startNodes = getNodesForExecutionScope(workflow.nodes, null)
|
|
222
|
+
.filter((node) => node.type === 'start')
|
|
223
|
+
.map((node) => ({
|
|
224
|
+
id: node.id,
|
|
225
|
+
label: node.label,
|
|
226
|
+
inputFields: Array.isArray(node.data?.inputFields) ? clone(node.data.inputFields) : [],
|
|
227
|
+
}));
|
|
228
|
+
return {
|
|
229
|
+
workflow_id: workflow.id,
|
|
230
|
+
title: workflow.name,
|
|
231
|
+
description: workflow.description ?? '',
|
|
232
|
+
inputFields: startNodes[0]?.inputFields ?? [],
|
|
233
|
+
startNodes,
|
|
234
|
+
updatedAt: workflow.updatedAt,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function formatExecutionSteps(log, nodeId) {
|
|
238
|
+
return log.steps
|
|
239
|
+
.filter((step) => !nodeId || step.nodeId === nodeId)
|
|
240
|
+
.map((step) => ({
|
|
241
|
+
nodeId: step.nodeId,
|
|
242
|
+
nodeLabel: step.nodeLabel,
|
|
243
|
+
status: step.status,
|
|
244
|
+
startedAt: step.startedAt,
|
|
245
|
+
finishedAt: step.finishedAt,
|
|
246
|
+
duration: step.finishedAt ? step.finishedAt - step.startedAt : undefined,
|
|
247
|
+
input: step.input,
|
|
248
|
+
output: step.output,
|
|
249
|
+
error: step.error,
|
|
250
|
+
logs: step.logs,
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
function validateWorkflowId(workflowId) {
|
|
254
|
+
if (!workflowId)
|
|
255
|
+
return { success: false, message: 'workflow_id is required' };
|
|
256
|
+
if (!workflowService.getWorkflow(workflowId))
|
|
257
|
+
return { success: false, message: `Workflow not found: ${workflowId}` };
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
function requireWorkflowExecutionManager() {
|
|
261
|
+
if (!workflowExecutionManager)
|
|
262
|
+
return { success: false, message: 'Workflow execution manager is not initialized' };
|
|
263
|
+
return workflowExecutionManager;
|
|
264
|
+
}
|
|
265
|
+
function getAllowedWorkflowToolNames(allowedTools) {
|
|
266
|
+
const names = new Set(allowedTools ?? BUILT_IN_AGENT_TOOLS.map((tool) => tool.name));
|
|
267
|
+
const hasWorkflowTools = Array.from(names).some((name) => isWorkflowExecutionToolName(name));
|
|
268
|
+
if (hasWorkflowTools) {
|
|
269
|
+
names.add('list_workflows');
|
|
270
|
+
names.add('search_workflow');
|
|
271
|
+
names.add('get_workflow_result');
|
|
272
|
+
names.add('get_workflow_latest_result');
|
|
273
|
+
}
|
|
274
|
+
return names;
|
|
275
|
+
}
|
|
276
|
+
function isWorkflowExecutionToolName(name) {
|
|
277
|
+
return name === 'list_workflows'
|
|
278
|
+
|| name === 'search_workflow'
|
|
279
|
+
|| name === 'execute_workflow_sync'
|
|
280
|
+
|| name === 'execute_workflow_async'
|
|
281
|
+
|| name === 'get_workflow_result'
|
|
282
|
+
|| name === 'get_workflow_latest_result';
|
|
283
|
+
}
|
|
284
|
+
function pageArgs(input) {
|
|
285
|
+
return {
|
|
286
|
+
page: Math.max(1, Math.floor(numberInput(input, 'page', 1))),
|
|
287
|
+
pageSize: Math.min(50, Math.max(1, Math.floor(numberInput(input, 'page_size', 10)))),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function resolveWorkflowId(input) {
|
|
291
|
+
return stringInput(input, 'workflow_id') ?? stringInput(input, 'workflowId') ?? '';
|
|
292
|
+
}
|
|
293
|
+
function schema(properties, required) {
|
|
294
|
+
return { type: 'object', properties, required, additionalProperties: false };
|
|
295
|
+
}
|
|
296
|
+
function asRecord(input) {
|
|
297
|
+
return input && typeof input === 'object' && !Array.isArray(input) ? input : {};
|
|
298
|
+
}
|
|
299
|
+
function stringInput(input, key) {
|
|
300
|
+
const value = input[key];
|
|
301
|
+
if (typeof value !== 'string')
|
|
302
|
+
return undefined;
|
|
303
|
+
const trimmed = value.trim();
|
|
304
|
+
return trimmed || undefined;
|
|
305
|
+
}
|
|
306
|
+
function numberInput(input, key, fallback) {
|
|
307
|
+
const value = input[key];
|
|
308
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
|
|
309
|
+
}
|
|
310
|
+
function objectInput(input, key) {
|
|
311
|
+
const value = input[key];
|
|
312
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
313
|
+
}
|
|
314
|
+
function clone(value) {
|
|
315
|
+
return JSON.parse(JSON.stringify(value));
|
|
316
|
+
}
|
|
317
|
+
function sleep(ms) {
|
|
318
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=workflow-exec-tools.js.map
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import * as store from '../storage/chat-store.js';
|
|
4
|
+
// --- Agent CRUD ---
|
|
5
|
+
export function listAgents() {
|
|
6
|
+
return store.listAgents();
|
|
7
|
+
}
|
|
8
|
+
export function createAgent(data) {
|
|
9
|
+
const id = randomUUID();
|
|
10
|
+
const now = new Date().toISOString();
|
|
11
|
+
const agent = {
|
|
12
|
+
...normalizeAgentData(data),
|
|
13
|
+
id,
|
|
14
|
+
workingDir: store.chatWorkspaceDir(id),
|
|
15
|
+
createdAt: now,
|
|
16
|
+
updatedAt: now,
|
|
17
|
+
};
|
|
18
|
+
store.saveAgent(agent, data.skills);
|
|
19
|
+
return agent;
|
|
20
|
+
}
|
|
21
|
+
export function updateAgent(id, data) {
|
|
22
|
+
const existing = store.findAgent(id);
|
|
23
|
+
if (!existing)
|
|
24
|
+
return null;
|
|
25
|
+
const updated = {
|
|
26
|
+
...existing,
|
|
27
|
+
...normalizeAgentData({ ...existing, ...data }),
|
|
28
|
+
id,
|
|
29
|
+
createdAt: existing.createdAt,
|
|
30
|
+
workingDir: store.chatWorkspaceDir(id),
|
|
31
|
+
updatedAt: new Date().toISOString(),
|
|
32
|
+
};
|
|
33
|
+
store.saveAgent(updated, data.skills);
|
|
34
|
+
return updated;
|
|
35
|
+
}
|
|
36
|
+
export function deleteAgent(id) {
|
|
37
|
+
if (!store.findAgent(id))
|
|
38
|
+
return false;
|
|
39
|
+
store.deleteAgent(id);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
export function findAgent(id) {
|
|
43
|
+
return store.findAgent(id);
|
|
44
|
+
}
|
|
45
|
+
// --- Message CRUD ---
|
|
46
|
+
export function listMessages(agentId, limit, before) {
|
|
47
|
+
return store.listMessages(agentId, limit, before);
|
|
48
|
+
}
|
|
49
|
+
export function saveMessage(msg) {
|
|
50
|
+
const message = {
|
|
51
|
+
...msg,
|
|
52
|
+
id: randomUUID(),
|
|
53
|
+
timestamp: new Date().toISOString(),
|
|
54
|
+
};
|
|
55
|
+
store.saveMessage(message);
|
|
56
|
+
return message;
|
|
57
|
+
}
|
|
58
|
+
export function clearMessages(agentId) {
|
|
59
|
+
store.deleteMessagesByAgent(agentId);
|
|
60
|
+
}
|
|
61
|
+
export function getRecentMessages(agentId, limit) {
|
|
62
|
+
return store.getRecentMessages(agentId, limit);
|
|
63
|
+
}
|
|
64
|
+
export function getAgentWorkingDir(agentId) {
|
|
65
|
+
const agent = store.findAgent(agentId);
|
|
66
|
+
if (!agent)
|
|
67
|
+
return null;
|
|
68
|
+
return agent.workingDir || store.chatWorkspaceDir(agentId);
|
|
69
|
+
}
|
|
70
|
+
export function getAgentConfigDir(agentId) {
|
|
71
|
+
return store.findAgent(agentId) ? store.agentDir(agentId) : null;
|
|
72
|
+
}
|
|
73
|
+
export function getAgentWorkspace(agentId) {
|
|
74
|
+
const workingDir = getAgentWorkingDir(agentId);
|
|
75
|
+
if (!workingDir || !existsSync(workingDir))
|
|
76
|
+
return null;
|
|
77
|
+
const now = new Date().toISOString();
|
|
78
|
+
return {
|
|
79
|
+
id: `chat:${agentId}`,
|
|
80
|
+
name: 'Chat Agent',
|
|
81
|
+
boundDirs: [workingDir],
|
|
82
|
+
agentspaceDir: workingDir,
|
|
83
|
+
createdAt: now,
|
|
84
|
+
updatedAt: now,
|
|
85
|
+
activeChannels: [],
|
|
86
|
+
activeIssues: [],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function normalizeAgentData(data) {
|
|
90
|
+
const provider = stringValue(data.provider) || stringValue(data.modelProvider) || 'openai-chat-completions';
|
|
91
|
+
const model = stringValue(data.model) || stringValue(data.modelId) || '';
|
|
92
|
+
const baseURL = stringValue(data.baseURL) || stringValue(data.apiBase) || undefined;
|
|
93
|
+
const avatar = stringValue(data.avatar) || stringValue(data.avatarUrl) || undefined;
|
|
94
|
+
const skills = normalizeSkillNames(data.skills);
|
|
95
|
+
return {
|
|
96
|
+
name: stringValue(data.name) || 'New Chat Agent',
|
|
97
|
+
role: 'agent',
|
|
98
|
+
runtimeKind: 'langchain',
|
|
99
|
+
avatar,
|
|
100
|
+
avatarUrl: avatar,
|
|
101
|
+
icon: stringValue(data.icon) || undefined,
|
|
102
|
+
description: stringValue(data.description) || undefined,
|
|
103
|
+
systemPrompt: stringValue(data.systemPrompt) || undefined,
|
|
104
|
+
provider,
|
|
105
|
+
modelProvider: provider,
|
|
106
|
+
model,
|
|
107
|
+
modelId: model,
|
|
108
|
+
apiKey: stringValue(data.apiKey),
|
|
109
|
+
baseURL,
|
|
110
|
+
apiBase: baseURL,
|
|
111
|
+
workingDir: stringValue(data.workingDir),
|
|
112
|
+
mcps: isRecord(data.mcps) ? data.mcps : {},
|
|
113
|
+
skills,
|
|
114
|
+
tools: Array.isArray(data.tools) ? data.tools : [],
|
|
115
|
+
outputStyle: stringValue(data.outputStyle) || undefined,
|
|
116
|
+
temperature: typeof data.temperature === 'number' ? data.temperature : 0.3,
|
|
117
|
+
maxTokens: typeof data.maxTokens === 'number' ? data.maxTokens : 4096,
|
|
118
|
+
enabled: data.enabled !== false,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function stringValue(value) {
|
|
122
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
123
|
+
}
|
|
124
|
+
function isRecord(value) {
|
|
125
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
126
|
+
}
|
|
127
|
+
function normalizeSkillNames(skills) {
|
|
128
|
+
if (!Array.isArray(skills))
|
|
129
|
+
return [];
|
|
130
|
+
return skills
|
|
131
|
+
.map(skill => typeof skill === 'string' ? skill : isRecord(skill) ? stringValue(skill.name) : '')
|
|
132
|
+
.filter(Boolean);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=chat.js.map
|
|
@@ -75,6 +75,22 @@ export function stopCommand(workspaceId, commandId) {
|
|
|
75
75
|
ptyService.write(cmdProcess.sessionId, '\x03');
|
|
76
76
|
cmdProcess.status = 'stopping';
|
|
77
77
|
}
|
|
78
|
+
export function restartCommand(workspaceId, commandId) {
|
|
79
|
+
const cmdProcess = processes.get(commandId);
|
|
80
|
+
if (!cmdProcess)
|
|
81
|
+
return runCommand(workspaceId, commandId);
|
|
82
|
+
console.log(`[command] restartCommand: command=${commandId} session=${cmdProcess.sessionId}`);
|
|
83
|
+
const timer = restartTimers.get(commandId);
|
|
84
|
+
if (timer) {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
restartTimers.delete(commandId);
|
|
87
|
+
}
|
|
88
|
+
processes.delete(commandId);
|
|
89
|
+
sessionIndex.delete(cmdProcess.sessionId);
|
|
90
|
+
ptyService.kill(cmdProcess.sessionId);
|
|
91
|
+
broadcastToWorkspace(workspaceId, 'terminal.closed', { sessionId: cmdProcess.sessionId });
|
|
92
|
+
return runCommand(workspaceId, commandId);
|
|
93
|
+
}
|
|
78
94
|
function handlePtyExit(sessionId, exitCode) {
|
|
79
95
|
const commandId = sessionIndex.get(sessionId);
|
|
80
96
|
if (!commandId)
|