@goondocks/myco 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-run-S4MFWUSV.js → agent-run-MNU2QWHR.js} +4 -4
- package/dist/{agent-tasks-JZ77AZSK.js → agent-tasks-NCRKUU6E.js} +4 -4
- package/dist/{chunk-U255A3RE.js → chunk-2E7YGLLN.js} +2 -2
- package/dist/{chunk-VEQLNB7E.js → chunk-4U6X35TH.js} +2 -2
- package/dist/{chunk-OH334Y3J.js → chunk-BNAYBGPH.js} +2 -2
- package/dist/{chunk-KYSLNB3C.js → chunk-D63XTGBV.js} +2 -2
- package/dist/{chunk-G6LM45FD.js → chunk-RJRRHTAA.js} +2 -2
- package/dist/{chunk-WKAYMCPR.js → chunk-SGYYOTNM.js} +9 -3
- package/dist/{chunk-WKAYMCPR.js.map → chunk-SGYYOTNM.js.map} +1 -1
- package/dist/{chunk-VQZPWCBH.js → chunk-ZMODJWI5.js} +2 -2
- package/dist/{cli-U2FZT4GP.js → cli-RYYABF2X.js} +34 -34
- package/dist/{client-MZL5SFQI.js → client-5VXKGNN2.js} +3 -3
- package/dist/{doctor-OJW7SCDQ.js → doctor-M4Q7VCDO.js} +4 -4
- package/dist/{executor-HP3Y64PD.js → executor-ULRFWJCH.js} +37 -11
- package/dist/executor-ULRFWJCH.js.map +1 -0
- package/dist/{init-XVAONLZ7.js → init-AEHAQFPK.js} +7 -7
- package/dist/{init-wizard-3OPLXLNA.js → init-wizard-SVKDS3LR.js} +2 -2
- package/dist/{main-VAU5UPY7.js → main-GAGOE6XB.js} +11 -11
- package/dist/{open-ES2AOXL5.js → open-4QMAL32X.js} +4 -4
- package/dist/{post-compact-CCSP4ZRC.js → post-compact-OAWEBEDK.js} +4 -4
- package/dist/{post-tool-use-5UIVOE7I.js → post-tool-use-B3KOEOIM.js} +3 -3
- package/dist/{post-tool-use-failure-SR2523FX.js → post-tool-use-failure-2I5ELTTN.js} +4 -4
- package/dist/{pre-compact-2G2UWGDZ.js → pre-compact-NOXNJ5EV.js} +4 -4
- package/dist/{remove-L4HNBCSZ.js → remove-LX4G6KP7.js} +4 -4
- package/dist/{restart-ZQ3QNRF4.js → restart-WSNBSALP.js} +5 -5
- package/dist/{search-ECJ76TU3.js → search-Q6N3SHKP.js} +4 -4
- package/dist/{server-4MUFDPDP.js → server-OFRKA6N7.js} +3 -3
- package/dist/{session-ZHYO3BBY.js → session-SKXJLJYH.js} +5 -5
- package/dist/{session-end-UJM3UODF.js → session-end-5EIVRCPS.js} +3 -3
- package/dist/{session-start-UXLG36AZ.js → session-start-OL2ICLED.js} +4 -4
- package/dist/{setup-llm-NEN5XPNY.js → setup-llm-BRNQW7K2.js} +4 -4
- 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/{stats-AYRSUFHR.js → stats-U5FHDIR7.js} +5 -5
- package/dist/{stop-5WD22XAH.js → stop-YUZNQBRQ.js} +3 -3
- package/dist/{stop-failure-FLFIOPJY.js → stop-failure-6WFAKH2U.js} +4 -4
- package/dist/{subagent-start-AMCPECUD.js → subagent-start-GWJXAAH3.js} +4 -4
- package/dist/{subagent-stop-4M4BUENR.js → subagent-stop-B44SMV2R.js} +4 -4
- package/dist/{task-completed-QJOEVDXZ.js → task-completed-GIUFSRTP.js} +4 -4
- package/dist/{team-FWEVWYIY.js → team-3YI3UWB3.js} +2 -2
- package/dist/{update-F2LPJMUE.js → update-QPRTLGYU.js} +4 -4
- package/dist/{user-prompt-submit-UOAIU3JW.js → user-prompt-submit-FSYEPW7W.js} +3 -3
- package/dist/{version-2NJN3WW6.js → version-VS2EDHBG.js} +2 -2
- package/package.json +1 -1
- package/dist/executor-HP3Y64PD.js.map +0 -1
- /package/dist/{agent-run-S4MFWUSV.js.map → agent-run-MNU2QWHR.js.map} +0 -0
- /package/dist/{agent-tasks-JZ77AZSK.js.map → agent-tasks-NCRKUU6E.js.map} +0 -0
- /package/dist/{chunk-U255A3RE.js.map → chunk-2E7YGLLN.js.map} +0 -0
- /package/dist/{chunk-VEQLNB7E.js.map → chunk-4U6X35TH.js.map} +0 -0
- /package/dist/{chunk-OH334Y3J.js.map → chunk-BNAYBGPH.js.map} +0 -0
- /package/dist/{chunk-KYSLNB3C.js.map → chunk-D63XTGBV.js.map} +0 -0
- /package/dist/{chunk-G6LM45FD.js.map → chunk-RJRRHTAA.js.map} +0 -0
- /package/dist/{chunk-VQZPWCBH.js.map → chunk-ZMODJWI5.js.map} +0 -0
- /package/dist/{cli-U2FZT4GP.js.map → cli-RYYABF2X.js.map} +0 -0
- /package/dist/{client-MZL5SFQI.js.map → client-5VXKGNN2.js.map} +0 -0
- /package/dist/{doctor-OJW7SCDQ.js.map → doctor-M4Q7VCDO.js.map} +0 -0
- /package/dist/{init-XVAONLZ7.js.map → init-AEHAQFPK.js.map} +0 -0
- /package/dist/{init-wizard-3OPLXLNA.js.map → init-wizard-SVKDS3LR.js.map} +0 -0
- /package/dist/{main-VAU5UPY7.js.map → main-GAGOE6XB.js.map} +0 -0
- /package/dist/{open-ES2AOXL5.js.map → open-4QMAL32X.js.map} +0 -0
- /package/dist/{post-compact-CCSP4ZRC.js.map → post-compact-OAWEBEDK.js.map} +0 -0
- /package/dist/{post-tool-use-5UIVOE7I.js.map → post-tool-use-B3KOEOIM.js.map} +0 -0
- /package/dist/{post-tool-use-failure-SR2523FX.js.map → post-tool-use-failure-2I5ELTTN.js.map} +0 -0
- /package/dist/{pre-compact-2G2UWGDZ.js.map → pre-compact-NOXNJ5EV.js.map} +0 -0
- /package/dist/{remove-L4HNBCSZ.js.map → remove-LX4G6KP7.js.map} +0 -0
- /package/dist/{restart-ZQ3QNRF4.js.map → restart-WSNBSALP.js.map} +0 -0
- /package/dist/{search-ECJ76TU3.js.map → search-Q6N3SHKP.js.map} +0 -0
- /package/dist/{server-4MUFDPDP.js.map → server-OFRKA6N7.js.map} +0 -0
- /package/dist/{session-ZHYO3BBY.js.map → session-SKXJLJYH.js.map} +0 -0
- /package/dist/{session-end-UJM3UODF.js.map → session-end-5EIVRCPS.js.map} +0 -0
- /package/dist/{session-start-UXLG36AZ.js.map → session-start-OL2ICLED.js.map} +0 -0
- /package/dist/{setup-llm-NEN5XPNY.js.map → setup-llm-BRNQW7K2.js.map} +0 -0
- /package/dist/{stats-AYRSUFHR.js.map → stats-U5FHDIR7.js.map} +0 -0
- /package/dist/{stop-5WD22XAH.js.map → stop-YUZNQBRQ.js.map} +0 -0
- /package/dist/{stop-failure-FLFIOPJY.js.map → stop-failure-6WFAKH2U.js.map} +0 -0
- /package/dist/{subagent-start-AMCPECUD.js.map → subagent-start-GWJXAAH3.js.map} +0 -0
- /package/dist/{subagent-stop-4M4BUENR.js.map → subagent-stop-B44SMV2R.js.map} +0 -0
- /package/dist/{task-completed-QJOEVDXZ.js.map → task-completed-GIUFSRTP.js.map} +0 -0
- /package/dist/{team-FWEVWYIY.js.map → team-3YI3UWB3.js.map} +0 -0
- /package/dist/{update-F2LPJMUE.js.map → update-QPRTLGYU.js.map} +0 -0
- /package/dist/{user-prompt-submit-UOAIU3JW.js.map → user-prompt-submit-FSYEPW7W.js.map} +0 -0
- /package/dist/{version-2NJN3WW6.js.map → version-VS2EDHBG.js.map} +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
connectToDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BNAYBGPH.js";
|
|
5
5
|
import "./chunk-SAKJMNSR.js";
|
|
6
6
|
import "./chunk-TIAYBVSI.js";
|
|
7
7
|
import "./chunk-VWXDSDJU.js";
|
|
8
8
|
import "./chunk-MYX5NCRH.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-RJRRHTAA.js";
|
|
10
|
+
import "./chunk-2E7YGLLN.js";
|
|
11
11
|
import "./chunk-LPUQPDC2.js";
|
|
12
12
|
import "./chunk-34NHDRWI.js";
|
|
13
13
|
import "./chunk-E7NUADTQ.js";
|
|
@@ -32,4 +32,4 @@ async function run(args, vaultDir) {
|
|
|
32
32
|
export {
|
|
33
33
|
run
|
|
34
34
|
};
|
|
35
|
-
//# sourceMappingURL=agent-run-
|
|
35
|
+
//# sourceMappingURL=agent-run-MNU2QWHR.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
connectToDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BNAYBGPH.js";
|
|
5
5
|
import "./chunk-SAKJMNSR.js";
|
|
6
6
|
import "./chunk-TIAYBVSI.js";
|
|
7
7
|
import "./chunk-VWXDSDJU.js";
|
|
8
8
|
import "./chunk-MYX5NCRH.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-RJRRHTAA.js";
|
|
10
|
+
import "./chunk-2E7YGLLN.js";
|
|
11
11
|
import "./chunk-LPUQPDC2.js";
|
|
12
12
|
import "./chunk-34NHDRWI.js";
|
|
13
13
|
import "./chunk-E7NUADTQ.js";
|
|
@@ -178,4 +178,4 @@ async function run(args, vaultDir) {
|
|
|
178
178
|
export {
|
|
179
179
|
run
|
|
180
180
|
};
|
|
181
|
-
//# sourceMappingURL=agent-tasks-
|
|
181
|
+
//# sourceMappingURL=agent-tasks-NCRKUU6E.js.map
|
|
@@ -11,7 +11,7 @@ var cached;
|
|
|
11
11
|
function getPluginVersion() {
|
|
12
12
|
if (cached) return cached;
|
|
13
13
|
if (true) {
|
|
14
|
-
cached = "0.16.
|
|
14
|
+
cached = "0.16.2";
|
|
15
15
|
return cached;
|
|
16
16
|
}
|
|
17
17
|
const root = findPackageRoot(path.dirname(fileURLToPath(import.meta.url)));
|
|
@@ -32,4 +32,4 @@ function getPluginVersion() {
|
|
|
32
32
|
export {
|
|
33
33
|
getPluginVersion
|
|
34
34
|
};
|
|
35
|
-
//# sourceMappingURL=chunk-
|
|
35
|
+
//# sourceMappingURL=chunk-2E7YGLLN.js.map
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-5ZT2Q6P5.js";
|
|
12
12
|
import {
|
|
13
13
|
DaemonClient
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-RJRRHTAA.js";
|
|
15
15
|
|
|
16
16
|
// src/hooks/send-event.ts
|
|
17
17
|
import fs from "fs";
|
|
@@ -39,4 +39,4 @@ async function sendEvent(hookName, buildEvent) {
|
|
|
39
39
|
export {
|
|
40
40
|
sendEvent
|
|
41
41
|
};
|
|
42
|
-
//# sourceMappingURL=chunk-
|
|
42
|
+
//# sourceMappingURL=chunk-4U6X35TH.js.map
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "./chunk-MYX5NCRH.js";
|
|
14
14
|
import {
|
|
15
15
|
DaemonClient
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-RJRRHTAA.js";
|
|
17
17
|
|
|
18
18
|
// src/cli/shared.ts
|
|
19
19
|
import fs from "fs";
|
|
@@ -109,4 +109,4 @@ export {
|
|
|
109
109
|
VAULT_GITIGNORE,
|
|
110
110
|
registerSymbionts
|
|
111
111
|
};
|
|
112
|
-
//# sourceMappingURL=chunk-
|
|
112
|
+
//# sourceMappingURL=chunk-BNAYBGPH.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-IRSNOBGD.js";
|
|
6
6
|
import {
|
|
7
7
|
getSession
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SGYYOTNM.js";
|
|
9
9
|
import {
|
|
10
10
|
getTeamMachineId,
|
|
11
11
|
syncRow
|
|
@@ -1579,4 +1579,4 @@ export {
|
|
|
1579
1579
|
insertReport,
|
|
1580
1580
|
listReports
|
|
1581
1581
|
};
|
|
1582
|
-
//# sourceMappingURL=chunk-
|
|
1582
|
+
//# sourceMappingURL=chunk-D63XTGBV.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getPluginVersion
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2E7YGLLN.js";
|
|
5
5
|
import {
|
|
6
6
|
DAEMON_CLIENT_TIMEOUT_MS,
|
|
7
7
|
DAEMON_HEALTH_CHECK_TIMEOUT_MS,
|
|
@@ -185,4 +185,4 @@ export {
|
|
|
185
185
|
resolveCliEntryPath,
|
|
186
186
|
DaemonClient
|
|
187
187
|
};
|
|
188
|
-
//# sourceMappingURL=chunk-
|
|
188
|
+
//# sourceMappingURL=chunk-RJRRHTAA.js.map
|
|
@@ -262,10 +262,16 @@ function deleteSessionCascade(sessionId) {
|
|
|
262
262
|
const result = db.transaction(() => {
|
|
263
263
|
db.prepare(`DELETE FROM activities WHERE session_id = ?`).run(sessionId);
|
|
264
264
|
const attachments = db.prepare(`DELETE FROM attachments WHERE session_id = ?`).run(sessionId);
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
db.prepare(`DELETE FROM plans WHERE session_id = ?`).run(sessionId);
|
|
266
|
+
db.prepare(`DELETE FROM skill_usage WHERE session_id = ?`).run(sessionId);
|
|
267
|
+
const resEvents = db.prepare(
|
|
268
|
+
`DELETE FROM resolution_events
|
|
269
|
+
WHERE session_id = ?
|
|
270
|
+
OR spore_id IN (SELECT id FROM spores WHERE session_id = ?)`
|
|
271
|
+
).run(sessionId, sessionId);
|
|
267
272
|
const edges = db.prepare(`DELETE FROM graph_edges WHERE session_id = ?`).run(sessionId);
|
|
268
273
|
const spores = db.prepare(`DELETE FROM spores WHERE session_id = ?`).run(sessionId);
|
|
274
|
+
const prompts = db.prepare(`DELETE FROM prompt_batches WHERE session_id = ?`).run(sessionId);
|
|
269
275
|
const session = db.prepare(`DELETE FROM sessions WHERE id = ?`).run(sessionId);
|
|
270
276
|
return {
|
|
271
277
|
deleted: session.changes > 0,
|
|
@@ -296,4 +302,4 @@ export {
|
|
|
296
302
|
getSessionImpact,
|
|
297
303
|
deleteSessionCascade
|
|
298
304
|
};
|
|
299
|
-
//# sourceMappingURL=chunk-
|
|
305
|
+
//# sourceMappingURL=chunk-SGYYOTNM.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/queries/sessions.ts"],"sourcesContent":["/**\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}\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.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\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 * 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 const sporeIds = (db.prepare(\n `SELECT id FROM spores WHERE session_id = ?`,\n ).all(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 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 const prompts = db.prepare(`DELETE FROM prompt_batches WHERE session_id = ?`).run(sessionId);\n const resEvents = db.prepare(`DELETE FROM resolution_events WHERE session_id = ?`).run(sessionId);\n const edges = db.prepare(`DELETE FROM graph_edges WHERE session_id = ?`).run(sessionId);\n const spores = db.prepare(`DELETE FROM spores 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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/db/queries/sessions.ts"],"sourcesContent":["/**\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}\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.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\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 * 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 const sporeIds = (db.prepare(\n `SELECT id FROM spores WHERE session_id = ?`,\n ).all(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 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 (SELECT id FROM spores WHERE session_id = ?)`,\n ).run(sessionId, sessionId);\n const edges = db.prepare(`DELETE FROM graph_edges WHERE session_id = ?`).run(sessionId);\n const spores = db.prepare(`DELETE FROM spores WHERE session_id = ?`).run(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":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
isProcessAlive
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BNAYBGPH.js";
|
|
5
5
|
import {
|
|
6
6
|
loadConfig
|
|
7
7
|
} from "./chunk-XAXQ72L3.js";
|
|
@@ -184,4 +184,4 @@ export {
|
|
|
184
184
|
getEmbeddingQueueDepth,
|
|
185
185
|
gatherStats
|
|
186
186
|
};
|
|
187
|
-
//# sourceMappingURL=chunk-
|
|
187
|
+
//# sourceMappingURL=chunk-ZMODJWI5.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
loadEnv
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BNAYBGPH.js";
|
|
6
6
|
import "./chunk-SAKJMNSR.js";
|
|
7
7
|
import "./chunk-TIAYBVSI.js";
|
|
8
8
|
import "./chunk-VWXDSDJU.js";
|
|
@@ -10,8 +10,8 @@ import "./chunk-MYX5NCRH.js";
|
|
|
10
10
|
import {
|
|
11
11
|
resolveVaultDir
|
|
12
12
|
} from "./chunk-5ZT2Q6P5.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-RJRRHTAA.js";
|
|
14
|
+
import "./chunk-2E7YGLLN.js";
|
|
15
15
|
import "./chunk-LPUQPDC2.js";
|
|
16
16
|
import "./chunk-34NHDRWI.js";
|
|
17
17
|
import "./chunk-E7NUADTQ.js";
|
|
@@ -55,29 +55,29 @@ async function main() {
|
|
|
55
55
|
process.stdout.write(USAGE);
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
|
-
if (cmd === "init") return (await import("./init-
|
|
58
|
+
if (cmd === "init") return (await import("./init-AEHAQFPK.js")).run(args);
|
|
59
59
|
if (cmd === "detect-providers") return (await import("./detect-providers-R7QOB3H6.js")).run(args);
|
|
60
60
|
if (cmd === "version" || cmd === "--version" || cmd === "-v") {
|
|
61
|
-
const { getPluginVersion } = await import("./version-
|
|
61
|
+
const { getPluginVersion } = await import("./version-VS2EDHBG.js");
|
|
62
62
|
console.log(getPluginVersion());
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
if (cmd === "mcp") return (await import("./server-
|
|
65
|
+
if (cmd === "mcp") return (await import("./server-OFRKA6N7.js")).main();
|
|
66
66
|
if (cmd === "hook") {
|
|
67
67
|
const hookName = args[0];
|
|
68
68
|
const HOOK_DISPATCH = {
|
|
69
|
-
"session-start": () => import("./session-start-
|
|
70
|
-
"session-end": () => import("./session-end-
|
|
71
|
-
"stop": () => import("./stop-
|
|
72
|
-
"user-prompt-submit": () => import("./user-prompt-submit-
|
|
73
|
-
"post-tool-use": () => import("./post-tool-use-
|
|
74
|
-
"post-tool-use-failure": () => import("./post-tool-use-failure-
|
|
75
|
-
"subagent-start": () => import("./subagent-start-
|
|
76
|
-
"subagent-stop": () => import("./subagent-stop-
|
|
77
|
-
"stop-failure": () => import("./stop-failure-
|
|
78
|
-
"task-completed": () => import("./task-completed-
|
|
79
|
-
"pre-compact": () => import("./pre-compact-
|
|
80
|
-
"post-compact": () => import("./post-compact-
|
|
69
|
+
"session-start": () => import("./session-start-OL2ICLED.js"),
|
|
70
|
+
"session-end": () => import("./session-end-5EIVRCPS.js"),
|
|
71
|
+
"stop": () => import("./stop-YUZNQBRQ.js"),
|
|
72
|
+
"user-prompt-submit": () => import("./user-prompt-submit-FSYEPW7W.js"),
|
|
73
|
+
"post-tool-use": () => import("./post-tool-use-B3KOEOIM.js"),
|
|
74
|
+
"post-tool-use-failure": () => import("./post-tool-use-failure-2I5ELTTN.js"),
|
|
75
|
+
"subagent-start": () => import("./subagent-start-GWJXAAH3.js"),
|
|
76
|
+
"subagent-stop": () => import("./subagent-stop-B44SMV2R.js"),
|
|
77
|
+
"stop-failure": () => import("./stop-failure-6WFAKH2U.js"),
|
|
78
|
+
"task-completed": () => import("./task-completed-GIUFSRTP.js"),
|
|
79
|
+
"pre-compact": () => import("./pre-compact-NOXNJ5EV.js"),
|
|
80
|
+
"post-compact": () => import("./post-compact-OAWEBEDK.js")
|
|
81
81
|
};
|
|
82
82
|
const loader = HOOK_DISPATCH[hookName];
|
|
83
83
|
if (!loader) {
|
|
@@ -86,13 +86,13 @@ async function main() {
|
|
|
86
86
|
}
|
|
87
87
|
return (await loader()).main();
|
|
88
88
|
}
|
|
89
|
-
if (cmd === "daemon") return (await import("./main-
|
|
89
|
+
if (cmd === "daemon") return (await import("./main-GAGOE6XB.js")).main();
|
|
90
90
|
if (cmd === "doctor") {
|
|
91
91
|
const vaultDir2 = resolveVaultDir();
|
|
92
|
-
return (await import("./doctor-
|
|
92
|
+
return (await import("./doctor-M4Q7VCDO.js")).run(args, vaultDir2);
|
|
93
93
|
}
|
|
94
|
-
if (cmd === "update") return (await import("./update-
|
|
95
|
-
if (cmd === "remove") return (await import("./remove-
|
|
94
|
+
if (cmd === "update") return (await import("./update-QPRTLGYU.js")).run(args);
|
|
95
|
+
if (cmd === "remove") return (await import("./remove-LX4G6KP7.js")).run(args);
|
|
96
96
|
const vaultDir = resolveVaultDir();
|
|
97
97
|
if (!fs.existsSync(path.join(vaultDir, "myco.yaml"))) {
|
|
98
98
|
console.error(`No myco.yaml found in ${vaultDir}. Run 'myco init' first.`);
|
|
@@ -104,33 +104,33 @@ async function main() {
|
|
|
104
104
|
case "verify":
|
|
105
105
|
return (await import("./verify-ITBMLK67.js")).run(args, vaultDir);
|
|
106
106
|
case "stats":
|
|
107
|
-
return (await import("./stats-
|
|
107
|
+
return (await import("./stats-U5FHDIR7.js")).run(args, vaultDir);
|
|
108
108
|
case "search":
|
|
109
|
-
return (await import("./search-
|
|
109
|
+
return (await import("./search-Q6N3SHKP.js")).run(args, vaultDir);
|
|
110
110
|
case "vectors":
|
|
111
|
-
return (await import("./search-
|
|
111
|
+
return (await import("./search-Q6N3SHKP.js")).runVectors(args, vaultDir);
|
|
112
112
|
case "session":
|
|
113
|
-
return (await import("./session-
|
|
113
|
+
return (await import("./session-SKXJLJYH.js")).run(args, vaultDir);
|
|
114
114
|
case "setup-llm":
|
|
115
|
-
return (await import("./setup-llm-
|
|
115
|
+
return (await import("./setup-llm-BRNQW7K2.js")).run(args, vaultDir);
|
|
116
116
|
case "setup-digest":
|
|
117
117
|
return (await import("./setup-digest-4KDSXAIV.js")).run(args, vaultDir);
|
|
118
118
|
case "agent":
|
|
119
|
-
return (await import("./agent-run-
|
|
119
|
+
return (await import("./agent-run-MNU2QWHR.js")).run(args, vaultDir);
|
|
120
120
|
case "task":
|
|
121
|
-
return (await import("./agent-tasks-
|
|
121
|
+
return (await import("./agent-tasks-NCRKUU6E.js")).run(args, vaultDir);
|
|
122
122
|
case "team": {
|
|
123
123
|
const sub = args[0];
|
|
124
|
-
if (sub === "init") return (await import("./team-
|
|
125
|
-
if (sub === "upgrade") return (await import("./team-
|
|
124
|
+
if (sub === "init") return (await import("./team-3YI3UWB3.js")).teamInit(vaultDir);
|
|
125
|
+
if (sub === "upgrade") return (await import("./team-3YI3UWB3.js")).teamUpgrade(vaultDir);
|
|
126
126
|
console.error("Usage: myco team <init|upgrade>");
|
|
127
127
|
process.exit(1);
|
|
128
128
|
break;
|
|
129
129
|
}
|
|
130
130
|
case "open":
|
|
131
|
-
return (await import("./open-
|
|
131
|
+
return (await import("./open-4QMAL32X.js")).run(args, vaultDir);
|
|
132
132
|
case "restart":
|
|
133
|
-
return (await import("./restart-
|
|
133
|
+
return (await import("./restart-WSNBSALP.js")).run(args, vaultDir);
|
|
134
134
|
case "logs":
|
|
135
135
|
return (await import("./logs-TMKNLSJY.js")).run(args, vaultDir);
|
|
136
136
|
default:
|
|
@@ -143,4 +143,4 @@ main().catch((err) => {
|
|
|
143
143
|
console.error(`myco: ${err.message}`);
|
|
144
144
|
process.exit(1);
|
|
145
145
|
});
|
|
146
|
-
//# sourceMappingURL=cli-
|
|
146
|
+
//# sourceMappingURL=cli-RYYABF2X.js.map
|
|
@@ -2,8 +2,8 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
|
|
|
2
2
|
import {
|
|
3
3
|
DaemonClient,
|
|
4
4
|
resolveCliEntryPath
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-RJRRHTAA.js";
|
|
6
|
+
import "./chunk-2E7YGLLN.js";
|
|
7
7
|
import "./chunk-LPUQPDC2.js";
|
|
8
8
|
import "./chunk-34NHDRWI.js";
|
|
9
9
|
import "./chunk-E7NUADTQ.js";
|
|
@@ -12,4 +12,4 @@ export {
|
|
|
12
12
|
DaemonClient,
|
|
13
13
|
resolveCliEntryPath
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=client-
|
|
15
|
+
//# sourceMappingURL=client-5VXKGNN2.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
isProcessAlive
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BNAYBGPH.js";
|
|
5
5
|
import "./chunk-SAKJMNSR.js";
|
|
6
6
|
import {
|
|
7
7
|
MYCO_MCP_SERVER_NAME
|
|
8
8
|
} from "./chunk-TIAYBVSI.js";
|
|
9
9
|
import "./chunk-VWXDSDJU.js";
|
|
10
10
|
import "./chunk-MYX5NCRH.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-RJRRHTAA.js";
|
|
12
|
+
import "./chunk-2E7YGLLN.js";
|
|
13
13
|
import "./chunk-LPUQPDC2.js";
|
|
14
14
|
import "./chunk-34NHDRWI.js";
|
|
15
15
|
import "./chunk-E7NUADTQ.js";
|
|
@@ -270,4 +270,4 @@ export {
|
|
|
270
270
|
run,
|
|
271
271
|
runChecks
|
|
272
272
|
};
|
|
273
|
-
//# sourceMappingURL=doctor-
|
|
273
|
+
//# sourceMappingURL=doctor-M4Q7VCDO.js.map
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
updateRunStatus,
|
|
32
32
|
updateSkillRecord,
|
|
33
33
|
upsertDigestExtract
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-D63XTGBV.js";
|
|
35
35
|
import {
|
|
36
36
|
fullTextSearch
|
|
37
37
|
} from "./chunk-UILSK6DK.js";
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
import {
|
|
71
71
|
listSessions,
|
|
72
72
|
updateSession
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-SGYYOTNM.js";
|
|
74
74
|
import "./chunk-4JVHWBZF.js";
|
|
75
75
|
import {
|
|
76
76
|
AGENT_SETTABLE_STATUSES,
|
|
@@ -87,7 +87,7 @@ import {
|
|
|
87
87
|
} from "./chunk-MYX5NCRH.js";
|
|
88
88
|
import {
|
|
89
89
|
getPluginVersion
|
|
90
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-2E7YGLLN.js";
|
|
91
91
|
import {
|
|
92
92
|
findPackageRoot
|
|
93
93
|
} from "./chunk-LPUQPDC2.js";
|
|
@@ -694,6 +694,14 @@ function parseAllowedTools(rawValue) {
|
|
|
694
694
|
if (parts.some((p) => sentinels.has(p))) return null;
|
|
695
695
|
return parts;
|
|
696
696
|
}
|
|
697
|
+
function stemToken(word) {
|
|
698
|
+
let w = word;
|
|
699
|
+
if (w.length > 5 && w.endsWith("ing")) w = w.slice(0, -3);
|
|
700
|
+
else if (w.length > 5 && w.endsWith("ed")) w = w.slice(0, -2);
|
|
701
|
+
if (w.length > 4 && w.endsWith("s")) w = w.slice(0, -1);
|
|
702
|
+
if (w.length > 4 && w.endsWith("e")) w = w.slice(0, -1);
|
|
703
|
+
return w;
|
|
704
|
+
}
|
|
697
705
|
function tokenSet(text) {
|
|
698
706
|
const stopwords = /* @__PURE__ */ new Set([
|
|
699
707
|
"the",
|
|
@@ -753,21 +761,34 @@ function tokenSet(text) {
|
|
|
753
761
|
"makes"
|
|
754
762
|
]);
|
|
755
763
|
return new Set(
|
|
756
|
-
text.toLowerCase().replace(/[^a-z0-9_\s]/g, " ").split(/\s+/).filter((w) => w.length >= 4 && !stopwords.has(w))
|
|
764
|
+
text.toLowerCase().replace(/[^a-z0-9_\s]/g, " ").split(/\s+/).filter((w) => w.length >= 4 && !stopwords.has(w)).map(stemToken)
|
|
757
765
|
);
|
|
758
766
|
}
|
|
767
|
+
function intersectionSize(a, b) {
|
|
768
|
+
let count = 0;
|
|
769
|
+
for (const token of a) {
|
|
770
|
+
if (b.has(token)) count++;
|
|
771
|
+
}
|
|
772
|
+
return count;
|
|
773
|
+
}
|
|
759
774
|
function descriptionSimilarity(a, b) {
|
|
760
775
|
const aTokens = tokenSet(a);
|
|
761
776
|
const bTokens = tokenSet(b);
|
|
762
777
|
if (aTokens.size === 0 || bTokens.size === 0) return 0;
|
|
763
|
-
|
|
764
|
-
for (const token of aTokens) {
|
|
765
|
-
if (bTokens.has(token)) intersection++;
|
|
766
|
-
}
|
|
778
|
+
const intersection = intersectionSize(aTokens, bTokens);
|
|
767
779
|
const union = aTokens.size + bTokens.size - intersection;
|
|
768
780
|
return union === 0 ? 0 : intersection / union;
|
|
769
781
|
}
|
|
782
|
+
function topicOverlapSimilarity(a, b, minTokens = 3) {
|
|
783
|
+
const aTokens = tokenSet(a);
|
|
784
|
+
const bTokens = tokenSet(b);
|
|
785
|
+
if (aTokens.size < minTokens || bTokens.size < minTokens) return 0;
|
|
786
|
+
const intersection = intersectionSize(aTokens, bTokens);
|
|
787
|
+
const smaller = Math.min(aTokens.size, bTokens.size);
|
|
788
|
+
return smaller === 0 ? 0 : intersection / smaller;
|
|
789
|
+
}
|
|
770
790
|
var DESCRIPTION_DUPLICATE_THRESHOLD = 0.4;
|
|
791
|
+
var TOPIC_OVERLAP_THRESHOLD = 0.6;
|
|
771
792
|
function checkFrontmatterPreservation(existing, incoming) {
|
|
772
793
|
const violations = [];
|
|
773
794
|
for (const field of PROTECTED_FRONTMATTER_FIELDS) {
|
|
@@ -849,8 +870,13 @@ function createSkillTools(deps) {
|
|
|
849
870
|
function findOverlappingCandidate(newTopic, existing) {
|
|
850
871
|
let best = null;
|
|
851
872
|
for (const candidate of existing) {
|
|
852
|
-
const
|
|
853
|
-
|
|
873
|
+
const jaccard = descriptionSimilarity(newTopic, candidate.topic);
|
|
874
|
+
const overlap = topicOverlapSimilarity(newTopic, candidate.topic);
|
|
875
|
+
const hitsJaccard = jaccard >= DESCRIPTION_DUPLICATE_THRESHOLD;
|
|
876
|
+
const hitsOverlap = overlap >= TOPIC_OVERLAP_THRESHOLD;
|
|
877
|
+
if (!hitsJaccard && !hitsOverlap) continue;
|
|
878
|
+
const score = Math.max(jaccard, overlap);
|
|
879
|
+
if (!best || score > best.score) {
|
|
854
880
|
best = { candidate, score };
|
|
855
881
|
}
|
|
856
882
|
}
|
|
@@ -2650,4 +2676,4 @@ export {
|
|
|
2650
2676
|
computeWaves,
|
|
2651
2677
|
runAgent
|
|
2652
2678
|
};
|
|
2653
|
-
//# sourceMappingURL=executor-
|
|
2679
|
+
//# sourceMappingURL=executor-ULRFWJCH.js.map
|