@agent-spaces/server 0.3.63 → 0.3.65
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 +68 -2
- package/dist/adapters/claude-code-runtime/message-format.js +27 -1
- package/dist/adapters/claude-code-runtime/sdk-config.js +12 -0
- package/dist/adapters/git.js +168 -57
- package/dist/agents/agent-designer.js +66 -12
- package/dist/agents/agent-message-parts.js +1 -1
- package/dist/agents/commit-agent.js +4 -2
- package/dist/agents/issue-task-controller.js +7 -3
- package/dist/app.js +56 -69
- package/dist/package.json +1 -1
- package/dist/routes/agent-commands.js +72 -0
- package/dist/routes/agent-sse.js +7 -0
- package/dist/routes/agent.js +18 -1
- package/dist/routes/database.js +346 -0
- package/dist/routes/git.js +198 -267
- package/dist/routes/kanban.js +39 -0
- package/dist/routes/robot-account.js +68 -0
- package/dist/services/agent-commands.js +168 -0
- package/dist/services/agent.js +36 -2
- package/dist/services/builtin-tools/command-tools.js +117 -0
- package/dist/services/builtin-tools/database-tools.js +578 -0
- package/dist/services/builtin-tools/index.js +5 -0
- package/dist/services/builtin-tools/input-helpers.js +26 -0
- package/dist/services/builtin-tools/issue-tools.js +209 -0
- package/dist/services/builtin-tools/kanban-tools.js +281 -0
- package/dist/services/database-vector.js +244 -0
- package/dist/services/git-operation-log.js +40 -0
- package/dist/services/global-wechat-qr.js +72 -0
- package/dist/services/hook-engine.js +175 -17
- package/dist/services/kanban.js +50 -0
- package/dist/services/notification-hub/bot-agent.js +3 -1
- package/dist/services/notification-hub/service.js +12 -2
- package/dist/services/robot-account.js +34 -0
- package/dist/services/workspace.js +2 -0
- package/dist/storage/database-store.js +365 -0
- package/dist/storage/kanban-store.js +142 -0
- package/dist/storage/robot-account-store.js +39 -0
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +4 -4
- package/dist/web/__next._full.txt +24 -31
- package/dist/web/__next._head.txt +4 -4
- package/dist/web/__next._index.txt +14 -14
- package/dist/web/__next._tree.txt +3 -8
- package/dist/web/_next/static/chunks/0-a.-hl3wv99k.js +1 -0
- package/dist/web/_next/static/chunks/{0ctg5qmw7uu.1.js → 0-pi.67w.ymsr.js} +3 -3
- package/dist/web/_next/static/chunks/0-v_p6j5u3_9l.js +1 -0
- package/dist/web/_next/static/chunks/0.-x29t-8gk0r.js +1 -0
- package/dist/web/_next/static/chunks/0.6b64sy0g5.3.js +3 -0
- package/dist/web/_next/static/chunks/0.l5e8~r7_0~p.js +1 -0
- package/dist/web/_next/static/chunks/00-syqzi-6zxr.js +1 -0
- package/dist/web/_next/static/chunks/{13~y-b.b9rrw4.js → 01~quun6sefgl.js} +1 -1
- package/dist/web/_next/static/chunks/02802taez976w.js +67 -0
- package/dist/web/_next/static/chunks/02j4sr9psucf-.js +1 -0
- package/dist/web/_next/static/chunks/033.awk90g6eh.js +1 -0
- package/dist/web/_next/static/chunks/06.kdsa9rr2h1.js +1 -0
- package/dist/web/_next/static/chunks/{0-oog4zg4_m~m.css → 062f9zqctzg.b.css} +0 -3
- package/dist/web/_next/static/chunks/06si8l0doqe8p.js +1 -0
- package/dist/web/_next/static/chunks/08ugbvzr20drp.js +2 -0
- package/dist/web/_next/static/chunks/{0kof5qdg8c2-k.js → 08x85faoz58i7.js} +37 -37
- package/dist/web/_next/static/chunks/0_cqojbge48kq.js +5 -0
- package/dist/web/_next/static/chunks/0_mvduwjsm35w.js +1 -0
- package/dist/web/_next/static/chunks/0d6~~lv0-6kex.js +3 -0
- package/dist/web/_next/static/chunks/{0ogpc3f3keopc.js → 0db14450oqzhg.js} +2 -2
- package/dist/web/_next/static/chunks/0fttswpzu69qx.js +1 -0
- package/dist/web/_next/static/chunks/0gdwop9cnpmtu.js +1 -0
- package/dist/web/_next/static/chunks/0ghx3j_.-gdyd.js +1 -0
- package/dist/web/_next/static/chunks/0j-l7l_k9jt45.js +1 -0
- package/dist/web/_next/static/chunks/0k4zdm72k_bfy.js +1 -0
- package/dist/web/_next/static/chunks/0kbvoxla7f751.js +1 -0
- package/dist/web/_next/static/chunks/{0aa6bcdmtpekn.js → 0l2w0qz1ea7ql.js} +2 -2
- package/dist/web/_next/static/chunks/0p3h-h3zj5ujg.js +30 -0
- package/dist/web/_next/static/chunks/0paaat8y96ayc.js +7 -0
- package/dist/web/_next/static/chunks/0pm-un~-sy3rl.js +1 -0
- package/dist/web/_next/static/chunks/0pq318f8xgafg.js +1 -0
- package/dist/web/_next/static/chunks/0t6s8of0qr6nc.js +1 -0
- package/dist/web/_next/static/chunks/0u6h-hqc_i52e.js +1 -0
- package/dist/web/_next/static/chunks/0uxzi~9b~k4mn.js +31 -0
- package/dist/web/_next/static/chunks/{002-dxhags4dj.js → 0v6hte2z-32ca.js} +2 -2
- package/dist/web/_next/static/chunks/{014x2qbuiszni.js → 0vis~lx0nxgn-.js} +3 -3
- package/dist/web/_next/static/chunks/{0y09i51u6ixq5.js → 0w7.tb29958zj.js} +1 -1
- package/dist/web/_next/static/chunks/0xbaakj0dfc0..js +1 -0
- package/dist/web/_next/static/chunks/0yd.m1afqg.2t.js +3 -0
- package/dist/web/_next/static/chunks/0yhbr8hl09b-5.js +1 -0
- package/dist/web/_next/static/chunks/0zncg76rgtbm-.js +1 -0
- package/dist/web/_next/static/chunks/0z~vqzbm_q371.js +1 -0
- package/dist/web/_next/static/chunks/0~~_ltu6dx_ch.js +1 -0
- package/dist/web/_next/static/chunks/{02c22g~xd-y30.js → 11cchuwoupmbf.js} +2 -2
- package/dist/web/_next/static/chunks/12jm4gwmvq-0q.js +90 -0
- package/dist/web/_next/static/chunks/12oxcgyhpaxw~.js +1 -0
- package/dist/web/_next/static/chunks/1452eibz62gs6.css +1 -0
- package/dist/web/_next/static/chunks/16zlreiems5cn.js +1 -0
- package/dist/web/_next/static/chunks/18awqjk9-o5m0.js +1 -0
- package/dist/web/_next/static/chunks/18c7g84y01mj0.js +1 -0
- package/dist/web/_next/static/chunks/{turbopack-0ndm2zc_pdptk.js → turbopack-11qjwlynmfc-n.js} +1 -1
- package/dist/web/_not-found/__next._full.txt +31 -30
- package/dist/web/_not-found/__next._head.txt +4 -4
- package/dist/web/_not-found/__next._index.txt +14 -14
- 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 +3 -3
- package/dist/web/_not-found.html +1 -1
- package/dist/web/_not-found.txt +31 -30
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +24 -31
- package/dist/web/login/__next._full.txt +32 -36
- package/dist/web/login/__next._head.txt +4 -4
- package/dist/web/login/__next._index.txt +14 -14
- package/dist/web/login/__next._tree.txt +3 -8
- 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 +32 -36
- package/dist/web/settings/__next._full.txt +34 -38
- package/dist/web/settings/__next._head.txt +4 -4
- package/dist/web/settings/__next._index.txt +14 -14
- package/dist/web/settings/__next._tree.txt +3 -8
- 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 +27 -32
- package/dist/web/settings/agents/__next._head.txt +4 -4
- package/dist/web/settings/agents/__next._index.txt +14 -14
- package/dist/web/settings/agents/__next._tree.txt +3 -8
- 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 +27 -32
- package/dist/web/settings/mcps/__next._full.txt +27 -32
- package/dist/web/settings/mcps/__next._head.txt +4 -4
- package/dist/web/settings/mcps/__next._index.txt +14 -14
- package/dist/web/settings/mcps/__next._tree.txt +3 -8
- 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 +27 -32
- package/dist/web/settings/models/__next._full.txt +27 -32
- package/dist/web/settings/models/__next._head.txt +4 -4
- package/dist/web/settings/models/__next._index.txt +14 -14
- package/dist/web/settings/models/__next._tree.txt +3 -8
- 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 +27 -32
- package/dist/web/settings/output-styles/__next._full.txt +27 -32
- package/dist/web/settings/output-styles/__next._head.txt +4 -4
- package/dist/web/settings/output-styles/__next._index.txt +14 -14
- package/dist/web/settings/output-styles/__next._tree.txt +3 -8
- package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +4 -4
- package/dist/web/settings/output-styles/__next.settings.output-styles.txt +3 -3
- package/dist/web/settings/output-styles/__next.settings.txt +5 -5
- package/dist/web/settings/output-styles.html +1 -1
- package/dist/web/settings/output-styles.txt +27 -32
- package/dist/web/settings/prompts/__next._full.txt +27 -32
- package/dist/web/settings/prompts/__next._head.txt +4 -4
- package/dist/web/settings/prompts/__next._index.txt +14 -14
- package/dist/web/settings/prompts/__next._tree.txt +3 -8
- 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 +27 -32
- package/dist/web/settings/providers/__next._full.txt +27 -32
- package/dist/web/settings/providers/__next._head.txt +4 -4
- package/dist/web/settings/providers/__next._index.txt +14 -14
- package/dist/web/settings/providers/__next._tree.txt +3 -8
- 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 +27 -32
- package/dist/web/settings/skills/__next._full.txt +27 -32
- package/dist/web/settings/skills/__next._head.txt +4 -4
- package/dist/web/settings/skills/__next._index.txt +14 -14
- package/dist/web/settings/skills/__next._tree.txt +3 -8
- 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 +27 -32
- package/dist/web/settings/tools/__next._full.txt +38 -0
- package/dist/web/settings/tools/__next._head.txt +6 -0
- package/dist/web/settings/tools/__next._index.txt +15 -0
- package/dist/web/settings/tools/__next._tree.txt +3 -0
- package/dist/web/settings/tools/__next.settings.tools.__PAGE__.txt +9 -0
- package/dist/web/settings/tools/__next.settings.tools.txt +5 -0
- package/dist/web/settings/tools/__next.settings.txt +7 -0
- package/dist/web/settings/tools.html +1 -0
- package/dist/web/settings/tools.txt +38 -0
- package/dist/web/settings.html +1 -1
- package/dist/web/settings.txt +34 -38
- package/dist/web/workflows/__next._full.txt +32 -38
- package/dist/web/workflows/__next._head.txt +4 -4
- package/dist/web/workflows/__next._index.txt +14 -14
- package/dist/web/workflows/__next._tree.txt +3 -8
- 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 -38
- package/dist/web/workspace/_/__next._full.txt +31 -36
- package/dist/web/workspace/_/__next._head.txt +4 -4
- package/dist/web/workspace/_/__next._index.txt +14 -14
- package/dist/web/workspace/_/__next._tree.txt +4 -8
- package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.txt +3 -3
- package/dist/web/workspace/_.html +1 -1
- package/dist/web/workspace/_.txt +31 -36
- package/dist/web/workspaces/__next._full.txt +30 -37
- package/dist/web/workspaces/__next._head.txt +4 -4
- package/dist/web/workspaces/__next._index.txt +14 -14
- package/dist/web/workspaces/__next._tree.txt +3 -8
- 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 +30 -37
- package/dist/ws/agent-prompt.js +45 -8
- package/dist/ws/agent-runner.js +88 -10
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/0-1bfvfwifh-m.js +0 -1
- package/dist/web/_next/static/chunks/02mf61htij8g0.js +0 -31
- package/dist/web/_next/static/chunks/046me66nilkff.js +0 -1
- package/dist/web/_next/static/chunks/04v-pqqs-2lvp.css +0 -1
- package/dist/web/_next/static/chunks/06w~.izyfylap.js +0 -1
- package/dist/web/_next/static/chunks/09t62a89~jesc.js +0 -3
- package/dist/web/_next/static/chunks/09y_3krccdd~u.js +0 -1
- package/dist/web/_next/static/chunks/0_e~hmntdfop9.js +0 -1
- package/dist/web/_next/static/chunks/0_udc.6.tueey.js +0 -1
- package/dist/web/_next/static/chunks/0cke33d38fnby.js +0 -90
- package/dist/web/_next/static/chunks/0cyq~8xb~r5fc.js +0 -1
- package/dist/web/_next/static/chunks/0ewceguykiut5.js +0 -1
- package/dist/web/_next/static/chunks/0fxa1edqr7dve.js +0 -1
- package/dist/web/_next/static/chunks/0hra80eyuu37u.js +0 -1
- package/dist/web/_next/static/chunks/0ie7y4k2ncvnn.js +0 -1
- package/dist/web/_next/static/chunks/0igc~uli58ncw.js +0 -2
- package/dist/web/_next/static/chunks/0msb2mi3hiu5_.js +0 -67
- package/dist/web/_next/static/chunks/0p1n8bvfnpl41.js +0 -1
- package/dist/web/_next/static/chunks/0ppr271hz0xoq.js +0 -1
- package/dist/web/_next/static/chunks/0s_dva~eh2yhi.js +0 -3
- package/dist/web/_next/static/chunks/0typj55ox8d5i.js +0 -1
- package/dist/web/_next/static/chunks/0w2p4ldi2aymp.js +0 -1
- package/dist/web/_next/static/chunks/0zc0xgp5ourcn.js +0 -1
- package/dist/web/_next/static/chunks/0zmhdridea1s5.js +0 -90
- package/dist/web/_next/static/chunks/10.alq.6stmld.js +0 -1
- package/dist/web/_next/static/chunks/11b3zgk1etlkw.js +0 -7
- package/dist/web/_next/static/chunks/11qp8r5dotf7d.js +0 -1
- package/dist/web/_next/static/chunks/12mxlicp247c8.js +0 -1
- package/dist/web/_next/static/chunks/135w27dd8c19s.js +0 -5
- package/dist/web/_next/static/chunks/176dc-dtokxxi.js +0 -16
- package/dist/web/_next/static/chunks/17g-0pqre.anw.js +0 -1
- package/dist/web/_next/static/media/0a7740363b4d4863-s.1110aazvokzp..woff2 +0 -0
- package/dist/web/_next/static/media/0da9c7f357bd9d4d-s.0ek5sshv8wk3m.woff2 +0 -0
- package/dist/web/_next/static/media/1b99372b3eaef0c8-s.p.0gx2haw2tmll8.woff2 +0 -0
- package/dist/web/_next/static/media/41e95f694c5c4549-s.0r1jrq7neqdsq.woff2 +0 -0
- package/dist/web/_next/static/media/5c285b27cdda1fe8-s.p.0yo6-5yoeeudq.woff2 +0 -0
- package/dist/web/_next/static/media/5f9d24ebef5d5292-s.0esuu2f5si~v8.woff2 +0 -0
- package/dist/web/_next/static/media/6c55a692938ebbbc-s.0g6rbszwfgn9y.woff2 +0 -0
- package/dist/web/_next/static/media/8e6fa89aa22d24ec-s.p.0uvzar8hswo3p.woff2 +0 -0
- package/dist/web/_next/static/media/a218039a3287bcfd-s.p.17-1enzs_j91b.woff2 +0 -0
- package/dist/web/_next/static/media/b2ea385cb5ae8625-s.0kjod.kaq1k69.woff2 +0 -0
- package/dist/web/_next/static/media/bdc7e24a509eb931-s.0apt5mko2.qn3.woff2 +0 -0
- package/dist/web/_next/static/media/c3cb240f9c892514-s.163v2i5cux7-c.woff2 +0 -0
- package/dist/web/_next/static/media/e2334d715941921e-s.p.12skym0rqknxy.woff2 +0 -0
- package/public/output-styles/carmack-mode.md +0 -381
- package/public/output-styles/codex-rigor-mode.md +0 -114
- package/public/output-styles/dhh-mode.md +0 -265
- package/public/output-styles/evan-you-mode.md +0 -539
- package/public/output-styles/index.json +0 -37
- package/public/output-styles/jobs-mode.md +0 -369
- package/public/output-styles/linus-mode.md +0 -135
- package/public/output-styles/uncle-bob-mode.md +0 -221
- package/public/prompt/andrej-karpathy-skills.md +0 -65
- package/public/prompt/claude-token-efficient-coding.md +0 -35
- package/public/prompt/index.json +0 -12
- package/public/skills/index.json +0 -92
- package/public/skills/planning-with-files/planning-with-files-zh/SKILL.md +0 -243
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.ps1 +0 -44
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/check-complete.sh +0 -46
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.ps1 +0 -124
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/init-session.sh +0 -124
- package/public/skills/planning-with-files/planning-with-files-zh/scripts/session-catchup.py +0 -438
- package/public/skills/planning-with-files/planning-with-files-zh/templates/findings.md +0 -29
- package/public/skills/planning-with-files/planning-with-files-zh/templates/progress.md +0 -40
- package/public/skills/planning-with-files/planning-with-files-zh/templates/task_plan.md +0 -58
- package/public/skills/superpowers/brainstorming/SKILL.md +0 -164
- package/public/skills/superpowers/brainstorming/scripts/frame-template.html +0 -214
- package/public/skills/superpowers/brainstorming/scripts/helper.js +0 -88
- package/public/skills/superpowers/brainstorming/scripts/server.cjs +0 -354
- package/public/skills/superpowers/brainstorming/scripts/start-server.sh +0 -148
- package/public/skills/superpowers/brainstorming/scripts/stop-server.sh +0 -56
- package/public/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +0 -49
- package/public/skills/superpowers/brainstorming/visual-companion.md +0 -287
- package/public/skills/superpowers/dispatching-parallel-agents/SKILL.md +0 -182
- package/public/skills/superpowers/executing-plans/SKILL.md +0 -70
- package/public/skills/superpowers/finishing-a-development-branch/SKILL.md +0 -251
- package/public/skills/superpowers/receiving-code-review/SKILL.md +0 -213
- package/public/skills/superpowers/requesting-code-review/SKILL.md +0 -103
- package/public/skills/superpowers/requesting-code-review/code-reviewer.md +0 -168
- package/public/skills/superpowers/subagent-driven-development/SKILL.md +0 -279
- package/public/skills/superpowers/subagent-driven-development/code-quality-reviewer-prompt.md +0 -25
- package/public/skills/superpowers/subagent-driven-development/implementer-prompt.md +0 -113
- package/public/skills/superpowers/subagent-driven-development/spec-reviewer-prompt.md +0 -61
- package/public/skills/superpowers/systematic-debugging/CREATION-LOG.md +0 -119
- package/public/skills/superpowers/systematic-debugging/SKILL.md +0 -296
- package/public/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +0 -158
- package/public/skills/superpowers/systematic-debugging/condition-based-waiting.md +0 -115
- package/public/skills/superpowers/systematic-debugging/defense-in-depth.md +0 -122
- package/public/skills/superpowers/systematic-debugging/find-polluter.sh +0 -63
- package/public/skills/superpowers/systematic-debugging/root-cause-tracing.md +0 -169
- package/public/skills/superpowers/systematic-debugging/test-academic.md +0 -14
- package/public/skills/superpowers/systematic-debugging/test-pressure-1.md +0 -58
- package/public/skills/superpowers/systematic-debugging/test-pressure-2.md +0 -68
- package/public/skills/superpowers/systematic-debugging/test-pressure-3.md +0 -69
- package/public/skills/superpowers/test-driven-development/SKILL.md +0 -371
- package/public/skills/superpowers/test-driven-development/testing-anti-patterns.md +0 -299
- package/public/skills/superpowers/using-git-worktrees/SKILL.md +0 -215
- package/public/skills/superpowers/using-superpowers/SKILL.md +0 -117
- package/public/skills/superpowers/using-superpowers/references/codex-tools.md +0 -59
- package/public/skills/superpowers/using-superpowers/references/copilot-tools.md +0 -42
- package/public/skills/superpowers/using-superpowers/references/gemini-tools.md +0 -51
- package/public/skills/superpowers/verification-before-completion/SKILL.md +0 -139
- package/public/skills/superpowers/writing-plans/SKILL.md +0 -152
- package/public/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +0 -49
- package/public/skills/superpowers/writing-skills/SKILL.md +0 -655
- package/public/skills/superpowers/writing-skills/anthropic-best-practices.md +0 -1150
- package/public/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
- package/public/skills/superpowers/writing-skills/graphviz-conventions.dot +0 -172
- package/public/skills/superpowers/writing-skills/persuasion-principles.md +0 -187
- package/public/skills/superpowers/writing-skills/render-graphs.js +0 -168
- package/public/skills/superpowers/writing-skills/testing-skills-with-subagents.md +0 -384
- /package/dist/web/_next/static/{OoXAsPtrUWjC1l898FSvI → x4-CsKe6qUQyFDWVtfvUg}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{OoXAsPtrUWjC1l898FSvI → x4-CsKe6qUQyFDWVtfvUg}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{OoXAsPtrUWjC1l898FSvI → x4-CsKe6qUQyFDWVtfvUg}/_ssgManifest.js +0 -0
|
@@ -28,7 +28,8 @@ export async function runBotAgent(workspaceId, preset, message) {
|
|
|
28
28
|
const workingDir = agentService.resolveWorkingDir(workspaceId, preset);
|
|
29
29
|
const workspace = workspaceService.getById(workspaceId);
|
|
30
30
|
try {
|
|
31
|
-
const
|
|
31
|
+
const userPrompt = buildBotPrompt(message);
|
|
32
|
+
const result = await runtime.execute(prependPersistentAgentContext(userPrompt, {
|
|
32
33
|
workspaceId,
|
|
33
34
|
workingDir,
|
|
34
35
|
boundDirs: workspace?.boundDirs,
|
|
@@ -36,6 +37,7 @@ export async function runBotAgent(workspaceId, preset, message) {
|
|
|
36
37
|
excludeNativeClaudeMd: preset.runtimeKind === 'claude-code',
|
|
37
38
|
}), workingDir, {
|
|
38
39
|
maxTurns: 20,
|
|
40
|
+
userPrompt,
|
|
39
41
|
mcpServers: agentService.getMcpServers(preset.mcps),
|
|
40
42
|
skills: agentService.getAvailableSkillNames(agentService.getAgentConfigDir(workspaceId, preset), preset.skills),
|
|
41
43
|
configDir: agentService.getAgentConfigDir(workspaceId, preset),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as workspaceService from '../workspace.js';
|
|
2
|
+
import { resolveCredentials } from '../robot-account.js';
|
|
2
3
|
import { adapters } from './types.js';
|
|
3
4
|
import { persistServiceRunning } from './helpers.js';
|
|
4
5
|
import { WeChatNotificationAdapter } from './wechat-adapter.js';
|
|
@@ -9,15 +10,24 @@ export async function startWorkspaceNotificationService(workspaceId) {
|
|
|
9
10
|
if (!workspace || !settings?.enabled)
|
|
10
11
|
return { started: false };
|
|
11
12
|
await stopWorkspaceNotificationService(workspaceId);
|
|
13
|
+
const credentials = resolveCredentials(settings);
|
|
12
14
|
if (settings.provider === 'lark') {
|
|
13
|
-
|
|
15
|
+
if (!credentials || credentials.type !== 'lark') {
|
|
16
|
+
throw new Error('Lark credentials not found. Link a Robot Account or configure appId/appSecret.');
|
|
17
|
+
}
|
|
18
|
+
const mergedSettings = { ...settings, lark: { ...settings.lark, appId: credentials.appId, appSecret: credentials.appSecret } };
|
|
19
|
+
const adapter = new LarkNotificationAdapter(workspace, mergedSettings);
|
|
14
20
|
await adapter.start();
|
|
15
21
|
adapters.set(workspaceId, adapter);
|
|
16
22
|
persistServiceRunning(workspaceId, true);
|
|
17
23
|
return { started: true, provider: 'lark' };
|
|
18
24
|
}
|
|
19
25
|
if (settings.provider === 'wechat') {
|
|
20
|
-
|
|
26
|
+
if (!credentials || credentials.type !== 'wechat') {
|
|
27
|
+
throw new Error('WeChat credentials not found. Link a Robot Account or scan QR code first.');
|
|
28
|
+
}
|
|
29
|
+
const mergedSettings = { ...settings, wechat: { ...settings.wechat, token: credentials.token, baseUrl: credentials.baseUrl, accountId: credentials.accountId, userId: credentials.userId } };
|
|
30
|
+
const adapter = new WeChatNotificationAdapter(workspace, mergedSettings);
|
|
21
31
|
await adapter.start();
|
|
22
32
|
adapters.set(workspaceId, adapter);
|
|
23
33
|
persistServiceRunning(workspaceId, true);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { v4 as uuid } from 'uuid';
|
|
2
|
+
import { listRobotAccounts, getRobotAccount, createRobotAccount, updateRobotAccount, deleteRobotAccount } from '../storage/robot-account-store.js';
|
|
3
|
+
export { listRobotAccounts, getRobotAccount, deleteRobotAccount };
|
|
4
|
+
export function createAccount(input) {
|
|
5
|
+
const now = new Date().toISOString();
|
|
6
|
+
const account = { id: uuid(), name: input.name, type: input.type, lark: input.lark, wechat: input.wechat, createdAt: now, updatedAt: now };
|
|
7
|
+
createRobotAccount(account);
|
|
8
|
+
return account;
|
|
9
|
+
}
|
|
10
|
+
export function updateAccount(id, patch) {
|
|
11
|
+
return updateRobotAccount(id, patch);
|
|
12
|
+
}
|
|
13
|
+
export function resolveCredentials(settings) {
|
|
14
|
+
if (settings.robotAccountId) {
|
|
15
|
+
const account = getRobotAccount(settings.robotAccountId);
|
|
16
|
+
if (account) {
|
|
17
|
+
if (account.type === 'lark' && account.lark) {
|
|
18
|
+
return { type: 'lark', appId: account.lark.appId, appSecret: account.lark.appSecret };
|
|
19
|
+
}
|
|
20
|
+
if (account.type === 'wechat' && account.wechat) {
|
|
21
|
+
return { type: 'wechat', token: account.wechat.token, baseUrl: account.wechat.baseUrl || 'https://qyapi.weixin.qq.com', accountId: account.wechat.accountId, userId: account.wechat.userId };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// fallback to inline credentials
|
|
26
|
+
if (settings.provider === 'lark' && settings.lark?.appId && settings.lark?.appSecret) {
|
|
27
|
+
return { type: 'lark', appId: settings.lark.appId, appSecret: settings.lark.appSecret };
|
|
28
|
+
}
|
|
29
|
+
if (settings.provider === 'wechat' && settings.wechat?.token && settings.wechat?.accountId) {
|
|
30
|
+
return { type: 'wechat', token: settings.wechat.token, baseUrl: settings.wechat.baseUrl || 'https://qyapi.weixin.qq.com', accountId: settings.wechat.accountId, userId: settings.wechat.userId };
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=robot-account.js.map
|
|
@@ -59,6 +59,8 @@ export function update(id, data) {
|
|
|
59
59
|
allowed.autoProcessIssues = data.autoProcessIssues;
|
|
60
60
|
if (Object.hasOwn(data, 'notificationSettings'))
|
|
61
61
|
allowed.notificationSettings = data.notificationSettings;
|
|
62
|
+
if (Object.hasOwn(data, 'hooksEnabled'))
|
|
63
|
+
allowed.hooksEnabled = data.hooksEnabled;
|
|
62
64
|
Object.assign(ws, allowed, { updatedAt: new Date().toISOString() });
|
|
63
65
|
updateWorkspace(ws);
|
|
64
66
|
return ws;
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { v4 as uuid } from 'uuid';
|
|
5
|
+
import { getDataDir, ensureDir } from './json-store.js';
|
|
6
|
+
let db = null;
|
|
7
|
+
function openDb() {
|
|
8
|
+
if (db)
|
|
9
|
+
return db;
|
|
10
|
+
const dir = join(getDataDir(), 'database');
|
|
11
|
+
ensureDir(dir);
|
|
12
|
+
db = new DatabaseSync(join(dir, 'database.sqlite'));
|
|
13
|
+
const hasDocNodes = Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'doc_nodes'").get());
|
|
14
|
+
const hasDatabaseId = hasDocNodes
|
|
15
|
+
&& db.prepare('PRAGMA table_info(doc_nodes)').all()
|
|
16
|
+
.some((column) => column.name === 'database_id');
|
|
17
|
+
if (hasDocNodes && !hasDatabaseId) {
|
|
18
|
+
db.exec('DROP TABLE IF EXISTS doc_nodes; DROP TABLE IF EXISTS databases;');
|
|
19
|
+
}
|
|
20
|
+
db.exec(`
|
|
21
|
+
CREATE TABLE IF NOT EXISTS databases (
|
|
22
|
+
id TEXT PRIMARY KEY,
|
|
23
|
+
workspace_id TEXT NOT NULL,
|
|
24
|
+
name TEXT NOT NULL DEFAULT '',
|
|
25
|
+
description TEXT NOT NULL DEFAULT '',
|
|
26
|
+
embedding_model_id TEXT,
|
|
27
|
+
created_at INTEGER NOT NULL,
|
|
28
|
+
updated_at INTEGER NOT NULL
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS doc_nodes (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
workspace_id TEXT NOT NULL,
|
|
34
|
+
database_id TEXT NOT NULL,
|
|
35
|
+
title TEXT NOT NULL DEFAULT '',
|
|
36
|
+
icon TEXT NOT NULL DEFAULT '',
|
|
37
|
+
cover TEXT NOT NULL DEFAULT '',
|
|
38
|
+
content TEXT NOT NULL DEFAULT '',
|
|
39
|
+
parent_id TEXT,
|
|
40
|
+
is_trash INTEGER NOT NULL DEFAULT 0,
|
|
41
|
+
created_at INTEGER NOT NULL,
|
|
42
|
+
updated_at INTEGER NOT NULL
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
CREATE TABLE IF NOT EXISTS database_embeddings (
|
|
46
|
+
workspace_id TEXT NOT NULL,
|
|
47
|
+
database_id TEXT NOT NULL,
|
|
48
|
+
node_id TEXT NOT NULL,
|
|
49
|
+
title TEXT NOT NULL DEFAULT '',
|
|
50
|
+
path TEXT NOT NULL DEFAULT '',
|
|
51
|
+
content TEXT NOT NULL DEFAULT '',
|
|
52
|
+
content_hash TEXT NOT NULL,
|
|
53
|
+
embedding TEXT NOT NULL,
|
|
54
|
+
model_id TEXT NOT NULL DEFAULT '',
|
|
55
|
+
agent_id TEXT NOT NULL DEFAULT '',
|
|
56
|
+
updated_at INTEGER NOT NULL,
|
|
57
|
+
PRIMARY KEY (workspace_id, database_id, node_id)
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
CREATE TABLE IF NOT EXISTS doc_node_versions (
|
|
61
|
+
id TEXT PRIMARY KEY,
|
|
62
|
+
workspace_id TEXT NOT NULL,
|
|
63
|
+
database_id TEXT NOT NULL,
|
|
64
|
+
node_id TEXT NOT NULL,
|
|
65
|
+
title TEXT NOT NULL DEFAULT '',
|
|
66
|
+
patch_json TEXT NOT NULL,
|
|
67
|
+
old_hash TEXT NOT NULL,
|
|
68
|
+
new_hash TEXT NOT NULL,
|
|
69
|
+
created_at INTEGER NOT NULL
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_databases_workspace ON databases(workspace_id);
|
|
73
|
+
CREATE INDEX IF NOT EXISTS idx_doc_nodes_workspace ON doc_nodes(workspace_id);
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_doc_nodes_database ON doc_nodes(workspace_id, database_id);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_doc_nodes_parent ON doc_nodes(workspace_id, database_id, parent_id);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_database_embeddings_database ON database_embeddings(workspace_id, database_id);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_doc_node_versions_node ON doc_node_versions(workspace_id, database_id, node_id, created_at DESC);
|
|
78
|
+
`);
|
|
79
|
+
ensureColumn('databases', 'embedding_model_id', 'TEXT');
|
|
80
|
+
migrateEmbeddingModelColumn();
|
|
81
|
+
return db;
|
|
82
|
+
}
|
|
83
|
+
function ensureColumn(table, column, type) {
|
|
84
|
+
const database = db;
|
|
85
|
+
const exists = database.prepare(`PRAGMA table_info(${table})`).all()
|
|
86
|
+
.some((item) => item.name === column);
|
|
87
|
+
if (!exists)
|
|
88
|
+
database.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
|
|
89
|
+
}
|
|
90
|
+
function migrateEmbeddingModelColumn() {
|
|
91
|
+
const database = db;
|
|
92
|
+
const columns = database.prepare('PRAGMA table_info(databases)').all();
|
|
93
|
+
const hasLegacyAgentColumn = columns.some((item) => item.name === 'embedding_agent_id');
|
|
94
|
+
if (!hasLegacyAgentColumn)
|
|
95
|
+
return;
|
|
96
|
+
database.exec(`
|
|
97
|
+
UPDATE databases
|
|
98
|
+
SET embedding_model_id = COALESCE(embedding_model_id, embedding_agent_id)
|
|
99
|
+
WHERE embedding_agent_id IS NOT NULL AND embedding_agent_id != ''
|
|
100
|
+
`);
|
|
101
|
+
}
|
|
102
|
+
function rowToDatabase(row) {
|
|
103
|
+
return {
|
|
104
|
+
id: row.id,
|
|
105
|
+
workspaceId: row.workspace_id,
|
|
106
|
+
name: row.name,
|
|
107
|
+
description: row.description,
|
|
108
|
+
embeddingModelId: row.embedding_model_id || undefined,
|
|
109
|
+
createdAt: row.created_at,
|
|
110
|
+
updatedAt: row.updated_at,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function rowToNode(row) {
|
|
114
|
+
return {
|
|
115
|
+
id: row.id,
|
|
116
|
+
databaseId: row.database_id,
|
|
117
|
+
title: row.title,
|
|
118
|
+
icon: row.icon,
|
|
119
|
+
cover: row.cover,
|
|
120
|
+
content: row.content,
|
|
121
|
+
parentId: row.parent_id || null,
|
|
122
|
+
isTrash: !!row.is_trash,
|
|
123
|
+
createdAt: row.created_at,
|
|
124
|
+
updatedAt: row.updated_at,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function rowToVersionRow(row) {
|
|
128
|
+
return {
|
|
129
|
+
id: row.id,
|
|
130
|
+
nodeId: row.node_id,
|
|
131
|
+
databaseId: row.database_id,
|
|
132
|
+
title: row.title,
|
|
133
|
+
patch: JSON.parse(row.patch_json),
|
|
134
|
+
oldHash: row.old_hash,
|
|
135
|
+
newHash: row.new_hash,
|
|
136
|
+
createdAt: row.created_at,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export function listDatabases(workspaceId) {
|
|
140
|
+
const database = openDb();
|
|
141
|
+
const rows = database.prepare('SELECT * FROM databases WHERE workspace_id = ? ORDER BY created_at ASC').all(workspaceId);
|
|
142
|
+
return rows.map(rowToDatabase);
|
|
143
|
+
}
|
|
144
|
+
export function getDatabase(workspaceId, databaseId) {
|
|
145
|
+
const database = openDb();
|
|
146
|
+
const row = database.prepare('SELECT * FROM databases WHERE workspace_id = ? AND id = ?').get(workspaceId, databaseId);
|
|
147
|
+
return row ? rowToDatabase(row) : null;
|
|
148
|
+
}
|
|
149
|
+
export function getDefaultDatabase(workspaceId) {
|
|
150
|
+
const existing = listDatabases(workspaceId)[0];
|
|
151
|
+
if (existing)
|
|
152
|
+
return existing;
|
|
153
|
+
return createDatabase(workspaceId, { name: 'Default Database' });
|
|
154
|
+
}
|
|
155
|
+
export function createDatabase(workspaceId, input) {
|
|
156
|
+
const database = openDb();
|
|
157
|
+
const id = input.id || uuid();
|
|
158
|
+
const now = Date.now();
|
|
159
|
+
database.prepare(`INSERT INTO databases (id, workspace_id, name, description, created_at, updated_at)
|
|
160
|
+
VALUES (?, ?, ?, ?, ?, ?)`).run(id, workspaceId, input.name?.trim() || 'Untitled Database', input.description || '', now, now);
|
|
161
|
+
return getDatabase(workspaceId, id);
|
|
162
|
+
}
|
|
163
|
+
export function updateDatabase(workspaceId, databaseId, updates) {
|
|
164
|
+
const existing = getDatabase(workspaceId, databaseId);
|
|
165
|
+
if (!existing)
|
|
166
|
+
return null;
|
|
167
|
+
const database = openDb();
|
|
168
|
+
const merged = { ...existing, ...updates, updatedAt: Date.now() };
|
|
169
|
+
database.prepare('UPDATE databases SET name = ?, description = ?, embedding_model_id = ?, updated_at = ? WHERE workspace_id = ? AND id = ?').run(merged.name.trim() || 'Untitled Database', merged.description, merged.embeddingModelId ?? null, merged.updatedAt, workspaceId, databaseId);
|
|
170
|
+
return getDatabase(workspaceId, databaseId);
|
|
171
|
+
}
|
|
172
|
+
export function deleteDatabase(workspaceId, databaseId) {
|
|
173
|
+
const database = openDb();
|
|
174
|
+
database.prepare('DELETE FROM doc_nodes WHERE workspace_id = ? AND database_id = ?').run(workspaceId, databaseId);
|
|
175
|
+
database.prepare('DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ?').run(workspaceId, databaseId);
|
|
176
|
+
const result = database.prepare('DELETE FROM databases WHERE workspace_id = ? AND id = ?').run(workspaceId, databaseId);
|
|
177
|
+
if (result.changes > 0 && listDatabases(workspaceId).length === 0)
|
|
178
|
+
getDefaultDatabase(workspaceId);
|
|
179
|
+
return result.changes > 0;
|
|
180
|
+
}
|
|
181
|
+
export function listNodes(workspaceId, databaseId) {
|
|
182
|
+
const database = openDb();
|
|
183
|
+
const activeDatabaseId = databaseId ?? getDefaultDatabase(workspaceId).id;
|
|
184
|
+
const rows = database.prepare('SELECT * FROM doc_nodes WHERE workspace_id = ? AND database_id = ? ORDER BY created_at ASC').all(workspaceId, activeDatabaseId);
|
|
185
|
+
return rows.map(rowToNode);
|
|
186
|
+
}
|
|
187
|
+
export function getNode(workspaceId, nodeId, databaseId) {
|
|
188
|
+
const database = openDb();
|
|
189
|
+
const row = databaseId
|
|
190
|
+
? database.prepare('SELECT * FROM doc_nodes WHERE workspace_id = ? AND database_id = ? AND id = ?').get(workspaceId, databaseId, nodeId)
|
|
191
|
+
: database.prepare('SELECT * FROM doc_nodes WHERE workspace_id = ? AND id = ?').get(workspaceId, nodeId);
|
|
192
|
+
return row ? rowToNode(row) : null;
|
|
193
|
+
}
|
|
194
|
+
export function createNode(workspaceId, node) {
|
|
195
|
+
const database = openDb();
|
|
196
|
+
const databaseId = node.databaseId || getDefaultDatabase(workspaceId).id;
|
|
197
|
+
if (!getDatabase(workspaceId, databaseId))
|
|
198
|
+
throw new Error(`Database not found: ${databaseId}`);
|
|
199
|
+
const id = node.id || uuid();
|
|
200
|
+
const now = Date.now();
|
|
201
|
+
database.prepare(`INSERT INTO doc_nodes (id, workspace_id, database_id, title, icon, cover, content, parent_id, is_trash, created_at, updated_at)
|
|
202
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, workspaceId, databaseId, node.title || 'Untitled Document', node.icon || '\u{1F4DD}', node.cover || '', node.content || '', node.parentId ?? null, node.isTrash ? 1 : 0, node.createdAt || now, node.updatedAt || now);
|
|
203
|
+
return getNode(workspaceId, id, databaseId);
|
|
204
|
+
}
|
|
205
|
+
export function updateNode(workspaceId, nodeId, updates, databaseId) {
|
|
206
|
+
const existing = getNode(workspaceId, nodeId, databaseId);
|
|
207
|
+
if (!existing)
|
|
208
|
+
return null;
|
|
209
|
+
const database = openDb();
|
|
210
|
+
const merged = { ...existing, ...updates, updatedAt: Date.now() };
|
|
211
|
+
if (Object.hasOwn(updates, 'content') && merged.content !== existing.content) {
|
|
212
|
+
insertNodeVersion(database, workspaceId, existing, merged.content);
|
|
213
|
+
}
|
|
214
|
+
database.prepare(`UPDATE doc_nodes SET title = ?, icon = ?, cover = ?, content = ?, parent_id = ?, is_trash = ?, updated_at = ?
|
|
215
|
+
WHERE workspace_id = ? AND database_id = ? AND id = ?`).run(merged.title, merged.icon, merged.cover, merged.content, merged.parentId, merged.isTrash ? 1 : 0, merged.updatedAt, workspaceId, existing.databaseId, nodeId);
|
|
216
|
+
return getNode(workspaceId, nodeId, existing.databaseId);
|
|
217
|
+
}
|
|
218
|
+
export function listNodeVersions(workspaceId, nodeId, databaseId, limit = 50) {
|
|
219
|
+
const node = getNode(workspaceId, nodeId, databaseId);
|
|
220
|
+
if (!node)
|
|
221
|
+
return [];
|
|
222
|
+
const database = openDb();
|
|
223
|
+
const normalizedLimit = Number.isFinite(limit) ? Math.max(1, Math.min(100, Math.trunc(limit))) : 50;
|
|
224
|
+
const rows = database.prepare(`SELECT * FROM doc_node_versions
|
|
225
|
+
WHERE workspace_id = ? AND database_id = ? AND node_id = ?
|
|
226
|
+
ORDER BY created_at DESC
|
|
227
|
+
LIMIT ?`).all(workspaceId, node.databaseId, nodeId, normalizedLimit);
|
|
228
|
+
const stored = rows.map(rowToVersionRow);
|
|
229
|
+
let after = node.content;
|
|
230
|
+
return stored.map((item) => {
|
|
231
|
+
const before = applyReversePatch(after, item.patch);
|
|
232
|
+
const version = {
|
|
233
|
+
id: item.id,
|
|
234
|
+
nodeId: item.nodeId,
|
|
235
|
+
databaseId: item.databaseId,
|
|
236
|
+
title: item.title,
|
|
237
|
+
patch: item.patch,
|
|
238
|
+
oldContent: before,
|
|
239
|
+
newContent: after,
|
|
240
|
+
createdAt: item.createdAt,
|
|
241
|
+
};
|
|
242
|
+
after = before;
|
|
243
|
+
return version;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
export function deleteNode(workspaceId, nodeId, databaseId) {
|
|
247
|
+
const database = openDb();
|
|
248
|
+
const existing = getNode(workspaceId, nodeId, databaseId);
|
|
249
|
+
if (!existing)
|
|
250
|
+
return false;
|
|
251
|
+
database.prepare('DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ? AND node_id = ?')
|
|
252
|
+
.run(workspaceId, existing.databaseId, nodeId);
|
|
253
|
+
database.prepare('DELETE FROM doc_node_versions WHERE workspace_id = ? AND database_id = ? AND node_id = ?')
|
|
254
|
+
.run(workspaceId, existing.databaseId, nodeId);
|
|
255
|
+
const result = database.prepare('DELETE FROM doc_nodes WHERE workspace_id = ? AND database_id = ? AND id = ?').run(workspaceId, existing.databaseId, nodeId);
|
|
256
|
+
return result.changes > 0;
|
|
257
|
+
}
|
|
258
|
+
function insertNodeVersion(database, workspaceId, existing, nextContent) {
|
|
259
|
+
const patch = createContentPatch(existing.content, nextContent);
|
|
260
|
+
database.prepare(`INSERT INTO doc_node_versions
|
|
261
|
+
(id, workspace_id, database_id, node_id, title, patch_json, old_hash, new_hash, created_at)
|
|
262
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(uuid(), workspaceId, existing.databaseId, existing.id, existing.title, JSON.stringify(patch), hashContent(existing.content), hashContent(nextContent), Date.now());
|
|
263
|
+
}
|
|
264
|
+
function createContentPatch(oldContent, newContent) {
|
|
265
|
+
let start = 0;
|
|
266
|
+
while (start < oldContent.length
|
|
267
|
+
&& start < newContent.length
|
|
268
|
+
&& oldContent[start] === newContent[start]) {
|
|
269
|
+
start++;
|
|
270
|
+
}
|
|
271
|
+
let oldEnd = oldContent.length;
|
|
272
|
+
let newEnd = newContent.length;
|
|
273
|
+
while (oldEnd > start
|
|
274
|
+
&& newEnd > start
|
|
275
|
+
&& oldContent[oldEnd - 1] === newContent[newEnd - 1]) {
|
|
276
|
+
oldEnd--;
|
|
277
|
+
newEnd--;
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
start,
|
|
281
|
+
deleteText: oldContent.slice(start, oldEnd),
|
|
282
|
+
insertText: newContent.slice(start, newEnd),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function applyReversePatch(content, patch) {
|
|
286
|
+
const insertEnd = patch.start + patch.insertText.length;
|
|
287
|
+
return `${content.slice(0, patch.start)}${patch.deleteText}${content.slice(insertEnd)}`;
|
|
288
|
+
}
|
|
289
|
+
function hashContent(content) {
|
|
290
|
+
return createHash('sha256').update(content).digest('hex');
|
|
291
|
+
}
|
|
292
|
+
export function moveNode(workspaceId, nodeId, newParentId, databaseId) {
|
|
293
|
+
return updateNode(workspaceId, nodeId, { parentId: newParentId }, databaseId);
|
|
294
|
+
}
|
|
295
|
+
export function trashNode(workspaceId, nodeId, databaseId) {
|
|
296
|
+
return updateNode(workspaceId, nodeId, { isTrash: true }, databaseId);
|
|
297
|
+
}
|
|
298
|
+
export function restoreNode(workspaceId, nodeId, databaseId) {
|
|
299
|
+
const node = getNode(workspaceId, nodeId, databaseId);
|
|
300
|
+
if (!node)
|
|
301
|
+
return null;
|
|
302
|
+
if (node.parentId) {
|
|
303
|
+
const parent = getNode(workspaceId, node.parentId, node.databaseId);
|
|
304
|
+
if (parent && parent.isTrash) {
|
|
305
|
+
return updateNode(workspaceId, nodeId, { isTrash: false, parentId: null }, node.databaseId);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return updateNode(workspaceId, nodeId, { isTrash: false }, node.databaseId);
|
|
309
|
+
}
|
|
310
|
+
export function getVectorStats(workspaceId, databaseId) {
|
|
311
|
+
const database = openDb();
|
|
312
|
+
const meta = getDatabase(workspaceId, databaseId);
|
|
313
|
+
const indexed = database.prepare('SELECT COUNT(*) AS count, MAX(updated_at) AS last_indexed_at FROM database_embeddings WHERE workspace_id = ? AND database_id = ?').get(workspaceId, databaseId);
|
|
314
|
+
const nodes = database.prepare('SELECT COUNT(*) AS count FROM doc_nodes WHERE workspace_id = ? AND database_id = ? AND is_trash = 0').get(workspaceId, databaseId);
|
|
315
|
+
return {
|
|
316
|
+
databaseId,
|
|
317
|
+
embeddingModelId: meta?.embeddingModelId ?? null,
|
|
318
|
+
indexedCount: indexed.count,
|
|
319
|
+
nodeCount: nodes.count,
|
|
320
|
+
lastIndexedAt: indexed.last_indexed_at,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
export function setDatabaseEmbeddingModel(workspaceId, databaseId, embeddingModelId) {
|
|
324
|
+
return updateDatabase(workspaceId, databaseId, { embeddingModelId: embeddingModelId ?? undefined });
|
|
325
|
+
}
|
|
326
|
+
export function upsertDatabaseEmbedding(workspaceId, databaseId, record) {
|
|
327
|
+
const database = openDb();
|
|
328
|
+
database.prepare(`INSERT INTO database_embeddings
|
|
329
|
+
(workspace_id, database_id, node_id, title, path, content, content_hash, embedding, model_id, agent_id, updated_at)
|
|
330
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
331
|
+
ON CONFLICT(workspace_id, database_id, node_id) DO UPDATE SET
|
|
332
|
+
title = excluded.title,
|
|
333
|
+
path = excluded.path,
|
|
334
|
+
content = excluded.content,
|
|
335
|
+
content_hash = excluded.content_hash,
|
|
336
|
+
embedding = excluded.embedding,
|
|
337
|
+
model_id = excluded.model_id,
|
|
338
|
+
agent_id = excluded.agent_id,
|
|
339
|
+
updated_at = excluded.updated_at`).run(workspaceId, databaseId, record.nodeId, record.title, record.path, record.content, record.contentHash, JSON.stringify(record.embedding), record.modelId, record.agentId, Date.now());
|
|
340
|
+
}
|
|
341
|
+
export function deleteStaleDatabaseEmbeddings(workspaceId, databaseId, activeNodeIds) {
|
|
342
|
+
const database = openDb();
|
|
343
|
+
if (activeNodeIds.length === 0) {
|
|
344
|
+
const result = database.prepare('DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ?')
|
|
345
|
+
.run(workspaceId, databaseId);
|
|
346
|
+
return result.changes;
|
|
347
|
+
}
|
|
348
|
+
const placeholders = activeNodeIds.map(() => '?').join(',');
|
|
349
|
+
const result = database.prepare(`DELETE FROM database_embeddings WHERE workspace_id = ? AND database_id = ? AND node_id NOT IN (${placeholders})`).run(workspaceId, databaseId, ...activeNodeIds);
|
|
350
|
+
return result.changes;
|
|
351
|
+
}
|
|
352
|
+
export function listDatabaseEmbeddings(workspaceId, databaseId) {
|
|
353
|
+
const database = openDb();
|
|
354
|
+
const rows = database.prepare('SELECT node_id, title, path, content, embedding, updated_at FROM database_embeddings WHERE workspace_id = ? AND database_id = ?').all(workspaceId, databaseId);
|
|
355
|
+
return rows.map((row) => ({
|
|
356
|
+
nodeId: row.node_id,
|
|
357
|
+
title: row.title,
|
|
358
|
+
path: row.path,
|
|
359
|
+
content: row.content,
|
|
360
|
+
score: 0,
|
|
361
|
+
updatedAt: row.updated_at,
|
|
362
|
+
embedding: JSON.parse(row.embedding),
|
|
363
|
+
}));
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=database-store.js.map
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
3
|
+
import { v4 as uuid } from 'uuid';
|
|
4
|
+
import { getDataDir, ensureDir } from './json-store.js';
|
|
5
|
+
let db = null;
|
|
6
|
+
function openDb() {
|
|
7
|
+
if (db)
|
|
8
|
+
return db;
|
|
9
|
+
const dir = join(getDataDir(), 'kanban');
|
|
10
|
+
ensureDir(dir);
|
|
11
|
+
db = new DatabaseSync(join(dir, 'kanban.sqlite'));
|
|
12
|
+
db.exec(`
|
|
13
|
+
CREATE TABLE IF NOT EXISTS kanban_boards (
|
|
14
|
+
id TEXT PRIMARY KEY,
|
|
15
|
+
workspace_id TEXT NOT NULL,
|
|
16
|
+
title TEXT NOT NULL DEFAULT 'Kanban Board',
|
|
17
|
+
layout_mode TEXT NOT NULL DEFAULT 'horizontal',
|
|
18
|
+
created_at INTEGER NOT NULL,
|
|
19
|
+
updated_at INTEGER NOT NULL
|
|
20
|
+
);
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_kanban_boards_workspace ON kanban_boards(workspace_id);
|
|
22
|
+
CREATE TABLE IF NOT EXISTS kanban_columns (
|
|
23
|
+
id TEXT PRIMARY KEY,
|
|
24
|
+
board_id TEXT NOT NULL,
|
|
25
|
+
title TEXT NOT NULL,
|
|
26
|
+
color TEXT NOT NULL DEFAULT 'sky',
|
|
27
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
28
|
+
FOREIGN KEY (board_id) REFERENCES kanban_boards(id) ON DELETE CASCADE
|
|
29
|
+
);
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_kanban_columns_board ON kanban_columns(board_id);
|
|
31
|
+
CREATE TABLE IF NOT EXISTS kanban_tasks (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
board_id TEXT NOT NULL,
|
|
34
|
+
column_id TEXT NOT NULL,
|
|
35
|
+
title TEXT NOT NULL,
|
|
36
|
+
description TEXT NOT NULL DEFAULT '',
|
|
37
|
+
priority TEXT NOT NULL DEFAULT 'medium',
|
|
38
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
39
|
+
due_date TEXT,
|
|
40
|
+
created_at INTEGER NOT NULL,
|
|
41
|
+
FOREIGN KEY (board_id) REFERENCES kanban_boards(id) ON DELETE CASCADE
|
|
42
|
+
);
|
|
43
|
+
CREATE INDEX IF NOT EXISTS idx_kanban_tasks_board ON kanban_tasks(board_id);
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_kanban_tasks_column ON kanban_tasks(column_id);
|
|
45
|
+
`);
|
|
46
|
+
return db;
|
|
47
|
+
}
|
|
48
|
+
export function getBoard(workspaceId) {
|
|
49
|
+
const database = openDb();
|
|
50
|
+
const row = database.prepare('SELECT * FROM kanban_boards WHERE workspace_id = ? ORDER BY updated_at DESC').get(workspaceId);
|
|
51
|
+
if (!row)
|
|
52
|
+
return null;
|
|
53
|
+
return hydrateBoard(workspaceId, row);
|
|
54
|
+
}
|
|
55
|
+
export function listBoards(workspaceId) {
|
|
56
|
+
const database = openDb();
|
|
57
|
+
const rows = database.prepare('SELECT * FROM kanban_boards WHERE workspace_id = ? ORDER BY updated_at DESC').all(workspaceId);
|
|
58
|
+
return rows.map((row) => hydrateBoard(workspaceId, row));
|
|
59
|
+
}
|
|
60
|
+
function hydrateBoard(workspaceId, row) {
|
|
61
|
+
const database = openDb();
|
|
62
|
+
const boardId = row.id;
|
|
63
|
+
const columns = database.prepare('SELECT * FROM kanban_columns WHERE board_id = ? ORDER BY sort_order ASC').all(boardId).map(r => ({
|
|
64
|
+
id: r.id,
|
|
65
|
+
title: r.title,
|
|
66
|
+
color: r.color,
|
|
67
|
+
order: r.sort_order,
|
|
68
|
+
}));
|
|
69
|
+
const tasks = database.prepare('SELECT * FROM kanban_tasks WHERE board_id = ? ORDER BY sort_order ASC').all(boardId).map(r => ({
|
|
70
|
+
id: r.id,
|
|
71
|
+
title: r.title,
|
|
72
|
+
description: r.description,
|
|
73
|
+
priority: r.priority,
|
|
74
|
+
columnId: r.column_id,
|
|
75
|
+
order: r.sort_order,
|
|
76
|
+
createdAt: r.created_at,
|
|
77
|
+
dueDate: r.due_date || undefined,
|
|
78
|
+
}));
|
|
79
|
+
return {
|
|
80
|
+
id: boardId,
|
|
81
|
+
workspaceId,
|
|
82
|
+
title: row.title,
|
|
83
|
+
layoutMode: row.layout_mode || 'horizontal',
|
|
84
|
+
columns,
|
|
85
|
+
tasks,
|
|
86
|
+
createdAt: row.created_at,
|
|
87
|
+
updatedAt: row.updated_at,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export function createBoard(workspaceId, title) {
|
|
91
|
+
const database = openDb();
|
|
92
|
+
const id = uuid();
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
database.prepare('INSERT INTO kanban_boards (id, workspace_id, title, layout_mode, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)').run(id, workspaceId, title || 'Kanban Board', 'horizontal', now, now);
|
|
95
|
+
return { id, workspaceId, title: title || 'Kanban Board', layoutMode: 'horizontal', columns: [], tasks: [], createdAt: now, updatedAt: now };
|
|
96
|
+
}
|
|
97
|
+
export function updateBoard(workspaceId, updates, boardId) {
|
|
98
|
+
let board = boardId ? listBoards(workspaceId).find((item) => item.id === boardId) ?? null : getBoard(workspaceId);
|
|
99
|
+
if (!board)
|
|
100
|
+
return null;
|
|
101
|
+
const database = openDb();
|
|
102
|
+
const now = Date.now();
|
|
103
|
+
if (updates.title !== undefined) {
|
|
104
|
+
database.prepare('UPDATE kanban_boards SET title = ?, updated_at = ? WHERE workspace_id = ? AND id = ?').run(updates.title, now, workspaceId, board.id);
|
|
105
|
+
}
|
|
106
|
+
if (updates.layoutMode !== undefined) {
|
|
107
|
+
database.prepare('UPDATE kanban_boards SET layout_mode = ?, updated_at = ? WHERE workspace_id = ? AND id = ?').run(updates.layoutMode, now, workspaceId, board.id);
|
|
108
|
+
}
|
|
109
|
+
return (boardId ? listBoards(workspaceId).find((item) => item.id === board.id) : getBoard(workspaceId)) ?? null;
|
|
110
|
+
}
|
|
111
|
+
export function deleteBoard(workspaceId, boardId) {
|
|
112
|
+
const database = openDb();
|
|
113
|
+
const board = boardId
|
|
114
|
+
? database.prepare('SELECT * FROM kanban_boards WHERE workspace_id = ? AND id = ?').get(workspaceId, boardId)
|
|
115
|
+
: database.prepare('SELECT * FROM kanban_boards WHERE workspace_id = ?').get(workspaceId);
|
|
116
|
+
if (!board)
|
|
117
|
+
return false;
|
|
118
|
+
const id = board.id;
|
|
119
|
+
database.prepare('DELETE FROM kanban_tasks WHERE board_id = ?').run(id);
|
|
120
|
+
database.prepare('DELETE FROM kanban_columns WHERE board_id = ?').run(id);
|
|
121
|
+
database.prepare('DELETE FROM kanban_boards WHERE id = ? AND workspace_id = ?').run(id, workspaceId);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
export function saveColumns(boardId, columns) {
|
|
125
|
+
const database = openDb();
|
|
126
|
+
database.prepare('DELETE FROM kanban_columns WHERE board_id = ?').run(boardId);
|
|
127
|
+
const stmt = database.prepare('INSERT INTO kanban_columns (id, board_id, title, color, sort_order) VALUES (?, ?, ?, ?, ?)');
|
|
128
|
+
for (const col of columns) {
|
|
129
|
+
stmt.run(col.id, boardId, col.title, col.color, col.order);
|
|
130
|
+
}
|
|
131
|
+
database.prepare('UPDATE kanban_boards SET updated_at = ? WHERE id = ?').run(Date.now(), boardId);
|
|
132
|
+
}
|
|
133
|
+
export function saveTasks(boardId, tasks) {
|
|
134
|
+
const database = openDb();
|
|
135
|
+
database.prepare('DELETE FROM kanban_tasks WHERE board_id = ?').run(boardId);
|
|
136
|
+
const stmt = database.prepare('INSERT INTO kanban_tasks (id, board_id, column_id, title, description, priority, sort_order, due_date, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
|
137
|
+
for (const task of tasks) {
|
|
138
|
+
stmt.run(task.id, boardId, task.columnId, task.title, task.description, task.priority, task.order, task.dueDate || null, task.createdAt);
|
|
139
|
+
}
|
|
140
|
+
database.prepare('UPDATE kanban_boards SET updated_at = ? WHERE id = ?').run(Date.now(), boardId);
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=kanban-store.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { readJsonFile, writeJsonFile, getDataDir } from './json-store.js';
|
|
3
|
+
const FILE = () => join(getDataDir(), 'robot-accounts.json');
|
|
4
|
+
function read() {
|
|
5
|
+
return readJsonFile(FILE()) ?? { accounts: [] };
|
|
6
|
+
}
|
|
7
|
+
function write(data) {
|
|
8
|
+
writeJsonFile(FILE(), data);
|
|
9
|
+
}
|
|
10
|
+
export function listRobotAccounts() {
|
|
11
|
+
return read().accounts;
|
|
12
|
+
}
|
|
13
|
+
export function getRobotAccount(id) {
|
|
14
|
+
return read().accounts.find((a) => a.id === id);
|
|
15
|
+
}
|
|
16
|
+
export function createRobotAccount(account) {
|
|
17
|
+
const data = read();
|
|
18
|
+
data.accounts.push(account);
|
|
19
|
+
write(data);
|
|
20
|
+
}
|
|
21
|
+
export function updateRobotAccount(id, patch) {
|
|
22
|
+
const data = read();
|
|
23
|
+
const idx = data.accounts.findIndex((a) => a.id === id);
|
|
24
|
+
if (idx === -1)
|
|
25
|
+
return null;
|
|
26
|
+
data.accounts[idx] = { ...data.accounts[idx], ...patch, id, updatedAt: new Date().toISOString() };
|
|
27
|
+
write(data);
|
|
28
|
+
return data.accounts[idx];
|
|
29
|
+
}
|
|
30
|
+
export function deleteRobotAccount(id) {
|
|
31
|
+
const data = read();
|
|
32
|
+
const before = data.accounts.length;
|
|
33
|
+
data.accounts = data.accounts.filter((a) => a.id !== id);
|
|
34
|
+
if (data.accounts.length === before)
|
|
35
|
+
return false;
|
|
36
|
+
write(data);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=robot-account-store.js.map
|