@goondocks/myco 0.20.2 → 0.21.0
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-eval-RJSQI5S2.js +355 -0
- package/dist/agent-eval-RJSQI5S2.js.map +1 -0
- package/dist/{agent-run-X25Q2A6T.js → agent-run-2JSYFOKU.js} +10 -8
- package/dist/{agent-run-X25Q2A6T.js.map → agent-run-2JSYFOKU.js.map} +1 -1
- package/dist/{agent-tasks-7B6OFERB.js → agent-tasks-APFJIM2T.js} +10 -8
- package/dist/{agent-tasks-7B6OFERB.js.map → agent-tasks-APFJIM2T.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-DCSGJ7W4.js → chunk-5ZG4RMUH.js} +2 -2
- package/dist/{chunk-FLLBJLHM.js → chunk-6C6QZ4PM.js} +9 -5
- package/dist/chunk-6C6QZ4PM.js.map +1 -0
- package/dist/chunk-6LB7XELY.js +406 -0
- package/dist/chunk-6LB7XELY.js.map +1 -0
- package/dist/{chunk-JZGN33AY.js → chunk-75Z7UKDY.js} +4 -4
- package/dist/{chunk-XG5RRUYF.js → chunk-BUTL6IFS.js} +2 -2
- package/dist/chunk-CESKJD44.js +586 -0
- package/dist/chunk-CESKJD44.js.map +1 -0
- package/dist/chunk-CISWUP5W.js +101 -0
- package/dist/chunk-CISWUP5W.js.map +1 -0
- package/dist/chunk-DJ3IHNYO.js +50 -0
- package/dist/chunk-DJ3IHNYO.js.map +1 -0
- package/dist/chunk-F3OEQYLS.js +847 -0
- package/dist/chunk-F3OEQYLS.js.map +1 -0
- 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-2PDWCDKY.js → chunk-G6QIBNZM.js} +9 -6
- package/dist/{chunk-2PDWCDKY.js.map → chunk-G6QIBNZM.js.map} +1 -1
- package/dist/{chunk-6X2ERTQV.js → chunk-ILJPRYES.js} +6 -4
- package/dist/{chunk-6X2ERTQV.js.map → chunk-ILJPRYES.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-KESLPBKV.js → chunk-JR54LTPP.js} +4 -4
- package/dist/{chunk-CCRGY3QW.js → chunk-JZS6GZ6T.js} +16 -94
- package/dist/chunk-JZS6GZ6T.js.map +1 -0
- package/dist/{chunk-5XIVBO25.js → chunk-LVIY7P35.js} +2 -2
- package/dist/chunk-NGH7U6A3.js +13844 -0
- package/dist/chunk-NGH7U6A3.js.map +1 -0
- package/dist/chunk-OUJSQSKE.js +113 -0
- package/dist/chunk-OUJSQSKE.js.map +1 -0
- package/dist/{chunk-VVNL26WX.js → chunk-P66DLD6G.js} +22 -10
- package/dist/chunk-P66DLD6G.js.map +1 -0
- package/dist/{chunk-XATDZX7U.js → chunk-R2JIJBCL.js} +18 -4
- package/dist/{chunk-XATDZX7U.js.map → chunk-R2JIJBCL.js.map} +1 -1
- package/dist/{chunk-MYOZLMB2.js → chunk-RL5R4CQU.js} +538 -19
- package/dist/chunk-RL5R4CQU.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-Q36VMZST.js → chunk-VHNRMM4O.js} +3 -2
- 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/{cli-GGPWH4UO.js → cli-LNYSTDQM.js} +49 -42
- package/dist/cli-LNYSTDQM.js.map +1 -0
- package/dist/{client-YXQUTXVZ.js → client-NWE4TCNO.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-providers-5KOPZ7J2.js → detect-providers-ILLQZROY.js} +4 -4
- package/dist/{doctor-5JXJ36KA.js → doctor-TI7EZ3RW.js} +48 -15
- package/dist/doctor-TI7EZ3RW.js.map +1 -0
- package/dist/executor-F2YU7HXJ.js +44 -0
- package/dist/{init-LMYOVZAV.js → init-KG3TYVGE.js} +14 -12
- package/dist/{init-LMYOVZAV.js.map → init-KG3TYVGE.js.map} +1 -1
- package/dist/{installer-FS257JRZ.js → installer-UMH7OJ5A.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-NAVVZK63.js} +4 -3
- package/dist/{main-YTBVRTBI.js → main-5PRQNEEE.js} +2453 -650
- package/dist/main-5PRQNEEE.js.map +1 -0
- package/dist/{open-HG2DX6RN.js → open-5A27BCSB.js} +10 -8
- package/dist/{open-HG2DX6RN.js.map → open-5A27BCSB.js.map} +1 -1
- package/dist/{post-compact-JSECI44W.js → post-compact-USAODKPQ.js} +6 -6
- package/dist/{post-tool-use-POGPTJBA.js → post-tool-use-GMMSYBII.js} +9 -7
- package/dist/post-tool-use-GMMSYBII.js.map +1 -0
- package/dist/{post-tool-use-failure-OT7BFWQW.js → post-tool-use-failure-NZVSL2PO.js} +6 -6
- package/dist/{pre-compact-OXVODKH4.js → pre-compact-LZ57DLUS.js} +6 -6
- package/dist/{provider-check-43LAMSMH.js → provider-check-ZEV5P4KM.js} +4 -4
- package/dist/{registry-U4CHXK6R.js → registry-M2Z5QBWH.js} +5 -4
- package/dist/{remove-N7ZPELFU.js → remove-T3KE6C5N.js} +10 -8
- package/dist/{remove-N7ZPELFU.js.map → remove-T3KE6C5N.js.map} +1 -1
- package/dist/{restart-ADG5GBTB.js → restart-YWDEVZUJ.js} +11 -9
- package/dist/{restart-ADG5GBTB.js.map → restart-YWDEVZUJ.js.map} +1 -1
- package/dist/{search-AHZEUNRR.js → search-GKFDGELR.js} +11 -9
- package/dist/{search-AHZEUNRR.js.map → search-GKFDGELR.js.map} +1 -1
- package/dist/{server-AGVYZVP5.js → server-AHUR6CWF.js} +368 -269
- package/dist/server-AHUR6CWF.js.map +1 -0
- package/dist/{session-6IU4AXYP.js → session-2ZEPLWW6.js} +11 -9
- package/dist/{session-6IU4AXYP.js.map → session-2ZEPLWW6.js.map} +1 -1
- package/dist/{session-end-FT27DWYZ.js → session-end-LWJYQAXX.js} +5 -5
- package/dist/session-start-WTA6GCOQ.js +134 -0
- package/dist/session-start-WTA6GCOQ.js.map +1 -0
- package/dist/{setup-llm-77MP4I2G.js → setup-llm-E7UU5IO7.js} +11 -9
- package/dist/{setup-llm-77MP4I2G.js.map → setup-llm-E7UU5IO7.js.map} +1 -1
- package/dist/src/agent/definitions/agent.yaml +9 -5
- package/dist/src/agent/definitions/tasks/cortex-instructions.yaml +93 -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 +4 -4
- package/dist/src/agent/definitions/tasks/skill-generate.yaml +1 -1
- 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} +17 -82
- 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/pi.yaml +22 -0
- 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-DFG6S23S.js} +11 -9
- package/dist/{stats-NVPWOYTE.js.map → stats-DFG6S23S.js.map} +1 -1
- package/dist/{stop-ZPIKVLH4.js → stop-WRBTXEVT.js} +5 -5
- package/dist/{stop-failure-2PX67YJC.js → stop-failure-32MGIG2Q.js} +6 -6
- package/dist/{subagent-start-UUE6EHQD.js → subagent-start-VFGHQFVL.js} +6 -6
- package/dist/{subagent-stop-KQWWWPE6.js → subagent-stop-663FXG3P.js} +6 -6
- package/dist/{task-completed-WMHOFQ7B.js → task-completed-ZCQYEFMZ.js} +6 -6
- package/dist/{team-LRZ6GTQK.js → team-JTI5CDUO.js} +7 -5
- package/dist/{turns-YFNI5CQC.js → turns-HU2CTZAP.js} +2 -2
- package/dist/ui/assets/index-DGf1h-Ha.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-3NBQTG32.js} +10 -8
- package/dist/{update-O6V4RC4W.js.map → update-3NBQTG32.js.map} +1 -1
- package/dist/{user-prompt-submit-N36KUPHI.js → user-prompt-submit-ME2TBKOS.js} +8 -7
- package/dist/{user-prompt-submit-N36KUPHI.js.map → user-prompt-submit-ME2TBKOS.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-GQAFBBPX.js} +2 -2
- package/dist/version-GQAFBBPX.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-curate/SKILL.md +1 -1
- package/dist/chunk-4YFKBL3F.js +0 -195
- package/dist/chunk-4YFKBL3F.js.map +0 -1
- package/dist/chunk-CCRGY3QW.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-OD4AA7PV.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/dist/{chunk-DCSGJ7W4.js.map → chunk-5ZG4RMUH.js.map} +0 -0
- /package/dist/{chunk-JZGN33AY.js.map → chunk-75Z7UKDY.js.map} +0 -0
- /package/dist/{chunk-XG5RRUYF.js.map → chunk-BUTL6IFS.js.map} +0 -0
- /package/dist/{chunk-KESLPBKV.js.map → chunk-JR54LTPP.js.map} +0 -0
- /package/dist/{chunk-5XIVBO25.js.map → chunk-LVIY7P35.js.map} +0 -0
- /package/dist/{chunk-BPRIYNLE.js.map → chunk-TKAJ3JVF.js.map} +0 -0
- /package/dist/{chunk-Q36VMZST.js.map → chunk-VHNRMM4O.js.map} +0 -0
- /package/dist/{client-YXQUTXVZ.js.map → client-NWE4TCNO.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-F2YU7HXJ.js.map} +0 -0
- /package/dist/{llm-TH4NLIRM.js.map → installer-UMH7OJ5A.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-NAVVZK63.js.map} +0 -0
- /package/dist/{post-compact-JSECI44W.js.map → post-compact-USAODKPQ.js.map} +0 -0
- /package/dist/{post-tool-use-failure-OT7BFWQW.js.map → post-tool-use-failure-NZVSL2PO.js.map} +0 -0
- /package/dist/{pre-compact-OXVODKH4.js.map → pre-compact-LZ57DLUS.js.map} +0 -0
- /package/dist/{registry-U4CHXK6R.js.map → provider-check-ZEV5P4KM.js.map} +0 -0
- /package/dist/{team-LRZ6GTQK.js.map → registry-M2Z5QBWH.js.map} +0 -0
- /package/dist/{session-end-FT27DWYZ.js.map → session-end-LWJYQAXX.js.map} +0 -0
- /package/dist/{stop-ZPIKVLH4.js.map → stop-WRBTXEVT.js.map} +0 -0
- /package/dist/{stop-failure-2PX67YJC.js.map → stop-failure-32MGIG2Q.js.map} +0 -0
- /package/dist/{subagent-start-UUE6EHQD.js.map → subagent-start-VFGHQFVL.js.map} +0 -0
- /package/dist/{subagent-stop-KQWWWPE6.js.map → subagent-stop-663FXG3P.js.map} +0 -0
- /package/dist/{task-completed-WMHOFQ7B.js.map → task-completed-ZCQYEFMZ.js.map} +0 -0
- /package/dist/{turns-YFNI5CQC.js.map → team-JTI5CDUO.js.map} +0 -0
- /package/dist/{version-XMPPJQHR.js.map → turns-HU2CTZAP.js.map} +0 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
// Managed by Myco. Regenerated on `myco update`. Edit src/symbionts/templates/pi/plugin.ts in the Myco repo instead.
|
|
2
|
+
// myco:plugin-marker:pi
|
|
3
|
+
//
|
|
4
|
+
// Myco Codebase Intelligence Extension for Pi.
|
|
5
|
+
//
|
|
6
|
+
// This extension runs inside pi's extension runtime (jiti) and communicates with
|
|
7
|
+
// the local Myco daemon over HTTP — no subprocess spawns, no hook CLI, no stdin piping.
|
|
8
|
+
//
|
|
9
|
+
// Capture: POST /sessions/register, /sessions/unregister, /events, /events/stop
|
|
10
|
+
// Context: POST /context, /context/resume
|
|
11
|
+
// Inject: before_agent_start → systemPrompt augmentation
|
|
12
|
+
//
|
|
13
|
+
// See https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/extensions.md
|
|
14
|
+
//
|
|
15
|
+
// Degraded-mode safety: this extension ships committed inside any project that has
|
|
16
|
+
// run `myco init` — the file lives at .pi/extensions/myco/index.ts in that project's
|
|
17
|
+
// repo. When a teammate clones such a project WITHOUT having Myco installed
|
|
18
|
+
// locally, pi will still load this extension. Every path that would contact the
|
|
19
|
+
// Myco daemon gracefully no-ops when `.myco/daemon.json` is absent or the daemon
|
|
20
|
+
// is unreachable, so the extension becomes invisible rather than throwing.
|
|
21
|
+
// Do NOT add runtime imports from Myco packages — only use pi's own exports
|
|
22
|
+
// and Node.js built-ins.
|
|
23
|
+
|
|
24
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
25
|
+
import { readFileSync, appendFileSync, mkdirSync } from "node:fs";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
import { Type } from "@sinclair/typebox";
|
|
28
|
+
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Constants
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Keep in sync with `TOOL_OUTPUT_PREVIEW_CHARS` in src/constants.ts (currently 200).
|
|
35
|
+
* The extension file is standalone and cannot import from Myco — this value is copied
|
|
36
|
+
* so every symbiont records tool_output previews at the same length.
|
|
37
|
+
*/
|
|
38
|
+
const TOOL_OUTPUT_PREVIEW_CHARS = 200;
|
|
39
|
+
|
|
40
|
+
/** Timeout for daemon HTTP calls — must be short so we never block pi. */
|
|
41
|
+
const MYCO_FETCH_TIMEOUT_MS = 3000;
|
|
42
|
+
|
|
43
|
+
/** Max size of resume context injection to keep resumed sessions lean. */
|
|
44
|
+
const RESUME_CONTEXT_MAX_CHARS = 4000;
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Daemon HTTP transport
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
let cachedDaemonPort: number | null | undefined = undefined;
|
|
51
|
+
|
|
52
|
+
function readDaemonPortFromDisk(directory: string): number | null {
|
|
53
|
+
try {
|
|
54
|
+
const raw = readFileSync(join(directory, ".myco", "daemon.json"), "utf-8");
|
|
55
|
+
const info = JSON.parse(raw) as { port?: number };
|
|
56
|
+
return typeof info.port === "number" ? info.port : null;
|
|
57
|
+
} catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getDaemonPort(directory: string): number | null {
|
|
63
|
+
if (cachedDaemonPort === undefined) cachedDaemonPort = readDaemonPortFromDisk(directory);
|
|
64
|
+
return cachedDaemonPort;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function refreshDaemonPort(directory: string): number | null {
|
|
68
|
+
cachedDaemonPort = readDaemonPortFromDisk(directory);
|
|
69
|
+
return cachedDaemonPort;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function fetchWithTimeout(url: string, init?: RequestInit): Promise<Response | null> {
|
|
73
|
+
const controller = new AbortController();
|
|
74
|
+
const timer = setTimeout(() => controller.abort(), MYCO_FETCH_TIMEOUT_MS);
|
|
75
|
+
try {
|
|
76
|
+
const res = await fetch(url, { ...init, signal: controller.signal });
|
|
77
|
+
return res.ok ? res : null;
|
|
78
|
+
} catch {
|
|
79
|
+
return null;
|
|
80
|
+
} finally {
|
|
81
|
+
clearTimeout(timer);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function fetchFromDaemon(
|
|
86
|
+
directory: string,
|
|
87
|
+
urlPath: string,
|
|
88
|
+
init?: RequestInit,
|
|
89
|
+
): Promise<Response | null> {
|
|
90
|
+
const port = getDaemonPort(directory);
|
|
91
|
+
if (!port) return null;
|
|
92
|
+
|
|
93
|
+
const first = await fetchWithTimeout(`http://localhost:${port}${urlPath}`, init);
|
|
94
|
+
if (first) return first;
|
|
95
|
+
|
|
96
|
+
// Retry once with a refreshed port — the daemon may have restarted.
|
|
97
|
+
const freshPort = refreshDaemonPort(directory);
|
|
98
|
+
if (!freshPort || freshPort === port) return null;
|
|
99
|
+
return fetchWithTimeout(`http://localhost:${freshPort}${urlPath}`, init);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function postJson(
|
|
103
|
+
directory: string,
|
|
104
|
+
urlPath: string,
|
|
105
|
+
body: Record<string, unknown>,
|
|
106
|
+
): Promise<{ ok: boolean; data?: unknown }> {
|
|
107
|
+
const res = await fetchFromDaemon(directory, urlPath, {
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: { "Content-Type": "application/json" },
|
|
110
|
+
body: JSON.stringify(body),
|
|
111
|
+
});
|
|
112
|
+
if (!res) return { ok: false };
|
|
113
|
+
try {
|
|
114
|
+
return { ok: true, data: await res.json() };
|
|
115
|
+
} catch {
|
|
116
|
+
return { ok: true };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function getJson(
|
|
121
|
+
directory: string,
|
|
122
|
+
urlPath: string,
|
|
123
|
+
): Promise<{ ok: boolean; data?: unknown }> {
|
|
124
|
+
const res = await fetchFromDaemon(directory, urlPath);
|
|
125
|
+
if (!res) return { ok: false };
|
|
126
|
+
try {
|
|
127
|
+
return { ok: true, data: await res.json() };
|
|
128
|
+
} catch {
|
|
129
|
+
return { ok: true };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Buffer fallback — identical pattern to opencode plugin
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
function bufferEvent(
|
|
138
|
+
directory: string,
|
|
139
|
+
sessionId: string,
|
|
140
|
+
event: Record<string, unknown>,
|
|
141
|
+
): void {
|
|
142
|
+
try {
|
|
143
|
+
const bufferDir = join(directory, ".myco", "buffer");
|
|
144
|
+
mkdirSync(bufferDir, { recursive: true });
|
|
145
|
+
const filePath = join(bufferDir, `${sessionId}.jsonl`);
|
|
146
|
+
const { session_id: _sid, ...payload } = event;
|
|
147
|
+
const line = JSON.stringify({
|
|
148
|
+
...payload,
|
|
149
|
+
timestamp: payload.timestamp ?? new Date().toISOString(),
|
|
150
|
+
});
|
|
151
|
+
appendFileSync(filePath, line + "\n");
|
|
152
|
+
} catch {
|
|
153
|
+
// Best-effort — swallow to never crash pi
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function postEventWithBuffer(
|
|
158
|
+
directory: string,
|
|
159
|
+
sessionId: string,
|
|
160
|
+
event: Record<string, unknown>,
|
|
161
|
+
): Promise<void> {
|
|
162
|
+
const result = await postJson(directory, "/events", event);
|
|
163
|
+
if (!result.ok) {
|
|
164
|
+
bufferEvent(directory, sessionId, event);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Daemon API wrappers
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
async function mycoRegisterSession(
|
|
173
|
+
directory: string,
|
|
174
|
+
sessionId: string,
|
|
175
|
+
): Promise<void> {
|
|
176
|
+
await postJson(directory, "/sessions/register", {
|
|
177
|
+
session_id: sessionId,
|
|
178
|
+
agent: "pi",
|
|
179
|
+
started_at: new Date().toISOString(),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function mycoUnregisterSession(directory: string, sessionId: string): Promise<void> {
|
|
184
|
+
await postJson(directory, "/sessions/unregister", { session_id: sessionId });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function mycoPostUserPrompt(
|
|
188
|
+
directory: string,
|
|
189
|
+
sessionId: string,
|
|
190
|
+
prompt: string,
|
|
191
|
+
images: Array<{ data: string; mediaType: string }>,
|
|
192
|
+
): Promise<void> {
|
|
193
|
+
await postEventWithBuffer(directory, sessionId, {
|
|
194
|
+
type: "user_prompt",
|
|
195
|
+
session_id: sessionId,
|
|
196
|
+
agent: "pi",
|
|
197
|
+
prompt,
|
|
198
|
+
...(images.length > 0 ? { images } : {}),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function mycoPostToolUse(
|
|
203
|
+
directory: string,
|
|
204
|
+
sessionId: string,
|
|
205
|
+
toolName: string,
|
|
206
|
+
toolInput: unknown,
|
|
207
|
+
toolOutput: string,
|
|
208
|
+
): Promise<void> {
|
|
209
|
+
await postEventWithBuffer(directory, sessionId, {
|
|
210
|
+
type: "tool_use",
|
|
211
|
+
session_id: sessionId,
|
|
212
|
+
agent: "pi",
|
|
213
|
+
tool_name: toolName,
|
|
214
|
+
tool_input: toolInput,
|
|
215
|
+
output_preview: toolOutput,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function mycoPostStop(
|
|
220
|
+
directory: string,
|
|
221
|
+
sessionId: string,
|
|
222
|
+
lastAssistantMessage: string | undefined,
|
|
223
|
+
): Promise<void> {
|
|
224
|
+
await postJson(directory, "/events/stop", {
|
|
225
|
+
session_id: sessionId,
|
|
226
|
+
agent: "pi",
|
|
227
|
+
last_assistant_message: lastAssistantMessage,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function fetchMycoSessionContext(
|
|
232
|
+
directory: string,
|
|
233
|
+
sessionId: string,
|
|
234
|
+
): Promise<string | null> {
|
|
235
|
+
const result = await postJson(directory, "/context", { session_id: sessionId });
|
|
236
|
+
if (!result.ok) return null;
|
|
237
|
+
const data = result.data as { text?: string } | undefined;
|
|
238
|
+
const text = data?.text?.trim() ?? "";
|
|
239
|
+
return text.length > 0 ? text : null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function fetchMycoResumeContext(
|
|
243
|
+
directory: string,
|
|
244
|
+
sessionId: string,
|
|
245
|
+
parentSessionId: string,
|
|
246
|
+
): Promise<string | null> {
|
|
247
|
+
const result = await postJson(directory, "/context/resume", {
|
|
248
|
+
session_id: sessionId,
|
|
249
|
+
parent_session_id: parentSessionId,
|
|
250
|
+
});
|
|
251
|
+
if (!result.ok) return null;
|
|
252
|
+
const data = result.data as { text?: string } | undefined;
|
|
253
|
+
const text = data?.text?.trim() ?? "";
|
|
254
|
+
if (!text || text.length > RESUME_CONTEXT_MAX_CHARS) return null;
|
|
255
|
+
return text;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async function mycoPostCompact(
|
|
259
|
+
directory: string,
|
|
260
|
+
sessionId: string,
|
|
261
|
+
): Promise<void> {
|
|
262
|
+
await postEventWithBuffer(directory, sessionId, {
|
|
263
|
+
type: "pre_compact",
|
|
264
|
+
session_id: sessionId,
|
|
265
|
+
agent: "pi",
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
// Helpers
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
|
|
273
|
+
function summarizeToolOutput(output: unknown): string {
|
|
274
|
+
if (typeof output !== "string") return "";
|
|
275
|
+
return output.length > TOOL_OUTPUT_PREVIEW_CHARS
|
|
276
|
+
? output.slice(0, TOOL_OUTPUT_PREVIEW_CHARS) + "..."
|
|
277
|
+
: output;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Derive a stable session ID from pi's session file path.
|
|
282
|
+
* Pi sessions are stored as JSONL files with UUID-based names
|
|
283
|
+
* at ~/.pi/agent/sessions/<path-hash>/<timestamp>_<uuid>.jsonl.
|
|
284
|
+
* We extract the filename (without extension) as the session ID.
|
|
285
|
+
*/
|
|
286
|
+
function deriveSessionId(sessionFile: string | null): string | null {
|
|
287
|
+
if (!sessionFile) return null;
|
|
288
|
+
const base = sessionFile.split("/").pop() ?? sessionFile;
|
|
289
|
+
return base.replace(/\.jsonl$/, "");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Extract text content from pi message content (string or content block array).
|
|
294
|
+
*/
|
|
295
|
+
function extractTextFromContent(content: unknown): string {
|
|
296
|
+
if (typeof content === "string") return content;
|
|
297
|
+
if (!Array.isArray(content)) return "";
|
|
298
|
+
return content
|
|
299
|
+
.filter((c: { type?: string; text?: string }) => c.type === "text" && c.text)
|
|
300
|
+
.map((c: { text: string }) => c.text)
|
|
301
|
+
.join("\n");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Extract images from a pi message content array.
|
|
306
|
+
*/
|
|
307
|
+
function extractImagesFromContent(content: unknown): Array<{ data: string; mediaType: string }> {
|
|
308
|
+
if (!Array.isArray(content)) return [];
|
|
309
|
+
return content
|
|
310
|
+
.filter((c: { type?: string; data?: string; mimeType?: string }) =>
|
|
311
|
+
c.type === "image" && c.data && c.mimeType)
|
|
312
|
+
.map((c: { data: string; mimeType: string }) => ({
|
|
313
|
+
data: c.data,
|
|
314
|
+
mediaType: c.mimeType,
|
|
315
|
+
}));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ---------------------------------------------------------------------------
|
|
319
|
+
// Extension entry
|
|
320
|
+
// ---------------------------------------------------------------------------
|
|
321
|
+
|
|
322
|
+
export default function (pi: ExtensionAPI) {
|
|
323
|
+
let currentSessionId: string | null = null;
|
|
324
|
+
let currentCwd: string = process.cwd();
|
|
325
|
+
let lastAssistantMessage: string = "";
|
|
326
|
+
|
|
327
|
+
// ── Session lifecycle ──────────────────────────────────────────────────
|
|
328
|
+
|
|
329
|
+
pi.on("session_start", async (event, ctx) => {
|
|
330
|
+
currentCwd = ctx.cwd;
|
|
331
|
+
|
|
332
|
+
// Check if daemon is available — silent no-op if not
|
|
333
|
+
if (!getDaemonPort(currentCwd)) return;
|
|
334
|
+
|
|
335
|
+
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
336
|
+
const sessionId = deriveSessionId(sessionFile);
|
|
337
|
+
if (!sessionId) return;
|
|
338
|
+
|
|
339
|
+
currentSessionId = sessionId;
|
|
340
|
+
lastAssistantMessage = "";
|
|
341
|
+
|
|
342
|
+
const isResume = event.reason === "resume";
|
|
343
|
+
const isFork = event.reason === "fork";
|
|
344
|
+
|
|
345
|
+
// Register with the daemon
|
|
346
|
+
await mycoRegisterSession(currentCwd, sessionId);
|
|
347
|
+
|
|
348
|
+
// Fetch and inject context as a persistent custom message.
|
|
349
|
+
// Pi's before_agent_start hook augments the system prompt each turn,
|
|
350
|
+
// but this initial injection ensures context is visible in the session
|
|
351
|
+
// history and survives compaction.
|
|
352
|
+
let contextText: string | null = null;
|
|
353
|
+
|
|
354
|
+
if (isResume && event.previousSessionFile) {
|
|
355
|
+
const previousSessionId = deriveSessionId(event.previousSessionFile);
|
|
356
|
+
if (previousSessionId) {
|
|
357
|
+
contextText = await fetchMycoResumeContext(currentCwd, sessionId, previousSessionId);
|
|
358
|
+
}
|
|
359
|
+
} else if (!isFork) {
|
|
360
|
+
contextText = await fetchMycoSessionContext(currentCwd, sessionId);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (contextText) {
|
|
364
|
+
pi.sendMessage({
|
|
365
|
+
customType: "myco-context",
|
|
366
|
+
content: contextText,
|
|
367
|
+
display: false,
|
|
368
|
+
}, {
|
|
369
|
+
deliverAs: "nextTurn",
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
pi.on("session_shutdown", async () => {
|
|
375
|
+
if (!currentSessionId) return;
|
|
376
|
+
|
|
377
|
+
await mycoPostStop(currentCwd, currentSessionId, lastAssistantMessage || undefined);
|
|
378
|
+
await mycoUnregisterSession(currentCwd, currentSessionId);
|
|
379
|
+
currentSessionId = null;
|
|
380
|
+
lastAssistantMessage = "";
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// ── User prompt capture + context injection ────────────────────────────
|
|
384
|
+
//
|
|
385
|
+
// Single before_agent_start handler: captures the user prompt AND
|
|
386
|
+
// augments the system prompt with Myco context. This avoids registering
|
|
387
|
+
// two handlers for the same event (pi chains them, but the second
|
|
388
|
+
// handler's return value would overwrite the first).
|
|
389
|
+
|
|
390
|
+
pi.on("before_agent_start", async (event, _ctx) => {
|
|
391
|
+
if (!currentSessionId) return;
|
|
392
|
+
|
|
393
|
+
// 1. Capture the user prompt
|
|
394
|
+
const prompt = event.prompt ?? "";
|
|
395
|
+
const images = extractImagesFromContent(event.images);
|
|
396
|
+
if (prompt) {
|
|
397
|
+
// Fire-and-forget capture — don't block the agent start
|
|
398
|
+
mycoPostUserPrompt(currentCwd, currentSessionId, prompt, images);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// 2. Augment system prompt with Myco context
|
|
402
|
+
const contextText = await fetchMycoSessionContext(currentCwd, currentSessionId);
|
|
403
|
+
if (contextText) {
|
|
404
|
+
return {
|
|
405
|
+
systemPrompt: event.systemPrompt + "\n\n" + contextText,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
return undefined;
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// ── Tool use capture ───────────────────────────────────────────────────
|
|
412
|
+
|
|
413
|
+
pi.on("tool_result", async (event) => {
|
|
414
|
+
if (!currentSessionId) return;
|
|
415
|
+
|
|
416
|
+
const toolName = event.toolName ?? "unknown";
|
|
417
|
+
const toolInput = event.input ?? {};
|
|
418
|
+
const rawOutput = Array.isArray(event.content)
|
|
419
|
+
? event.content
|
|
420
|
+
.filter((c: { type?: string; text?: string }) => c.type === "text")
|
|
421
|
+
.map((c: { text: string }) => c.text)
|
|
422
|
+
.join("\n")
|
|
423
|
+
: "";
|
|
424
|
+
const toolOutput = summarizeToolOutput(rawOutput);
|
|
425
|
+
|
|
426
|
+
// Fire-and-forget — don't block tool result processing
|
|
427
|
+
mycoPostToolUse(currentCwd, currentSessionId, toolName, toolInput, toolOutput);
|
|
428
|
+
return undefined;
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
// ── Track last assistant message ───────────────────────────────────────
|
|
432
|
+
|
|
433
|
+
pi.on("message_end", async (event) => {
|
|
434
|
+
if (!currentSessionId) return;
|
|
435
|
+
if (event.message?.role === "assistant") {
|
|
436
|
+
const text = extractTextFromContent(event.message.content);
|
|
437
|
+
if (text) {
|
|
438
|
+
lastAssistantMessage = text;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// ── Agent end → post stop for agentic loop completion ──────────────────
|
|
444
|
+
//
|
|
445
|
+
// Pi fires agent_end after each user prompt's agentic loop completes.
|
|
446
|
+
// We post a stop event so the daemon can process the turn. session_shutdown
|
|
447
|
+
// handles the final cleanup on exit.
|
|
448
|
+
|
|
449
|
+
pi.on("agent_end", async () => {
|
|
450
|
+
if (!currentSessionId) return;
|
|
451
|
+
await mycoPostStop(currentCwd, currentSessionId, lastAssistantMessage || undefined);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// ── Compaction hook — notify daemon of context compaction ──────────────
|
|
455
|
+
|
|
456
|
+
pi.on("session_before_compact", async () => {
|
|
457
|
+
if (!currentSessionId) return;
|
|
458
|
+
await mycoPostCompact(currentCwd, currentSessionId);
|
|
459
|
+
return undefined;
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
// ── MCP tool proxies — expose Myco's intelligence to the LLM ──────────
|
|
463
|
+
//
|
|
464
|
+
// Pi has no native MCP support. Instead, we register Myco's core tools
|
|
465
|
+
// directly via pi.registerTool() so the LLM can query the knowledge vault.
|
|
466
|
+
|
|
467
|
+
pi.registerTool({
|
|
468
|
+
name: "myco_context",
|
|
469
|
+
label: "Myco Context",
|
|
470
|
+
description:
|
|
471
|
+
"Get project context, observations, and intelligence from Myco's knowledge vault. " +
|
|
472
|
+
"Use this to understand the project's history, prior decisions, gotchas, and patterns.",
|
|
473
|
+
promptSnippet: "Query Myco vault for project intelligence, prior decisions, and observations",
|
|
474
|
+
promptGuidelines: [
|
|
475
|
+
"Use myco_context at the start of complex tasks to understand project history and prior decisions.",
|
|
476
|
+
"Use myco_context when you encounter unfamiliar code patterns or architecture choices.",
|
|
477
|
+
],
|
|
478
|
+
parameters: Type.Object({}),
|
|
479
|
+
async execute() {
|
|
480
|
+
if (!currentSessionId) {
|
|
481
|
+
return { content: [{ type: "text" as const, text: "No active session" }], details: {} };
|
|
482
|
+
}
|
|
483
|
+
const result = await fetchMycoSessionContext(currentCwd, currentSessionId);
|
|
484
|
+
return {
|
|
485
|
+
content: [{ type: "text" as const, text: result ?? "No context available from Myco vault." }],
|
|
486
|
+
details: {},
|
|
487
|
+
};
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
pi.registerTool({
|
|
492
|
+
name: "myco_search",
|
|
493
|
+
label: "Myco Search",
|
|
494
|
+
description:
|
|
495
|
+
"Search Myco's knowledge vault for specific topics, patterns, or prior observations. " +
|
|
496
|
+
"Returns relevant spores (observations), session summaries, and related intelligence.",
|
|
497
|
+
promptSnippet: "Search Myco vault for specific topics, patterns, or observations",
|
|
498
|
+
promptGuidelines: [
|
|
499
|
+
"Use myco_search when you need specific information about a topic, pattern, or past decision.",
|
|
500
|
+
"Prefer myco_search over myco_context when you have a focused query.",
|
|
501
|
+
],
|
|
502
|
+
parameters: Type.Object({
|
|
503
|
+
query: Type.String({ description: "Search query — topic, pattern, or question" }),
|
|
504
|
+
}),
|
|
505
|
+
async execute(_toolCallId, params) {
|
|
506
|
+
if (!currentSessionId) {
|
|
507
|
+
return { content: [{ type: "text" as const, text: "No active session" }], details: {} };
|
|
508
|
+
}
|
|
509
|
+
const result = await getJson(currentCwd, `/api/search?q=${encodeURIComponent(params.query)}`);
|
|
510
|
+
if (!result.ok || !result.data) {
|
|
511
|
+
return { content: [{ type: "text" as const, text: "Search unavailable — Myco daemon may not be running." }], details: {} };
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
content: [{ type: "text" as const, text: JSON.stringify(result.data, null, 2) }],
|
|
515
|
+
details: {},
|
|
516
|
+
};
|
|
517
|
+
},
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
pi.registerTool({
|
|
521
|
+
name: "myco_observe",
|
|
522
|
+
label: "Myco Observe",
|
|
523
|
+
description:
|
|
524
|
+
"Record an observation (gotcha, decision, discovery, trade-off, bug fix) in Myco's knowledge vault. " +
|
|
525
|
+
"Use this when you discover something important about the codebase that future sessions should know.",
|
|
526
|
+
promptSnippet: "Record an observation in Myco vault for future sessions",
|
|
527
|
+
promptGuidelines: [
|
|
528
|
+
"Use myco_observe to record important discoveries, gotchas, decisions, and trade-offs.",
|
|
529
|
+
"Include enough context that a future session can understand the observation without seeing this conversation.",
|
|
530
|
+
],
|
|
531
|
+
parameters: Type.Object({
|
|
532
|
+
observation_type: Type.String({
|
|
533
|
+
description: "Type: gotcha, decision, discovery, trade-off, bug_fix, pattern, or any descriptive string",
|
|
534
|
+
}),
|
|
535
|
+
title: Type.String({ description: "Short title for the observation" }),
|
|
536
|
+
content: Type.String({ description: "Detailed observation with context" }),
|
|
537
|
+
tags: Type.Optional(Type.Array(Type.String(), { description: "Optional tags for categorization" })),
|
|
538
|
+
}),
|
|
539
|
+
async execute(_toolCallId, params) {
|
|
540
|
+
if (!currentSessionId) {
|
|
541
|
+
return { content: [{ type: "text" as const, text: "No active session" }], details: {} };
|
|
542
|
+
}
|
|
543
|
+
const result = await postJson(currentCwd, "/api/spores", {
|
|
544
|
+
session_id: currentSessionId,
|
|
545
|
+
observation_type: params.observation_type,
|
|
546
|
+
title: params.title,
|
|
547
|
+
content: params.content,
|
|
548
|
+
tags: params.tags ?? [],
|
|
549
|
+
});
|
|
550
|
+
if (!result.ok) {
|
|
551
|
+
return { content: [{ type: "text" as const, text: "Failed to record observation — Myco daemon may not be running." }], details: {} };
|
|
552
|
+
}
|
|
553
|
+
return {
|
|
554
|
+
content: [{ type: "text" as const, text: `Observation recorded: ${params.title}` }],
|
|
555
|
+
details: {},
|
|
556
|
+
};
|
|
557
|
+
},
|
|
558
|
+
});
|
|
559
|
+
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
gatherStats
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-75Z7UKDY.js";
|
|
5
5
|
import {
|
|
6
6
|
initVaultDb
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JR54LTPP.js";
|
|
8
8
|
import "./chunk-SAKJMNSR.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-VHNRMM4O.js";
|
|
10
|
+
import "./chunk-X3IGT5RV.js";
|
|
11
|
+
import "./chunk-53RPGOEN.js";
|
|
12
|
+
import "./chunk-OUJSQSKE.js";
|
|
13
|
+
import "./chunk-POEPHBQK.js";
|
|
12
14
|
import "./chunk-MYX5NCRH.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-P66DLD6G.js";
|
|
16
|
+
import "./chunk-BUTL6IFS.js";
|
|
15
17
|
import "./chunk-LPUQPDC2.js";
|
|
16
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-6C6QZ4PM.js";
|
|
17
19
|
import "./chunk-UUHLLQXO.js";
|
|
18
20
|
import "./chunk-6LQIMRTC.js";
|
|
19
21
|
import "./chunk-ODXLRR4U.js";
|
|
@@ -92,4 +94,4 @@ function formatUptime(seconds) {
|
|
|
92
94
|
export {
|
|
93
95
|
run
|
|
94
96
|
};
|
|
95
|
-
//# sourceMappingURL=stats-
|
|
97
|
+
//# sourceMappingURL=stats-DFG6S23S.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/stats.ts"],"sourcesContent":["/**\n * CLI: myco stats — display vault statistics.\n *\n * Opens the SQLite database directly (WAL mode allows concurrent reads).\n * Does NOT require the daemon to be running.\n */\n\nimport type { V2Stats } from '../services/stats.js';\nimport { gatherStats } from '../services/stats.js';\nimport { initVaultDb } from './shared.js';\n\nexport async function run(_args: string[], vaultDir: string): Promise<void> {\n const cleanup = initVaultDb(vaultDir);\n let stats: V2Stats;\n try {\n stats = gatherStats(vaultDir);\n } catch (err) {\n cleanup();\n console.error('Failed to read vault database:', (err as Error).message);\n process.exit(1);\n }\n cleanup();\n\n console.log('=== Myco Vault ===');\n console.log(`Path: ${stats.vault.path}`);\n console.log(`Name: ${stats.vault.name}`);\n\n console.log('\\n--- Data ---');\n console.log(`Sessions: ${stats.vault.session_count}`);\n console.log(`Batches: ${stats.vault.batch_count}`);\n console.log(`Spores: ${stats.vault.spore_count}`);\n console.log(`Plans: ${stats.vault.plan_count}`);\n console.log(`Artifacts: ${stats.vault.artifact_count}`);\n console.log(`Entities: ${stats.vault.entity_count}`);\n console.log(`Edges: ${stats.vault.edge_count}`);\n\n console.log('\\n--- Embeddings ---');\n console.log(`Provider: ${stats.embedding.provider} (${stats.embedding.model})`);\n console.log(`Embedded: ${stats.embedding.embedded_count} / ${stats.embedding.total_embeddable}`);\n if (stats.embedding.queue_depth > 0) {\n console.log(`Queue: ${stats.embedding.queue_depth} pending`);\n }\n\n console.log('\\n--- Agent ---');\n if (stats.agent.total_runs === 0) {\n console.log('No runs yet');\n } else {\n const lastAt = stats.agent.last_run_at\n ? new Date(stats.agent.last_run_at * 1000).toISOString()\n : 'never';\n console.log(`Last run: ${lastAt} (${stats.agent.last_run_status ?? 'unknown'})`);\n console.log(`Total runs: ${stats.agent.total_runs}`);\n }\n if (stats.unprocessed_batches > 0) {\n console.log(`Pending: ${stats.unprocessed_batches} unprocessed batch(es)`);\n }\n\n console.log('\\n--- Digest ---');\n if (stats.digest.tiers_available.length === 0) {\n console.log('No digest extracts yet');\n } else {\n const generatedAt = stats.digest.generated_at\n ? new Date(stats.digest.generated_at * 1000).toISOString()\n : 'unknown';\n console.log(`Tiers: ${stats.digest.tiers_available.join(', ')}`);\n console.log(`Freshest: tier ${stats.digest.freshest_tier} (generated ${generatedAt})`);\n }\n\n // Daemon section — from the live daemon stats\n const { pid, port, version, uptime_seconds, active_sessions } = stats.daemon;\n if (pid > 0) {\n console.log('\\n--- Daemon ---');\n console.log(`PID: ${pid} (running)`);\n console.log(`Port: ${port}`);\n if (version) console.log(`Version: ${version}`);\n if (uptime_seconds > 0) {\n console.log(`Uptime: ${formatUptime(uptime_seconds)}`);\n }\n console.log(`Dashboard: http://localhost:${port}/`);\n console.log(`Sessions: ${active_sessions.length}`);\n }\n}\n\nfunction formatUptime(seconds: number): string {\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = seconds % 60;\n if (h > 0) return `${h}h ${m}m ${s}s`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/cli/stats.ts"],"sourcesContent":["/**\n * CLI: myco stats — display vault statistics.\n *\n * Opens the SQLite database directly (WAL mode allows concurrent reads).\n * Does NOT require the daemon to be running.\n */\n\nimport type { V2Stats } from '../services/stats.js';\nimport { gatherStats } from '../services/stats.js';\nimport { initVaultDb } from './shared.js';\n\nexport async function run(_args: string[], vaultDir: string): Promise<void> {\n const cleanup = initVaultDb(vaultDir);\n let stats: V2Stats;\n try {\n stats = gatherStats(vaultDir);\n } catch (err) {\n cleanup();\n console.error('Failed to read vault database:', (err as Error).message);\n process.exit(1);\n }\n cleanup();\n\n console.log('=== Myco Vault ===');\n console.log(`Path: ${stats.vault.path}`);\n console.log(`Name: ${stats.vault.name}`);\n\n console.log('\\n--- Data ---');\n console.log(`Sessions: ${stats.vault.session_count}`);\n console.log(`Batches: ${stats.vault.batch_count}`);\n console.log(`Spores: ${stats.vault.spore_count}`);\n console.log(`Plans: ${stats.vault.plan_count}`);\n console.log(`Artifacts: ${stats.vault.artifact_count}`);\n console.log(`Entities: ${stats.vault.entity_count}`);\n console.log(`Edges: ${stats.vault.edge_count}`);\n\n console.log('\\n--- Embeddings ---');\n console.log(`Provider: ${stats.embedding.provider} (${stats.embedding.model})`);\n console.log(`Embedded: ${stats.embedding.embedded_count} / ${stats.embedding.total_embeddable}`);\n if (stats.embedding.queue_depth > 0) {\n console.log(`Queue: ${stats.embedding.queue_depth} pending`);\n }\n\n console.log('\\n--- Agent ---');\n if (stats.agent.total_runs === 0) {\n console.log('No runs yet');\n } else {\n const lastAt = stats.agent.last_run_at\n ? new Date(stats.agent.last_run_at * 1000).toISOString()\n : 'never';\n console.log(`Last run: ${lastAt} (${stats.agent.last_run_status ?? 'unknown'})`);\n console.log(`Total runs: ${stats.agent.total_runs}`);\n }\n if (stats.unprocessed_batches > 0) {\n console.log(`Pending: ${stats.unprocessed_batches} unprocessed batch(es)`);\n }\n\n console.log('\\n--- Digest ---');\n if (stats.digest.tiers_available.length === 0) {\n console.log('No digest extracts yet');\n } else {\n const generatedAt = stats.digest.generated_at\n ? new Date(stats.digest.generated_at * 1000).toISOString()\n : 'unknown';\n console.log(`Tiers: ${stats.digest.tiers_available.join(', ')}`);\n console.log(`Freshest: tier ${stats.digest.freshest_tier} (generated ${generatedAt})`);\n }\n\n // Daemon section — from the live daemon stats\n const { pid, port, version, uptime_seconds, active_sessions } = stats.daemon;\n if (pid > 0) {\n console.log('\\n--- Daemon ---');\n console.log(`PID: ${pid} (running)`);\n console.log(`Port: ${port}`);\n if (version) console.log(`Version: ${version}`);\n if (uptime_seconds > 0) {\n console.log(`Uptime: ${formatUptime(uptime_seconds)}`);\n }\n console.log(`Dashboard: http://localhost:${port}/`);\n console.log(`Sessions: ${active_sessions.length}`);\n }\n}\n\nfunction formatUptime(seconds: number): string {\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = seconds % 60;\n if (h > 0) return `${h}h ${m}m ${s}s`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAWA,eAAsB,IAAI,OAAiB,UAAiC;AAC1E,QAAM,UAAU,YAAY,QAAQ;AACpC,MAAI;AACJ,MAAI;AACF,YAAQ,YAAY,QAAQ;AAAA,EAC9B,SAAS,KAAK;AACZ,YAAQ;AACR,YAAQ,MAAM,kCAAmC,IAAc,OAAO;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ;AAER,UAAQ,IAAI,oBAAoB;AAChC,UAAQ,IAAI,UAAU,MAAM,MAAM,IAAI,EAAE;AACxC,UAAQ,IAAI,UAAU,MAAM,MAAM,IAAI,EAAE;AAExC,UAAQ,IAAI,gBAAgB;AAC5B,UAAQ,IAAI,eAAe,MAAM,MAAM,aAAa,EAAE;AACtD,UAAQ,IAAI,eAAe,MAAM,MAAM,WAAW,EAAE;AACpD,UAAQ,IAAI,eAAe,MAAM,MAAM,WAAW,EAAE;AACpD,UAAQ,IAAI,eAAe,MAAM,MAAM,UAAU,EAAE;AACnD,UAAQ,IAAI,eAAe,MAAM,MAAM,cAAc,EAAE;AACvD,UAAQ,IAAI,eAAe,MAAM,MAAM,YAAY,EAAE;AACrD,UAAQ,IAAI,eAAe,MAAM,MAAM,UAAU,EAAE;AAEnD,UAAQ,IAAI,sBAAsB;AAClC,UAAQ,IAAI,eAAe,MAAM,UAAU,QAAQ,KAAK,MAAM,UAAU,KAAK,GAAG;AAChF,UAAQ,IAAI,eAAe,MAAM,UAAU,cAAc,MAAM,MAAM,UAAU,gBAAgB,EAAE;AACjG,MAAI,MAAM,UAAU,cAAc,GAAG;AACnC,YAAQ,IAAI,eAAe,MAAM,UAAU,WAAW,UAAU;AAAA,EAClE;AAEA,UAAQ,IAAI,iBAAiB;AAC7B,MAAI,MAAM,MAAM,eAAe,GAAG;AAChC,YAAQ,IAAI,aAAa;AAAA,EAC3B,OAAO;AACL,UAAM,SAAS,MAAM,MAAM,cACvB,IAAI,KAAK,MAAM,MAAM,cAAc,GAAI,EAAE,YAAY,IACrD;AACJ,YAAQ,IAAI,eAAe,MAAM,KAAK,MAAM,MAAM,mBAAmB,SAAS,GAAG;AACjF,YAAQ,IAAI,eAAe,MAAM,MAAM,UAAU,EAAE;AAAA,EACrD;AACA,MAAI,MAAM,sBAAsB,GAAG;AACjC,YAAQ,IAAI,eAAe,MAAM,mBAAmB,wBAAwB;AAAA,EAC9E;AAEA,UAAQ,IAAI,kBAAkB;AAC9B,MAAI,MAAM,OAAO,gBAAgB,WAAW,GAAG;AAC7C,YAAQ,IAAI,wBAAwB;AAAA,EACtC,OAAO;AACL,UAAM,cAAc,MAAM,OAAO,eAC7B,IAAI,KAAK,MAAM,OAAO,eAAe,GAAI,EAAE,YAAY,IACvD;AACJ,YAAQ,IAAI,eAAe,MAAM,OAAO,gBAAgB,KAAK,IAAI,CAAC,EAAE;AACpE,YAAQ,IAAI,oBAAoB,MAAM,OAAO,aAAa,eAAe,WAAW,GAAG;AAAA,EACzF;AAGA,QAAM,EAAE,KAAK,MAAM,SAAS,gBAAgB,gBAAgB,IAAI,MAAM;AACtE,MAAI,MAAM,GAAG;AACX,YAAQ,IAAI,kBAAkB;AAC9B,YAAQ,IAAI,cAAc,GAAG,YAAY;AACzC,YAAQ,IAAI,cAAc,IAAI,EAAE;AAChC,QAAI,QAAS,SAAQ,IAAI,cAAc,OAAO,EAAE;AAChD,QAAI,iBAAiB,GAAG;AACtB,cAAQ,IAAI,cAAc,aAAa,cAAc,CAAC,EAAE;AAAA,IAC1D;AACA,YAAQ,IAAI,+BAA+B,IAAI,GAAG;AAClD,YAAQ,IAAI,cAAc,gBAAgB,MAAM,EAAE;AAAA,EACpD;AACF;AAEA,SAAS,aAAa,SAAyB;AAC7C,QAAM,IAAI,KAAK,MAAM,UAAU,IAAI;AACnC,QAAM,IAAI,KAAK,MAAO,UAAU,OAAQ,EAAE;AAC1C,QAAM,IAAI,UAAU;AACpB,MAAI,IAAI,EAAG,QAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;AAClC,MAAI,IAAI,EAAG,QAAO,GAAG,CAAC,KAAK,CAAC;AAC5B,SAAO,GAAG,CAAC;AACb;","names":[]}
|
|
@@ -2,18 +2,18 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
|
|
|
2
2
|
import {
|
|
3
3
|
normalizeHookInput,
|
|
4
4
|
readStdin
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5ZG4RMUH.js";
|
|
6
6
|
import "./chunk-ZXZPJJN3.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveVaultDir
|
|
9
9
|
} from "./chunk-CUDIZJY7.js";
|
|
10
10
|
import {
|
|
11
11
|
DaemonClient
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-P66DLD6G.js";
|
|
13
|
+
import "./chunk-BUTL6IFS.js";
|
|
14
14
|
import "./chunk-NGROSFOH.js";
|
|
15
15
|
import "./chunk-LPUQPDC2.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-6C6QZ4PM.js";
|
|
17
17
|
import "./chunk-UUHLLQXO.js";
|
|
18
18
|
import "./chunk-6LQIMRTC.js";
|
|
19
19
|
import "./chunk-ODXLRR4U.js";
|
|
@@ -46,4 +46,4 @@ async function main() {
|
|
|
46
46
|
export {
|
|
47
47
|
main
|
|
48
48
|
};
|
|
49
|
-
//# sourceMappingURL=stop-
|
|
49
|
+
//# sourceMappingURL=stop-WRBTXEVT.js.map
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
sendEvent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-G6QIBNZM.js";
|
|
5
5
|
import "./chunk-V7XG6V6C.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-5ZG4RMUH.js";
|
|
7
7
|
import "./chunk-ZXZPJJN3.js";
|
|
8
8
|
import "./chunk-CUDIZJY7.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-P66DLD6G.js";
|
|
10
|
+
import "./chunk-BUTL6IFS.js";
|
|
11
11
|
import "./chunk-NGROSFOH.js";
|
|
12
12
|
import "./chunk-LPUQPDC2.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-6C6QZ4PM.js";
|
|
14
14
|
import "./chunk-UUHLLQXO.js";
|
|
15
15
|
import "./chunk-6LQIMRTC.js";
|
|
16
16
|
import "./chunk-ODXLRR4U.js";
|
|
@@ -28,4 +28,4 @@ async function main() {
|
|
|
28
28
|
export {
|
|
29
29
|
main
|
|
30
30
|
};
|
|
31
|
-
//# sourceMappingURL=stop-failure-
|
|
31
|
+
//# sourceMappingURL=stop-failure-32MGIG2Q.js.map
|