@agent-spaces/server 0.3.62 → 0.3.63
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-types.js +12 -0
- package/dist/adapters/claude-code-runtime/index.js +3 -0
- package/dist/adapters/codex-runtime.js +2 -2
- package/dist/adapters/langchain-runtime.js +2 -2
- package/dist/adapters/open-agent-sdk-runtime.js +2 -2
- package/dist/agents/commit-agent.js +1 -0
- package/dist/agents/issue-agent-progress.js +4 -2
- package/dist/agents/issue-agent-runner.js +5 -5
- package/dist/agents/issue-task-controller.js +95 -14
- package/dist/app.js +74 -5
- package/dist/package.json +1 -1
- package/dist/routes/agent-sse.js +4 -2
- package/dist/routes/hooks.js +88 -0
- package/dist/routes/issue.js +59 -1
- package/dist/routes/output-style.js +48 -0
- package/dist/routes/prompt-template.js +2 -2
- package/dist/routes/skill.js +86 -15
- package/dist/routes/task.js +13 -1
- package/dist/services/hook-engine.js +118 -0
- package/dist/services/issue.js +6 -0
- package/dist/services/notification-hub/bot-agent.js +1 -0
- package/dist/services/output-style.js +134 -0
- package/dist/services/prompt-template.js +2 -2
- package/dist/services/skill.js +148 -35
- package/dist/storage/hook-store.js +55 -0
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +4 -4
- package/dist/web/__next._full.txt +25 -24
- 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/0-1bfvfwifh-m.js +1 -0
- package/dist/web/_next/static/chunks/0-f~0xmwl__u5.js +1 -0
- package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +1 -0
- package/dist/web/_next/static/chunks/002_j970b9gdx.js +1 -0
- package/dist/web/_next/static/chunks/014x2qbuiszni.js +3 -0
- package/dist/web/_next/static/chunks/01iqv28_snwus.js +1 -0
- package/dist/web/_next/static/chunks/02c22g~xd-y30.js +19 -0
- package/dist/web/_next/static/chunks/02mf61htij8g0.js +31 -0
- package/dist/web/_next/static/chunks/03scq1-0ykve3.js +1 -0
- package/dist/web/_next/static/chunks/046me66nilkff.js +1 -0
- package/dist/web/_next/static/chunks/04v-pqqs-2lvp.css +1 -0
- package/dist/web/_next/static/chunks/{0zd1o3u04~qvo.js → 05psi2gtx~bev.js} +7 -7
- package/dist/web/_next/static/chunks/{12odetnu-lyrr.js → 06whz1~s_7pva.js} +12 -12
- package/dist/web/_next/static/chunks/06w~.izyfylap.js +1 -0
- package/dist/web/_next/static/chunks/09t62a89~jesc.js +3 -0
- package/dist/web/_next/static/chunks/09y_3krccdd~u.js +1 -0
- package/dist/web/_next/static/chunks/{0njy89g5coeyi.js → 0_8dm7bxp18xo.js} +6 -6
- package/dist/web/_next/static/chunks/0_e~hmntdfop9.js +1 -0
- package/dist/web/_next/static/chunks/0_udc.6.tueey.js +1 -0
- package/dist/web/_next/static/chunks/0_vi1a~g4wx46.js +3 -0
- package/dist/web/_next/static/chunks/{0rke_patcovgr.js → 0aa6bcdmtpekn.js} +1 -1
- package/dist/web/_next/static/chunks/{0tvd~rxgf0oh_.js → 0bbmx45w_h5np.js} +1 -1
- package/dist/web/_next/static/chunks/0cke33d38fnby.js +90 -0
- package/dist/web/_next/static/chunks/{07a0rktf_nr5h.js → 0ctg5qmw7uu.1.js} +2 -2
- package/dist/web/_next/static/chunks/0cyq~8xb~r5fc.js +1 -0
- package/dist/web/_next/static/chunks/0ewceguykiut5.js +1 -0
- package/dist/web/_next/static/chunks/0fxa1edqr7dve.js +1 -0
- package/dist/web/_next/static/chunks/{0202ia13sijwb.js → 0h18ej5yf974e.js} +1 -1
- package/dist/web/_next/static/chunks/0hra80eyuu37u.js +1 -0
- package/dist/web/_next/static/chunks/0i39jifmxla7q.js +1 -0
- package/dist/web/_next/static/chunks/0ie7y4k2ncvnn.js +1 -0
- package/dist/web/_next/static/chunks/0igc~uli58ncw.js +2 -0
- package/dist/web/_next/static/chunks/0kof5qdg8c2-k.js +71 -0
- package/dist/web/_next/static/chunks/{08o-zmr-40r5g.js → 0m11vvph7q94-.js} +1 -1
- package/dist/web/_next/static/chunks/0msb2mi3hiu5_.js +67 -0
- package/dist/web/_next/static/chunks/0np.d~hc1-pmh.js +4 -0
- package/dist/web/_next/static/chunks/{0qpq0~_58fe9a.js → 0oaq67r7ix.vg.js} +1 -1
- package/dist/web/_next/static/chunks/0ogpc3f3keopc.js +3 -0
- package/dist/web/_next/static/chunks/{0d_dp_4ofz0l3.css → 0ojcao3hdm36s.css} +0 -1
- package/dist/web/_next/static/chunks/0p1n8bvfnpl41.js +1 -0
- package/dist/web/_next/static/chunks/{0gig.k.rq8d0x.js → 0ppr271hz0xoq.js} +1 -1
- package/dist/web/_next/static/chunks/0s_dva~eh2yhi.js +3 -0
- package/dist/web/_next/static/chunks/0typj55ox8d5i.js +1 -0
- package/dist/web/_next/static/chunks/0w2p4ldi2aymp.js +1 -0
- package/dist/web/_next/static/chunks/{0..g0jl-8qup7.js → 0xoo17yef_b8g.js} +1 -1
- package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +1 -0
- package/dist/web/_next/static/chunks/0y09i51u6ixq5.js +1 -0
- package/dist/web/_next/static/chunks/0za1r07-6az6w.js +1 -0
- package/dist/web/_next/static/chunks/0zc0xgp5ourcn.js +1 -0
- package/dist/web/_next/static/chunks/0zmhdridea1s5.js +90 -0
- package/dist/web/_next/static/chunks/0~u.5r3-t7179.js +1 -0
- package/dist/web/_next/static/chunks/10.alq.6stmld.js +1 -0
- package/dist/web/_next/static/chunks/11-czmcci_55y.js +1 -0
- package/dist/web/_next/static/chunks/11b3zgk1etlkw.js +7 -0
- package/dist/web/_next/static/chunks/11k-.49r~1mfm.js +1 -0
- package/dist/web/_next/static/chunks/11qp8r5dotf7d.js +1 -0
- package/dist/web/_next/static/chunks/{0k.8qdk7oi_os.js → 128ugqd34tr_-.js} +1 -1
- package/dist/web/_next/static/chunks/12mxlicp247c8.js +1 -0
- package/dist/web/_next/static/chunks/135w27dd8c19s.js +5 -0
- package/dist/web/_next/static/chunks/13~y-b.b9rrw4.js +1 -0
- package/dist/web/_next/static/chunks/{0jokpgh485~28.js → 14hqmid8q4apf.js} +11 -11
- package/dist/web/_next/static/chunks/16sg-lflc8csx.js +1 -0
- package/dist/web/_next/static/chunks/176dc-dtokxxi.js +16 -0
- package/dist/web/_next/static/chunks/17g-0pqre.anw.js +1 -0
- package/dist/web/_next/static/chunks/17oc2l.ekcs8b.css +1 -0
- package/dist/web/_next/static/chunks/{turbopack-0lrdxynxb9-1t.js → turbopack-0ndm2zc_pdptk.js} +1 -1
- package/dist/web/_not-found/__next._full.txt +29 -30
- 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 +29 -30
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +25 -24
- package/dist/web/login/__next._full.txt +29 -29
- 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 +29 -29
- package/dist/web/settings/__next._full.txt +28 -28
- 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 +43 -0
- package/dist/web/settings/output-styles/__next._head.txt +6 -0
- package/dist/web/settings/output-styles/__next._index.txt +15 -0
- package/dist/web/settings/output-styles/__next._tree.txt +8 -0
- package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +9 -0
- package/dist/web/settings/output-styles/__next.settings.output-styles.txt +5 -0
- package/dist/web/settings/output-styles/__next.settings.txt +7 -0
- package/dist/web/settings/output-styles.html +1 -0
- package/dist/web/settings/output-styles.txt +43 -0
- 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.html +1 -1
- package/dist/web/settings.txt +28 -28
- package/dist/web/workflows/__next._full.txt +32 -31
- 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 +32 -31
- package/dist/web/workspace/_/__next._full.txt +30 -71
- 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 -17
- package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -18
- 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 +30 -71
- package/dist/web/workspaces/__next._full.txt +31 -32
- 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 +31 -32
- package/dist/ws/agent-runner.js +4 -2
- package/package.json +1 -1
- package/public/output-styles/carmack-mode.md +381 -0
- package/public/output-styles/codex-rigor-mode.md +114 -0
- package/public/output-styles/dhh-mode.md +265 -0
- package/public/output-styles/evan-you-mode.md +539 -0
- package/public/output-styles/index.json +37 -0
- package/public/output-styles/jobs-mode.md +369 -0
- package/public/output-styles/linus-mode.md +135 -0
- package/public/output-styles/uncle-bob-mode.md +221 -0
- package/public/prompt/andrej-karpathy-skills.md +65 -0
- package/public/prompt/claude-token-efficient-coding.md +35 -0
- package/public/prompt/index.json +12 -0
- package/public/skills/index.json +92 -0
- package/public/skills/planning-with-files/planning-with-files-zh/SKILL.md +243 -0
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.ps1 +44 -0
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.sh +46 -0
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.ps1 +124 -0
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.sh +124 -0
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/session-catchup.py +438 -0
- package/public/skills/planning-with-files/planning-with-files-zh/templates/findings.md +29 -0
- package/public/skills/planning-with-files/planning-with-files-zh/templates/progress.md +40 -0
- package/public/skills/planning-with-files/planning-with-files-zh/templates/task_plan.md +58 -0
- package/public/skills/superpowers/brainstorming/SKILL.md +164 -0
- package/public/skills/superpowers/brainstorming/scripts/frame-template.html +214 -0
- package/public/skills/superpowers/brainstorming/scripts/helper.js +88 -0
- package/public/skills/superpowers/brainstorming/scripts/server.cjs +354 -0
- package/public/skills/superpowers/brainstorming/scripts/start-server.sh +148 -0
- package/public/skills/superpowers/brainstorming/scripts/stop-server.sh +56 -0
- package/public/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/public/skills/superpowers/brainstorming/visual-companion.md +287 -0
- package/public/skills/superpowers/dispatching-parallel-agents/SKILL.md +182 -0
- package/public/skills/superpowers/executing-plans/SKILL.md +70 -0
- package/public/skills/superpowers/finishing-a-development-branch/SKILL.md +251 -0
- package/public/skills/superpowers/receiving-code-review/SKILL.md +213 -0
- package/public/skills/superpowers/requesting-code-review/SKILL.md +103 -0
- package/public/skills/superpowers/requesting-code-review/code-reviewer.md +168 -0
- package/public/skills/superpowers/subagent-driven-development/SKILL.md +279 -0
- package/public/skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +25 -0
- package/public/skills/superpowers/subagent-driven-development/implementer-prompt.md +113 -0
- package/public/skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/public/skills/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
- package/public/skills/superpowers/systematic-debugging/SKILL.md +296 -0
- package/public/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/public/skills/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
- package/public/skills/superpowers/systematic-debugging/defense-in-depth.md +122 -0
- package/public/skills/superpowers/systematic-debugging/find-polluter.sh +63 -0
- package/public/skills/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
- package/public/skills/superpowers/systematic-debugging/test-academic.md +14 -0
- package/public/skills/superpowers/systematic-debugging/test-pressure-1.md +58 -0
- package/public/skills/superpowers/systematic-debugging/test-pressure-2.md +68 -0
- package/public/skills/superpowers/systematic-debugging/test-pressure-3.md +69 -0
- package/public/skills/superpowers/test-driven-development/SKILL.md +371 -0
- package/public/skills/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
- package/public/skills/superpowers/using-git-worktrees/SKILL.md +215 -0
- package/public/skills/superpowers/using-superpowers/SKILL.md +117 -0
- package/public/skills/superpowers/using-superpowers/references/codex-tools.md +59 -0
- package/public/skills/superpowers/using-superpowers/references/copilot-tools.md +42 -0
- package/public/skills/superpowers/using-superpowers/references/gemini-tools.md +51 -0
- package/public/skills/superpowers/verification-before-completion/SKILL.md +139 -0
- package/public/skills/superpowers/writing-plans/SKILL.md +152 -0
- package/public/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/public/skills/superpowers/writing-skills/SKILL.md +655 -0
- package/public/skills/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
- package/public/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/public/skills/superpowers/writing-skills/graphviz-conventions.dot +172 -0
- package/public/skills/superpowers/writing-skills/persuasion-principles.md +187 -0
- package/public/skills/superpowers/writing-skills/render-graphs.js +168 -0
- package/public/skills/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
- package/dist/web/_next/static/chunks/0-81wi7xr2nd-.js +0 -270
- package/dist/web/_next/static/chunks/00lca9lsasdm7.js +0 -1
- package/dist/web/_next/static/chunks/01gi~q0c6ez6..js +0 -1
- package/dist/web/_next/static/chunks/02shswpmybici.js +0 -1
- package/dist/web/_next/static/chunks/05tx6hzdtkgi9.js +0 -2
- package/dist/web/_next/static/chunks/07nbyndvzftr1.js +0 -3
- package/dist/web/_next/static/chunks/0bn~onkv~9xza.js +0 -1
- package/dist/web/_next/static/chunks/0g-0n6glz_z6w.js +0 -1
- package/dist/web/_next/static/chunks/0gyede80jpy3n.js +0 -4
- package/dist/web/_next/static/chunks/0hrbuvzuxrjfl.js +0 -1
- package/dist/web/_next/static/chunks/0i51q.5s_-.vh.css +0 -1
- package/dist/web/_next/static/chunks/0qf163pbrwy4z.js +0 -1
- package/dist/web/_next/static/chunks/0rnt-f3pjxb-d.js +0 -5
- package/dist/web/_next/static/chunks/0tgbcgsca9mrg.js +0 -1
- package/dist/web/_next/static/chunks/0tyhv6.y7~yxd.js +0 -1
- package/dist/web/_next/static/chunks/0u7_qd9hzqwac.js +0 -1
- package/dist/web/_next/static/chunks/0vuvql8rloda5.js +0 -1
- package/dist/web/_next/static/chunks/0wv0h27jafag4.js +0 -1
- package/dist/web/_next/static/chunks/0wwvc4zc2q6bn.js +0 -1
- package/dist/web/_next/static/chunks/0xmmk3vebw8xs.js +0 -1
- package/dist/web/_next/static/chunks/0xwqf.llmm_u2.js +0 -31
- package/dist/web/_next/static/chunks/0yo22_w53mo~5.js +0 -1
- package/dist/web/_next/static/chunks/12c0jp0qvlr1t.js +0 -1
- package/dist/web/_next/static/chunks/12pg1nn3v~~5k.js +0 -1
- package/dist/web/_next/static/chunks/16cyr8ilpx1nn.js +0 -1
- package/public/avatars/1777813826407-bea0ja-minimax.svg +0 -1
- package/public/avatars/1777813967088-3xlvd0-minimax.svg +0 -1
- package/public/avatars/1777814041714-yp0qeq-minimax.svg +0 -1
- package/public/avatars/1777904986095-rg26je-icon.png +0 -0
- package/public/avatars/1778953228323-5je54x-user.jpg +0 -0
- package/public/avatars/1778954057880-g01q6y-user.jpg +0 -0
- /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → OoXAsPtrUWjC1l898FSvI}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → OoXAsPtrUWjC1l898FSvI}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{GS3b40oeaeLxm7i9-ibaj → OoXAsPtrUWjC1l898FSvI}/_ssgManifest.js +0 -0
- /package/public/avatars/{1777815865622-08wp9m-user.jpg → user.jpg} +0 -0
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
import { resolveOutputStyleContent } from '../services/output-style.js';
|
|
1
2
|
export function summarizeResult(text) {
|
|
2
3
|
const normalized = text.trim().replace(/\s+/g, ' ');
|
|
3
4
|
if (!normalized)
|
|
4
5
|
return 'Completed agent execution';
|
|
5
6
|
return normalized.length > 160 ? `${normalized.slice(0, 157)}...` : normalized;
|
|
6
7
|
}
|
|
8
|
+
export function appendOutputStyleToPrompt(prompt, outputStyle) {
|
|
9
|
+
const style = resolveOutputStyleContent(outputStyle)?.trim();
|
|
10
|
+
if (!style)
|
|
11
|
+
return prompt;
|
|
12
|
+
return [
|
|
13
|
+
prompt.trimEnd(),
|
|
14
|
+
'',
|
|
15
|
+
'Output style instructions:',
|
|
16
|
+
style,
|
|
17
|
+
].join('\n');
|
|
18
|
+
}
|
|
7
19
|
//# sourceMappingURL=agent-runtime-types.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
3
3
|
import { summarizeResult } from '../agent-runtime-types.js';
|
|
4
|
+
import { prepareClaudeOutputStyleFile } from '../../services/output-style.js';
|
|
4
5
|
import { normalizeAdditionalDirectories, normalizePermissionMode, normalizeSkillNames, prepareConfigDir, resolveBundledClaudeExecutable, buildEnv, normalizeMcpServers } from './sdk-config.js';
|
|
5
6
|
import { startClaudeAdapterIfNeeded, getClaudeCodeModel } from './adapter-pool.js';
|
|
6
7
|
import { extractThinkingEvents, extractToolUseEvents, extractToolResultEvent, logToolDebug, formatMessage, isAskUserQuestionAutoResult, countUsageTokens, formatUsageLine, normalizeUsage } from './message-format.js';
|
|
@@ -25,6 +26,7 @@ export class ClaudeCodeRuntime {
|
|
|
25
26
|
if (configDir)
|
|
26
27
|
prepareConfigDir(configDir, agentDir);
|
|
27
28
|
const skillNames = normalizeSkillNames(options?.skills, configDir);
|
|
29
|
+
const outputStyleFile = configDir ? prepareClaudeOutputStyleFile(configDir, options?.outputStyle) : undefined;
|
|
28
30
|
const claudeExecutable = resolveBundledClaudeExecutable();
|
|
29
31
|
this.adapterRun = await startClaudeAdapterIfNeeded(this.config);
|
|
30
32
|
const baseURL = this.adapterRun?.url ?? this.config.baseURL;
|
|
@@ -46,6 +48,7 @@ export class ClaudeCodeRuntime {
|
|
|
46
48
|
tools: { type: 'preset', preset: 'claude_code' },
|
|
47
49
|
mcpServers: sdkMcpServers,
|
|
48
50
|
skills: skillNames,
|
|
51
|
+
outputStyle: outputStyleFile,
|
|
49
52
|
managedSettings: {
|
|
50
53
|
strictPluginOnlyCustomization: ['mcp'],
|
|
51
54
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { basename, extname, join } from 'node:path';
|
|
3
3
|
import { Codex } from '@openai/codex-sdk';
|
|
4
|
-
import { summarizeResult } from './agent-runtime-types.js';
|
|
4
|
+
import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
|
|
5
5
|
/**
|
|
6
6
|
* Runtime backed by OpenAI's Codex SDK.
|
|
7
7
|
* Spawns the bundled Codex CLI and consumes its structured JSONL event stream.
|
|
@@ -48,7 +48,7 @@ export class CodexRuntime {
|
|
|
48
48
|
const thread = options?.resumeSessionId
|
|
49
49
|
? codex.resumeThread(options.resumeSessionId, threadOptions)
|
|
50
50
|
: codex.startThread(threadOptions);
|
|
51
|
-
const { events } = await thread.runStreamed(prompt, {
|
|
51
|
+
const { events } = await thread.runStreamed(appendOutputStyleToPrompt(prompt, options?.outputStyle), {
|
|
52
52
|
signal: this.abortController.signal,
|
|
53
53
|
});
|
|
54
54
|
let resultText = '';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createAgent, initChatModel, tool } from 'langchain';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { summarizeResult } from './agent-runtime-types.js';
|
|
3
|
+
import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Runtime backed by LangChain.js.
|
|
6
6
|
* Uses LangChain's provider-neutral createAgent API and adapts Agent Spaces tools.
|
|
@@ -27,7 +27,7 @@ export class LangChainRuntime {
|
|
|
27
27
|
tools: buildLangChainTools(options?.functionTools, output, options),
|
|
28
28
|
systemPrompt: options?.systemPrompt,
|
|
29
29
|
});
|
|
30
|
-
const result = await agent.invoke({ messages: [{ role: 'user', content: prompt }] }, {
|
|
30
|
+
const result = await agent.invoke({ messages: [{ role: 'user', content: appendOutputStyleToPrompt(prompt, options?.outputStyle) }] }, {
|
|
31
31
|
signal: this.abortController?.signal,
|
|
32
32
|
recursionLimit: options?.maxTurns ? Math.max(2, options.maxTurns * 2 + 1) : undefined,
|
|
33
33
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAgent } from '@codeany/open-agent-sdk';
|
|
2
|
-
import { summarizeResult } from './agent-runtime-types.js';
|
|
2
|
+
import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Runtime backed by @codeany/open-agent-sdk.
|
|
5
5
|
* Runs the agent loop in-process with the SDK's built-in tools.
|
|
@@ -35,7 +35,7 @@ export class OpenAgentSdkRuntime {
|
|
|
35
35
|
});
|
|
36
36
|
d('agent created, sending prompt...');
|
|
37
37
|
d('tool debug | open-agent-sdk runtime does not expose per-tool stream events through prompt(); only final text/usage is available here');
|
|
38
|
-
const result = await this.agent.prompt(prompt);
|
|
38
|
+
const result = await this.agent.prompt(appendOutputStyleToPrompt(prompt, options?.outputStyle));
|
|
39
39
|
const elapsed = Date.now() - startTime;
|
|
40
40
|
const inputTokens = result.usage.input_tokens;
|
|
41
41
|
const outputTokens = result.usage.output_tokens;
|
|
@@ -42,6 +42,7 @@ export async function runCommitAgent(workspaceId) {
|
|
|
42
42
|
}), workingDir, {
|
|
43
43
|
maxTurns: 1,
|
|
44
44
|
systemPrompt,
|
|
45
|
+
outputStyle: commitAgent.outputStyle,
|
|
45
46
|
});
|
|
46
47
|
agentService.complete(workspaceId, session.id, result.success ? undefined : result.error, {
|
|
47
48
|
runtime: commitAgent.runtimeKind,
|
|
@@ -74,7 +74,9 @@ export function createIssueAgentProgress(workspaceId, issue, preset, agentSessio
|
|
|
74
74
|
return { message, comment };
|
|
75
75
|
}
|
|
76
76
|
export function completeIssueAgentProgress(workspaceId, issue, progress, summary, output, metadata) {
|
|
77
|
-
const
|
|
77
|
+
const parts = metadata.parts;
|
|
78
|
+
const finalText = [...(parts ?? [])].reverse().find((part) => part.type === 'text')?.text.trim();
|
|
79
|
+
const content = finalText || summary.trim() || output.join('\n').trim();
|
|
78
80
|
if (!content.trim())
|
|
79
81
|
return;
|
|
80
82
|
const message = messageService.updateMessage(workspaceId, issue.channelId, progress.message.id, {
|
|
@@ -88,7 +90,7 @@ export function completeIssueAgentProgress(workspaceId, issue, progress, summary
|
|
|
88
90
|
summary,
|
|
89
91
|
duration: metadata.duration,
|
|
90
92
|
},
|
|
91
|
-
parts
|
|
93
|
+
parts,
|
|
92
94
|
});
|
|
93
95
|
if (message)
|
|
94
96
|
broadcastToWorkspace(workspaceId, 'channel.message.updated', message);
|
|
@@ -9,6 +9,11 @@ export async function runIssueAutomation(workspaceId, issueId, ctx) {
|
|
|
9
9
|
console.warn(`[issue-runner] issue not found workspaceId=${workspaceId} issueId=${issueId}`);
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
+
const tasks = taskService.list(workspaceId, issueId);
|
|
13
|
+
if (tasks.length > 0) {
|
|
14
|
+
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
12
17
|
// Workflow template branch
|
|
13
18
|
if (issue.workflowId) {
|
|
14
19
|
const template = workflowService.getWorkflow(issue.workflowId);
|
|
@@ -29,11 +34,6 @@ export async function runIssueAutomation(workspaceId, issueId, ctx) {
|
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
|
-
const tasks = taskService.list(workspaceId, issueId);
|
|
33
|
-
if (tasks.length > 0) {
|
|
34
|
-
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
37
|
console.warn(`[issue-runner] no workflow configured for issue workspaceId=${workspaceId} issueId=${issueId}`);
|
|
38
38
|
}
|
|
39
39
|
export function hasActiveIssueAutomation(workspaceId) {
|
|
@@ -9,7 +9,9 @@ import { createIssueFunctionTools } from '../services/builtin-tools.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
|
+
import { wrapOnEventWithHooks } from '../services/hook-engine.js';
|
|
12
13
|
const ACTIVE_TASK_STATUSES = ['running', 'reviewing', 'retrying', 'waiting_review'];
|
|
14
|
+
const activeIssueRuntimes = new Map();
|
|
13
15
|
export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, ctx) {
|
|
14
16
|
const issue = issueService.getById(workspaceId, issueId);
|
|
15
17
|
if (!issue) {
|
|
@@ -31,6 +33,7 @@ export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, c
|
|
|
31
33
|
ctx.broadcast('agent.output', { agentId: taskSyncAgent.id, data: `Syncing issue tasks: ${issueId}` });
|
|
32
34
|
const startTime = Date.now();
|
|
33
35
|
const taskSyncWorkingDir = resolveIssueWorkspaceRoot(workspaceId);
|
|
36
|
+
const workspace = workspaceService.getById(workspaceId);
|
|
34
37
|
const progress = createIssueAgentProgress(workspaceId, issue, taskSyncPreset, taskSyncAgent.id, {
|
|
35
38
|
runtime: taskSyncPreset.runtimeKind,
|
|
36
39
|
model: taskSyncPreset.modelId,
|
|
@@ -53,7 +56,8 @@ export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, c
|
|
|
53
56
|
skills: [],
|
|
54
57
|
configDir: agentService.getAgentConfigDir(workspaceId, taskSyncPreset),
|
|
55
58
|
sandboxDirs: taskSyncPreset.sandboxDirs,
|
|
56
|
-
|
|
59
|
+
outputStyle: taskSyncPreset.outputStyle,
|
|
60
|
+
onEvent: wrapOnEventWithHooks(taskSyncTracker.handleEvent.bind(taskSyncTracker), workspaceId, workspace?.hooksEnabled),
|
|
57
61
|
});
|
|
58
62
|
if (taskSyncTracker.output.length === 0) {
|
|
59
63
|
for (const line of result.output) {
|
|
@@ -101,7 +105,10 @@ export async function syncIssueTasksAfterPlanning(workspaceId, issueId, input, c
|
|
|
101
105
|
updateIssueStatus(workspaceId, issueId, 'in_progress', ctx);
|
|
102
106
|
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
|
|
103
107
|
}
|
|
104
|
-
export async function scheduleRunnableIssueTasks(workspaceId, issueId, ctx) {
|
|
108
|
+
export async function scheduleRunnableIssueTasks(workspaceId, issueId, ctx, _options = {}) {
|
|
109
|
+
const issue = issueService.getById(workspaceId, issueId);
|
|
110
|
+
if (!issue)
|
|
111
|
+
return;
|
|
105
112
|
const tasks = taskService.list(workspaceId, issueId);
|
|
106
113
|
const doneIds = new Set(tasks.filter((task) => task.status === 'done').map((task) => task.id));
|
|
107
114
|
const hasActive = tasks.some((task) => ACTIVE_TASK_STATUSES.includes(task.status));
|
|
@@ -113,7 +120,8 @@ export async function scheduleRunnableIssueTasks(workspaceId, issueId, ctx) {
|
|
|
113
120
|
}
|
|
114
121
|
return;
|
|
115
122
|
}
|
|
116
|
-
|
|
123
|
+
const tasksToRun = issue.continuousRun === false ? runnable.slice(0, 1) : runnable;
|
|
124
|
+
for (const task of tasksToRun) {
|
|
117
125
|
await runIssueTask(workspaceId, issueId, task.id, ctx);
|
|
118
126
|
}
|
|
119
127
|
}
|
|
@@ -129,6 +137,8 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
|
|
|
129
137
|
}
|
|
130
138
|
const taskAgentPreset = findAgentForTask(workspaceId, issue, task);
|
|
131
139
|
if (!taskAgentPreset) {
|
|
140
|
+
if (issueService.getById(workspaceId, issueId)?.status === 'error')
|
|
141
|
+
return;
|
|
132
142
|
const missingExecutorResult = {
|
|
133
143
|
success: false,
|
|
134
144
|
summary: 'No runnable agent configured in issue channel members',
|
|
@@ -161,6 +171,7 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
|
|
|
161
171
|
broadcastTaskUpdate(ctx, runningTask, task.status);
|
|
162
172
|
agentService.assignTask(workspaceId, taskAgent.id, taskId);
|
|
163
173
|
const runtime = createRuntimeForPreset(taskAgentPreset);
|
|
174
|
+
registerActiveIssueRuntime(workspaceId, issueId, taskAgent.id, runtime);
|
|
164
175
|
const agentWorkingDir = resolveIssueWorkspaceRoot(workspaceId);
|
|
165
176
|
const startTime = Date.now();
|
|
166
177
|
const progress = createIssueAgentProgress(workspaceId, issue, taskAgentPreset, taskAgent.id, {
|
|
@@ -180,20 +191,40 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
|
|
|
180
191
|
ctx.broadcast('task.output', { taskId, data: line });
|
|
181
192
|
},
|
|
182
193
|
});
|
|
194
|
+
const workspace = workspaceService.getById(workspaceId);
|
|
183
195
|
ctx.broadcast('agent.output', { agentId: taskAgent.id, data: `Executing task: ${runningTask.title}` });
|
|
184
196
|
ctx.broadcast('agent.output', {
|
|
185
197
|
agentId: taskAgent.id,
|
|
186
198
|
data: `[debug] workflow agentConfigId=${taskAgentPreset.id} role=${taskAgentPreset.role} taskAgentConfigId=${runningTask.agentConfigId || '(fallback)'} runtime=${taskAgentPreset.runtimeKind ?? 'open-agent-sdk'}`,
|
|
187
199
|
});
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
let result;
|
|
201
|
+
try {
|
|
202
|
+
result = await runtime.execute(buildIssueAgentPrompt(workspaceId, buildTaskAgentPrompt(issue, runningTask, taskAgentPreset, agentWorkingDir), agentWorkingDir, taskAgentPreset), agentWorkingDir, {
|
|
203
|
+
maxTurns: 100,
|
|
204
|
+
mcpServers: agentService.getMcpServers(taskAgentPreset.mcps),
|
|
205
|
+
functionTools: createCurrentIssueTools(workspaceId, issue, taskAgentPreset),
|
|
206
|
+
skills: agentService.getAvailableSkillNames(agentService.getAgentConfigDir(workspaceId, taskAgentPreset), taskAgentPreset.skills),
|
|
207
|
+
configDir: agentService.getAgentConfigDir(workspaceId, taskAgentPreset),
|
|
208
|
+
sandboxDirs: runningTask.sandboxDirs ?? taskAgentPreset.sandboxDirs,
|
|
209
|
+
outputStyle: taskAgentPreset.outputStyle,
|
|
210
|
+
onEvent: wrapOnEventWithHooks(agentTracker.handleEvent.bind(agentTracker), workspaceId, workspace?.hooksEnabled),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
unregisterActiveIssueRuntime(workspaceId, issueId, taskAgent.id);
|
|
215
|
+
}
|
|
216
|
+
if (issueService.getById(workspaceId, issueId)?.status === 'error') {
|
|
217
|
+
const failedTask = taskService.updateStatus(workspaceId, taskId, 'failed', {
|
|
218
|
+
result: {
|
|
219
|
+
success: false,
|
|
220
|
+
summary: 'Interrupted by user',
|
|
221
|
+
artifacts: [],
|
|
222
|
+
error: 'Interrupted by user',
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
broadcastTaskUpdate(ctx, failedTask, 'running');
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
197
228
|
if (agentTracker.output.length === 0) {
|
|
198
229
|
for (const line of result.output) {
|
|
199
230
|
agentTracker.output.push(line);
|
|
@@ -235,10 +266,42 @@ export async function runIssueTask(workspaceId, issueId, taskId, ctx) {
|
|
|
235
266
|
}
|
|
236
267
|
const completedTask = taskService.complete(workspaceId, taskId, result);
|
|
237
268
|
broadcastTaskUpdate(ctx, completedTask, 'running');
|
|
238
|
-
|
|
269
|
+
if (issueService.getById(workspaceId, issueId)?.continuousRun !== false) {
|
|
270
|
+
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
|
|
271
|
+
}
|
|
239
272
|
}
|
|
240
273
|
export async function continueIssueTaskScheduling(workspaceId, issueId, ctx) {
|
|
241
|
-
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx);
|
|
274
|
+
await scheduleRunnableIssueTasks(workspaceId, issueId, ctx, { force: true });
|
|
275
|
+
}
|
|
276
|
+
export function stopIssueAutomation(workspaceId, issueId, reason = 'Interrupted by user') {
|
|
277
|
+
const key = issueRunKey(workspaceId, issueId);
|
|
278
|
+
const runtimes = activeIssueRuntimes.get(key);
|
|
279
|
+
if (runtimes) {
|
|
280
|
+
for (const [agentId, runtime] of runtimes.entries()) {
|
|
281
|
+
try {
|
|
282
|
+
runtime.stop();
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
// Runtime may already be unwinding.
|
|
286
|
+
}
|
|
287
|
+
agentService.complete(workspaceId, agentId, reason);
|
|
288
|
+
}
|
|
289
|
+
activeIssueRuntimes.delete(key);
|
|
290
|
+
}
|
|
291
|
+
const activeTasks = taskService.list(workspaceId, issueId)
|
|
292
|
+
.filter((task) => ACTIVE_TASK_STATUSES.includes(task.status));
|
|
293
|
+
return activeTasks.map((task) => {
|
|
294
|
+
const from = task.status;
|
|
295
|
+
const failed = taskService.updateStatus(workspaceId, task.id, 'failed', {
|
|
296
|
+
result: {
|
|
297
|
+
success: false,
|
|
298
|
+
summary: reason,
|
|
299
|
+
artifacts: [],
|
|
300
|
+
error: reason,
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
return failed ? { task: failed, from } : null;
|
|
304
|
+
}).filter((item) => Boolean(item));
|
|
242
305
|
}
|
|
243
306
|
function createTaskSyncTools(workspaceId, issue, preset, ctx) {
|
|
244
307
|
return [
|
|
@@ -417,6 +480,24 @@ async function handleTaskFailure(workspaceId, issueId, taskId, result, ctx) {
|
|
|
417
480
|
ctx.broadcast('issue.status_changed', { issueId, from: issue?.status ?? 'in_progress', to: 'error' });
|
|
418
481
|
ctx.broadcast('issue.updated', updated);
|
|
419
482
|
}
|
|
483
|
+
function registerActiveIssueRuntime(workspaceId, issueId, agentId, runtime) {
|
|
484
|
+
const key = issueRunKey(workspaceId, issueId);
|
|
485
|
+
const runtimes = activeIssueRuntimes.get(key) ?? new Map();
|
|
486
|
+
runtimes.set(agentId, runtime);
|
|
487
|
+
activeIssueRuntimes.set(key, runtimes);
|
|
488
|
+
}
|
|
489
|
+
function unregisterActiveIssueRuntime(workspaceId, issueId, agentId) {
|
|
490
|
+
const key = issueRunKey(workspaceId, issueId);
|
|
491
|
+
const runtimes = activeIssueRuntimes.get(key);
|
|
492
|
+
if (!runtimes)
|
|
493
|
+
return;
|
|
494
|
+
runtimes.delete(agentId);
|
|
495
|
+
if (runtimes.size === 0)
|
|
496
|
+
activeIssueRuntimes.delete(key);
|
|
497
|
+
}
|
|
498
|
+
function issueRunKey(workspaceId, issueId) {
|
|
499
|
+
return `${workspaceId}:${issueId}`;
|
|
500
|
+
}
|
|
420
501
|
function broadcastTaskUpdate(ctx, task, from) {
|
|
421
502
|
if (!task)
|
|
422
503
|
return;
|
package/dist/app.js
CHANGED
|
@@ -5,9 +5,9 @@ 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 } from 'node:fs';
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
9
9
|
import { writeFile } from 'node:fs/promises';
|
|
10
|
-
import { join, dirname } from 'node:path';
|
|
10
|
+
import { join, dirname, basename } from 'node:path';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
12
|
import workspaceRouter from './routes/workspace.js';
|
|
13
13
|
import fileRouter from './routes/file.js';
|
|
@@ -22,8 +22,10 @@ import authRouter from './routes/auth.js';
|
|
|
22
22
|
import folderRouter from './routes/folder.js';
|
|
23
23
|
import commandRouter from './routes/command.js';
|
|
24
24
|
import codeFavoritesRouter from './routes/code-favorites.js';
|
|
25
|
+
import hooksRouter from './routes/hooks.js';
|
|
25
26
|
import skillRouter from './routes/skill.js';
|
|
26
27
|
import promptTemplateRouter from './routes/prompt-template.js';
|
|
28
|
+
import outputStyleRouter from './routes/output-style.js';
|
|
27
29
|
import mcpRouter from './routes/mcp.js';
|
|
28
30
|
import subscriptionRouter from './routes/subscription.js';
|
|
29
31
|
import agentSseRouter from './routes/agent-sse.js';
|
|
@@ -65,6 +67,73 @@ app.use('/api', authMiddleware);
|
|
|
65
67
|
// Serve static files from public/
|
|
66
68
|
const publicDir = resolveRuntimeDir('public');
|
|
67
69
|
app.use('/public', express.static(publicDir));
|
|
70
|
+
// Scan public/prompt/ and generate index.json for the prompt store
|
|
71
|
+
function scanPromptStore() {
|
|
72
|
+
const promptDir = join(publicDir, 'prompt');
|
|
73
|
+
if (!existsSync(promptDir))
|
|
74
|
+
return;
|
|
75
|
+
const files = readdirSync(promptDir).filter((f) => f.endsWith('.md'));
|
|
76
|
+
const index = files.map((filename) => {
|
|
77
|
+
const id = basename(filename, '.md');
|
|
78
|
+
const content = readFileSync(join(promptDir, filename), 'utf-8');
|
|
79
|
+
const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
|
|
80
|
+
const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
|
|
81
|
+
return { id, name, filename };
|
|
82
|
+
});
|
|
83
|
+
writeFileSync(join(promptDir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
|
|
84
|
+
console.log(`[prompt-store] scanned ${index.length} templates`);
|
|
85
|
+
}
|
|
86
|
+
scanPromptStore();
|
|
87
|
+
// Scan public/output-styles/ and generate index.json
|
|
88
|
+
function scanOutputStyleStore() {
|
|
89
|
+
const dir = join(publicDir, 'output-styles');
|
|
90
|
+
if (!existsSync(dir))
|
|
91
|
+
return;
|
|
92
|
+
const files = readdirSync(dir).filter((f) => f.endsWith('.md'));
|
|
93
|
+
const index = files.map((filename) => {
|
|
94
|
+
const id = basename(filename, '.md');
|
|
95
|
+
const content = readFileSync(join(dir, filename), 'utf-8');
|
|
96
|
+
const firstHeading = content.split('\n').find((l) => /^#\s+/.test(l));
|
|
97
|
+
const name = firstHeading ? firstHeading.replace(/^#\s+/, '').trim() : id.replace(/[-_]/g, ' ');
|
|
98
|
+
return { id, name, filename };
|
|
99
|
+
});
|
|
100
|
+
writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
|
|
101
|
+
console.log(`[output-style-store] scanned ${index.length} templates`);
|
|
102
|
+
}
|
|
103
|
+
scanOutputStyleStore();
|
|
104
|
+
// Scan public/skills/{group}/{skill-name}/SKILL.md and generate index.json
|
|
105
|
+
function scanSkillStore() {
|
|
106
|
+
const dir = join(publicDir, 'skills');
|
|
107
|
+
if (!existsSync(dir))
|
|
108
|
+
return;
|
|
109
|
+
const index = [];
|
|
110
|
+
for (const groupEntry of readdirSync(dir, { withFileTypes: true })) {
|
|
111
|
+
if (!groupEntry.isDirectory())
|
|
112
|
+
continue;
|
|
113
|
+
const group = groupEntry.name;
|
|
114
|
+
const groupDir = join(dir, group);
|
|
115
|
+
for (const skillEntry of readdirSync(groupDir, { withFileTypes: true })) {
|
|
116
|
+
if (!skillEntry.isDirectory())
|
|
117
|
+
continue;
|
|
118
|
+
const skillName = skillEntry.name;
|
|
119
|
+
const skillFile = join(groupDir, skillName, 'SKILL.md');
|
|
120
|
+
if (!existsSync(skillFile))
|
|
121
|
+
continue;
|
|
122
|
+
const content = readFileSync(skillFile, 'utf-8');
|
|
123
|
+
const fm = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
124
|
+
let name = skillName;
|
|
125
|
+
if (fm) {
|
|
126
|
+
const nameLine = fm[1].split(/\r?\n/).find((l) => /^\s*name\s*:/i.test(l));
|
|
127
|
+
if (nameLine)
|
|
128
|
+
name = nameLine.split(':', 2)[1].trim() || skillName;
|
|
129
|
+
}
|
|
130
|
+
index.push({ id: skillName, name, group, path: `${group}/${skillName}` });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
writeFileSync(join(dir, 'index.json'), JSON.stringify(index, null, 2), 'utf-8');
|
|
134
|
+
console.log(`[skill-store] scanned ${index.length} skills`);
|
|
135
|
+
}
|
|
136
|
+
scanSkillStore();
|
|
68
137
|
app.get('/api/health', (_req, res) => {
|
|
69
138
|
res.json({ status: 'ok', timestamp: new Date().toISOString(), platform: process.platform });
|
|
70
139
|
});
|
|
@@ -82,9 +151,7 @@ app.post('/api/upload/avatar', async (req, res) => {
|
|
|
82
151
|
return;
|
|
83
152
|
}
|
|
84
153
|
const [, mime, base64] = match;
|
|
85
|
-
const
|
|
86
|
-
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
87
|
-
const name = filename ? `${id}-${filename.replace(/[^a-zA-Z0-9._-]/g, '_')}` : `${id}.${ext}`;
|
|
154
|
+
const name = 'user.jpg';
|
|
88
155
|
const avatarsDir = join(publicDir, 'avatars');
|
|
89
156
|
if (!existsSync(avatarsDir))
|
|
90
157
|
mkdirSync(avatarsDir, { recursive: true });
|
|
@@ -113,6 +180,7 @@ app.use('/api/workspaces/:id/issues', issueRouter);
|
|
|
113
180
|
app.use('/api/workflows', workflowRouter);
|
|
114
181
|
app.use('/api/workspaces/:id/commands', commandRouter);
|
|
115
182
|
app.use('/api/workspaces/:id/code-favorites', codeFavoritesRouter);
|
|
183
|
+
app.use('/api/workspaces/:id/hooks', hooksRouter);
|
|
116
184
|
app.use('/api/workspaces/:id/agents', agentRouter);
|
|
117
185
|
app.use('/api/workspaces/:id/tasks', taskRouter);
|
|
118
186
|
app.use('/api/workspaces/:id/git', gitRouter);
|
|
@@ -144,6 +212,7 @@ app.use('/api', llmRouter);
|
|
|
144
212
|
app.use('/api/folder', folderRouter);
|
|
145
213
|
app.use('/api/skills', skillRouter);
|
|
146
214
|
app.use('/api/prompt-templates', promptTemplateRouter);
|
|
215
|
+
app.use('/api/output-styles', outputStyleRouter);
|
|
147
216
|
app.use('/api/mcps', mcpRouter);
|
|
148
217
|
app.use('/api/subscriptions', subscriptionRouter);
|
|
149
218
|
app.use('/api/speech-recognition', speechRecognitionRouter);
|
package/dist/package.json
CHANGED
package/dist/routes/agent-sse.js
CHANGED
|
@@ -5,6 +5,7 @@ import * as agentService from '../services/agent.js';
|
|
|
5
5
|
import * as workspaceService from '../services/workspace.js';
|
|
6
6
|
import { getThinkingRuntimeConfig } from '../services/llm-model-config.js';
|
|
7
7
|
import { buildAgentPrompt } from '../ws/agent-prompt.js';
|
|
8
|
+
import { wrapOnEventWithHooks } from '../services/hook-engine.js';
|
|
8
9
|
const router = Router();
|
|
9
10
|
router.post('/run', async (req, res) => {
|
|
10
11
|
const body = req.body;
|
|
@@ -78,11 +79,12 @@ router.post('/run', async (req, res) => {
|
|
|
78
79
|
skills,
|
|
79
80
|
configDir,
|
|
80
81
|
sandboxDirs: preset.sandboxDirs,
|
|
81
|
-
|
|
82
|
+
outputStyle: body.outputStyle ?? preset.outputStyle,
|
|
83
|
+
onEvent: wrapOnEventWithHooks((event) => {
|
|
82
84
|
if (event.type === 'output')
|
|
83
85
|
output.push(event.line);
|
|
84
86
|
writeSse(res, event.type, serializeRuntimeEvent(event));
|
|
85
|
-
},
|
|
87
|
+
}, workspaceId, workspace?.hooksEnabled),
|
|
86
88
|
});
|
|
87
89
|
completed = true;
|
|
88
90
|
const displayOutput = output.length ? output : result.output;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import * as store from '../storage/hook-store.js';
|
|
3
|
+
const router = Router({ mergeParams: true });
|
|
4
|
+
router.get('/', (req, res) => {
|
|
5
|
+
try {
|
|
6
|
+
res.json(store.listHooks(req.params.id));
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
res.status(500).json({ error: error.message });
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
router.get('/:name', (req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
const hook = store.getHook(req.params.id, req.params.name);
|
|
15
|
+
if (!hook) {
|
|
16
|
+
res.status(404).json({ error: 'Hook not found' });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
res.json(hook);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
res.status(500).json({ error: error.message });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
router.post('/', (req, res) => {
|
|
26
|
+
try {
|
|
27
|
+
const config = req.body;
|
|
28
|
+
if (!config.name) {
|
|
29
|
+
res.status(400).json({ error: 'name required' });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
store.saveHook(req.params.id, config);
|
|
33
|
+
res.status(201).json(config);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
res.status(400).json({ error: error.message });
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
router.put('/:name', (req, res) => {
|
|
40
|
+
try {
|
|
41
|
+
const config = req.body;
|
|
42
|
+
config.name = req.params.name;
|
|
43
|
+
store.saveHook(req.params.id, config);
|
|
44
|
+
res.json(config);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
res.status(400).json({ error: error.message });
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
router.delete('/:name', (req, res) => {
|
|
51
|
+
try {
|
|
52
|
+
store.deleteHook(req.params.id, req.params.name);
|
|
53
|
+
res.status(204).send();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
res.status(400).json({ error: error.message });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
router.post('/upload', (req, res) => {
|
|
60
|
+
try {
|
|
61
|
+
const { content } = req.body;
|
|
62
|
+
if (!content || typeof content !== 'string') {
|
|
63
|
+
res.status(400).json({ error: 'content (string) required' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const config = store.uploadHook(req.params.id, content);
|
|
67
|
+
res.status(201).json(config);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
res.status(400).json({ error: error.message });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
router.post('/:name/apply', (req, res) => {
|
|
74
|
+
try {
|
|
75
|
+
const { targetWorkspaceId } = req.body;
|
|
76
|
+
if (!targetWorkspaceId) {
|
|
77
|
+
res.status(400).json({ error: 'targetWorkspaceId required' });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
store.applyToWorkspace(req.params.id, req.params.name, targetWorkspaceId);
|
|
81
|
+
res.json({ ok: true });
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
res.status(400).json({ error: error.message });
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
export default router;
|
|
88
|
+
//# sourceMappingURL=hooks.js.map
|