@agent-spaces/server 0.3.3 → 0.3.5
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/claude-code-runtime/index.js +19 -1
- package/dist/adapters/codex-runtime.js +13 -3
- package/dist/agents/agent-message-parts.js +9 -1
- package/dist/agents/commit-agent.js +7 -15
- package/dist/app.js +37 -0
- package/dist/package.json +4 -1
- package/dist/routes/channel.js +18 -6
- package/dist/routes/code-favorites.js +60 -0
- package/dist/routes/file.js +15 -2
- package/dist/routes/inspector.js +14 -0
- package/dist/routes/issue.js +7 -0
- package/dist/routes/prompt-template.js +48 -0
- package/dist/services/agent.js +45 -3
- package/dist/services/channel.js +2 -0
- package/dist/services/code-favorites.js +23 -0
- package/dist/services/file.js +8 -0
- package/dist/services/inspector-history.js +53 -0
- package/dist/services/notification-hub/events.js +34 -1
- package/dist/services/persistent-agent-context.js +3 -2
- package/dist/services/prompt-template.js +93 -0
- package/dist/services/pty.js +24 -4
- package/dist/services/search.js +3 -5
- package/dist/storage/code-favorites-store.js +15 -0
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +4 -4
- package/dist/web/__next._full.txt +21 -21
- package/dist/web/__next._head.txt +4 -4
- package/dist/web/__next._index.txt +13 -13
- package/dist/web/__next._tree.txt +2 -2
- package/dist/web/_next/static/chunks/0-1pn22sg~67u.js +2 -0
- package/dist/web/_next/static/chunks/0-lseun2l1m_t.js +2 -0
- package/dist/web/_next/static/chunks/0-wkj-hzh444r.css +4 -0
- package/dist/web/_next/static/chunks/{0f6vrjsdauiwl.js → 0-~4vw4_9z_0_.js} +2 -2
- package/dist/web/_next/static/chunks/0..g0jl-8qup7.js +1 -0
- package/dist/web/_next/static/chunks/0.006.ycpe92w.js +496 -0
- package/dist/web/_next/static/chunks/0.6x8f.mb-1qf.js +1 -0
- package/dist/web/_next/static/chunks/{0qe5wvs8fe9ip.js → 004wt62de8617.js} +1 -1
- package/dist/web/_next/static/chunks/016xz2o-hv3am.js +1 -0
- package/dist/web/_next/static/chunks/01gi~q0c6ez6..js +1 -0
- package/dist/web/_next/static/chunks/023lpc7n70tav.css +1 -0
- package/dist/web/_next/static/chunks/03me5_ir..2ix.js +1 -0
- package/dist/web/_next/static/chunks/04fk~8rnrvs44.js +1 -0
- package/dist/web/_next/static/chunks/05eu2fdixf7c9.js +1 -0
- package/dist/web/_next/static/chunks/05gt_g_vbzh-5.css +1 -0
- package/dist/web/_next/static/chunks/06vadtvw631k5.css +1 -0
- package/dist/web/_next/static/chunks/07ge_85i__6pb.js +1 -0
- package/dist/web/_next/static/chunks/07ne4g8zopykv.js +1 -0
- package/dist/web/_next/static/chunks/07xvadmf~8bow.js +1 -0
- package/dist/web/_next/static/chunks/08.u~dmq20cak.css +23 -0
- package/dist/web/_next/static/chunks/08ag2f8y6f8cr.js +1 -0
- package/dist/web/_next/static/chunks/{03sd~wmqw.9gc.js → 08kpa0nox.bb1.js} +2 -2
- package/dist/web/_next/static/chunks/08o-zmr-40r5g.js +1 -0
- package/dist/web/_next/static/chunks/0_-c.y2qq4ax4.js +270 -0
- package/dist/web/_next/static/chunks/0a1rewz7xr-xi.js +1 -0
- package/dist/web/_next/static/chunks/0amcocbojo4v2.js +1 -0
- package/dist/web/_next/static/chunks/0brrgp3ki5w4_.css +17 -0
- package/dist/web/_next/static/chunks/0bzmgi.ynrn.0.css +3 -0
- package/dist/web/_next/static/chunks/0c_vfzf1z7-rt.js +2 -0
- package/dist/web/_next/static/chunks/0cjmfclopcxho.css +1 -0
- package/dist/web/_next/static/chunks/0cs830n97dgjy.js +1 -0
- package/dist/web/_next/static/chunks/0d_dp_4ofz0l3.css +3 -0
- package/dist/web/_next/static/chunks/0dws-faof-ryx.css +13 -0
- package/dist/web/_next/static/chunks/0ejc_zlyocy_r.css +1 -0
- package/dist/web/_next/static/chunks/0esty_4gmxfq3.js +1 -0
- package/dist/web/_next/static/chunks/0evjw7bao5_e~.js +1 -0
- package/dist/web/_next/static/chunks/{0ag4p6m9rze~n.js → 0g-0n6glz_z6w.js} +1 -1
- package/dist/web/_next/static/chunks/{145qu5b0tgm9w.js → 0gig.k.rq8d0x.js} +1 -1
- package/dist/web/_next/static/chunks/0hl_7y464qll6.css +2 -0
- package/dist/web/_next/static/chunks/0hrbuvzuxrjfl.js +1 -0
- package/dist/web/_next/static/chunks/0i_3.3rdsu2mw.js +2 -0
- package/dist/web/_next/static/chunks/0i_gi.kq2dau8.css +1 -0
- package/dist/web/_next/static/chunks/0j00r2f_n-.lx.js +1 -0
- package/dist/web/_next/static/chunks/0jh9xnkimjkyh.js +1 -0
- package/dist/web/_next/static/chunks/0jokpgh485~28.js +167 -0
- package/dist/web/_next/static/chunks/0kvsjgpj7zcb9.css +9 -0
- package/dist/web/_next/static/chunks/0l5ab99s37x5f.js +1 -0
- package/dist/web/_next/static/chunks/0lcc9r.o.p.sc.js +1 -0
- package/dist/web/_next/static/chunks/0lh~x2tf~i1hd.css +2 -0
- package/dist/web/_next/static/chunks/0me8ho8j4tq7_.css +2 -0
- package/dist/web/_next/static/chunks/0mny8i81aenx3.js +1 -0
- package/dist/web/_next/static/chunks/0mt-7av8yrg0o.css +3 -0
- package/dist/web/_next/static/chunks/0njy89g5coeyi.js +60 -0
- package/dist/web/_next/static/chunks/0nsu~f3voe~0i.js +5 -0
- package/dist/web/_next/static/chunks/0ow~co9wcleka.js +173 -0
- package/dist/web/_next/static/chunks/0pldvk5_h__t7.css +3 -0
- package/dist/web/_next/static/chunks/0qad.lgvtlt0b.css +16 -0
- package/dist/web/_next/static/chunks/0qpq0~_58fe9a.js +18 -0
- package/dist/web/_next/static/chunks/{0.335m_d-cd_g.js → 0qtc_rbo1oghu.js} +1 -1
- package/dist/web/_next/static/chunks/0qz5~3wquy~3q.css +2 -0
- package/dist/web/_next/static/chunks/0rv0nj__24y60.js +10 -0
- package/dist/web/_next/static/chunks/{145gbwitjxamg.js → 0sz8_nijfiz0p.js} +1 -1
- package/dist/web/_next/static/chunks/0tvd~rxgf0oh_.js +1 -0
- package/dist/web/_next/static/chunks/0wv0h27jafag4.js +1 -0
- package/dist/web/_next/static/chunks/0wwvc4zc2q6bn.js +1 -0
- package/dist/web/_next/static/chunks/0x4b-a2ixww6m.js +1 -0
- package/dist/web/_next/static/chunks/0z8ipjj2z-3al.css +8 -0
- package/dist/web/_next/static/chunks/0zd1o3u04~qvo.js +127 -0
- package/dist/web/_next/static/chunks/0~2l1-8o4delc.js +1 -0
- package/dist/web/_next/static/chunks/0~w6ugk9s5p-h.css +1 -0
- package/dist/web/_next/static/chunks/10jfi.9fw5g48.js +1 -0
- package/dist/web/_next/static/chunks/11_tltlhc8.sj.js +1 -0
- package/dist/web/_next/static/chunks/125nunjfj2fj0.js +1 -0
- package/dist/web/_next/static/chunks/12md9ajfx2o85.css +1 -0
- package/dist/web/_next/static/chunks/12odetnu-lyrr.js +167 -0
- package/dist/web/_next/static/chunks/12u4g4uzrlten.js +2 -0
- package/dist/web/_next/static/chunks/134ozsnbd~0qw.js +1 -0
- package/dist/web/_next/static/chunks/13ess~4pdmxma.js +1 -0
- package/dist/web/_next/static/chunks/13xfagjq0q~tf.js +1 -0
- package/dist/web/_next/static/chunks/143.pbs8a1ivm.js +1 -0
- package/dist/web/_next/static/chunks/14_y_s_5rhsd1.css +5 -0
- package/dist/web/_next/static/chunks/15hca2.5le07..js +3 -0
- package/dist/web/_next/static/chunks/15rf3~h7sugz4.css +19 -0
- package/dist/web/_next/static/chunks/16i87txo0qh0h.css +6 -0
- package/dist/web/_next/static/chunks/16~udgv7eel6a.css +2 -0
- package/dist/web/_next/static/chunks/{turbopack-0-j2hpomozegf.js → turbopack-000x5q9w-wx10.js} +1 -1
- package/dist/web/_next/static/chunks/{turbopack-0rrhp9pbrv0p3.js → turbopack-0hrx111grzq49.js} +1 -1
- package/dist/web/_next/static/chunks/{turbopack-0_zn00zg5kmqz.js → turbopack-0w-kua.9ymd0x.js} +1 -1
- package/dist/web/_next/static/chunks/{turbopack-0l~pq1hytx49z.js → turbopack-15zqm_4ixj.18.js} +1 -1
- package/dist/web/_next/static/media/code-icon.0g3wskzlr7oxf.svg +1 -0
- package/dist/web/_next/static/media/codicon.0pqe-t5rtghj8.ttf +0 -0
- package/dist/web/_next/static/media/continue-tb.0qei4mru4tzd2.png +0 -0
- package/dist/web/_next/static/media/dark_modern.09.uq6bp373zs.json +1 -0
- package/dist/web/_next/static/media/dark_plus.187umr0~d1_r7.json +1 -0
- package/dist/web/_next/static/media/dark_vs.12ju8ocr7rg--.json +1 -0
- package/dist/web/_next/static/media/document-dark.0vvlbsi_fdy~4.svg +3 -0
- package/dist/web/_next/static/media/document-light.0bfi_yt9e~vk7.svg +3 -0
- package/dist/web/_next/static/media/editor.worker.0ffjdaaj15t6e.js +1 -0
- package/dist/web/_next/static/media/extensionHost.worker.14sz5xf8-1efr.js +2 -0
- package/dist/web/_next/static/media/fake.16yx0-xxqj4pc.html +10 -0
- package/dist/web/_next/static/media/folder-dark.02kdicw3013tb.svg +3 -0
- package/dist/web/_next/static/media/folder-light.0s165k4fp3.53.svg +3 -0
- package/dist/web/_next/static/media/folder-open-dark.0sk6.yh45uqs3.svg +4 -0
- package/dist/web/_next/static/media/folder-open-light.10k1v_ugaq8ic.svg +4 -0
- package/dist/web/_next/static/media/hc_black.0-ul9e2oc5twb.json +1 -0
- package/dist/web/_next/static/media/hc_light.0vi.a7fr.z4gy.json +1 -0
- package/dist/web/_next/static/media/index.0jmafs_mwcjgg.html +1341 -0
- package/dist/web/_next/static/media/keyboard-dark.0t86n~1rrhj2-.svg +10 -0
- package/dist/web/_next/static/media/keyboard-light.0abw0ukjcd9ox.svg +10 -0
- package/dist/web/_next/static/media/letterpress-dark.181s2xkw~lfyo.svg +3 -0
- package/dist/web/_next/static/media/letterpress-hcDark.0ftfw8fess-5y.svg +3 -0
- package/dist/web/_next/static/media/letterpress-hcLight.06x23d0.aixf_.svg +3 -0
- package/dist/web/_next/static/media/letterpress-light.0xb1bapis~iw7.svg +3 -0
- package/dist/web/_next/static/media/light_modern.00ps-apoc9ph7.json +1 -0
- package/dist/web/_next/static/media/light_plus.0ow37ouyuazdz.json +1 -0
- package/dist/web/_next/static/media/light_vs.0fdbve5sxkgq1.json +1 -0
- package/dist/web/_next/static/media/onig.0dk~55st~1x8..wasm +0 -0
- package/dist/web/_next/static/media/opacity-background.0-9.t0ta0ko23.png +0 -0
- package/dist/web/_next/static/media/package.0_p8a~hpmb_uj.json +1 -0
- package/dist/web/_next/static/media/package.nls.0e5hn-g497b64.json +1 -0
- package/dist/web/_next/static/media/pause-tb.0ttrm1r1uuz_c.png +0 -0
- package/dist/web/_next/static/media/restart-tb.086872s_sc2qv.png +0 -0
- package/dist/web/_next/static/media/root-folder-dark.14iwnfb7p2na~.svg +5 -0
- package/dist/web/_next/static/media/root-folder-light.0ljk9fi7sw3.2.svg +5 -0
- package/dist/web/_next/static/media/root-folder-open-dark.08vw3g9zvki33.svg +5 -0
- package/dist/web/_next/static/media/root-folder-open-light.0f46.ahns5c~..svg +5 -0
- package/dist/web/_next/static/media/run-with-debugging-tb.0j1h52k~h~72z.png +0 -0
- package/dist/web/_next/static/media/service-worker.0_udu6mraxn4k.js +543 -0
- package/dist/web/_next/static/media/stepinto-tb.0cl87yt4ub_j8.png +0 -0
- package/dist/web/_next/static/media/stepout-tb.0vjib_bn-_xax.png +0 -0
- package/dist/web/_next/static/media/stepover-tb.04beeu~7cxr4l.png +0 -0
- package/dist/web/_next/static/media/stop-tb.1498tmu97_y9j.png +0 -0
- package/dist/web/_next/static/media/vs_minimal-icon-theme.0-qs73lvw4voi.json +1 -0
- package/dist/web/_next/static/media/webWorkerExtensionHostIframe.0x2r1o97s.m0m.html +156 -0
- package/dist/web/_next/static/media/worker.081j0x4avp1l1.js +2 -0
- package/dist/web/_not-found/__next._full.txt +19 -19
- package/dist/web/_not-found/__next._head.txt +4 -4
- package/dist/web/_not-found/__next._index.txt +13 -13
- package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/dist/web/_not-found/__next._not-found.txt +3 -3
- package/dist/web/_not-found/__next._tree.txt +2 -2
- package/dist/web/_not-found.html +1 -1
- package/dist/web/_not-found.txt +19 -19
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +21 -21
- package/dist/web/login/__next._full.txt +21 -21
- package/dist/web/login/__next._head.txt +4 -4
- package/dist/web/login/__next._index.txt +13 -13
- package/dist/web/login/__next._tree.txt +2 -2
- package/dist/web/login/__next.login.__PAGE__.txt +4 -4
- package/dist/web/login/__next.login.txt +3 -3
- package/dist/web/login.html +1 -1
- package/dist/web/login.txt +21 -21
- package/dist/web/settings/__next._full.txt +23 -23
- package/dist/web/settings/__next._head.txt +4 -4
- package/dist/web/settings/__next._index.txt +13 -13
- package/dist/web/settings/__next._tree.txt +2 -2
- package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
- package/dist/web/settings/__next.settings.txt +5 -5
- package/dist/web/settings/agents/__next._full.txt +23 -23
- package/dist/web/settings/agents/__next._head.txt +4 -4
- package/dist/web/settings/agents/__next._index.txt +13 -13
- package/dist/web/settings/agents/__next._tree.txt +2 -2
- package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
- package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
- package/dist/web/settings/agents/__next.settings.txt +5 -5
- package/dist/web/settings/agents.html +1 -1
- package/dist/web/settings/agents.txt +23 -23
- package/dist/web/settings/mcps/__next._full.txt +23 -23
- package/dist/web/settings/mcps/__next._head.txt +4 -4
- package/dist/web/settings/mcps/__next._index.txt +13 -13
- package/dist/web/settings/mcps/__next._tree.txt +2 -2
- package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
- package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
- package/dist/web/settings/mcps/__next.settings.txt +5 -5
- package/dist/web/settings/mcps.html +1 -1
- package/dist/web/settings/mcps.txt +23 -23
- package/dist/web/settings/models/__next._full.txt +23 -23
- package/dist/web/settings/models/__next._head.txt +4 -4
- package/dist/web/settings/models/__next._index.txt +13 -13
- package/dist/web/settings/models/__next._tree.txt +2 -2
- package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
- package/dist/web/settings/models/__next.settings.models.txt +3 -3
- package/dist/web/settings/models/__next.settings.txt +5 -5
- package/dist/web/settings/models.html +1 -1
- package/dist/web/settings/models.txt +23 -23
- package/dist/web/settings/prompts/__next._full.txt +42 -0
- package/dist/web/settings/prompts/__next._head.txt +6 -0
- package/dist/web/settings/prompts/__next._index.txt +15 -0
- package/dist/web/settings/prompts/__next._tree.txt +8 -0
- package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +9 -0
- package/dist/web/settings/prompts/__next.settings.prompts.txt +5 -0
- package/dist/web/settings/prompts/__next.settings.txt +7 -0
- package/dist/web/settings/prompts.html +1 -0
- package/dist/web/settings/prompts.txt +42 -0
- package/dist/web/settings/providers/__next._full.txt +23 -23
- package/dist/web/settings/providers/__next._head.txt +4 -4
- package/dist/web/settings/providers/__next._index.txt +13 -13
- package/dist/web/settings/providers/__next._tree.txt +2 -2
- package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
- package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
- package/dist/web/settings/providers/__next.settings.txt +5 -5
- package/dist/web/settings/providers.html +1 -1
- package/dist/web/settings/providers.txt +23 -23
- package/dist/web/settings/skills/__next._full.txt +23 -23
- package/dist/web/settings/skills/__next._head.txt +4 -4
- package/dist/web/settings/skills/__next._index.txt +13 -13
- package/dist/web/settings/skills/__next._tree.txt +2 -2
- package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
- package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
- package/dist/web/settings/skills/__next.settings.txt +5 -5
- package/dist/web/settings/skills.html +1 -1
- package/dist/web/settings/skills.txt +23 -23
- package/dist/web/settings.html +1 -1
- package/dist/web/settings.txt +23 -23
- package/dist/web/workflows/__next._full.txt +21 -21
- 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 +21 -21
- package/dist/web/workspace/_/__next._full.txt +68 -35
- 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 +15 -3
- package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +16 -4
- 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 +68 -35
- package/dist/web/workspaces/__next._full.txt +21 -21
- package/dist/web/workspaces/__next._head.txt +4 -4
- package/dist/web/workspaces/__next._index.txt +13 -13
- package/dist/web/workspaces/__next._tree.txt +2 -2
- package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
- package/dist/web/workspaces/__next.workspaces.txt +3 -3
- package/dist/web/workspaces.html +1 -1
- package/dist/web/workspaces.txt +21 -21
- package/dist/ws/agent-runner.js +159 -20
- package/dist/ws/connection-manager.js +13 -0
- package/dist/ws/handler.js +9 -12
- package/dist/ws/message-parts.js +20 -1
- package/dist/ws/terminal-handler.js +28 -7
- package/dist/ws/typescript-lsp.js +78 -0
- package/package.json +5 -1
- package/dist/web/_next/static/chunks/0-a17~4piefz_.js +0 -1
- package/dist/web/_next/static/chunks/0anuxr11yn5iv.js +0 -2
- package/dist/web/_next/static/chunks/0cwvdk55mrt_9.css +0 -1
- package/dist/web/_next/static/chunks/0e.z4v3cd78dx.js +0 -1
- package/dist/web/_next/static/chunks/0egot8y~i-ge3.js +0 -1
- package/dist/web/_next/static/chunks/0gczc8mmde5my.js +0 -1
- package/dist/web/_next/static/chunks/0gtbd3yt7y1gx.js +0 -1
- package/dist/web/_next/static/chunks/0j2w71psq6w9u.js +0 -1
- package/dist/web/_next/static/chunks/0kyv5yika-41a.js +0 -1
- package/dist/web/_next/static/chunks/0lmeh15xwcj0s.js +0 -204
- package/dist/web/_next/static/chunks/0plreh4_gkxf9.js +0 -1
- package/dist/web/_next/static/chunks/0puhc.l_.mc99.js +0 -1
- package/dist/web/_next/static/chunks/0qxk21zejhdbm.js +0 -1
- package/dist/web/_next/static/chunks/0v7nmghv8ieef.js +0 -1
- package/dist/web/_next/static/chunks/0wekj7h15h7z7.js +0 -5
- package/dist/web/_next/static/chunks/14iaqoj9-09g..js +0 -2
- package/dist/web/_next/static/chunks/17oc2l.ekcs8b.css +0 -1
- /package/dist/web/_next/static/{gN3O86ki0NGTvGTqE2Ibh → Pf6ZjtN82szw-ZzU9lITd}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{gN3O86ki0NGTvGTqE2Ibh → Pf6ZjtN82szw-ZzU9lITd}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{gN3O86ki0NGTvGTqE2Ibh → Pf6ZjtN82szw-ZzU9lITd}/_ssgManifest.js +0 -0
|
@@ -54,6 +54,7 @@ export class ClaudeCodeRuntime {
|
|
|
54
54
|
additionalDirectories,
|
|
55
55
|
permissionMode,
|
|
56
56
|
allowDangerouslySkipPermissions: permissionMode === 'bypassPermissions' ? true : undefined,
|
|
57
|
+
resume: options?.resumeSessionId,
|
|
57
58
|
abortController: this.abortController,
|
|
58
59
|
env: buildEnv(this.config, configDir, { baseURL, apiKey }),
|
|
59
60
|
stderr: (data) => {
|
|
@@ -72,10 +73,16 @@ export class ClaudeCodeRuntime {
|
|
|
72
73
|
let usageLine = null;
|
|
73
74
|
let usage;
|
|
74
75
|
let costUsd;
|
|
76
|
+
let sessionId = options?.resumeSessionId;
|
|
75
77
|
let sawResult = false;
|
|
76
78
|
const pendingAskUserQuestionToolIds = new Set();
|
|
77
79
|
let waitingForUserAnswer = false;
|
|
78
80
|
for await (const message of this.activeQuery) {
|
|
81
|
+
const nextSessionId = readSessionId(message);
|
|
82
|
+
if (nextSessionId && nextSessionId !== sessionId) {
|
|
83
|
+
sessionId = nextSessionId;
|
|
84
|
+
options?.onEvent?.({ type: 'session', sessionId });
|
|
85
|
+
}
|
|
79
86
|
const toolUses = extractToolUseEvents(message);
|
|
80
87
|
for (const toolUse of toolUses) {
|
|
81
88
|
if (toolUse.name === 'AskUserQuestion') {
|
|
@@ -116,6 +123,7 @@ export class ClaudeCodeRuntime {
|
|
|
116
123
|
usageLine = formatUsageLine(message.usage);
|
|
117
124
|
usage = normalizeUsage(message.usage);
|
|
118
125
|
costUsd = readTotalCostUsd(message);
|
|
126
|
+
sessionId = readSessionId(message) ?? sessionId;
|
|
119
127
|
if (message.subtype === 'success') {
|
|
120
128
|
if (!isAskUserQuestionAutoResult(message.result)) {
|
|
121
129
|
resultText = message.result;
|
|
@@ -141,6 +149,7 @@ export class ClaudeCodeRuntime {
|
|
|
141
149
|
output,
|
|
142
150
|
usage,
|
|
143
151
|
costUsd,
|
|
152
|
+
sessionId,
|
|
144
153
|
};
|
|
145
154
|
}
|
|
146
155
|
if (waitingForUserAnswer && (!error || isAskUserQuestionAutoResult(error))) {
|
|
@@ -154,6 +163,7 @@ export class ClaudeCodeRuntime {
|
|
|
154
163
|
output,
|
|
155
164
|
usage,
|
|
156
165
|
costUsd,
|
|
166
|
+
sessionId,
|
|
157
167
|
};
|
|
158
168
|
}
|
|
159
169
|
if (error) {
|
|
@@ -170,6 +180,7 @@ export class ClaudeCodeRuntime {
|
|
|
170
180
|
output,
|
|
171
181
|
usage,
|
|
172
182
|
costUsd,
|
|
183
|
+
sessionId,
|
|
173
184
|
};
|
|
174
185
|
}
|
|
175
186
|
const text = resultText || output.at(-1) || '';
|
|
@@ -187,6 +198,7 @@ export class ClaudeCodeRuntime {
|
|
|
187
198
|
output: finalOutput,
|
|
188
199
|
usage,
|
|
189
200
|
costUsd,
|
|
201
|
+
sessionId,
|
|
190
202
|
};
|
|
191
203
|
}
|
|
192
204
|
catch (err) {
|
|
@@ -198,7 +210,7 @@ export class ClaudeCodeRuntime {
|
|
|
198
210
|
console.error(err.stack);
|
|
199
211
|
appendUnique(output, stderrLines);
|
|
200
212
|
appendUnique(output, [runtimeError]);
|
|
201
|
-
return { success: false, summary: 'Claude Code execution failed', artifacts: [], error: runtimeError, output };
|
|
213
|
+
return { success: false, summary: 'Claude Code execution failed', artifacts: [], error: runtimeError, output, sessionId: options?.resumeSessionId };
|
|
202
214
|
}
|
|
203
215
|
finally {
|
|
204
216
|
this.activeQuery?.close();
|
|
@@ -215,6 +227,12 @@ export class ClaudeCodeRuntime {
|
|
|
215
227
|
});
|
|
216
228
|
}
|
|
217
229
|
}
|
|
230
|
+
function readSessionId(message) {
|
|
231
|
+
if (!message || typeof message !== 'object')
|
|
232
|
+
return undefined;
|
|
233
|
+
const value = message.session_id;
|
|
234
|
+
return typeof value === 'string' && value.trim() ? value : undefined;
|
|
235
|
+
}
|
|
218
236
|
function readTotalCostUsd(message) {
|
|
219
237
|
if (!message || typeof message !== 'object')
|
|
220
238
|
return undefined;
|
|
@@ -35,7 +35,7 @@ export class CodexRuntime {
|
|
|
35
35
|
config: configOverrides,
|
|
36
36
|
env: buildEnv(this.config, codexHome),
|
|
37
37
|
});
|
|
38
|
-
const
|
|
38
|
+
const threadOptions = {
|
|
39
39
|
model: this.config.model,
|
|
40
40
|
sandboxMode,
|
|
41
41
|
approvalPolicy,
|
|
@@ -44,7 +44,10 @@ export class CodexRuntime {
|
|
|
44
44
|
additionalDirectories: options?.sandboxDirs,
|
|
45
45
|
networkAccessEnabled: true,
|
|
46
46
|
webSearchMode: 'live',
|
|
47
|
-
}
|
|
47
|
+
};
|
|
48
|
+
const thread = options?.resumeSessionId
|
|
49
|
+
? codex.resumeThread(options.resumeSessionId, threadOptions)
|
|
50
|
+
: codex.startThread(threadOptions);
|
|
48
51
|
const { events } = await thread.runStreamed(prompt, {
|
|
49
52
|
signal: this.abortController.signal,
|
|
50
53
|
});
|
|
@@ -52,8 +55,13 @@ export class CodexRuntime {
|
|
|
52
55
|
let tokenCount = 0;
|
|
53
56
|
let usage;
|
|
54
57
|
let error;
|
|
58
|
+
let sessionId = options?.resumeSessionId ?? thread.id ?? undefined;
|
|
55
59
|
const emittedItemLines = new Set();
|
|
56
60
|
for await (const event of events) {
|
|
61
|
+
if (event.type === 'thread.started') {
|
|
62
|
+
sessionId = event.thread_id;
|
|
63
|
+
options?.onEvent?.({ type: 'session', sessionId });
|
|
64
|
+
}
|
|
57
65
|
logEventDebug(event, d);
|
|
58
66
|
const mappedEvents = mapRuntimeEvents(event);
|
|
59
67
|
const mappedEventLines = new Set(mappedEvents.flatMap((runtimeEvent) => (runtimeEvent.type === 'tool_use' ? [runtimeEvent.line] : [])));
|
|
@@ -95,6 +103,7 @@ export class CodexRuntime {
|
|
|
95
103
|
artifacts: [],
|
|
96
104
|
error,
|
|
97
105
|
output,
|
|
106
|
+
sessionId,
|
|
98
107
|
usage,
|
|
99
108
|
};
|
|
100
109
|
}
|
|
@@ -105,6 +114,7 @@ export class CodexRuntime {
|
|
|
105
114
|
summary: summarizeResult(text),
|
|
106
115
|
artifacts: [],
|
|
107
116
|
output,
|
|
117
|
+
sessionId,
|
|
108
118
|
usage,
|
|
109
119
|
};
|
|
110
120
|
}
|
|
@@ -114,7 +124,7 @@ export class CodexRuntime {
|
|
|
114
124
|
d(`failed ${elapsed}ms | ${message}`);
|
|
115
125
|
if (err instanceof Error && err.stack)
|
|
116
126
|
console.error(err.stack);
|
|
117
|
-
return { success: false, summary: 'Codex execution failed', artifacts: [], error: message, output };
|
|
127
|
+
return { success: false, summary: 'Codex execution failed', artifacts: [], error: message, output, sessionId: options?.resumeSessionId };
|
|
118
128
|
}
|
|
119
129
|
finally {
|
|
120
130
|
this.abortController = null;
|
|
@@ -41,6 +41,8 @@ export function createAgentMessagePartsTracker(input) {
|
|
|
41
41
|
}
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
+
if (event.type === 'session')
|
|
45
|
+
return;
|
|
44
46
|
output.push(event.line);
|
|
45
47
|
input.onOutput?.(event.line);
|
|
46
48
|
},
|
|
@@ -432,11 +434,17 @@ function isToolLikeLine(line) {
|
|
|
432
434
|
return /^(Using|Tool:|Read|Write|Edit|MultiEdit|Bash|Search|Grep|Glob|Todo|Task|Web|Fetch|Claude Code initialized|Codex initialized|.+ running \(\d+s\))/i.test(line.trim());
|
|
433
435
|
}
|
|
434
436
|
function isIgnorableToolProgressLine(line) {
|
|
435
|
-
const
|
|
437
|
+
const raw = line.trim();
|
|
438
|
+
const trimmed = stripSubagentProgressPrefix(raw);
|
|
439
|
+
const isSubagentProgress = trimmed !== raw;
|
|
436
440
|
return /^Claude$/i.test(trimmed)
|
|
437
441
|
|| /^(Reading|Searching)(\.{1,3}|…)?$/i.test(trimmed)
|
|
442
|
+
|| (isSubagentProgress && /^(Reading|Searching)\s+\S.+$/i.test(trimmed))
|
|
438
443
|
|| /^(Read|Search|Grep|Glob|SemanticSearch|WebSearch)\s+running\s+\(\d+s\)$/i.test(trimmed);
|
|
439
444
|
}
|
|
445
|
+
function stripSubagentProgressPrefix(line) {
|
|
446
|
+
return line.replace(/^\[[^\]]+\]\s+subagent progress\s+\|\s*/i, '');
|
|
447
|
+
}
|
|
440
448
|
function isFinalAnswerLine(line) {
|
|
441
449
|
return !isToolLikeLine(line) && !/^(\[.*\]|Agent runtime configuration:|Conversation history:)/.test(line.trim());
|
|
442
450
|
}
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import * as agentService from '../services/agent.js';
|
|
2
|
+
import { AGENT_COMMIT_PRESET_ID, getDefaultCommitAgentPreset } from '../services/agent.js';
|
|
2
3
|
import { createAgentRuntime } from '../adapters/agent-runtime.js';
|
|
3
4
|
import { getWorkspace } from '../storage/workspace-store.js';
|
|
4
5
|
import { getThinkingRuntimeConfig } from '../services/llm-model-config.js';
|
|
5
6
|
import { prependPersistentAgentContext } from '../services/persistent-agent-context.js';
|
|
6
7
|
import { simpleGit } from 'simple-git';
|
|
7
|
-
const DEFAULT_SYSTEM_PROMPT =
|
|
8
|
-
'You are a git commit message generator.',
|
|
9
|
-
'Return exactly one concise commit message for the provided git diff.',
|
|
10
|
-
'Use conventional format: type: description.',
|
|
11
|
-
'Allowed types: feat, fix, docs, style, refactor, perf, test, chore.',
|
|
12
|
-
'Keep the subject under 72 characters.',
|
|
13
|
-
'If a body is needed, add one blank line and at most 3 short bullet lines.',
|
|
14
|
-
'Do not greet, explain, ask questions, provide options, use markdown, or wrap in code fences.',
|
|
15
|
-
'Output only the final commit message text.',
|
|
16
|
-
].join(' ');
|
|
8
|
+
const DEFAULT_SYSTEM_PROMPT = 'You are a git commit message generator. Return exactly one concise commit message for the provided git diff. Use conventional format: type: description. Allowed types: feat, fix, docs, style, refactor, perf, test, chore. Keep the subject under 72 characters. If a body is needed, add one blank line and at most 3 short bullet lines. Do not greet, explain, ask questions, provide options, use markdown, or wrap in code fences. Output only the final commit message text.';
|
|
17
9
|
export async function runCommitAgent(workspaceId) {
|
|
18
10
|
const ws = getWorkspace(workspaceId);
|
|
19
11
|
if (!ws)
|
|
@@ -22,8 +14,6 @@ export async function runCommitAgent(workspaceId) {
|
|
|
22
14
|
if (!diff.trim())
|
|
23
15
|
throw new Error('No changes found');
|
|
24
16
|
const commitAgent = findCommitAgent(workspaceId);
|
|
25
|
-
if (!commitAgent)
|
|
26
|
-
throw new Error('No commit agent configured. Add a commit-type agent preset.');
|
|
27
17
|
const session = agentService.getOrCreateSessionForConfig(workspaceId, commitAgent);
|
|
28
18
|
agentService.updateStatus(workspaceId, session.id, 'active');
|
|
29
19
|
const runtime = createAgentRuntime({
|
|
@@ -199,9 +189,11 @@ function inferType(subject) {
|
|
|
199
189
|
}
|
|
200
190
|
function findCommitAgent(workspaceId) {
|
|
201
191
|
const presets = agentService.listPresets(workspaceId);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
192
|
+
const preset = presets?.find((a) => a.id === AGENT_COMMIT_PRESET_ID);
|
|
193
|
+
if (preset)
|
|
194
|
+
return preset;
|
|
195
|
+
const template = agentService.readAgentTemplate(AGENT_COMMIT_PRESET_ID);
|
|
196
|
+
return template ?? getDefaultCommitAgentPreset();
|
|
205
197
|
}
|
|
206
198
|
async function collectDiff(ws) {
|
|
207
199
|
const git = simpleGit(ws.boundDirs[0]);
|
package/dist/app.js
CHANGED
|
@@ -21,7 +21,9 @@ import llmRouter from './routes/llm.js';
|
|
|
21
21
|
import authRouter from './routes/auth.js';
|
|
22
22
|
import folderRouter from './routes/folder.js';
|
|
23
23
|
import commandRouter from './routes/command.js';
|
|
24
|
+
import codeFavoritesRouter from './routes/code-favorites.js';
|
|
24
25
|
import skillRouter from './routes/skill.js';
|
|
26
|
+
import promptTemplateRouter from './routes/prompt-template.js';
|
|
25
27
|
import mcpRouter from './routes/mcp.js';
|
|
26
28
|
import subscriptionRouter from './routes/subscription.js';
|
|
27
29
|
import agentSseRouter from './routes/agent-sse.js';
|
|
@@ -31,6 +33,8 @@ import speechRecognitionRouter, { handleSpeechStream } from './routes/speech-rec
|
|
|
31
33
|
import { getUserSettings, setUserAvatarUrl, removeUserAvatarUrl } from './storage/user-settings-store.js';
|
|
32
34
|
import { authMiddleware, verifyToken } from './middleware/auth.js';
|
|
33
35
|
import { handleConnection } from './ws/handler.js';
|
|
36
|
+
import { handleTypeScriptLspConnection } from './ws/typescript-lsp.js';
|
|
37
|
+
import { broadcastToAll } from './ws/connection-manager.js';
|
|
34
38
|
import { startScheduler, stopScheduler } from './agents/scheduler-agent.js';
|
|
35
39
|
import { recoverRunningWorkOnStartup } from './services/issue-retry.js';
|
|
36
40
|
import { startPersistedNotificationServices } from './services/notification-hub/index.js';
|
|
@@ -47,6 +51,16 @@ const CORS_ORIGIN = process.env.CORS_ORIGIN || '*';
|
|
|
47
51
|
app.use(cors({ origin: CORS_ORIGIN }));
|
|
48
52
|
app.use(express.json({ limit: '50mb' }));
|
|
49
53
|
app.use('/api/agent-sse', agentSseRouter);
|
|
54
|
+
// Inspector track endpoint (no auth - called by dom-inspector-hook from external apps)
|
|
55
|
+
app.post('/api/inspector/track', (req, res) => {
|
|
56
|
+
const { path, name, line, column, timestamp } = req.body;
|
|
57
|
+
if (!path || line == null) {
|
|
58
|
+
res.status(400).json({ error: 'path and line are required' });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
broadcastToAll('inspector.jump', { path, name, line, column: column ?? 1, timestamp });
|
|
62
|
+
res.json({ ok: true });
|
|
63
|
+
});
|
|
50
64
|
app.use('/api', authMiddleware);
|
|
51
65
|
// Serve static files from public/
|
|
52
66
|
const publicDir = resolveRuntimeDir('public');
|
|
@@ -98,6 +112,7 @@ app.use('/api/workspaces/:id/channels', channelRouter);
|
|
|
98
112
|
app.use('/api/workspaces/:id/issues', issueRouter);
|
|
99
113
|
app.use('/api/workflows', workflowRouter);
|
|
100
114
|
app.use('/api/workspaces/:id/commands', commandRouter);
|
|
115
|
+
app.use('/api/workspaces/:id/code-favorites', codeFavoritesRouter);
|
|
101
116
|
app.use('/api/workspaces/:id/agents', agentRouter);
|
|
102
117
|
app.use('/api/workspaces/:id/tasks', taskRouter);
|
|
103
118
|
app.use('/api/workspaces/:id/git', gitRouter);
|
|
@@ -128,6 +143,7 @@ app.use('/api/agents', agentRouter);
|
|
|
128
143
|
app.use('/api', llmRouter);
|
|
129
144
|
app.use('/api/folder', folderRouter);
|
|
130
145
|
app.use('/api/skills', skillRouter);
|
|
146
|
+
app.use('/api/prompt-templates', promptTemplateRouter);
|
|
131
147
|
app.use('/api/mcps', mcpRouter);
|
|
132
148
|
app.use('/api/subscriptions', subscriptionRouter);
|
|
133
149
|
app.use('/api/speech-recognition', speechRecognitionRouter);
|
|
@@ -158,6 +174,7 @@ else {
|
|
|
158
174
|
}
|
|
159
175
|
const server = createServer(app);
|
|
160
176
|
const wss = new WebSocketServer({ noServer: true });
|
|
177
|
+
const typescriptLspWss = new WebSocketServer({ noServer: true });
|
|
161
178
|
// Speech recognition WebSocket on /ws/speech
|
|
162
179
|
const speechWss = new WebSocketServer({ noServer: true });
|
|
163
180
|
speechWss.on('connection', (ws, req) => {
|
|
@@ -183,6 +200,20 @@ wss.on('connection', (ws, req) => {
|
|
|
183
200
|
}
|
|
184
201
|
handleConnection(ws, workspaceId);
|
|
185
202
|
});
|
|
203
|
+
typescriptLspWss.on('connection', (ws, req) => {
|
|
204
|
+
const url = new URL(req.url || '', `http://localhost:${PORT}`);
|
|
205
|
+
const workspaceId = url.searchParams.get('workspaceId');
|
|
206
|
+
if (!workspaceId) {
|
|
207
|
+
ws.close(4001, 'workspaceId required');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const token = url.searchParams.get('token');
|
|
211
|
+
if (!verifyToken(token)) {
|
|
212
|
+
ws.close(4003, 'Unauthorized');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
handleTypeScriptLspConnection(ws, workspaceId);
|
|
216
|
+
});
|
|
186
217
|
server.on('upgrade', (req, socket, head) => {
|
|
187
218
|
const { pathname } = new URL(req.url || '/', `http://localhost:${PORT}`);
|
|
188
219
|
if (pathname === '/ws') {
|
|
@@ -197,6 +228,12 @@ server.on('upgrade', (req, socket, head) => {
|
|
|
197
228
|
});
|
|
198
229
|
return;
|
|
199
230
|
}
|
|
231
|
+
if (pathname === '/ws/lsp/typescript') {
|
|
232
|
+
typescriptLspWss.handleUpgrade(req, socket, head, (ws) => {
|
|
233
|
+
typescriptLspWss.emit('connection', ws, req);
|
|
234
|
+
});
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
200
237
|
socket.destroy();
|
|
201
238
|
});
|
|
202
239
|
const HOST = process.env.HOST || '0.0.0.0';
|
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.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "app.js",
|
|
6
6
|
"packageManager": "pnpm@10.17.1",
|
|
@@ -21,9 +21,12 @@
|
|
|
21
21
|
"dotenv": "^17.4.2",
|
|
22
22
|
"express": "^5.1.0",
|
|
23
23
|
"langchain": "^1.4.0",
|
|
24
|
+
"minimatch": "^10.2.5",
|
|
24
25
|
"node-pty": "^1.1.0",
|
|
25
26
|
"simple-git": "^3.36.0",
|
|
27
|
+
"typescript-language-server": "^5.2.0",
|
|
26
28
|
"uuid": "^11.1.0",
|
|
29
|
+
"vscode-ws-jsonrpc": "^3.5.0",
|
|
27
30
|
"ws": "^8.18.2",
|
|
28
31
|
"zod": "^4.0.0"
|
|
29
32
|
},
|
package/dist/routes/channel.js
CHANGED
|
@@ -4,6 +4,7 @@ import { listMessages, createMessage, updateMessage, deleteMessage, clearMessage
|
|
|
4
4
|
import { broadcastToWorkspace } from '../ws/connection-manager.js';
|
|
5
5
|
import { hasActiveChannelRuns, markInactiveChannelRunsStopped, stopChannelRuns } from '../ws/agent-runner.js';
|
|
6
6
|
import { getToolDetail } from '../services/tool-detail.js';
|
|
7
|
+
import * as issueService from '../services/issue.js';
|
|
7
8
|
const router = Router({ mergeParams: true });
|
|
8
9
|
// GET /api/workspaces/:id/channels
|
|
9
10
|
router.get('/', (req, res) => {
|
|
@@ -12,11 +13,7 @@ router.get('/', (req, res) => {
|
|
|
12
13
|
// POST /api/workspaces/:id/channels
|
|
13
14
|
router.post('/', (req, res) => {
|
|
14
15
|
const { name, type, members } = req.body;
|
|
15
|
-
|
|
16
|
-
res.status(400).json({ error: 'name required' });
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const channel = createChannel(req.params.id, { name, type: type || 'general', members });
|
|
16
|
+
const channel = createChannel(req.params.id, { name: name || 'General', type: type || 'general', members });
|
|
20
17
|
broadcastToWorkspace(req.params.id, 'channel.updated', channel);
|
|
21
18
|
res.status(201).json(channel);
|
|
22
19
|
});
|
|
@@ -24,7 +21,7 @@ router.post('/', (req, res) => {
|
|
|
24
21
|
router.put('/:channelId', (req, res) => {
|
|
25
22
|
const { id, channelId } = req.params;
|
|
26
23
|
const patch = {};
|
|
27
|
-
for (const key of ['name', 'type', 'issueId', 'members', 'pinnedMentionId', 'draft', 'todos', 'archived']) {
|
|
24
|
+
for (const key of ['name', 'type', 'issueId', 'members', 'pinnedMentionId', 'draft', 'todos', 'notifyOnComplete', 'archived']) {
|
|
28
25
|
if (Object.hasOwn(req.body, key))
|
|
29
26
|
patch[key] = req.body[key];
|
|
30
27
|
}
|
|
@@ -34,6 +31,21 @@ router.put('/:channelId', (req, res) => {
|
|
|
34
31
|
return;
|
|
35
32
|
}
|
|
36
33
|
broadcastToWorkspace(id, 'channel.updated', channel);
|
|
34
|
+
// 频道归档/取消归档时,同步关联的 Issue
|
|
35
|
+
if (Object.hasOwn(patch, 'archived') && channel.issueId) {
|
|
36
|
+
const issue = issueService.getById(id, channel.issueId);
|
|
37
|
+
if (issue) {
|
|
38
|
+
const prevStatus = issue.status;
|
|
39
|
+
const newStatus = patch.archived ? 'archived' : 'draft';
|
|
40
|
+
if (prevStatus !== newStatus) {
|
|
41
|
+
const saved = issueService.updateStatus(id, channel.issueId, newStatus);
|
|
42
|
+
if (saved) {
|
|
43
|
+
broadcastToWorkspace(id, 'issue.updated', saved);
|
|
44
|
+
broadcastToWorkspace(id, 'issue.status_changed', { issueId: channel.issueId, from: prevStatus, to: newStatus });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
37
49
|
res.json(channel);
|
|
38
50
|
});
|
|
39
51
|
// DELETE /api/workspaces/:id/channels/:channelId
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import * as svc from '../services/code-favorites.js';
|
|
3
|
+
const router = Router({ mergeParams: true });
|
|
4
|
+
router.get('/', (req, res) => {
|
|
5
|
+
const workspaceId = req.params.id;
|
|
6
|
+
if (!workspaceId) {
|
|
7
|
+
res.status(400).json({ error: 'workspaceId required' });
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
res.json(svc.listFavorites(workspaceId));
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
res.status(500).json({ error: error.message });
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
router.post('/', (req, res) => {
|
|
18
|
+
const workspaceId = req.params.id;
|
|
19
|
+
if (!workspaceId) {
|
|
20
|
+
res.status(400).json({ error: 'workspaceId required' });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const fav = svc.addFavorite(workspaceId, req.body);
|
|
25
|
+
res.status(201).json(fav);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
res.status(400).json({ error: error.message });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
router.delete('/:favId', (req, res) => {
|
|
32
|
+
const { id: workspaceId, favId } = req.params;
|
|
33
|
+
if (!workspaceId || !favId) {
|
|
34
|
+
res.status(400).json({ error: 'workspaceId and favId required' });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
svc.removeFavorite(workspaceId, favId);
|
|
39
|
+
res.status(204).send();
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
res.status(400).json({ error: error.message });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
router.delete('/', (req, res) => {
|
|
46
|
+
const workspaceId = req.params.id;
|
|
47
|
+
if (!workspaceId) {
|
|
48
|
+
res.status(400).json({ error: 'workspaceId required' });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
svc.clearFavorites(workspaceId);
|
|
53
|
+
res.status(204).send();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
res.status(400).json({ error: error.message });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
export default router;
|
|
60
|
+
//# sourceMappingURL=code-favorites.js.map
|
package/dist/routes/file.js
CHANGED
|
@@ -34,6 +34,19 @@ router.get('/content', async (req, res) => {
|
|
|
34
34
|
}
|
|
35
35
|
res.json(result);
|
|
36
36
|
});
|
|
37
|
+
router.get('/exists', async (req, res) => {
|
|
38
|
+
const ws = fileService.getWorkspace(req.params.id);
|
|
39
|
+
if (!ws) {
|
|
40
|
+
res.status(404).json({ error: 'Workspace not found' });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const path = req.query.path;
|
|
44
|
+
if (!path) {
|
|
45
|
+
res.status(400).json({ error: 'path is required' });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
res.json({ exists: fileService.fileExists(ws, path) });
|
|
49
|
+
});
|
|
37
50
|
router.put('/content', async (req, res) => {
|
|
38
51
|
const ws = fileService.getWorkspace(req.params.id);
|
|
39
52
|
if (!ws) {
|
|
@@ -95,12 +108,12 @@ router.put('/editor-state', async (req, res) => {
|
|
|
95
108
|
res.status(404).json({ error: 'Workspace not found' });
|
|
96
109
|
return;
|
|
97
110
|
}
|
|
98
|
-
const { openFilePaths, activeFilePath } = req.body;
|
|
111
|
+
const { openFilePaths, activeFilePath, pinnedPaths } = req.body;
|
|
99
112
|
if (!Array.isArray(openFilePaths)) {
|
|
100
113
|
res.status(400).json({ error: 'openFilePaths is required' });
|
|
101
114
|
return;
|
|
102
115
|
}
|
|
103
|
-
const ok = await fileService.writeFileContent(ws, EDITOR_STATE_PATH, JSON.stringify({ openFilePaths, activeFilePath }, null, 2));
|
|
116
|
+
const ok = await fileService.writeFileContent(ws, EDITOR_STATE_PATH, JSON.stringify({ openFilePaths, activeFilePath, pinnedPaths: pinnedPaths ?? [] }, null, 2));
|
|
104
117
|
if (!ok) {
|
|
105
118
|
res.status(500).json({ error: 'Failed to save editor state' });
|
|
106
119
|
return;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import * as fileService from '../services/file.js';
|
|
3
|
+
import { getInspectorHistory } from '../services/inspector-history.js';
|
|
4
|
+
const router = Router({ mergeParams: true });
|
|
5
|
+
router.get('/history', (req, res) => {
|
|
6
|
+
const ws = fileService.getWorkspace(req.params.id);
|
|
7
|
+
if (!ws) {
|
|
8
|
+
res.status(404).json({ error: 'Workspace not found' });
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
res.json(getInspectorHistory(ws));
|
|
12
|
+
});
|
|
13
|
+
export default router;
|
|
14
|
+
//# sourceMappingURL=inspector.js.map
|
package/dist/routes/issue.js
CHANGED
|
@@ -77,6 +77,13 @@ router.put('/:issueId', (req, res) => {
|
|
|
77
77
|
stopChannelRuns(req.params.id, issue.channelId);
|
|
78
78
|
}
|
|
79
79
|
broadcastToWorkspace(req.params.id, 'issue.status_changed', { issueId: req.params.issueId, from: previousStatus, to: status });
|
|
80
|
+
// Issue 归档/取消归档时,同步关联的 Channel
|
|
81
|
+
if (issue.channelId && (status === 'archived' || previousStatus === 'archived')) {
|
|
82
|
+
const archived = status === 'archived';
|
|
83
|
+
const updatedChannel = channelService.updateChannel(req.params.id, issue.channelId, { archived });
|
|
84
|
+
if (updatedChannel)
|
|
85
|
+
broadcastToWorkspace(req.params.id, 'channel.updated', updatedChannel);
|
|
86
|
+
}
|
|
80
87
|
}
|
|
81
88
|
res.json(saved);
|
|
82
89
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { listPromptTemplates, createPromptTemplate, updatePromptTemplate, deletePromptTemplate, applyPromptToAgents, listAgentCandidates, } from '../services/prompt-template.js';
|
|
3
|
+
const router = Router();
|
|
4
|
+
router.get('/', (_req, res) => {
|
|
5
|
+
res.json(listPromptTemplates());
|
|
6
|
+
});
|
|
7
|
+
router.post('/', (req, res) => {
|
|
8
|
+
const { name, content } = req.body;
|
|
9
|
+
if (!name || !content) {
|
|
10
|
+
res.status(400).json({ error: 'name and content required' });
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
res.json(createPromptTemplate(name, content));
|
|
14
|
+
});
|
|
15
|
+
router.put('/:id', (req, res) => {
|
|
16
|
+
const id = typeof req.params.id === 'string' ? req.params.id : req.params.id[0];
|
|
17
|
+
const data = req.body;
|
|
18
|
+
const tmpl = updatePromptTemplate(id, data);
|
|
19
|
+
if (!tmpl) {
|
|
20
|
+
res.status(404).json({ error: 'Template not found' });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
res.json(tmpl);
|
|
24
|
+
});
|
|
25
|
+
router.delete('/:id', (req, res) => {
|
|
26
|
+
const id = typeof req.params.id === 'string' ? req.params.id : req.params.id[0];
|
|
27
|
+
const ok = deletePromptTemplate(id);
|
|
28
|
+
if (!ok) {
|
|
29
|
+
res.status(404).json({ error: 'Template not found' });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
res.json({ success: true });
|
|
33
|
+
});
|
|
34
|
+
router.post('/:id/apply', (req, res) => {
|
|
35
|
+
const id = typeof req.params.id === 'string' ? req.params.id : req.params.id[0];
|
|
36
|
+
const { agentIds } = req.body;
|
|
37
|
+
if (!Array.isArray(agentIds) || agentIds.length === 0) {
|
|
38
|
+
res.status(400).json({ error: 'agentIds required' });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const applied = applyPromptToAgents(id, agentIds);
|
|
42
|
+
res.json({ applied });
|
|
43
|
+
});
|
|
44
|
+
router.get('/agents', (_req, res) => {
|
|
45
|
+
res.json(listAgentCandidates());
|
|
46
|
+
});
|
|
47
|
+
export default router;
|
|
48
|
+
//# sourceMappingURL=prompt-template.js.map
|
package/dist/services/agent.js
CHANGED
|
@@ -10,6 +10,7 @@ import { ensureDir, getDataDir } from '../storage/json-store.js';
|
|
|
10
10
|
import { extractUsageFromOutput } from '../storage/usage.js';
|
|
11
11
|
const DEFAULT_AGENT_ROLE = 'agent';
|
|
12
12
|
export const AGENT_GENERATOR_PRESET_ID = 'agent-generator';
|
|
13
|
+
export const AGENT_COMMIT_PRESET_ID = 'commit-agent';
|
|
13
14
|
const VALID_RUNTIME_KINDS = ['open-agent-sdk', 'claude-code', 'codex', 'langchain'];
|
|
14
15
|
const VALID_TOOL_NAMES = new Set(BUILT_IN_AGENT_TOOLS.map((tool) => tool.name));
|
|
15
16
|
const ANTHROPIC_BRIDGE_PROVIDERS = [
|
|
@@ -25,7 +26,7 @@ export function isValidRole(role) {
|
|
|
25
26
|
export function listTemplates() {
|
|
26
27
|
const root = getGlobalAgentTemplatesDir();
|
|
27
28
|
if (!existsSync(root))
|
|
28
|
-
return [getDefaultAgentGeneratorPreset()];
|
|
29
|
+
return [getDefaultAgentGeneratorPreset(), getDefaultCommitAgentPreset()];
|
|
29
30
|
const templates = readdirSync(root, { withFileTypes: true })
|
|
30
31
|
.filter((entry) => entry.isDirectory())
|
|
31
32
|
.map((entry) => readAgentTemplate(entry.name))
|
|
@@ -33,6 +34,9 @@ export function listTemplates() {
|
|
|
33
34
|
if (!templates.some((template) => template.id === AGENT_GENERATOR_PRESET_ID)) {
|
|
34
35
|
templates.unshift(getDefaultAgentGeneratorPreset());
|
|
35
36
|
}
|
|
37
|
+
if (!templates.some((template) => template.id === AGENT_COMMIT_PRESET_ID)) {
|
|
38
|
+
templates.unshift(getDefaultCommitAgentPreset());
|
|
39
|
+
}
|
|
36
40
|
return templates;
|
|
37
41
|
}
|
|
38
42
|
export async function testConnection(workspaceId, data) {
|
|
@@ -515,13 +519,17 @@ function ensureWorkspaceAgentCopy(preset, agentspaceDir) {
|
|
|
515
519
|
export function readAgentTemplate(agentId) {
|
|
516
520
|
const filePath = join(getGlobalAgentTemplateDir(agentId), 'agent.json');
|
|
517
521
|
if (!existsSync(filePath)) {
|
|
518
|
-
return agentId === AGENT_GENERATOR_PRESET_ID ? getDefaultAgentGeneratorPreset()
|
|
522
|
+
return agentId === AGENT_GENERATOR_PRESET_ID ? getDefaultAgentGeneratorPreset()
|
|
523
|
+
: agentId === AGENT_COMMIT_PRESET_ID ? getDefaultCommitAgentPreset()
|
|
524
|
+
: null;
|
|
519
525
|
}
|
|
520
526
|
try {
|
|
521
527
|
return JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
522
528
|
}
|
|
523
529
|
catch {
|
|
524
|
-
return agentId === AGENT_GENERATOR_PRESET_ID ? getDefaultAgentGeneratorPreset()
|
|
530
|
+
return agentId === AGENT_GENERATOR_PRESET_ID ? getDefaultAgentGeneratorPreset()
|
|
531
|
+
: agentId === AGENT_COMMIT_PRESET_ID ? getDefaultCommitAgentPreset()
|
|
532
|
+
: null;
|
|
525
533
|
}
|
|
526
534
|
}
|
|
527
535
|
function getDefaultAgentGeneratorPreset() {
|
|
@@ -557,6 +565,36 @@ function getDefaultAgentGeneratorPreset() {
|
|
|
557
565
|
enabled: true,
|
|
558
566
|
};
|
|
559
567
|
}
|
|
568
|
+
export function getDefaultCommitAgentPreset() {
|
|
569
|
+
return {
|
|
570
|
+
id: AGENT_COMMIT_PRESET_ID,
|
|
571
|
+
name: 'Commit Agent',
|
|
572
|
+
role: 'commit',
|
|
573
|
+
description: '根据 git diff 自动生成 conventional commit message。',
|
|
574
|
+
runtimeKind: 'claude-code',
|
|
575
|
+
modelProvider: undefined,
|
|
576
|
+
modelId: '',
|
|
577
|
+
apiBase: '',
|
|
578
|
+
apiKey: '',
|
|
579
|
+
workingDir: '',
|
|
580
|
+
mcps: {},
|
|
581
|
+
skills: [],
|
|
582
|
+
tools: [],
|
|
583
|
+
systemPrompt: [
|
|
584
|
+
'You are a git commit message generator.',
|
|
585
|
+
'Return exactly one concise commit message for the provided git diff.',
|
|
586
|
+
'Use conventional format: type: description.',
|
|
587
|
+
'Allowed types: feat, fix, docs, style, refactor, perf, test, chore.',
|
|
588
|
+
'Keep the subject under 72 characters.',
|
|
589
|
+
'If a body is needed, add one blank line and at most 3 short bullet lines.',
|
|
590
|
+
'Do not greet, explain, ask questions, provide options, use markdown, or wrap in code fences.',
|
|
591
|
+
'Output only the final commit message text.',
|
|
592
|
+
].join(' '),
|
|
593
|
+
temperature: 0,
|
|
594
|
+
maxTokens: 512,
|
|
595
|
+
enabled: true,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
560
598
|
function sanitizeMarkdownFilename(name) {
|
|
561
599
|
const raw = basename(name).replace(/\.md$/i, '');
|
|
562
600
|
const safe = raw.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'skill';
|
|
@@ -565,6 +603,8 @@ function sanitizeMarkdownFilename(name) {
|
|
|
565
603
|
export function deletePreset(workspaceId, presetId) {
|
|
566
604
|
if (presetId === AGENT_GENERATOR_PRESET_ID)
|
|
567
605
|
return false;
|
|
606
|
+
if (presetId === AGENT_COMMIT_PRESET_ID)
|
|
607
|
+
return false;
|
|
568
608
|
const ws = getWorkspace(workspaceId);
|
|
569
609
|
if (!ws)
|
|
570
610
|
return null;
|
|
@@ -654,6 +694,8 @@ export function updateGlobalPreset(presetId, data) {
|
|
|
654
694
|
export function deleteGlobalPreset(presetId) {
|
|
655
695
|
if (presetId === AGENT_GENERATOR_PRESET_ID)
|
|
656
696
|
return false;
|
|
697
|
+
if (presetId === AGENT_COMMIT_PRESET_ID)
|
|
698
|
+
return false;
|
|
657
699
|
const templateDir = getGlobalAgentTemplateDir(presetId);
|
|
658
700
|
if (!existsSync(templateDir))
|
|
659
701
|
return false;
|
package/dist/services/channel.js
CHANGED
|
@@ -53,6 +53,8 @@ export function updateChannel(workspaceId, channelId, data) {
|
|
|
53
53
|
channels[idx].draft = data.draft;
|
|
54
54
|
if (Object.hasOwn(data, 'todos'))
|
|
55
55
|
channels[idx].todos = data.todos;
|
|
56
|
+
if (Object.hasOwn(data, 'notifyOnComplete'))
|
|
57
|
+
channels[idx].notifyOnComplete = data.notifyOnComplete;
|
|
56
58
|
if (Object.hasOwn(data, 'archived'))
|
|
57
59
|
channels[idx].archived = data.archived;
|
|
58
60
|
writeJsonFile(channelsPath(workspaceId), channels);
|