@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.
Files changed (178) hide show
  1. package/README.md +104 -43
  2. package/dist/{analytics-RPT73WNM.js → analytics-L24W3B7U.js} +1 -2
  3. package/dist/auto-processor-QIRUOGEI.js +12 -0
  4. package/dist/{chunk-UPLBF4RZ.js → chunk-2UVWCTAY.js} +2 -2
  5. package/dist/{chunk-CSL3ERUI.js → chunk-4P6TRFPZ.js} +3 -3
  6. package/dist/chunk-4P6TRFPZ.js.map +1 -0
  7. package/dist/{chunk-4CWAGBNS.js → chunk-4TQQZILG.js} +73 -3
  8. package/dist/chunk-4TQQZILG.js.map +1 -0
  9. package/dist/{chunk-DA7IKHC4.js → chunk-5CO5JTYT.js} +2 -2
  10. package/dist/chunk-5CO5JTYT.js.map +1 -0
  11. package/dist/{chunk-A7BJPQQ6.js → chunk-5O5OGOOQ.js} +2 -2
  12. package/dist/{chunk-UWQTZMNI.js → chunk-7GZ4D6V6.js} +2 -2
  13. package/dist/{chunk-FLZU44SV.js → chunk-AN6Y4MDD.js} +6 -6
  14. package/dist/{chunk-4FDUOGSZ.js → chunk-D7AWV24Z.js} +3 -3
  15. package/dist/{chunk-CHJ5GNZC.js → chunk-EC42HQQH.js} +2 -2
  16. package/dist/{chunk-YIJY5DBV.js → chunk-KLYMGWQJ.js} +4 -4
  17. package/dist/chunk-KLYMGWQJ.js.map +1 -0
  18. package/dist/{chunk-YUFNYN2H.js → chunk-M62KLIEK.js} +4 -4
  19. package/dist/chunk-M62KLIEK.js.map +1 -0
  20. package/dist/{chunk-GJNNR2RA.js → chunk-M6PDMK2O.js} +3 -3
  21. package/dist/{chunk-M7NXUK55.js → chunk-NVC2WY4K.js} +2 -2
  22. package/dist/{chunk-XTBKL5BI.js → chunk-PMFAYKBD.js} +2 -2
  23. package/dist/chunk-PMFAYKBD.js.map +1 -0
  24. package/dist/{chunk-274RV3YO.js → chunk-QMOIVORH.js} +3 -3
  25. package/dist/chunk-QMOIVORH.js.map +1 -0
  26. package/dist/{chunk-RY3ZFII7.js → chunk-SEHAQTBO.js} +6 -6
  27. package/dist/{chunk-MPZ3BPUI.js → chunk-UMXPOYZR.js} +4 -4
  28. package/dist/{chunk-W4T7PGI2.js → chunk-UXCHAS3Z.js} +4 -4
  29. package/dist/cli/index.js +153 -167
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/config-PYSS3QY6.js +12 -0
  32. package/dist/context-loader-RSXXFW5R.js +12 -0
  33. package/dist/{conversation-QDEIDQPH.js → conversation-TBTFIJVU.js} +6 -7
  34. package/dist/{cost-tracker-RS3W7SVY.js → cost-tracker-NZRZEHVA.js} +1 -2
  35. package/dist/{delegate-VJCJLYEK.js → delegate-3KJAL4NZ.js} +7 -8
  36. package/dist/{emotional-state-VQVRA6ED.js → emotional-state-IN4ZUL2Q.js} +1 -2
  37. package/dist/{emotional-state-VQVRA6ED.js.map → emotional-state-IN4ZUL2Q.js.map} +1 -1
  38. package/dist/{env-discovery-2BLVMAIM.js → env-discovery-PXBRE5FX.js} +1 -2
  39. package/dist/{env-discovery-2BLVMAIM.js.map → env-discovery-PXBRE5FX.js.map} +1 -1
  40. package/dist/{export-6GCYHEHQ.js → export-GYLWROMB.js} +3 -4
  41. package/dist/{export-6GCYHEHQ.js.map → export-GYLWROMB.js.map} +1 -1
  42. package/dist/graph-LEEO37L3.js +13 -0
  43. package/dist/{harness-WE4SLCML.js → harness-R5FKRICG.js} +8 -9
  44. package/dist/{health-NZ6WNIMV.js → health-HL2JYHIY.js} +1 -2
  45. package/dist/indexer-L5UC6J2V.js +15 -0
  46. package/dist/{instinct-learner-SRM72DHF.js → instinct-learner-QGAMIS3X.js} +5 -6
  47. package/dist/{intake-4M3HNU43.js → intake-SVJKFHTL.js} +5 -6
  48. package/dist/{intelligence-HJOCA4SJ.js → intelligence-XPV3MC5U.js} +10 -13
  49. package/dist/intelligence-XPV3MC5U.js.map +1 -0
  50. package/dist/{journal-WANJL3MI.js → journal-ITUMKT6U.js} +5 -6
  51. package/dist/{loader-C3TKIKZR.js → loader-27PLDCOJ.js} +3 -4
  52. package/dist/{mcp-WTQJJZAO.js → mcp-JSIUJJZV.js} +1 -2
  53. package/dist/{mcp-discovery-WPAQFL6S.js → mcp-discovery-DG3RQYLM.js} +1 -2
  54. package/dist/{mcp-discovery-WPAQFL6S.js.map → mcp-discovery-DG3RQYLM.js.map} +1 -1
  55. package/dist/{mcp-installer-6O2XXD3V.js → mcp-installer-X2TJ2S2G.js} +3 -4
  56. package/dist/{mcp-installer-6O2XXD3V.js.map → mcp-installer-X2TJ2S2G.js.map} +1 -1
  57. package/dist/{metrics-KXGNFAAB.js → metrics-2MNINXNQ.js} +1 -2
  58. package/dist/{primitive-registry-I6VTIR4W.js → primitive-registry-ZMGGXSO5.js} +3 -4
  59. package/dist/{primitive-registry-I6VTIR4W.js.map → primitive-registry-ZMGGXSO5.js.map} +1 -1
  60. package/dist/{project-discovery-C4UMD7JI.js → project-discovery-FQLAZKEM.js} +1 -2
  61. package/dist/project-discovery-FQLAZKEM.js.map +1 -0
  62. package/dist/{provider-SXPQZ74H.js → provider-HQY6SPZI.js} +1 -2
  63. package/dist/{rate-limiter-RLRVM325.js → rate-limiter-PH5DCVU4.js} +1 -2
  64. package/dist/{rule-engine-YGQ3RYZM.js → rule-engine-DM26S77N.js} +3 -4
  65. package/dist/{rule-engine-YGQ3RYZM.js.map → rule-engine-DM26S77N.js.map} +1 -1
  66. package/dist/{scaffold-A3VRRCBV.js → scaffold-2F36YVW6.js} +5 -6
  67. package/dist/{scaffold-A3VRRCBV.js.map → scaffold-2F36YVW6.js.map} +1 -1
  68. package/dist/{scheduler-XHHIVHRI.js → scheduler-Q7GB2KCW.js} +11 -12
  69. package/dist/{scheduler-XHHIVHRI.js.map → scheduler-Q7GB2KCW.js.map} +1 -1
  70. package/dist/{search-V3W5JMJG.js → search-6Y6NCOLQ.js} +3 -4
  71. package/dist/search-6Y6NCOLQ.js.map +1 -0
  72. package/dist/{semantic-search-2DTOO5UX.js → semantic-search-FN6FZIXI.js} +3 -4
  73. package/dist/semantic-search-FN6FZIXI.js.map +1 -0
  74. package/dist/{serve-DTQ3HENY.js → serve-MXRTP2HE.js} +10 -11
  75. package/dist/serve-MXRTP2HE.js.map +1 -0
  76. package/dist/{sessions-CZGVXKQE.js → sessions-G6SZZXWS.js} +1 -2
  77. package/dist/{sources-RW5DT56F.js → sources-7LDYO5GK.js} +1 -2
  78. package/dist/{starter-packs-76YUVHEU.js → starter-packs-OR7NI5NA.js} +1 -2
  79. package/dist/{starter-packs-76YUVHEU.js.map → starter-packs-OR7NI5NA.js.map} +1 -1
  80. package/dist/{state-GMXILIHW.js → state-25IQEC5C.js} +1 -2
  81. package/dist/{state-merge-NKO5FRBA.js → state-merge-E333OEIQ.js} +1 -2
  82. package/dist/{state-merge-NKO5FRBA.js.map → state-merge-E333OEIQ.js.map} +1 -1
  83. package/dist/{telemetry-UC6PBXC7.js → telemetry-RS2JZUZP.js} +4 -5
  84. package/dist/{tool-executor-MJ7IG7PQ.js → tool-executor-6I5PHQDY.js} +5 -6
  85. package/dist/{tools-DZ4KETET.js → tools-NDFJNVHK.js} +4 -5
  86. package/dist/{types-EW7AIB3R.js → types-NPJZAI72.js} +2 -3
  87. package/dist/{universal-installer-AAXXYM5A.js → universal-installer-LCAZHFZR.js} +91 -7
  88. package/dist/universal-installer-LCAZHFZR.js.map +1 -0
  89. package/dist/validator-LM7RZWSH.js +21 -0
  90. package/dist/{verification-gate-FYXUX6LH.js → verification-gate-2O6DF2B7.js} +3 -4
  91. package/dist/verification-gate-2O6DF2B7.js.map +1 -0
  92. package/dist/{versioning-Z3XNE2Q2.js → versioning-WEGF6KJG.js} +1 -2
  93. package/dist/versioning-WEGF6KJG.js.map +1 -0
  94. package/dist/{watcher-ISJC7YKL.js → watcher-GZWQSWZ6.js} +5 -6
  95. package/dist/{watcher-ISJC7YKL.js.map → watcher-GZWQSWZ6.js.map} +1 -1
  96. package/dist/{web-server-DD7ZOP46.js → web-server-2Y4CHD2W.js} +8 -9
  97. package/package.json +1 -9
  98. package/dist/agent-framework-K4GUIICH.js +0 -344
  99. package/dist/agent-framework-K4GUIICH.js.map +0 -1
  100. package/dist/auto-processor-OLE45UI3.js +0 -13
  101. package/dist/chunk-274RV3YO.js.map +0 -1
  102. package/dist/chunk-4CWAGBNS.js.map +0 -1
  103. package/dist/chunk-CSL3ERUI.js.map +0 -1
  104. package/dist/chunk-DA7IKHC4.js.map +0 -1
  105. package/dist/chunk-DGUM43GV.js +0 -11
  106. package/dist/chunk-FD55B3IO.js +0 -204
  107. package/dist/chunk-FD55B3IO.js.map +0 -1
  108. package/dist/chunk-GUJTBGVS.js +0 -2212
  109. package/dist/chunk-GUJTBGVS.js.map +0 -1
  110. package/dist/chunk-KFX54TQM.js +0 -165
  111. package/dist/chunk-KFX54TQM.js.map +0 -1
  112. package/dist/chunk-XTBKL5BI.js.map +0 -1
  113. package/dist/chunk-YIJY5DBV.js.map +0 -1
  114. package/dist/chunk-YUFNYN2H.js.map +0 -1
  115. package/dist/chunk-ZZJOFKAT.js +0 -13
  116. package/dist/config-WVMRUOCA.js +0 -13
  117. package/dist/context-loader-3ORBPMHJ.js +0 -13
  118. package/dist/graph-YUIPOSOO.js +0 -14
  119. package/dist/harness-LCHA3DWP.js +0 -10
  120. package/dist/index.d.ts +0 -3612
  121. package/dist/index.js +0 -13713
  122. package/dist/index.js.map +0 -1
  123. package/dist/indexer-LONANRRM.js +0 -16
  124. package/dist/intelligence-HJOCA4SJ.js.map +0 -1
  125. package/dist/project-discovery-C4UMD7JI.js.map +0 -1
  126. package/dist/provider-LQHQX7Z7.js +0 -26
  127. package/dist/search-V3W5JMJG.js.map +0 -1
  128. package/dist/semantic-search-2DTOO5UX.js.map +0 -1
  129. package/dist/serve-DTQ3HENY.js.map +0 -1
  130. package/dist/tools-DZ4KETET.js.map +0 -1
  131. package/dist/types-EW7AIB3R.js.map +0 -1
  132. package/dist/types-WGDLSPO6.js +0 -16
  133. package/dist/types-WGDLSPO6.js.map +0 -1
  134. package/dist/universal-installer-AAXXYM5A.js.map +0 -1
  135. package/dist/validator-7WXMDIHH.js +0 -22
  136. package/dist/validator-7WXMDIHH.js.map +0 -1
  137. package/dist/verification-gate-FYXUX6LH.js.map +0 -1
  138. package/dist/versioning-Z3XNE2Q2.js.map +0 -1
  139. package/dist/web-server-DD7ZOP46.js.map +0 -1
  140. /package/dist/{analytics-RPT73WNM.js.map → analytics-L24W3B7U.js.map} +0 -0
  141. /package/dist/{auto-processor-OLE45UI3.js.map → auto-processor-QIRUOGEI.js.map} +0 -0
  142. /package/dist/{chunk-UPLBF4RZ.js.map → chunk-2UVWCTAY.js.map} +0 -0
  143. /package/dist/{chunk-A7BJPQQ6.js.map → chunk-5O5OGOOQ.js.map} +0 -0
  144. /package/dist/{chunk-UWQTZMNI.js.map → chunk-7GZ4D6V6.js.map} +0 -0
  145. /package/dist/{chunk-FLZU44SV.js.map → chunk-AN6Y4MDD.js.map} +0 -0
  146. /package/dist/{chunk-4FDUOGSZ.js.map → chunk-D7AWV24Z.js.map} +0 -0
  147. /package/dist/{chunk-CHJ5GNZC.js.map → chunk-EC42HQQH.js.map} +0 -0
  148. /package/dist/{chunk-GJNNR2RA.js.map → chunk-M6PDMK2O.js.map} +0 -0
  149. /package/dist/{chunk-M7NXUK55.js.map → chunk-NVC2WY4K.js.map} +0 -0
  150. /package/dist/{chunk-RY3ZFII7.js.map → chunk-SEHAQTBO.js.map} +0 -0
  151. /package/dist/{chunk-MPZ3BPUI.js.map → chunk-UMXPOYZR.js.map} +0 -0
  152. /package/dist/{chunk-W4T7PGI2.js.map → chunk-UXCHAS3Z.js.map} +0 -0
  153. /package/dist/{chunk-DGUM43GV.js.map → config-PYSS3QY6.js.map} +0 -0
  154. /package/dist/{chunk-ZZJOFKAT.js.map → context-loader-RSXXFW5R.js.map} +0 -0
  155. /package/dist/{config-WVMRUOCA.js.map → conversation-TBTFIJVU.js.map} +0 -0
  156. /package/dist/{context-loader-3ORBPMHJ.js.map → cost-tracker-NZRZEHVA.js.map} +0 -0
  157. /package/dist/{conversation-QDEIDQPH.js.map → delegate-3KJAL4NZ.js.map} +0 -0
  158. /package/dist/{cost-tracker-RS3W7SVY.js.map → graph-LEEO37L3.js.map} +0 -0
  159. /package/dist/{delegate-VJCJLYEK.js.map → harness-R5FKRICG.js.map} +0 -0
  160. /package/dist/{graph-YUIPOSOO.js.map → health-HL2JYHIY.js.map} +0 -0
  161. /package/dist/{harness-LCHA3DWP.js.map → indexer-L5UC6J2V.js.map} +0 -0
  162. /package/dist/{harness-WE4SLCML.js.map → instinct-learner-QGAMIS3X.js.map} +0 -0
  163. /package/dist/{health-NZ6WNIMV.js.map → intake-SVJKFHTL.js.map} +0 -0
  164. /package/dist/{indexer-LONANRRM.js.map → journal-ITUMKT6U.js.map} +0 -0
  165. /package/dist/{instinct-learner-SRM72DHF.js.map → loader-27PLDCOJ.js.map} +0 -0
  166. /package/dist/{intake-4M3HNU43.js.map → mcp-JSIUJJZV.js.map} +0 -0
  167. /package/dist/{journal-WANJL3MI.js.map → metrics-2MNINXNQ.js.map} +0 -0
  168. /package/dist/{loader-C3TKIKZR.js.map → provider-HQY6SPZI.js.map} +0 -0
  169. /package/dist/{mcp-WTQJJZAO.js.map → rate-limiter-PH5DCVU4.js.map} +0 -0
  170. /package/dist/{metrics-KXGNFAAB.js.map → sessions-G6SZZXWS.js.map} +0 -0
  171. /package/dist/{provider-LQHQX7Z7.js.map → sources-7LDYO5GK.js.map} +0 -0
  172. /package/dist/{provider-SXPQZ74H.js.map → state-25IQEC5C.js.map} +0 -0
  173. /package/dist/{rate-limiter-RLRVM325.js.map → telemetry-RS2JZUZP.js.map} +0 -0
  174. /package/dist/{sessions-CZGVXKQE.js.map → tool-executor-6I5PHQDY.js.map} +0 -0
  175. /package/dist/{sources-RW5DT56F.js.map → tools-NDFJNVHK.js.map} +0 -0
  176. /package/dist/{state-GMXILIHW.js.map → types-NPJZAI72.js.map} +0 -0
  177. /package/dist/{telemetry-UC6PBXC7.js.map → validator-LM7RZWSH.js.map} +0 -0
  178. /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
+ loadConfig,
5
+ writeDefaultConfig
6
+ } from "./chunk-EC42HQQH.js";
7
+ import "./chunk-4TQQZILG.js";
8
+ export {
9
+ loadConfig,
10
+ writeDefaultConfig
11
+ };
12
+ //# sourceMappingURL=config-PYSS3QY6.js.map
@@ -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-MPZ3BPUI.js";
8
- import "./chunk-UWQTZMNI.js";
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-UPLBF4RZ.js";
11
+ import "./chunk-2UVWCTAY.js";
12
12
  import "./chunk-BSKDOFRT.js";
13
13
  import "./chunk-IZ6UZ3ZL.js";
14
- import "./chunk-CHJ5GNZC.js";
15
- import "./chunk-4CWAGBNS.js";
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-QDEIDQPH.js.map
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-RS3W7SVY.js.map
23
+ //# sourceMappingURL=cost-tracker-NZRZEHVA.js.map
@@ -7,17 +7,16 @@ import {
7
7
  findAgent,
8
8
  listAgents,
9
9
  loadAgentDocs
10
- } from "./chunk-YUFNYN2H.js";
11
- import "./chunk-DA7IKHC4.js";
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-XTBKL5BI.js";
15
- import "./chunk-UPLBF4RZ.js";
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-CHJ5GNZC.js";
19
- import "./chunk-4CWAGBNS.js";
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-VJCJLYEK.js.map
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-VQVRA6ED.js.map
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-2BLVMAIM.js.map
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-CHJ5GNZC.js";
5
+ } from "./chunk-EC42HQQH.js";
6
6
  import {
7
7
  getPrimitiveDirs
8
- } from "./chunk-4CWAGBNS.js";
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-6GCYHEHQ.js.map
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":"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","names":[]}
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-YIJY5DBV.js";
5
+ } from "./chunk-KLYMGWQJ.js";
6
6
  import "./chunk-AGAAFJEO.js";
7
7
  import "./chunk-5H34JPMB.js";
8
- import "./chunk-DA7IKHC4.js";
9
- import "./chunk-UWQTZMNI.js";
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-XTBKL5BI.js";
17
- import "./chunk-UPLBF4RZ.js";
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-CHJ5GNZC.js";
21
- import "./chunk-4CWAGBNS.js";
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-WE4SLCML.js.map
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-NZ6WNIMV.js.map
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-GJNNR2RA.js";
9
- import "./chunk-UPLBF4RZ.js";
8
+ } from "./chunk-M6PDMK2O.js";
9
+ import "./chunk-2UVWCTAY.js";
10
10
  import "./chunk-IZ6UZ3ZL.js";
11
- import "./chunk-CHJ5GNZC.js";
12
- import "./chunk-4CWAGBNS.js";
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-SRM72DHF.js.map
19
+ //# sourceMappingURL=instinct-learner-QGAMIS3X.js.map
@@ -6,11 +6,10 @@ import {
6
6
  fixCapability,
7
7
  installCapability,
8
8
  processIntake
9
- } from "./chunk-W4T7PGI2.js";
10
- import "./chunk-4FDUOGSZ.js";
11
- import "./chunk-UPLBF4RZ.js";
12
- import "./chunk-4CWAGBNS.js";
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-4M3HNU43.js.map
20
+ //# sourceMappingURL=intake-SVJKFHTL.js.map
@@ -2,20 +2,20 @@
2
2
 
3
3
  import {
4
4
  validateHarness
5
- } from "./chunk-FLZU44SV.js";
5
+ } from "./chunk-AN6Y4MDD.js";
6
6
  import {
7
7
  buildDependencyGraph
8
- } from "./chunk-274RV3YO.js";
8
+ } from "./chunk-QMOIVORH.js";
9
9
  import {
10
10
  installInstinct
11
- } from "./chunk-GJNNR2RA.js";
12
- import "./chunk-W4T7PGI2.js";
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-4FDUOGSZ.js";
18
- import "./chunk-UWQTZMNI.js";
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-UPLBF4RZ.js";
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-CHJ5GNZC.js";
37
+ } from "./chunk-EC42HQQH.js";
38
38
  import {
39
39
  getPrimitiveDirs
40
- } from "./chunk-4CWAGBNS.js";
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-HJOCA4SJ.js.map
1078
+ //# sourceMappingURL=intelligence-XPV3MC5U.js.map