open-multi-agent-kit 0.80.8 → 0.90.3

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 (208) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +21 -31
  3. package/dist/cli/args.d.ts +0 -2
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +2 -7
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/core/agent-session.d.ts +2 -0
  8. package/dist/core/agent-session.d.ts.map +1 -1
  9. package/dist/core/agent-session.js +41 -5
  10. package/dist/core/agent-session.js.map +1 -1
  11. package/dist/core/automation/index.d.ts +359 -0
  12. package/dist/core/automation/index.d.ts.map +1 -0
  13. package/dist/core/automation/index.js +665 -0
  14. package/dist/core/automation/index.js.map +1 -0
  15. package/dist/core/bang-skill-invocation.d.ts +26 -0
  16. package/dist/core/bang-skill-invocation.d.ts.map +1 -0
  17. package/dist/core/bang-skill-invocation.js +59 -0
  18. package/dist/core/bang-skill-invocation.js.map +1 -0
  19. package/dist/core/browser-use.d.ts +8 -0
  20. package/dist/core/browser-use.d.ts.map +1 -1
  21. package/dist/core/browser-use.js +61 -23
  22. package/dist/core/browser-use.js.map +1 -1
  23. package/dist/core/compactor.d.ts.map +1 -1
  24. package/dist/core/compactor.js +0 -3
  25. package/dist/core/compactor.js.map +1 -1
  26. package/dist/core/context-budget-governor-v2.d.ts +2 -1
  27. package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
  28. package/dist/core/context-budget-governor-v2.js +1 -0
  29. package/dist/core/context-budget-governor-v2.js.map +1 -1
  30. package/dist/core/context-budget-headroom-types.d.ts +8 -0
  31. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  32. package/dist/core/context-budget-headroom-types.js.map +1 -1
  33. package/dist/core/context-budget-headroom.d.ts +1 -1
  34. package/dist/core/context-budget-headroom.d.ts.map +1 -1
  35. package/dist/core/context-budget-headroom.js +17 -4
  36. package/dist/core/context-budget-headroom.js.map +1 -1
  37. package/dist/core/context-budget-system-prompt.d.ts +2 -1
  38. package/dist/core/context-budget-system-prompt.d.ts.map +1 -1
  39. package/dist/core/context-budget-system-prompt.js +6 -1
  40. package/dist/core/context-budget-system-prompt.js.map +1 -1
  41. package/dist/core/context-budget-v2-cache-hash.d.ts +3 -0
  42. package/dist/core/context-budget-v2-cache-hash.d.ts.map +1 -0
  43. package/dist/core/context-budget-v2-cache-hash.js +16 -0
  44. package/dist/core/context-budget-v2-cache-hash.js.map +1 -0
  45. package/dist/core/context-budget-v2-cache-keys.d.ts +58 -0
  46. package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -0
  47. package/dist/core/context-budget-v2-cache-keys.js +128 -0
  48. package/dist/core/context-budget-v2-cache-keys.js.map +1 -0
  49. package/dist/core/context-budget-v2-cache-provider.d.ts +23 -0
  50. package/dist/core/context-budget-v2-cache-provider.d.ts.map +1 -0
  51. package/dist/core/context-budget-v2-cache-provider.js +29 -0
  52. package/dist/core/context-budget-v2-cache-provider.js.map +1 -0
  53. package/dist/core/context-budget-v2-cache-telemetry.d.ts +36 -0
  54. package/dist/core/context-budget-v2-cache-telemetry.d.ts.map +1 -0
  55. package/dist/core/context-budget-v2-cache-telemetry.js +64 -0
  56. package/dist/core/context-budget-v2-cache-telemetry.js.map +1 -0
  57. package/dist/core/context-budget-v2-cache-validation.d.ts +36 -0
  58. package/dist/core/context-budget-v2-cache-validation.d.ts.map +1 -0
  59. package/dist/core/context-budget-v2-cache-validation.js +98 -0
  60. package/dist/core/context-budget-v2-cache-validation.js.map +1 -0
  61. package/dist/core/context-budget-v2-cache.d.ts +36 -0
  62. package/dist/core/context-budget-v2-cache.d.ts.map +1 -0
  63. package/dist/core/context-budget-v2-cache.js +50 -0
  64. package/dist/core/context-budget-v2-cache.js.map +1 -0
  65. package/dist/core/context-budget-v2-plan-cache-keys.d.ts +16 -0
  66. package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -0
  67. package/dist/core/context-budget-v2-plan-cache-keys.js +49 -0
  68. package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -0
  69. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  70. package/dist/core/context-budget-v2-planner.js +55 -2
  71. package/dist/core/context-budget-v2-planner.js.map +1 -1
  72. package/dist/core/context-budget-v2-representation-cache.d.ts +27 -0
  73. package/dist/core/context-budget-v2-representation-cache.d.ts.map +1 -0
  74. package/dist/core/context-budget-v2-representation-cache.js +173 -0
  75. package/dist/core/context-budget-v2-representation-cache.js.map +1 -0
  76. package/dist/core/context-budget-v2-selection.d.ts +2 -0
  77. package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
  78. package/dist/core/context-budget-v2-selection.js +12 -2
  79. package/dist/core/context-budget-v2-selection.js.map +1 -1
  80. package/dist/core/context-budget-v2-types.d.ts +107 -1
  81. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  82. package/dist/core/context-budget-v2-types.js.map +1 -1
  83. package/dist/core/diagnostics.d.ts +2 -0
  84. package/dist/core/diagnostics.d.ts.map +1 -1
  85. package/dist/core/diagnostics.js.map +1 -1
  86. package/dist/core/extensions/builtin/todo-checklist.d.ts.map +1 -1
  87. package/dist/core/extensions/builtin/todo-checklist.js +3 -0
  88. package/dist/core/extensions/builtin/todo-checklist.js.map +1 -1
  89. package/dist/core/footer-data-provider.d.ts +3 -1
  90. package/dist/core/footer-data-provider.d.ts.map +1 -1
  91. package/dist/core/footer-data-provider.js +4 -0
  92. package/dist/core/footer-data-provider.js.map +1 -1
  93. package/dist/core/headroom.d.ts.map +1 -1
  94. package/dist/core/headroom.js +0 -4
  95. package/dist/core/headroom.js.map +1 -1
  96. package/dist/core/hook-inventory.d.ts.map +1 -1
  97. package/dist/core/hook-inventory.js +6 -0
  98. package/dist/core/hook-inventory.js.map +1 -1
  99. package/dist/core/mcp-computer-use-presets.d.ts +64 -0
  100. package/dist/core/mcp-computer-use-presets.d.ts.map +1 -0
  101. package/dist/core/mcp-computer-use-presets.js +158 -0
  102. package/dist/core/mcp-computer-use-presets.js.map +1 -0
  103. package/dist/core/mcp-public-presets.d.ts +578 -0
  104. package/dist/core/mcp-public-presets.d.ts.map +1 -0
  105. package/dist/core/mcp-public-presets.js +647 -0
  106. package/dist/core/mcp-public-presets.js.map +1 -0
  107. package/dist/core/model-registry.d.ts.map +1 -1
  108. package/dist/core/model-registry.js +1 -0
  109. package/dist/core/model-registry.js.map +1 -1
  110. package/dist/core/model-resolver.d.ts.map +1 -1
  111. package/dist/core/model-resolver.js +1 -0
  112. package/dist/core/model-resolver.js.map +1 -1
  113. package/dist/core/pi-package-intake-candidates.d.ts +34 -0
  114. package/dist/core/pi-package-intake-candidates.d.ts.map +1 -0
  115. package/dist/core/pi-package-intake-candidates.js +291 -0
  116. package/dist/core/pi-package-intake-candidates.js.map +1 -0
  117. package/dist/core/pi-package-intake.d.ts +50 -0
  118. package/dist/core/pi-package-intake.d.ts.map +1 -0
  119. package/dist/core/pi-package-intake.js +132 -0
  120. package/dist/core/pi-package-intake.js.map +1 -0
  121. package/dist/core/provider-display-names.d.ts.map +1 -1
  122. package/dist/core/provider-display-names.js +1 -0
  123. package/dist/core/provider-display-names.js.map +1 -1
  124. package/dist/core/resource-loader.d.ts.map +1 -1
  125. package/dist/core/resource-loader.js +1 -0
  126. package/dist/core/resource-loader.js.map +1 -1
  127. package/dist/core/reverse-skill.d.ts +2 -0
  128. package/dist/core/reverse-skill.d.ts.map +1 -0
  129. package/dist/core/reverse-skill.js +7 -0
  130. package/dist/core/reverse-skill.js.map +1 -0
  131. package/dist/core/settings-manager.d.ts +3 -3
  132. package/dist/core/settings-manager.d.ts.map +1 -1
  133. package/dist/core/settings-manager.js.map +1 -1
  134. package/dist/core/skills.d.ts +4 -0
  135. package/dist/core/skills.d.ts.map +1 -1
  136. package/dist/core/skills.js +115 -43
  137. package/dist/core/skills.js.map +1 -1
  138. package/dist/core/system-prompt.d.ts +2 -0
  139. package/dist/core/system-prompt.d.ts.map +1 -1
  140. package/dist/core/system-prompt.js +58 -5
  141. package/dist/core/system-prompt.js.map +1 -1
  142. package/dist/core/todo-runtime-state.d.ts +5 -0
  143. package/dist/core/todo-runtime-state.d.ts.map +1 -0
  144. package/dist/core/todo-runtime-state.js +12 -0
  145. package/dist/core/todo-runtime-state.js.map +1 -0
  146. package/dist/index.d.ts +2 -0
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/index.js +2 -0
  149. package/dist/index.js.map +1 -1
  150. package/dist/migrations.d.ts +19 -0
  151. package/dist/migrations.d.ts.map +1 -1
  152. package/dist/migrations.js +39 -15
  153. package/dist/migrations.js.map +1 -1
  154. package/dist/modes/interactive/components/control-panel-box.d.ts +3 -3
  155. package/dist/modes/interactive/components/control-panel-box.d.ts.map +1 -1
  156. package/dist/modes/interactive/components/control-panel-box.js +10 -10
  157. package/dist/modes/interactive/components/control-panel-box.js.map +1 -1
  158. package/dist/modes/interactive/components/control-panel-gradient-motion.d.ts.map +1 -1
  159. package/dist/modes/interactive/components/control-panel-gradient-motion.js +2 -1
  160. package/dist/modes/interactive/components/control-panel-gradient-motion.js.map +1 -1
  161. package/dist/modes/interactive/components/control-panel-layout.d.ts +22 -1
  162. package/dist/modes/interactive/components/control-panel-layout.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/control-panel-layout.js +244 -68
  164. package/dist/modes/interactive/components/control-panel-layout.js.map +1 -1
  165. package/dist/modes/interactive/components/control-panel-runtime-status.d.ts +2 -1
  166. package/dist/modes/interactive/components/control-panel-runtime-status.d.ts.map +1 -1
  167. package/dist/modes/interactive/components/control-panel-runtime-status.js +20 -1
  168. package/dist/modes/interactive/components/control-panel-runtime-status.js.map +1 -1
  169. package/dist/modes/interactive/components/control-panel-sparkles.d.ts +27 -0
  170. package/dist/modes/interactive/components/control-panel-sparkles.d.ts.map +1 -0
  171. package/dist/modes/interactive/components/control-panel-sparkles.js +42 -0
  172. package/dist/modes/interactive/components/control-panel-sparkles.js.map +1 -0
  173. package/dist/modes/interactive/components/control-panel.d.ts +9 -0
  174. package/dist/modes/interactive/components/control-panel.d.ts.map +1 -1
  175. package/dist/modes/interactive/components/control-panel.js +50 -6
  176. package/dist/modes/interactive/components/control-panel.js.map +1 -1
  177. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  178. package/dist/modes/interactive/components/footer.js +6 -0
  179. package/dist/modes/interactive/components/footer.js.map +1 -1
  180. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  181. package/dist/modes/interactive/components/settings-selector.js +2 -1
  182. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  183. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  184. package/dist/modes/interactive/components/thinking-selector.js +2 -1
  185. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  186. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  187. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  188. package/dist/modes/interactive/interactive-mode.js +70 -15
  189. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  190. package/dist/modes/interactive/theme/theme.d.ts +1 -1
  191. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  192. package/dist/modes/interactive/theme/theme.js +5 -0
  193. package/dist/modes/interactive/theme/theme.js.map +1 -1
  194. package/docs/providers.md +12 -0
  195. package/docs/skills.md +8 -4
  196. package/docs/usage.md +4 -3
  197. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  198. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  199. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  200. package/examples/extensions/gondolin/package-lock.json +2 -2
  201. package/examples/extensions/gondolin/package.json +1 -1
  202. package/examples/extensions/preset.ts +2 -2
  203. package/examples/extensions/sandbox/package-lock.json +2 -2
  204. package/examples/extensions/sandbox/package.json +1 -1
  205. package/examples/extensions/with-deps/package-lock.json +2 -2
  206. package/examples/extensions/with-deps/package.json +1 -1
  207. package/npm-shrinkwrap.json +27 -34
  208. package/package.json +5 -5
@@ -0,0 +1,665 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile, stat } from "node:fs/promises";
3
+ export const AUTOPILOT_MAX = {
4
+ id: "autopilot-max",
5
+ humanPromptBudget: { maxPromptsPerTask: 0, maxPromptRate: 0 },
6
+ capabilities: [
7
+ "fs.read",
8
+ "fs.write",
9
+ "process.exec",
10
+ "network.read",
11
+ "network.write",
12
+ "browser.observe",
13
+ "browser.mutate",
14
+ "browser.credentialed",
15
+ "mcp.call",
16
+ "extension.run",
17
+ "api.call",
18
+ "secrets.resolve",
19
+ "subagent.spawn",
20
+ ],
21
+ env: {
22
+ mode: "passthrough-audited",
23
+ allowPatterns: ["*"],
24
+ denyPatterns: [],
25
+ redactPatterns: [
26
+ "*KEY*",
27
+ "*TOKEN*",
28
+ "*SECRET*",
29
+ "*PASSWORD*",
30
+ "AWS_*",
31
+ "GCP_*",
32
+ "AZURE_*",
33
+ "OPENAI_*",
34
+ "ANTHROPIC_*",
35
+ "GITHUB_*",
36
+ "NPM_*",
37
+ ],
38
+ exposeToModel: false,
39
+ },
40
+ api: {
41
+ allowOrigins: ["*"],
42
+ allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE"],
43
+ mutationDefault: "auto",
44
+ requireIdempotencyForMethods: ["POST", "PUT", "PATCH", "DELETE"],
45
+ },
46
+ browser: {
47
+ persistentProfile: true,
48
+ credentialedSessions: true,
49
+ autoSubmit: true,
50
+ autoDownload: true,
51
+ maxUnknownOutcomeReconciliations: 5,
52
+ },
53
+ verification: {
54
+ minVerifiabilityByRisk: { R0: 0.1, R1: 0.25, R2: 0.45, R3: 0.65 },
55
+ requireEvidenceByRisk: { R0: false, R1: true, R2: true, R3: true },
56
+ requirePostconditionsByRisk: { R0: false, R1: true, R2: true, R3: true },
57
+ },
58
+ recovery: {
59
+ autoRetry: true,
60
+ autoRollback: true,
61
+ autoCompensate: true,
62
+ duplicateMutationSuppression: true,
63
+ },
64
+ budgets: {
65
+ maxWallClockMs: 30 * 60 * 1000,
66
+ maxToolCalls: 500,
67
+ maxBrowserActions: 250,
68
+ maxNetworkCalls: 1000,
69
+ maxCostUsd: 10,
70
+ riskBudget: { R0: 10000, R1: 2000, R2: 500, R3: 100 },
71
+ },
72
+ };
73
+ export class EnvBroker {
74
+ processEnv;
75
+ ledger;
76
+ constructor(args) {
77
+ this.processEnv = args.processEnv;
78
+ this.ledger = args.ledger;
79
+ }
80
+ async createChildEnv(req) {
81
+ const selected = this.collect(req).filter((record) => this.isAllowed(record, req));
82
+ const childEnv = {};
83
+ for (const record of selected) {
84
+ childEnv[record.key] = record.value;
85
+ await this.ledger.append({
86
+ actionId: req.actionId,
87
+ toolId: req.toolId,
88
+ key: record.key,
89
+ sensitivity: record.sensitivity,
90
+ fingerprint: record.fingerprint,
91
+ purpose: req.purpose,
92
+ passedToProcess: true,
93
+ exposedToModel: false,
94
+ timestamp: new Date().toISOString(),
95
+ });
96
+ }
97
+ return childEnv;
98
+ }
99
+ redactEnvForModel(env) {
100
+ const out = {};
101
+ for (const [key, value] of Object.entries(env)) {
102
+ const sensitivity = classifyEnvKey(key, value);
103
+ out[key] = sensitivity === "public" ? value : `[REDACTED:${sha256(value).slice(0, 12)}]`;
104
+ }
105
+ return out;
106
+ }
107
+ collect(req) {
108
+ const records = [];
109
+ for (const [key, value] of Object.entries(this.processEnv)) {
110
+ if (typeof value !== "string")
111
+ continue;
112
+ records.push({
113
+ key,
114
+ value,
115
+ sensitivity: classifyEnvKey(key, value),
116
+ source: "process",
117
+ fingerprint: sha256(value),
118
+ });
119
+ }
120
+ for (const [key, value] of Object.entries(req.extraEnv ?? {})) {
121
+ records.push({
122
+ key,
123
+ value,
124
+ sensitivity: classifyEnvKey(key, value),
125
+ source: "tool",
126
+ fingerprint: sha256(value),
127
+ });
128
+ }
129
+ return records;
130
+ }
131
+ isAllowed(record, req) {
132
+ if (req.profile.env.mode === "passthrough-full")
133
+ return true;
134
+ if (req.profile.env.mode === "secret-ref-only" && record.sensitivity !== "public")
135
+ return false;
136
+ const allowedByPattern = matchesAny(record.key, req.profile.env.allowPatterns);
137
+ const deniedByPattern = matchesAny(record.key, req.profile.env.denyPatterns);
138
+ if (deniedByPattern || !allowedByPattern)
139
+ return false;
140
+ if (req.requestedKeys?.includes(record.key))
141
+ return true;
142
+ if (req.requestedPatterns?.some((pattern) => globMatch(record.key, pattern)))
143
+ return true;
144
+ return req.profile.env.allowPatterns.includes("*");
145
+ }
146
+ }
147
+ export class EvidenceLedger {
148
+ sessionId;
149
+ taskId;
150
+ events = [];
151
+ previousHash = "genesis";
152
+ constructor(args) {
153
+ this.sessionId = args.sessionId;
154
+ this.taskId = args.taskId;
155
+ }
156
+ async append(event) {
157
+ const fullWithoutHash = {
158
+ ...event,
159
+ sequence: this.events.length + 1,
160
+ previousHash: this.previousHash,
161
+ timestamp: new Date().toISOString(),
162
+ sessionId: this.sessionId,
163
+ taskId: this.taskId,
164
+ };
165
+ const eventHash = canonicalHash(fullWithoutHash);
166
+ const full = { ...fullWithoutHash, eventHash };
167
+ this.events.push(full);
168
+ this.previousHash = eventHash;
169
+ return full;
170
+ }
171
+ snapshot() {
172
+ return this.events.map((event) => ({ ...event }));
173
+ }
174
+ }
175
+ export class PostconditionVerifier {
176
+ async verify(conditions, ctx) {
177
+ if (conditions.length === 0) {
178
+ return { pass: false, confidence: 0, evidencePointers: [], failures: ["no postconditions"] };
179
+ }
180
+ const results = [];
181
+ for (const condition of conditions) {
182
+ results.push(await this.verifyOne(condition, ctx));
183
+ }
184
+ return {
185
+ pass: results.every((result) => result.pass),
186
+ confidence: Math.min(...results.map((result) => result.confidence)),
187
+ evidencePointers: results.flatMap((result) => result.evidencePointers),
188
+ failures: results.flatMap((result) => result.failures),
189
+ receiptId: results.find((result) => result.receiptId)?.receiptId,
190
+ };
191
+ }
192
+ async verifyOne(condition, ctx) {
193
+ switch (condition.kind) {
194
+ case "api-status":
195
+ return booleanResult(ctx.apiStatus === condition.status, "api-status", `status ${condition.status}`);
196
+ case "api-json": {
197
+ const actual = readJsonPath(ctx.apiBody, condition.jsonPath);
198
+ return booleanResult(deepEqual(actual, condition.expected), "api-json", condition.jsonPath);
199
+ }
200
+ case "text": {
201
+ const text = ctx.text ?? "";
202
+ const pass = condition.exact !== undefined
203
+ ? text.includes(condition.exact)
204
+ : condition.pattern !== undefined && new RegExp(condition.pattern).test(text);
205
+ return booleanResult(pass, "text", condition.exact ?? condition.pattern ?? "<missing>");
206
+ }
207
+ case "url": {
208
+ const currentUrl = ctx.currentUrl;
209
+ if (typeof currentUrl !== "string") {
210
+ return booleanResult(false, "url", "<missing>");
211
+ }
212
+ const parsedUrl = new URL(currentUrl);
213
+ let pass = true;
214
+ if (condition.origin)
215
+ pass = parsedUrl.origin === condition.origin;
216
+ if (pass && condition.path)
217
+ pass = parsedUrl.pathname === condition.path;
218
+ if (pass && condition.pattern)
219
+ pass = new RegExp(condition.pattern).test(currentUrl);
220
+ return booleanResult(pass, "url", currentUrl ?? "<missing>");
221
+ }
222
+ case "file-exists":
223
+ return verifyFile(condition.path, condition.sha256, "file-exists");
224
+ case "download":
225
+ return verifyFile(condition.path, condition.sha256, "download");
226
+ case "receipt": {
227
+ const receiptId = ctx.receiptId;
228
+ const pass = typeof receiptId === "string" && new RegExp(condition.idPattern).test(receiptId);
229
+ return { ...booleanResult(pass, "receipt", receiptId ?? "<missing>"), receiptId };
230
+ }
231
+ case "database": {
232
+ const actualHash = ctx.databaseHashes?.[condition.queryId];
233
+ return booleanResult(actualHash === condition.expectedHash, "database", condition.queryId);
234
+ }
235
+ case "element-visible": {
236
+ const pass = (ctx.elements ?? []).some((element) => element.visible === true &&
237
+ (condition.ref === undefined || element.ref === condition.ref) &&
238
+ (condition.role === undefined || element.role === condition.role) &&
239
+ (condition.name === undefined || element.name === condition.name));
240
+ return booleanResult(pass, "element-visible", condition.ref ?? condition.role ?? condition.name ?? "<any>");
241
+ }
242
+ case "element-value": {
243
+ const pass = (ctx.elements ?? []).some((element) => element.ref === condition.ref && element.value === condition.expected);
244
+ return booleanResult(pass, "element-value", condition.ref);
245
+ }
246
+ }
247
+ }
248
+ }
249
+ export class ApiBroker {
250
+ ledger;
251
+ verifier;
252
+ fetcher;
253
+ constructor(args) {
254
+ this.ledger = args.ledger;
255
+ this.verifier = args.verifier;
256
+ this.fetcher = args.fetcher ?? defaultFetcher;
257
+ }
258
+ async execute(action, ctx = {}) {
259
+ const idempotencyKey = action.idempotencyKey ?? deriveIdempotencyKey(action);
260
+ const headers = { ...action.headers, "Idempotency-Key": idempotencyKey, "X-OMK-Action-Id": action.actionId };
261
+ await this.ledger.append({
262
+ actor: "api",
263
+ kind: "api.dispatch.planned",
264
+ actionId: action.actionId,
265
+ inputHash: canonicalHash({ method: action.method, url: action.url, headers, body: action.body }),
266
+ outcome: "planned",
267
+ });
268
+ let response;
269
+ try {
270
+ response = await this.fetcher(action.url, {
271
+ method: action.method,
272
+ headers,
273
+ body: action.body === undefined ? undefined : JSON.stringify(action.body),
274
+ signal: ctx.signal,
275
+ });
276
+ }
277
+ catch {
278
+ return this.reconcileUnknown(action, idempotencyKey, ctx.profile ?? AUTOPILOT_MAX);
279
+ }
280
+ const rawBody = await safeReadJsonOrText(response);
281
+ const redactedBody = redactForModel(rawBody);
282
+ await this.ledger.append({
283
+ actor: "api",
284
+ kind: "api.response",
285
+ actionId: action.actionId,
286
+ outputHash: canonicalHash(rawBody),
287
+ redactedOutputHash: canonicalHash(redactedBody),
288
+ outcome: "executed",
289
+ });
290
+ const verification = await this.verifier.verify(action.expectedPostconditions, {
291
+ apiStatus: response.status,
292
+ apiBody: rawBody,
293
+ receiptId: readReceiptId(rawBody),
294
+ });
295
+ if (!verification.pass) {
296
+ return {
297
+ kind: "succeeded_unverified",
298
+ status: response.status,
299
+ bodyHash: canonicalHash(rawBody),
300
+ redactedBody,
301
+ };
302
+ }
303
+ return {
304
+ kind: "succeeded",
305
+ status: response.status,
306
+ bodyHash: canonicalHash(rawBody),
307
+ receiptId: verification.receiptId,
308
+ redactedBody,
309
+ };
310
+ }
311
+ async reconcileUnknown(action, idempotencyKey, profile) {
312
+ for (let attempt = 0; attempt < profile.browser.maxUnknownOutcomeReconciliations; attempt++) {
313
+ const verification = await this.verifier.verify(action.expectedPostconditions, { receiptId: idempotencyKey });
314
+ if (verification.pass) {
315
+ await this.ledger.append({
316
+ actor: "recovery",
317
+ kind: "api.unknown.reconciled",
318
+ actionId: action.actionId,
319
+ outcome: "reconciled",
320
+ });
321
+ return { kind: "succeeded", receiptId: verification.receiptId };
322
+ }
323
+ }
324
+ await this.ledger.append({
325
+ actor: "recovery",
326
+ kind: "api.unknown.unresolved",
327
+ actionId: action.actionId,
328
+ outcome: "unknown_after_dispatch",
329
+ });
330
+ return { kind: "unknown_after_dispatch" };
331
+ }
332
+ }
333
+ export function strategyForRisk(risk) {
334
+ if (risk === "R0") {
335
+ return {
336
+ execute: true,
337
+ requirePostcondition: false,
338
+ requireIdempotency: false,
339
+ recovery: "retry",
340
+ evidenceDepth: "minimal",
341
+ };
342
+ }
343
+ if (risk === "R1") {
344
+ return {
345
+ execute: true,
346
+ requirePostcondition: true,
347
+ requireIdempotency: false,
348
+ recovery: "retry",
349
+ evidenceDepth: "normal",
350
+ };
351
+ }
352
+ if (risk === "R2") {
353
+ return {
354
+ execute: true,
355
+ requirePostcondition: true,
356
+ requireIdempotency: true,
357
+ recovery: "repair",
358
+ evidenceDepth: "deep",
359
+ };
360
+ }
361
+ return {
362
+ execute: true,
363
+ requirePostcondition: true,
364
+ requireIdempotency: true,
365
+ recovery: "reconcile-and-compensate",
366
+ evidenceDepth: "forensic",
367
+ };
368
+ }
369
+ export class DynamicToolPortfolioOptimizer {
370
+ rank(candidates, need) {
371
+ return candidates
372
+ .filter((candidate) => candidate.enabled && candidate.capability === need.requiredCapability)
373
+ .map((candidate) => this.scoreCandidate(candidate, need))
374
+ .sort((left, right) => right.score - left.score);
375
+ }
376
+ scoreCandidate(candidate, need) {
377
+ const strategy = strategyForRisk(need.risk);
378
+ const contextMatch = need.contextFingerprint === undefined || candidate.contextFingerprint === need.contextFingerprint ? 1 : 0;
379
+ const idempotency = !strategy.requireIdempotency || candidate.supportsIdempotency ? 1 : 0;
380
+ const latency = Math.max(0, 1 - candidate.avgLatencyMs / 30000);
381
+ const cost = Math.max(0, 1 - candidate.costUsd / Math.max(1, AUTOPILOT_MAX.budgets.maxCostUsd));
382
+ const postconditionCoverage = need.requiredPostconditions.length > 0 ? candidate.verificationStrength : 1;
383
+ const score = 0.32 * candidate.reliability +
384
+ 0.26 * postconditionCoverage +
385
+ 0.16 * idempotency +
386
+ 0.12 * contextMatch +
387
+ 0.08 * latency +
388
+ 0.06 * cost;
389
+ return {
390
+ candidate,
391
+ score: Number(score.toFixed(4)),
392
+ strategy,
393
+ reasons: [
394
+ `reliability=${candidate.reliability}`,
395
+ `verification=${postconditionCoverage}`,
396
+ `idempotency=${idempotency}`,
397
+ `context=${contextMatch}`,
398
+ ],
399
+ };
400
+ }
401
+ }
402
+ export class ToolExecutionBroker {
403
+ ledger;
404
+ profile;
405
+ optimizer;
406
+ constructor(args) {
407
+ this.ledger = args.ledger;
408
+ this.profile = args.profile ?? AUTOPILOT_MAX;
409
+ this.optimizer = args.optimizer ?? new DynamicToolPortfolioOptimizer();
410
+ }
411
+ async select(need, candidates) {
412
+ const choices = this.optimizer.rank(candidates, need);
413
+ const choice = choices[0];
414
+ if (choice === undefined) {
415
+ throw new Error(`No enabled tool candidate for ${need.requiredCapability}`);
416
+ }
417
+ await this.ledger.append({
418
+ actor: "tool",
419
+ kind: "tool.execution.planned",
420
+ actionId: need.actionId,
421
+ inputHash: canonicalHash(need),
422
+ policyHash: canonicalHash(this.profile),
423
+ schemaHash: choice.candidate.schemaHash,
424
+ outcome: "planned",
425
+ });
426
+ return choice;
427
+ }
428
+ async recordResult(choice, result) {
429
+ return this.ledger.append({
430
+ actor: "tool",
431
+ kind: "tool.execution.result",
432
+ actionId: choice.candidate.toolId,
433
+ outputHash: canonicalHash(result),
434
+ schemaHash: choice.candidate.schemaHash,
435
+ outcome: result.pass ? "verified" : "unknown_after_dispatch",
436
+ });
437
+ }
438
+ }
439
+ export class AutomationHarnessScorer {
440
+ score(input) {
441
+ const verifiedSuccess = this.verifiedSuccess(input);
442
+ const autonomy = 1 - input.trace.humanPrompts / Math.max(1, input.trace.actions.length);
443
+ const toolUse = this.toolUseScore(input.trace);
444
+ const browserUse = this.browserUseScore(input.trace);
445
+ const envApi = this.envApiScore(input.trace);
446
+ const recovery = this.recoveryScore(input.trace);
447
+ const determinism = input.trace.replayMatches ? 1 : 0;
448
+ const context = this.contextScore(input.trace);
449
+ const critical = input.trace.secretLeaks > 0 ||
450
+ input.trace.duplicateIrreversibleMutations > 0 ||
451
+ (input.requiredPostconditions.length > 0 && verifiedSuccess < 1) ||
452
+ !input.trace.replayMatches ||
453
+ input.trace.unledgeredEnvUses > 0 ||
454
+ input.trace.envApiUses.some((use) => !use.ledgered) ||
455
+ input.trace.actions.some((action) => action.schemaHashMatched === false ||
456
+ (action.kind === "browser" && action.targetFingerprintMatched === false));
457
+ const raw = 20 * verifiedSuccess +
458
+ 15 * autonomy +
459
+ 15 * toolUse +
460
+ 15 * browserUse +
461
+ 10 * envApi +
462
+ 10 * recovery +
463
+ 10 * determinism +
464
+ 5 * context;
465
+ return {
466
+ score: critical ? Math.min(79, raw) : raw,
467
+ verifiedSuccess: verifiedSuccess >= 0.93,
468
+ envApiUseCorrectness: envApi,
469
+ duplicateMutations: input.trace.duplicateIrreversibleMutations,
470
+ secretLeaks: input.trace.secretLeaks,
471
+ critical,
472
+ };
473
+ }
474
+ verifiedSuccess(input) {
475
+ const passed = input.requiredPostconditions.filter((condition) => input.trace.verifications.some((verification) => verification.conditionHash === canonicalHash(condition) && verification.pass));
476
+ return passed.length / Math.max(1, input.requiredPostconditions.length);
477
+ }
478
+ toolUseScore(trace) {
479
+ const calls = trace.actions.filter((action) => action.kind === "tool");
480
+ if (calls.length === 0)
481
+ return 1;
482
+ const verified = calls.filter((action) => action.verificationPass).length;
483
+ const schemaStable = calls.filter((action) => action.schemaHashMatched === true).length;
484
+ const envLedgered = calls.filter((action) => action.envUseLedgered === true).length;
485
+ return (verified + schemaStable + envLedgered) / (3 * calls.length);
486
+ }
487
+ browserUseScore(trace) {
488
+ const actions = trace.actions.filter((action) => action.kind === "browser");
489
+ if (actions.length === 0)
490
+ return 1;
491
+ const verified = actions.filter((action) => action.verificationPass).length;
492
+ const targetStable = actions.filter((action) => action.targetFingerprintMatched === true).length;
493
+ const unknownResolved = actions.filter((action) => action.outcome !== "unknown_after_dispatch" || action.reconciled === true).length;
494
+ return (verified + targetStable + unknownResolved) / (3 * actions.length);
495
+ }
496
+ envApiScore(trace) {
497
+ if (trace.envApiUses.length === 0)
498
+ return 1;
499
+ const ledgered = trace.envApiUses.filter((use) => use.ledgered).length;
500
+ const notLeaked = trace.envApiUses.filter((use) => !use.exposedToModel && !use.exposedToLogs).length;
501
+ return (ledgered + notLeaked) / (2 * trace.envApiUses.length);
502
+ }
503
+ recoveryScore(trace) {
504
+ const failures = trace.failures + trace.unknownOutcomes;
505
+ if (failures === 0)
506
+ return 1;
507
+ return (trace.recoveredFailures + trace.reconciledUnknowns) / failures;
508
+ }
509
+ contextScore(trace) {
510
+ if (trace.contextPlans.length === 0)
511
+ return 1;
512
+ const valid = trace.contextPlans.filter((plan) => plan.renderedTokens <= plan.resourceBudget &&
513
+ plan.planHash === plan.renderedHashLinkedPlanHash &&
514
+ plan.outputReserveCountedOnce).length;
515
+ return valid / trace.contextPlans.length;
516
+ }
517
+ }
518
+ export function classifyEnvKey(key, value) {
519
+ const normalizedKey = key.toUpperCase();
520
+ if (normalizedKey.includes("TOKEN") ||
521
+ normalizedKey.includes("SECRET") ||
522
+ normalizedKey.includes("PASSWORD") ||
523
+ normalizedKey.includes("API_KEY") ||
524
+ normalizedKey.endsWith("_KEY") ||
525
+ normalizedKey.startsWith("AWS_") ||
526
+ normalizedKey.startsWith("GCP_") ||
527
+ normalizedKey.startsWith("AZURE_") ||
528
+ normalizedKey.startsWith("OPENAI_") ||
529
+ normalizedKey.startsWith("ANTHROPIC_") ||
530
+ normalizedKey.startsWith("GITHUB_") ||
531
+ normalizedKey.startsWith("NPM_")) {
532
+ return "credential";
533
+ }
534
+ if (looksLikePaymentCredential(value))
535
+ return "payment";
536
+ if (looksLikeSessionCookie(value))
537
+ return "session";
538
+ return "public";
539
+ }
540
+ export function canonicalHash(value) {
541
+ return sha256(stableStringify(value));
542
+ }
543
+ export function redactForModel(value) {
544
+ if (typeof value === "string")
545
+ return redactString(value);
546
+ if (Array.isArray(value))
547
+ return value.map((item) => redactForModel(item));
548
+ if (isRecord(value)) {
549
+ const out = {};
550
+ for (const [key, child] of Object.entries(value)) {
551
+ out[key] =
552
+ classifyEnvKey(key, typeof child === "string" ? child : "") === "public"
553
+ ? redactForModel(child)
554
+ : "[REDACTED]";
555
+ }
556
+ return out;
557
+ }
558
+ return value;
559
+ }
560
+ function booleanResult(pass, kind, description) {
561
+ return {
562
+ pass,
563
+ confidence: pass ? 1 : 0,
564
+ evidencePointers: pass ? [{ kind, description }] : [],
565
+ failures: pass ? [] : [`${kind} postcondition failed: ${description}`],
566
+ };
567
+ }
568
+ async function verifyFile(path, expectedHash, kind) {
569
+ try {
570
+ await stat(path);
571
+ const content = await readFile(path);
572
+ const actualHash = createHash("sha256").update(content).digest("hex");
573
+ const pass = expectedHash === undefined || expectedHash === actualHash;
574
+ return {
575
+ pass,
576
+ confidence: pass ? 1 : 0,
577
+ evidencePointers: pass ? [{ kind, description: path, sha256: actualHash }] : [],
578
+ failures: pass ? [] : [`${kind} hash mismatch for ${path}`],
579
+ };
580
+ }
581
+ catch {
582
+ return { pass: false, confidence: 0, evidencePointers: [], failures: [`${kind} missing: ${path}`] };
583
+ }
584
+ }
585
+ function readJsonPath(value, path) {
586
+ if (path === "$")
587
+ return value;
588
+ if (!path.startsWith("$."))
589
+ return undefined;
590
+ let current = value;
591
+ for (const segment of path.slice(2).split(".")) {
592
+ if (!isRecord(current))
593
+ return undefined;
594
+ current = current[segment];
595
+ }
596
+ return current;
597
+ }
598
+ function readReceiptId(value) {
599
+ if (!isRecord(value))
600
+ return undefined;
601
+ const receipt = value.receiptId ?? value.id;
602
+ return typeof receipt === "string" ? receipt : undefined;
603
+ }
604
+ async function safeReadJsonOrText(response) {
605
+ try {
606
+ return await response.json();
607
+ }
608
+ catch {
609
+ return response.text();
610
+ }
611
+ }
612
+ function deriveIdempotencyKey(action) {
613
+ return `omk-${canonicalHash({ method: action.method, url: action.url, body: action.body, actionId: action.actionId }).slice(0, 24)}`;
614
+ }
615
+ async function defaultFetcher(url, init) {
616
+ const response = await fetch(url, init);
617
+ return {
618
+ status: response.status,
619
+ json: () => response.json(),
620
+ text: () => response.text(),
621
+ };
622
+ }
623
+ function redactString(value) {
624
+ return value
625
+ .replace(/Bearer\s+[A-Za-z0-9._~+/=-]{8,}/g, "Bearer [REDACTED]")
626
+ .replace(/([?&]?(?:access_)?token=)[^&\s]+/gi, "$1[REDACTED]")
627
+ .replace(/((?:api[_-]?key|password|secret)=)[^&\s]+/gi, "$1[REDACTED]");
628
+ }
629
+ function deepEqual(left, right) {
630
+ return stableStringify(left) === stableStringify(right);
631
+ }
632
+ function stableStringify(value) {
633
+ if (value === null || typeof value !== "object")
634
+ return JSON.stringify(value);
635
+ if (Array.isArray(value))
636
+ return `[${value.map((item) => stableStringify(item)).join(",")}]`;
637
+ const record = value;
638
+ return `{${Object.keys(record)
639
+ .sort()
640
+ .map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)
641
+ .join(",")}}`;
642
+ }
643
+ function matchesAny(value, patterns) {
644
+ return patterns.some((pattern) => pattern === "*" || globMatch(value, pattern));
645
+ }
646
+ function globMatch(value, pattern) {
647
+ const escaped = pattern
648
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
649
+ .replace(/\*/g, ".*")
650
+ .replace(/\?/g, ".");
651
+ return new RegExp(`^${escaped}$`, "i").test(value);
652
+ }
653
+ function sha256(value) {
654
+ return createHash("sha256").update(value).digest("hex");
655
+ }
656
+ function looksLikePaymentCredential(value) {
657
+ return /\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\b/.test(value);
658
+ }
659
+ function looksLikeSessionCookie(value) {
660
+ return value.length >= 32 && /[A-Za-z0-9+/=_-]{32,}/.test(value);
661
+ }
662
+ function isRecord(value) {
663
+ return typeof value === "object" && value !== null && !Array.isArray(value);
664
+ }
665
+ //# sourceMappingURL=index.js.map