@goondocks/myco 0.20.2 → 0.21.1
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/bin/myco-run +68 -7
- package/dist/agent-eval-YK2VP2S4.js +356 -0
- package/dist/agent-eval-YK2VP2S4.js.map +1 -0
- package/dist/{agent-run-X25Q2A6T.js → agent-run-GEJBD2YD.js} +10 -8
- package/dist/{agent-run-X25Q2A6T.js.map → agent-run-GEJBD2YD.js.map} +1 -1
- package/dist/{agent-tasks-7B6OFERB.js → agent-tasks-5XSRGTRX.js} +10 -8
- package/dist/{agent-tasks-7B6OFERB.js.map → agent-tasks-5XSRGTRX.js.map} +1 -1
- package/dist/{chunk-OD4AA7PV.js → chunk-53RPGOEN.js} +56 -8
- package/dist/chunk-53RPGOEN.js.map +1 -0
- package/dist/chunk-54SXG5HF.js +26 -0
- package/dist/chunk-54SXG5HF.js.map +1 -0
- package/dist/{chunk-XATDZX7U.js → chunk-6ALVMIB4.js} +19 -5
- package/dist/{chunk-XATDZX7U.js.map → chunk-6ALVMIB4.js.map} +1 -1
- package/dist/{chunk-FLLBJLHM.js → chunk-6C6QZ4PM.js} +9 -5
- package/dist/chunk-6C6QZ4PM.js.map +1 -0
- package/dist/{chunk-CCRGY3QW.js → chunk-AUIXX33A.js} +24 -95
- package/dist/chunk-AUIXX33A.js.map +1 -0
- package/dist/chunk-CISWUP5W.js +101 -0
- package/dist/chunk-CISWUP5W.js.map +1 -0
- package/dist/{chunk-MYOZLMB2.js → chunk-DTWUHHFI.js} +576 -20
- package/dist/chunk-DTWUHHFI.js.map +1 -0
- package/dist/chunk-EEOJWLMP.js +582 -0
- package/dist/chunk-EEOJWLMP.js.map +1 -0
- package/dist/{chunk-XG5RRUYF.js → chunk-ENZR5NG7.js} +2 -2
- package/dist/{chunk-6RFZWV4R.js → chunk-FCJ5JV54.js} +1 -1
- package/dist/{chunk-6RFZWV4R.js.map → chunk-FCJ5JV54.js.map} +1 -1
- package/dist/{chunk-US4LNCAT.js → chunk-IPPMYQ2Y.js} +5 -1
- package/dist/chunk-IPPMYQ2Y.js.map +1 -0
- package/dist/{chunk-VVNL26WX.js → chunk-KTTSXYEK.js} +22 -10
- package/dist/chunk-KTTSXYEK.js.map +1 -0
- package/dist/chunk-LQIPXVDH.js +17 -0
- package/dist/chunk-LQIPXVDH.js.map +1 -0
- package/dist/{chunk-DCSGJ7W4.js → chunk-N2DGFACQ.js} +3 -3
- package/dist/chunk-N7Z3LUEZ.js +858 -0
- package/dist/chunk-N7Z3LUEZ.js.map +1 -0
- package/dist/{chunk-2PDWCDKY.js → chunk-NFO7BRCO.js} +10 -7
- package/dist/{chunk-2PDWCDKY.js.map → chunk-NFO7BRCO.js.map} +1 -1
- package/dist/{chunk-Q36VMZST.js → chunk-OTQH5KZW.js} +89 -38
- package/dist/chunk-OTQH5KZW.js.map +1 -0
- package/dist/chunk-OUJSQSKE.js +113 -0
- package/dist/chunk-OUJSQSKE.js.map +1 -0
- package/dist/chunk-OZ3FBAK5.js +50 -0
- package/dist/chunk-OZ3FBAK5.js.map +1 -0
- package/dist/chunk-QATYARI5.js +408 -0
- package/dist/chunk-QATYARI5.js.map +1 -0
- package/dist/{chunk-KESLPBKV.js → chunk-QDLVIW2O.js} +4 -4
- package/dist/{chunk-5XIVBO25.js → chunk-QLLBJEM7.js} +6 -2
- package/dist/chunk-QLLBJEM7.js.map +1 -0
- package/dist/{chunk-EVDQKYCG.js → chunk-RQSJLWP4.js} +13 -2
- package/dist/chunk-RQSJLWP4.js.map +1 -0
- package/dist/{chunk-BPRIYNLE.js → chunk-TKAJ3JVF.js} +3 -3
- package/dist/chunk-TSM6VESW.js +25 -0
- package/dist/chunk-TSM6VESW.js.map +1 -0
- package/dist/{chunk-6X2ERTQV.js → chunk-USVFEWYL.js} +6 -4
- package/dist/{chunk-6X2ERTQV.js.map → chunk-USVFEWYL.js.map} +1 -1
- package/dist/{chunk-JZGN33AY.js → chunk-VRI56337.js} +4 -4
- package/dist/chunk-X2IRGXGF.js +14103 -0
- package/dist/chunk-X2IRGXGF.js.map +1 -0
- package/dist/{chunk-FMRZ26U5.js → chunk-X3IGT5RV.js} +5 -2
- package/dist/{chunk-FMRZ26U5.js.map → chunk-X3IGT5RV.js.map} +1 -1
- package/dist/{chunk-KHT24OWC.js → chunk-YDUOSRGD.js} +8 -94
- package/dist/{chunk-KHT24OWC.js.map → chunk-YDUOSRGD.js.map} +1 -1
- package/dist/{chunk-NGROSFOH.js → chunk-Z66IT5KL.js} +14 -9
- package/dist/chunk-Z66IT5KL.js.map +1 -0
- package/dist/{cli-GGPWH4UO.js → cli-HSLIG7EX.js} +50 -43
- package/dist/cli-HSLIG7EX.js.map +1 -0
- package/dist/{client-YXQUTXVZ.js → client-Z43DNLJH.js} +4 -4
- package/dist/{config-OMCYHG2S.js → config-VC4ACP42.js} +6 -4
- package/dist/{config-OMCYHG2S.js.map → config-VC4ACP42.js.map} +1 -1
- package/dist/{detect-PXNM6TA7.js → detect-7NUD5B5R.js} +2 -2
- package/dist/{detect-providers-5KOPZ7J2.js → detect-providers-ILLQZROY.js} +4 -4
- package/dist/{doctor-5JXJ36KA.js → doctor-HJCWHAU4.js} +49 -16
- package/dist/doctor-HJCWHAU4.js.map +1 -0
- package/dist/executor-DO6QFC6G.js +45 -0
- package/dist/{init-LMYOVZAV.js → init-4KVK7W2E.js} +16 -14
- package/dist/{init-LMYOVZAV.js.map → init-4KVK7W2E.js.map} +1 -1
- package/dist/{installer-FS257JRZ.js → installer-N4UTEACX.js} +6 -4
- package/dist/{llm-TH4NLIRM.js → llm-AGVEF5XD.js} +5 -4
- package/dist/{loader-CQYTFHEW.js → loader-LX7TFRM6.js} +5 -3
- package/dist/{loader-NOMBJUPW.js → loader-UDNUMEDA.js} +5 -3
- package/dist/{main-YTBVRTBI.js → main-4J4QZZTZ.js} +2518 -656
- package/dist/main-4J4QZZTZ.js.map +1 -0
- package/dist/{open-HG2DX6RN.js → open-7TXJQM3H.js} +10 -8
- package/dist/{open-HG2DX6RN.js.map → open-7TXJQM3H.js.map} +1 -1
- package/dist/{post-compact-JSECI44W.js → post-compact-7AEFVCZS.js} +8 -8
- package/dist/{post-tool-use-POGPTJBA.js → post-tool-use-TZINWWDH.js} +11 -9
- package/dist/post-tool-use-TZINWWDH.js.map +1 -0
- package/dist/{post-tool-use-failure-OT7BFWQW.js → post-tool-use-failure-TCFEU2GI.js} +8 -8
- package/dist/{pre-compact-OXVODKH4.js → pre-compact-LO2VZCGR.js} +8 -8
- package/dist/{provider-check-43LAMSMH.js → provider-check-ZEV5P4KM.js} +4 -4
- package/dist/{registry-U4CHXK6R.js → registry-F3THYC5M.js} +6 -4
- package/dist/{remove-N7ZPELFU.js → remove-F77AAALE.js} +12 -10
- package/dist/{remove-N7ZPELFU.js.map → remove-F77AAALE.js.map} +1 -1
- package/dist/{restart-ADG5GBTB.js → restart-UEFDPMLT.js} +11 -9
- package/dist/{restart-ADG5GBTB.js.map → restart-UEFDPMLT.js.map} +1 -1
- package/dist/{search-AHZEUNRR.js → search-NHNVUAQQ.js} +11 -9
- package/dist/{search-AHZEUNRR.js.map → search-NHNVUAQQ.js.map} +1 -1
- package/dist/{server-AGVYZVP5.js → server-AZJSTQEK.js} +369 -270
- package/dist/server-AZJSTQEK.js.map +1 -0
- package/dist/{session-6IU4AXYP.js → session-3HLC5KOD.js} +11 -9
- package/dist/{session-6IU4AXYP.js.map → session-3HLC5KOD.js.map} +1 -1
- package/dist/{session-end-FT27DWYZ.js → session-end-FS46UARX.js} +7 -7
- package/dist/session-start-46KPFV2H.js +134 -0
- package/dist/session-start-46KPFV2H.js.map +1 -0
- package/dist/{setup-llm-77MP4I2G.js → setup-llm-JMWSNQ2C.js} +11 -9
- package/dist/{setup-llm-77MP4I2G.js.map → setup-llm-JMWSNQ2C.js.map} +1 -1
- package/dist/src/agent/definitions/agent.yaml +9 -5
- package/dist/src/agent/definitions/tasks/cortex-instructions.yaml +115 -0
- package/dist/src/agent/definitions/tasks/cortex-prompt-builder.yaml +67 -0
- package/dist/src/agent/definitions/tasks/digest-only.yaml +1 -1
- package/dist/src/agent/definitions/tasks/extract-only.yaml +1 -1
- package/dist/src/agent/definitions/tasks/review-session.yaml +10 -39
- package/dist/src/agent/definitions/tasks/skill-evolve.yaml +181 -25
- package/dist/src/agent/definitions/tasks/skill-generate.yaml +21 -7
- package/dist/src/agent/definitions/tasks/skill-survey.yaml +2 -6
- package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +1 -1
- package/dist/src/agent/definitions/tasks/title-summary.yaml +12 -19
- package/dist/src/agent/definitions/tasks/{full-intelligence.yaml → vault-evolve.yaml} +74 -129
- package/dist/src/agent/definitions/tasks/vault-seed.yaml +370 -0
- package/dist/src/agent/prompts/agent.md +12 -38
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/hooks/post-tool-use.js +1 -1
- package/dist/src/hooks/session-end.js +1 -1
- package/dist/src/hooks/session-start.js +1 -1
- package/dist/src/hooks/stop.js +1 -1
- package/dist/src/hooks/user-prompt-submit.js +1 -1
- package/dist/src/mcp/server.js +1 -1
- package/dist/src/symbionts/manifests/claude-code.yaml +4 -0
- package/dist/src/symbionts/manifests/opencode.yaml +7 -0
- package/dist/src/symbionts/manifests/pi.yaml +22 -0
- package/dist/src/symbionts/templates/agents-starter.md +1 -1
- package/dist/src/symbionts/templates/pi/package.json +6 -0
- package/dist/src/symbionts/templates/pi/plugin.ts +559 -0
- package/dist/{stats-NVPWOYTE.js → stats-MKMETHMA.js} +11 -9
- package/dist/{stats-NVPWOYTE.js.map → stats-MKMETHMA.js.map} +1 -1
- package/dist/{stop-ZPIKVLH4.js → stop-OUEX6KA4.js} +7 -7
- package/dist/{stop-failure-2PX67YJC.js → stop-failure-2BWVNZEG.js} +8 -8
- package/dist/{subagent-start-UUE6EHQD.js → subagent-start-J4VV6DEE.js} +8 -8
- package/dist/{subagent-stop-KQWWWPE6.js → subagent-stop-JMLVEPIA.js} +8 -8
- package/dist/{task-completed-WMHOFQ7B.js → task-completed-65CHMMKA.js} +8 -8
- package/dist/{team-LRZ6GTQK.js → team-U2LDKIS4.js} +7 -5
- package/dist/{turns-YFNI5CQC.js → turns-HU2CTZAP.js} +2 -2
- package/dist/ui/assets/index-BUGor9dk.js +842 -0
- package/dist/ui/assets/index-_OP4ifzH.css +1 -0
- package/dist/ui/index.html +2 -2
- package/dist/{update-O6V4RC4W.js → update-ZSHVXWSQ.js} +12 -10
- package/dist/{update-O6V4RC4W.js.map → update-ZSHVXWSQ.js.map} +1 -1
- package/dist/{user-prompt-submit-N36KUPHI.js → user-prompt-submit-APMO6FVU.js} +10 -9
- package/dist/{user-prompt-submit-N36KUPHI.js.map → user-prompt-submit-APMO6FVU.js.map} +1 -1
- package/dist/{verify-LXPV7NYG.js → verify-R76ZFJSZ.js} +8 -5
- package/dist/{verify-LXPV7NYG.js.map → verify-R76ZFJSZ.js.map} +1 -1
- package/dist/{version-XMPPJQHR.js → version-TXPPS3L5.js} +2 -2
- package/dist/version-TXPPS3L5.js.map +1 -0
- package/package.json +3 -1
- package/skills/myco/SKILL.md +16 -1
- package/skills/myco/references/cli-usage.md +1 -1
- package/skills/myco-rules/SKILL.md +94 -0
- package/skills/{rules → myco-rules}/references/rules-bad-example.md +1 -1
- package/skills/{rules → myco-rules}/references/rules-good-example.md +1 -1
- package/dist/chunk-4YFKBL3F.js +0 -195
- package/dist/chunk-4YFKBL3F.js.map +0 -1
- package/dist/chunk-5XIVBO25.js.map +0 -1
- package/dist/chunk-CCRGY3QW.js.map +0 -1
- package/dist/chunk-CUDIZJY7.js +0 -36
- package/dist/chunk-CUDIZJY7.js.map +0 -1
- package/dist/chunk-EVDQKYCG.js.map +0 -1
- package/dist/chunk-FLLBJLHM.js.map +0 -1
- package/dist/chunk-MYOZLMB2.js.map +0 -1
- package/dist/chunk-NGROSFOH.js.map +0 -1
- package/dist/chunk-OD4AA7PV.js.map +0 -1
- package/dist/chunk-Q36VMZST.js.map +0 -1
- package/dist/chunk-US4LNCAT.js.map +0 -1
- package/dist/chunk-UYMFCYBF.js +0 -2326
- package/dist/chunk-UYMFCYBF.js.map +0 -1
- package/dist/chunk-VVNL26WX.js.map +0 -1
- package/dist/cli-GGPWH4UO.js.map +0 -1
- package/dist/doctor-5JXJ36KA.js.map +0 -1
- package/dist/executor-HWW2QNZQ.js +0 -2472
- package/dist/executor-HWW2QNZQ.js.map +0 -1
- package/dist/main-YTBVRTBI.js.map +0 -1
- package/dist/post-tool-use-POGPTJBA.js.map +0 -1
- package/dist/server-AGVYZVP5.js.map +0 -1
- package/dist/session-start-LAFICHII.js +0 -189
- package/dist/session-start-LAFICHII.js.map +0 -1
- package/dist/src/agent/definitions/tasks/graph-maintenance.yaml +0 -93
- package/dist/ui/assets/index-C2JuNtRB.css +0 -1
- package/dist/ui/assets/index-JLVaQKV2.js +0 -832
- package/skills/myco-curate/SKILL.md +0 -86
- package/skills/rules/SKILL.md +0 -214
- /package/dist/{chunk-XG5RRUYF.js.map → chunk-ENZR5NG7.js.map} +0 -0
- /package/dist/{chunk-DCSGJ7W4.js.map → chunk-N2DGFACQ.js.map} +0 -0
- /package/dist/{chunk-KESLPBKV.js.map → chunk-QDLVIW2O.js.map} +0 -0
- /package/dist/{chunk-BPRIYNLE.js.map → chunk-TKAJ3JVF.js.map} +0 -0
- /package/dist/{chunk-JZGN33AY.js.map → chunk-VRI56337.js.map} +0 -0
- /package/dist/{client-YXQUTXVZ.js.map → client-Z43DNLJH.js.map} +0 -0
- /package/dist/{detect-PXNM6TA7.js.map → detect-7NUD5B5R.js.map} +0 -0
- /package/dist/{detect-providers-5KOPZ7J2.js.map → detect-providers-ILLQZROY.js.map} +0 -0
- /package/dist/{installer-FS257JRZ.js.map → executor-DO6QFC6G.js.map} +0 -0
- /package/dist/{llm-TH4NLIRM.js.map → installer-N4UTEACX.js.map} +0 -0
- /package/dist/{loader-CQYTFHEW.js.map → llm-AGVEF5XD.js.map} +0 -0
- /package/dist/{loader-NOMBJUPW.js.map → loader-LX7TFRM6.js.map} +0 -0
- /package/dist/{provider-check-43LAMSMH.js.map → loader-UDNUMEDA.js.map} +0 -0
- /package/dist/{post-compact-JSECI44W.js.map → post-compact-7AEFVCZS.js.map} +0 -0
- /package/dist/{post-tool-use-failure-OT7BFWQW.js.map → post-tool-use-failure-TCFEU2GI.js.map} +0 -0
- /package/dist/{pre-compact-OXVODKH4.js.map → pre-compact-LO2VZCGR.js.map} +0 -0
- /package/dist/{registry-U4CHXK6R.js.map → provider-check-ZEV5P4KM.js.map} +0 -0
- /package/dist/{team-LRZ6GTQK.js.map → registry-F3THYC5M.js.map} +0 -0
- /package/dist/{session-end-FT27DWYZ.js.map → session-end-FS46UARX.js.map} +0 -0
- /package/dist/{stop-ZPIKVLH4.js.map → stop-OUEX6KA4.js.map} +0 -0
- /package/dist/{stop-failure-2PX67YJC.js.map → stop-failure-2BWVNZEG.js.map} +0 -0
- /package/dist/{subagent-start-UUE6EHQD.js.map → subagent-start-J4VV6DEE.js.map} +0 -0
- /package/dist/{subagent-stop-KQWWWPE6.js.map → subagent-stop-JMLVEPIA.js.map} +0 -0
- /package/dist/{task-completed-WMHOFQ7B.js.map → task-completed-65CHMMKA.js.map} +0 -0
- /package/dist/{turns-YFNI5CQC.js.map → team-U2LDKIS4.js.map} +0 -0
- /package/dist/{version-XMPPJQHR.js.map → turns-HU2CTZAP.js.map} +0 -0
package/dist/chunk-4YFKBL3F.js
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
getTeamMachineId,
|
|
4
|
-
syncRow
|
|
5
|
-
} from "./chunk-EVDQKYCG.js";
|
|
6
|
-
import {
|
|
7
|
-
getDatabase
|
|
8
|
-
} from "./chunk-MYX5NCRH.js";
|
|
9
|
-
|
|
10
|
-
// src/db/queries/spores.ts
|
|
11
|
-
var DEFAULT_LIST_LIMIT = 100;
|
|
12
|
-
var DEFAULT_STATUS = "active";
|
|
13
|
-
var DEFAULT_IMPORTANCE = 5;
|
|
14
|
-
var SPORE_COLUMNS = [
|
|
15
|
-
"id",
|
|
16
|
-
"agent_id",
|
|
17
|
-
"session_id",
|
|
18
|
-
"prompt_batch_id",
|
|
19
|
-
"observation_type",
|
|
20
|
-
"status",
|
|
21
|
-
"content",
|
|
22
|
-
"context",
|
|
23
|
-
"importance",
|
|
24
|
-
"file_path",
|
|
25
|
-
"tags",
|
|
26
|
-
"content_hash",
|
|
27
|
-
"properties",
|
|
28
|
-
"embedded",
|
|
29
|
-
"created_at",
|
|
30
|
-
"updated_at",
|
|
31
|
-
"machine_id",
|
|
32
|
-
"synced_at"
|
|
33
|
-
];
|
|
34
|
-
var SELECT_COLUMNS = SPORE_COLUMNS.join(", ");
|
|
35
|
-
function toSporeRow(row) {
|
|
36
|
-
return {
|
|
37
|
-
id: row.id,
|
|
38
|
-
agent_id: row.agent_id,
|
|
39
|
-
session_id: row.session_id ?? null,
|
|
40
|
-
prompt_batch_id: row.prompt_batch_id ?? null,
|
|
41
|
-
observation_type: row.observation_type,
|
|
42
|
-
status: row.status,
|
|
43
|
-
content: row.content,
|
|
44
|
-
context: row.context ?? null,
|
|
45
|
-
importance: row.importance,
|
|
46
|
-
file_path: row.file_path ?? null,
|
|
47
|
-
tags: row.tags ?? null,
|
|
48
|
-
content_hash: row.content_hash ?? null,
|
|
49
|
-
properties: row.properties ?? null,
|
|
50
|
-
embedded: row.embedded ?? 0,
|
|
51
|
-
created_at: row.created_at,
|
|
52
|
-
updated_at: row.updated_at ?? null,
|
|
53
|
-
machine_id: row.machine_id ?? "local",
|
|
54
|
-
synced_at: row.synced_at ?? null
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function insertSpore(data) {
|
|
58
|
-
const db = getDatabase();
|
|
59
|
-
db.prepare(
|
|
60
|
-
`INSERT INTO spores (
|
|
61
|
-
id, agent_id, session_id, prompt_batch_id,
|
|
62
|
-
observation_type, status, content, context,
|
|
63
|
-
importance, file_path, tags, content_hash,
|
|
64
|
-
properties, created_at, updated_at, machine_id
|
|
65
|
-
) VALUES (
|
|
66
|
-
?, ?, ?, ?,
|
|
67
|
-
?, ?, ?, ?,
|
|
68
|
-
?, ?, ?, ?,
|
|
69
|
-
?, ?, ?, ?
|
|
70
|
-
)`
|
|
71
|
-
).run(
|
|
72
|
-
data.id,
|
|
73
|
-
data.agent_id,
|
|
74
|
-
data.session_id ?? null,
|
|
75
|
-
data.prompt_batch_id ?? null,
|
|
76
|
-
data.observation_type,
|
|
77
|
-
data.status ?? DEFAULT_STATUS,
|
|
78
|
-
data.content,
|
|
79
|
-
data.context ?? null,
|
|
80
|
-
data.importance ?? DEFAULT_IMPORTANCE,
|
|
81
|
-
data.file_path ?? null,
|
|
82
|
-
data.tags ?? null,
|
|
83
|
-
data.content_hash ?? null,
|
|
84
|
-
data.properties ?? null,
|
|
85
|
-
data.created_at,
|
|
86
|
-
data.updated_at ?? null,
|
|
87
|
-
data.machine_id ?? getTeamMachineId()
|
|
88
|
-
);
|
|
89
|
-
const row = toSporeRow(
|
|
90
|
-
db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(data.id)
|
|
91
|
-
);
|
|
92
|
-
syncRow("spores", row);
|
|
93
|
-
return row;
|
|
94
|
-
}
|
|
95
|
-
function getSpore(id) {
|
|
96
|
-
const db = getDatabase();
|
|
97
|
-
const row = db.prepare(
|
|
98
|
-
`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`
|
|
99
|
-
).get(id);
|
|
100
|
-
if (!row) return null;
|
|
101
|
-
return toSporeRow(row);
|
|
102
|
-
}
|
|
103
|
-
function buildSporeWhere(options) {
|
|
104
|
-
const conditions = [];
|
|
105
|
-
const params = [];
|
|
106
|
-
if (options.agent_id !== void 0) {
|
|
107
|
-
conditions.push(`agent_id = ?`);
|
|
108
|
-
params.push(options.agent_id);
|
|
109
|
-
}
|
|
110
|
-
if (options.observation_type !== void 0) {
|
|
111
|
-
conditions.push(`observation_type = ?`);
|
|
112
|
-
params.push(options.observation_type);
|
|
113
|
-
}
|
|
114
|
-
if (options.status !== void 0) {
|
|
115
|
-
conditions.push(`status = ?`);
|
|
116
|
-
params.push(options.status);
|
|
117
|
-
}
|
|
118
|
-
if (options.session_id !== void 0) {
|
|
119
|
-
conditions.push(`session_id = ?`);
|
|
120
|
-
params.push(options.session_id);
|
|
121
|
-
}
|
|
122
|
-
if (options.search !== void 0 && options.search.length > 0) {
|
|
123
|
-
conditions.push(`(content LIKE ? OR observation_type LIKE ?)`);
|
|
124
|
-
const pattern = `%${options.search}%`;
|
|
125
|
-
params.push(pattern, pattern);
|
|
126
|
-
}
|
|
127
|
-
if (options.since !== void 0) {
|
|
128
|
-
conditions.push("created_at > ?");
|
|
129
|
-
params.push(options.since);
|
|
130
|
-
}
|
|
131
|
-
if (options.includeActive === false && options.session_id === void 0) {
|
|
132
|
-
conditions.push(
|
|
133
|
-
`(session_id IS NULL OR EXISTS (SELECT 1 FROM sessions s WHERE s.id = spores.session_id AND s.status != 'active'))`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
return {
|
|
137
|
-
where: conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "",
|
|
138
|
-
params
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function listSpores(options = {}) {
|
|
142
|
-
const db = getDatabase();
|
|
143
|
-
const { where, params } = buildSporeWhere(options);
|
|
144
|
-
const limit = options.limit ?? DEFAULT_LIST_LIMIT;
|
|
145
|
-
const offset = options.offset ?? 0;
|
|
146
|
-
const rows = db.prepare(
|
|
147
|
-
`SELECT ${SELECT_COLUMNS}
|
|
148
|
-
FROM spores
|
|
149
|
-
${where}
|
|
150
|
-
ORDER BY created_at DESC
|
|
151
|
-
LIMIT ?
|
|
152
|
-
OFFSET ?`
|
|
153
|
-
).all(...params, limit, offset);
|
|
154
|
-
return rows.map(toSporeRow);
|
|
155
|
-
}
|
|
156
|
-
function countSpores(options = {}) {
|
|
157
|
-
const db = getDatabase();
|
|
158
|
-
const { where, params } = buildSporeWhere(options);
|
|
159
|
-
const row = db.prepare(
|
|
160
|
-
`SELECT COUNT(*) as count FROM spores ${where}`
|
|
161
|
-
).get(...params);
|
|
162
|
-
return row.count;
|
|
163
|
-
}
|
|
164
|
-
function listSporeIdsSince(sinceEpoch, limit = 20) {
|
|
165
|
-
const db = getDatabase();
|
|
166
|
-
const rows = db.prepare(
|
|
167
|
-
`SELECT id FROM spores WHERE created_at > ? AND status = 'active' ORDER BY created_at DESC LIMIT ?`
|
|
168
|
-
).all(sinceEpoch, limit);
|
|
169
|
-
return rows.map((r) => r.id);
|
|
170
|
-
}
|
|
171
|
-
function updateSporeStatus(id, status, updatedAt) {
|
|
172
|
-
const db = getDatabase();
|
|
173
|
-
const info = db.prepare(
|
|
174
|
-
`UPDATE spores
|
|
175
|
-
SET status = ?, updated_at = ?
|
|
176
|
-
WHERE id = ?`
|
|
177
|
-
).run(status, updatedAt, id);
|
|
178
|
-
if (info.changes === 0) return null;
|
|
179
|
-
const row = toSporeRow(
|
|
180
|
-
db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(id)
|
|
181
|
-
);
|
|
182
|
-
syncRow("spores", row);
|
|
183
|
-
return row;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export {
|
|
187
|
-
DEFAULT_IMPORTANCE,
|
|
188
|
-
insertSpore,
|
|
189
|
-
getSpore,
|
|
190
|
-
listSpores,
|
|
191
|
-
countSpores,
|
|
192
|
-
listSporeIdsSince,
|
|
193
|
-
updateSporeStatus
|
|
194
|
-
};
|
|
195
|
-
//# sourceMappingURL=chunk-4YFKBL3F.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/queries/spores.ts"],"sourcesContent":["/**\n * Spore CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\nimport { syncRow } from '@myco/db/queries/team-outbox.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default number of spores returned by listSpores when no limit given. */\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Default spore status for new spores. */\nconst DEFAULT_STATUS = 'active';\n\n/** Default importance score for new spores. */\nexport const DEFAULT_IMPORTANCE = 5;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when inserting a spore. */\nexport interface SporeInsert {\n id: string;\n agent_id: string;\n observation_type: string;\n content: string;\n created_at: number;\n session_id?: string | null;\n prompt_batch_id?: number | null;\n status?: string;\n context?: string | null;\n importance?: number;\n file_path?: string | null;\n tags?: string | null;\n content_hash?: string | null;\n properties?: string | null;\n updated_at?: number | null;\n machine_id?: string;\n}\n\n/** Row shape returned from spore queries (all columns). */\nexport interface SporeRow {\n id: string;\n agent_id: string;\n session_id: string | null;\n prompt_batch_id: number | null;\n observation_type: string;\n status: string;\n content: string;\n context: string | null;\n importance: number;\n file_path: string | null;\n tags: string | null;\n content_hash: string | null;\n properties: string | null;\n embedded: number;\n created_at: number;\n updated_at: number | null;\n machine_id: string;\n synced_at: number | null;\n}\n\n/** Filter options for `listSpores`. */\nexport interface ListSporesOptions {\n agent_id?: string;\n observation_type?: string;\n status?: string;\n session_id?: string;\n search?: string;\n /** Only return spores created after this epoch-seconds timestamp. */\n since?: number;\n limit?: number;\n offset?: number;\n /**\n * When explicitly `false`, exclude spores whose source session is still\n * `status = 'active'` — intelligence-task reads (agent tools, context\n * queries) should opt in to this. Defaults to permissive so UI listings\n * and prompt-time context injection keep seeing in-flight work. Explicit\n * `session_id` filters bypass this check: a direct lookup of one session's\n * spores is always permitted.\n */\n includeActive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst SPORE_COLUMNS = [\n 'id',\n 'agent_id',\n 'session_id',\n 'prompt_batch_id',\n 'observation_type',\n 'status',\n 'content',\n 'context',\n 'importance',\n 'file_path',\n 'tags',\n 'content_hash',\n 'properties',\n 'embedded',\n 'created_at',\n 'updated_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = SPORE_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed SporeRow. */\nfunction toSporeRow(row: Record<string, unknown>): SporeRow {\n return {\n id: row.id as string,\n agent_id: row.agent_id as string,\n session_id: (row.session_id as string) ?? null,\n prompt_batch_id: (row.prompt_batch_id as number) ?? null,\n observation_type: row.observation_type as string,\n status: row.status as string,\n content: row.content as string,\n context: (row.context as string) ?? null,\n importance: row.importance as number,\n file_path: (row.file_path as string) ?? null,\n tags: (row.tags as string) ?? null,\n content_hash: (row.content_hash as string) ?? null,\n properties: (row.properties as string) ?? null,\n embedded: (row.embedded as number) ?? 0,\n created_at: row.created_at as number,\n updated_at: (row.updated_at as number) ?? null,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Insert a new spore.\n *\n * Requires a valid `agent_id` (foreign key to agents table).\n */\nexport function insertSpore(data: SporeInsert): SporeRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO spores (\n id, agent_id, session_id, prompt_batch_id,\n observation_type, status, content, context,\n importance, file_path, tags, content_hash,\n properties, created_at, updated_at, machine_id\n ) VALUES (\n ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?\n )`,\n ).run(\n data.id,\n data.agent_id,\n data.session_id ?? null,\n data.prompt_batch_id ?? null,\n data.observation_type,\n data.status ?? DEFAULT_STATUS,\n data.content,\n data.context ?? null,\n data.importance ?? DEFAULT_IMPORTANCE,\n data.file_path ?? null,\n data.tags ?? null,\n data.content_hash ?? null,\n data.properties ?? null,\n data.created_at,\n data.updated_at ?? null,\n data.machine_id ?? getTeamMachineId(),\n );\n\n const row = toSporeRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(data.id) as Record<string, unknown>,\n );\n\n syncRow('spores', row);\n\n return row;\n}\n\n/**\n * Retrieve a single spore by id.\n *\n * @returns the spore row, or null if not found.\n */\nexport function getSpore(id: string): SporeRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toSporeRow(row);\n}\n\n/**\n * List spores with optional filters, ordered by created_at DESC.\n */\n/** Build WHERE clause and bound params from spore filter options. */\nfunction buildSporeWhere(\n options: Omit<ListSporesOptions, 'limit' | 'offset'>,\n): { where: string; params: unknown[] } {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options.agent_id !== undefined) {\n conditions.push(`agent_id = ?`);\n params.push(options.agent_id);\n }\n if (options.observation_type !== undefined) {\n conditions.push(`observation_type = ?`);\n params.push(options.observation_type);\n }\n if (options.status !== undefined) {\n conditions.push(`status = ?`);\n params.push(options.status);\n }\n if (options.session_id !== undefined) {\n conditions.push(`session_id = ?`);\n params.push(options.session_id);\n }\n if (options.search !== undefined && options.search.length > 0) {\n conditions.push(`(content LIKE ? OR observation_type LIKE ?)`);\n const pattern = `%${options.search}%`;\n params.push(pattern, pattern);\n }\n if (options.since !== undefined) {\n conditions.push('created_at > ?');\n params.push(options.since);\n }\n\n // Only exclude spores from in-flight sessions when the caller explicitly\n // asks for it (intelligence tasks). UI and hook-level context injection\n // leave this unset so they see everything. A direct session_id filter\n // bypasses the gate — that lookup is always permitted.\n if (options.includeActive === false && options.session_id === undefined) {\n conditions.push(\n `(session_id IS NULL OR EXISTS (SELECT 1 FROM sessions s WHERE s.id = spores.session_id AND s.status != 'active'))`,\n );\n }\n\n return {\n where: conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '',\n params,\n };\n}\n\n/**\n * List spores with optional filters, ordered by created_at DESC.\n */\nexport function listSpores(\n options: ListSporesOptions = {},\n): SporeRow[] {\n const db = getDatabase();\n const { where, params } = buildSporeWhere(options);\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n const offset = options.offset ?? 0;\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM spores\n ${where}\n ORDER BY created_at DESC\n LIMIT ?\n OFFSET ?`,\n ).all(...params, limit, offset) as Record<string, unknown>[];\n\n return rows.map(toSporeRow);\n}\n\n/**\n * Count spores matching optional filters (for pagination totals).\n */\nexport function countSpores(\n options: Omit<ListSporesOptions, 'limit' | 'offset'> = {},\n): number {\n const db = getDatabase();\n const { where, params } = buildSporeWhere(options);\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM spores ${where}`,\n ).get(...params) as { count: number };\n\n return row.count;\n}\n\n/**\n * Count active spores created after a given timestamp.\n * Used by skill-evolve to detect new knowledge since last assessment.\n */\nexport function countSporesSince(sinceEpoch: number): number {\n const db = getDatabase();\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM spores WHERE created_at > ? AND status = 'active'`,\n ).get(sinceEpoch) as { count: number };\n return row.count;\n}\n\n/**\n * List active spore IDs created after a given timestamp, ordered newest first.\n */\nexport function listSporeIdsSince(sinceEpoch: number, limit = 20): string[] {\n const db = getDatabase();\n const rows = db.prepare(\n `SELECT id FROM spores WHERE created_at > ? AND status = 'active' ORDER BY created_at DESC LIMIT ?`,\n ).all(sinceEpoch, limit) as Array<{ id: string }>;\n return rows.map(r => r.id);\n}\n\n/**\n * Update the status and updated_at timestamp of a spore.\n *\n * @returns the updated row, or null if the spore does not exist.\n */\nexport function updateSporeStatus(\n id: string,\n status: string,\n updatedAt: number,\n): SporeRow | null {\n const db = getDatabase();\n\n const info = db.prepare(\n `UPDATE spores\n SET status = ?, updated_at = ?\n WHERE id = ?`,\n ).run(status, updatedAt, id);\n\n if (info.changes === 0) return null;\n\n const row = toSporeRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM spores WHERE id = ?`).get(id) as Record<string, unknown>,\n );\n\n syncRow('spores', row);\n\n return row;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/queries/search.ts"],"sourcesContent":["/**\n * Full-text search using SQLite FTS5.\n *\n * Searches prompt_batches and activities via their FTS5 virtual tables.\n * Semantic search (vector similarity) is handled by the external VectorStore —\n * this module covers text-based retrieval only.\n *\n * All queries use parameterized placeholders throughout.\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport {\n SEARCH_RESULTS_DEFAULT_LIMIT,\n SEARCH_PREVIEW_CHARS,\n} from '@myco/constants.js';\nimport type { VectorSearchResult } from '@myco/daemon/embedding/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All result types that can appear in search results. */\nexport type SearchResultType =\n | 'session'\n | 'spore'\n | 'plan'\n | 'artifact'\n | 'prompt_batch'\n | 'activity'\n | 'skill';\n\n/** A single result returned from full-text or semantic search. */\nexport interface SearchResult {\n id: string;\n type: SearchResultType;\n title: string;\n preview: string;\n score: number;\n session_id?: string;\n}\n\n/** Options for fullTextSearch. */\nexport interface SearchOptions {\n /** Restrict results to a single type. */\n type?: string;\n /** Maximum number of results to return (default: SEARCH_RESULTS_DEFAULT_LIMIT). */\n limit?: number;\n /**\n * When explicitly `false`, hide results belonging to sessions still in\n * `status = 'active'` (and active sessions themselves). Intelligence-task\n * reads opt in to this; UI/CLI callers leave it unset.\n */\n includeActive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Full-text search across capture tables using SQLite FTS5.\n *\n * Searches prompt_batches (indexed on user_prompt) and activities (indexed\n * on tool_name, tool_input, file_path). The raw query string is passed\n * directly to FTS5 MATCH — callers should sanitize if needed.\n *\n * FTS5 `rank` values are negative (lower = better match). This function\n * converts them to positive scores via `Math.abs()` so higher = better\n * in the returned results.\n *\n * When `options.type` is specified, only the matching table branch is queried.\n *\n * @param query — search string (FTS5 MATCH syntax)\n * @param options — optional type filter and result limit\n * @returns SearchResult[] ordered by score DESC\n */\nexport function fullTextSearch(\n query: string,\n options: SearchOptions = {},\n): SearchResult[] {\n const db = getDatabase();\n const limit = options.limit ?? SEARCH_RESULTS_DEFAULT_LIMIT;\n const typeFilter = options.type;\n const excludeActive = options.includeActive === false;\n\n const results: SearchResult[] = [];\n\n // -- prompt_batches branch ------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'prompt_batch') {\n const activeGate = excludeActive\n ? ` AND EXISTS (SELECT 1 FROM sessions s WHERE s.id = pb.session_id AND s.status != 'active')`\n : '';\n const batchRows = db.prepare(\n `SELECT pb.id, pb.prompt_number, pb.session_id,\n substr(COALESCE(pb.user_prompt, '') || ' ' || COALESCE(pb.response_summary, ''), 1, ?) AS preview,\n fts.rank\n FROM prompt_batches_fts fts\n JOIN prompt_batches pb ON pb.id = fts.rowid\n WHERE prompt_batches_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(SEARCH_PREVIEW_CHARS, query, limit) as Array<{\n id: number;\n prompt_number: number | null;\n session_id: string | null;\n preview: string;\n rank: number;\n }>;\n\n for (const row of batchRows) {\n results.push({\n id: String(row.id),\n type: 'prompt_batch',\n title: row.prompt_number != null\n ? `Batch #${row.prompt_number}`\n : `Batch ${row.id}`,\n preview: row.preview,\n score: Math.abs(row.rank),\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // -- activities branch ----------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'activity') {\n const activeGate = excludeActive\n ? ` AND EXISTS (SELECT 1 FROM sessions s WHERE s.id = a.session_id AND s.status != 'active')`\n : '';\n const activityRows = db.prepare(\n `SELECT a.id, a.tool_name, a.tool_input, a.file_path, a.session_id,\n fts.rank\n FROM activities_fts fts\n JOIN activities a ON a.id = fts.rowid\n WHERE activities_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(query, limit) as Array<{\n id: number;\n tool_name: string;\n tool_input: string | null;\n file_path: string | null;\n session_id: string | null;\n rank: number;\n }>;\n\n for (const row of activityRows) {\n const preview = (row.tool_input ?? row.file_path ?? '').slice(0, SEARCH_PREVIEW_CHARS);\n results.push({\n id: String(row.id),\n type: 'activity',\n title: row.tool_name,\n preview,\n score: Math.abs(row.rank),\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // -- spores branch --------------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'spore') {\n // Spores may have a NULL session_id (agent-authored, no source session),\n // which are always kept; only spores attached to still-active sessions\n // are excluded when the gate is on.\n const activeGate = excludeActive\n ? ` AND (s.session_id IS NULL OR EXISTS (SELECT 1 FROM sessions ss WHERE ss.id = s.session_id AND ss.status != 'active'))`\n : '';\n const sporeRows = db.prepare(\n `SELECT s.id, s.observation_type, s.session_id,\n substr(COALESCE(s.content, ''), 1, ?) AS preview,\n fts.rank\n FROM spores_fts fts\n JOIN spores s ON s.rowid = fts.rowid\n WHERE spores_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(SEARCH_PREVIEW_CHARS, query, limit) as Array<{\n id: string;\n observation_type: string;\n session_id: string | null;\n preview: string;\n rank: number;\n }>;\n\n for (const row of sporeRows) {\n results.push({\n id: String(row.id),\n type: 'spore',\n title: row.observation_type,\n preview: row.preview,\n score: Math.abs(row.rank),\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // -- sessions branch ------------------------------------------------------\n if (typeFilter === undefined || typeFilter === 'session') {\n const activeGate = excludeActive ? ` AND s.status != 'active'` : '';\n const sessionRows = db.prepare(\n `SELECT s.id, s.title,\n substr(COALESCE(s.summary, s.title, ''), 1, ?) AS preview,\n fts.rank\n FROM sessions_fts fts\n JOIN sessions s ON s.rowid = fts.rowid\n WHERE sessions_fts MATCH ?${activeGate}\n ORDER BY fts.rank\n LIMIT ?`\n ).all(SEARCH_PREVIEW_CHARS, query, limit) as Array<{\n id: string;\n title: string | null;\n preview: string;\n rank: number;\n }>;\n\n for (const row of sessionRows) {\n results.push({\n id: String(row.id),\n type: 'session',\n title: row.title ?? `Session ${row.id.slice(-6)}`,\n preview: row.preview,\n score: Math.abs(row.rank),\n });\n }\n }\n\n // Sort combined results by score DESC and apply limit.\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, limit);\n}\n\n// ---------------------------------------------------------------------------\n// Hydration — convert VectorSearchResults into SearchResults\n// ---------------------------------------------------------------------------\n\n/** Row shape returned from sessions table for hydration. */\ninterface SessionRow {\n id: string;\n title: string | null;\n summary: string | null;\n session_id?: undefined;\n}\n\n/** Row shape returned from spores table for hydration. */\ninterface SporeRow {\n id: string;\n observation_type: string;\n content: string;\n session_id: string | null;\n}\n\n/** Row shape returned from plans table for hydration. */\ninterface PlanRow {\n id: string;\n title: string | null;\n content: string | null;\n session_id: string | null;\n}\n\n/** Row shape returned from artifacts table for hydration. */\ninterface ArtifactRow {\n id: string;\n title: string;\n content: string | null;\n}\n\n/**\n * Hydrate vector search results into SearchResults by fetching full records\n * from the record store.\n *\n * Groups results by namespace, queries each table for the relevant IDs, then\n * maps them into SearchResult format with titles and previews.\n */\nexport function hydrateSearchResults(\n vectorResults: VectorSearchResult[],\n): SearchResult[] {\n if (vectorResults.length === 0) return [];\n\n const db = getDatabase();\n const results: SearchResult[] = [];\n\n // Group result IDs by namespace\n const byNamespace = new Map<string, VectorSearchResult[]>();\n for (const vr of vectorResults) {\n const group = byNamespace.get(vr.namespace) ?? [];\n group.push(vr);\n byNamespace.set(vr.namespace, group);\n }\n\n // Use json_each so the statement text is stable and SQLite can cache the plan.\n const sessionStmt = db.prepare(\n `SELECT id, title, summary FROM sessions WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const sporeStmt = db.prepare(\n `SELECT id, observation_type, content, session_id FROM spores WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const planStmt = db.prepare(\n `SELECT id, title, content, session_id FROM plans WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const artifactStmt = db.prepare(\n `SELECT id, title, content FROM artifacts WHERE id IN (SELECT value FROM json_each(?))`,\n );\n const skillStmt = db.prepare(\n `SELECT id, name, display_name, description FROM skill_records WHERE id IN (SELECT value FROM json_each(?))`,\n );\n\n // --- sessions ---\n const sessionResults = byNamespace.get('sessions');\n if (sessionResults && sessionResults.length > 0) {\n const ids = sessionResults.map((r) => r.id);\n const rows = sessionStmt.all(JSON.stringify(ids)) as SessionRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of sessionResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'session',\n title: row.title ?? `Session ${row.id.slice(-6)}`,\n preview: (row.summary ?? '').slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n });\n }\n }\n\n // --- spores ---\n const sporeResults = byNamespace.get('spores');\n if (sporeResults && sporeResults.length > 0) {\n const ids = sporeResults.map((r) => r.id);\n const rows = sporeStmt.all(JSON.stringify(ids)) as SporeRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of sporeResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'spore',\n title: row.observation_type,\n preview: row.content.slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // --- plans ---\n const planResults = byNamespace.get('plans');\n if (planResults && planResults.length > 0) {\n const ids = planResults.map((r) => r.id);\n const rows = planStmt.all(JSON.stringify(ids)) as PlanRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of planResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'plan',\n title: row.title ?? `Plan ${row.id.slice(-6)}`,\n preview: (row.content ?? '').slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n ...(row.session_id != null ? { session_id: row.session_id } : {}),\n });\n }\n }\n\n // --- artifacts ---\n const artifactResults = byNamespace.get('artifacts');\n if (artifactResults && artifactResults.length > 0) {\n const ids = artifactResults.map((r) => r.id);\n const rows = artifactStmt.all(JSON.stringify(ids)) as ArtifactRow[];\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of artifactResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'artifact',\n title: row.title,\n preview: (row.content ?? '').slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n });\n }\n }\n\n // --- skill_records ---\n const skillResults = byNamespace.get('skill_records');\n if (skillResults && skillResults.length > 0) {\n const ids = skillResults.map((r) => r.id);\n const rows = skillStmt.all(JSON.stringify(ids)) as Array<{ id: string; name: string; display_name: string; description: string }>;\n\n const rowMap = new Map(rows.map((r) => [r.id, r]));\n for (const vr of skillResults) {\n const row = rowMap.get(vr.id);\n if (!row) continue;\n results.push({\n id: row.id,\n type: 'skill',\n title: row.display_name || row.name,\n preview: row.description.slice(0, SEARCH_PREVIEW_CHARS),\n score: vr.similarity,\n });\n }\n }\n\n // Preserve the original similarity-based ordering from vector search\n results.sort((a, b) => b.score - a.score);\n return results;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent/loader.ts","../src/db/queries/agents.ts","../src/db/queries/tasks.ts","../src/agent/schemas.ts"],"sourcesContent":["/**\n * Agent definition and task YAML loader.\n *\n * Reads agent.yaml and tasks/*.yaml from the definitions directory,\n * validates their shape, and provides helpers for merging built-in\n * definitions with database overrides into an EffectiveConfig.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { findPackageRoot } from '@myco/utils/find-package-root.js';\nimport { parse as parseYaml } from 'yaml';\nimport { epochSeconds, DEFAULT_AGENT_ID, BUILT_IN_SOURCE, USER_TASK_SOURCE } from '@myco/constants.js';\nimport { getDatabase } from '@myco/db/client.js';\nimport { registerAgent } from '@myco/db/queries/agents.js';\nimport { upsertTask } from '@myco/db/queries/tasks.js';\nimport type { AgentRow } from '@myco/db/queries/agents.js';\nimport type { AgentDefinition, AgentTask, EffectiveConfig } from './types.js';\nimport { AgentDefinitionSchema, AgentTaskSchema } from './schemas.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Filename for the built-in agent definition. */\nconst AGENT_DEFINITION_FILE = 'agent.yaml';\n\n/** Subdirectory containing task YAML files. */\nconst TASKS_SUBDIRECTORY = 'tasks';\n\n// Package root resolution uses shared findPackageRoot from @myco/utils\n\n// BUILT_IN_SOURCE imported from @myco/constants.js\n\n// ---------------------------------------------------------------------------\n// Definitions directory resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the definitions directory at runtime.\n *\n * Strategy (same pattern as `src/prompts/index.ts`):\n * 1. Walk up from `import.meta.url` looking for `package.json`.\n * 2. From package root, try `dist/src/agent/definitions/` (tsup output).\n * 3. Fall back to `src/agent/definitions/` (dev mode / tsc output).\n * 4. Also check if the current file's directory already contains agent.yaml.\n */\nexport function resolveDefinitionsDir(): string {\n const scriptDir = path.dirname(fileURLToPath(import.meta.url));\n\n // Check if we're already adjacent to the definitions (tsc output or dev mode)\n const adjacentDefs = path.join(scriptDir, 'definitions');\n if (fs.existsSync(path.join(adjacentDefs, AGENT_DEFINITION_FILE))) {\n return adjacentDefs;\n }\n\n // Walk up to package root using shared utility\n const root = findPackageRoot(scriptDir);\n if (root) {\n // Try dist path first (tsup bundled output)\n const distPath = path.join(root, 'dist', 'src', 'agent', 'definitions');\n if (fs.existsSync(path.join(distPath, AGENT_DEFINITION_FILE))) {\n return distPath;\n }\n // Fall back to src path (dev mode)\n const srcPath = path.join(root, 'src', 'agent', 'definitions');\n if (fs.existsSync(path.join(srcPath, AGENT_DEFINITION_FILE))) {\n return srcPath;\n }\n }\n\n // Final fallback: adjacent to current file\n return adjacentDefs;\n}\n\n// ---------------------------------------------------------------------------\n// YAML loaders\n// ---------------------------------------------------------------------------\n\n/**\n * Load and parse the built-in agent definition from `agent.yaml`.\n *\n * @param definitionsDir — path to the definitions directory.\n * @returns the parsed AgentDefinition.\n * @throws if the file is missing or malformed.\n */\nexport function loadAgentDefinition(definitionsDir: string): AgentDefinition {\n const filePath = path.join(definitionsDir, AGENT_DEFINITION_FILE);\n const raw = fs.readFileSync(filePath, 'utf-8');\n const parsed = AgentDefinitionSchema.parse(parseYaml(raw));\n\n return {\n name: parsed.name,\n displayName: parsed.displayName,\n description: parsed.description.trim(),\n model: parsed.model,\n maxTurns: parsed.maxTurns,\n timeoutSeconds: parsed.timeoutSeconds,\n systemPromptPath: parsed.systemPromptPath,\n tools: parsed.tools,\n };\n}\n\n/**\n * Load and parse all task YAML files from `tasks/`.\n *\n * @param definitionsDir — path to the definitions directory.\n * @returns array of parsed AgentTask objects.\n */\nexport function loadAgentTasks(definitionsDir: string): AgentTask[] {\n const tasksDir = path.join(definitionsDir, TASKS_SUBDIRECTORY);\n if (!fs.existsSync(tasksDir)) return [];\n\n const files = fs.readdirSync(tasksDir).filter((f) => f.endsWith('.yaml'));\n return files.map((file) => {\n const raw = fs.readFileSync(path.join(tasksDir, file), 'utf-8');\n const parsed = AgentTaskSchema.parse(parseYaml(raw));\n\n return taskFromParsed(parsed);\n });\n}\n\n/**\n * Convert a Zod-parsed task schema result to an AgentTask object.\n *\n * Shared by loadAgentTasks (built-in) and registry (user tasks) to ensure\n * all optional fields are consistently spread. Adding a new optional field\n * to AgentTaskSchema only requires updating this one function.\n */\nexport function taskFromParsed(parsed: AgentTask): AgentTask {\n return {\n name: parsed.name,\n displayName: parsed.displayName,\n description: parsed.description.trim(),\n agent: parsed.agent,\n prompt: parsed.prompt.trim(),\n isDefault: parsed.isDefault,\n ...(parsed.toolOverrides ? { toolOverrides: parsed.toolOverrides } : {}),\n ...(parsed.model ? { model: parsed.model } : {}),\n ...(parsed.maxTurns ? { maxTurns: parsed.maxTurns } : {}),\n ...(parsed.timeoutSeconds ? { timeoutSeconds: parsed.timeoutSeconds } : {}),\n ...(parsed.phases ? { phases: parsed.phases } : {}),\n ...(parsed.orchestrator ? { orchestrator: parsed.orchestrator } : {}),\n ...(parsed.contextQueries ? { contextQueries: parsed.contextQueries } : {}),\n ...(parsed.execution ? { execution: parsed.execution } : {}),\n ...(parsed.schemaVersion ? { schemaVersion: parsed.schemaVersion } : {}),\n ...(parsed.schedule ? { schedule: parsed.schedule } : {}),\n ...(parsed.params ? { params: parsed.params } : {}),\n };\n}\n\n/**\n * Load a system prompt markdown file.\n *\n * @param definitionsDir — path to the definitions directory.\n * @param relativePath — path relative to definitionsDir (from AgentDefinition.systemPromptPath).\n * @returns the prompt file content as a string.\n */\nexport function loadSystemPrompt(definitionsDir: string, relativePath: string): string {\n const filePath = path.resolve(definitionsDir, relativePath);\n return fs.readFileSync(filePath, 'utf-8').trim();\n}\n\n// ---------------------------------------------------------------------------\n// Config resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Merge a built-in AgentDefinition with optional database overrides and\n * task-specific configuration to produce the effective runtime config.\n *\n * Priority (highest wins):\n * 1. Task toolOverrides (replaces tool list entirely if present)\n * 2. AgentRow database overrides (model, maxTurns, timeoutSeconds, tool_access)\n * 3. Built-in AgentDefinition defaults\n *\n * @param definition — the built-in agent definition from YAML.\n * @param agentOverrides — optional database row with user-applied overrides.\n * @param taskOverrides — optional task definition (determines prompt and may override tools).\n * @returns the merged EffectiveConfig.\n */\nexport function resolveEffectiveConfig(\n definition: AgentDefinition,\n agentOverrides?: AgentRow | null,\n taskOverrides?: AgentTask,\n): EffectiveConfig {\n // Start with definition defaults\n let model = definition.model;\n let maxTurns = definition.maxTurns;\n let timeoutSeconds = definition.timeoutSeconds;\n let tools = [...definition.tools];\n const agentId = agentOverrides?.id ?? DEFAULT_AGENT_ID;\n\n // Apply agent DB overrides\n if (agentOverrides) {\n if (agentOverrides.model) model = agentOverrides.model;\n if (agentOverrides.max_turns !== null) maxTurns = agentOverrides.max_turns;\n if (agentOverrides.timeout_seconds !== null) timeoutSeconds = agentOverrides.timeout_seconds;\n if (agentOverrides.tool_access) {\n try {\n const parsed = JSON.parse(agentOverrides.tool_access);\n if (Array.isArray(parsed)) tools = parsed as string[];\n } catch {\n // Invalid JSON in tool_access — keep definition defaults\n }\n }\n }\n\n // Apply task overrides (model, turns, timeout, tool list)\n if (taskOverrides?.model) model = taskOverrides.model;\n if (taskOverrides?.maxTurns) maxTurns = taskOverrides.maxTurns;\n if (taskOverrides?.timeoutSeconds) timeoutSeconds = taskOverrides.timeoutSeconds;\n if (taskOverrides?.toolOverrides) {\n tools = [...taskOverrides.toolOverrides];\n }\n\n // Apply execution config overrides (highest priority)\n // Precedence: execution.model > task.model > agent.model\n if (taskOverrides?.execution) {\n if (taskOverrides.execution.model) model = taskOverrides.execution.model;\n if (taskOverrides.execution.maxTurns) maxTurns = taskOverrides.execution.maxTurns;\n if (taskOverrides.execution.timeoutSeconds) timeoutSeconds = taskOverrides.execution.timeoutSeconds;\n }\n\n // Task prompt and display info (fall back to a generic prompt)\n const taskName = taskOverrides?.name ?? 'full-intelligence';\n const taskDisplayName = taskOverrides?.displayName ?? 'Full Intelligence';\n const taskPrompt = taskOverrides?.prompt ?? '';\n\n return {\n agentId,\n model,\n maxTurns,\n timeoutSeconds,\n systemPromptPath: definition.systemPromptPath,\n tools,\n taskName,\n taskDisplayName,\n taskPrompt,\n ...(taskOverrides?.phases ? { phases: taskOverrides.phases } : {}),\n ...(taskOverrides?.orchestrator ? { orchestrator: taskOverrides.orchestrator } : {}),\n ...(taskOverrides?.contextQueries ? { contextQueries: taskOverrides.contextQueries } : {}),\n ...(taskOverrides?.execution ? { execution: taskOverrides.execution } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Database registration\n// ---------------------------------------------------------------------------\n\n/**\n * Register the built-in agent and all built-in tasks into the database.\n *\n * Idempotent: uses upsert (ON CONFLICT DO UPDATE) for both agent and tasks.\n * Safe to call on every daemon startup.\n *\n * @param definitionsDir — path to the definitions directory.\n */\nexport async function registerBuiltInAgentsAndTasks(definitionsDir: string, vaultDir?: string): Promise<void> {\n const definition = loadAgentDefinition(definitionsDir);\n const tasks = loadAgentTasks(definitionsDir);\n const now = epochSeconds();\n\n // Upsert the built-in agent\n registerAgent({\n id: definition.name,\n name: definition.displayName,\n model: definition.model,\n source: BUILT_IN_SOURCE,\n max_turns: definition.maxTurns,\n timeout_seconds: definition.timeoutSeconds,\n tool_access: JSON.stringify(definition.tools),\n created_at: now,\n updated_at: now,\n });\n\n // Upsert all built-in tasks\n for (const task of tasks) {\n upsertTask({\n id: task.name,\n agent_id: definition.name,\n source: BUILT_IN_SOURCE,\n display_name: task.displayName,\n description: task.description,\n prompt: task.prompt,\n is_default: task.isDefault ? 1 : 0,\n tool_overrides: task.toolOverrides ? JSON.stringify(task.toolOverrides) : null,\n config: JSON.stringify({\n phases: task.phases ?? null,\n execution: task.execution ?? null,\n contextQueries: task.contextQueries ?? null,\n schemaVersion: task.schemaVersion ?? 1,\n }),\n created_at: now,\n updated_at: now,\n });\n }\n\n // Remove built-in tasks that no longer have YAML definitions\n const validTaskIds = tasks.map(t => t.name);\n if (validTaskIds.length > 0) {\n const db = getDatabase();\n const placeholders = validTaskIds.map(() => '?').join(', ');\n db.prepare(\n `DELETE FROM agent_tasks\n WHERE source = ? AND agent_id = ? AND id NOT IN (${placeholders})`,\n ).run(BUILT_IN_SOURCE, definition.name, ...validTaskIds);\n }\n\n // Register user tasks from the vault (if vault dir provided)\n if (vaultDir) {\n const { loadAllTasks } = await import('./registry.js');\n const allTasks = loadAllTasks(definitionsDir, vaultDir);\n for (const [name, task] of allTasks) {\n if (task.source === USER_TASK_SOURCE) {\n upsertTask({\n id: name,\n agent_id: task.agent ?? definition.name,\n source: USER_TASK_SOURCE,\n display_name: task.displayName,\n description: task.description,\n prompt: task.prompt,\n is_default: task.isDefault ? 1 : 0,\n tool_overrides: task.toolOverrides ? JSON.stringify(task.toolOverrides) : null,\n config: JSON.stringify({\n phases: task.phases ?? null,\n execution: task.execution ?? null,\n contextQueries: task.contextQueries ?? null,\n schemaVersion: task.schemaVersion ?? 1,\n }),\n created_at: now,\n updated_at: now,\n });\n }\n }\n }\n}\n","/**\n * Agent CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when registering an agent. */\nexport interface AgentInsert {\n id: string;\n name: string;\n created_at: number;\n provider?: string | null;\n model?: string | null;\n system_prompt_hash?: string | null;\n config?: string | null;\n source?: string;\n system_prompt?: string | null;\n max_turns?: number | null;\n timeout_seconds?: number | null;\n tool_access?: string | null;\n enabled?: number;\n updated_at?: number | null;\n}\n\n/** Row shape returned from agent queries (all columns). */\nexport interface AgentRow {\n id: string;\n name: string;\n provider: string | null;\n model: string | null;\n system_prompt_hash: string | null;\n config: string | null;\n source: string;\n system_prompt: string | null;\n max_turns: number | null;\n timeout_seconds: number | null;\n tool_access: string | null;\n enabled: number;\n created_at: number;\n updated_at: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default agent source for new agents. */\nconst DEFAULT_SOURCE = 'built-in';\n\n/** Default enabled flag for new agents. */\nconst DEFAULT_ENABLED = 1;\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst AGENT_COLUMNS = [\n 'id',\n 'name',\n 'provider',\n 'model',\n 'system_prompt_hash',\n 'config',\n 'source',\n 'system_prompt',\n 'max_turns',\n 'timeout_seconds',\n 'tool_access',\n 'enabled',\n 'created_at',\n 'updated_at',\n] as const;\n\nconst SELECT_COLUMNS = AGENT_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed AgentRow. */\nfunction toAgentRow(row: Record<string, unknown>): AgentRow {\n return {\n id: row.id as string,\n name: row.name as string,\n provider: (row.provider as string) ?? null,\n model: (row.model as string) ?? null,\n system_prompt_hash: (row.system_prompt_hash as string) ?? null,\n config: (row.config as string) ?? null,\n source: (row.source as string) ?? DEFAULT_SOURCE,\n system_prompt: (row.system_prompt as string) ?? null,\n max_turns: (row.max_turns as number) ?? null,\n timeout_seconds: (row.timeout_seconds as number) ?? null,\n tool_access: (row.tool_access as string) ?? null,\n enabled: (row.enabled as number) ?? DEFAULT_ENABLED,\n created_at: row.created_at as number,\n updated_at: (row.updated_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Register an agent or update it if the id already exists.\n *\n * On conflict the row is updated with the values from `data`.\n * This is the idempotent upsert — calling twice with the same data\n * produces the same result.\n */\nexport function registerAgent(data: AgentInsert): AgentRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO agents (\n id, name, provider, model, system_prompt_hash, config,\n source, system_prompt, max_turns, timeout_seconds, tool_access,\n enabled, created_at, updated_at\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?, ?\n )\n ON CONFLICT (id) DO UPDATE SET\n name = EXCLUDED.name,\n provider = EXCLUDED.provider,\n model = EXCLUDED.model,\n system_prompt_hash = EXCLUDED.system_prompt_hash,\n config = EXCLUDED.config,\n source = EXCLUDED.source,\n system_prompt = EXCLUDED.system_prompt,\n max_turns = EXCLUDED.max_turns,\n timeout_seconds = EXCLUDED.timeout_seconds,\n tool_access = EXCLUDED.tool_access,\n enabled = EXCLUDED.enabled,\n updated_at = EXCLUDED.updated_at`,\n ).run(\n data.id,\n data.name,\n data.provider ?? null,\n data.model ?? null,\n data.system_prompt_hash ?? null,\n data.config ?? null,\n data.source ?? DEFAULT_SOURCE,\n data.system_prompt ?? null,\n data.max_turns ?? null,\n data.timeout_seconds ?? null,\n data.tool_access ?? null,\n data.enabled ?? DEFAULT_ENABLED,\n data.created_at,\n data.updated_at ?? null,\n );\n\n return toAgentRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM agents WHERE id = ?`).get(data.id) as Record<string, unknown>,\n );\n}\n\n/**\n * Retrieve a single agent by id.\n *\n * @returns the agent row, or null if not found.\n */\nexport function getAgent(id: string): AgentRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM agents WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toAgentRow(row);\n}\n\n/**\n * List all agents, ordered by created_at ASC.\n */\nexport function listAgents(): AgentRow[] {\n const db = getDatabase();\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM agents\n ORDER BY created_at ASC`,\n ).all() as Record<string, unknown>[];\n\n return rows.map(toAgentRow);\n}\n","/**\n * Agent task CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { BUILT_IN_SOURCE } from '@myco/constants.js';\nimport type { TaskConfig } from '@myco/agent/types.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default number of tasks returned by listTasks when no limit given. */\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Default task source for new tasks. */\nconst DEFAULT_SOURCE = BUILT_IN_SOURCE;\n\n/** Default is_default flag for new tasks. */\nconst DEFAULT_IS_DEFAULT = 0;\n\n/** Value indicating a task is the default for its agent. */\nconst IS_DEFAULT_TRUE = 1;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when upserting a task. */\nexport interface TaskInsert {\n id: string;\n agent_id: string;\n prompt: string;\n created_at: number;\n source?: string;\n display_name?: string | null;\n description?: string | null;\n is_default?: number;\n tool_overrides?: string | null;\n model?: string | null;\n config?: string | null;\n updated_at?: number | null;\n}\n\n/** Row shape returned from agent_tasks queries (all columns). */\nexport interface TaskRow {\n id: string;\n agent_id: string;\n source: string;\n display_name: string | null;\n description: string | null;\n prompt: string;\n is_default: number;\n tool_overrides: string | null;\n model: string | null;\n config: string | null;\n created_at: number;\n updated_at: number | null;\n}\n\n/** Filter options for `listTasks`. */\nexport interface ListTasksOptions {\n limit?: number;\n agent_id?: string;\n source?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst TASK_COLUMNS = [\n 'id',\n 'agent_id',\n 'source',\n 'display_name',\n 'description',\n 'prompt',\n 'is_default',\n 'tool_overrides',\n 'model',\n 'config',\n 'created_at',\n 'updated_at',\n] as const;\n\nconst SELECT_COLUMNS = TASK_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed TaskRow. */\nfunction toTaskRow(row: Record<string, unknown>): TaskRow {\n return {\n id: row.id as string,\n agent_id: row.agent_id as string,\n source: (row.source as string) ?? DEFAULT_SOURCE,\n display_name: (row.display_name as string) ?? null,\n description: (row.description as string) ?? null,\n prompt: row.prompt as string,\n is_default: (row.is_default as number) ?? DEFAULT_IS_DEFAULT,\n tool_overrides: (row.tool_overrides as string) ?? null,\n model: (row.model as string) ?? null,\n config: (row.config as string) ?? null,\n created_at: row.created_at as number,\n updated_at: (row.updated_at as number) ?? null,\n };\n}\n\n/** Serialize a TaskConfig to a JSON string for storage. */\nexport function serializeConfig(config: TaskConfig | null): string | null {\n if (!config) return null;\n return JSON.stringify(config);\n}\n\n/** Deserialize a TaskConfig from a stored JSON string. Returns null on failure. */\nexport function deserializeConfig(raw: string | null): TaskConfig | null {\n if (!raw) return null;\n try {\n return JSON.parse(raw) as TaskConfig;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Upsert a task — insert or update on conflict.\n *\n * On conflict the row is updated with the values from `data`.\n * This is the idempotent upsert — calling twice with the same data\n * produces the same result.\n */\nexport function upsertTask(data: TaskInsert): TaskRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO agent_tasks (\n id, agent_id, source, display_name, description,\n prompt, is_default, tool_overrides, model, config,\n created_at, updated_at\n ) VALUES (\n ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?\n )\n ON CONFLICT (id) DO UPDATE SET\n agent_id = EXCLUDED.agent_id,\n source = EXCLUDED.source,\n display_name = EXCLUDED.display_name,\n description = EXCLUDED.description,\n prompt = EXCLUDED.prompt,\n is_default = EXCLUDED.is_default,\n tool_overrides = EXCLUDED.tool_overrides,\n model = EXCLUDED.model,\n config = EXCLUDED.config,\n updated_at = EXCLUDED.updated_at`,\n ).run(\n data.id,\n data.agent_id,\n data.source ?? DEFAULT_SOURCE,\n data.display_name ?? null,\n data.description ?? null,\n data.prompt,\n data.is_default ?? DEFAULT_IS_DEFAULT,\n data.tool_overrides ?? null,\n data.model ?? null,\n data.config ?? null,\n data.created_at,\n data.updated_at ?? null,\n );\n\n return toTaskRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM agent_tasks WHERE id = ?`).get(data.id) as Record<string, unknown>,\n );\n}\n\n/**\n * Retrieve a single task by id.\n *\n * @returns the task row, or null if not found.\n */\nexport function getTask(id: string): TaskRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM agent_tasks WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toTaskRow(row);\n}\n\n/**\n * List tasks with optional filters, ordered by created_at ASC.\n */\nexport function listTasks(\n options: ListTasksOptions = {},\n): TaskRow[] {\n const db = getDatabase();\n\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options.agent_id !== undefined) {\n conditions.push(`agent_id = ?`);\n params.push(options.agent_id);\n }\n\n if (options.source !== undefined) {\n conditions.push(`source = ?`);\n params.push(options.source);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n\n params.push(limit);\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM agent_tasks\n ${where}\n ORDER BY created_at ASC\n LIMIT ?`,\n ).all(...params) as Record<string, unknown>[];\n\n return rows.map(toTaskRow);\n}\n\n/**\n * Get the default task for an agent.\n *\n * @returns the default task row, or null if no default exists.\n */\nexport function getDefaultTask(\n agentId: string,\n): TaskRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM agent_tasks\n WHERE agent_id = ? AND is_default = ?\n LIMIT 1`,\n ).get(agentId, IS_DEFAULT_TRUE) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toTaskRow(row);\n}\n\n/**\n * List all tasks for an agent, ordered by display_name ASC.\n *\n * Rows with a null display_name sort before named tasks.\n */\nexport function listTasksByAgent(\n agentId: string,\n): TaskRow[] {\n const db = getDatabase();\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM agent_tasks\n WHERE agent_id = ?\n ORDER BY display_name ASC`,\n ).all(agentId) as Record<string, unknown>[];\n\n return rows.map(toTaskRow);\n}\n\n/**\n * Delete a task by id.\n *\n * Built-in tasks (source = 'built-in') are protected and cannot be deleted.\n *\n * @returns true if the task was deleted, false if not found or protected.\n */\nexport function deleteTask(id: string): boolean {\n const db = getDatabase();\n const info = db.prepare(\n `DELETE FROM agent_tasks WHERE id = ? AND source != ?`,\n ).run(id, BUILT_IN_SOURCE);\n return info.changes > 0;\n}\n","/**\n * Zod schemas for agent definition and task YAML validation.\n *\n * These schemas are shared between the loader (which validates YAML files)\n * and any other code that needs to parse or validate task/agent config.\n */\n\nimport { z } from 'zod/v4';\nimport { SCHEDULABLE_POWER_STATES } from '@myco/constants.js';\n\n// ---------------------------------------------------------------------------\n// Schema version\n// ---------------------------------------------------------------------------\n\n/** Current schema version for task config structures. */\nexport const CURRENT_TASK_SCHEMA_VERSION = 1;\n\n// ---------------------------------------------------------------------------\n// Shared sub-schemas\n// ---------------------------------------------------------------------------\n\n/** Schema for API provider configuration. */\nexport const ProviderConfigSchema = z.object({\n type: z.enum(['anthropic', 'ollama', 'lmstudio']),\n baseUrl: z.string().optional(),\n apiKey: z.string().optional(),\n model: z.string().optional(),\n});\n\n/** Schema for execution configuration overrides. */\nexport const ExecutionConfigSchema = z.object({\n model: z.string().optional(),\n maxTurns: z.number().optional(),\n timeoutSeconds: z.number().optional(),\n provider: ProviderConfigSchema.optional(),\n});\n\n/** Schema for a single context query entry. */\nexport const ContextQuerySchema = z.object({\n tool: z.string(),\n queryTemplate: z.string(),\n limit: z.number(),\n purpose: z.string(),\n required: z.boolean(),\n});\n\n// ---------------------------------------------------------------------------\n// Agent definition schema\n// ---------------------------------------------------------------------------\n\n/** Schema for agent.yaml agent definition files. */\nexport const AgentDefinitionSchema = z.object({\n name: z.string(),\n displayName: z.string(),\n description: z.string(),\n model: z.string(),\n maxTurns: z.number(),\n timeoutSeconds: z.number(),\n systemPromptPath: z.string(),\n tools: z.array(z.string()),\n});\n\n// ---------------------------------------------------------------------------\n// Task schemas\n// ---------------------------------------------------------------------------\n\n/** Schema for orchestrator configuration on a task definition. */\nexport const OrchestratorConfigSchema = z.object({\n enabled: z.boolean(),\n model: z.string().optional(),\n maxTurns: z.number().optional(),\n});\n\n/** Pre-condition identifiers for scheduled task auto-runs. */\nconst PreConditionSchema = z.enum([\n 'has-unprocessed-batches',\n 'has-active-skills',\n 'has-approved-candidates',\n 'has-skill-survey-evidence',\n]);\n\n/** Schedule configuration for automatic task execution via PowerManager. */\nexport const TaskScheduleSchema = z.object({\n /** Whether auto-run is enabled for this task. */\n enabled: z.boolean().default(false),\n /** Seconds between runs. */\n intervalSeconds: z.number().int().positive(),\n /** PowerManager states where this task runs. */\n runIn: z.array(z.enum([...SCHEDULABLE_POWER_STATES])).min(1),\n /** Optional pre-condition check before running. */\n preCondition: PreConditionSchema.optional(),\n});\n\n/** Schema for a single phase within a phased task pipeline. */\nexport const PhaseDefinitionSchema = z.object({\n name: z.string(),\n prompt: z.string(),\n tools: z.array(z.string()),\n maxTurns: z.number(),\n model: z.string().optional(),\n required: z.boolean(),\n dependsOn: z.array(z.string()).optional(),\n provider: ProviderConfigSchema.optional(),\n skipPriorContext: z.boolean().optional(),\n readOnly: z.boolean().optional(),\n});\n\n/** Schema for task YAML files in tasks/. */\nexport const AgentTaskSchema = z.object({\n name: z.string(),\n displayName: z.string(),\n description: z.string(),\n agent: z.string(),\n prompt: z.string(),\n isDefault: z.boolean(),\n toolOverrides: z.array(z.string()).optional(),\n model: z.string().optional(),\n maxTurns: z.number().optional(),\n timeoutSeconds: z.number().optional(),\n phases: z.array(PhaseDefinitionSchema).optional(),\n execution: ExecutionConfigSchema.optional(),\n contextQueries: z.record(z.string(), z.array(ContextQuerySchema)).optional(),\n schemaVersion: z.number().optional(),\n orchestrator: OrchestratorConfigSchema.optional(),\n schedule: TaskScheduleSchema.optional(),\n /** Task-specific params with defaults. */\n params: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n});\n"],"mappings":"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","names":["DEFAULT_SOURCE","SELECT_COLUMNS","DEFAULT_SOURCE","SELECT_COLUMNS","SELECT_COLUMNS","parseYaml"]}
|
package/dist/chunk-CUDIZJY7.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// src/vault/resolve.ts
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { execFileSync } from "child_process";
|
|
6
|
-
var MYCO_PROJECT_ROOT_ENV = "MYCO_PROJECT_ROOT";
|
|
7
|
-
var MYCO_VAULT_DIR_ENV = "MYCO_VAULT_DIR";
|
|
8
|
-
function resolveVaultDir(cwd = process.cwd(), env = process.env) {
|
|
9
|
-
const explicitVaultDir = readAbsoluteEnv(env, MYCO_VAULT_DIR_ENV);
|
|
10
|
-
if (explicitVaultDir) return explicitVaultDir;
|
|
11
|
-
const explicitProjectRoot = readAbsoluteEnv(env, MYCO_PROJECT_ROOT_ENV);
|
|
12
|
-
if (explicitProjectRoot) return path.join(explicitProjectRoot, ".myco");
|
|
13
|
-
return path.join(resolveRepoRoot(cwd), ".myco");
|
|
14
|
-
}
|
|
15
|
-
function readAbsoluteEnv(env, key) {
|
|
16
|
-
const raw = env[key];
|
|
17
|
-
if (typeof raw !== "string" || raw.length === 0) return null;
|
|
18
|
-
return path.isAbsolute(raw) ? raw : null;
|
|
19
|
-
}
|
|
20
|
-
function resolveRepoRoot(cwd) {
|
|
21
|
-
try {
|
|
22
|
-
const gitCommon = execFileSync(
|
|
23
|
-
"git",
|
|
24
|
-
["rev-parse", "--git-common-dir"],
|
|
25
|
-
{ cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
26
|
-
).trim();
|
|
27
|
-
return path.resolve(cwd, gitCommon, "..");
|
|
28
|
-
} catch {
|
|
29
|
-
return cwd;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
resolveVaultDir
|
|
35
|
-
};
|
|
36
|
-
//# sourceMappingURL=chunk-CUDIZJY7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vault/resolve.ts"],"sourcesContent":["import path from 'node:path';\nimport { execFileSync } from 'node:child_process';\n\nexport const MYCO_PROJECT_ROOT_ENV = 'MYCO_PROJECT_ROOT';\nexport const MYCO_VAULT_DIR_ENV = 'MYCO_VAULT_DIR';\n\n/**\n * Resolve the vault directory.\n *\n * Always `.myco/` in the project root. The vault is a SQLite database\n * that lives with the project — no external overrides needed.\n *\n * Uses git to find the repo root so this works correctly in\n * git worktrees — worktree agents resolve to the same vault\n * as the main working tree. Some symbionts launch their MCP child with\n * cwd=/, so explicit env anchors win before any cwd-based fallback.\n */\nexport function resolveVaultDir(\n cwd = process.cwd(),\n env: NodeJS.ProcessEnv = process.env,\n): string {\n const explicitVaultDir = readAbsoluteEnv(env, MYCO_VAULT_DIR_ENV);\n if (explicitVaultDir) return explicitVaultDir;\n\n const explicitProjectRoot = readAbsoluteEnv(env, MYCO_PROJECT_ROOT_ENV);\n if (explicitProjectRoot) return path.join(explicitProjectRoot, '.myco');\n\n return path.join(resolveRepoRoot(cwd), '.myco');\n}\n\nfunction readAbsoluteEnv(\n env: NodeJS.ProcessEnv,\n key: string,\n): string | null {\n const raw = env[key];\n if (typeof raw !== 'string' || raw.length === 0) return null;\n return path.isAbsolute(raw) ? raw : null;\n}\n\n/**\n * Find the main repo root, even from a git worktree.\n *\n * `git rev-parse --git-common-dir` returns the shared .git directory:\n * - In a normal repo: \".git\" (relative)\n * - In a worktree: \"/abs/path/to/main-repo/.git\" (absolute)\n *\n * The repo root is the parent of that path.\n * Falls back to cwd if not in a git repo.\n */\nfunction resolveRepoRoot(cwd: string): string {\n try {\n const gitCommon = execFileSync(\n 'git', ['rev-parse', '--git-common-dir'],\n { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },\n ).trim();\n return path.resolve(cwd, gitCommon, '..');\n } catch {\n return cwd;\n }\n}\n"],"mappings":";;;AAAA,OAAO,UAAU;AACjB,SAAS,oBAAoB;AAEtB,IAAM,wBAAwB;AAC9B,IAAM,qBAAqB;AAa3B,SAAS,gBACd,MAAM,QAAQ,IAAI,GAClB,MAAyB,QAAQ,KACzB;AACR,QAAM,mBAAmB,gBAAgB,KAAK,kBAAkB;AAChE,MAAI,iBAAkB,QAAO;AAE7B,QAAM,sBAAsB,gBAAgB,KAAK,qBAAqB;AACtE,MAAI,oBAAqB,QAAO,KAAK,KAAK,qBAAqB,OAAO;AAEtE,SAAO,KAAK,KAAK,gBAAgB,GAAG,GAAG,OAAO;AAChD;AAEA,SAAS,gBACP,KACA,KACe;AACf,QAAM,MAAM,IAAI,GAAG;AACnB,MAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,EAAG,QAAO;AACxD,SAAO,KAAK,WAAW,GAAG,IAAI,MAAM;AACtC;AAYA,SAAS,gBAAgB,KAAqB;AAC5C,MAAI;AACF,UAAM,YAAY;AAAA,MAChB;AAAA,MAAO,CAAC,aAAa,kBAAkB;AAAA,MACvC,EAAE,KAAK,UAAU,SAAS,OAAO,CAAC,QAAQ,QAAQ,MAAM,EAAE;AAAA,IAC5D,EAAE,KAAK;AACP,WAAO,KAAK,QAAQ,KAAK,WAAW,IAAI;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/daemon/team-context.ts","../src/db/queries/team-outbox.ts","../src/db/queries/sessions.ts"],"sourcesContent":["/**\n * Module-level state for team sync.\n *\n * Initialized once by the daemon on startup. Query modules import\n * `isTeamSyncEnabled()` and `getTeamMachineId()` to decide whether\n * to enqueue outbox records on write.\n */\n\nimport { SYNC_PROTOCOL_VERSION, DEFAULT_MACHINE_ID } from '@myco/constants.js';\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n\nlet teamSyncEnabled = false;\nlet teamMachineId = DEFAULT_MACHINE_ID;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Initialize team context. Called once on daemon startup.\n */\nexport function initTeamContext(enabled: boolean, machineId: string): void {\n teamSyncEnabled = enabled;\n teamMachineId = machineId;\n}\n\n/**\n * Whether team sync is currently enabled.\n *\n * Query modules check this before enqueuing outbox records.\n */\nexport function isTeamSyncEnabled(): boolean {\n return teamSyncEnabled;\n}\n\n/**\n * The machine ID for this instance.\n */\nexport function getTeamMachineId(): string {\n return teamMachineId;\n}\n\n/**\n * The sync protocol version in use.\n */\nexport function getTeamSyncProtocolVersion(): number {\n return SYNC_PROTOCOL_VERSION;\n}\n\n/**\n * Reset team context (for testing).\n */\nexport function resetTeamContext(): void {\n teamSyncEnabled = false;\n teamMachineId = DEFAULT_MACHINE_ID;\n}\n","/**\n * Team outbox CRUD query helpers.\n *\n * The outbox pattern: write paths enqueue records here when team sync is enabled.\n * The sync client flushes pending records in batches to the Cloudflare Worker.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { isTeamSyncEnabled, getTeamMachineId } from '@myco/daemon/team-context.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Max records returned per listPending call. */\nconst BURST_BATCH_SIZE = 200;\n\n/** Age in seconds after which sent records are pruned (24 hours). */\nconst SENT_PRUNE_AGE_SECONDS = 86_400;\n\n/** Max retry attempts before a record is dead-lettered. */\nexport const MAX_OUTBOX_RETRIES = 10;\n\n/** Milliseconds-per-second multiplier for epoch math. */\nconst MS_PER_SECOND = 1000;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required when enqueuing an outbox record. */\nexport interface OutboxInsert {\n table_name: string;\n row_id: string;\n operation?: string;\n payload: string;\n machine_id: string;\n created_at: number;\n}\n\n/** Row shape returned from outbox queries. */\nexport interface OutboxRow {\n id: number;\n table_name: string;\n row_id: string;\n operation: string;\n payload: string;\n machine_id: string;\n created_at: number;\n sent_at: number | null;\n retry_count: number;\n last_attempt_at: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst OUTBOX_COLUMNS = [\n 'id',\n 'table_name',\n 'row_id',\n 'operation',\n 'payload',\n 'machine_id',\n 'created_at',\n 'sent_at',\n 'retry_count',\n 'last_attempt_at',\n] as const;\n\nconst SELECT_COLUMNS = OUTBOX_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Normalize a SQLite result row into a typed OutboxRow. */\nfunction toOutboxRow(row: Record<string, unknown>): OutboxRow {\n return {\n id: row.id as number,\n table_name: row.table_name as string,\n row_id: row.row_id as string,\n operation: row.operation as string,\n payload: row.payload as string,\n machine_id: row.machine_id as string,\n created_at: row.created_at as number,\n sent_at: (row.sent_at as number) ?? null,\n retry_count: (row.retry_count as number) ?? 0,\n last_attempt_at: (row.last_attempt_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Convenience helper — used by query modules\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue a row for team sync if sync is enabled.\n *\n * Centralizes the if-enabled / enqueue / serialize pattern that every\n * write-path query module previously duplicated inline.\n */\nexport function syncRow(tableName: string, row: { id: string | number; created_at?: number }): void {\n if (!isTeamSyncEnabled()) return;\n enqueueOutbox({\n table_name: tableName,\n row_id: String(row.id),\n payload: JSON.stringify(row),\n machine_id: getTeamMachineId(),\n created_at: row.created_at ?? Math.floor(Date.now() / 1000),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue a record into the team outbox for later sync.\n *\n * Inserted with `sent_at = NULL` (pending).\n */\nexport function enqueueOutbox(data: OutboxInsert): OutboxRow {\n const db = getDatabase();\n\n const info = db.prepare(\n `INSERT INTO team_outbox (\n table_name, row_id, operation, payload, machine_id, created_at\n ) VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(\n data.table_name,\n data.row_id,\n data.operation ?? 'upsert',\n data.payload,\n data.machine_id,\n data.created_at,\n );\n\n const id = Number(info.lastInsertRowid);\n\n return toOutboxRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM team_outbox WHERE id = ?`).get(id) as Record<string, unknown>,\n );\n}\n\n/**\n * List pending outbox records (oldest-first).\n *\n * Uses burst sizing: fetches BURST_BATCH_SIZE rows and returns them all.\n * If fewer than BURST_THRESHOLD rows come back, callers get a normal-size\n * batch; if more, the full burst. This avoids a separate COUNT query.\n */\nexport function listPending(limit?: number): OutboxRow[] {\n const db = getDatabase();\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM team_outbox\n WHERE sent_at IS NULL AND retry_count < ?\n ORDER BY created_at ASC\n LIMIT ?`,\n ).all(MAX_OUTBOX_RETRIES, limit ?? BURST_BATCH_SIZE) as Record<string, unknown>[];\n\n return rows.map(toOutboxRow);\n}\n\n/**\n * Mark outbox records as sent by setting sent_at.\n */\nexport function markSent(ids: number[], sentAt: number): void {\n if (ids.length === 0) return;\n\n const db = getDatabase();\n const placeholders = ids.map(() => '?').join(', ');\n\n db.prepare(\n `UPDATE team_outbox\n SET sent_at = ?\n WHERE id IN (${placeholders})`,\n ).run(sentAt, ...ids);\n}\n\n/**\n * Reset sent_at to NULL for records that need to be retried.\n *\n * This allows the sync client to re-enqueue specific records for retry.\n */\nexport function markForRetry(ids: number[]): void {\n if (ids.length === 0) return;\n\n const db = getDatabase();\n const placeholders = ids.map(() => '?').join(', ');\n\n db.prepare(\n `UPDATE team_outbox\n SET sent_at = NULL\n WHERE id IN (${placeholders})`,\n ).run(...ids);\n}\n\n/**\n * Increment retry_count and set last_attempt_at for failed outbox records.\n *\n * @returns IDs of records that have now reached MAX_OUTBOX_RETRIES (newly dead-lettered).\n */\nexport function incrementRetryCount(ids: number[], attemptAt: number): number[] {\n if (ids.length === 0) return [];\n\n const db = getDatabase();\n const placeholders = ids.map(() => '?').join(', ');\n\n db.prepare(\n `UPDATE team_outbox\n SET retry_count = retry_count + 1, last_attempt_at = ?\n WHERE id IN (${placeholders})`,\n ).run(attemptAt, ...ids);\n\n // Return IDs that just hit the threshold\n const deadLettered = db.prepare(\n `SELECT id FROM team_outbox\n WHERE id IN (${placeholders}) AND retry_count >= ?`,\n ).all(...ids, MAX_OUTBOX_RETRIES) as Array<{ id: number }>;\n\n return deadLettered.map((r) => r.id);\n}\n\n/**\n * Reset all dead-lettered records back to pending for retry.\n *\n * @returns the number of records reset.\n */\nexport function retryDeadLettered(): number {\n const db = getDatabase();\n\n const info = db.prepare(\n `UPDATE team_outbox\n SET retry_count = 0, last_attempt_at = NULL\n WHERE sent_at IS NULL AND retry_count >= ?`,\n ).run(MAX_OUTBOX_RETRIES);\n\n return info.changes;\n}\n\n/**\n * Count dead-lettered outbox records (exceeded max retries, never sent).\n */\nexport function countDeadLettered(): number {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM team_outbox WHERE sent_at IS NULL AND retry_count >= ?`,\n ).get(MAX_OUTBOX_RETRIES) as { count: number };\n\n return row.count;\n}\n\n/**\n * Prune old outbox records.\n *\n * Removes sent records older than 24 hours.\n *\n * @returns the number of records deleted.\n */\nexport function pruneOld(): number {\n const db = getDatabase();\n const cutoff = Math.floor(Date.now() / MS_PER_SECOND) - SENT_PRUNE_AGE_SECONDS;\n\n const info = db.prepare(\n `DELETE FROM team_outbox\n WHERE sent_at IS NOT NULL AND sent_at < ?`,\n ).run(cutoff);\n\n return info.changes;\n}\n\n/**\n * Count pending (unsent) outbox records.\n */\nexport function countPending(): number {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM team_outbox WHERE sent_at IS NULL AND retry_count < ?`,\n ).get(MAX_OUTBOX_RETRIES) as { count: number };\n\n return row.count;\n}\n\n// ---------------------------------------------------------------------------\n// Source-row sync bookkeeping\n// ---------------------------------------------------------------------------\n\n/** Tables eligible for backfill/sync (must have id, machine_id, synced_at columns). */\nconst BACKFILL_TABLES = [\n 'sessions',\n 'prompt_batches',\n 'spores',\n 'entities',\n 'graph_edges',\n 'resolution_events',\n 'plans',\n 'artifacts',\n 'digest_extracts',\n 'skill_candidates',\n 'skill_records',\n] as const;\n// entity_mentions excluded — no `id` column (composite key entity_id+note_id+note_type)\n// skill_usage excluded — no `synced_at` column (syncs via syncRow on insert)\n\nconst BACKFILL_TABLE_SET = new Set<string>(BACKFILL_TABLES);\n\n/**\n * Mark source rows as synced after successful outbox flush.\n *\n * Groups outbox records by table_name, then sets `synced_at` on the\n * corresponding source rows. This closes the re-enqueue loop: once\n * synced_at is non-NULL, `backfillUnsynced` skips the row even after\n * the outbox entry is pruned.\n */\nexport function markSourceRowsSynced(records: OutboxRow[], syncedAt: number): void {\n const db = getDatabase();\n\n // Group row_ids by table\n const byTable = new Map<string, string[]>();\n for (const rec of records) {\n if (!BACKFILL_TABLE_SET.has(rec.table_name)) continue;\n const ids = byTable.get(rec.table_name) ?? [];\n ids.push(rec.row_id);\n byTable.set(rec.table_name, ids);\n }\n\n for (const [table, ids] of byTable) {\n const placeholders = ids.map(() => '?').join(', ');\n db.prepare(\n `UPDATE ${table} SET synced_at = ? WHERE id IN (${placeholders}) AND synced_at IS NULL`,\n ).run(syncedAt, ...ids);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Backfill\n// ---------------------------------------------------------------------------\n\n/**\n * Enqueue all unsynced records across all synced tables into the outbox.\n *\n * Scans each table for rows where `synced_at IS NULL`, serializes the full\n * row as JSON, and inserts into the outbox. Idempotent — re-running only\n * picks up rows not yet in the outbox (checked via existing outbox entries).\n *\n * @returns the total number of records enqueued.\n */\nexport function backfillUnsynced(machineId: string): number {\n const db = getDatabase();\n let total = 0;\n\n const now = Math.floor(Date.now() / MS_PER_SECOND);\n\n // Process one table at a time in separate transactions to avoid long locks\n for (const table of BACKFILL_TABLES) {\n const rows = db.prepare(\n `SELECT * FROM ${table}\n WHERE synced_at IS NULL\n AND NOT EXISTS (\n SELECT 1 FROM team_outbox\n WHERE team_outbox.table_name = ? AND team_outbox.row_id = CAST(${table}.id AS TEXT)\n )`,\n ).all(table) as Record<string, unknown>[];\n\n if (rows.length === 0) continue;\n\n const insertBatch = db.transaction((batchRows: Record<string, unknown>[]) => {\n const stmt = db.prepare(\n `INSERT INTO team_outbox (table_name, row_id, operation, payload, machine_id, created_at)\n VALUES (?, ?, 'upsert', ?, ?, ?)`,\n );\n for (const row of batchRows) {\n stmt.run(table, String(row.id), JSON.stringify(row), machineId, now);\n }\n });\n\n insertBatch(rows);\n total += rows.length;\n }\n\n return total;\n}\n\n","/**\n * Session CRUD query helpers.\n *\n * All functions obtain the SQLite instance internally via `getDatabase()`.\n * Queries use positional `?` placeholders throughout (better-sqlite3).\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { getTeamMachineId } from '@myco/daemon/team-context.js';\nimport { syncRow } from '@myco/db/queries/team-outbox.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Default number of sessions returned by listSessions when no limit given. */\nconst DEFAULT_LIST_LIMIT = 100;\n\n/** Session status value when a session is closed normally. */\nconst STATUS_COMPLETED = 'completed';\n\n/** Default session status for new sessions. */\nconst DEFAULT_STATUS = 'active';\n\n/** Default prompt count for new sessions. */\nconst DEFAULT_PROMPT_COUNT = 0;\n\n/** Default tool count for new sessions. */\nconst DEFAULT_TOOL_COUNT = 0;\n\n/** Default processed flag for new sessions. */\nconst DEFAULT_PROCESSED = 0;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Fields required (or optional) when inserting/upserting a session. */\nexport interface SessionInsert {\n id: string;\n agent: string;\n started_at: number;\n created_at: number;\n user?: string | null;\n project_root?: string | null;\n branch?: string | null;\n ended_at?: number | null;\n status?: string;\n prompt_count?: number;\n tool_count?: number;\n title?: string | null;\n summary?: string | null;\n transcript_path?: string | null;\n parent_session_id?: string | null;\n parent_session_reason?: string | null;\n processed?: number;\n content_hash?: string | null;\n machine_id?: string;\n}\n\n/** Row shape returned from session queries (all columns). */\nexport interface SessionRow {\n id: string;\n agent: string;\n user: string | null;\n project_root: string | null;\n branch: string | null;\n started_at: number;\n ended_at: number | null;\n status: string;\n prompt_count: number;\n tool_count: number;\n title: string | null;\n summary: string | null;\n transcript_path: string | null;\n parent_session_id: string | null;\n parent_session_reason: string | null;\n processed: number;\n content_hash: string | null;\n embedded: number;\n created_at: number;\n machine_id: string;\n synced_at: number | null;\n}\n\n/** Updatable fields for `updateSession`. */\nexport interface SessionUpdate {\n agent?: string;\n user?: string | null;\n project_root?: string | null;\n branch?: string | null;\n ended_at?: number | null;\n status?: string;\n prompt_count?: number;\n tool_count?: number;\n title?: string | null;\n summary?: string | null;\n transcript_path?: string | null;\n parent_session_id?: string | null;\n parent_session_reason?: string | null;\n processed?: number;\n content_hash?: string | null;\n}\n\n/** Filter options for `listSessions`. */\nexport interface ListSessionsOptions {\n limit?: number;\n offset?: number;\n status?: string;\n agent?: string;\n search?: string;\n /** Filter to sessions that ran on this git branch. */\n branch?: string;\n /** Filter to sessions authored by this user. */\n user?: string;\n /** Filter to this exact session id (used for plan→session resolution). */\n id?: string;\n /** Only return sessions created after this epoch-seconds timestamp. */\n since?: number;\n /**\n * When explicitly `false` and no `status` filter is set, exclude sessions\n * still in `status = 'active'` — intelligence-task reads opt in to this.\n * Defaults permissive so UI listings keep showing in-flight sessions.\n */\n includeActive?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Column list\n// ---------------------------------------------------------------------------\n\nconst SESSION_COLUMNS = [\n 'id',\n 'agent',\n '\"user\"',\n 'project_root',\n 'branch',\n 'started_at',\n 'ended_at',\n 'status',\n 'prompt_count',\n 'tool_count',\n 'title',\n 'summary',\n 'transcript_path',\n 'parent_session_id',\n 'parent_session_reason',\n 'processed',\n 'content_hash',\n 'embedded',\n 'created_at',\n 'machine_id',\n 'synced_at',\n] as const;\n\nconst SELECT_COLUMNS = SESSION_COLUMNS.join(', ');\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a SQLite result row into a typed SessionRow.\n *\n * The quoted \"user\" column comes back as `user` in the result object.\n */\nfunction toSessionRow(row: Record<string, unknown>): SessionRow {\n return {\n id: row.id as string,\n agent: row.agent as string,\n user: (row.user as string) ?? null,\n project_root: (row.project_root as string) ?? null,\n branch: (row.branch as string) ?? null,\n started_at: row.started_at as number,\n ended_at: (row.ended_at as number) ?? null,\n status: row.status as string,\n prompt_count: row.prompt_count as number,\n tool_count: row.tool_count as number,\n title: (row.title as string) ?? null,\n summary: (row.summary as string) ?? null,\n transcript_path: (row.transcript_path as string) ?? null,\n parent_session_id: (row.parent_session_id as string) ?? null,\n parent_session_reason: (row.parent_session_reason as string) ?? null,\n processed: row.processed as number,\n content_hash: (row.content_hash as string) ?? null,\n embedded: (row.embedded as number) ?? 0,\n created_at: row.created_at as number,\n machine_id: (row.machine_id as string) ?? 'local',\n synced_at: (row.synced_at as number) ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Insert a session or update it if the id already exists.\n *\n * On conflict the row is updated with the values from `data`, preserving\n * any columns not supplied via COALESCE with EXCLUDED values.\n */\nexport function upsertSession(data: SessionInsert): SessionRow {\n const db = getDatabase();\n\n db.prepare(\n `INSERT INTO sessions (\n id, agent, \"user\", project_root, branch,\n started_at, ended_at, status, prompt_count, tool_count,\n title, summary, transcript_path,\n parent_session_id, parent_session_reason,\n processed, content_hash, created_at, machine_id\n ) VALUES (\n ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?, ?,\n ?, ?,\n ?, ?, ?, ?\n )\n ON CONFLICT (id) DO UPDATE SET\n agent = EXCLUDED.agent,\n \"user\" = EXCLUDED.\"user\",\n project_root = EXCLUDED.project_root,\n branch = EXCLUDED.branch,\n started_at = EXCLUDED.started_at,\n ended_at = COALESCE(EXCLUDED.ended_at, sessions.ended_at),\n status = COALESCE(EXCLUDED.status, sessions.status),\n prompt_count = CASE WHEN ? THEN EXCLUDED.prompt_count ELSE sessions.prompt_count END,\n tool_count = CASE WHEN ? THEN EXCLUDED.tool_count ELSE sessions.tool_count END,\n title = COALESCE(EXCLUDED.title, sessions.title),\n summary = COALESCE(EXCLUDED.summary, sessions.summary),\n transcript_path = COALESCE(EXCLUDED.transcript_path, sessions.transcript_path),\n parent_session_id = EXCLUDED.parent_session_id,\n parent_session_reason = EXCLUDED.parent_session_reason,\n processed = COALESCE(EXCLUDED.processed, sessions.processed),\n content_hash = EXCLUDED.content_hash`,\n ).run(\n data.id,\n data.agent,\n data.user ?? null,\n data.project_root ?? null,\n data.branch ?? null,\n data.started_at,\n data.ended_at ?? null,\n data.status ?? DEFAULT_STATUS,\n data.prompt_count ?? DEFAULT_PROMPT_COUNT,\n data.tool_count ?? DEFAULT_TOOL_COUNT,\n data.title ?? null,\n data.summary ?? null,\n data.transcript_path ?? null,\n data.parent_session_id ?? null,\n data.parent_session_reason ?? null,\n data.processed ?? DEFAULT_PROCESSED,\n data.content_hash ?? null,\n data.created_at,\n data.machine_id ?? getTeamMachineId(),\n data.prompt_count !== undefined ? 1 : 0,\n data.tool_count !== undefined ? 1 : 0,\n );\n\n const row = toSessionRow(\n db.prepare(`SELECT ${SELECT_COLUMNS} FROM sessions WHERE id = ?`).get(data.id) as Record<string, unknown>,\n );\n\n syncRow('sessions', row);\n\n return row;\n}\n\n/**\n * Retrieve a single session by id.\n *\n * @returns the session row, or null if not found.\n */\nexport function getSession(id: string): SessionRow | null {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM sessions WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n\n if (!row) return null;\n return toSessionRow(row);\n}\n\n/** Build WHERE clause and bound params from session filter options. */\nfunction buildSessionsWhere(\n options: Omit<ListSessionsOptions, 'limit' | 'offset'>,\n): { where: string; params: unknown[] } {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (options.status !== undefined) {\n conditions.push(`status = ?`);\n params.push(options.status);\n }\n\n if (options.agent !== undefined) {\n conditions.push(`agent = ?`);\n params.push(options.agent);\n }\n\n if (options.branch !== undefined) {\n conditions.push(`branch = ?`);\n params.push(options.branch);\n }\n\n if (options.user !== undefined) {\n conditions.push(`\"user\" = ?`);\n params.push(options.user);\n }\n\n if (options.id !== undefined) {\n conditions.push(`id = ?`);\n params.push(options.id);\n }\n\n if (options.search !== undefined && options.search.length > 0) {\n conditions.push(`(title LIKE ? OR id LIKE ?)`);\n const pattern = `%${options.search}%`;\n params.push(pattern, pattern);\n }\n if (options.since !== undefined) {\n conditions.push('created_at > ?');\n params.push(options.since);\n }\n\n // Exclude active sessions only when the caller explicitly opts in and\n // hasn't already constrained `status`. Intelligence-task reads set this\n // to avoid picking up in-flight work; UI/CLI leave it unset.\n if (options.includeActive === false && options.status === undefined) {\n conditions.push(`status != 'active'`);\n }\n\n return {\n where: conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '',\n params,\n };\n}\n\n/**\n * List sessions with optional filters, ordered by created_at DESC.\n */\nexport function listSessions(\n options: ListSessionsOptions = {},\n): SessionRow[] {\n const db = getDatabase();\n const { where, params } = buildSessionsWhere(options);\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n const offset = options.offset ?? 0;\n\n const rows = db.prepare(\n `SELECT ${SELECT_COLUMNS}\n FROM sessions\n ${where}\n ORDER BY created_at DESC\n LIMIT ?\n OFFSET ?`,\n ).all(...params, limit, offset) as Record<string, unknown>[];\n\n return rows.map(toSessionRow);\n}\n\n/**\n * Count sessions matching optional filters (for pagination totals).\n */\nexport function countSessions(\n options: Omit<ListSessionsOptions, 'limit' | 'offset'> = {},\n): number {\n const db = getDatabase();\n const { where, params } = buildSessionsWhere(options);\n\n const row = db.prepare(\n `SELECT COUNT(*) as count FROM sessions ${where}`,\n ).get(...params) as { count: number };\n\n return row.count;\n}\n\n/**\n * Return the set of session IDs currently in `status = 'active'`.\n *\n * Used by the semantic-search path, which can't apply a SQL join against\n * session status (the vector store is a separate concern), so it filters\n * results in-memory against this set instead. Bounded by the number of\n * concurrent in-flight sessions — typically small.\n */\nexport function getActiveSessionIds(): Set<string> {\n const db = getDatabase();\n const rows = db.prepare(\n `SELECT id FROM sessions WHERE status = 'active'`,\n ).all() as Array<{ id: string }>;\n return new Set(rows.map((r) => r.id));\n}\n\n/**\n * Flip a session back to `status = 'active'` if it's currently `'completed'`.\n *\n * Called on live user activity (`user_prompt` events) so a session that was\n * auto-completed by the stale sweep or manually completed via the API snaps\n * back to active transparently when the user resumes. No-op for sessions\n * that are already active or don't exist.\n *\n * The `ended_at` column is intentionally preserved — it records the most\n * recent completion time, and the next completion will overwrite it.\n *\n * @returns true if a row was updated (session was completed and is now active)\n */\nexport function reactivateSessionIfCompleted(id: string): boolean {\n const db = getDatabase();\n const info = db.prepare(\n `UPDATE sessions SET status = 'active' WHERE id = ? AND status = 'completed'`,\n ).run(id);\n if (info.changes === 0) return false;\n\n const row = db.prepare(\n `SELECT ${SELECT_COLUMNS} FROM sessions WHERE id = ?`,\n ).get(id) as Record<string, unknown> | undefined;\n if (row) syncRow('sessions', toSessionRow(row));\n\n return true;\n}\n\n/**\n * Update specific fields on an existing session.\n *\n * @returns the updated row, or null if the session does not exist.\n */\nexport function updateSession(\n id: string,\n updates: SessionUpdate,\n): SessionRow | null {\n const db = getDatabase();\n\n const setClauses: string[] = [];\n const params: unknown[] = [];\n\n const fieldMap: Record<string, string> = {\n agent: 'agent',\n user: '\"user\"',\n project_root: 'project_root',\n branch: 'branch',\n ended_at: 'ended_at',\n status: 'status',\n prompt_count: 'prompt_count',\n tool_count: 'tool_count',\n title: 'title',\n summary: 'summary',\n transcript_path: 'transcript_path',\n parent_session_id: 'parent_session_id',\n parent_session_reason: 'parent_session_reason',\n processed: 'processed',\n content_hash: 'content_hash',\n };\n\n for (const [key, column] of Object.entries(fieldMap)) {\n if (key in updates) {\n setClauses.push(`${column} = ?`);\n params.push((updates as Record<string, unknown>)[key] ?? null);\n }\n }\n\n if (setClauses.length === 0) return getSession(id);\n\n params.push(id);\n\n db.prepare(\n `UPDATE sessions\n SET ${setClauses.join(', ')}\n WHERE id = ?`,\n ).run(...params);\n\n const updated = getSession(id);\n\n if (updated) syncRow('sessions', updated);\n\n return updated;\n}\n\n/**\n * Atomically increment tool_count for a session.\n *\n * Uses SQL `tool_count + 1` to avoid read-modify-write races.\n */\nexport function incrementSessionToolCount(id: string): void {\n const db = getDatabase();\n db.prepare(\n `UPDATE sessions SET tool_count = COALESCE(tool_count, 0) + 1 WHERE id = ?`,\n ).run(id);\n}\n\n/**\n * Close a session — set status to 'completed' and record the end time.\n *\n * @returns the updated row, or null if the session does not exist.\n */\nexport function closeSession(\n id: string,\n endedAt: number,\n): SessionRow | null {\n const db = getDatabase();\n\n db.prepare(\n `UPDATE sessions\n SET status = ?, ended_at = ?\n WHERE id = ?`,\n ).run(STATUS_COMPLETED, endedAt, id);\n\n const closed = getSession(id);\n\n if (closed) syncRow('sessions', closed);\n\n return closed;\n}\n\n/**\n * Delete a session and all its child rows (batches, activities, attachments).\n *\n * No ON DELETE CASCADE in the schema, so we delete children first.\n * Returns true if the session existed and was deleted.\n */\nexport function deleteSession(id: string): boolean {\n const db = getDatabase();\n\n db.prepare(`DELETE FROM activities WHERE session_id = ?`).run(id);\n db.prepare(`DELETE FROM attachments WHERE session_id = ?`).run(id);\n db.prepare(`DELETE FROM prompt_batches WHERE session_id = ?`).run(id);\n const info = db.prepare(`DELETE FROM sessions WHERE id = ?`).run(id);\n\n return info.changes > 0;\n}\n\n// ---------------------------------------------------------------------------\n// Cascade delete + impact query\n// ---------------------------------------------------------------------------\n\n/** Counts of related data that would be affected by a session delete. */\nexport interface SessionImpact {\n promptCount: number;\n sporeCount: number;\n attachmentCount: number;\n graphEdgeCount: number;\n}\n\n/** Result of a cascade delete operation. */\nexport interface DeleteCascadeResult {\n deleted: boolean;\n counts: {\n prompts: number;\n spores: number;\n attachments: number;\n graphEdges: number;\n resolutionEvents: number;\n };\n /** Spore IDs that were deleted (needed for vault file + vector cleanup). */\n deletedSporeIds: string[];\n /** Attachment file paths that were deleted from DB (needed for disk cleanup). */\n deletedAttachmentPaths: string[];\n}\n\n/**\n * Get counts of all data related to a session, for pre-delete impact display.\n */\nexport function getSessionImpact(sessionId: string): SessionImpact {\n const db = getDatabase();\n\n const row = db.prepare(\n `SELECT\n (SELECT COUNT(*) FROM prompt_batches WHERE session_id = ?) AS promptCount,\n (SELECT COUNT(*) FROM spores WHERE session_id = ?) AS sporeCount,\n (SELECT COUNT(*) FROM attachments WHERE session_id = ?) AS attachmentCount,\n (SELECT COUNT(*) FROM graph_edges WHERE session_id = ?) AS graphEdgeCount`,\n ).get(sessionId, sessionId, sessionId, sessionId) as SessionImpact;\n\n return row;\n}\n\n/**\n * Delete a session and ALL related data in a single transaction.\n *\n * Returns counts of deleted rows and IDs needed for post-transaction\n * cleanup (vault files, embedding vectors).\n */\nexport function deleteSessionCascade(sessionId: string): DeleteCascadeResult {\n const db = getDatabase();\n\n const zeroCounts: DeleteCascadeResult = {\n deleted: false,\n counts: { prompts: 0, spores: 0, attachments: 0, graphEdges: 0, resolutionEvents: 0 },\n deletedSporeIds: [],\n deletedAttachmentPaths: [],\n };\n\n // Check session exists first\n const exists = db.prepare(`SELECT id FROM sessions WHERE id = ?`).get(sessionId);\n if (!exists) return zeroCounts;\n\n // Collect IDs/paths needed for post-transaction cleanup before deleting.\n // Spores can reference prompt_batches from a different session (cross-session\n // spore linkage), so we must also collect spores linked via prompt_batch_id.\n const sporeIds = (db.prepare(\n `SELECT id FROM spores\n WHERE session_id = ?\n OR prompt_batch_id IN (SELECT id FROM prompt_batches WHERE session_id = ?)`,\n ).all(sessionId, sessionId) as { id: string }[]).map((r) => r.id);\n\n const attachmentPaths = (db.prepare(\n `SELECT file_path FROM attachments WHERE session_id = ?`,\n ).all(sessionId) as { file_path: string }[]).map((r) => r.file_path);\n\n // Run all deletes in a single transaction.\n //\n // Order matters — foreign_keys = ON is set in client.ts, so every DELETE\n // is checked immediately. Child rows must be removed before their parents:\n // - spores.prompt_batch_id → prompt_batches(id) [spores BEFORE prompt_batches]\n // - plans.prompt_batch_id → prompt_batches(id) [plans BEFORE prompt_batches]\n // - resolution_events.spore_id → spores(id) [resolution_events BEFORE spores]\n // - skill_usage.session_id → sessions(id) NOT NULL\n // - plans.session_id → sessions(id)\n // resolution_events can reference spores across sessions (e.g. a later\n // session supersedes an earlier session's spore), so we match by either\n // session_id OR spore_id-in-this-session to catch cross-session references.\n //\n // Spores can also reference prompt_batches from a different session\n // (cross-session prompt_batch_id linkage). We must delete those spores\n // BEFORE deleting prompt_batches to avoid FK violations.\n const result = db.transaction(() => {\n db.prepare(`DELETE FROM activities WHERE session_id = ?`).run(sessionId);\n const attachments = db.prepare(`DELETE FROM attachments WHERE session_id = ?`).run(sessionId);\n db.prepare(`DELETE FROM plans WHERE session_id = ?`).run(sessionId);\n db.prepare(`DELETE FROM skill_usage WHERE session_id = ?`).run(sessionId);\n const resEvents = db.prepare(\n `DELETE FROM resolution_events\n WHERE session_id = ?\n OR spore_id IN (\n SELECT id FROM spores\n WHERE session_id = ?\n OR prompt_batch_id IN (SELECT id FROM prompt_batches WHERE session_id = ?)\n )`,\n ).run(sessionId, sessionId, sessionId);\n const edges = db.prepare(`DELETE FROM graph_edges WHERE session_id = ?`).run(sessionId);\n const spores = db.prepare(\n `DELETE FROM spores\n WHERE session_id = ?\n OR prompt_batch_id IN (SELECT id FROM prompt_batches WHERE session_id = ?)`,\n ).run(sessionId, sessionId);\n const prompts = db.prepare(`DELETE FROM prompt_batches WHERE session_id = ?`).run(sessionId);\n const session = db.prepare(`DELETE FROM sessions WHERE id = ?`).run(sessionId);\n\n return {\n deleted: session.changes > 0,\n counts: {\n prompts: prompts.changes,\n spores: spores.changes,\n attachments: attachments.changes,\n graphEdges: edges.changes,\n resolutionEvents: resEvents.changes,\n },\n };\n })();\n\n return {\n ...result,\n deletedSporeIds: sporeIds,\n deletedAttachmentPaths: attachmentPaths,\n };\n}\n"],"mappings":"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","names":["SELECT_COLUMNS"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/update.ts","../src/constants.ts"],"sourcesContent":["import path from 'node:path';\nimport os from 'node:os';\n\n/** npm registry base URL for Myco packages. */\nexport const NPM_REGISTRY_BASE_URL = 'https://registry.npmjs.org';\n\n/** Global Myco directory for machine-wide state. */\nexport const MYCO_GLOBAL_DIR = path.join(os.homedir(), '.myco');\n\n/** Path to the cached update check result. */\nexport const UPDATE_CHECK_CACHE_PATH = path.join(MYCO_GLOBAL_DIR, 'last-update-check.json');\n\n/** Path to the update configuration file (channel, interval). */\nexport const UPDATE_CONFIG_PATH = path.join(MYCO_GLOBAL_DIR, 'update.yaml');\n\n/** Path to the update error file (written by update script on failure). */\nexport const UPDATE_ERROR_PATH = path.join(MYCO_GLOBAL_DIR, 'update-error.json');\n\n/** Filename for the version stamp written by `myco update` (lives inside vault .myco/). */\nexport const UPDATE_STAMP_FILENAME = 'last-update-version';\n\n/** Filename for the restart reason signal file (lives inside vault .myco/). */\nexport const RESTART_REASON_FILENAME = 'restart-reason.json';\n\n/** Default check interval in hours. */\nexport const UPDATE_CHECK_INTERVAL_HOURS = 6;\n\n/** Milliseconds per hour. */\nexport const MS_PER_HOUR = 3_600_000;\n\n/** Primary Myco npm package name. */\nexport const NPM_PACKAGE_NAME = '@goondocks/myco';\n\n/** Optional standalone Myco Team package name. */\nexport const TEAM_PACKAGE_NAME = '@goondocks/myco-team';\n\n/** Optional standalone Myco Collective package name. */\nexport const COLLECTIVE_PACKAGE_NAME = '@goondocks/myco-collective';\n\n/** Global-package update targets shown in the Operations UI. */\nexport const UPDATE_PACKAGES = [\n { id: 'myco', packageName: NPM_PACKAGE_NAME, displayName: 'Myco' },\n { id: 'myco-team', packageName: TEAM_PACKAGE_NAME, displayName: 'Myco Team' },\n { id: 'myco-collective', packageName: COLLECTIVE_PACKAGE_NAME, displayName: 'Myco Collective' },\n] as const;\nexport type UpdatePackageId = (typeof UPDATE_PACKAGES)[number]['id'];\n\n/** Delay in seconds before update script starts (allows daemon to exit). */\nexport const UPDATE_SCRIPT_DELAY_SECONDS = 2;\n\n/** Valid release channels. */\nexport const RELEASE_CHANNELS = ['stable', 'beta'] as const;\nexport type ReleaseChannel = (typeof RELEASE_CHANNELS)[number];\n\n/** Default release channel. */\nexport const DEFAULT_RELEASE_CHANNEL: ReleaseChannel = 'stable';\n","/**\n * Shared constants for the Myco codebase.\n * Per CLAUDE.md: \"No Magic Literals — Numeric and string constants\n * MUST NOT appear inline in logic.\"\n */\n\nexport { LOG_KINDS, type LogKind, kindToComponent } from './constants/log-kinds.js';\n\n// --- Agent phase prompt composition ---\n/**\n * Maximum chars per phase summary passed to subsequent phases.\n * Set to 4000 to ensure the digest-assess phase findings pass\n * untruncated to parallel tier phases.\n */\nexport const PHASE_SUMMARY_MAX_CHARS = 4000;\n\n// --- Token estimation ---\n/** Approximate characters per token for the chars/4 heuristic. */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Estimate token count from character length using the CHARS_PER_TOKEN heuristic. */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\n// --- Time (primitives — must precede derived constants) ---\n/** Milliseconds per second. */\nexport const MS_PER_SECOND = 1000;\n\n// --- Embedding ---\n/** Max characters of text sent to the embedding model. */\nexport const EMBEDDING_INPUT_LIMIT = 8000;\n\n/** Max rows per embedding worker cycle. */\nexport const EMBEDDING_BATCH_SIZE = 10;\n\n/** Content hash algorithm for staleness detection. */\nexport const CONTENT_HASH_ALGORITHM = 'sha256';\n\n// --- Truncation limits (display/preview) ---\n/** Max chars for a user prompt preview in event summaries. */\nexport const PROMPT_PREVIEW_CHARS = 300;\n/** Max chars for an AI response preview in event summaries. */\nexport const AI_RESPONSE_PREVIEW_CHARS = 500;\n/** Max chars for a command string preview. */\nexport const COMMAND_PREVIEW_CHARS = 80;\n/** Max chars for a content snippet in search results. */\nexport const CONTENT_SNIPPET_CHARS = 120;\n/** Max chars for a tool output preview in hooks. */\nexport const TOOL_OUTPUT_PREVIEW_CHARS = 200;\n/** Max chars for a session summary preview in MCP tools. */\nexport const SESSION_SUMMARY_PREVIEW_CHARS = 300;\n/** Max chars for a recall summary preview. */\nexport const RECALL_SUMMARY_PREVIEW_CHARS = 200;\n/** Max chars for search result and hydrated context previews. */\nexport const SEARCH_PREVIEW_CHARS = 300;\n\n// --- Log preview limits (short previews for structured log fields) ---\n/** Max chars for a user prompt preview in log entries. */\nexport const LOG_PROMPT_PREVIEW_CHARS = 50;\n/** Max chars for an assistant message preview in log entries. */\nexport const LOG_MESSAGE_PREVIEW_CHARS = 80;\n\n// --- Context injection layer budgets (chars, not tokens — used with .slice()) ---\nexport const CONTEXT_SESSION_PREVIEW_CHARS = 80;\nexport const CONTEXT_SPORE_PREVIEW_CHARS = 80;\n\n// --- Processor maxTokens budgets ---\n/** Response token budget for observation extraction. */\nexport const EXTRACTION_MAX_TOKENS = 2048;\n/** Response token budget for session summary. */\nexport const SUMMARY_MAX_TOKENS = 512;\n/** Response token budget for session title generation. */\nexport const TITLE_MAX_TOKENS = 32;\n\n// --- Timeouts ---\n/** Daemon client HTTP request timeout (ms). */\nexport const DAEMON_CLIENT_TIMEOUT_MS = 2000;\n/** Health check timeout (ms) — fail fast if daemon isn't responding. */\nexport const DAEMON_HEALTH_CHECK_TIMEOUT_MS = 500;\n/** LLM request timeout (ms). All LLM calls are background daemon work — no need to be aggressive. */\nexport const LLM_REQUEST_TIMEOUT_MS = 180_000;\n/** Embedding request timeout (ms). Embeddings run in background batch processing — generous timeout. */\nexport const EMBEDDING_REQUEST_TIMEOUT_MS = 60_000;\n/** Digest LLM request timeout (ms). Digest cycles use large context windows and may need model loading time. */\nexport const DIGEST_LLM_REQUEST_TIMEOUT_MS = 600_000;\n/** Stdin read timeout for hooks (ms). */\nexport const STDIN_TIMEOUT_MS = 100;\n/** Provider detection timeout for detect-providers CLI command (ms). */\nexport const PROVIDER_DETECT_TIMEOUT_MS = 3000;\n\n// --- Time ---\n/** Milliseconds in one day. */\nexport const MS_PER_DAY = 24 * 60 * 60 * 1000;\n\n/** Current Unix epoch in seconds. */\nexport function epochSeconds(): number {\n return Math.floor(Date.now() / MS_PER_SECOND);\n}\n\n// --- Buffer cleanup ---\n/** Max age for stale buffer files before cleanup (ms). */\nexport const STALE_BUFFER_MAX_AGE_MS = 1 * MS_PER_DAY;\n\n// --- Retry backoff ---\n/** Retry delays for daemon health check (ms). */\nexport const DAEMON_HEALTH_RETRY_DELAYS = [100, 200, 400, 800, 1500];\n\n/** Grace period after daemon.json is written before stale checks can trigger a restart (ms).\n * Prevents rapid restart loops from concurrent hooks or session reloads. */\nexport const DAEMON_STALE_GRACE_PERIOD_MS = 60_000;\n\n/** Grace period for SIGTERM before escalating to SIGKILL (ms).\n * Gives the old daemon a chance to shut down cleanly, but force-kills\n * to guarantee the configured port is reclaimed. */\nexport const DAEMON_EVICT_TIMEOUT_MS = 3000;\n/** Poll interval when waiting for an evicted daemon to die (ms). */\nexport const DAEMON_EVICT_POLL_MS = 100;\n\n// --- Slug limits ---\n/** Max length for slugified artifact IDs. */\n\n// --- Turn rendering ---\n/** Max file paths displayed per turn in session notes. */\nexport const TURN_MAX_FILES_DISPLAYED = 10;\n\n// --- Transcript mining ---\n/** Minimum content length to consider a transcript entry meaningful. */\nexport const MIN_TRANSCRIPT_CONTENT_LENGTH = 10;\n\n// --- Graph edge types (lineage — auto-created by daemon) ---\n/** Spore was extracted during this session. */\nexport const EDGE_TYPE_FROM_SESSION = 'FROM_SESSION';\n/** Spore was extracted from this prompt batch. */\nexport const EDGE_TYPE_EXTRACTED_FROM = 'EXTRACTED_FROM';\n/** Wisdom spore was derived from (consolidated) this source spore. */\nexport const EDGE_TYPE_DERIVED_FROM = 'DERIVED_FROM';\n/** Session contains this prompt batch. */\nexport const EDGE_TYPE_HAS_BATCH = 'HAS_BATCH';\n// --- Query defaults ---\n/** Default row limit for query module list operations. */\nexport const QUERY_DEFAULT_LIST_LIMIT = 100;\n/** Default LIMIT for paginated list queries. */\nexport const DEFAULT_LIST_LIMIT = 50;\n/** Default confidence score for graph edges. */\nexport const GRAPH_EDGE_DEFAULT_CONFIDENCE = 1.0;\n\n// --- Query limits ---\n/** Max recent sessions to check for lineage heuristics. */\nexport const LINEAGE_RECENT_SESSIONS_LIMIT = 5;\n/** Max related spores to query for session notes. */\nexport const RELATED_SPORES_LIMIT = 50;\n\n// --- Context injection ---\n/** Max spores to inject per prompt. */\nexport const PROMPT_CONTEXT_MAX_SPORES = 3;\n/** Minimum similarity score for prompt context injection (0-1). */\nexport const PROMPT_CONTEXT_MIN_SIMILARITY = 0.3;\n/** Max token budget for session-start context injection. */\nexport const SESSION_CONTEXT_MAX_TOKENS = 500;\n/** Max token budget for per-prompt context injection. */\nexport const PROMPT_CONTEXT_MAX_TOKENS = 300;\n/** Minimum prompt length to trigger context search. */\nexport const PROMPT_CONTEXT_MIN_LENGTH = 10;\n\n/** Over-fetch multiplier for vector search to compensate for post-filtering. */\nexport const PROMPT_VECTOR_OVER_FETCH = 2;\n\n// --- Spore status filtering ---\n/** Spore statuses excluded from search results and context injection. */\nexport const EXCLUDED_SPORE_STATUSES = new Set(['superseded', 'archived']);\n\n// --- Agent identity ---\n/** Default agent ID for the built-in intelligence agent. */\nexport const DEFAULT_AGENT_ID = 'myco-agent';\n/** Agent ID for user-initiated MCP operations. */\nexport const USER_AGENT_ID = 'user';\n/** Agent name for user-initiated MCP operations. */\nexport const USER_AGENT_NAME = 'User (MCP)';\n\n// --- MCP tool defaults ---\n/** Default result limit for myco_search. */\nexport const MCP_SEARCH_DEFAULT_LIMIT = 10;\n/** Default result limit for myco_sessions. */\nexport const MCP_SESSIONS_DEFAULT_LIMIT = 20;\n/** Default result limit for myco_logs. */\nexport const MCP_LOGS_DEFAULT_LIMIT = 50;\n/** Default result limit for myco_skills and myco_skill_candidates. */\nexport const MCP_SKILLS_DEFAULT_LIMIT = 50;\n\n// --- Feed ---\n/** Default number of entries returned by the activity feed. */\nexport const FEED_DEFAULT_LIMIT = 50;\n\n// --- Digest — Tiers ---\n/** Available token-budget tiers for digest synthesis. */\nexport const DIGEST_TIERS = [1500, 5000, 10000] as const;\nexport type DigestTier = (typeof DIGEST_TIERS)[number];\n\n// --- Digest — Context window minimums per tier ---\n/** Minimum context window (tokens) required to run a digest at a given tier. */\nexport const DIGEST_TIER_MIN_CONTEXT: Record<number, number> = {\n 1500: 6500,\n 5000: 18500,\n 10000: 30500,\n};\n\n// --- Digest — Substrate ---\n/** Default minimum substrate notes required before a digest cycle runs. */\nexport const DIGEST_MIN_NOTES_FOR_CYCLE = 10;\n\n/** Scoring weights by note type when selecting substrate for synthesis. */\nexport const DIGEST_SUBSTRATE_TYPE_WEIGHTS: Record<string, number> = {\n session: 3,\n spore: 3,\n plan: 2,\n artifact: 1,\n team: 1,\n};\n\n// --- LLM reasoning control ---\n/** Reasoning mode for all Myco LLM calls. Suppresses chain-of-thought tokens from reasoning models. */\nexport const LLM_REASONING_MODE = 'off' as const;\n\n// --- Digest — System prompt overhead estimate ---\n\n// --- Vault intelligence ---\n/** Max candidate spores after post-filtering for supersession check. */\nexport const SUPERSESSION_CANDIDATE_LIMIT = 5;\n\n/** Over-fetch from vector index before post-filtering by status/type. */\nexport const SUPERSESSION_VECTOR_FETCH_LIMIT = 20;\n\n/** Max output tokens for supersession LLM evaluation. */\nexport const SUPERSESSION_MAX_TOKENS = 256;\n\n/** Similarity threshold for clustering related spores in batch agent processing. */\nexport const AGENT_CLUSTER_SIMILARITY = 0.75;\n\n// --- Search ---\n/** Default number of results returned by vector search and fullTextSearch. */\nexport const SEARCH_RESULTS_DEFAULT_LIMIT = 20;\n/** Minimum cosine similarity score for semantic search results (0-1). */\nexport const SEARCH_SIMILARITY_THRESHOLD = 0.3;\n\n// --- Pipeline processing ---\n/** Default page size for pipeline items API listing. */\nexport const PIPELINE_ITEMS_DEFAULT_LIMIT = 50;\n\n// --- Pipeline retry ---\n/** Max retries for parse (structural) pipeline failures — fail fast. */\nexport const PIPELINE_PARSE_MAX_RETRIES = 1;\n/** Exponential backoff multiplier for successive pipeline retries. */\nexport const PIPELINE_BACKOFF_MULTIPLIER = 4;\n\n// --- Pipeline stages (ordered) ---\nexport const PIPELINE_STAGES = ['capture', 'extraction', 'embedding', 'consolidation', 'digest'] as const;\nexport type PipelineStage = typeof PIPELINE_STAGES[number];\n\n// --- Pipeline statuses ---\nexport const PIPELINE_STATUSES = ['pending', 'processing', 'succeeded', 'failed', 'blocked', 'skipped', 'poisoned'] as const;\nexport type PipelineStatus = typeof PIPELINE_STATUSES[number];\n\n// --- Provider roles for circuit breakers ---\nexport const PIPELINE_PROVIDER_ROLES = ['llm', 'embedding', 'digest-llm'] as const;\nexport type PipelineProviderRole = typeof PIPELINE_PROVIDER_ROLES[number];\n\n// --- Stage to provider role mapping ---\nexport const STAGE_PROVIDER_MAP: Record<PipelineStage, PipelineProviderRole | null> = {\n capture: null,\n extraction: 'llm',\n embedding: 'embedding',\n consolidation: 'digest-llm',\n digest: 'digest-llm',\n};\n\n/**\n * Stages processed by the pipeline tick timer.\n * Capture is handled at registration time, digest is gated by the metabolism timer.\n */\nexport const PIPELINE_TICK_STAGES: PipelineStage[] = ['extraction', 'embedding', 'consolidation'];\n\n// --- Item type to applicable stages ---\n// Sessions skip consolidation — consolidation applies to the spores\n// extracted FROM sessions, not the session work item itself.\n// Lineage detection stays outside the pipeline (fire-and-forget, non-critical).\nexport const ITEM_STAGE_MAP: Record<string, PipelineStage[]> = {\n session: ['capture', 'extraction', 'embedding', 'digest'],\n spore: ['capture', 'embedding', 'consolidation', 'digest'],\n artifact: ['capture', 'embedding', 'digest'],\n};\n\n// --- User task registry ---\n/** Subdirectory within the vault for user-created task YAML files. */\nexport const USER_TASKS_DIR = 'tasks';\n\n/** Source label for user-created tasks. */\nexport const USER_TASK_SOURCE = 'user';\n\n/** Source label for built-in tasks shipped with the package. */\nexport const BUILT_IN_SOURCE = 'built-in';\n\n/** Task name validation pattern (lowercase, hyphens, digits). */\nexport const TASK_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/;\n\n/** Maximum length for task names. */\nexport const MAX_TASK_NAME_LENGTH = 50;\n\n// --- Automatic consolidation ---\n/** Minimum cluster size required before asking LLM to consolidate. */\nexport const CONSOLIDATION_MIN_CLUSTER_SIZE = 3;\n\n/** Over-fetch from vector index before post-filtering by status/type. */\nexport const CONSOLIDATION_VECTOR_FETCH_LIMIT = 20;\n\n/** Max output tokens for consolidation LLM synthesis.\n * Must be large enough for the full JSON response including content field. */\nexport const CONSOLIDATION_MAX_TOKENS = 2048;\n\n// --- Power management ---\n/** PowerManager states valid for task scheduling (excludes deep_sleep which halts all ticks). */\nexport const SCHEDULABLE_POWER_STATES = ['active', 'idle', 'sleep'] as const;\nexport type SchedulablePowerState = typeof SCHEDULABLE_POWER_STATES[number];\n\n/** Time without activity before transitioning to idle (ms). */\nexport const POWER_IDLE_THRESHOLD_MS = 5 * 60 * MS_PER_SECOND;\n/** Time without activity before transitioning to sleep (ms). */\nexport const POWER_SLEEP_THRESHOLD_MS = 30 * 60 * MS_PER_SECOND;\n/** Time without activity before transitioning to deep sleep (ms). */\nexport const POWER_DEEP_SLEEP_THRESHOLD_MS = 90 * 60 * MS_PER_SECOND;\n/** Job cycle interval during active/idle states (ms). */\nexport const POWER_ACTIVE_INTERVAL_MS = 60 * MS_PER_SECOND;\n/** Job cycle interval during sleep state (ms). */\nexport const POWER_SLEEP_INTERVAL_MS = 5 * 60 * MS_PER_SECOND;\n\n// --- Session maintenance ---\n/** Time without new prompts before an active session is auto-completed (ms). */\nexport const STALE_SESSION_THRESHOLD_MS = 60 * 60 * MS_PER_SECOND;\n/**\n * Max prompt count for a session to be considered dead and auto-deleted.\n *\n * Set to 0: only sessions that were registered but never received a prompt\n * are eligible for dead-session cleanup. A session with even ONE real user\n * prompt has produced captured state worth preserving — the user did work,\n * the agent likely responded, tool calls may have happened, code may have\n * changed. Deleting such a session was a real data-loss failure mode seen\n * during opencode testing where a 1-prompt session that made an actual\n * committed code change was auto-deleted within a minute of TUI exit.\n */\nexport const DEAD_SESSION_MAX_PROMPTS = 0;\n\n// --- Init wizard ---\n/** Minimum Node.js major version required by Myco. */\nexport const MIN_NODE_MAJOR_VERSION = 22;\n\n/** Recommended context window for local intelligence models. */\nexport const RECOMMENDED_LOCAL_CONTEXT_WINDOW = 8192;\n\n/** Default Ollama embedding model recommended during init. */\nexport const DEFAULT_OLLAMA_EMBEDDING_MODEL = 'bge-m3';\n\n/** Default OpenAI embedding model recommended during init. */\nexport const DEFAULT_OPENAI_EMBEDDING_MODEL = 'text-embedding-3-small';\n\n// --- Sync protocol ---\n/** Protocol version for backup and team sync wire format. */\nexport const SYNC_PROTOCOL_VERSION = 1;\n\n// --- Team sync ---\n/** Default machine ID for rows created before multi-machine support. */\nexport const DEFAULT_MACHINE_ID = 'local';\n/** Prefix for team search result source attribution. */\nexport const TEAM_SOURCE_PREFIX = 'team:';\n/** Timeout for team search requests (ms). */\nexport const TEAM_SEARCH_TIMEOUT_MS = 3000;\n/** Timeout for team health check requests (ms). */\nexport const TEAM_HEALTH_TIMEOUT_MS = 5000;\n/** Secrets key for the team API key in secrets.env. */\nexport const TEAM_API_KEY_SECRET = 'MYCO_TEAM_API_KEY';\n/** Secrets key for the team MCP token in secrets.env. */\nexport const TEAM_MCP_TOKEN_SECRET = 'MYCO_TEAM_MCP_TOKEN';\n/** Secrets key for the Collective admin token in secrets.env. */\nexport const COLLECTIVE_ADMIN_TOKEN_SECRET = 'MYCO_COLLECTIVE_ADMIN_TOKEN';\n/** Secrets key for the Collective MCP token in secrets.env. */\nexport const COLLECTIVE_MCP_TOKEN_SECRET = 'MYCO_COLLECTIVE_MCP_TOKEN';\n/** Timeout for wrangler CLI commands (ms). */\nexport const WRANGLER_COMMAND_TIMEOUT_MS = 60_000;\n\n// --- HTTP response flush ---\n/** Delay before initiating shutdown — allows the HTTP response to flush. */\nexport const RESTART_RESPONSE_FLUSH_MS = 500;\n\n// --- Self-update ---\nexport {\n NPM_REGISTRY_BASE_URL,\n MYCO_GLOBAL_DIR,\n UPDATE_CHECK_CACHE_PATH,\n UPDATE_CONFIG_PATH,\n UPDATE_ERROR_PATH,\n UPDATE_CHECK_INTERVAL_HOURS,\n MS_PER_HOUR,\n NPM_PACKAGE_NAME,\n UPDATE_SCRIPT_DELAY_SECONDS,\n RELEASE_CHANNELS,\n DEFAULT_RELEASE_CHANNEL,\n type ReleaseChannel,\n} from './constants/update.js';\n"],"mappings":"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","names":[]}
|