pm-orchestrator-runner 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +108 -0
  3. package/dist/cli/cli-interface.d.ts +150 -0
  4. package/dist/cli/cli-interface.d.ts.map +1 -0
  5. package/dist/cli/cli-interface.js +606 -0
  6. package/dist/cli/cli-interface.js.map +1 -0
  7. package/dist/cli/index.d.ts +13 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +243 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/llm-sentinel.d.ts +15 -0
  12. package/dist/cli/llm-sentinel.d.ts.map +1 -0
  13. package/dist/cli/llm-sentinel.js +184 -0
  14. package/dist/cli/llm-sentinel.js.map +1 -0
  15. package/dist/config/configuration-manager.d.ts +149 -0
  16. package/dist/config/configuration-manager.d.ts.map +1 -0
  17. package/dist/config/configuration-manager.js +241 -0
  18. package/dist/config/configuration-manager.js.map +1 -0
  19. package/dist/continuation/continuation-control-manager.d.ts +154 -0
  20. package/dist/continuation/continuation-control-manager.d.ts.map +1 -0
  21. package/dist/continuation/continuation-control-manager.js +303 -0
  22. package/dist/continuation/continuation-control-manager.js.map +1 -0
  23. package/dist/core/runner-core.d.ts +474 -0
  24. package/dist/core/runner-core.d.ts.map +1 -0
  25. package/dist/core/runner-core.js +1311 -0
  26. package/dist/core/runner-core.js.map +1 -0
  27. package/dist/errors/error-codes.d.ts +105 -0
  28. package/dist/errors/error-codes.d.ts.map +1 -0
  29. package/dist/errors/error-codes.js +198 -0
  30. package/dist/errors/error-codes.js.map +1 -0
  31. package/dist/errors/runner-error.d.ts +14 -0
  32. package/dist/errors/runner-error.d.ts.map +1 -0
  33. package/dist/errors/runner-error.js +33 -0
  34. package/dist/errors/runner-error.js.map +1 -0
  35. package/dist/evidence/evidence-manager.d.ts +112 -0
  36. package/dist/evidence/evidence-manager.d.ts.map +1 -0
  37. package/dist/evidence/evidence-manager.js +337 -0
  38. package/dist/evidence/evidence-manager.js.map +1 -0
  39. package/dist/executor/claude-code-executor.d.ts +136 -0
  40. package/dist/executor/claude-code-executor.d.ts.map +1 -0
  41. package/dist/executor/claude-code-executor.js +643 -0
  42. package/dist/executor/claude-code-executor.js.map +1 -0
  43. package/dist/executor/deterministic-executor.d.ts +40 -0
  44. package/dist/executor/deterministic-executor.d.ts.map +1 -0
  45. package/dist/executor/deterministic-executor.js +269 -0
  46. package/dist/executor/deterministic-executor.js.map +1 -0
  47. package/dist/lifecycle/lifecycle-controller.d.ts +270 -0
  48. package/dist/lifecycle/lifecycle-controller.d.ts.map +1 -0
  49. package/dist/lifecycle/lifecycle-controller.js +596 -0
  50. package/dist/lifecycle/lifecycle-controller.js.map +1 -0
  51. package/dist/limits/resource-limit-manager.d.ts +200 -0
  52. package/dist/limits/resource-limit-manager.d.ts.map +1 -0
  53. package/dist/limits/resource-limit-manager.js +376 -0
  54. package/dist/limits/resource-limit-manager.js.map +1 -0
  55. package/dist/locks/lock-manager.d.ts +116 -0
  56. package/dist/locks/lock-manager.d.ts.map +1 -0
  57. package/dist/locks/lock-manager.js +306 -0
  58. package/dist/locks/lock-manager.js.map +1 -0
  59. package/dist/logging/index.d.ts +8 -0
  60. package/dist/logging/index.d.ts.map +1 -0
  61. package/dist/logging/index.js +22 -0
  62. package/dist/logging/index.js.map +1 -0
  63. package/dist/logging/sensitive-data-masker.d.ts +90 -0
  64. package/dist/logging/sensitive-data-masker.d.ts.map +1 -0
  65. package/dist/logging/sensitive-data-masker.js +228 -0
  66. package/dist/logging/sensitive-data-masker.js.map +1 -0
  67. package/dist/logging/task-log-manager.d.ts +215 -0
  68. package/dist/logging/task-log-manager.d.ts.map +1 -0
  69. package/dist/logging/task-log-manager.js +743 -0
  70. package/dist/logging/task-log-manager.js.map +1 -0
  71. package/dist/mediation/fail-closed-runner.d.ts +131 -0
  72. package/dist/mediation/fail-closed-runner.d.ts.map +1 -0
  73. package/dist/mediation/fail-closed-runner.js +245 -0
  74. package/dist/mediation/fail-closed-runner.js.map +1 -0
  75. package/dist/mediation/llm-client-with-evidence.d.ts +123 -0
  76. package/dist/mediation/llm-client-with-evidence.d.ts.map +1 -0
  77. package/dist/mediation/llm-client-with-evidence.js +245 -0
  78. package/dist/mediation/llm-client-with-evidence.js.map +1 -0
  79. package/dist/mediation/llm-client.d.ts +102 -0
  80. package/dist/mediation/llm-client.d.ts.map +1 -0
  81. package/dist/mediation/llm-client.js +206 -0
  82. package/dist/mediation/llm-client.js.map +1 -0
  83. package/dist/mediation/llm-evidence-manager.d.ts +108 -0
  84. package/dist/mediation/llm-evidence-manager.d.ts.map +1 -0
  85. package/dist/mediation/llm-evidence-manager.js +230 -0
  86. package/dist/mediation/llm-evidence-manager.js.map +1 -0
  87. package/dist/mediation/llm-mediation-layer.d.ts +175 -0
  88. package/dist/mediation/llm-mediation-layer.d.ts.map +1 -0
  89. package/dist/mediation/llm-mediation-layer.js +315 -0
  90. package/dist/mediation/llm-mediation-layer.js.map +1 -0
  91. package/dist/mediation/llm-sentinel.d.ts +107 -0
  92. package/dist/mediation/llm-sentinel.d.ts.map +1 -0
  93. package/dist/mediation/llm-sentinel.js +187 -0
  94. package/dist/mediation/llm-sentinel.js.map +1 -0
  95. package/dist/mediation/real-llm-mediation-layer.d.ts +104 -0
  96. package/dist/mediation/real-llm-mediation-layer.d.ts.map +1 -0
  97. package/dist/mediation/real-llm-mediation-layer.js +322 -0
  98. package/dist/mediation/real-llm-mediation-layer.js.map +1 -0
  99. package/dist/mediation/verdict-reporter.d.ts +61 -0
  100. package/dist/mediation/verdict-reporter.d.ts.map +1 -0
  101. package/dist/mediation/verdict-reporter.js +178 -0
  102. package/dist/mediation/verdict-reporter.js.map +1 -0
  103. package/dist/models/enums.d.ts +133 -0
  104. package/dist/models/enums.d.ts.map +1 -0
  105. package/dist/models/enums.js +201 -0
  106. package/dist/models/enums.js.map +1 -0
  107. package/dist/models/evidence.d.ts +60 -0
  108. package/dist/models/evidence.d.ts.map +1 -0
  109. package/dist/models/evidence.js +135 -0
  110. package/dist/models/evidence.js.map +1 -0
  111. package/dist/models/execution-result.d.ts +89 -0
  112. package/dist/models/execution-result.d.ts.map +1 -0
  113. package/dist/models/execution-result.js +197 -0
  114. package/dist/models/execution-result.js.map +1 -0
  115. package/dist/models/file-lock.d.ts +62 -0
  116. package/dist/models/file-lock.d.ts.map +1 -0
  117. package/dist/models/file-lock.js +133 -0
  118. package/dist/models/file-lock.js.map +1 -0
  119. package/dist/models/index.d.ts +12 -0
  120. package/dist/models/index.d.ts.map +1 -0
  121. package/dist/models/index.js +91 -0
  122. package/dist/models/index.js.map +1 -0
  123. package/dist/models/repl/index.d.ts +7 -0
  124. package/dist/models/repl/index.d.ts.map +1 -0
  125. package/dist/models/repl/index.js +32 -0
  126. package/dist/models/repl/index.js.map +1 -0
  127. package/dist/models/repl/model-registry.d.ts +73 -0
  128. package/dist/models/repl/model-registry.d.ts.map +1 -0
  129. package/dist/models/repl/model-registry.js +116 -0
  130. package/dist/models/repl/model-registry.js.map +1 -0
  131. package/dist/models/repl/repl-state.d.ts +86 -0
  132. package/dist/models/repl/repl-state.d.ts.map +1 -0
  133. package/dist/models/repl/repl-state.js +152 -0
  134. package/dist/models/repl/repl-state.js.map +1 -0
  135. package/dist/models/repl/task-log.d.ts +247 -0
  136. package/dist/models/repl/task-log.d.ts.map +1 -0
  137. package/dist/models/repl/task-log.js +178 -0
  138. package/dist/models/repl/task-log.js.map +1 -0
  139. package/dist/models/session.d.ts +71 -0
  140. package/dist/models/session.d.ts.map +1 -0
  141. package/dist/models/session.js +140 -0
  142. package/dist/models/session.js.map +1 -0
  143. package/dist/models/supporting.d.ts +97 -0
  144. package/dist/models/supporting.d.ts.map +1 -0
  145. package/dist/models/supporting.js +208 -0
  146. package/dist/models/supporting.js.map +1 -0
  147. package/dist/models/task.d.ts +77 -0
  148. package/dist/models/task.d.ts.map +1 -0
  149. package/dist/models/task.js +170 -0
  150. package/dist/models/task.js.map +1 -0
  151. package/dist/output/output-control-manager.d.ts +217 -0
  152. package/dist/output/output-control-manager.d.ts.map +1 -0
  153. package/dist/output/output-control-manager.js +378 -0
  154. package/dist/output/output-control-manager.js.map +1 -0
  155. package/dist/pool/agent-pool.d.ts +284 -0
  156. package/dist/pool/agent-pool.d.ts.map +1 -0
  157. package/dist/pool/agent-pool.js +451 -0
  158. package/dist/pool/agent-pool.js.map +1 -0
  159. package/dist/repl/commands/index.d.ts +12 -0
  160. package/dist/repl/commands/index.d.ts.map +1 -0
  161. package/dist/repl/commands/index.js +26 -0
  162. package/dist/repl/commands/index.js.map +1 -0
  163. package/dist/repl/commands/init.d.ts +31 -0
  164. package/dist/repl/commands/init.d.ts.map +1 -0
  165. package/dist/repl/commands/init.js +234 -0
  166. package/dist/repl/commands/init.js.map +1 -0
  167. package/dist/repl/commands/keys.d.ts +63 -0
  168. package/dist/repl/commands/keys.d.ts.map +1 -0
  169. package/dist/repl/commands/keys.js +114 -0
  170. package/dist/repl/commands/keys.js.map +1 -0
  171. package/dist/repl/commands/logs.d.ts +91 -0
  172. package/dist/repl/commands/logs.d.ts.map +1 -0
  173. package/dist/repl/commands/logs.js +200 -0
  174. package/dist/repl/commands/logs.js.map +1 -0
  175. package/dist/repl/commands/model.d.ts +85 -0
  176. package/dist/repl/commands/model.d.ts.map +1 -0
  177. package/dist/repl/commands/model.js +225 -0
  178. package/dist/repl/commands/model.js.map +1 -0
  179. package/dist/repl/commands/models.d.ts +50 -0
  180. package/dist/repl/commands/models.d.ts.map +1 -0
  181. package/dist/repl/commands/models.js +180 -0
  182. package/dist/repl/commands/models.js.map +1 -0
  183. package/dist/repl/commands/provider.d.ts +79 -0
  184. package/dist/repl/commands/provider.d.ts.map +1 -0
  185. package/dist/repl/commands/provider.js +291 -0
  186. package/dist/repl/commands/provider.js.map +1 -0
  187. package/dist/repl/commands/session.d.ts +50 -0
  188. package/dist/repl/commands/session.d.ts.map +1 -0
  189. package/dist/repl/commands/session.js +152 -0
  190. package/dist/repl/commands/session.js.map +1 -0
  191. package/dist/repl/commands/status.d.ts +55 -0
  192. package/dist/repl/commands/status.d.ts.map +1 -0
  193. package/dist/repl/commands/status.js +182 -0
  194. package/dist/repl/commands/status.js.map +1 -0
  195. package/dist/repl/index.d.ts +6 -0
  196. package/dist/repl/index.d.ts.map +1 -0
  197. package/dist/repl/index.js +25 -0
  198. package/dist/repl/index.js.map +1 -0
  199. package/dist/repl/repl-interface.d.ts +371 -0
  200. package/dist/repl/repl-interface.d.ts.map +1 -0
  201. package/dist/repl/repl-interface.js +1214 -0
  202. package/dist/repl/repl-interface.js.map +1 -0
  203. package/dist/session/session-manager.d.ts +85 -0
  204. package/dist/session/session-manager.d.ts.map +1 -0
  205. package/dist/session/session-manager.js +217 -0
  206. package/dist/session/session-manager.js.map +1 -0
  207. package/dist/supervisor/executor-supervisor.d.ts +90 -0
  208. package/dist/supervisor/executor-supervisor.d.ts.map +1 -0
  209. package/dist/supervisor/executor-supervisor.js +223 -0
  210. package/dist/supervisor/executor-supervisor.js.map +1 -0
  211. package/dist/supervisor/index.d.ts +5 -0
  212. package/dist/supervisor/index.d.ts.map +1 -0
  213. package/dist/supervisor/index.js +9 -0
  214. package/dist/supervisor/index.js.map +1 -0
  215. package/package.json +57 -0
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ /**
3
+ * LLM Client with Evidence Recording
4
+ *
5
+ * Extends LLMClient with automatic evidence recording for fail-closed behavior.
6
+ * Every API call generates a proof file that can be verified.
7
+ *
8
+ * ARCHITECTURAL RULES:
9
+ * - Every LLM call MUST generate evidence
10
+ * - COMPLETE status can only be asserted if evidence exists
11
+ * - Double Execution Gate: API key check + Evidence file check
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.LLMClientWithEvidence = void 0;
48
+ exports.createLLMClientWithEvidence = createLLMClientWithEvidence;
49
+ const crypto = __importStar(require("crypto"));
50
+ const llm_client_1 = require("./llm-client");
51
+ const llm_evidence_manager_1 = require("./llm-evidence-manager");
52
+ /**
53
+ * LLM Client with automatic evidence recording
54
+ *
55
+ * Implements Double Execution Gate:
56
+ * - Gate 1: API key validation (fail-closed)
57
+ * - Gate 2: Evidence directory ready (fail-closed)
58
+ *
59
+ * Both gates must pass before any LLM call can be made.
60
+ */
61
+ class LLMClientWithEvidence {
62
+ client;
63
+ evidenceManager;
64
+ provider;
65
+ model;
66
+ gateCheckPerformed = false;
67
+ gateResult = null;
68
+ constructor(config) {
69
+ // Gate 1: API key validation (fail-closed)
70
+ // This will throw APIKeyMissingError if key is not set
71
+ this.client = llm_client_1.LLMClient.fromEnv(config.provider ?? 'openai', config.model, { temperature: config.temperature ?? 0.7 });
72
+ // Gate 2: Evidence directory initialization
73
+ this.evidenceManager = new llm_evidence_manager_1.LLMEvidenceManager(config.evidenceDir);
74
+ this.provider = config.provider ?? 'openai';
75
+ this.model = config.model ?? (config.provider === 'anthropic' ? 'claude-3-haiku-20240307' : 'gpt-4o-mini');
76
+ }
77
+ /**
78
+ * Create client from environment with evidence recording
79
+ * @throws APIKeyMissingError if API key is not set (fail-closed)
80
+ */
81
+ static fromEnv(evidenceDir, provider = 'openai', model, options) {
82
+ return new LLMClientWithEvidence({
83
+ provider,
84
+ model,
85
+ temperature: options?.temperature,
86
+ evidenceDir,
87
+ });
88
+ }
89
+ /**
90
+ * Check Double Execution Gate
91
+ *
92
+ * Gate 1: API key is valid (already checked in constructor)
93
+ * Gate 2: Evidence directory is ready
94
+ *
95
+ * @returns Gate check result
96
+ */
97
+ checkExecutionGate() {
98
+ // Gate 1 passed if we got here (constructor would throw otherwise)
99
+ const gate1Pass = true;
100
+ // Gate 2: Evidence directory ready
101
+ const evidenceDir = this.evidenceManager.getEvidenceDir();
102
+ const gate2Pass = evidenceDir !== null && evidenceDir !== undefined;
103
+ this.gateResult = {
104
+ gate1_api_key: gate1Pass ? 'PASS' : 'FAIL',
105
+ gate2_evidence_ready: gate2Pass ? 'PASS' : 'FAIL',
106
+ can_execute: gate1Pass && gate2Pass,
107
+ failure_reason: !gate1Pass
108
+ ? 'API key not configured'
109
+ : !gate2Pass
110
+ ? 'Evidence directory not ready'
111
+ : undefined,
112
+ };
113
+ this.gateCheckPerformed = true;
114
+ return this.gateResult;
115
+ }
116
+ /**
117
+ * Send chat completion request with automatic evidence recording
118
+ *
119
+ * @throws Error if Double Execution Gate not passed
120
+ */
121
+ async chat(messages) {
122
+ // Enforce Double Execution Gate check
123
+ if (!this.gateCheckPerformed) {
124
+ this.checkExecutionGate();
125
+ }
126
+ if (!this.gateResult?.can_execute) {
127
+ throw new Error(`LLM execution blocked by Double Execution Gate: ${this.gateResult?.failure_reason}`);
128
+ }
129
+ const callId = this.generateCallId();
130
+ const requestHash = (0, llm_evidence_manager_1.hashRequest)(messages);
131
+ const startTime = Date.now();
132
+ try {
133
+ // Make the actual API call
134
+ const response = await this.client.chat(messages);
135
+ const endTime = Date.now();
136
+ // Record success evidence
137
+ const evidence = {
138
+ call_id: callId,
139
+ provider: this.provider,
140
+ model: this.model,
141
+ request_hash: requestHash,
142
+ response_hash: (0, llm_evidence_manager_1.hashResponse)(response.content),
143
+ timestamp: new Date().toISOString(),
144
+ duration_ms: endTime - startTime,
145
+ success: true,
146
+ };
147
+ this.evidenceManager.recordEvidence(evidence);
148
+ return {
149
+ ...response,
150
+ evidence_id: callId,
151
+ };
152
+ }
153
+ catch (error) {
154
+ const endTime = Date.now();
155
+ // Record failure evidence
156
+ const evidence = {
157
+ call_id: callId,
158
+ provider: this.provider,
159
+ model: this.model,
160
+ request_hash: requestHash,
161
+ response_hash: null,
162
+ timestamp: new Date().toISOString(),
163
+ duration_ms: endTime - startTime,
164
+ success: false,
165
+ error: error instanceof Error ? error.message : String(error),
166
+ };
167
+ this.evidenceManager.recordEvidence(evidence);
168
+ // Re-throw the error
169
+ throw error;
170
+ }
171
+ }
172
+ /**
173
+ * Check if COMPLETE status can be asserted
174
+ *
175
+ * This is the fail-closed check:
176
+ * - Returns true only if at least one successful LLM call has evidence
177
+ * - Returns false if no evidence exists or all calls failed
178
+ */
179
+ canAssertComplete() {
180
+ return this.evidenceManager.canAssertComplete();
181
+ }
182
+ /**
183
+ * Get evidence statistics
184
+ */
185
+ getEvidenceStats() {
186
+ return this.evidenceManager.getStats();
187
+ }
188
+ /**
189
+ * Get evidence by call ID
190
+ */
191
+ getEvidence(callId) {
192
+ return this.evidenceManager.getEvidence(callId);
193
+ }
194
+ /**
195
+ * Verify evidence integrity
196
+ */
197
+ verifyEvidence(callId) {
198
+ return this.evidenceManager.verifyIntegrity(callId);
199
+ }
200
+ /**
201
+ * List all evidence
202
+ */
203
+ listEvidence() {
204
+ return this.evidenceManager.listEvidence();
205
+ }
206
+ /**
207
+ * Get the underlying evidence manager
208
+ */
209
+ getEvidenceManager() {
210
+ return this.evidenceManager;
211
+ }
212
+ /**
213
+ * Get the configured provider
214
+ */
215
+ getProvider() {
216
+ return this.provider;
217
+ }
218
+ /**
219
+ * Get the configured model
220
+ */
221
+ getModel() {
222
+ return this.model;
223
+ }
224
+ /**
225
+ * Generate unique call ID
226
+ */
227
+ generateCallId() {
228
+ const timestamp = Date.now().toString(36);
229
+ const random = crypto.randomBytes(4).toString('hex');
230
+ return `llm-${timestamp}-${random}`;
231
+ }
232
+ }
233
+ exports.LLMClientWithEvidence = LLMClientWithEvidence;
234
+ /**
235
+ * Create LLM Client with Evidence (convenience function)
236
+ *
237
+ * @param evidenceDir - Directory to store evidence files
238
+ * @param provider - LLM provider (default: openai)
239
+ * @param model - Model name (optional)
240
+ * @throws APIKeyMissingError if API key is not configured
241
+ */
242
+ function createLLMClientWithEvidence(evidenceDir, provider = 'openai', model) {
243
+ return LLMClientWithEvidence.fromEnv(evidenceDir, provider, model);
244
+ }
245
+ //# sourceMappingURL=llm-client-with-evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-client-with-evidence.js","sourceRoot":"","sources":["../../src/mediation/llm-client-with-evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * LLM Client - Real API calls to LLM providers
3
+ *
4
+ * REQUIREMENTS:
5
+ * - NO stubs, mocks, or fixed responses
6
+ * - temperature > 0 required (non-deterministic output)
7
+ * - API key from environment variables only
8
+ * - fail-closed on missing API key
9
+ */
10
+ /**
11
+ * LLM Provider types
12
+ */
13
+ export type LLMProvider = 'openai' | 'anthropic';
14
+ /**
15
+ * LLM Client configuration
16
+ */
17
+ export interface LLMClientConfig {
18
+ provider: LLMProvider;
19
+ model: string;
20
+ apiKey: string;
21
+ temperature?: number;
22
+ maxTokens?: number;
23
+ baseUrl?: string;
24
+ }
25
+ /**
26
+ * Chat message format
27
+ */
28
+ export interface ChatMessage {
29
+ role: 'system' | 'user' | 'assistant';
30
+ content: string;
31
+ }
32
+ /**
33
+ * LLM response
34
+ */
35
+ export interface LLMResponse {
36
+ content: string;
37
+ model: string;
38
+ usage?: {
39
+ prompt_tokens: number;
40
+ completion_tokens: number;
41
+ total_tokens: number;
42
+ };
43
+ }
44
+ /**
45
+ * Error thrown when API key is missing (fail-closed)
46
+ */
47
+ export declare class APIKeyMissingError extends Error {
48
+ constructor(provider: LLMProvider);
49
+ }
50
+ /**
51
+ * Error thrown when LLM API call fails
52
+ */
53
+ export declare class LLMAPIError extends Error {
54
+ readonly provider: LLMProvider;
55
+ readonly statusCode: number;
56
+ readonly responseBody: string;
57
+ constructor(provider: LLMProvider, statusCode: number, responseBody: string);
58
+ }
59
+ /**
60
+ * Get API key from environment variable
61
+ * @throws APIKeyMissingError if key is not set (fail-closed)
62
+ */
63
+ export declare function getAPIKeyFromEnv(provider: LLMProvider): string;
64
+ /**
65
+ * LLM Client class - Makes real API calls to LLM providers
66
+ *
67
+ * IMPORTANT: This class NEVER uses stubs or mocks.
68
+ * All calls go to the real LLM API.
69
+ */
70
+ export declare class LLMClient {
71
+ private readonly config;
72
+ constructor(config: LLMClientConfig);
73
+ /**
74
+ * Create LLM client from environment variables
75
+ * @throws APIKeyMissingError if API key is not set (fail-closed)
76
+ */
77
+ static fromEnv(provider?: LLMProvider, model?: string, options?: {
78
+ temperature?: number;
79
+ maxTokens?: number;
80
+ }): LLMClient;
81
+ /**
82
+ * Send chat completion request to LLM
83
+ */
84
+ chat(messages: ChatMessage[]): Promise<LLMResponse>;
85
+ /**
86
+ * OpenAI API call
87
+ */
88
+ private chatOpenAI;
89
+ /**
90
+ * Anthropic API call
91
+ */
92
+ private chatAnthropic;
93
+ /**
94
+ * Get the configured model name
95
+ */
96
+ getModel(): string;
97
+ /**
98
+ * Get the configured provider
99
+ */
100
+ getProvider(): LLMProvider;
101
+ }
102
+ //# sourceMappingURL=llm-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../../src/mediation/llm-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,WAAW;CAIlC;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;aAElB,QAAQ,EAAE,WAAW;aACrB,UAAU,EAAE,MAAM;aAClB,YAAY,EAAE,MAAM;gBAFpB,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM;CAKvC;AAcD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAS9D;AAgBD;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;gBAEvC,MAAM,EAAE,eAAe;IAiBnC;;;OAGG;IACH,MAAM,CAAC,OAAO,CACZ,QAAQ,GAAE,WAAsB,EAChC,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GACrD,SAAS;IAWZ;;OAEG;IACG,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IASzD;;OAEG;YACW,UAAU;IAiCxB;;OAEG;YACW,aAAa;IA8C3B;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,WAAW,IAAI,WAAW;CAG3B"}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ /**
3
+ * LLM Client - Real API calls to LLM providers
4
+ *
5
+ * REQUIREMENTS:
6
+ * - NO stubs, mocks, or fixed responses
7
+ * - temperature > 0 required (non-deterministic output)
8
+ * - API key from environment variables only
9
+ * - fail-closed on missing API key
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.LLMClient = exports.LLMAPIError = exports.APIKeyMissingError = void 0;
13
+ exports.getAPIKeyFromEnv = getAPIKeyFromEnv;
14
+ /**
15
+ * Error thrown when API key is missing (fail-closed)
16
+ */
17
+ class APIKeyMissingError extends Error {
18
+ constructor(provider) {
19
+ super(`API key not found for provider: ${provider}. Set ${getEnvVarName(provider)} environment variable.`);
20
+ this.name = 'APIKeyMissingError';
21
+ }
22
+ }
23
+ exports.APIKeyMissingError = APIKeyMissingError;
24
+ /**
25
+ * Error thrown when LLM API call fails
26
+ */
27
+ class LLMAPIError extends Error {
28
+ provider;
29
+ statusCode;
30
+ responseBody;
31
+ constructor(provider, statusCode, responseBody) {
32
+ super(`LLM API error (${provider}): ${statusCode} - ${responseBody}`);
33
+ this.provider = provider;
34
+ this.statusCode = statusCode;
35
+ this.responseBody = responseBody;
36
+ this.name = 'LLMAPIError';
37
+ }
38
+ }
39
+ exports.LLMAPIError = LLMAPIError;
40
+ /**
41
+ * Get environment variable name for API key
42
+ */
43
+ function getEnvVarName(provider) {
44
+ switch (provider) {
45
+ case 'openai':
46
+ return 'OPENAI_API_KEY';
47
+ case 'anthropic':
48
+ return 'ANTHROPIC_API_KEY';
49
+ }
50
+ }
51
+ /**
52
+ * Get API key from environment variable
53
+ * @throws APIKeyMissingError if key is not set (fail-closed)
54
+ */
55
+ function getAPIKeyFromEnv(provider) {
56
+ const envVar = getEnvVarName(provider);
57
+ const apiKey = process.env[envVar];
58
+ if (!apiKey || apiKey.trim() === '') {
59
+ throw new APIKeyMissingError(provider);
60
+ }
61
+ return apiKey.trim();
62
+ }
63
+ /**
64
+ * Default configuration for providers
65
+ */
66
+ const DEFAULT_CONFIGS = {
67
+ openai: {
68
+ baseUrl: 'https://api.openai.com/v1',
69
+ defaultModel: 'gpt-4o-mini',
70
+ },
71
+ anthropic: {
72
+ baseUrl: 'https://api.anthropic.com/v1',
73
+ defaultModel: 'claude-3-haiku-20240307',
74
+ },
75
+ };
76
+ /**
77
+ * LLM Client class - Makes real API calls to LLM providers
78
+ *
79
+ * IMPORTANT: This class NEVER uses stubs or mocks.
80
+ * All calls go to the real LLM API.
81
+ */
82
+ class LLMClient {
83
+ config;
84
+ constructor(config) {
85
+ // Validate temperature > 0 (required for non-determinism)
86
+ const temperature = config.temperature ?? 0.7;
87
+ if (temperature <= 0) {
88
+ throw new Error('temperature must be > 0 to ensure non-deterministic output');
89
+ }
90
+ this.config = {
91
+ provider: config.provider,
92
+ model: config.model,
93
+ apiKey: config.apiKey,
94
+ temperature,
95
+ maxTokens: config.maxTokens ?? 1024,
96
+ baseUrl: config.baseUrl ?? DEFAULT_CONFIGS[config.provider].baseUrl,
97
+ };
98
+ }
99
+ /**
100
+ * Create LLM client from environment variables
101
+ * @throws APIKeyMissingError if API key is not set (fail-closed)
102
+ */
103
+ static fromEnv(provider = 'openai', model, options) {
104
+ const apiKey = getAPIKeyFromEnv(provider);
105
+ return new LLMClient({
106
+ provider,
107
+ model: model ?? DEFAULT_CONFIGS[provider].defaultModel,
108
+ apiKey,
109
+ temperature: options?.temperature ?? 0.7,
110
+ maxTokens: options?.maxTokens ?? 1024,
111
+ });
112
+ }
113
+ /**
114
+ * Send chat completion request to LLM
115
+ */
116
+ async chat(messages) {
117
+ switch (this.config.provider) {
118
+ case 'openai':
119
+ return this.chatOpenAI(messages);
120
+ case 'anthropic':
121
+ return this.chatAnthropic(messages);
122
+ }
123
+ }
124
+ /**
125
+ * OpenAI API call
126
+ */
127
+ async chatOpenAI(messages) {
128
+ const response = await fetch(`${this.config.baseUrl}/chat/completions`, {
129
+ method: 'POST',
130
+ headers: {
131
+ 'Content-Type': 'application/json',
132
+ 'Authorization': `Bearer ${this.config.apiKey}`,
133
+ },
134
+ body: JSON.stringify({
135
+ model: this.config.model,
136
+ messages,
137
+ temperature: this.config.temperature,
138
+ max_tokens: this.config.maxTokens,
139
+ }),
140
+ });
141
+ if (!response.ok) {
142
+ const body = await response.text();
143
+ throw new LLMAPIError('openai', response.status, body);
144
+ }
145
+ const data = await response.json();
146
+ return {
147
+ content: data.choices[0]?.message?.content ?? '',
148
+ model: data.model,
149
+ usage: data.usage,
150
+ };
151
+ }
152
+ /**
153
+ * Anthropic API call
154
+ */
155
+ async chatAnthropic(messages) {
156
+ // Extract system message if present
157
+ const systemMessage = messages.find(m => m.role === 'system');
158
+ const conversationMessages = messages.filter(m => m.role !== 'system');
159
+ const response = await fetch(`${this.config.baseUrl}/messages`, {
160
+ method: 'POST',
161
+ headers: {
162
+ 'Content-Type': 'application/json',
163
+ 'x-api-key': this.config.apiKey,
164
+ 'anthropic-version': '2023-06-01',
165
+ },
166
+ body: JSON.stringify({
167
+ model: this.config.model,
168
+ max_tokens: this.config.maxTokens,
169
+ temperature: this.config.temperature,
170
+ system: systemMessage?.content,
171
+ messages: conversationMessages.map(m => ({
172
+ role: m.role,
173
+ content: m.content,
174
+ })),
175
+ }),
176
+ });
177
+ if (!response.ok) {
178
+ const body = await response.text();
179
+ throw new LLMAPIError('anthropic', response.status, body);
180
+ }
181
+ const data = await response.json();
182
+ return {
183
+ content: data.content[0]?.text ?? '',
184
+ model: data.model,
185
+ usage: data.usage ? {
186
+ prompt_tokens: data.usage.input_tokens,
187
+ completion_tokens: data.usage.output_tokens,
188
+ total_tokens: data.usage.input_tokens + data.usage.output_tokens,
189
+ } : undefined,
190
+ };
191
+ }
192
+ /**
193
+ * Get the configured model name
194
+ */
195
+ getModel() {
196
+ return this.config.model;
197
+ }
198
+ /**
199
+ * Get the configured provider
200
+ */
201
+ getProvider() {
202
+ return this.config.provider;
203
+ }
204
+ }
205
+ exports.LLMClient = LLMClient;
206
+ //# sourceMappingURL=llm-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-client.js","sourceRoot":"","sources":["../../src/mediation/llm-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * LLM Evidence Manager
3
+ *
4
+ * Tracks and verifies evidence of real LLM API calls.
5
+ * This is the fail-closed mechanism that ensures:
6
+ * 1. Every LLM call generates a proof file
7
+ * 2. COMPLETE status can only be asserted with evidence
8
+ * 3. Evidence files are tamper-resistant (hash verification)
9
+ *
10
+ * ARCHITECTURAL RULES:
11
+ * - No evidence file = LLM call did not happen
12
+ * - Evidence must exist BEFORE asserting COMPLETE
13
+ * - Failed calls are also recorded (to prove attempt)
14
+ */
15
+ /**
16
+ * LLM Evidence structure
17
+ * Records proof of a real LLM API call
18
+ */
19
+ export interface LLMEvidence {
20
+ /** Unique identifier for this call */
21
+ call_id: string;
22
+ /** LLM provider (openai, anthropic) */
23
+ provider: string;
24
+ /** Model used */
25
+ model: string;
26
+ /** Hash of the request payload */
27
+ request_hash: string;
28
+ /** Hash of the response (null if failed) */
29
+ response_hash: string | null;
30
+ /** ISO timestamp of the call */
31
+ timestamp: string;
32
+ /** Duration in milliseconds */
33
+ duration_ms: number;
34
+ /** Whether the call succeeded */
35
+ success: boolean;
36
+ /** Error message if failed */
37
+ error?: string;
38
+ }
39
+ /**
40
+ * Evidence statistics
41
+ */
42
+ export interface EvidenceStats {
43
+ total_calls: number;
44
+ successful_calls: number;
45
+ failed_calls: number;
46
+ }
47
+ /**
48
+ * LLM Evidence Manager
49
+ *
50
+ * Manages evidence files for LLM API calls.
51
+ * Uses file-based storage for durability and auditability.
52
+ */
53
+ export declare class LLMEvidenceManager {
54
+ private readonly evidenceDir;
55
+ private readonly evidenceMap;
56
+ constructor(baseDir: string);
57
+ /**
58
+ * Load existing evidence files from disk
59
+ */
60
+ private loadExistingEvidence;
61
+ /**
62
+ * Record evidence for an LLM call
63
+ * @returns Path to the evidence file
64
+ */
65
+ recordEvidence(evidence: LLMEvidence): string;
66
+ /**
67
+ * Check if evidence exists for a call
68
+ */
69
+ hasEvidence(callId: string): boolean;
70
+ /**
71
+ * Get evidence by call ID
72
+ */
73
+ getEvidence(callId: string): LLMEvidence | null;
74
+ /**
75
+ * List all evidence
76
+ */
77
+ listEvidence(): LLMEvidence[];
78
+ /**
79
+ * Get evidence statistics
80
+ */
81
+ getStats(): EvidenceStats;
82
+ /**
83
+ * Check if we can assert COMPLETE status
84
+ * Requires at least one successful LLM call with evidence
85
+ */
86
+ canAssertComplete(): boolean;
87
+ /**
88
+ * Verify integrity of an evidence file
89
+ * Detects tampering by comparing stored hash with recalculated hash
90
+ */
91
+ verifyIntegrity(callId: string): boolean;
92
+ /**
93
+ * Get evidence directory path
94
+ */
95
+ getEvidenceDir(): string;
96
+ }
97
+ /**
98
+ * Create hash for request payload
99
+ */
100
+ export declare function hashRequest(messages: Array<{
101
+ role: string;
102
+ content: string;
103
+ }>): string;
104
+ /**
105
+ * Create hash for response content
106
+ */
107
+ export declare function hashResponse(content: string): string;
108
+ //# sourceMappingURL=llm-evidence-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-evidence-manager.d.ts","sourceRoot":"","sources":["../../src/mediation/llm-evidence-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;gBAEvD,OAAO,EAAE,MAAM;IAY3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM;IAqB7C;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAWpC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAuB/C;;OAEG;IACH,YAAY,IAAI,WAAW,EAAE;IAM7B;;OAEG;IACH,QAAQ,IAAI,aAAa;IAYzB;;;OAGG;IACH,iBAAiB,IAAI,OAAO;IAY5B;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAqBxC;;OAEG;IACH,cAAc,IAAI,MAAM;CAGzB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAGtF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD"}