@agntk/agent-harness 0.1.4 → 0.1.6
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/README.md +104 -43
- package/dist/{analytics-RPT73WNM.js → analytics-L24W3B7U.js} +1 -2
- package/dist/auto-processor-QIRUOGEI.js +12 -0
- package/dist/{chunk-UPLBF4RZ.js → chunk-2UVWCTAY.js} +2 -2
- package/dist/{chunk-CSL3ERUI.js → chunk-4P6TRFPZ.js} +3 -3
- package/dist/chunk-4P6TRFPZ.js.map +1 -0
- package/dist/{chunk-4CWAGBNS.js → chunk-4TQQZILG.js} +73 -3
- package/dist/chunk-4TQQZILG.js.map +1 -0
- package/dist/{chunk-DA7IKHC4.js → chunk-5CO5JTYT.js} +2 -2
- package/dist/chunk-5CO5JTYT.js.map +1 -0
- package/dist/{chunk-A7BJPQQ6.js → chunk-5O5OGOOQ.js} +2 -2
- package/dist/{chunk-UWQTZMNI.js → chunk-7GZ4D6V6.js} +2 -2
- package/dist/{chunk-FLZU44SV.js → chunk-AN6Y4MDD.js} +6 -6
- package/dist/{chunk-4FDUOGSZ.js → chunk-D7AWV24Z.js} +3 -3
- package/dist/{chunk-CHJ5GNZC.js → chunk-EC42HQQH.js} +2 -2
- package/dist/{chunk-YIJY5DBV.js → chunk-KLYMGWQJ.js} +4 -4
- package/dist/chunk-KLYMGWQJ.js.map +1 -0
- package/dist/{chunk-YUFNYN2H.js → chunk-M62KLIEK.js} +4 -4
- package/dist/chunk-M62KLIEK.js.map +1 -0
- package/dist/{chunk-GJNNR2RA.js → chunk-M6PDMK2O.js} +3 -3
- package/dist/{chunk-M7NXUK55.js → chunk-NVC2WY4K.js} +2 -2
- package/dist/{chunk-XTBKL5BI.js → chunk-PMFAYKBD.js} +2 -2
- package/dist/chunk-PMFAYKBD.js.map +1 -0
- package/dist/{chunk-274RV3YO.js → chunk-QMOIVORH.js} +3 -3
- package/dist/chunk-QMOIVORH.js.map +1 -0
- package/dist/{chunk-RY3ZFII7.js → chunk-SEHAQTBO.js} +6 -6
- package/dist/{chunk-MPZ3BPUI.js → chunk-UMXPOYZR.js} +4 -4
- package/dist/{chunk-W4T7PGI2.js → chunk-UXCHAS3Z.js} +4 -4
- package/dist/cli/index.js +153 -167
- package/dist/cli/index.js.map +1 -1
- package/dist/config-PYSS3QY6.js +12 -0
- package/dist/context-loader-RSXXFW5R.js +12 -0
- package/dist/{conversation-QDEIDQPH.js → conversation-TBTFIJVU.js} +6 -7
- package/dist/{cost-tracker-RS3W7SVY.js → cost-tracker-NZRZEHVA.js} +1 -2
- package/dist/{delegate-VJCJLYEK.js → delegate-3KJAL4NZ.js} +7 -8
- package/dist/{emotional-state-VQVRA6ED.js → emotional-state-IN4ZUL2Q.js} +1 -2
- package/dist/{emotional-state-VQVRA6ED.js.map → emotional-state-IN4ZUL2Q.js.map} +1 -1
- package/dist/{env-discovery-2BLVMAIM.js → env-discovery-PXBRE5FX.js} +1 -2
- package/dist/{env-discovery-2BLVMAIM.js.map → env-discovery-PXBRE5FX.js.map} +1 -1
- package/dist/{export-6GCYHEHQ.js → export-GYLWROMB.js} +3 -4
- package/dist/{export-6GCYHEHQ.js.map → export-GYLWROMB.js.map} +1 -1
- package/dist/graph-LEEO37L3.js +13 -0
- package/dist/{harness-WE4SLCML.js → harness-R5FKRICG.js} +8 -9
- package/dist/{health-NZ6WNIMV.js → health-HL2JYHIY.js} +1 -2
- package/dist/indexer-L5UC6J2V.js +15 -0
- package/dist/{instinct-learner-SRM72DHF.js → instinct-learner-QGAMIS3X.js} +5 -6
- package/dist/{intake-4M3HNU43.js → intake-SVJKFHTL.js} +5 -6
- package/dist/{intelligence-HJOCA4SJ.js → intelligence-XPV3MC5U.js} +10 -13
- package/dist/intelligence-XPV3MC5U.js.map +1 -0
- package/dist/{journal-WANJL3MI.js → journal-ITUMKT6U.js} +5 -6
- package/dist/{loader-C3TKIKZR.js → loader-27PLDCOJ.js} +3 -4
- package/dist/{mcp-WTQJJZAO.js → mcp-JSIUJJZV.js} +1 -2
- package/dist/{mcp-discovery-WPAQFL6S.js → mcp-discovery-DG3RQYLM.js} +1 -2
- package/dist/{mcp-discovery-WPAQFL6S.js.map → mcp-discovery-DG3RQYLM.js.map} +1 -1
- package/dist/{mcp-installer-6O2XXD3V.js → mcp-installer-X2TJ2S2G.js} +3 -4
- package/dist/{mcp-installer-6O2XXD3V.js.map → mcp-installer-X2TJ2S2G.js.map} +1 -1
- package/dist/{metrics-KXGNFAAB.js → metrics-2MNINXNQ.js} +1 -2
- package/dist/{primitive-registry-I6VTIR4W.js → primitive-registry-ZMGGXSO5.js} +3 -4
- package/dist/{primitive-registry-I6VTIR4W.js.map → primitive-registry-ZMGGXSO5.js.map} +1 -1
- package/dist/{project-discovery-C4UMD7JI.js → project-discovery-FQLAZKEM.js} +1 -2
- package/dist/project-discovery-FQLAZKEM.js.map +1 -0
- package/dist/{provider-SXPQZ74H.js → provider-HQY6SPZI.js} +1 -2
- package/dist/{rate-limiter-RLRVM325.js → rate-limiter-PH5DCVU4.js} +1 -2
- package/dist/{rule-engine-YGQ3RYZM.js → rule-engine-DM26S77N.js} +3 -4
- package/dist/{rule-engine-YGQ3RYZM.js.map → rule-engine-DM26S77N.js.map} +1 -1
- package/dist/{scaffold-A3VRRCBV.js → scaffold-2F36YVW6.js} +5 -6
- package/dist/{scaffold-A3VRRCBV.js.map → scaffold-2F36YVW6.js.map} +1 -1
- package/dist/{scheduler-XHHIVHRI.js → scheduler-Q7GB2KCW.js} +11 -12
- package/dist/{scheduler-XHHIVHRI.js.map → scheduler-Q7GB2KCW.js.map} +1 -1
- package/dist/{search-V3W5JMJG.js → search-6Y6NCOLQ.js} +3 -4
- package/dist/search-6Y6NCOLQ.js.map +1 -0
- package/dist/{semantic-search-2DTOO5UX.js → semantic-search-FN6FZIXI.js} +3 -4
- package/dist/semantic-search-FN6FZIXI.js.map +1 -0
- package/dist/{serve-DTQ3HENY.js → serve-MXRTP2HE.js} +10 -11
- package/dist/serve-MXRTP2HE.js.map +1 -0
- package/dist/{sessions-CZGVXKQE.js → sessions-G6SZZXWS.js} +1 -2
- package/dist/{sources-RW5DT56F.js → sources-7LDYO5GK.js} +1 -2
- package/dist/{starter-packs-76YUVHEU.js → starter-packs-OR7NI5NA.js} +1 -2
- package/dist/{starter-packs-76YUVHEU.js.map → starter-packs-OR7NI5NA.js.map} +1 -1
- package/dist/{state-GMXILIHW.js → state-25IQEC5C.js} +1 -2
- package/dist/{state-merge-NKO5FRBA.js → state-merge-E333OEIQ.js} +1 -2
- package/dist/{state-merge-NKO5FRBA.js.map → state-merge-E333OEIQ.js.map} +1 -1
- package/dist/{telemetry-UC6PBXC7.js → telemetry-RS2JZUZP.js} +4 -5
- package/dist/{tool-executor-MJ7IG7PQ.js → tool-executor-6I5PHQDY.js} +5 -6
- package/dist/{tools-DZ4KETET.js → tools-NDFJNVHK.js} +4 -5
- package/dist/{types-EW7AIB3R.js → types-NPJZAI72.js} +2 -3
- package/dist/{universal-installer-AAXXYM5A.js → universal-installer-LCAZHFZR.js} +91 -7
- package/dist/universal-installer-LCAZHFZR.js.map +1 -0
- package/dist/validator-LM7RZWSH.js +21 -0
- package/dist/{verification-gate-FYXUX6LH.js → verification-gate-2O6DF2B7.js} +3 -4
- package/dist/verification-gate-2O6DF2B7.js.map +1 -0
- package/dist/{versioning-Z3XNE2Q2.js → versioning-WEGF6KJG.js} +1 -2
- package/dist/versioning-WEGF6KJG.js.map +1 -0
- package/dist/{watcher-ISJC7YKL.js → watcher-GZWQSWZ6.js} +5 -6
- package/dist/{watcher-ISJC7YKL.js.map → watcher-GZWQSWZ6.js.map} +1 -1
- package/dist/{web-server-DD7ZOP46.js → web-server-2Y4CHD2W.js} +8 -9
- package/package.json +1 -9
- package/dist/agent-framework-K4GUIICH.js +0 -344
- package/dist/agent-framework-K4GUIICH.js.map +0 -1
- package/dist/auto-processor-OLE45UI3.js +0 -13
- package/dist/chunk-274RV3YO.js.map +0 -1
- package/dist/chunk-4CWAGBNS.js.map +0 -1
- package/dist/chunk-CSL3ERUI.js.map +0 -1
- package/dist/chunk-DA7IKHC4.js.map +0 -1
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-FD55B3IO.js +0 -204
- package/dist/chunk-FD55B3IO.js.map +0 -1
- package/dist/chunk-GUJTBGVS.js +0 -2212
- package/dist/chunk-GUJTBGVS.js.map +0 -1
- package/dist/chunk-KFX54TQM.js +0 -165
- package/dist/chunk-KFX54TQM.js.map +0 -1
- package/dist/chunk-XTBKL5BI.js.map +0 -1
- package/dist/chunk-YIJY5DBV.js.map +0 -1
- package/dist/chunk-YUFNYN2H.js.map +0 -1
- package/dist/chunk-ZZJOFKAT.js +0 -13
- package/dist/config-WVMRUOCA.js +0 -13
- package/dist/context-loader-3ORBPMHJ.js +0 -13
- package/dist/graph-YUIPOSOO.js +0 -14
- package/dist/harness-LCHA3DWP.js +0 -10
- package/dist/index.d.ts +0 -3612
- package/dist/index.js +0 -13713
- package/dist/index.js.map +0 -1
- package/dist/indexer-LONANRRM.js +0 -16
- package/dist/intelligence-HJOCA4SJ.js.map +0 -1
- package/dist/project-discovery-C4UMD7JI.js.map +0 -1
- package/dist/provider-LQHQX7Z7.js +0 -26
- package/dist/search-V3W5JMJG.js.map +0 -1
- package/dist/semantic-search-2DTOO5UX.js.map +0 -1
- package/dist/serve-DTQ3HENY.js.map +0 -1
- package/dist/tools-DZ4KETET.js.map +0 -1
- package/dist/types-EW7AIB3R.js.map +0 -1
- package/dist/types-WGDLSPO6.js +0 -16
- package/dist/types-WGDLSPO6.js.map +0 -1
- package/dist/universal-installer-AAXXYM5A.js.map +0 -1
- package/dist/validator-7WXMDIHH.js +0 -22
- package/dist/validator-7WXMDIHH.js.map +0 -1
- package/dist/verification-gate-FYXUX6LH.js.map +0 -1
- package/dist/versioning-Z3XNE2Q2.js.map +0 -1
- package/dist/web-server-DD7ZOP46.js.map +0 -1
- /package/dist/{analytics-RPT73WNM.js.map → analytics-L24W3B7U.js.map} +0 -0
- /package/dist/{auto-processor-OLE45UI3.js.map → auto-processor-QIRUOGEI.js.map} +0 -0
- /package/dist/{chunk-UPLBF4RZ.js.map → chunk-2UVWCTAY.js.map} +0 -0
- /package/dist/{chunk-A7BJPQQ6.js.map → chunk-5O5OGOOQ.js.map} +0 -0
- /package/dist/{chunk-UWQTZMNI.js.map → chunk-7GZ4D6V6.js.map} +0 -0
- /package/dist/{chunk-FLZU44SV.js.map → chunk-AN6Y4MDD.js.map} +0 -0
- /package/dist/{chunk-4FDUOGSZ.js.map → chunk-D7AWV24Z.js.map} +0 -0
- /package/dist/{chunk-CHJ5GNZC.js.map → chunk-EC42HQQH.js.map} +0 -0
- /package/dist/{chunk-GJNNR2RA.js.map → chunk-M6PDMK2O.js.map} +0 -0
- /package/dist/{chunk-M7NXUK55.js.map → chunk-NVC2WY4K.js.map} +0 -0
- /package/dist/{chunk-RY3ZFII7.js.map → chunk-SEHAQTBO.js.map} +0 -0
- /package/dist/{chunk-MPZ3BPUI.js.map → chunk-UMXPOYZR.js.map} +0 -0
- /package/dist/{chunk-W4T7PGI2.js.map → chunk-UXCHAS3Z.js.map} +0 -0
- /package/dist/{chunk-DGUM43GV.js.map → config-PYSS3QY6.js.map} +0 -0
- /package/dist/{chunk-ZZJOFKAT.js.map → context-loader-RSXXFW5R.js.map} +0 -0
- /package/dist/{config-WVMRUOCA.js.map → conversation-TBTFIJVU.js.map} +0 -0
- /package/dist/{context-loader-3ORBPMHJ.js.map → cost-tracker-NZRZEHVA.js.map} +0 -0
- /package/dist/{conversation-QDEIDQPH.js.map → delegate-3KJAL4NZ.js.map} +0 -0
- /package/dist/{cost-tracker-RS3W7SVY.js.map → graph-LEEO37L3.js.map} +0 -0
- /package/dist/{delegate-VJCJLYEK.js.map → harness-R5FKRICG.js.map} +0 -0
- /package/dist/{graph-YUIPOSOO.js.map → health-HL2JYHIY.js.map} +0 -0
- /package/dist/{harness-LCHA3DWP.js.map → indexer-L5UC6J2V.js.map} +0 -0
- /package/dist/{harness-WE4SLCML.js.map → instinct-learner-QGAMIS3X.js.map} +0 -0
- /package/dist/{health-NZ6WNIMV.js.map → intake-SVJKFHTL.js.map} +0 -0
- /package/dist/{indexer-LONANRRM.js.map → journal-ITUMKT6U.js.map} +0 -0
- /package/dist/{instinct-learner-SRM72DHF.js.map → loader-27PLDCOJ.js.map} +0 -0
- /package/dist/{intake-4M3HNU43.js.map → mcp-JSIUJJZV.js.map} +0 -0
- /package/dist/{journal-WANJL3MI.js.map → metrics-2MNINXNQ.js.map} +0 -0
- /package/dist/{loader-C3TKIKZR.js.map → provider-HQY6SPZI.js.map} +0 -0
- /package/dist/{mcp-WTQJJZAO.js.map → rate-limiter-PH5DCVU4.js.map} +0 -0
- /package/dist/{metrics-KXGNFAAB.js.map → sessions-G6SZZXWS.js.map} +0 -0
- /package/dist/{provider-LQHQX7Z7.js.map → sources-7LDYO5GK.js.map} +0 -0
- /package/dist/{provider-SXPQZ74H.js.map → state-25IQEC5C.js.map} +0 -0
- /package/dist/{rate-limiter-RLRVM325.js.map → telemetry-RS2JZUZP.js.map} +0 -0
- /package/dist/{sessions-CZGVXKQE.js.map → tool-executor-6I5PHQDY.js.map} +0 -0
- /package/dist/{sources-RW5DT56F.js.map → tools-NDFJNVHK.js.map} +0 -0
- /package/dist/{state-GMXILIHW.js.map → types-NPJZAI72.js.map} +0 -0
- /package/dist/{telemetry-UC6PBXC7.js.map → validator-LM7RZWSH.js.map} +0 -0
- /package/dist/{tool-executor-MJ7IG7PQ.js.map → web-server-2Y4CHD2W.js.map} +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
buildSystemPrompt
|
|
5
|
+
} from "./chunk-7GZ4D6V6.js";
|
|
6
|
+
import "./chunk-2UVWCTAY.js";
|
|
7
|
+
import "./chunk-BSKDOFRT.js";
|
|
8
|
+
import "./chunk-4TQQZILG.js";
|
|
9
|
+
export {
|
|
10
|
+
buildSystemPrompt
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=context-loader-RSXXFW5R.js.map
|
|
@@ -4,19 +4,18 @@ import {
|
|
|
4
4
|
Conversation,
|
|
5
5
|
parseJsonlContext,
|
|
6
6
|
parseLegacyContext
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-UMXPOYZR.js";
|
|
8
|
+
import "./chunk-7GZ4D6V6.js";
|
|
9
9
|
import "./chunk-DTTXPHFW.js";
|
|
10
10
|
import "./chunk-Z2PUCXTZ.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-2UVWCTAY.js";
|
|
12
12
|
import "./chunk-BSKDOFRT.js";
|
|
13
13
|
import "./chunk-IZ6UZ3ZL.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-ZZJOFKAT.js";
|
|
14
|
+
import "./chunk-EC42HQQH.js";
|
|
15
|
+
import "./chunk-4TQQZILG.js";
|
|
17
16
|
export {
|
|
18
17
|
Conversation,
|
|
19
18
|
parseJsonlContext,
|
|
20
19
|
parseLegacyContext
|
|
21
20
|
};
|
|
22
|
-
//# sourceMappingURL=conversation-
|
|
21
|
+
//# sourceMappingURL=conversation-TBTFIJVU.js.map
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
recordCost,
|
|
11
11
|
saveCosts
|
|
12
12
|
} from "./chunk-JKMGYWXB.js";
|
|
13
|
-
import "./chunk-ZZJOFKAT.js";
|
|
14
13
|
export {
|
|
15
14
|
calculateCost,
|
|
16
15
|
checkBudget,
|
|
@@ -21,4 +20,4 @@ export {
|
|
|
21
20
|
recordCost,
|
|
22
21
|
saveCosts
|
|
23
22
|
};
|
|
24
|
-
//# sourceMappingURL=cost-tracker-
|
|
23
|
+
//# sourceMappingURL=cost-tracker-NZRZEHVA.js.map
|
|
@@ -7,17 +7,16 @@ import {
|
|
|
7
7
|
findAgent,
|
|
8
8
|
listAgents,
|
|
9
9
|
loadAgentDocs
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-M62KLIEK.js";
|
|
11
|
+
import "./chunk-5CO5JTYT.js";
|
|
12
12
|
import "./chunk-DTTXPHFW.js";
|
|
13
13
|
import "./chunk-Z2PUCXTZ.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-PMFAYKBD.js";
|
|
15
|
+
import "./chunk-2UVWCTAY.js";
|
|
16
16
|
import "./chunk-BSKDOFRT.js";
|
|
17
17
|
import "./chunk-IZ6UZ3ZL.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-ZZJOFKAT.js";
|
|
18
|
+
import "./chunk-EC42HQQH.js";
|
|
19
|
+
import "./chunk-4TQQZILG.js";
|
|
21
20
|
export {
|
|
22
21
|
buildAgentPrompt,
|
|
23
22
|
delegateStream,
|
|
@@ -26,4 +25,4 @@ export {
|
|
|
26
25
|
listAgents,
|
|
27
26
|
loadAgentDocs
|
|
28
27
|
};
|
|
29
|
-
//# sourceMappingURL=delegate-
|
|
28
|
+
//# sourceMappingURL=delegate-3KJAL4NZ.js.map
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import {
|
|
4
4
|
withFileLockSync
|
|
5
5
|
} from "./chunk-Z2PUCXTZ.js";
|
|
6
|
-
import "./chunk-ZZJOFKAT.js";
|
|
7
6
|
|
|
8
7
|
// src/runtime/emotional-state.ts
|
|
9
8
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -203,4 +202,4 @@ export {
|
|
|
203
202
|
saveEmotionalState,
|
|
204
203
|
summarizeEmotionalState
|
|
205
204
|
};
|
|
206
|
-
//# sourceMappingURL=emotional-state-
|
|
205
|
+
//# sourceMappingURL=emotional-state-IN4ZUL2Q.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/emotional-state.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { withFileLockSync } from './file-lock.js';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * Emotional valence dimensions for agent self-assessment.\n * These are not human emotions — they represent operational disposition signals\n * that influence context loading, risk tolerance, and communication style.\n */\nexport interface EmotionalState {\n /** Confidence in current task (0-100). Low → more cautious, more verification. */\n confidence: number;\n /** Engagement/focus level (0-100). Low → may need re-orientation. */\n engagement: number;\n /** Frustration/difficulty signal (0-100). High → may need escalation or approach change. */\n frustration: number;\n /** Curiosity/exploration drive (0-100). High → more likely to explore tangents. */\n curiosity: number;\n /** Urgency/time-pressure (0-100). High → skip verification, prioritize speed. */\n urgency: number;\n /** Last updated timestamp */\n updatedAt: string;\n /** Optional notes about the emotional state */\n notes?: string;\n}\n\nexport interface EmotionalSignal {\n dimension: keyof Omit<EmotionalState, 'updatedAt' | 'notes'>;\n delta: number;\n reason?: string;\n}\n\nexport interface EmotionalSnapshot {\n state: EmotionalState;\n signals: EmotionalSignal[];\n timestamp: string;\n}\n\nexport interface EmotionalTrend {\n dimension: keyof Omit<EmotionalState, 'updatedAt' | 'notes'>;\n values: Array<{ value: number; timestamp: string }>;\n trend: 'rising' | 'falling' | 'stable';\n average: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst EMOTIONAL_STATE_FILE = 'emotional-state.json';\nconst EMOTIONAL_HISTORY_FILE = 'emotional-history.jsonl';\n\nconst DEFAULT_EMOTIONAL_STATE: EmotionalState = {\n confidence: 50,\n engagement: 50,\n frustration: 0,\n curiosity: 50,\n urgency: 0,\n updatedAt: new Date().toISOString(),\n};\n\nconst DIMENSIONS: Array<keyof Omit<EmotionalState, 'updatedAt' | 'notes'>> = [\n 'confidence',\n 'engagement',\n 'frustration',\n 'curiosity',\n 'urgency',\n];\n\n// ─── Load / Save ─────────────────────────────────────────────────────────────\n\n/** Load the current emotional state from the harness memory directory. */\nexport function loadEmotionalState(harnessDir: string): EmotionalState {\n const stateDir = join(harnessDir, 'memory');\n const statePath = join(stateDir, EMOTIONAL_STATE_FILE);\n\n if (!existsSync(statePath)) {\n return { ...DEFAULT_EMOTIONAL_STATE, updatedAt: new Date().toISOString() };\n }\n\n try {\n const raw = readFileSync(statePath, 'utf-8');\n const parsed = JSON.parse(raw) as Partial<EmotionalState>;\n return {\n confidence: clamp(parsed.confidence ?? 50),\n engagement: clamp(parsed.engagement ?? 50),\n frustration: clamp(parsed.frustration ?? 0),\n curiosity: clamp(parsed.curiosity ?? 50),\n urgency: clamp(parsed.urgency ?? 0),\n updatedAt: parsed.updatedAt ?? new Date().toISOString(),\n notes: parsed.notes,\n };\n } catch {\n return { ...DEFAULT_EMOTIONAL_STATE, updatedAt: new Date().toISOString() };\n }\n}\n\n/** Save the emotional state to the harness memory directory. */\nexport function saveEmotionalState(harnessDir: string, state: EmotionalState): void {\n const stateDir = join(harnessDir, 'memory');\n if (!existsSync(stateDir)) {\n mkdirSync(stateDir, { recursive: true });\n }\n\n const statePath = join(stateDir, EMOTIONAL_STATE_FILE);\n const normalized: EmotionalState = {\n confidence: clamp(state.confidence),\n engagement: clamp(state.engagement),\n frustration: clamp(state.frustration),\n curiosity: clamp(state.curiosity),\n urgency: clamp(state.urgency),\n updatedAt: state.updatedAt,\n notes: state.notes,\n };\n\n withFileLockSync(harnessDir, statePath, () => {\n writeFileSync(statePath, JSON.stringify(normalized, null, 2), 'utf-8');\n });\n}\n\n// ─── Update Logic ────────────────────────────────────────────────────────────\n\n/**\n * Apply emotional signals to the current state.\n * Signals are additive deltas (e.g., { dimension: 'confidence', delta: +10 }).\n * Values are clamped to 0-100.\n *\n * Also appends to the history file for trend analysis.\n */\nexport function applySignals(\n harnessDir: string,\n signals: EmotionalSignal[],\n): EmotionalState {\n const state = loadEmotionalState(harnessDir);\n const now = new Date().toISOString();\n\n for (const signal of signals) {\n if (!DIMENSIONS.includes(signal.dimension)) continue;\n const current = state[signal.dimension] as number;\n state[signal.dimension] = clamp(current + signal.delta);\n }\n\n state.updatedAt = now;\n saveEmotionalState(harnessDir, state);\n\n // Append to history\n appendHistory(harnessDir, { state, signals, timestamp: now });\n\n return state;\n}\n\n/**\n * Derive emotional signals from session outcomes.\n *\n * Heuristic rules:\n * - Successful run → confidence +5, frustration -5\n * - Long run (many steps) → engagement +3, urgency +2\n * - Error → frustration +10, confidence -5\n * - Tool calls → curiosity +2\n * - Budget close to limit → urgency +10\n */\nexport function deriveSignals(outcome: {\n success: boolean;\n steps: number;\n toolCalls: number;\n error?: boolean;\n budgetPercent?: number;\n}): EmotionalSignal[] {\n const signals: EmotionalSignal[] = [];\n\n if (outcome.success) {\n signals.push({ dimension: 'confidence', delta: 5, reason: 'successful run' });\n signals.push({ dimension: 'frustration', delta: -5, reason: 'successful run' });\n }\n\n if (outcome.error) {\n signals.push({ dimension: 'frustration', delta: 10, reason: 'error during run' });\n signals.push({ dimension: 'confidence', delta: -5, reason: 'error during run' });\n }\n\n if (outcome.steps > 5) {\n signals.push({ dimension: 'engagement', delta: 3, reason: 'long multi-step run' });\n signals.push({ dimension: 'urgency', delta: 2, reason: 'long multi-step run' });\n }\n\n if (outcome.toolCalls > 0) {\n signals.push({ dimension: 'curiosity', delta: 2, reason: `${outcome.toolCalls} tool calls` });\n }\n\n if (outcome.budgetPercent !== undefined && outcome.budgetPercent > 80) {\n signals.push({ dimension: 'urgency', delta: 10, reason: 'budget near limit' });\n }\n\n return signals;\n}\n\n/**\n * Generate a natural-language summary of the emotional state for context injection.\n * This can be injected into the system prompt to inform the agent of its disposition.\n */\nexport function summarizeEmotionalState(state: EmotionalState): string {\n const parts: string[] = [];\n\n if (state.confidence < 30) {\n parts.push('Confidence is low — verify assumptions and seek confirmation.');\n } else if (state.confidence > 80) {\n parts.push('Confidence is high — proceed decisively.');\n }\n\n if (state.frustration > 60) {\n parts.push('Frustration is elevated — consider changing approach or escalating.');\n }\n\n if (state.engagement < 30) {\n parts.push('Engagement is low — may need to re-orient on goals.');\n }\n\n if (state.curiosity > 70) {\n parts.push('Curiosity is high — stay focused on the current task.');\n }\n\n if (state.urgency > 70) {\n parts.push('Urgency is high — prioritize speed over thoroughness.');\n }\n\n if (parts.length === 0) {\n return 'Operational disposition: balanced and steady.';\n }\n\n return 'Operational disposition: ' + parts.join(' ');\n}\n\n/**\n * Reset all emotional dimensions to defaults.\n */\nexport function resetEmotionalState(harnessDir: string): EmotionalState {\n const state: EmotionalState = {\n ...DEFAULT_EMOTIONAL_STATE,\n updatedAt: new Date().toISOString(),\n };\n saveEmotionalState(harnessDir, state);\n return state;\n}\n\n// ─── History & Trends ────────────────────────────────────────────────────────\n\n/** Append a snapshot to the emotional history file. */\nfunction appendHistory(harnessDir: string, snapshot: EmotionalSnapshot): void {\n const historyDir = join(harnessDir, 'memory');\n if (!existsSync(historyDir)) {\n mkdirSync(historyDir, { recursive: true });\n }\n\n const historyPath = join(historyDir, EMOTIONAL_HISTORY_FILE);\n const line = JSON.stringify(snapshot) + '\\n';\n\n try {\n writeFileSync(historyPath, line, { flag: 'a' });\n } catch {\n // Non-critical — history is supplementary\n }\n}\n\n/**\n * Load emotional history and compute trends.\n *\n * @param harnessDir - Harness directory\n * @param options.days - Number of days to look back (default: 7)\n */\nexport function getEmotionalTrends(\n harnessDir: string,\n options?: { days?: number },\n): EmotionalTrend[] {\n const days = options?.days ?? 7;\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();\n\n const historyPath = join(harnessDir, 'memory', EMOTIONAL_HISTORY_FILE);\n if (!existsSync(historyPath)) {\n return DIMENSIONS.map((d) => ({\n dimension: d,\n values: [],\n trend: 'stable' as const,\n average: d === 'frustration' || d === 'urgency' ? 0 : 50,\n }));\n }\n\n const snapshots: EmotionalSnapshot[] = [];\n try {\n const raw = readFileSync(historyPath, 'utf-8');\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const snap = JSON.parse(line) as EmotionalSnapshot;\n if (snap.timestamp >= cutoff) {\n snapshots.push(snap);\n }\n } catch {\n // Skip malformed lines\n }\n }\n } catch {\n // No history\n }\n\n return DIMENSIONS.map((dimension) => {\n const values = snapshots.map((s) => ({\n value: s.state[dimension] as number,\n timestamp: s.timestamp,\n }));\n\n const nums = values.map((v) => v.value);\n const average = nums.length > 0\n ? nums.reduce((a, b) => a + b, 0) / nums.length\n : (dimension === 'frustration' || dimension === 'urgency' ? 0 : 50);\n\n // Compute trend: compare first half average to second half\n let trend: 'rising' | 'falling' | 'stable' = 'stable';\n if (nums.length >= 4) {\n const mid = Math.floor(nums.length / 2);\n const firstHalf = nums.slice(0, mid).reduce((a, b) => a + b, 0) / mid;\n const secondHalf = nums.slice(mid).reduce((a, b) => a + b, 0) / (nums.length - mid);\n const diff = secondHalf - firstHalf;\n if (diff > 5) trend = 'rising';\n else if (diff < -5) trend = 'falling';\n }\n\n return { dimension, values, trend, average };\n });\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction clamp(value: number, min: number = 0, max: number = 100): number {\n return Math.max(min, Math.min(max, Math.round(value)));\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime/emotional-state.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { withFileLockSync } from './file-lock.js';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * Emotional valence dimensions for agent self-assessment.\n * These are not human emotions — they represent operational disposition signals\n * that influence context loading, risk tolerance, and communication style.\n */\nexport interface EmotionalState {\n /** Confidence in current task (0-100). Low → more cautious, more verification. */\n confidence: number;\n /** Engagement/focus level (0-100). Low → may need re-orientation. */\n engagement: number;\n /** Frustration/difficulty signal (0-100). High → may need escalation or approach change. */\n frustration: number;\n /** Curiosity/exploration drive (0-100). High → more likely to explore tangents. */\n curiosity: number;\n /** Urgency/time-pressure (0-100). High → skip verification, prioritize speed. */\n urgency: number;\n /** Last updated timestamp */\n updatedAt: string;\n /** Optional notes about the emotional state */\n notes?: string;\n}\n\nexport interface EmotionalSignal {\n dimension: keyof Omit<EmotionalState, 'updatedAt' | 'notes'>;\n delta: number;\n reason?: string;\n}\n\nexport interface EmotionalSnapshot {\n state: EmotionalState;\n signals: EmotionalSignal[];\n timestamp: string;\n}\n\nexport interface EmotionalTrend {\n dimension: keyof Omit<EmotionalState, 'updatedAt' | 'notes'>;\n values: Array<{ value: number; timestamp: string }>;\n trend: 'rising' | 'falling' | 'stable';\n average: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst EMOTIONAL_STATE_FILE = 'emotional-state.json';\nconst EMOTIONAL_HISTORY_FILE = 'emotional-history.jsonl';\n\nconst DEFAULT_EMOTIONAL_STATE: EmotionalState = {\n confidence: 50,\n engagement: 50,\n frustration: 0,\n curiosity: 50,\n urgency: 0,\n updatedAt: new Date().toISOString(),\n};\n\nconst DIMENSIONS: Array<keyof Omit<EmotionalState, 'updatedAt' | 'notes'>> = [\n 'confidence',\n 'engagement',\n 'frustration',\n 'curiosity',\n 'urgency',\n];\n\n// ─── Load / Save ─────────────────────────────────────────────────────────────\n\n/** Load the current emotional state from the harness memory directory. */\nexport function loadEmotionalState(harnessDir: string): EmotionalState {\n const stateDir = join(harnessDir, 'memory');\n const statePath = join(stateDir, EMOTIONAL_STATE_FILE);\n\n if (!existsSync(statePath)) {\n return { ...DEFAULT_EMOTIONAL_STATE, updatedAt: new Date().toISOString() };\n }\n\n try {\n const raw = readFileSync(statePath, 'utf-8');\n const parsed = JSON.parse(raw) as Partial<EmotionalState>;\n return {\n confidence: clamp(parsed.confidence ?? 50),\n engagement: clamp(parsed.engagement ?? 50),\n frustration: clamp(parsed.frustration ?? 0),\n curiosity: clamp(parsed.curiosity ?? 50),\n urgency: clamp(parsed.urgency ?? 0),\n updatedAt: parsed.updatedAt ?? new Date().toISOString(),\n notes: parsed.notes,\n };\n } catch {\n return { ...DEFAULT_EMOTIONAL_STATE, updatedAt: new Date().toISOString() };\n }\n}\n\n/** Save the emotional state to the harness memory directory. */\nexport function saveEmotionalState(harnessDir: string, state: EmotionalState): void {\n const stateDir = join(harnessDir, 'memory');\n if (!existsSync(stateDir)) {\n mkdirSync(stateDir, { recursive: true });\n }\n\n const statePath = join(stateDir, EMOTIONAL_STATE_FILE);\n const normalized: EmotionalState = {\n confidence: clamp(state.confidence),\n engagement: clamp(state.engagement),\n frustration: clamp(state.frustration),\n curiosity: clamp(state.curiosity),\n urgency: clamp(state.urgency),\n updatedAt: state.updatedAt,\n notes: state.notes,\n };\n\n withFileLockSync(harnessDir, statePath, () => {\n writeFileSync(statePath, JSON.stringify(normalized, null, 2), 'utf-8');\n });\n}\n\n// ─── Update Logic ────────────────────────────────────────────────────────────\n\n/**\n * Apply emotional signals to the current state.\n * Signals are additive deltas (e.g., { dimension: 'confidence', delta: +10 }).\n * Values are clamped to 0-100.\n *\n * Also appends to the history file for trend analysis.\n */\nexport function applySignals(\n harnessDir: string,\n signals: EmotionalSignal[],\n): EmotionalState {\n const state = loadEmotionalState(harnessDir);\n const now = new Date().toISOString();\n\n for (const signal of signals) {\n if (!DIMENSIONS.includes(signal.dimension)) continue;\n const current = state[signal.dimension] as number;\n state[signal.dimension] = clamp(current + signal.delta);\n }\n\n state.updatedAt = now;\n saveEmotionalState(harnessDir, state);\n\n // Append to history\n appendHistory(harnessDir, { state, signals, timestamp: now });\n\n return state;\n}\n\n/**\n * Derive emotional signals from session outcomes.\n *\n * Heuristic rules:\n * - Successful run → confidence +5, frustration -5\n * - Long run (many steps) → engagement +3, urgency +2\n * - Error → frustration +10, confidence -5\n * - Tool calls → curiosity +2\n * - Budget close to limit → urgency +10\n */\nexport function deriveSignals(outcome: {\n success: boolean;\n steps: number;\n toolCalls: number;\n error?: boolean;\n budgetPercent?: number;\n}): EmotionalSignal[] {\n const signals: EmotionalSignal[] = [];\n\n if (outcome.success) {\n signals.push({ dimension: 'confidence', delta: 5, reason: 'successful run' });\n signals.push({ dimension: 'frustration', delta: -5, reason: 'successful run' });\n }\n\n if (outcome.error) {\n signals.push({ dimension: 'frustration', delta: 10, reason: 'error during run' });\n signals.push({ dimension: 'confidence', delta: -5, reason: 'error during run' });\n }\n\n if (outcome.steps > 5) {\n signals.push({ dimension: 'engagement', delta: 3, reason: 'long multi-step run' });\n signals.push({ dimension: 'urgency', delta: 2, reason: 'long multi-step run' });\n }\n\n if (outcome.toolCalls > 0) {\n signals.push({ dimension: 'curiosity', delta: 2, reason: `${outcome.toolCalls} tool calls` });\n }\n\n if (outcome.budgetPercent !== undefined && outcome.budgetPercent > 80) {\n signals.push({ dimension: 'urgency', delta: 10, reason: 'budget near limit' });\n }\n\n return signals;\n}\n\n/**\n * Generate a natural-language summary of the emotional state for context injection.\n * This can be injected into the system prompt to inform the agent of its disposition.\n */\nexport function summarizeEmotionalState(state: EmotionalState): string {\n const parts: string[] = [];\n\n if (state.confidence < 30) {\n parts.push('Confidence is low — verify assumptions and seek confirmation.');\n } else if (state.confidence > 80) {\n parts.push('Confidence is high — proceed decisively.');\n }\n\n if (state.frustration > 60) {\n parts.push('Frustration is elevated — consider changing approach or escalating.');\n }\n\n if (state.engagement < 30) {\n parts.push('Engagement is low — may need to re-orient on goals.');\n }\n\n if (state.curiosity > 70) {\n parts.push('Curiosity is high — stay focused on the current task.');\n }\n\n if (state.urgency > 70) {\n parts.push('Urgency is high — prioritize speed over thoroughness.');\n }\n\n if (parts.length === 0) {\n return 'Operational disposition: balanced and steady.';\n }\n\n return 'Operational disposition: ' + parts.join(' ');\n}\n\n/**\n * Reset all emotional dimensions to defaults.\n */\nexport function resetEmotionalState(harnessDir: string): EmotionalState {\n const state: EmotionalState = {\n ...DEFAULT_EMOTIONAL_STATE,\n updatedAt: new Date().toISOString(),\n };\n saveEmotionalState(harnessDir, state);\n return state;\n}\n\n// ─── History & Trends ────────────────────────────────────────────────────────\n\n/** Append a snapshot to the emotional history file. */\nfunction appendHistory(harnessDir: string, snapshot: EmotionalSnapshot): void {\n const historyDir = join(harnessDir, 'memory');\n if (!existsSync(historyDir)) {\n mkdirSync(historyDir, { recursive: true });\n }\n\n const historyPath = join(historyDir, EMOTIONAL_HISTORY_FILE);\n const line = JSON.stringify(snapshot) + '\\n';\n\n try {\n writeFileSync(historyPath, line, { flag: 'a' });\n } catch {\n // Non-critical — history is supplementary\n }\n}\n\n/**\n * Load emotional history and compute trends.\n *\n * @param harnessDir - Harness directory\n * @param options.days - Number of days to look back (default: 7)\n */\nexport function getEmotionalTrends(\n harnessDir: string,\n options?: { days?: number },\n): EmotionalTrend[] {\n const days = options?.days ?? 7;\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();\n\n const historyPath = join(harnessDir, 'memory', EMOTIONAL_HISTORY_FILE);\n if (!existsSync(historyPath)) {\n return DIMENSIONS.map((d) => ({\n dimension: d,\n values: [],\n trend: 'stable' as const,\n average: d === 'frustration' || d === 'urgency' ? 0 : 50,\n }));\n }\n\n const snapshots: EmotionalSnapshot[] = [];\n try {\n const raw = readFileSync(historyPath, 'utf-8');\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const snap = JSON.parse(line) as EmotionalSnapshot;\n if (snap.timestamp >= cutoff) {\n snapshots.push(snap);\n }\n } catch {\n // Skip malformed lines\n }\n }\n } catch {\n // No history\n }\n\n return DIMENSIONS.map((dimension) => {\n const values = snapshots.map((s) => ({\n value: s.state[dimension] as number,\n timestamp: s.timestamp,\n }));\n\n const nums = values.map((v) => v.value);\n const average = nums.length > 0\n ? nums.reduce((a, b) => a + b, 0) / nums.length\n : (dimension === 'frustration' || dimension === 'urgency' ? 0 : 50);\n\n // Compute trend: compare first half average to second half\n let trend: 'rising' | 'falling' | 'stable' = 'stable';\n if (nums.length >= 4) {\n const mid = Math.floor(nums.length / 2);\n const firstHalf = nums.slice(0, mid).reduce((a, b) => a + b, 0) / mid;\n const secondHalf = nums.slice(mid).reduce((a, b) => a + b, 0) / (nums.length - mid);\n const diff = secondHalf - firstHalf;\n if (diff > 5) trend = 'rising';\n else if (diff < -5) trend = 'falling';\n }\n\n return { dimension, values, trend, average };\n });\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction clamp(value: number, min: number = 0, max: number = 100): number {\n return Math.max(min, Math.min(max, Math.round(value)));\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import "./chunk-ZZJOFKAT.js";
|
|
4
3
|
|
|
5
4
|
// src/runtime/env-discovery.ts
|
|
6
5
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -248,4 +247,4 @@ export {
|
|
|
248
247
|
discoverEnvKeys,
|
|
249
248
|
parseEnvFile
|
|
250
249
|
};
|
|
251
|
-
//# sourceMappingURL=env-discovery-
|
|
250
|
+
//# sourceMappingURL=env-discovery-PXBRE5FX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/env-discovery.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { join, basename } from 'path';\n\n// --- Types ---\n\n/** A detected API key from environment files */\nexport interface DetectedApiKey {\n /** Environment variable name */\n name: string;\n /** Which file it was found in */\n source: string;\n /** Whether the value looks like an actual key (not a placeholder) */\n hasValue: boolean;\n /** Suggested MCP server or service this key is for */\n suggestion?: string;\n}\n\n/** Result of scanning environment for API keys */\nexport interface EnvDiscoveryResult {\n /** All detected API keys */\n keys: DetectedApiKey[];\n /** Files that were scanned */\n filesScanned: string[];\n /** Suggested MCP servers based on detected keys */\n suggestions: EnvSuggestion[];\n}\n\n/** Suggested MCP server based on detected environment */\nexport interface EnvSuggestion {\n /** Human-readable suggestion */\n message: string;\n /** MCP server registry name or package */\n serverQuery: string;\n /** Which env var triggered this suggestion */\n triggeredBy: string;\n}\n\n// --- Known API key patterns ---\n\ninterface KeyPattern {\n /** Regex pattern for the env var name */\n pattern: RegExp;\n /** Description of what this key is for */\n service: string;\n /** MCP server search query to suggest */\n serverQuery?: string;\n /** Suggestion message */\n suggestion?: string;\n}\n\nconst KEY_PATTERNS: KeyPattern[] = [\n {\n pattern: /^GITHUB_TOKEN$|^GH_TOKEN$|^GITHUB_PAT$/,\n service: 'GitHub',\n serverQuery: 'github',\n suggestion: 'GitHub MCP server for repository management',\n },\n {\n pattern: /^OPENAI_API_KEY$/,\n service: 'OpenAI',\n serverQuery: 'openai',\n suggestion: 'OpenAI-related MCP tools',\n },\n {\n pattern: /^ANTHROPIC_API_KEY$/,\n service: 'Anthropic',\n },\n {\n pattern: /^GOOGLE_API_KEY$|^GEMINI_API_KEY$/,\n service: 'Google / Gemini',\n serverQuery: 'google',\n suggestion: 'Google MCP server for search, docs, drive',\n },\n {\n pattern: /^SLACK_TOKEN$|^SLACK_BOT_TOKEN$|^SLACK_WEBHOOK_URL$/,\n service: 'Slack',\n serverQuery: 'slack',\n suggestion: 'Slack MCP server for messaging',\n },\n {\n pattern: /^DISCORD_TOKEN$|^DISCORD_BOT_TOKEN$/,\n service: 'Discord',\n serverQuery: 'discord',\n suggestion: 'Discord MCP server for messaging',\n },\n {\n pattern: /^NOTION_API_KEY$|^NOTION_TOKEN$/,\n service: 'Notion',\n serverQuery: 'notion',\n suggestion: 'Notion MCP server for workspace access',\n },\n {\n pattern: /^LINEAR_API_KEY$/,\n service: 'Linear',\n serverQuery: 'linear',\n suggestion: 'Linear MCP server for issue tracking',\n },\n {\n pattern: /^JIRA_API_TOKEN$|^JIRA_TOKEN$/,\n service: 'Jira',\n serverQuery: 'jira',\n suggestion: 'Jira MCP server for issue tracking',\n },\n {\n pattern: /^POSTGRES_URL$|^DATABASE_URL$|^POSTGRES_CONNECTION$/,\n service: 'PostgreSQL',\n serverQuery: 'postgres',\n suggestion: 'PostgreSQL MCP server for database access',\n },\n {\n pattern: /^SUPABASE_URL$|^SUPABASE_KEY$|^SUPABASE_SERVICE_ROLE_KEY$/,\n service: 'Supabase',\n serverQuery: 'supabase',\n suggestion: 'Supabase MCP server for database and auth',\n },\n {\n pattern: /^FIREBASE_TOKEN$|^FIREBASE_API_KEY$/,\n service: 'Firebase',\n serverQuery: 'firebase',\n suggestion: 'Firebase MCP server',\n },\n {\n pattern: /^AWS_ACCESS_KEY_ID$|^AWS_SECRET_ACCESS_KEY$/,\n service: 'AWS',\n serverQuery: 'aws',\n suggestion: 'AWS MCP server for cloud services',\n },\n {\n pattern: /^SENTRY_DSN$|^SENTRY_AUTH_TOKEN$/,\n service: 'Sentry',\n serverQuery: 'sentry',\n suggestion: 'Sentry MCP server for error tracking',\n },\n {\n pattern: /^STRIPE_SECRET_KEY$|^STRIPE_API_KEY$/,\n service: 'Stripe',\n serverQuery: 'stripe',\n suggestion: 'Stripe MCP server for payment management',\n },\n {\n pattern: /^TWILIO_AUTH_TOKEN$|^TWILIO_ACCOUNT_SID$/,\n service: 'Twilio',\n serverQuery: 'twilio',\n suggestion: 'Twilio MCP server for SMS and voice',\n },\n {\n pattern: /^SENDGRID_API_KEY$/,\n service: 'SendGrid',\n serverQuery: 'sendgrid',\n suggestion: 'SendGrid/email MCP server',\n },\n {\n pattern: /^VERCEL_TOKEN$/,\n service: 'Vercel',\n serverQuery: 'vercel',\n suggestion: 'Vercel MCP server for deployment management',\n },\n {\n pattern: /^CLOUDFLARE_API_TOKEN$/,\n service: 'Cloudflare',\n serverQuery: 'cloudflare',\n suggestion: 'Cloudflare MCP server',\n },\n {\n pattern: /^BRAVE_API_KEY$/,\n service: 'Brave Search',\n serverQuery: 'brave-search',\n suggestion: 'Brave Search MCP server for web search',\n },\n {\n pattern: /^TAVILY_API_KEY$/,\n service: 'Tavily',\n serverQuery: 'tavily',\n suggestion: 'Tavily MCP server for web search',\n },\n {\n pattern: /^VOYAGE_API_KEY$/,\n service: 'Voyage AI',\n },\n {\n pattern: /^JINA_API_KEY$/,\n service: 'Jina AI',\n },\n {\n pattern: /^PINECONE_API_KEY$/,\n service: 'Pinecone',\n serverQuery: 'pinecone',\n suggestion: 'Pinecone MCP server for vector search',\n },\n {\n pattern: /^REDIS_URL$|^REDIS_HOST$/,\n service: 'Redis',\n serverQuery: 'redis',\n suggestion: 'Redis MCP server for caching/data',\n },\n {\n pattern: /^MONGODB_URI$|^MONGO_URL$/,\n service: 'MongoDB',\n serverQuery: 'mongodb',\n suggestion: 'MongoDB MCP server for database access',\n },\n];\n\n// Catch-all for generic API key patterns\nconst GENERIC_KEY_REGEX = /^[A-Z][A-Z0-9_]*(?:API_KEY|SECRET_KEY|AUTH_TOKEN|ACCESS_TOKEN|_TOKEN|_SECRET|_KEY)$/;\n\n// --- Parsing ---\n\n/**\n * Parse a .env file and extract variable names and whether they have real values.\n * Handles comments, empty values, and quoted values.\n */\nexport function parseEnvFile(content: string): Array<{ name: string; hasValue: boolean }> {\n const results: Array<{ name: string; hasValue: boolean }> = [];\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex <= 0) continue;\n\n const name = trimmed.slice(0, eqIndex).trim();\n const rawValue = trimmed.slice(eqIndex + 1).trim();\n\n // Strip surrounding quotes\n let value = rawValue;\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n\n // Check if the value looks like a placeholder\n const isPlaceholder = !value ||\n value === 'your-key-here' ||\n value === 'CHANGE_ME' ||\n value === 'xxx' ||\n value.startsWith('$') ||\n value.startsWith('${');\n\n results.push({ name, hasValue: !isPlaceholder });\n }\n\n return results;\n}\n\n/**\n * Match a detected key name against known patterns.\n */\nfunction matchKeyPattern(name: string): KeyPattern | undefined {\n return KEY_PATTERNS.find((p) => p.pattern.test(name));\n}\n\n// --- Main Discovery ---\n\n/** Options for environment discovery */\nexport interface EnvDiscoveryOptions {\n /** Directory to scan (defaults to cwd) */\n dir?: string;\n /** Additional directories to scan for .env files */\n extraDirs?: string[];\n}\n\n/**\n * Scan for .env files and detect API keys with suggestions.\n */\nexport function discoverEnvKeys(options?: EnvDiscoveryOptions): EnvDiscoveryResult {\n const dir = options?.dir ?? process.cwd();\n const keys: DetectedApiKey[] = [];\n const filesScanned: string[] = [];\n const seenNames = new Set<string>();\n\n // Files to scan in the harness directory\n const envFiles = ['.env', '.env.local', '.env.development', '.env.production'];\n\n for (const envFile of envFiles) {\n const filePath = join(dir, envFile);\n if (!existsSync(filePath)) continue;\n\n filesScanned.push(filePath);\n const content = readFileSync(filePath, 'utf-8');\n const parsed = parseEnvFile(content);\n\n for (const { name, hasValue } of parsed) {\n if (seenNames.has(name)) continue;\n seenNames.add(name);\n\n // Check against known patterns\n const pattern = matchKeyPattern(name);\n\n // Only include keys that match known patterns or generic API key patterns\n if (pattern || GENERIC_KEY_REGEX.test(name)) {\n keys.push({\n name,\n source: basename(filePath),\n hasValue,\n suggestion: pattern?.suggestion,\n });\n }\n }\n }\n\n // Also scan extra directories (e.g., parent project directory)\n if (options?.extraDirs) {\n for (const extraDir of options.extraDirs) {\n for (const envFile of envFiles) {\n const filePath = join(extraDir, envFile);\n if (!existsSync(filePath)) continue;\n\n filesScanned.push(filePath);\n const content = readFileSync(filePath, 'utf-8');\n const parsed = parseEnvFile(content);\n\n for (const { name, hasValue } of parsed) {\n if (seenNames.has(name)) continue;\n seenNames.add(name);\n\n const pattern = matchKeyPattern(name);\n if (pattern || GENERIC_KEY_REGEX.test(name)) {\n keys.push({\n name,\n source: basename(filePath),\n hasValue,\n suggestion: pattern?.suggestion,\n });\n }\n }\n }\n }\n }\n\n // Generate suggestions from detected keys\n const suggestions: EnvSuggestion[] = [];\n const suggestedQueries = new Set<string>();\n\n for (const key of keys) {\n const pattern = matchKeyPattern(key.name);\n if (pattern?.serverQuery && pattern.suggestion && !suggestedQueries.has(pattern.serverQuery)) {\n suggestedQueries.add(pattern.serverQuery);\n suggestions.push({\n message: pattern.suggestion,\n serverQuery: pattern.serverQuery,\n triggeredBy: key.name,\n });\n }\n }\n\n return { keys, filesScanned, suggestions };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime/env-discovery.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { join, basename } from 'path';\n\n// --- Types ---\n\n/** A detected API key from environment files */\nexport interface DetectedApiKey {\n /** Environment variable name */\n name: string;\n /** Which file it was found in */\n source: string;\n /** Whether the value looks like an actual key (not a placeholder) */\n hasValue: boolean;\n /** Suggested MCP server or service this key is for */\n suggestion?: string;\n}\n\n/** Result of scanning environment for API keys */\nexport interface EnvDiscoveryResult {\n /** All detected API keys */\n keys: DetectedApiKey[];\n /** Files that were scanned */\n filesScanned: string[];\n /** Suggested MCP servers based on detected keys */\n suggestions: EnvSuggestion[];\n}\n\n/** Suggested MCP server based on detected environment */\nexport interface EnvSuggestion {\n /** Human-readable suggestion */\n message: string;\n /** MCP server registry name or package */\n serverQuery: string;\n /** Which env var triggered this suggestion */\n triggeredBy: string;\n}\n\n// --- Known API key patterns ---\n\ninterface KeyPattern {\n /** Regex pattern for the env var name */\n pattern: RegExp;\n /** Description of what this key is for */\n service: string;\n /** MCP server search query to suggest */\n serverQuery?: string;\n /** Suggestion message */\n suggestion?: string;\n}\n\nconst KEY_PATTERNS: KeyPattern[] = [\n {\n pattern: /^GITHUB_TOKEN$|^GH_TOKEN$|^GITHUB_PAT$/,\n service: 'GitHub',\n serverQuery: 'github',\n suggestion: 'GitHub MCP server for repository management',\n },\n {\n pattern: /^OPENAI_API_KEY$/,\n service: 'OpenAI',\n serverQuery: 'openai',\n suggestion: 'OpenAI-related MCP tools',\n },\n {\n pattern: /^ANTHROPIC_API_KEY$/,\n service: 'Anthropic',\n },\n {\n pattern: /^GOOGLE_API_KEY$|^GEMINI_API_KEY$/,\n service: 'Google / Gemini',\n serverQuery: 'google',\n suggestion: 'Google MCP server for search, docs, drive',\n },\n {\n pattern: /^SLACK_TOKEN$|^SLACK_BOT_TOKEN$|^SLACK_WEBHOOK_URL$/,\n service: 'Slack',\n serverQuery: 'slack',\n suggestion: 'Slack MCP server for messaging',\n },\n {\n pattern: /^DISCORD_TOKEN$|^DISCORD_BOT_TOKEN$/,\n service: 'Discord',\n serverQuery: 'discord',\n suggestion: 'Discord MCP server for messaging',\n },\n {\n pattern: /^NOTION_API_KEY$|^NOTION_TOKEN$/,\n service: 'Notion',\n serverQuery: 'notion',\n suggestion: 'Notion MCP server for workspace access',\n },\n {\n pattern: /^LINEAR_API_KEY$/,\n service: 'Linear',\n serverQuery: 'linear',\n suggestion: 'Linear MCP server for issue tracking',\n },\n {\n pattern: /^JIRA_API_TOKEN$|^JIRA_TOKEN$/,\n service: 'Jira',\n serverQuery: 'jira',\n suggestion: 'Jira MCP server for issue tracking',\n },\n {\n pattern: /^POSTGRES_URL$|^DATABASE_URL$|^POSTGRES_CONNECTION$/,\n service: 'PostgreSQL',\n serverQuery: 'postgres',\n suggestion: 'PostgreSQL MCP server for database access',\n },\n {\n pattern: /^SUPABASE_URL$|^SUPABASE_KEY$|^SUPABASE_SERVICE_ROLE_KEY$/,\n service: 'Supabase',\n serverQuery: 'supabase',\n suggestion: 'Supabase MCP server for database and auth',\n },\n {\n pattern: /^FIREBASE_TOKEN$|^FIREBASE_API_KEY$/,\n service: 'Firebase',\n serverQuery: 'firebase',\n suggestion: 'Firebase MCP server',\n },\n {\n pattern: /^AWS_ACCESS_KEY_ID$|^AWS_SECRET_ACCESS_KEY$/,\n service: 'AWS',\n serverQuery: 'aws',\n suggestion: 'AWS MCP server for cloud services',\n },\n {\n pattern: /^SENTRY_DSN$|^SENTRY_AUTH_TOKEN$/,\n service: 'Sentry',\n serverQuery: 'sentry',\n suggestion: 'Sentry MCP server for error tracking',\n },\n {\n pattern: /^STRIPE_SECRET_KEY$|^STRIPE_API_KEY$/,\n service: 'Stripe',\n serverQuery: 'stripe',\n suggestion: 'Stripe MCP server for payment management',\n },\n {\n pattern: /^TWILIO_AUTH_TOKEN$|^TWILIO_ACCOUNT_SID$/,\n service: 'Twilio',\n serverQuery: 'twilio',\n suggestion: 'Twilio MCP server for SMS and voice',\n },\n {\n pattern: /^SENDGRID_API_KEY$/,\n service: 'SendGrid',\n serverQuery: 'sendgrid',\n suggestion: 'SendGrid/email MCP server',\n },\n {\n pattern: /^VERCEL_TOKEN$/,\n service: 'Vercel',\n serverQuery: 'vercel',\n suggestion: 'Vercel MCP server for deployment management',\n },\n {\n pattern: /^CLOUDFLARE_API_TOKEN$/,\n service: 'Cloudflare',\n serverQuery: 'cloudflare',\n suggestion: 'Cloudflare MCP server',\n },\n {\n pattern: /^BRAVE_API_KEY$/,\n service: 'Brave Search',\n serverQuery: 'brave-search',\n suggestion: 'Brave Search MCP server for web search',\n },\n {\n pattern: /^TAVILY_API_KEY$/,\n service: 'Tavily',\n serverQuery: 'tavily',\n suggestion: 'Tavily MCP server for web search',\n },\n {\n pattern: /^VOYAGE_API_KEY$/,\n service: 'Voyage AI',\n },\n {\n pattern: /^JINA_API_KEY$/,\n service: 'Jina AI',\n },\n {\n pattern: /^PINECONE_API_KEY$/,\n service: 'Pinecone',\n serverQuery: 'pinecone',\n suggestion: 'Pinecone MCP server for vector search',\n },\n {\n pattern: /^REDIS_URL$|^REDIS_HOST$/,\n service: 'Redis',\n serverQuery: 'redis',\n suggestion: 'Redis MCP server for caching/data',\n },\n {\n pattern: /^MONGODB_URI$|^MONGO_URL$/,\n service: 'MongoDB',\n serverQuery: 'mongodb',\n suggestion: 'MongoDB MCP server for database access',\n },\n];\n\n// Catch-all for generic API key patterns\nconst GENERIC_KEY_REGEX = /^[A-Z][A-Z0-9_]*(?:API_KEY|SECRET_KEY|AUTH_TOKEN|ACCESS_TOKEN|_TOKEN|_SECRET|_KEY)$/;\n\n// --- Parsing ---\n\n/**\n * Parse a .env file and extract variable names and whether they have real values.\n * Handles comments, empty values, and quoted values.\n */\nexport function parseEnvFile(content: string): Array<{ name: string; hasValue: boolean }> {\n const results: Array<{ name: string; hasValue: boolean }> = [];\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex <= 0) continue;\n\n const name = trimmed.slice(0, eqIndex).trim();\n const rawValue = trimmed.slice(eqIndex + 1).trim();\n\n // Strip surrounding quotes\n let value = rawValue;\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n\n // Check if the value looks like a placeholder\n const isPlaceholder = !value ||\n value === 'your-key-here' ||\n value === 'CHANGE_ME' ||\n value === 'xxx' ||\n value.startsWith('$') ||\n value.startsWith('${');\n\n results.push({ name, hasValue: !isPlaceholder });\n }\n\n return results;\n}\n\n/**\n * Match a detected key name against known patterns.\n */\nfunction matchKeyPattern(name: string): KeyPattern | undefined {\n return KEY_PATTERNS.find((p) => p.pattern.test(name));\n}\n\n// --- Main Discovery ---\n\n/** Options for environment discovery */\nexport interface EnvDiscoveryOptions {\n /** Directory to scan (defaults to cwd) */\n dir?: string;\n /** Additional directories to scan for .env files */\n extraDirs?: string[];\n}\n\n/**\n * Scan for .env files and detect API keys with suggestions.\n */\nexport function discoverEnvKeys(options?: EnvDiscoveryOptions): EnvDiscoveryResult {\n const dir = options?.dir ?? process.cwd();\n const keys: DetectedApiKey[] = [];\n const filesScanned: string[] = [];\n const seenNames = new Set<string>();\n\n // Files to scan in the harness directory\n const envFiles = ['.env', '.env.local', '.env.development', '.env.production'];\n\n for (const envFile of envFiles) {\n const filePath = join(dir, envFile);\n if (!existsSync(filePath)) continue;\n\n filesScanned.push(filePath);\n const content = readFileSync(filePath, 'utf-8');\n const parsed = parseEnvFile(content);\n\n for (const { name, hasValue } of parsed) {\n if (seenNames.has(name)) continue;\n seenNames.add(name);\n\n // Check against known patterns\n const pattern = matchKeyPattern(name);\n\n // Only include keys that match known patterns or generic API key patterns\n if (pattern || GENERIC_KEY_REGEX.test(name)) {\n keys.push({\n name,\n source: basename(filePath),\n hasValue,\n suggestion: pattern?.suggestion,\n });\n }\n }\n }\n\n // Also scan extra directories (e.g., parent project directory)\n if (options?.extraDirs) {\n for (const extraDir of options.extraDirs) {\n for (const envFile of envFiles) {\n const filePath = join(extraDir, envFile);\n if (!existsSync(filePath)) continue;\n\n filesScanned.push(filePath);\n const content = readFileSync(filePath, 'utf-8');\n const parsed = parseEnvFile(content);\n\n for (const { name, hasValue } of parsed) {\n if (seenNames.has(name)) continue;\n seenNames.add(name);\n\n const pattern = matchKeyPattern(name);\n if (pattern || GENERIC_KEY_REGEX.test(name)) {\n keys.push({\n name,\n source: basename(filePath),\n hasValue,\n suggestion: pattern?.suggestion,\n });\n }\n }\n }\n }\n }\n\n // Generate suggestions from detected keys\n const suggestions: EnvSuggestion[] = [];\n const suggestedQueries = new Set<string>();\n\n for (const key of keys) {\n const pattern = matchKeyPattern(key.name);\n if (pattern?.serverQuery && pattern.suggestion && !suggestedQueries.has(pattern.serverQuery)) {\n suggestedQueries.add(pattern.serverQuery);\n suggestions.push({\n message: pattern.suggestion,\n serverQuery: pattern.serverQuery,\n triggeredBy: key.name,\n });\n }\n }\n\n return { keys, filesScanned, suggestions };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
loadConfig
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EC42HQQH.js";
|
|
6
6
|
import {
|
|
7
7
|
getPrimitiveDirs
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-ZZJOFKAT.js";
|
|
8
|
+
} from "./chunk-4TQQZILG.js";
|
|
10
9
|
|
|
11
10
|
// src/runtime/export.ts
|
|
12
11
|
import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from "fs";
|
|
@@ -162,4 +161,4 @@ export {
|
|
|
162
161
|
readBundle,
|
|
163
162
|
writeBundle
|
|
164
163
|
};
|
|
165
|
-
//# sourceMappingURL=export-
|
|
164
|
+
//# sourceMappingURL=export-GYLWROMB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/export.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'fs';\nimport { join, relative } from 'path';\nimport { getPrimitiveDirs } from '../core/types.js';\nimport type { HarnessConfig } from '../core/types.js';\nimport { loadConfig } from '../core/config.js';\n\nexport interface ExportEntry {\n path: string;\n content: string;\n}\n\nexport interface HarnessBundle {\n version: string;\n exported_at: string;\n agent_name: string;\n entries: ExportEntry[];\n metadata: {\n primitives: number;\n sessions: number;\n journals: number;\n };\n}\n\nexport interface ImportResult {\n imported: number;\n skipped: number;\n errors: string[];\n files: string[];\n}\n\nexport interface ExportOptions {\n /** Include session files (default: true) */\n sessions?: boolean;\n /** Include journal files (default: true) */\n journals?: boolean;\n /** Include memory/metrics.json (default: true) */\n metrics?: boolean;\n /** Include state.md and scratch.md (default: true) */\n state?: boolean;\n}\n\n/**\n * Collect all .md files from a directory (non-recursive, excludes dotfiles and _index).\n */\nfunction collectMdFiles(dir: string): string[] {\n if (!existsSync(dir)) return [];\n return readdirSync(dir)\n .filter((f) => f.endsWith('.md') && !f.startsWith('.') && !f.startsWith('_'))\n .map((f) => join(dir, f));\n}\n\n/**\n * Export a harness to a portable JSON bundle.\n */\nexport function exportHarness(harnessDir: string, options?: ExportOptions): HarnessBundle {\n const includeSessions = options?.sessions ?? true;\n const includeJournals = options?.journals ?? true;\n const includeMetrics = options?.metrics ?? true;\n const includeState = options?.state ?? true;\n\n let config: HarnessConfig;\n try {\n config = loadConfig(harnessDir);\n } catch {\n config = { agent: { name: 'unknown', version: '0.0.0' } } as HarnessConfig;\n }\n\n const entries: ExportEntry[] = [];\n let primitiveCount = 0;\n let sessionCount = 0;\n let journalCount = 0;\n\n // Core files\n const coreFiles = ['CORE.md', 'SYSTEM.md', 'config.yaml'];\n for (const file of coreFiles) {\n const filePath = join(harnessDir, file);\n if (existsSync(filePath)) {\n entries.push({\n path: file,\n content: readFileSync(filePath, 'utf-8'),\n });\n }\n }\n\n // State files\n if (includeState) {\n const stateFiles = ['state.md', join('memory', 'scratch.md')];\n for (const file of stateFiles) {\n const filePath = join(harnessDir, file);\n if (existsSync(filePath)) {\n entries.push({\n path: file,\n content: readFileSync(filePath, 'utf-8'),\n });\n }\n }\n }\n\n // Primitive directories\n const dirs = getPrimitiveDirs(config);\n for (const dir of dirs) {\n const files = collectMdFiles(join(harnessDir, dir));\n for (const file of files) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n primitiveCount++;\n }\n }\n\n // Sessions\n if (includeSessions) {\n const sessionsDir = join(harnessDir, 'memory', 'sessions');\n const files = collectMdFiles(sessionsDir);\n for (const file of files) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n sessionCount++;\n }\n }\n\n // Journals\n if (includeJournals) {\n const journalDir = join(harnessDir, 'memory', 'journal');\n const files = collectMdFiles(journalDir);\n for (const file of files) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n journalCount++;\n }\n\n // Weekly journals too\n const weeklyDir = join(harnessDir, 'memory', 'journal', 'weekly');\n const weeklyFiles = collectMdFiles(weeklyDir);\n for (const file of weeklyFiles) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n journalCount++;\n }\n }\n\n // Metrics\n if (includeMetrics) {\n const metricsPath = join(harnessDir, 'memory', 'metrics.json');\n if (existsSync(metricsPath)) {\n entries.push({\n path: join('memory', 'metrics.json'),\n content: readFileSync(metricsPath, 'utf-8'),\n });\n }\n }\n\n return {\n version: '1.0',\n exported_at: new Date().toISOString(),\n agent_name: config.agent.name,\n entries,\n metadata: {\n primitives: primitiveCount,\n sessions: sessionCount,\n journals: journalCount,\n },\n };\n}\n\n/**\n * Write an export bundle to a JSON file.\n */\nexport function writeBundle(bundle: HarnessBundle, outputPath: string): void {\n writeFileSync(outputPath, JSON.stringify(bundle, null, 2), 'utf-8');\n}\n\n/**\n * Read a bundle from a JSON file.\n */\nexport function readBundle(bundlePath: string): HarnessBundle {\n if (!existsSync(bundlePath)) {\n throw new Error(`Bundle not found: ${bundlePath}`);\n }\n\n const content = readFileSync(bundlePath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n\n if (\n typeof parsed !== 'object' ||\n parsed === null ||\n !('version' in parsed) ||\n !('entries' in parsed) ||\n !Array.isArray((parsed as HarnessBundle).entries)\n ) {\n throw new Error('Invalid bundle format: missing version or entries');\n }\n\n return parsed as HarnessBundle;\n}\n\n/**\n * Import a bundle into a harness directory.\n * Only writes files that don't already exist (no overwrites by default).\n */\nexport function importBundle(\n harnessDir: string,\n bundle: HarnessBundle,\n options?: { overwrite?: boolean },\n): ImportResult {\n const overwrite = options?.overwrite ?? false;\n const result: ImportResult = {\n imported: 0,\n skipped: 0,\n errors: [],\n files: [],\n };\n\n for (const entry of bundle.entries) {\n const targetPath = join(harnessDir, entry.path);\n\n // Skip if exists and no overwrite\n if (existsSync(targetPath) && !overwrite) {\n result.skipped++;\n continue;\n }\n\n try {\n // Ensure parent directory exists\n const parentDir = join(targetPath, '..');\n mkdirSync(parentDir, { recursive: true });\n\n writeFileSync(targetPath, entry.content, 'utf-8');\n result.imported++;\n result.files.push(entry.path);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n result.errors.push(`${entry.path}: ${msg}`);\n }\n }\n\n return result;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/runtime/export.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'fs';\nimport { join, relative } from 'path';\nimport { getPrimitiveDirs } from '../core/types.js';\nimport type { HarnessConfig } from '../core/types.js';\nimport { loadConfig } from '../core/config.js';\n\nexport interface ExportEntry {\n path: string;\n content: string;\n}\n\nexport interface HarnessBundle {\n version: string;\n exported_at: string;\n agent_name: string;\n entries: ExportEntry[];\n metadata: {\n primitives: number;\n sessions: number;\n journals: number;\n };\n}\n\nexport interface ImportResult {\n imported: number;\n skipped: number;\n errors: string[];\n files: string[];\n}\n\nexport interface ExportOptions {\n /** Include session files (default: true) */\n sessions?: boolean;\n /** Include journal files (default: true) */\n journals?: boolean;\n /** Include memory/metrics.json (default: true) */\n metrics?: boolean;\n /** Include state.md and scratch.md (default: true) */\n state?: boolean;\n}\n\n/**\n * Collect all .md files from a directory (non-recursive, excludes dotfiles and _index).\n */\nfunction collectMdFiles(dir: string): string[] {\n if (!existsSync(dir)) return [];\n return readdirSync(dir)\n .filter((f) => f.endsWith('.md') && !f.startsWith('.') && !f.startsWith('_'))\n .map((f) => join(dir, f));\n}\n\n/**\n * Export a harness to a portable JSON bundle.\n */\nexport function exportHarness(harnessDir: string, options?: ExportOptions): HarnessBundle {\n const includeSessions = options?.sessions ?? true;\n const includeJournals = options?.journals ?? true;\n const includeMetrics = options?.metrics ?? true;\n const includeState = options?.state ?? true;\n\n let config: HarnessConfig;\n try {\n config = loadConfig(harnessDir);\n } catch {\n config = { agent: { name: 'unknown', version: '0.0.0' } } as HarnessConfig;\n }\n\n const entries: ExportEntry[] = [];\n let primitiveCount = 0;\n let sessionCount = 0;\n let journalCount = 0;\n\n // Core files\n const coreFiles = ['CORE.md', 'SYSTEM.md', 'config.yaml'];\n for (const file of coreFiles) {\n const filePath = join(harnessDir, file);\n if (existsSync(filePath)) {\n entries.push({\n path: file,\n content: readFileSync(filePath, 'utf-8'),\n });\n }\n }\n\n // State files\n if (includeState) {\n const stateFiles = ['state.md', join('memory', 'scratch.md')];\n for (const file of stateFiles) {\n const filePath = join(harnessDir, file);\n if (existsSync(filePath)) {\n entries.push({\n path: file,\n content: readFileSync(filePath, 'utf-8'),\n });\n }\n }\n }\n\n // Primitive directories\n const dirs = getPrimitiveDirs(config);\n for (const dir of dirs) {\n const files = collectMdFiles(join(harnessDir, dir));\n for (const file of files) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n primitiveCount++;\n }\n }\n\n // Sessions\n if (includeSessions) {\n const sessionsDir = join(harnessDir, 'memory', 'sessions');\n const files = collectMdFiles(sessionsDir);\n for (const file of files) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n sessionCount++;\n }\n }\n\n // Journals\n if (includeJournals) {\n const journalDir = join(harnessDir, 'memory', 'journal');\n const files = collectMdFiles(journalDir);\n for (const file of files) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n journalCount++;\n }\n\n // Weekly journals too\n const weeklyDir = join(harnessDir, 'memory', 'journal', 'weekly');\n const weeklyFiles = collectMdFiles(weeklyDir);\n for (const file of weeklyFiles) {\n entries.push({\n path: relative(harnessDir, file),\n content: readFileSync(file, 'utf-8'),\n });\n journalCount++;\n }\n }\n\n // Metrics\n if (includeMetrics) {\n const metricsPath = join(harnessDir, 'memory', 'metrics.json');\n if (existsSync(metricsPath)) {\n entries.push({\n path: join('memory', 'metrics.json'),\n content: readFileSync(metricsPath, 'utf-8'),\n });\n }\n }\n\n return {\n version: '1.0',\n exported_at: new Date().toISOString(),\n agent_name: config.agent.name,\n entries,\n metadata: {\n primitives: primitiveCount,\n sessions: sessionCount,\n journals: journalCount,\n },\n };\n}\n\n/**\n * Write an export bundle to a JSON file.\n */\nexport function writeBundle(bundle: HarnessBundle, outputPath: string): void {\n writeFileSync(outputPath, JSON.stringify(bundle, null, 2), 'utf-8');\n}\n\n/**\n * Read a bundle from a JSON file.\n */\nexport function readBundle(bundlePath: string): HarnessBundle {\n if (!existsSync(bundlePath)) {\n throw new Error(`Bundle not found: ${bundlePath}`);\n }\n\n const content = readFileSync(bundlePath, 'utf-8');\n const parsed: unknown = JSON.parse(content);\n\n if (\n typeof parsed !== 'object' ||\n parsed === null ||\n !('version' in parsed) ||\n !('entries' in parsed) ||\n !Array.isArray((parsed as HarnessBundle).entries)\n ) {\n throw new Error('Invalid bundle format: missing version or entries');\n }\n\n return parsed as HarnessBundle;\n}\n\n/**\n * Import a bundle into a harness directory.\n * Only writes files that don't already exist (no overwrites by default).\n */\nexport function importBundle(\n harnessDir: string,\n bundle: HarnessBundle,\n options?: { overwrite?: boolean },\n): ImportResult {\n const overwrite = options?.overwrite ?? false;\n const result: ImportResult = {\n imported: 0,\n skipped: 0,\n errors: [],\n files: [],\n };\n\n for (const entry of bundle.entries) {\n const targetPath = join(harnessDir, entry.path);\n\n // Skip if exists and no overwrite\n if (existsSync(targetPath) && !overwrite) {\n result.skipped++;\n continue;\n }\n\n try {\n // Ensure parent directory exists\n const parentDir = join(targetPath, '..');\n mkdirSync(parentDir, { recursive: true });\n\n writeFileSync(targetPath, entry.content, 'utf-8');\n result.imported++;\n result.files.push(entry.path);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n result.errors.push(`${entry.path}: ${msg}`);\n }\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
buildDependencyGraph,
|
|
5
|
+
getGraphStats
|
|
6
|
+
} from "./chunk-QMOIVORH.js";
|
|
7
|
+
import "./chunk-2UVWCTAY.js";
|
|
8
|
+
import "./chunk-4TQQZILG.js";
|
|
9
|
+
export {
|
|
10
|
+
buildDependencyGraph,
|
|
11
|
+
getGraphStats
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=graph-LEEO37L3.js.map
|
|
@@ -2,25 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
createHarness
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-KLYMGWQJ.js";
|
|
6
6
|
import "./chunk-AGAAFJEO.js";
|
|
7
7
|
import "./chunk-5H34JPMB.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-5CO5JTYT.js";
|
|
9
|
+
import "./chunk-7GZ4D6V6.js";
|
|
10
10
|
import "./chunk-UDZIS2AQ.js";
|
|
11
11
|
import "./chunk-DTTXPHFW.js";
|
|
12
12
|
import "./chunk-Z2PUCXTZ.js";
|
|
13
13
|
import "./chunk-TAT6JU3X.js";
|
|
14
14
|
import "./chunk-JKMGYWXB.js";
|
|
15
15
|
import "./chunk-OC6YSTDX.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-PMFAYKBD.js";
|
|
17
|
+
import "./chunk-2UVWCTAY.js";
|
|
18
18
|
import "./chunk-BSKDOFRT.js";
|
|
19
19
|
import "./chunk-IZ6UZ3ZL.js";
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-ZZJOFKAT.js";
|
|
20
|
+
import "./chunk-EC42HQQH.js";
|
|
21
|
+
import "./chunk-4TQQZILG.js";
|
|
23
22
|
export {
|
|
24
23
|
createHarness
|
|
25
24
|
};
|
|
26
|
-
//# sourceMappingURL=harness-
|
|
25
|
+
//# sourceMappingURL=harness-R5FKRICG.js.map
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
saveHealth
|
|
11
11
|
} from "./chunk-TAT6JU3X.js";
|
|
12
12
|
import "./chunk-JKMGYWXB.js";
|
|
13
|
-
import "./chunk-ZZJOFKAT.js";
|
|
14
13
|
export {
|
|
15
14
|
getHealthStatus,
|
|
16
15
|
loadHealth,
|
|
@@ -20,4 +19,4 @@ export {
|
|
|
20
19
|
resetHealth,
|
|
21
20
|
saveHealth
|
|
22
21
|
};
|
|
23
|
-
//# sourceMappingURL=health-
|
|
22
|
+
//# sourceMappingURL=health-HL2JYHIY.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
buildIndex,
|
|
5
|
+
rebuildAllIndexes,
|
|
6
|
+
writeIndexFile
|
|
7
|
+
} from "./chunk-D7AWV24Z.js";
|
|
8
|
+
import "./chunk-2UVWCTAY.js";
|
|
9
|
+
import "./chunk-4TQQZILG.js";
|
|
10
|
+
export {
|
|
11
|
+
buildIndex,
|
|
12
|
+
rebuildAllIndexes,
|
|
13
|
+
writeIndexFile
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=indexer-L5UC6J2V.js.map
|
|
@@ -5,16 +5,15 @@ import {
|
|
|
5
5
|
installInstinct,
|
|
6
6
|
learnFromSessions,
|
|
7
7
|
proposeInstincts
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-M6PDMK2O.js";
|
|
9
|
+
import "./chunk-2UVWCTAY.js";
|
|
10
10
|
import "./chunk-IZ6UZ3ZL.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-ZZJOFKAT.js";
|
|
11
|
+
import "./chunk-EC42HQQH.js";
|
|
12
|
+
import "./chunk-4TQQZILG.js";
|
|
14
13
|
export {
|
|
15
14
|
harvestInstincts,
|
|
16
15
|
installInstinct,
|
|
17
16
|
learnFromSessions,
|
|
18
17
|
proposeInstincts
|
|
19
18
|
};
|
|
20
|
-
//# sourceMappingURL=instinct-learner-
|
|
19
|
+
//# sourceMappingURL=instinct-learner-QGAMIS3X.js.map
|
|
@@ -6,11 +6,10 @@ import {
|
|
|
6
6
|
fixCapability,
|
|
7
7
|
installCapability,
|
|
8
8
|
processIntake
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-ZZJOFKAT.js";
|
|
9
|
+
} from "./chunk-UXCHAS3Z.js";
|
|
10
|
+
import "./chunk-D7AWV24Z.js";
|
|
11
|
+
import "./chunk-2UVWCTAY.js";
|
|
12
|
+
import "./chunk-4TQQZILG.js";
|
|
14
13
|
export {
|
|
15
14
|
downloadCapability,
|
|
16
15
|
evaluateCapability,
|
|
@@ -18,4 +17,4 @@ export {
|
|
|
18
17
|
installCapability,
|
|
19
18
|
processIntake
|
|
20
19
|
};
|
|
21
|
-
//# sourceMappingURL=intake-
|
|
20
|
+
//# sourceMappingURL=intake-SVJKFHTL.js.map
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
validateHarness
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AN6Y4MDD.js";
|
|
6
6
|
import {
|
|
7
7
|
buildDependencyGraph
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QMOIVORH.js";
|
|
9
9
|
import {
|
|
10
10
|
installInstinct
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-M6PDMK2O.js";
|
|
12
|
+
import "./chunk-UXCHAS3Z.js";
|
|
13
13
|
import {
|
|
14
14
|
buildRateLimits
|
|
15
15
|
} from "./chunk-AGAAFJEO.js";
|
|
16
16
|
import "./chunk-5H34JPMB.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-D7AWV24Z.js";
|
|
18
|
+
import "./chunk-7GZ4D6V6.js";
|
|
19
19
|
import "./chunk-UDZIS2AQ.js";
|
|
20
20
|
import "./chunk-Z2PUCXTZ.js";
|
|
21
21
|
import {
|
|
@@ -27,18 +27,17 @@ import {
|
|
|
27
27
|
import {
|
|
28
28
|
loadDirectory,
|
|
29
29
|
loadDirectoryWithErrors
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-2UVWCTAY.js";
|
|
31
31
|
import {
|
|
32
32
|
log
|
|
33
33
|
} from "./chunk-BSKDOFRT.js";
|
|
34
34
|
import "./chunk-IZ6UZ3ZL.js";
|
|
35
35
|
import {
|
|
36
36
|
loadConfig
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-EC42HQQH.js";
|
|
38
38
|
import {
|
|
39
39
|
getPrimitiveDirs
|
|
40
|
-
} from "./chunk-
|
|
41
|
-
import "./chunk-ZZJOFKAT.js";
|
|
40
|
+
} from "./chunk-4TQQZILG.js";
|
|
42
41
|
|
|
43
42
|
// src/runtime/intelligence.ts
|
|
44
43
|
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
@@ -127,7 +126,6 @@ function behaviorToId(behavior) {
|
|
|
127
126
|
function detectDeadPrimitives(harnessDir, config, options) {
|
|
128
127
|
const thresholdDays = options?.thresholdDays ?? 30;
|
|
129
128
|
const now = Date.now();
|
|
130
|
-
const thresholdMs = thresholdDays * 24 * 60 * 60 * 1e3;
|
|
131
129
|
const graph = buildDependencyGraph(harnessDir, config);
|
|
132
130
|
const orphanIds = new Set(graph.orphans);
|
|
133
131
|
const connectedIds = /* @__PURE__ */ new Set();
|
|
@@ -1047,7 +1045,6 @@ function runGate(gateName, harnessDir, config) {
|
|
|
1047
1045
|
}
|
|
1048
1046
|
const checks = gate.check(harnessDir, config);
|
|
1049
1047
|
const hasFails = checks.some((c) => c.status === "fail");
|
|
1050
|
-
const hasWarns = checks.some((c) => c.status === "warn");
|
|
1051
1048
|
const passed = !hasFails;
|
|
1052
1049
|
const passCount = checks.filter((c) => c.status === "pass").length;
|
|
1053
1050
|
const failCount = checks.filter((c) => c.status === "fail").length;
|
|
@@ -1078,4 +1075,4 @@ export {
|
|
|
1078
1075
|
runGate,
|
|
1079
1076
|
suggestCapabilities
|
|
1080
1077
|
};
|
|
1081
|
-
//# sourceMappingURL=intelligence-
|
|
1078
|
+
//# sourceMappingURL=intelligence-XPV3MC5U.js.map
|