@agntk/agent-harness 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +41 -0
  3. package/README.md +445 -0
  4. package/defaults/agents/summarizer.md +49 -0
  5. package/defaults/instincts/lead-with-answer.md +24 -0
  6. package/defaults/instincts/qualify-before-recommending.md +40 -0
  7. package/defaults/instincts/read-before-edit.md +23 -0
  8. package/defaults/instincts/search-before-create.md +23 -0
  9. package/defaults/playbooks/ship-feature.md +31 -0
  10. package/defaults/rules/ask-before-assuming.md +35 -0
  11. package/defaults/rules/operations.md +35 -0
  12. package/defaults/rules/respect-the-user.md +39 -0
  13. package/defaults/skills/business-analyst.md +181 -0
  14. package/defaults/skills/content-marketer.md +184 -0
  15. package/defaults/skills/research.md +34 -0
  16. package/defaults/tools/example-web-search.md +60 -0
  17. package/defaults/workflows/daily-reflection.md +54 -0
  18. package/dist/agent-framework-K4GUIICH.js +344 -0
  19. package/dist/agent-framework-K4GUIICH.js.map +1 -0
  20. package/dist/analytics-RPT73WNM.js +12 -0
  21. package/dist/analytics-RPT73WNM.js.map +1 -0
  22. package/dist/auto-processor-OLE45UI3.js +13 -0
  23. package/dist/auto-processor-OLE45UI3.js.map +1 -0
  24. package/dist/chunk-274RV3YO.js +162 -0
  25. package/dist/chunk-274RV3YO.js.map +1 -0
  26. package/dist/chunk-4CWAGBNS.js +168 -0
  27. package/dist/chunk-4CWAGBNS.js.map +1 -0
  28. package/dist/chunk-4FDUOGSZ.js +69 -0
  29. package/dist/chunk-4FDUOGSZ.js.map +1 -0
  30. package/dist/chunk-5H34JPMB.js +199 -0
  31. package/dist/chunk-5H34JPMB.js.map +1 -0
  32. package/dist/chunk-6EMOEYGU.js +102 -0
  33. package/dist/chunk-6EMOEYGU.js.map +1 -0
  34. package/dist/chunk-A7BJPQQ6.js +236 -0
  35. package/dist/chunk-A7BJPQQ6.js.map +1 -0
  36. package/dist/chunk-AGAAFJEO.js +76 -0
  37. package/dist/chunk-AGAAFJEO.js.map +1 -0
  38. package/dist/chunk-BSKDOFRT.js +65 -0
  39. package/dist/chunk-BSKDOFRT.js.map +1 -0
  40. package/dist/chunk-CHJ5GNZC.js +100 -0
  41. package/dist/chunk-CHJ5GNZC.js.map +1 -0
  42. package/dist/chunk-CSL3ERUI.js +307 -0
  43. package/dist/chunk-CSL3ERUI.js.map +1 -0
  44. package/dist/chunk-DA7IKHC4.js +229 -0
  45. package/dist/chunk-DA7IKHC4.js.map +1 -0
  46. package/dist/chunk-DGUM43GV.js +11 -0
  47. package/dist/chunk-DGUM43GV.js.map +1 -0
  48. package/dist/chunk-DTTXPHFW.js +211 -0
  49. package/dist/chunk-DTTXPHFW.js.map +1 -0
  50. package/dist/chunk-FD55B3IO.js +204 -0
  51. package/dist/chunk-FD55B3IO.js.map +1 -0
  52. package/dist/chunk-FLZU44SV.js +230 -0
  53. package/dist/chunk-FLZU44SV.js.map +1 -0
  54. package/dist/chunk-GJNNR2RA.js +200 -0
  55. package/dist/chunk-GJNNR2RA.js.map +1 -0
  56. package/dist/chunk-GNUSHD2Y.js +111 -0
  57. package/dist/chunk-GNUSHD2Y.js.map +1 -0
  58. package/dist/chunk-GUJTBGVS.js +2212 -0
  59. package/dist/chunk-GUJTBGVS.js.map +1 -0
  60. package/dist/chunk-IZ6UZ3ZL.js +207 -0
  61. package/dist/chunk-IZ6UZ3ZL.js.map +1 -0
  62. package/dist/chunk-JKMGYWXB.js +197 -0
  63. package/dist/chunk-JKMGYWXB.js.map +1 -0
  64. package/dist/chunk-KFX54TQM.js +165 -0
  65. package/dist/chunk-KFX54TQM.js.map +1 -0
  66. package/dist/chunk-M7NXUK55.js +199 -0
  67. package/dist/chunk-M7NXUK55.js.map +1 -0
  68. package/dist/chunk-MPZ3BPUI.js +374 -0
  69. package/dist/chunk-MPZ3BPUI.js.map +1 -0
  70. package/dist/chunk-OC6YSTDX.js +119 -0
  71. package/dist/chunk-OC6YSTDX.js.map +1 -0
  72. package/dist/chunk-RC6MEZB6.js +469 -0
  73. package/dist/chunk-RC6MEZB6.js.map +1 -0
  74. package/dist/chunk-RY3ZFII7.js +3440 -0
  75. package/dist/chunk-RY3ZFII7.js.map +1 -0
  76. package/dist/chunk-TAT6JU3X.js +167 -0
  77. package/dist/chunk-TAT6JU3X.js.map +1 -0
  78. package/dist/chunk-UDZIS2AQ.js +79 -0
  79. package/dist/chunk-UDZIS2AQ.js.map +1 -0
  80. package/dist/chunk-UPLBF4RZ.js +115 -0
  81. package/dist/chunk-UPLBF4RZ.js.map +1 -0
  82. package/dist/chunk-UWQTZMNI.js +154 -0
  83. package/dist/chunk-UWQTZMNI.js.map +1 -0
  84. package/dist/chunk-W4T7PGI2.js +346 -0
  85. package/dist/chunk-W4T7PGI2.js.map +1 -0
  86. package/dist/chunk-XTBKL5BI.js +111 -0
  87. package/dist/chunk-XTBKL5BI.js.map +1 -0
  88. package/dist/chunk-YIJY5DBV.js +399 -0
  89. package/dist/chunk-YIJY5DBV.js.map +1 -0
  90. package/dist/chunk-YUFNYN2H.js +242 -0
  91. package/dist/chunk-YUFNYN2H.js.map +1 -0
  92. package/dist/chunk-Z2PUCXTZ.js +94 -0
  93. package/dist/chunk-Z2PUCXTZ.js.map +1 -0
  94. package/dist/chunk-ZZJOFKAT.js +13 -0
  95. package/dist/chunk-ZZJOFKAT.js.map +1 -0
  96. package/dist/cli/index.js +3661 -0
  97. package/dist/cli/index.js.map +1 -0
  98. package/dist/config-WVMRUOCA.js +13 -0
  99. package/dist/config-WVMRUOCA.js.map +1 -0
  100. package/dist/context-loader-3ORBPMHJ.js +13 -0
  101. package/dist/context-loader-3ORBPMHJ.js.map +1 -0
  102. package/dist/conversation-QDEIDQPH.js +22 -0
  103. package/dist/conversation-QDEIDQPH.js.map +1 -0
  104. package/dist/cost-tracker-RS3W7SVY.js +24 -0
  105. package/dist/cost-tracker-RS3W7SVY.js.map +1 -0
  106. package/dist/delegate-VJCJLYEK.js +29 -0
  107. package/dist/delegate-VJCJLYEK.js.map +1 -0
  108. package/dist/emotional-state-VQVRA6ED.js +206 -0
  109. package/dist/emotional-state-VQVRA6ED.js.map +1 -0
  110. package/dist/env-discovery-2BLVMAIM.js +251 -0
  111. package/dist/env-discovery-2BLVMAIM.js.map +1 -0
  112. package/dist/export-6GCYHEHQ.js +165 -0
  113. package/dist/export-6GCYHEHQ.js.map +1 -0
  114. package/dist/graph-YUIPOSOO.js +14 -0
  115. package/dist/graph-YUIPOSOO.js.map +1 -0
  116. package/dist/harness-LCHA3DWP.js +10 -0
  117. package/dist/harness-LCHA3DWP.js.map +1 -0
  118. package/dist/harness-WE4SLCML.js +26 -0
  119. package/dist/harness-WE4SLCML.js.map +1 -0
  120. package/dist/health-NZ6WNIMV.js +23 -0
  121. package/dist/health-NZ6WNIMV.js.map +1 -0
  122. package/dist/index.d.ts +3612 -0
  123. package/dist/index.js +13501 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/indexer-LONANRRM.js +16 -0
  126. package/dist/indexer-LONANRRM.js.map +1 -0
  127. package/dist/instinct-learner-SRM72DHF.js +20 -0
  128. package/dist/instinct-learner-SRM72DHF.js.map +1 -0
  129. package/dist/intake-4M3HNU43.js +21 -0
  130. package/dist/intake-4M3HNU43.js.map +1 -0
  131. package/dist/intelligence-HJOCA4SJ.js +1081 -0
  132. package/dist/intelligence-HJOCA4SJ.js.map +1 -0
  133. package/dist/journal-WANJL3MI.js +24 -0
  134. package/dist/journal-WANJL3MI.js.map +1 -0
  135. package/dist/loader-C3TKIKZR.js +23 -0
  136. package/dist/loader-C3TKIKZR.js.map +1 -0
  137. package/dist/mcp-WTQJJZAO.js +15 -0
  138. package/dist/mcp-WTQJJZAO.js.map +1 -0
  139. package/dist/mcp-discovery-WPAQFL6S.js +377 -0
  140. package/dist/mcp-discovery-WPAQFL6S.js.map +1 -0
  141. package/dist/mcp-installer-6O2XXD3V.js +394 -0
  142. package/dist/mcp-installer-6O2XXD3V.js.map +1 -0
  143. package/dist/metrics-KXGNFAAB.js +20 -0
  144. package/dist/metrics-KXGNFAAB.js.map +1 -0
  145. package/dist/primitive-registry-I6VTIR4W.js +512 -0
  146. package/dist/primitive-registry-I6VTIR4W.js.map +1 -0
  147. package/dist/project-discovery-C4UMD7JI.js +246 -0
  148. package/dist/project-discovery-C4UMD7JI.js.map +1 -0
  149. package/dist/provider-LQHQX7Z7.js +26 -0
  150. package/dist/provider-LQHQX7Z7.js.map +1 -0
  151. package/dist/provider-SXPQZ74H.js +28 -0
  152. package/dist/provider-SXPQZ74H.js.map +1 -0
  153. package/dist/rate-limiter-RLRVM325.js +22 -0
  154. package/dist/rate-limiter-RLRVM325.js.map +1 -0
  155. package/dist/rule-engine-YGQ3RYZM.js +182 -0
  156. package/dist/rule-engine-YGQ3RYZM.js.map +1 -0
  157. package/dist/scaffold-A3VRRCBV.js +347 -0
  158. package/dist/scaffold-A3VRRCBV.js.map +1 -0
  159. package/dist/scheduler-XHHIVHRI.js +397 -0
  160. package/dist/scheduler-XHHIVHRI.js.map +1 -0
  161. package/dist/search-V3W5JMJG.js +75 -0
  162. package/dist/search-V3W5JMJG.js.map +1 -0
  163. package/dist/semantic-search-2DTOO5UX.js +241 -0
  164. package/dist/semantic-search-2DTOO5UX.js.map +1 -0
  165. package/dist/serve-DTQ3HENY.js +291 -0
  166. package/dist/serve-DTQ3HENY.js.map +1 -0
  167. package/dist/sessions-CZGVXKQE.js +21 -0
  168. package/dist/sessions-CZGVXKQE.js.map +1 -0
  169. package/dist/sources-RW5DT56F.js +32 -0
  170. package/dist/sources-RW5DT56F.js.map +1 -0
  171. package/dist/starter-packs-76YUVHEU.js +893 -0
  172. package/dist/starter-packs-76YUVHEU.js.map +1 -0
  173. package/dist/state-GMXILIHW.js +13 -0
  174. package/dist/state-GMXILIHW.js.map +1 -0
  175. package/dist/state-merge-NKO5FRBA.js +174 -0
  176. package/dist/state-merge-NKO5FRBA.js.map +1 -0
  177. package/dist/telemetry-UC6PBXC7.js +22 -0
  178. package/dist/telemetry-UC6PBXC7.js.map +1 -0
  179. package/dist/tool-executor-MJ7IG7PQ.js +28 -0
  180. package/dist/tool-executor-MJ7IG7PQ.js.map +1 -0
  181. package/dist/tools-DZ4KETET.js +20 -0
  182. package/dist/tools-DZ4KETET.js.map +1 -0
  183. package/dist/types-EW7AIB3R.js +18 -0
  184. package/dist/types-EW7AIB3R.js.map +1 -0
  185. package/dist/types-WGDLSPO6.js +16 -0
  186. package/dist/types-WGDLSPO6.js.map +1 -0
  187. package/dist/universal-installer-QGS4SJGX.js +578 -0
  188. package/dist/universal-installer-QGS4SJGX.js.map +1 -0
  189. package/dist/validator-7WXMDIHH.js +22 -0
  190. package/dist/validator-7WXMDIHH.js.map +1 -0
  191. package/dist/verification-gate-FYXUX6LH.js +246 -0
  192. package/dist/verification-gate-FYXUX6LH.js.map +1 -0
  193. package/dist/versioning-Z3XNE2Q2.js +271 -0
  194. package/dist/versioning-Z3XNE2Q2.js.map +1 -0
  195. package/dist/watcher-ISJC7YKL.js +109 -0
  196. package/dist/watcher-ISJC7YKL.js.map +1 -0
  197. package/dist/web-server-DD7ZOP46.js +28 -0
  198. package/dist/web-server-DD7ZOP46.js.map +1 -0
  199. package/package.json +76 -0
  200. package/sources.yaml +121 -0
  201. package/templates/assistant/CORE.md +24 -0
  202. package/templates/assistant/SYSTEM.md +24 -0
  203. package/templates/assistant/config.yaml +51 -0
  204. package/templates/base/CORE.md +17 -0
  205. package/templates/base/SYSTEM.md +24 -0
  206. package/templates/base/config.yaml +51 -0
  207. package/templates/claude-opus/config.yaml +51 -0
  208. package/templates/code-reviewer/CORE.md +25 -0
  209. package/templates/code-reviewer/SYSTEM.md +30 -0
  210. package/templates/code-reviewer/config.yaml +51 -0
  211. package/templates/gpt4/config.yaml +51 -0
  212. package/templates/local/config.yaml +51 -0
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ loadConfig,
5
+ writeDefaultConfig
6
+ } from "./chunk-CHJ5GNZC.js";
7
+ import "./chunk-4CWAGBNS.js";
8
+ import "./chunk-ZZJOFKAT.js";
9
+ export {
10
+ loadConfig,
11
+ writeDefaultConfig
12
+ };
13
+ //# sourceMappingURL=config-WVMRUOCA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ buildSystemPrompt
5
+ } from "./chunk-UWQTZMNI.js";
6
+ import "./chunk-UPLBF4RZ.js";
7
+ import "./chunk-BSKDOFRT.js";
8
+ import "./chunk-4CWAGBNS.js";
9
+ import "./chunk-ZZJOFKAT.js";
10
+ export {
11
+ buildSystemPrompt
12
+ };
13
+ //# sourceMappingURL=context-loader-3ORBPMHJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ Conversation,
5
+ parseJsonlContext,
6
+ parseLegacyContext
7
+ } from "./chunk-MPZ3BPUI.js";
8
+ import "./chunk-UWQTZMNI.js";
9
+ import "./chunk-DTTXPHFW.js";
10
+ import "./chunk-Z2PUCXTZ.js";
11
+ import "./chunk-UPLBF4RZ.js";
12
+ import "./chunk-BSKDOFRT.js";
13
+ import "./chunk-IZ6UZ3ZL.js";
14
+ import "./chunk-CHJ5GNZC.js";
15
+ import "./chunk-4CWAGBNS.js";
16
+ import "./chunk-ZZJOFKAT.js";
17
+ export {
18
+ Conversation,
19
+ parseJsonlContext,
20
+ parseLegacyContext
21
+ };
22
+ //# sourceMappingURL=conversation-QDEIDQPH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ calculateCost,
5
+ checkBudget,
6
+ clearCosts,
7
+ findPricing,
8
+ getSpending,
9
+ loadCosts,
10
+ recordCost,
11
+ saveCosts
12
+ } from "./chunk-JKMGYWXB.js";
13
+ import "./chunk-ZZJOFKAT.js";
14
+ export {
15
+ calculateCost,
16
+ checkBudget,
17
+ clearCosts,
18
+ findPricing,
19
+ getSpending,
20
+ loadCosts,
21
+ recordCost,
22
+ saveCosts
23
+ };
24
+ //# sourceMappingURL=cost-tracker-RS3W7SVY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ buildAgentPrompt,
5
+ delegateStream,
6
+ delegateTo,
7
+ findAgent,
8
+ listAgents,
9
+ loadAgentDocs
10
+ } from "./chunk-YUFNYN2H.js";
11
+ import "./chunk-DA7IKHC4.js";
12
+ import "./chunk-DTTXPHFW.js";
13
+ import "./chunk-Z2PUCXTZ.js";
14
+ import "./chunk-XTBKL5BI.js";
15
+ import "./chunk-UPLBF4RZ.js";
16
+ import "./chunk-BSKDOFRT.js";
17
+ import "./chunk-IZ6UZ3ZL.js";
18
+ import "./chunk-CHJ5GNZC.js";
19
+ import "./chunk-4CWAGBNS.js";
20
+ import "./chunk-ZZJOFKAT.js";
21
+ export {
22
+ buildAgentPrompt,
23
+ delegateStream,
24
+ delegateTo,
25
+ findAgent,
26
+ listAgents,
27
+ loadAgentDocs
28
+ };
29
+ //# sourceMappingURL=delegate-VJCJLYEK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ withFileLockSync
5
+ } from "./chunk-Z2PUCXTZ.js";
6
+ import "./chunk-ZZJOFKAT.js";
7
+
8
+ // src/runtime/emotional-state.ts
9
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
10
+ import { join } from "path";
11
+ var EMOTIONAL_STATE_FILE = "emotional-state.json";
12
+ var EMOTIONAL_HISTORY_FILE = "emotional-history.jsonl";
13
+ var DEFAULT_EMOTIONAL_STATE = {
14
+ confidence: 50,
15
+ engagement: 50,
16
+ frustration: 0,
17
+ curiosity: 50,
18
+ urgency: 0,
19
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
20
+ };
21
+ var DIMENSIONS = [
22
+ "confidence",
23
+ "engagement",
24
+ "frustration",
25
+ "curiosity",
26
+ "urgency"
27
+ ];
28
+ function loadEmotionalState(harnessDir) {
29
+ const stateDir = join(harnessDir, "memory");
30
+ const statePath = join(stateDir, EMOTIONAL_STATE_FILE);
31
+ if (!existsSync(statePath)) {
32
+ return { ...DEFAULT_EMOTIONAL_STATE, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
33
+ }
34
+ try {
35
+ const raw = readFileSync(statePath, "utf-8");
36
+ const parsed = JSON.parse(raw);
37
+ return {
38
+ confidence: clamp(parsed.confidence ?? 50),
39
+ engagement: clamp(parsed.engagement ?? 50),
40
+ frustration: clamp(parsed.frustration ?? 0),
41
+ curiosity: clamp(parsed.curiosity ?? 50),
42
+ urgency: clamp(parsed.urgency ?? 0),
43
+ updatedAt: parsed.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
44
+ notes: parsed.notes
45
+ };
46
+ } catch {
47
+ return { ...DEFAULT_EMOTIONAL_STATE, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
48
+ }
49
+ }
50
+ function saveEmotionalState(harnessDir, state) {
51
+ const stateDir = join(harnessDir, "memory");
52
+ if (!existsSync(stateDir)) {
53
+ mkdirSync(stateDir, { recursive: true });
54
+ }
55
+ const statePath = join(stateDir, EMOTIONAL_STATE_FILE);
56
+ const normalized = {
57
+ confidence: clamp(state.confidence),
58
+ engagement: clamp(state.engagement),
59
+ frustration: clamp(state.frustration),
60
+ curiosity: clamp(state.curiosity),
61
+ urgency: clamp(state.urgency),
62
+ updatedAt: state.updatedAt,
63
+ notes: state.notes
64
+ };
65
+ withFileLockSync(harnessDir, statePath, () => {
66
+ writeFileSync(statePath, JSON.stringify(normalized, null, 2), "utf-8");
67
+ });
68
+ }
69
+ function applySignals(harnessDir, signals) {
70
+ const state = loadEmotionalState(harnessDir);
71
+ const now = (/* @__PURE__ */ new Date()).toISOString();
72
+ for (const signal of signals) {
73
+ if (!DIMENSIONS.includes(signal.dimension)) continue;
74
+ const current = state[signal.dimension];
75
+ state[signal.dimension] = clamp(current + signal.delta);
76
+ }
77
+ state.updatedAt = now;
78
+ saveEmotionalState(harnessDir, state);
79
+ appendHistory(harnessDir, { state, signals, timestamp: now });
80
+ return state;
81
+ }
82
+ function deriveSignals(outcome) {
83
+ const signals = [];
84
+ if (outcome.success) {
85
+ signals.push({ dimension: "confidence", delta: 5, reason: "successful run" });
86
+ signals.push({ dimension: "frustration", delta: -5, reason: "successful run" });
87
+ }
88
+ if (outcome.error) {
89
+ signals.push({ dimension: "frustration", delta: 10, reason: "error during run" });
90
+ signals.push({ dimension: "confidence", delta: -5, reason: "error during run" });
91
+ }
92
+ if (outcome.steps > 5) {
93
+ signals.push({ dimension: "engagement", delta: 3, reason: "long multi-step run" });
94
+ signals.push({ dimension: "urgency", delta: 2, reason: "long multi-step run" });
95
+ }
96
+ if (outcome.toolCalls > 0) {
97
+ signals.push({ dimension: "curiosity", delta: 2, reason: `${outcome.toolCalls} tool calls` });
98
+ }
99
+ if (outcome.budgetPercent !== void 0 && outcome.budgetPercent > 80) {
100
+ signals.push({ dimension: "urgency", delta: 10, reason: "budget near limit" });
101
+ }
102
+ return signals;
103
+ }
104
+ function summarizeEmotionalState(state) {
105
+ const parts = [];
106
+ if (state.confidence < 30) {
107
+ parts.push("Confidence is low \u2014 verify assumptions and seek confirmation.");
108
+ } else if (state.confidence > 80) {
109
+ parts.push("Confidence is high \u2014 proceed decisively.");
110
+ }
111
+ if (state.frustration > 60) {
112
+ parts.push("Frustration is elevated \u2014 consider changing approach or escalating.");
113
+ }
114
+ if (state.engagement < 30) {
115
+ parts.push("Engagement is low \u2014 may need to re-orient on goals.");
116
+ }
117
+ if (state.curiosity > 70) {
118
+ parts.push("Curiosity is high \u2014 stay focused on the current task.");
119
+ }
120
+ if (state.urgency > 70) {
121
+ parts.push("Urgency is high \u2014 prioritize speed over thoroughness.");
122
+ }
123
+ if (parts.length === 0) {
124
+ return "Operational disposition: balanced and steady.";
125
+ }
126
+ return "Operational disposition: " + parts.join(" ");
127
+ }
128
+ function resetEmotionalState(harnessDir) {
129
+ const state = {
130
+ ...DEFAULT_EMOTIONAL_STATE,
131
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
132
+ };
133
+ saveEmotionalState(harnessDir, state);
134
+ return state;
135
+ }
136
+ function appendHistory(harnessDir, snapshot) {
137
+ const historyDir = join(harnessDir, "memory");
138
+ if (!existsSync(historyDir)) {
139
+ mkdirSync(historyDir, { recursive: true });
140
+ }
141
+ const historyPath = join(historyDir, EMOTIONAL_HISTORY_FILE);
142
+ const line = JSON.stringify(snapshot) + "\n";
143
+ try {
144
+ writeFileSync(historyPath, line, { flag: "a" });
145
+ } catch {
146
+ }
147
+ }
148
+ function getEmotionalTrends(harnessDir, options) {
149
+ const days = options?.days ?? 7;
150
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString();
151
+ const historyPath = join(harnessDir, "memory", EMOTIONAL_HISTORY_FILE);
152
+ if (!existsSync(historyPath)) {
153
+ return DIMENSIONS.map((d) => ({
154
+ dimension: d,
155
+ values: [],
156
+ trend: "stable",
157
+ average: d === "frustration" || d === "urgency" ? 0 : 50
158
+ }));
159
+ }
160
+ const snapshots = [];
161
+ try {
162
+ const raw = readFileSync(historyPath, "utf-8");
163
+ for (const line of raw.split("\n")) {
164
+ if (!line.trim()) continue;
165
+ try {
166
+ const snap = JSON.parse(line);
167
+ if (snap.timestamp >= cutoff) {
168
+ snapshots.push(snap);
169
+ }
170
+ } catch {
171
+ }
172
+ }
173
+ } catch {
174
+ }
175
+ return DIMENSIONS.map((dimension) => {
176
+ const values = snapshots.map((s) => ({
177
+ value: s.state[dimension],
178
+ timestamp: s.timestamp
179
+ }));
180
+ const nums = values.map((v) => v.value);
181
+ const average = nums.length > 0 ? nums.reduce((a, b) => a + b, 0) / nums.length : dimension === "frustration" || dimension === "urgency" ? 0 : 50;
182
+ let trend = "stable";
183
+ if (nums.length >= 4) {
184
+ const mid = Math.floor(nums.length / 2);
185
+ const firstHalf = nums.slice(0, mid).reduce((a, b) => a + b, 0) / mid;
186
+ const secondHalf = nums.slice(mid).reduce((a, b) => a + b, 0) / (nums.length - mid);
187
+ const diff = secondHalf - firstHalf;
188
+ if (diff > 5) trend = "rising";
189
+ else if (diff < -5) trend = "falling";
190
+ }
191
+ return { dimension, values, trend, average };
192
+ });
193
+ }
194
+ function clamp(value, min = 0, max = 100) {
195
+ return Math.max(min, Math.min(max, Math.round(value)));
196
+ }
197
+ export {
198
+ applySignals,
199
+ deriveSignals,
200
+ getEmotionalTrends,
201
+ loadEmotionalState,
202
+ resetEmotionalState,
203
+ saveEmotionalState,
204
+ summarizeEmotionalState
205
+ };
206
+ //# sourceMappingURL=emotional-state-VQVRA6ED.js.map
@@ -0,0 +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":[]}
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env node
2
+
3
+ import "./chunk-ZZJOFKAT.js";
4
+
5
+ // src/runtime/env-discovery.ts
6
+ import { existsSync, readFileSync } from "fs";
7
+ import { join, basename } from "path";
8
+ var KEY_PATTERNS = [
9
+ {
10
+ pattern: /^GITHUB_TOKEN$|^GH_TOKEN$|^GITHUB_PAT$/,
11
+ service: "GitHub",
12
+ serverQuery: "github",
13
+ suggestion: "GitHub MCP server for repository management"
14
+ },
15
+ {
16
+ pattern: /^OPENAI_API_KEY$/,
17
+ service: "OpenAI",
18
+ serverQuery: "openai",
19
+ suggestion: "OpenAI-related MCP tools"
20
+ },
21
+ {
22
+ pattern: /^ANTHROPIC_API_KEY$/,
23
+ service: "Anthropic"
24
+ },
25
+ {
26
+ pattern: /^GOOGLE_API_KEY$|^GEMINI_API_KEY$/,
27
+ service: "Google / Gemini",
28
+ serverQuery: "google",
29
+ suggestion: "Google MCP server for search, docs, drive"
30
+ },
31
+ {
32
+ pattern: /^SLACK_TOKEN$|^SLACK_BOT_TOKEN$|^SLACK_WEBHOOK_URL$/,
33
+ service: "Slack",
34
+ serverQuery: "slack",
35
+ suggestion: "Slack MCP server for messaging"
36
+ },
37
+ {
38
+ pattern: /^DISCORD_TOKEN$|^DISCORD_BOT_TOKEN$/,
39
+ service: "Discord",
40
+ serverQuery: "discord",
41
+ suggestion: "Discord MCP server for messaging"
42
+ },
43
+ {
44
+ pattern: /^NOTION_API_KEY$|^NOTION_TOKEN$/,
45
+ service: "Notion",
46
+ serverQuery: "notion",
47
+ suggestion: "Notion MCP server for workspace access"
48
+ },
49
+ {
50
+ pattern: /^LINEAR_API_KEY$/,
51
+ service: "Linear",
52
+ serverQuery: "linear",
53
+ suggestion: "Linear MCP server for issue tracking"
54
+ },
55
+ {
56
+ pattern: /^JIRA_API_TOKEN$|^JIRA_TOKEN$/,
57
+ service: "Jira",
58
+ serverQuery: "jira",
59
+ suggestion: "Jira MCP server for issue tracking"
60
+ },
61
+ {
62
+ pattern: /^POSTGRES_URL$|^DATABASE_URL$|^POSTGRES_CONNECTION$/,
63
+ service: "PostgreSQL",
64
+ serverQuery: "postgres",
65
+ suggestion: "PostgreSQL MCP server for database access"
66
+ },
67
+ {
68
+ pattern: /^SUPABASE_URL$|^SUPABASE_KEY$|^SUPABASE_SERVICE_ROLE_KEY$/,
69
+ service: "Supabase",
70
+ serverQuery: "supabase",
71
+ suggestion: "Supabase MCP server for database and auth"
72
+ },
73
+ {
74
+ pattern: /^FIREBASE_TOKEN$|^FIREBASE_API_KEY$/,
75
+ service: "Firebase",
76
+ serverQuery: "firebase",
77
+ suggestion: "Firebase MCP server"
78
+ },
79
+ {
80
+ pattern: /^AWS_ACCESS_KEY_ID$|^AWS_SECRET_ACCESS_KEY$/,
81
+ service: "AWS",
82
+ serverQuery: "aws",
83
+ suggestion: "AWS MCP server for cloud services"
84
+ },
85
+ {
86
+ pattern: /^SENTRY_DSN$|^SENTRY_AUTH_TOKEN$/,
87
+ service: "Sentry",
88
+ serverQuery: "sentry",
89
+ suggestion: "Sentry MCP server for error tracking"
90
+ },
91
+ {
92
+ pattern: /^STRIPE_SECRET_KEY$|^STRIPE_API_KEY$/,
93
+ service: "Stripe",
94
+ serverQuery: "stripe",
95
+ suggestion: "Stripe MCP server for payment management"
96
+ },
97
+ {
98
+ pattern: /^TWILIO_AUTH_TOKEN$|^TWILIO_ACCOUNT_SID$/,
99
+ service: "Twilio",
100
+ serverQuery: "twilio",
101
+ suggestion: "Twilio MCP server for SMS and voice"
102
+ },
103
+ {
104
+ pattern: /^SENDGRID_API_KEY$/,
105
+ service: "SendGrid",
106
+ serverQuery: "sendgrid",
107
+ suggestion: "SendGrid/email MCP server"
108
+ },
109
+ {
110
+ pattern: /^VERCEL_TOKEN$/,
111
+ service: "Vercel",
112
+ serverQuery: "vercel",
113
+ suggestion: "Vercel MCP server for deployment management"
114
+ },
115
+ {
116
+ pattern: /^CLOUDFLARE_API_TOKEN$/,
117
+ service: "Cloudflare",
118
+ serverQuery: "cloudflare",
119
+ suggestion: "Cloudflare MCP server"
120
+ },
121
+ {
122
+ pattern: /^BRAVE_API_KEY$/,
123
+ service: "Brave Search",
124
+ serverQuery: "brave-search",
125
+ suggestion: "Brave Search MCP server for web search"
126
+ },
127
+ {
128
+ pattern: /^TAVILY_API_KEY$/,
129
+ service: "Tavily",
130
+ serverQuery: "tavily",
131
+ suggestion: "Tavily MCP server for web search"
132
+ },
133
+ {
134
+ pattern: /^VOYAGE_API_KEY$/,
135
+ service: "Voyage AI"
136
+ },
137
+ {
138
+ pattern: /^JINA_API_KEY$/,
139
+ service: "Jina AI"
140
+ },
141
+ {
142
+ pattern: /^PINECONE_API_KEY$/,
143
+ service: "Pinecone",
144
+ serverQuery: "pinecone",
145
+ suggestion: "Pinecone MCP server for vector search"
146
+ },
147
+ {
148
+ pattern: /^REDIS_URL$|^REDIS_HOST$/,
149
+ service: "Redis",
150
+ serverQuery: "redis",
151
+ suggestion: "Redis MCP server for caching/data"
152
+ },
153
+ {
154
+ pattern: /^MONGODB_URI$|^MONGO_URL$/,
155
+ service: "MongoDB",
156
+ serverQuery: "mongodb",
157
+ suggestion: "MongoDB MCP server for database access"
158
+ }
159
+ ];
160
+ var GENERIC_KEY_REGEX = /^[A-Z][A-Z0-9_]*(?:API_KEY|SECRET_KEY|AUTH_TOKEN|ACCESS_TOKEN|_TOKEN|_SECRET|_KEY)$/;
161
+ function parseEnvFile(content) {
162
+ const results = [];
163
+ for (const line of content.split("\n")) {
164
+ const trimmed = line.trim();
165
+ if (!trimmed || trimmed.startsWith("#")) continue;
166
+ const eqIndex = trimmed.indexOf("=");
167
+ if (eqIndex <= 0) continue;
168
+ const name = trimmed.slice(0, eqIndex).trim();
169
+ const rawValue = trimmed.slice(eqIndex + 1).trim();
170
+ let value = rawValue;
171
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
172
+ value = value.slice(1, -1);
173
+ }
174
+ const isPlaceholder = !value || value === "your-key-here" || value === "CHANGE_ME" || value === "xxx" || value.startsWith("$") || value.startsWith("${");
175
+ results.push({ name, hasValue: !isPlaceholder });
176
+ }
177
+ return results;
178
+ }
179
+ function matchKeyPattern(name) {
180
+ return KEY_PATTERNS.find((p) => p.pattern.test(name));
181
+ }
182
+ function discoverEnvKeys(options) {
183
+ const dir = options?.dir ?? process.cwd();
184
+ const keys = [];
185
+ const filesScanned = [];
186
+ const seenNames = /* @__PURE__ */ new Set();
187
+ const envFiles = [".env", ".env.local", ".env.development", ".env.production"];
188
+ for (const envFile of envFiles) {
189
+ const filePath = join(dir, envFile);
190
+ if (!existsSync(filePath)) continue;
191
+ filesScanned.push(filePath);
192
+ const content = readFileSync(filePath, "utf-8");
193
+ const parsed = parseEnvFile(content);
194
+ for (const { name, hasValue } of parsed) {
195
+ if (seenNames.has(name)) continue;
196
+ seenNames.add(name);
197
+ const pattern = matchKeyPattern(name);
198
+ if (pattern || GENERIC_KEY_REGEX.test(name)) {
199
+ keys.push({
200
+ name,
201
+ source: basename(filePath),
202
+ hasValue,
203
+ suggestion: pattern?.suggestion
204
+ });
205
+ }
206
+ }
207
+ }
208
+ if (options?.extraDirs) {
209
+ for (const extraDir of options.extraDirs) {
210
+ for (const envFile of envFiles) {
211
+ const filePath = join(extraDir, envFile);
212
+ if (!existsSync(filePath)) continue;
213
+ filesScanned.push(filePath);
214
+ const content = readFileSync(filePath, "utf-8");
215
+ const parsed = parseEnvFile(content);
216
+ for (const { name, hasValue } of parsed) {
217
+ if (seenNames.has(name)) continue;
218
+ seenNames.add(name);
219
+ const pattern = matchKeyPattern(name);
220
+ if (pattern || GENERIC_KEY_REGEX.test(name)) {
221
+ keys.push({
222
+ name,
223
+ source: basename(filePath),
224
+ hasValue,
225
+ suggestion: pattern?.suggestion
226
+ });
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ const suggestions = [];
233
+ const suggestedQueries = /* @__PURE__ */ new Set();
234
+ for (const key of keys) {
235
+ const pattern = matchKeyPattern(key.name);
236
+ if (pattern?.serverQuery && pattern.suggestion && !suggestedQueries.has(pattern.serverQuery)) {
237
+ suggestedQueries.add(pattern.serverQuery);
238
+ suggestions.push({
239
+ message: pattern.suggestion,
240
+ serverQuery: pattern.serverQuery,
241
+ triggeredBy: key.name
242
+ });
243
+ }
244
+ }
245
+ return { keys, filesScanned, suggestions };
246
+ }
247
+ export {
248
+ discoverEnvKeys,
249
+ parseEnvFile
250
+ };
251
+ //# sourceMappingURL=env-discovery-2BLVMAIM.js.map
@@ -0,0 +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":[]}