@agent-spaces/server 0.3.64 → 0.3.67
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 +4 -0
- package/dist/adapters/claude-code-runtime/index.js +68 -2
- package/dist/adapters/claude-code-runtime/message-format.js +26 -0
- package/dist/adapters/claude-code-runtime/sdk-config.js +12 -0
- package/dist/adapters/codex-function-tool-bridge.js +144 -0
- package/dist/adapters/codex-runtime.js +23 -4
- package/dist/adapters/git.js +25 -7
- package/dist/adapters/hermes-runtime.js +210 -0
- package/dist/agents/agent-message-parts.js +1 -1
- package/dist/agents/commit-agent.js +4 -2
- package/dist/agents/issue-task-controller.js +75 -4
- package/dist/agents/pull-request-agent.js +115 -0
- package/dist/agents/scheduler-agent.js +1 -1
- package/dist/app.js +12 -70
- package/dist/middleware/auth.js +1 -1
- package/dist/package.json +2 -1
- package/dist/routes/agent-sse.js +2 -0
- package/dist/routes/agent.js +3 -0
- package/dist/routes/database.js +1 -0
- package/dist/routes/git.js +197 -317
- package/dist/routes/issue.js +1 -1
- package/dist/routes/notification.js +10 -0
- package/dist/routes/robot-account.js +68 -0
- package/dist/routes/version.js +94 -0
- package/dist/routes/worktree.js +93 -0
- package/dist/services/agent.js +37 -3
- package/dist/services/builtin-tools/kanban-tools.js +4 -0
- package/dist/services/git-operation-log.js +40 -0
- package/dist/services/global-wechat-qr.js +72 -0
- package/dist/services/hook-engine.js +175 -17
- package/dist/services/notification-center.js +9 -0
- package/dist/services/notification-hub/bot-agent.js +3 -1
- package/dist/services/notification-hub/service.js +12 -2
- package/dist/services/robot-account.js +34 -0
- package/dist/services/version.js +59 -0
- package/dist/services/workflow-command-runner.js +23 -0
- package/dist/services/workflow.js +25 -8
- package/dist/services/workspace.js +25 -1
- package/dist/services/worktree.js +207 -0
- package/dist/storage/robot-account-store.js +39 -0
- 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 +23 -25
- 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/{0n6_4so_afuwk.js → 0-92u-tiuy40a.js} +4 -4
- package/dist/web/_next/static/chunks/{0vbqaynjq8ga..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/{0iuf30t0rjsjv.js → 01y3e9pemva7b.js} +10 -10
- package/dist/web/_next/static/chunks/02802taez976w.js +67 -0
- package/dist/web/_next/static/chunks/02l~tmzrgny.~.js +1 -0
- package/dist/web/_next/static/chunks/033.awk90g6eh.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/06.kdsa9rr2h1.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/{04a4vsq2wknm4.js → 0j-8418fxvkd1.js} +1 -1
- package/dist/web/_next/static/chunks/0j-l7l_k9jt45.js +1 -0
- package/dist/web/_next/static/chunks/0j.wxxyoclma5.js +1 -0
- package/dist/web/_next/static/chunks/0jq.16sozqik..js +3 -0
- 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/0ncxf_zr4n839.js +1 -0
- 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/0p3h-h3zj5ujg.js +30 -0
- package/dist/web/_next/static/chunks/0pm-un~-sy3rl.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/0uxzi~9b~k4mn.js +31 -0
- package/dist/web/_next/static/chunks/0v8nof~waedlu.js +1 -0
- package/dist/web/_next/static/chunks/{0ctg5qmw7uu.1.js → 0vcfoagnpf.aw.js} +3 -3
- package/dist/web/_next/static/chunks/{08ckpwmmwlors.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/0zncg76rgtbm-.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/{10l-9myrdo3x9.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/{1442stwa0gbxe.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/_next/static/chunks/18c7g84y01mj0.js +1 -0
- package/dist/web/_next/static/chunks/{turbopack-0ndm2zc_pdptk.js → turbopack-11qjwlynmfc-n.js} +1 -1
- package/dist/web/_not-found/__next._full.txt +30 -29
- 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 +30 -29
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +23 -25
- package/dist/web/login/__next._full.txt +28 -28
- 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 +28 -28
- package/dist/web/settings/__next._full.txt +33 -32
- 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 +24 -24
- 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 +24 -24
- package/dist/web/settings/mcps/__next._full.txt +24 -24
- 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 +24 -24
- package/dist/web/settings/models/__next._full.txt +24 -24
- 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 +24 -24
- package/dist/web/settings/output-styles/__next._full.txt +24 -24
- 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 +24 -24
- package/dist/web/settings/prompts/__next._full.txt +24 -24
- 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 +24 -24
- package/dist/web/settings/providers/__next._full.txt +24 -24
- 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 +24 -24
- package/dist/web/settings/skills/__next._full.txt +24 -24
- 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 +24 -24
- package/dist/web/settings/tools/__next._full.txt +24 -24
- 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 +24 -24
- package/dist/web/settings.html +1 -1
- package/dist/web/settings.txt +33 -32
- package/dist/web/workflows/__next._full.txt +31 -33
- 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 +31 -33
- package/dist/web/workspace/_/__next._full.txt +28 -29
- 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 +28 -29
- package/dist/web/workspaces/__next._full.txt +29 -31
- 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 +29 -31
- package/dist/ws/agent-prompt.js +32 -3
- package/dist/ws/agent-runner.js +83 -6
- package/package.json +11 -11
- package/dist/web/_next/static/chunks/0-9194nbxy_6d.js +0 -1
- package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +0 -1
- package/dist/web/_next/static/chunks/02mf61htij8g0.js +0 -31
- package/dist/web/_next/static/chunks/04dg4l4hv11q2.js +0 -3
- package/dist/web/_next/static/chunks/04fxddw-y20~-.js +0 -7
- package/dist/web/_next/static/chunks/04w7~5ooz_pwm.js +0 -1
- package/dist/web/_next/static/chunks/05oc21sj24wtq.js +0 -1
- package/dist/web/_next/static/chunks/08kfx8on9oty~.js +0 -1
- package/dist/web/_next/static/chunks/08k~meqbd8d6v.js +0 -1
- package/dist/web/_next/static/chunks/099h96wjsdb25.js +0 -2
- package/dist/web/_next/static/chunks/09h23logvq65m.js +0 -1
- package/dist/web/_next/static/chunks/0a5y-vhf4i5id.js +0 -3
- package/dist/web/_next/static/chunks/0ake2f3x2uan4.js +0 -24
- package/dist/web/_next/static/chunks/0ck8dw_9-1cdx.js +0 -1
- package/dist/web/_next/static/chunks/0ewceguykiut5.js +0 -1
- package/dist/web/_next/static/chunks/0f7cb9li~3jra.js +0 -67
- package/dist/web/_next/static/chunks/0ghs9on7wodrm.js +0 -1
- package/dist/web/_next/static/chunks/0ghx3j_.-gdyd.js +0 -1
- package/dist/web/_next/static/chunks/0h9cu-k6z5o08.js +0 -1
- package/dist/web/_next/static/chunks/0jb4~3qqkw2ps.js +0 -1
- package/dist/web/_next/static/chunks/0nb8.iteznuvx.js +0 -1
- package/dist/web/_next/static/chunks/0os58q93stt7j.js +0 -3
- package/dist/web/_next/static/chunks/0s9lmk8iauou3.js +0 -1
- package/dist/web/_next/static/chunks/0sp_zbx~w0am7.js +0 -1
- package/dist/web/_next/static/chunks/0tel~zsv4z8l_.js +0 -1
- package/dist/web/_next/static/chunks/0twamv4wr_dbv.js +0 -1
- package/dist/web/_next/static/chunks/0uhol5wafdbl~.js +0 -1
- package/dist/web/_next/static/chunks/0v3a_x4vt42kx.js +0 -5
- package/dist/web/_next/static/chunks/0v7q4mys.mnm..css +0 -1
- package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +0 -1
- package/dist/web/_next/static/chunks/0z~vqzbm_q371.js +0 -1
- package/dist/web/_next/static/chunks/0~3xm80~j9ddg.js +0 -1
- package/dist/web/_next/static/chunks/14s37n6h0_q3x.js +0 -16
- package/dist/web/_next/static/chunks/161ik5kfyuwtd.js +0 -1
- package/dist/web/_next/static/chunks/17k~zbv0_4rep.js +0 -1
- package/public/output-styles/carmack-mode.md +0 -381
- package/public/output-styles/codex-rigor-mode.md +0 -114
- package/public/output-styles/dhh-mode.md +0 -265
- package/public/output-styles/evan-you-mode.md +0 -539
- package/public/output-styles/index.json +0 -37
- package/public/output-styles/jobs-mode.md +0 -369
- package/public/output-styles/linus-mode.md +0 -135
- package/public/output-styles/uncle-bob-mode.md +0 -221
- package/public/prompt/andrej-karpathy-skills.md +0 -65
- package/public/prompt/claude-token-efficient-coding.md +0 -35
- package/public/prompt/index.json +0 -12
- package/public/skills/index.json +0 -92
- package/public/skills/planning-with-files/planning-with-files-zh/SKILL.md +0 -243
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.ps1 +0 -44
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.sh +0 -46
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.ps1 +0 -124
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.sh +0 -124
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/session-catchup.py +0 -438
- package/public/skills/planning-with-files/planning-with-files-zh/templates/findings.md +0 -29
- package/public/skills/planning-with-files/planning-with-files-zh/templates/progress.md +0 -40
- package/public/skills/planning-with-files/planning-with-files-zh/templates/task_plan.md +0 -58
- package/public/skills/superpowers/brainstorming/SKILL.md +0 -164
- package/public/skills/superpowers/brainstorming/scripts/frame-template.html +0 -214
- package/public/skills/superpowers/brainstorming/scripts/helper.js +0 -88
- package/public/skills/superpowers/brainstorming/scripts/server.cjs +0 -354
- package/public/skills/superpowers/brainstorming/scripts/start-server.sh +0 -148
- package/public/skills/superpowers/brainstorming/scripts/stop-server.sh +0 -56
- package/public/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +0 -49
- package/public/skills/superpowers/brainstorming/visual-companion.md +0 -287
- package/public/skills/superpowers/dispatching-parallel-agents/SKILL.md +0 -182
- package/public/skills/superpowers/executing-plans/SKILL.md +0 -70
- package/public/skills/superpowers/finishing-a-development-branch/SKILL.md +0 -251
- package/public/skills/superpowers/receiving-code-review/SKILL.md +0 -213
- package/public/skills/superpowers/requesting-code-review/SKILL.md +0 -103
- package/public/skills/superpowers/requesting-code-review/code-reviewer.md +0 -168
- package/public/skills/superpowers/subagent-driven-development/SKILL.md +0 -279
- package/public/skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +0 -25
- package/public/skills/superpowers/subagent-driven-development/implementer-prompt.md +0 -113
- package/public/skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +0 -61
- package/public/skills/superpowers/systematic-debugging/CREATION-LOG.md +0 -119
- package/public/skills/superpowers/systematic-debugging/SKILL.md +0 -296
- package/public/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +0 -158
- package/public/skills/superpowers/systematic-debugging/condition-based-waiting.md +0 -115
- package/public/skills/superpowers/systematic-debugging/defense-in-depth.md +0 -122
- package/public/skills/superpowers/systematic-debugging/find-polluter.sh +0 -63
- package/public/skills/superpowers/systematic-debugging/root-cause-tracing.md +0 -169
- package/public/skills/superpowers/systematic-debugging/test-academic.md +0 -14
- package/public/skills/superpowers/systematic-debugging/test-pressure-1.md +0 -58
- package/public/skills/superpowers/systematic-debugging/test-pressure-2.md +0 -68
- package/public/skills/superpowers/systematic-debugging/test-pressure-3.md +0 -69
- package/public/skills/superpowers/test-driven-development/SKILL.md +0 -371
- package/public/skills/superpowers/test-driven-development/testing-anti-patterns.md +0 -299
- package/public/skills/superpowers/using-git-worktrees/SKILL.md +0 -215
- package/public/skills/superpowers/using-superpowers/SKILL.md +0 -117
- package/public/skills/superpowers/using-superpowers/references/codex-tools.md +0 -59
- package/public/skills/superpowers/using-superpowers/references/copilot-tools.md +0 -42
- package/public/skills/superpowers/using-superpowers/references/gemini-tools.md +0 -51
- package/public/skills/superpowers/verification-before-completion/SKILL.md +0 -139
- package/public/skills/superpowers/writing-plans/SKILL.md +0 -152
- package/public/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +0 -49
- package/public/skills/superpowers/writing-skills/SKILL.md +0 -655
- package/public/skills/superpowers/writing-skills/anthropic-best-practices.md +0 -1150
- package/public/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
- package/public/skills/superpowers/writing-skills/graphviz-conventions.dot +0 -172
- package/public/skills/superpowers/writing-skills/persuasion-principles.md +0 -187
- package/public/skills/superpowers/writing-skills/render-graphs.js +0 -168
- package/public/skills/superpowers/writing-skills/testing-skills-with-subagents.md +0 -384
- /package/dist/web/_next/static/{e8w3vd9Eov_LDYWj_0zsE → rGXyAK8rgod1NjF3bLZAY}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{e8w3vd9Eov_LDYWj_0zsE → rGXyAK8rgod1NjF3bLZAY}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{e8w3vd9Eov_LDYWj_0zsE → rGXyAK8rgod1NjF3bLZAY}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs';
|
|
3
|
+
import { basename, extname, join } from 'node:path';
|
|
4
|
+
import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Runtime backed by the external Hermes CLI.
|
|
7
|
+
*
|
|
8
|
+
* Hermes does not currently expose a structured JS SDK here, so this adapter
|
|
9
|
+
* treats verbose CLI output as the source of truth and streams it as text.
|
|
10
|
+
*/
|
|
11
|
+
export class HermesRuntime {
|
|
12
|
+
config;
|
|
13
|
+
child = null;
|
|
14
|
+
constructor(config = {}) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
}
|
|
17
|
+
async execute(prompt, workingDir, options) {
|
|
18
|
+
const output = [];
|
|
19
|
+
const cwd = workingDir || process.cwd();
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
const d = (message) => console.log(`[hermes] ${message}`);
|
|
22
|
+
const agentDir = options?.configDir;
|
|
23
|
+
const hermesHome = agentDir ? join(agentDir, '.hermes') : undefined;
|
|
24
|
+
if (hermesHome)
|
|
25
|
+
prepareHermesHome(hermesHome, agentDir);
|
|
26
|
+
const args = buildHermesArgs(appendOutputStyleToPrompt(prompt, options?.outputStyle), this.config, options);
|
|
27
|
+
d(`starting | cwd=${cwd} model=${this.config.model ?? 'profile-default'} provider=${this.config.provider ?? 'profile-default'} hermesHome=${hermesHome ?? 'default'} skills=${options?.skills?.join(',') || '-'}`);
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
let settled = false;
|
|
30
|
+
let stdoutBuffer = '';
|
|
31
|
+
let stderrBuffer = '';
|
|
32
|
+
let sessionId = options?.resumeSessionId;
|
|
33
|
+
let emittedSessionId = sessionId;
|
|
34
|
+
const finish = (result) => {
|
|
35
|
+
if (settled)
|
|
36
|
+
return;
|
|
37
|
+
settled = true;
|
|
38
|
+
this.child = null;
|
|
39
|
+
resolve(result);
|
|
40
|
+
};
|
|
41
|
+
try {
|
|
42
|
+
this.child = spawn('hermes', args, {
|
|
43
|
+
cwd,
|
|
44
|
+
env: buildEnv(this.config, hermesHome),
|
|
45
|
+
windowsHide: true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
50
|
+
d(`failed to start | ${message}`);
|
|
51
|
+
finish({
|
|
52
|
+
success: false,
|
|
53
|
+
summary: 'Hermes execution failed',
|
|
54
|
+
artifacts: [],
|
|
55
|
+
error: message,
|
|
56
|
+
output,
|
|
57
|
+
sessionId,
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.child.stdout.setEncoding('utf-8');
|
|
62
|
+
this.child.stderr.setEncoding('utf-8');
|
|
63
|
+
this.child.stdout.on('data', (chunk) => {
|
|
64
|
+
stdoutBuffer = consumeLines(stdoutBuffer + chunk, (line) => {
|
|
65
|
+
if (!line)
|
|
66
|
+
return;
|
|
67
|
+
output.push(line);
|
|
68
|
+
const parsedSessionId = extractSessionId(line);
|
|
69
|
+
if (parsedSessionId && parsedSessionId !== emittedSessionId) {
|
|
70
|
+
sessionId = parsedSessionId;
|
|
71
|
+
emittedSessionId = parsedSessionId;
|
|
72
|
+
options?.onEvent?.({ type: 'session', sessionId });
|
|
73
|
+
}
|
|
74
|
+
options?.onEvent?.({ type: 'output', line });
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
this.child.stderr.on('data', (chunk) => {
|
|
78
|
+
stderrBuffer = consumeLines(stderrBuffer + chunk, (line) => {
|
|
79
|
+
if (!line)
|
|
80
|
+
return;
|
|
81
|
+
const formatted = `[stderr] ${line}`;
|
|
82
|
+
output.push(formatted);
|
|
83
|
+
options?.onEvent?.({ type: 'output', line: formatted });
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
this.child.on('error', (err) => {
|
|
87
|
+
const message = err.message.includes('ENOENT')
|
|
88
|
+
? 'Hermes CLI was not found. Install Hermes and ensure the `hermes` command is available on PATH.'
|
|
89
|
+
: err.message;
|
|
90
|
+
d(`failed ${Date.now() - startTime}ms | ${message}`);
|
|
91
|
+
finish({
|
|
92
|
+
success: false,
|
|
93
|
+
summary: 'Hermes execution failed',
|
|
94
|
+
artifacts: [],
|
|
95
|
+
error: message,
|
|
96
|
+
output,
|
|
97
|
+
sessionId,
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
this.child.on('close', (code, signal) => {
|
|
101
|
+
stdoutBuffer = flushLine(stdoutBuffer, output, options);
|
|
102
|
+
stderrBuffer = flushLine(stderrBuffer, output, options, '[stderr] ');
|
|
103
|
+
const elapsed = Date.now() - startTime;
|
|
104
|
+
if (code === 0) {
|
|
105
|
+
const text = lastMeaningfulLine(output);
|
|
106
|
+
d(`done ${elapsed}ms`);
|
|
107
|
+
finish({
|
|
108
|
+
success: true,
|
|
109
|
+
summary: summarizeResult(text),
|
|
110
|
+
artifacts: [],
|
|
111
|
+
output,
|
|
112
|
+
sessionId,
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const error = signal
|
|
117
|
+
? `Hermes execution stopped by signal ${signal}`
|
|
118
|
+
: `Hermes execution failed with exit code ${code ?? 'unknown'}`;
|
|
119
|
+
d(`failed ${elapsed}ms | ${error}`);
|
|
120
|
+
finish({
|
|
121
|
+
success: false,
|
|
122
|
+
summary: 'Hermes execution failed',
|
|
123
|
+
artifacts: [],
|
|
124
|
+
error,
|
|
125
|
+
output,
|
|
126
|
+
sessionId,
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
stop() {
|
|
132
|
+
this.child?.kill();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function buildHermesArgs(prompt, config, options) {
|
|
136
|
+
const args = ['chat', '-q', prompt, '--verbose'];
|
|
137
|
+
for (const skill of normalizeSkillNames(options?.skills))
|
|
138
|
+
args.push('-s', skill);
|
|
139
|
+
if (config.model)
|
|
140
|
+
args.push('--model', config.model);
|
|
141
|
+
if (config.provider)
|
|
142
|
+
args.push('--provider', String(config.provider));
|
|
143
|
+
return args;
|
|
144
|
+
}
|
|
145
|
+
function buildEnv(config, hermesHome) {
|
|
146
|
+
const apiKey = config.apiKey || process.env.HERMES_API_KEY || process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY;
|
|
147
|
+
return {
|
|
148
|
+
...process.env,
|
|
149
|
+
HERMES_HOME: hermesHome || process.env.HERMES_HOME,
|
|
150
|
+
HERMES_API_KEY: apiKey,
|
|
151
|
+
HERMES_BASE_URL: config.baseURL || process.env.HERMES_BASE_URL,
|
|
152
|
+
OPENAI_API_KEY: config.apiKey || process.env.OPENAI_API_KEY,
|
|
153
|
+
OPENAI_BASE_URL: config.baseURL || process.env.OPENAI_BASE_URL,
|
|
154
|
+
ANTHROPIC_API_KEY: config.apiKey || process.env.ANTHROPIC_API_KEY,
|
|
155
|
+
NO_COLOR: process.env.NO_COLOR || '1',
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function prepareHermesHome(hermesHome, agentDir) {
|
|
159
|
+
mkdirSync(hermesHome, { recursive: true });
|
|
160
|
+
const skillsDir = join(hermesHome, 'skills');
|
|
161
|
+
rmSync(skillsDir, { recursive: true, force: true });
|
|
162
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
163
|
+
if (!agentDir)
|
|
164
|
+
return;
|
|
165
|
+
const sourceSkillsDir = join(agentDir, 'skills');
|
|
166
|
+
if (!existsSync(sourceSkillsDir))
|
|
167
|
+
return;
|
|
168
|
+
for (const file of readdirSync(sourceSkillsDir)) {
|
|
169
|
+
if (extname(file).toLowerCase() !== '.md')
|
|
170
|
+
continue;
|
|
171
|
+
const sourceFile = join(sourceSkillsDir, file);
|
|
172
|
+
if (!statSync(sourceFile).isFile())
|
|
173
|
+
continue;
|
|
174
|
+
copyFileSync(sourceFile, join(skillsDir, basename(file)));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function consumeLines(buffer, onLine) {
|
|
178
|
+
const lines = buffer.split(/\r?\n/);
|
|
179
|
+
const remainder = lines.pop() ?? '';
|
|
180
|
+
for (const line of lines)
|
|
181
|
+
onLine(stripAnsi(line).trimEnd());
|
|
182
|
+
return remainder;
|
|
183
|
+
}
|
|
184
|
+
function flushLine(buffer, output, options, prefix = '') {
|
|
185
|
+
const line = stripAnsi(buffer).trimEnd();
|
|
186
|
+
if (line) {
|
|
187
|
+
const formatted = `${prefix}${line}`;
|
|
188
|
+
output.push(formatted);
|
|
189
|
+
options?.onEvent?.({ type: 'output', line: formatted });
|
|
190
|
+
}
|
|
191
|
+
return '';
|
|
192
|
+
}
|
|
193
|
+
function extractSessionId(line) {
|
|
194
|
+
const match = line.match(/\bsession(?:\s+id)?\s*[:=]\s*([a-zA-Z0-9._:-]+)/i);
|
|
195
|
+
return match?.[1];
|
|
196
|
+
}
|
|
197
|
+
function normalizeSkillNames(skills) {
|
|
198
|
+
if (!Array.isArray(skills))
|
|
199
|
+
return [];
|
|
200
|
+
return skills
|
|
201
|
+
.map((skill) => basename(skill).replace(/\.md$/i, '').trim())
|
|
202
|
+
.filter(Boolean);
|
|
203
|
+
}
|
|
204
|
+
function lastMeaningfulLine(output) {
|
|
205
|
+
return [...output].reverse().find((line) => line.trim() && !line.startsWith('[stderr]')) ?? '';
|
|
206
|
+
}
|
|
207
|
+
function stripAnsi(value) {
|
|
208
|
+
return value.replace(/\u001b\[[0-9;]*m/g, '');
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=hermes-runtime.js.map
|
|
@@ -27,13 +27,14 @@ export async function runCommitAgent(workspaceId) {
|
|
|
27
27
|
const workingDir = agentService.resolveWorkingDir(workspaceId, commitAgent);
|
|
28
28
|
const systemPrompt = commitAgent.systemPrompt?.trim() || DEFAULT_SYSTEM_PROMPT;
|
|
29
29
|
const truncatedDiff = diff.length > 8000 ? diff.substring(0, 8000) + '\n... (truncated)' : diff;
|
|
30
|
-
const
|
|
30
|
+
const userPrompt = [
|
|
31
31
|
'Generate exactly one commit message for these changes.',
|
|
32
32
|
'Do not inspect files or run commands. Use only this diff.',
|
|
33
33
|
'Output only the commit message.',
|
|
34
34
|
'',
|
|
35
35
|
truncatedDiff,
|
|
36
|
-
].join('\n')
|
|
36
|
+
].join('\n');
|
|
37
|
+
const result = await runtime.execute(prependPersistentAgentContext(userPrompt, {
|
|
37
38
|
workspaceId,
|
|
38
39
|
workingDir,
|
|
39
40
|
boundDirs: ws.boundDirs,
|
|
@@ -41,6 +42,7 @@ export async function runCommitAgent(workspaceId) {
|
|
|
41
42
|
excludeNativeClaudeMd: commitAgent.runtimeKind === 'claude-code',
|
|
42
43
|
}), workingDir, {
|
|
43
44
|
maxTurns: 1,
|
|
45
|
+
userPrompt,
|
|
44
46
|
systemPrompt,
|
|
45
47
|
outputStyle: commitAgent.outputStyle,
|
|
46
48
|
});
|
|
@@ -4,12 +4,13 @@ import * as channelService from '../services/channel.js';
|
|
|
4
4
|
import * as issueService from '../services/issue.js';
|
|
5
5
|
import * as taskService from '../services/task.js';
|
|
6
6
|
import * as workspaceService from '../services/workspace.js';
|
|
7
|
-
import { mapWorkflowToTaskDrafts, validateWorkflowForRun } from '../services/workflow.js';
|
|
7
|
+
import { getWorkflow, mapWorkflowToTaskDrafts, validateWorkflowForRun } from '../services/workflow.js';
|
|
8
8
|
import { createIssueFunctionTools } from '../services/builtin-tools/index.js';
|
|
9
9
|
import { getThinkingRuntimeConfig } from '../services/llm-model-config.js';
|
|
10
10
|
import { prependPersistentAgentContext } from '../services/persistent-agent-context.js';
|
|
11
11
|
import { completeIssueAgentProgress, createIssueAgentProgress, createIssueAgentProgressTracker } from './issue-agent-progress.js';
|
|
12
12
|
import { wrapOnEventWithHooks } from '../services/hook-engine.js';
|
|
13
|
+
import { executeCommandNode } from '../services/workflow-command-runner.js';
|
|
13
14
|
const ACTIVE_TASK_STATUSES = ['running', 'reviewing', 'retrying', 'waiting_review'];
|
|
14
15
|
const activeIssueRuntimes = new Map();
|
|
15
16
|
export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, ctx) {
|
|
@@ -49,8 +50,10 @@ export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, c
|
|
|
49
50
|
},
|
|
50
51
|
});
|
|
51
52
|
const runtime = createRuntimeForPreset(taskSyncPreset);
|
|
52
|
-
const
|
|
53
|
+
const taskSyncUserPrompt = buildTaskSyncPrompt(issue, input, taskSyncWorkingDir);
|
|
54
|
+
const result = await runtime.execute(buildIssueAgentPrompt(workspaceId, taskSyncUserPrompt, taskSyncWorkingDir, taskSyncPreset), taskSyncWorkingDir, {
|
|
53
55
|
maxTurns: 20,
|
|
56
|
+
userPrompt: taskSyncUserPrompt,
|
|
54
57
|
mcpServers: undefined,
|
|
55
58
|
functionTools: createTaskSyncTools(workspaceId, issue, taskSyncPreset, ctx),
|
|
56
59
|
skills: [],
|
|
@@ -135,6 +138,13 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
|
|
|
135
138
|
if (task.status !== 'pending') {
|
|
136
139
|
return;
|
|
137
140
|
}
|
|
141
|
+
// Check if this task came from a command workflow node
|
|
142
|
+
const workflow = findWorkflowForIssue(workspaceId, issue);
|
|
143
|
+
const commandNode = findCommandNodeForTask(workflow, task);
|
|
144
|
+
if (commandNode) {
|
|
145
|
+
await runCommandTask(workspaceId, issueId, taskId, commandNode, ctx);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
138
148
|
const taskAgentPreset = findAgentForTask(workspaceId, issue, task);
|
|
139
149
|
if (!taskAgentPreset) {
|
|
140
150
|
if (issueService.getById(workspaceId, issueId)?.status === 'error')
|
|
@@ -199,8 +209,10 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
|
|
|
199
209
|
});
|
|
200
210
|
let result;
|
|
201
211
|
try {
|
|
202
|
-
|
|
212
|
+
const taskUserPrompt = buildTaskAgentPrompt(issue, runningTask, taskAgentPreset, agentWorkingDir);
|
|
213
|
+
result = await runtime.execute(buildIssueAgentPrompt(workspaceId, taskUserPrompt, agentWorkingDir, taskAgentPreset), agentWorkingDir, {
|
|
203
214
|
maxTurns: 100,
|
|
215
|
+
userPrompt: taskUserPrompt,
|
|
204
216
|
mcpServers: agentService.getMcpServers(taskAgentPreset.mcps),
|
|
205
217
|
functionTools: createCurrentIssueTools(workspaceId, issue, taskAgentPreset),
|
|
206
218
|
skills: agentService.getAvailableSkillNames(agentService.getAgentConfigDir(workspaceId, taskAgentPreset), taskAgentPreset.skills),
|
|
@@ -270,6 +282,48 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
|
|
|
270
282
|
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
|
|
271
283
|
}
|
|
272
284
|
}
|
|
285
|
+
async function runCommandTask(workspaceId, issueId, taskId, commandNode, ctx) {
|
|
286
|
+
const task = taskService.getById(workspaceId, taskId);
|
|
287
|
+
if (!task || task.status !== 'pending')
|
|
288
|
+
return;
|
|
289
|
+
const runningTask = taskService.updateStatus(workspaceId, taskId, 'running');
|
|
290
|
+
if (!runningTask)
|
|
291
|
+
return;
|
|
292
|
+
broadcastTaskUpdate(ctx, runningTask, 'pending');
|
|
293
|
+
ctx.broadcast('task.output', { taskId, data: `$ ${commandNode.data.script.split('\n')[0]}${commandNode.data.script.includes('\n') ? ' ...' : ''}` });
|
|
294
|
+
const result = await executeCommandNode(workspaceId, commandNode);
|
|
295
|
+
ctx.broadcast('task.output', { taskId, data: result.stdout });
|
|
296
|
+
if (result.stderr) {
|
|
297
|
+
ctx.broadcast('task.output', { taskId, data: result.stderr });
|
|
298
|
+
}
|
|
299
|
+
if (!result.success) {
|
|
300
|
+
const failedTask = taskService.updateStatus(workspaceId, taskId, 'failed', {
|
|
301
|
+
result: {
|
|
302
|
+
success: false,
|
|
303
|
+
summary: `Command failed with exit code ${result.exitCode}`,
|
|
304
|
+
artifacts: [],
|
|
305
|
+
error: result.stderr || `Exit code: ${result.exitCode}`,
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
broadcastTaskUpdate(ctx, failedTask, 'running');
|
|
309
|
+
await handleTaskFailure(workspaceId, issueId, taskId, {
|
|
310
|
+
success: false,
|
|
311
|
+
summary: `Command failed with exit code ${result.exitCode}`,
|
|
312
|
+
artifacts: [],
|
|
313
|
+
error: result.stderr || `Exit code: ${result.exitCode}`,
|
|
314
|
+
}, ctx);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const completedTask = taskService.complete(workspaceId, taskId, {
|
|
318
|
+
success: true,
|
|
319
|
+
summary: result.stdout.slice(-500) || 'Command completed',
|
|
320
|
+
artifacts: [],
|
|
321
|
+
});
|
|
322
|
+
broadcastTaskUpdate(ctx, completedTask, 'running');
|
|
323
|
+
if (issueService.getById(workspaceId, issueId)?.continuousRun !== false) {
|
|
324
|
+
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
273
327
|
export async function continueIssueTaskScheduling(workspaceId, issueId, ctx) {
|
|
274
328
|
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx, { force: true });
|
|
275
329
|
}
|
|
@@ -398,7 +452,7 @@ export function createTasksFromWorkflow(workspaceId, issueId, template, ctx) {
|
|
|
398
452
|
});
|
|
399
453
|
}
|
|
400
454
|
function ensureWorkflowAgentsForRun(workspaceId, issue, template, ctx) {
|
|
401
|
-
const workflowAgentIds = [...new Set(template.nodes.map((node) => node.data.agentConfigId).filter(Boolean))];
|
|
455
|
+
const workflowAgentIds = [...new Set(template.nodes.filter((n) => n.type === 'agent').map((node) => node.data.agentConfigId).filter(Boolean))];
|
|
402
456
|
const mergedMembers = [...new Set([...(issue.members ?? []), ...workflowAgentIds])];
|
|
403
457
|
const membersChanged = mergedMembers.length !== (issue.members ?? []).length
|
|
404
458
|
|| mergedMembers.some((member, index) => member !== issue.members?.[index]);
|
|
@@ -498,6 +552,23 @@ function unregisterActiveIssueRuntime(workspaceId, issueId, agentId) {
|
|
|
498
552
|
function issueRunKey(workspaceId, issueId) {
|
|
499
553
|
return `${workspaceId}:${issueId}`;
|
|
500
554
|
}
|
|
555
|
+
function findWorkflowForIssue(workspaceId, issue) {
|
|
556
|
+
if (!issue.workflowId)
|
|
557
|
+
return null;
|
|
558
|
+
return getWorkflow(issue.workflowId);
|
|
559
|
+
}
|
|
560
|
+
function findCommandNodeForTask(workflow, task) {
|
|
561
|
+
if (!workflow)
|
|
562
|
+
return null;
|
|
563
|
+
if (task.agentConfigId)
|
|
564
|
+
return null;
|
|
565
|
+
for (const node of workflow.nodes) {
|
|
566
|
+
if (node.type === 'command' && (task.title === node.data.label || task.description?.startsWith('Command:'))) {
|
|
567
|
+
return node;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
501
572
|
function broadcastTaskUpdate(ctx, task, from) {
|
|
502
573
|
if (!task)
|
|
503
574
|
return;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import * as agentService from '../services/agent.js';
|
|
2
|
+
import { AGENT_GENERATOR_PRESET_ID } from '../services/agent.js';
|
|
3
|
+
import { createAgentRuntime } from '../adapters/agent-runtime.js';
|
|
4
|
+
import { getWorkspace } from '../storage/workspace-store.js';
|
|
5
|
+
import { getThinkingRuntimeConfig } from '../services/llm-model-config.js';
|
|
6
|
+
import { prependPersistentAgentContext } from '../services/persistent-agent-context.js';
|
|
7
|
+
const DEFAULT_SYSTEM_PROMPT = [
|
|
8
|
+
'You are a pull request description generator.',
|
|
9
|
+
'Return a concise, useful PR body based only on the provided commits and diff.',
|
|
10
|
+
'Use Markdown with these sections: Summary and Changes.',
|
|
11
|
+
'Keep it short. Do not greet, explain your process, ask questions, provide options, or wrap the response in code fences.',
|
|
12
|
+
'Output only the final PR body text.',
|
|
13
|
+
].join(' ');
|
|
14
|
+
export async function runPullRequestAgent(workspaceId, input) {
|
|
15
|
+
const ws = getWorkspace(workspaceId);
|
|
16
|
+
if (!ws)
|
|
17
|
+
throw new Error('Workspace not found');
|
|
18
|
+
if (!input.diff.trim() && input.commits.length === 0)
|
|
19
|
+
throw new Error('No changes found');
|
|
20
|
+
const agent = findPullRequestAgent(workspaceId);
|
|
21
|
+
const session = agentService.getOrCreateSessionForConfig(workspaceId, agent);
|
|
22
|
+
agentService.updateStatus(workspaceId, session.id, 'active');
|
|
23
|
+
const runtime = createAgentRuntime({
|
|
24
|
+
kind: agent.runtimeKind,
|
|
25
|
+
provider: agent.modelProvider,
|
|
26
|
+
model: agent.modelId,
|
|
27
|
+
apiKey: agent.apiKey,
|
|
28
|
+
baseURL: agent.apiBase,
|
|
29
|
+
...getThinkingRuntimeConfig(agent),
|
|
30
|
+
});
|
|
31
|
+
const workingDir = agentService.resolveWorkingDir(workspaceId, agent);
|
|
32
|
+
const systemPrompt = DEFAULT_SYSTEM_PROMPT;
|
|
33
|
+
const truncatedDiff = input.diff.length > 12000
|
|
34
|
+
? `${input.diff.substring(0, 12000)}\n... (truncated)`
|
|
35
|
+
: input.diff;
|
|
36
|
+
const userPrompt = [
|
|
37
|
+
`Generate a pull request body for branch ${input.worktree.branch} targeting ${input.baseBranch}.`,
|
|
38
|
+
'',
|
|
39
|
+
'Commits:',
|
|
40
|
+
input.commits.length > 0 ? input.commits.map((commit) => `- ${commit}`).join('\n') : '- No commit messages available',
|
|
41
|
+
'',
|
|
42
|
+
'Diff:',
|
|
43
|
+
truncatedDiff,
|
|
44
|
+
].join('\n');
|
|
45
|
+
const result = await runtime.execute(prependPersistentAgentContext(userPrompt, {
|
|
46
|
+
workspaceId,
|
|
47
|
+
workingDir,
|
|
48
|
+
boundDirs: ws.boundDirs,
|
|
49
|
+
includeWorkspacePrompt: false,
|
|
50
|
+
excludeNativeClaudeMd: agent.runtimeKind === 'claude-code',
|
|
51
|
+
}), workingDir, {
|
|
52
|
+
maxTurns: 1,
|
|
53
|
+
userPrompt,
|
|
54
|
+
systemPrompt,
|
|
55
|
+
outputStyle: agent.outputStyle,
|
|
56
|
+
});
|
|
57
|
+
agentService.complete(workspaceId, session.id, result.success ? undefined : result.error, {
|
|
58
|
+
runtime: agent.runtimeKind,
|
|
59
|
+
model: agent.modelId,
|
|
60
|
+
summary: result.summary,
|
|
61
|
+
output: result.output,
|
|
62
|
+
usage: result.usage,
|
|
63
|
+
costUsd: result.costUsd,
|
|
64
|
+
});
|
|
65
|
+
if (!result.success) {
|
|
66
|
+
throw new Error(result.error || 'Pull request agent failed');
|
|
67
|
+
}
|
|
68
|
+
const body = sanitizePullRequestBody(result.output);
|
|
69
|
+
if (!body)
|
|
70
|
+
throw new Error('Empty response from pull request agent');
|
|
71
|
+
return body;
|
|
72
|
+
}
|
|
73
|
+
function findPullRequestAgent(workspaceId) {
|
|
74
|
+
const presets = agentService.listPresets(workspaceId);
|
|
75
|
+
const preset = presets?.find((a) => a.id === AGENT_GENERATOR_PRESET_ID);
|
|
76
|
+
if (preset)
|
|
77
|
+
return preset;
|
|
78
|
+
const template = agentService.readAgentTemplate(AGENT_GENERATOR_PRESET_ID);
|
|
79
|
+
if (template)
|
|
80
|
+
return template;
|
|
81
|
+
return agentService.listTemplates().find((a) => a.id === AGENT_GENERATOR_PRESET_ID) ?? agentService.listTemplates()[0];
|
|
82
|
+
}
|
|
83
|
+
function sanitizePullRequestBody(output) {
|
|
84
|
+
const chunks = (Array.isArray(output) ? output : [output])
|
|
85
|
+
.map((chunk) => cleanOutputChunk(chunk))
|
|
86
|
+
.filter(Boolean);
|
|
87
|
+
const uniqueChunks = dedupeAdjacentChunks(chunks);
|
|
88
|
+
return (uniqueChunks.at(-1) || uniqueChunks.join('\n\n')).trim();
|
|
89
|
+
}
|
|
90
|
+
function cleanOutputChunk(chunk) {
|
|
91
|
+
return chunk
|
|
92
|
+
.split('\n')
|
|
93
|
+
.filter((line) => !isRuntimeNoise(line))
|
|
94
|
+
.join('\n')
|
|
95
|
+
.replace(/```(?:\w+)?\n([\s\S]*?)```/g, '$1')
|
|
96
|
+
.trim();
|
|
97
|
+
}
|
|
98
|
+
function dedupeAdjacentChunks(chunks) {
|
|
99
|
+
const result = [];
|
|
100
|
+
for (const chunk of chunks) {
|
|
101
|
+
if (result.at(-1)?.trim() === chunk.trim())
|
|
102
|
+
continue;
|
|
103
|
+
result.push(chunk);
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
function isRuntimeNoise(line) {
|
|
108
|
+
const trimmed = line.trim();
|
|
109
|
+
return /^\[Usage\]/.test(trimmed)
|
|
110
|
+
|| /^Claude Code initialized\b/i.test(trimmed)
|
|
111
|
+
|| /^Codex initialized\b/i.test(trimmed)
|
|
112
|
+
|| /^Tool:/i.test(trimmed)
|
|
113
|
+
|| /^Todo:/i.test(trimmed);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=pull-request-agent.js.map
|
|
@@ -16,7 +16,7 @@ export function startScheduler(workspaceId, ctx) {
|
|
|
16
16
|
const tick = async () => {
|
|
17
17
|
// 检查 workspace 是否关闭了自动处理
|
|
18
18
|
const workspace = workspaceService.getById(workspaceId);
|
|
19
|
-
if (workspace && workspace.autoProcessIssues
|
|
19
|
+
if (workspace && workspace.autoProcessIssues !== true) {
|
|
20
20
|
console.log(`[scheduler:${workspaceId}] auto-processing disabled for this workspace, skip`);
|
|
21
21
|
return;
|
|
22
22
|
}
|
package/dist/app.js
CHANGED
|
@@ -5,7 +5,7 @@ import express from 'express';
|
|
|
5
5
|
import cors from 'cors';
|
|
6
6
|
import { createServer } from 'node:http';
|
|
7
7
|
import { WebSocketServer } from 'ws';
|
|
8
|
-
import { existsSync, mkdirSync,
|
|
8
|
+
import { existsSync, mkdirSync, readdirSync } from 'node:fs';
|
|
9
9
|
import { writeFile } from 'node:fs/promises';
|
|
10
10
|
import { join, dirname, extname, basename } from 'node:path';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
@@ -33,15 +33,18 @@ import searchRouter from './routes/search.js';
|
|
|
33
33
|
import notificationRouter from './routes/notification.js';
|
|
34
34
|
import databaseRouter from './routes/database.js';
|
|
35
35
|
import kanbanRouter from './routes/kanban.js';
|
|
36
|
+
import { worktreeRouter } from './routes/worktree.js';
|
|
36
37
|
import speechRecognitionRouter, { handleSpeechStream } from './routes/speech-recognition.js';
|
|
37
38
|
import agentCommandsRouter from './routes/agent-commands.js';
|
|
39
|
+
import robotAccountRouter from './routes/robot-account.js';
|
|
40
|
+
import versionRouter from './routes/version.js';
|
|
38
41
|
import { getUserSettings, setUserAvatarUrl, removeUserAvatarUrl } from './storage/user-settings-store.js';
|
|
39
42
|
import { authMiddleware, verifyToken } from './middleware/auth.js';
|
|
40
43
|
import { handleConnection } from './ws/handler.js';
|
|
41
44
|
import { handleTypeScriptLspConnection } from './ws/typescript-lsp.js';
|
|
42
45
|
import { broadcastToAll } from './ws/connection-manager.js';
|
|
43
46
|
import { startScheduler, stopScheduler } from './agents/scheduler-agent.js';
|
|
44
|
-
import { recoverRunningWorkOnStartup } from './services/issue-retry.js';
|
|
47
|
+
// import { recoverRunningWorkOnStartup } from './services/issue-retry.js';
|
|
45
48
|
import { startPersistedNotificationServices } from './services/notification-hub/index.js';
|
|
46
49
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
47
50
|
const PORT = parseInt(process.env.PORT || '3100', 10);
|
|
@@ -70,73 +73,9 @@ app.use('/api', authMiddleware);
|
|
|
70
73
|
// Serve static files from public/
|
|
71
74
|
const publicDir = resolveRuntimeDir('public');
|
|
72
75
|
app.use('/public', express.static(publicDir));
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (!existsSync(promptDir))
|
|
77
|
-
return;
|
|
78
|
-
const files = readdirSync(promptDir).filter((f) => f.endsWith('.md'));
|
|
79
|
-
const index = files.map((filename) => {
|
|
80
|
-
const id = basename(filename, '.md');
|
|
81
|
-
const content = readFileSync(join(promptDir, filename), 'utf-8');
|
|
82
|
-
const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
|
|
83
|
-
const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
|
|
84
|
-
return { id, name, filename };
|
|
85
|
-
});
|
|
86
|
-
writeFileSync(join(promptDir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
|
|
87
|
-
console.log(`[prompt-store] scanned ${index.length} templates`);
|
|
88
|
-
}
|
|
89
|
-
scanPromptStore();
|
|
90
|
-
// Scan public/output-styles/ and generate index.json
|
|
91
|
-
function scanOutputStyleStore() {
|
|
92
|
-
const dir = join(publicDir, 'output-styles');
|
|
93
|
-
if (!existsSync(dir))
|
|
94
|
-
return;
|
|
95
|
-
const files = readdirSync(dir).filter((f) => f.endsWith('.md'));
|
|
96
|
-
const index = files.map((filename) => {
|
|
97
|
-
const id = basename(filename, '.md');
|
|
98
|
-
const content = readFileSync(join(dir, filename), 'utf-8');
|
|
99
|
-
const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
|
|
100
|
-
const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
|
|
101
|
-
return { id, name, filename };
|
|
102
|
-
});
|
|
103
|
-
writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
|
|
104
|
-
console.log(`[output-style-store] scanned ${index.length} templates`);
|
|
105
|
-
}
|
|
106
|
-
scanOutputStyleStore();
|
|
107
|
-
// Scan public/skills/{group}/{skill-name}/SKILL.md and generate index.json
|
|
108
|
-
function scanSkillStore() {
|
|
109
|
-
const dir = join(publicDir, 'skills');
|
|
110
|
-
if (!existsSync(dir))
|
|
111
|
-
return;
|
|
112
|
-
const index = [];
|
|
113
|
-
for (const groupEntry of readdirSync(dir, { withFileTypes: true })) {
|
|
114
|
-
if (!groupEntry.isDirectory())
|
|
115
|
-
continue;
|
|
116
|
-
const group = groupEntry.name;
|
|
117
|
-
const groupDir = join(dir, group);
|
|
118
|
-
for (const skillEntry of readdirSync(groupDir, { withFileTypes: true })) {
|
|
119
|
-
if (!skillEntry.isDirectory())
|
|
120
|
-
continue;
|
|
121
|
-
const skillName = skillEntry.name;
|
|
122
|
-
const skillFile = join(groupDir, skillName, 'SKILL.md');
|
|
123
|
-
if (!existsSync(skillFile))
|
|
124
|
-
continue;
|
|
125
|
-
const content = readFileSync(skillFile, 'utf-8');
|
|
126
|
-
const fm = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
127
|
-
let name = skillName;
|
|
128
|
-
if (fm) {
|
|
129
|
-
const nameLine = fm[1].split(/\r?\n/).find((l) => /^\s*name\s*:/i.test(l));
|
|
130
|
-
if (nameLine)
|
|
131
|
-
name = nameLine.split(':', 2)[1].trim() || skillName;
|
|
132
|
-
}
|
|
133
|
-
index.push({ id: skillName, name, group, path: `${group}/${skillName}` });
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
|
|
137
|
-
console.log(`[skill-store] scanned ${index.length} skills`);
|
|
138
|
-
}
|
|
139
|
-
scanSkillStore();
|
|
76
|
+
// Serve agents store from packages/agents/
|
|
77
|
+
const agentsDir = resolveRuntimeDir('../agents');
|
|
78
|
+
app.use('/agents-store', express.static(agentsDir));
|
|
140
79
|
app.get('/api/health', (_req, res) => {
|
|
141
80
|
res.json({ status: 'ok', timestamp: new Date().toISOString(), platform: process.platform });
|
|
142
81
|
});
|
|
@@ -254,6 +193,7 @@ app.post('/api/git-config', async (req, res) => {
|
|
|
254
193
|
app.use('/api/workspaces/:id/search', searchRouter);
|
|
255
194
|
app.use('/api/workspaces/:id/database', databaseRouter);
|
|
256
195
|
app.use('/api/workspaces/:id/kanban', kanbanRouter);
|
|
196
|
+
app.use('/api/workspaces/:id/worktrees', worktreeRouter);
|
|
257
197
|
app.use('/api/workspaces/:id/notifications', notificationRouter);
|
|
258
198
|
app.use('/api/agents', agentRouter);
|
|
259
199
|
app.use('/api', llmRouter);
|
|
@@ -265,6 +205,8 @@ app.use('/api/mcps', mcpRouter);
|
|
|
265
205
|
app.use('/api/subscriptions', subscriptionRouter);
|
|
266
206
|
app.use('/api/speech-recognition', speechRecognitionRouter);
|
|
267
207
|
app.use('/api/agent-commands', agentCommandsRouter);
|
|
208
|
+
app.use('/api/robot-accounts', robotAccountRouter);
|
|
209
|
+
app.use('/api', versionRouter);
|
|
268
210
|
// Serve static web frontend in production (after API routes, before catch-all)
|
|
269
211
|
const webDir = resolveRuntimeDir('web');
|
|
270
212
|
if (existsSync(webDir)) {
|
|
@@ -358,7 +300,7 @@ const HOST = process.env.HOST || '0.0.0.0';
|
|
|
358
300
|
server.listen(PORT, HOST, () => {
|
|
359
301
|
console.log(`[server] listening on http://${HOST}:${PORT}`);
|
|
360
302
|
console.log(`[server] websocket on ws://${HOST}:${PORT}/ws?workspaceId=...`);
|
|
361
|
-
recoverRunningWorkOnStartup();
|
|
303
|
+
// recoverRunningWorkOnStartup();
|
|
362
304
|
startPersistedNotificationServices().catch((err) => {
|
|
363
305
|
console.error('[notification] failed to restore persisted services:', err);
|
|
364
306
|
});
|
package/dist/middleware/auth.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getSecret } from '../services/auth-store.js';
|
|
2
2
|
export function authMiddleware(req, res, next) {
|
|
3
3
|
const secret = getSecret();
|
|
4
|
-
const openPaths = ['/api/health', '/api/auth/login', '/api/auth/check'];
|
|
4
|
+
const openPaths = ['/api/health', '/api/auth/login', '/api/auth/check', '/api/version', '/api/version/check'];
|
|
5
5
|
if (openPaths.includes(req.path))
|
|
6
6
|
return next();
|
|
7
7
|
const auth = req.headers.authorization;
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-spaces/server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.66",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "app.js",
|
|
6
6
|
"packageManager": "pnpm@10.17.1",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"@langchain/google-genai": "^2.1.30",
|
|
17
17
|
"@langchain/openai": "^1.4.5",
|
|
18
18
|
"@larksuiteoapi/node-sdk": "^1.62.1",
|
|
19
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
19
20
|
"@openai/codex-sdk": "^0.128.0",
|
|
20
21
|
"cors": "^2.8.5",
|
|
21
22
|
"dotenv": "^17.4.2",
|