open-multi-agent-kit 0.80.8 → 0.90.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.
- package/CHANGELOG.md +4 -0
- package/README.md +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/automation/index.d.ts +359 -0
- package/dist/core/automation/index.d.ts.map +1 -0
- package/dist/core/automation/index.js +665 -0
- package/dist/core/automation/index.js.map +1 -0
- package/dist/core/browser-use.d.ts +8 -0
- package/dist/core/browser-use.d.ts.map +1 -1
- package/dist/core/browser-use.js +61 -23
- package/dist/core/browser-use.js.map +1 -1
- package/dist/core/diagnostics.d.ts +2 -0
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/diagnostics.js.map +1 -1
- package/dist/core/extensions/builtin/todo-checklist.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todo-checklist.js +3 -0
- package/dist/core/extensions/builtin/todo-checklist.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +3 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +4 -0
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/pi-package-intake-candidates.d.ts +21 -0
- package/dist/core/pi-package-intake-candidates.d.ts.map +1 -0
- package/dist/core/pi-package-intake-candidates.js +109 -0
- package/dist/core/pi-package-intake-candidates.js.map +1 -0
- package/dist/core/pi-package-intake.d.ts +43 -0
- package/dist/core/pi-package-intake.d.ts.map +1 -0
- package/dist/core/pi-package-intake.js +122 -0
- package/dist/core/pi-package-intake.js.map +1 -0
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +1 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/skills.d.ts +4 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +115 -43
- package/dist/core/skills.js.map +1 -1
- package/dist/core/todo-runtime-state.d.ts +5 -0
- package/dist/core/todo-runtime-state.d.ts.map +1 -0
- package/dist/core/todo-runtime-state.js +12 -0
- package/dist/core/todo-runtime-state.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-layout.d.ts +8 -1
- package/dist/modes/interactive/components/control-panel-layout.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-layout.js +48 -16
- package/dist/modes/interactive/components/control-panel-layout.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.d.ts +2 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.js +10 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.js.map +1 -1
- package/dist/modes/interactive/components/control-panel.d.ts +1 -0
- package/dist/modes/interactive/components/control-panel.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel.js +15 -3
- package/dist/modes/interactive/components/control-panel.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +6 -0
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +3 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/docs/providers.md +12 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/automation/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile, stat } from \"node:fs/promises\";\n\nexport type RiskLevel = \"R0\" | \"R1\" | \"R2\" | \"R3\";\n\nexport type Capability =\n\t| \"fs.read\"\n\t| \"fs.write\"\n\t| \"process.exec\"\n\t| \"network.read\"\n\t| \"network.write\"\n\t| \"browser.observe\"\n\t| \"browser.mutate\"\n\t| \"browser.credentialed\"\n\t| \"mcp.call\"\n\t| \"extension.run\"\n\t| \"api.call\"\n\t| \"secrets.resolve\"\n\t| \"subagent.spawn\";\n\nexport type EnvMode = \"secret-ref-only\" | \"passthrough-audited\" | \"passthrough-full\";\nexport type Sensitivity = \"public\" | \"internal\" | \"credential\" | \"payment\" | \"session\" | \"admin\";\nexport type ApiMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport interface AutonomyProfile {\n\tid: \"autopilot-max\" | \"trusted-dev\" | \"ci-agent\" | \"public-safe\";\n\thumanPromptBudget: { maxPromptsPerTask: number; maxPromptRate: number };\n\tcapabilities: Capability[];\n\tenv: {\n\t\tmode: EnvMode;\n\t\tallowPatterns: string[];\n\t\tdenyPatterns: string[];\n\t\tredactPatterns: string[];\n\t\texposeToModel: false;\n\t};\n\tapi: {\n\t\tallowOrigins: string[];\n\t\tallowMethods: ApiMethod[];\n\t\tmutationDefault: \"auto\";\n\t\trequireIdempotencyForMethods: ApiMethod[];\n\t};\n\tbrowser: {\n\t\tpersistentProfile: boolean;\n\t\tcredentialedSessions: boolean;\n\t\tautoSubmit: boolean;\n\t\tautoDownload: boolean;\n\t\tmaxUnknownOutcomeReconciliations: number;\n\t};\n\tverification: {\n\t\tminVerifiabilityByRisk: Record<RiskLevel, number>;\n\t\trequireEvidenceByRisk: Record<RiskLevel, boolean>;\n\t\trequirePostconditionsByRisk: Record<RiskLevel, boolean>;\n\t};\n\trecovery: {\n\t\tautoRetry: boolean;\n\t\tautoRollback: boolean;\n\t\tautoCompensate: boolean;\n\t\tduplicateMutationSuppression: boolean;\n\t};\n\tbudgets: {\n\t\tmaxWallClockMs: number;\n\t\tmaxToolCalls: number;\n\t\tmaxBrowserActions: number;\n\t\tmaxNetworkCalls: number;\n\t\tmaxCostUsd: number;\n\t\triskBudget: Record<RiskLevel, number>;\n\t};\n}\n\nexport const AUTOPILOT_MAX: AutonomyProfile = {\n\tid: \"autopilot-max\",\n\thumanPromptBudget: { maxPromptsPerTask: 0, maxPromptRate: 0 },\n\tcapabilities: [\n\t\t\"fs.read\",\n\t\t\"fs.write\",\n\t\t\"process.exec\",\n\t\t\"network.read\",\n\t\t\"network.write\",\n\t\t\"browser.observe\",\n\t\t\"browser.mutate\",\n\t\t\"browser.credentialed\",\n\t\t\"mcp.call\",\n\t\t\"extension.run\",\n\t\t\"api.call\",\n\t\t\"secrets.resolve\",\n\t\t\"subagent.spawn\",\n\t],\n\tenv: {\n\t\tmode: \"passthrough-audited\",\n\t\tallowPatterns: [\"*\"],\n\t\tdenyPatterns: [],\n\t\tredactPatterns: [\n\t\t\t\"*KEY*\",\n\t\t\t\"*TOKEN*\",\n\t\t\t\"*SECRET*\",\n\t\t\t\"*PASSWORD*\",\n\t\t\t\"AWS_*\",\n\t\t\t\"GCP_*\",\n\t\t\t\"AZURE_*\",\n\t\t\t\"OPENAI_*\",\n\t\t\t\"ANTHROPIC_*\",\n\t\t\t\"GITHUB_*\",\n\t\t\t\"NPM_*\",\n\t\t],\n\t\texposeToModel: false,\n\t},\n\tapi: {\n\t\tallowOrigins: [\"*\"],\n\t\tallowMethods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"],\n\t\tmutationDefault: \"auto\",\n\t\trequireIdempotencyForMethods: [\"POST\", \"PUT\", \"PATCH\", \"DELETE\"],\n\t},\n\tbrowser: {\n\t\tpersistentProfile: true,\n\t\tcredentialedSessions: true,\n\t\tautoSubmit: true,\n\t\tautoDownload: true,\n\t\tmaxUnknownOutcomeReconciliations: 5,\n\t},\n\tverification: {\n\t\tminVerifiabilityByRisk: { R0: 0.1, R1: 0.25, R2: 0.45, R3: 0.65 },\n\t\trequireEvidenceByRisk: { R0: false, R1: true, R2: true, R3: true },\n\t\trequirePostconditionsByRisk: { R0: false, R1: true, R2: true, R3: true },\n\t},\n\trecovery: {\n\t\tautoRetry: true,\n\t\tautoRollback: true,\n\t\tautoCompensate: true,\n\t\tduplicateMutationSuppression: true,\n\t},\n\tbudgets: {\n\t\tmaxWallClockMs: 30 * 60 * 1000,\n\t\tmaxToolCalls: 500,\n\t\tmaxBrowserActions: 250,\n\t\tmaxNetworkCalls: 1000,\n\t\tmaxCostUsd: 10,\n\t\triskBudget: { R0: 10000, R1: 2000, R2: 500, R3: 100 },\n\t},\n};\n\nexport interface EnvRecord {\n\tkey: string;\n\tvalue: string;\n\tsensitivity: Sensitivity;\n\tsource: \"process\" | \"profile\" | \"workspace\" | \"task\" | \"tool\";\n\tfingerprint: string;\n}\n\nexport interface EnvUseEvent {\n\tactionId: string;\n\ttoolId: string;\n\tkey: string;\n\tsensitivity: Sensitivity;\n\tfingerprint: string;\n\tpurpose: string;\n\tpassedToProcess: boolean;\n\texposedToModel: false;\n\ttimestamp: string;\n}\n\nexport interface EnvResolutionRequest {\n\tactionId: string;\n\ttoolId: string;\n\tpurpose: string;\n\tprofile: AutonomyProfile;\n\trequestedKeys?: string[];\n\trequestedPatterns?: string[];\n\textraEnv?: Record<string, string>;\n}\n\nexport interface EnvBrokerLedger {\n\tappend(event: EnvUseEvent): Promise<unknown>;\n}\n\nexport class EnvBroker {\n\tprivate readonly processEnv: Record<string, string | undefined>;\n\tprivate readonly ledger: EnvBrokerLedger;\n\n\tconstructor(args: { processEnv: Record<string, string | undefined>; ledger: EnvBrokerLedger }) {\n\t\tthis.processEnv = args.processEnv;\n\t\tthis.ledger = args.ledger;\n\t}\n\n\tasync createChildEnv(req: EnvResolutionRequest): Promise<Record<string, string>> {\n\t\tconst selected = this.collect(req).filter((record) => this.isAllowed(record, req));\n\t\tconst childEnv: Record<string, string> = {};\n\t\tfor (const record of selected) {\n\t\t\tchildEnv[record.key] = record.value;\n\t\t\tawait this.ledger.append({\n\t\t\t\tactionId: req.actionId,\n\t\t\t\ttoolId: req.toolId,\n\t\t\t\tkey: record.key,\n\t\t\t\tsensitivity: record.sensitivity,\n\t\t\t\tfingerprint: record.fingerprint,\n\t\t\t\tpurpose: req.purpose,\n\t\t\t\tpassedToProcess: true,\n\t\t\t\texposedToModel: false,\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t});\n\t\t}\n\t\treturn childEnv;\n\t}\n\n\tredactEnvForModel(env: Record<string, string>): Record<string, string> {\n\t\tconst out: Record<string, string> = {};\n\t\tfor (const [key, value] of Object.entries(env)) {\n\t\t\tconst sensitivity = classifyEnvKey(key, value);\n\t\t\tout[key] = sensitivity === \"public\" ? value : `[REDACTED:${sha256(value).slice(0, 12)}]`;\n\t\t}\n\t\treturn out;\n\t}\n\n\tprivate collect(req: EnvResolutionRequest): EnvRecord[] {\n\t\tconst records: EnvRecord[] = [];\n\t\tfor (const [key, value] of Object.entries(this.processEnv)) {\n\t\t\tif (typeof value !== \"string\") continue;\n\t\t\trecords.push({\n\t\t\t\tkey,\n\t\t\t\tvalue,\n\t\t\t\tsensitivity: classifyEnvKey(key, value),\n\t\t\t\tsource: \"process\",\n\t\t\t\tfingerprint: sha256(value),\n\t\t\t});\n\t\t}\n\t\tfor (const [key, value] of Object.entries(req.extraEnv ?? {})) {\n\t\t\trecords.push({\n\t\t\t\tkey,\n\t\t\t\tvalue,\n\t\t\t\tsensitivity: classifyEnvKey(key, value),\n\t\t\t\tsource: \"tool\",\n\t\t\t\tfingerprint: sha256(value),\n\t\t\t});\n\t\t}\n\t\treturn records;\n\t}\n\n\tprivate isAllowed(record: EnvRecord, req: EnvResolutionRequest): boolean {\n\t\tif (req.profile.env.mode === \"passthrough-full\") return true;\n\t\tif (req.profile.env.mode === \"secret-ref-only\" && record.sensitivity !== \"public\") return false;\n\t\tconst allowedByPattern = matchesAny(record.key, req.profile.env.allowPatterns);\n\t\tconst deniedByPattern = matchesAny(record.key, req.profile.env.denyPatterns);\n\t\tif (deniedByPattern || !allowedByPattern) return false;\n\t\tif (req.requestedKeys?.includes(record.key)) return true;\n\t\tif (req.requestedPatterns?.some((pattern) => globMatch(record.key, pattern))) return true;\n\t\treturn req.profile.env.allowPatterns.includes(\"*\");\n\t}\n}\n\nexport type EvidenceActor = \"agent\" | \"tool\" | \"browser\" | \"extension-host\" | \"mcp\" | \"api\" | \"verifier\" | \"recovery\";\nexport type EvidenceOutcome =\n\t| \"planned\"\n\t| \"executed\"\n\t| \"verified\"\n\t| \"failed_before_commit\"\n\t| \"unknown_after_dispatch\"\n\t| \"reconciled\"\n\t| \"compensated\";\n\nexport interface EvidenceEvent {\n\tsequence: number;\n\tpreviousHash: string;\n\teventHash: string;\n\ttimestamp: string;\n\tsessionId: string;\n\ttaskId: string;\n\tactionId?: string;\n\tactor: EvidenceActor;\n\tkind: string;\n\tinputHash?: string;\n\toutputHash?: string;\n\tredactedOutputHash?: string;\n\tenvUseHash?: string;\n\tpolicyHash?: string;\n\tprofileHash?: string;\n\tschemaHash?: string;\n\toutcome?: EvidenceOutcome;\n}\n\nexport type EvidenceEventInput = Omit<\n\tEvidenceEvent,\n\t\"sequence\" | \"previousHash\" | \"eventHash\" | \"timestamp\" | \"sessionId\" | \"taskId\"\n>;\n\nexport class EvidenceLedger {\n\tprivate readonly sessionId: string;\n\tprivate readonly taskId: string;\n\tprivate readonly events: EvidenceEvent[] = [];\n\tprivate previousHash = \"genesis\";\n\n\tconstructor(args: { sessionId: string; taskId: string }) {\n\t\tthis.sessionId = args.sessionId;\n\t\tthis.taskId = args.taskId;\n\t}\n\n\tasync append(event: EvidenceEventInput): Promise<EvidenceEvent> {\n\t\tconst fullWithoutHash = {\n\t\t\t...event,\n\t\t\tsequence: this.events.length + 1,\n\t\t\tpreviousHash: this.previousHash,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tsessionId: this.sessionId,\n\t\t\ttaskId: this.taskId,\n\t\t};\n\t\tconst eventHash = canonicalHash(fullWithoutHash);\n\t\tconst full: EvidenceEvent = { ...fullWithoutHash, eventHash };\n\t\tthis.events.push(full);\n\t\tthis.previousHash = eventHash;\n\t\treturn full;\n\t}\n\n\tsnapshot(): EvidenceEvent[] {\n\t\treturn this.events.map((event) => ({ ...event }));\n\t}\n}\n\nexport type Postcondition =\n\t| { kind: \"url\"; origin?: string; path?: string; pattern?: string }\n\t| { kind: \"text\"; exact?: string; pattern?: string }\n\t| { kind: \"element-visible\"; ref?: string; role?: string; name?: string }\n\t| { kind: \"element-value\"; ref: string; expected: string }\n\t| { kind: \"api-status\"; status: number }\n\t| { kind: \"api-json\"; jsonPath: string; expected: unknown }\n\t| { kind: \"file-exists\"; path: string; sha256?: string }\n\t| { kind: \"download\"; path: string; sha256?: string; mimeType?: string }\n\t| { kind: \"receipt\"; idPattern: string }\n\t| { kind: \"database\"; queryId: string; expectedHash: string };\n\nexport interface VerificationContext {\n\tcurrentUrl?: string;\n\ttext?: string;\n\telements?: Array<{ ref?: string; role?: string; name?: string; value?: string; visible?: boolean }>;\n\tapiStatus?: number;\n\tapiBody?: unknown;\n\treceiptId?: string;\n\tdatabaseHashes?: Record<string, string>;\n}\n\nexport interface EvidencePointer {\n\tkind: string;\n\tdescription: string;\n\tsha256?: string;\n}\n\nexport interface VerificationResult {\n\tpass: boolean;\n\tconfidence: number;\n\tevidencePointers: EvidencePointer[];\n\tfailures: string[];\n\treceiptId?: string;\n}\n\nexport class PostconditionVerifier {\n\tasync verify(conditions: Postcondition[], ctx: VerificationContext): Promise<VerificationResult> {\n\t\tif (conditions.length === 0) {\n\t\t\treturn { pass: false, confidence: 0, evidencePointers: [], failures: [\"no postconditions\"] };\n\t\t}\n\t\tconst results: VerificationResult[] = [];\n\t\tfor (const condition of conditions) {\n\t\t\tresults.push(await this.verifyOne(condition, ctx));\n\t\t}\n\t\treturn {\n\t\t\tpass: results.every((result) => result.pass),\n\t\t\tconfidence: Math.min(...results.map((result) => result.confidence)),\n\t\t\tevidencePointers: results.flatMap((result) => result.evidencePointers),\n\t\t\tfailures: results.flatMap((result) => result.failures),\n\t\t\treceiptId: results.find((result) => result.receiptId)?.receiptId,\n\t\t};\n\t}\n\n\tprivate async verifyOne(condition: Postcondition, ctx: VerificationContext): Promise<VerificationResult> {\n\t\tswitch (condition.kind) {\n\t\t\tcase \"api-status\":\n\t\t\t\treturn booleanResult(ctx.apiStatus === condition.status, \"api-status\", `status ${condition.status}`);\n\t\t\tcase \"api-json\": {\n\t\t\t\tconst actual = readJsonPath(ctx.apiBody, condition.jsonPath);\n\t\t\t\treturn booleanResult(deepEqual(actual, condition.expected), \"api-json\", condition.jsonPath);\n\t\t\t}\n\t\t\tcase \"text\": {\n\t\t\t\tconst text = ctx.text ?? \"\";\n\t\t\t\tconst pass =\n\t\t\t\t\tcondition.exact !== undefined\n\t\t\t\t\t\t? text.includes(condition.exact)\n\t\t\t\t\t\t: condition.pattern !== undefined && new RegExp(condition.pattern).test(text);\n\t\t\t\treturn booleanResult(pass, \"text\", condition.exact ?? condition.pattern ?? \"<missing>\");\n\t\t\t}\n\t\t\tcase \"url\": {\n\t\t\t\tconst currentUrl = ctx.currentUrl;\n\t\t\t\tif (typeof currentUrl !== \"string\") {\n\t\t\t\t\treturn booleanResult(false, \"url\", \"<missing>\");\n\t\t\t\t}\n\t\t\t\tconst parsedUrl = new URL(currentUrl);\n\t\t\t\tlet pass = true;\n\t\t\t\tif (condition.origin) pass = parsedUrl.origin === condition.origin;\n\t\t\t\tif (pass && condition.path) pass = parsedUrl.pathname === condition.path;\n\t\t\t\tif (pass && condition.pattern) pass = new RegExp(condition.pattern).test(currentUrl);\n\t\t\t\treturn booleanResult(pass, \"url\", currentUrl ?? \"<missing>\");\n\t\t\t}\n\t\t\tcase \"file-exists\":\n\t\t\t\treturn verifyFile(condition.path, condition.sha256, \"file-exists\");\n\t\t\tcase \"download\":\n\t\t\t\treturn verifyFile(condition.path, condition.sha256, \"download\");\n\t\t\tcase \"receipt\": {\n\t\t\t\tconst receiptId = ctx.receiptId;\n\t\t\t\tconst pass = typeof receiptId === \"string\" && new RegExp(condition.idPattern).test(receiptId);\n\t\t\t\treturn { ...booleanResult(pass, \"receipt\", receiptId ?? \"<missing>\"), receiptId };\n\t\t\t}\n\t\t\tcase \"database\": {\n\t\t\t\tconst actualHash = ctx.databaseHashes?.[condition.queryId];\n\t\t\t\treturn booleanResult(actualHash === condition.expectedHash, \"database\", condition.queryId);\n\t\t\t}\n\t\t\tcase \"element-visible\": {\n\t\t\t\tconst pass = (ctx.elements ?? []).some(\n\t\t\t\t\t(element) =>\n\t\t\t\t\t\telement.visible === true &&\n\t\t\t\t\t\t(condition.ref === undefined || element.ref === condition.ref) &&\n\t\t\t\t\t\t(condition.role === undefined || element.role === condition.role) &&\n\t\t\t\t\t\t(condition.name === undefined || element.name === condition.name),\n\t\t\t\t);\n\t\t\t\treturn booleanResult(pass, \"element-visible\", condition.ref ?? condition.role ?? condition.name ?? \"<any>\");\n\t\t\t}\n\t\t\tcase \"element-value\": {\n\t\t\t\tconst pass = (ctx.elements ?? []).some(\n\t\t\t\t\t(element) => element.ref === condition.ref && element.value === condition.expected,\n\t\t\t\t);\n\t\t\t\treturn booleanResult(pass, \"element-value\", condition.ref);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport interface ApiAction {\n\tactionId: string;\n\tmethod: ApiMethod;\n\turl: string;\n\theaders: Record<string, string>;\n\tbody?: unknown;\n\tcredentialRefs: string[];\n\texpectedPostconditions: Postcondition[];\n\tidempotencyKey?: string;\n}\n\nexport interface ApiOutcome {\n\tkind: \"succeeded\" | \"failed_before_commit\" | \"succeeded_unverified\" | \"unknown_after_dispatch\";\n\tstatus?: number;\n\tbodyHash?: string;\n\treceiptId?: string;\n\tredactedBody?: unknown;\n}\n\nexport interface BrokerFetchRequest {\n\tmethod: ApiMethod;\n\theaders: Record<string, string>;\n\tbody?: string;\n\tsignal?: AbortSignal;\n}\n\nexport interface BrokerFetchResponse {\n\tstatus: number;\n\tjson(): Promise<unknown>;\n\ttext(): Promise<string>;\n}\n\nexport type BrokerFetcher = (url: string, init: BrokerFetchRequest) => Promise<BrokerFetchResponse>;\n\nexport class ApiBroker {\n\tprivate readonly ledger: EvidenceLedger;\n\tprivate readonly verifier: PostconditionVerifier;\n\tprivate readonly fetcher: BrokerFetcher;\n\n\tconstructor(args: { ledger: EvidenceLedger; verifier: PostconditionVerifier; fetcher?: BrokerFetcher }) {\n\t\tthis.ledger = args.ledger;\n\t\tthis.verifier = args.verifier;\n\t\tthis.fetcher = args.fetcher ?? defaultFetcher;\n\t}\n\n\tasync execute(\n\t\taction: ApiAction,\n\t\tctx: { signal?: AbortSignal; profile?: AutonomyProfile } = {},\n\t): Promise<ApiOutcome> {\n\t\tconst idempotencyKey = action.idempotencyKey ?? deriveIdempotencyKey(action);\n\t\tconst headers = { ...action.headers, \"Idempotency-Key\": idempotencyKey, \"X-OMK-Action-Id\": action.actionId };\n\t\tawait this.ledger.append({\n\t\t\tactor: \"api\",\n\t\t\tkind: \"api.dispatch.planned\",\n\t\t\tactionId: action.actionId,\n\t\t\tinputHash: canonicalHash({ method: action.method, url: action.url, headers, body: action.body }),\n\t\t\toutcome: \"planned\",\n\t\t});\n\n\t\tlet response: BrokerFetchResponse;\n\t\ttry {\n\t\t\tresponse = await this.fetcher(action.url, {\n\t\t\t\tmethod: action.method,\n\t\t\t\theaders,\n\t\t\t\tbody: action.body === undefined ? undefined : JSON.stringify(action.body),\n\t\t\t\tsignal: ctx.signal,\n\t\t\t});\n\t\t} catch {\n\t\t\treturn this.reconcileUnknown(action, idempotencyKey, ctx.profile ?? AUTOPILOT_MAX);\n\t\t}\n\n\t\tconst rawBody = await safeReadJsonOrText(response);\n\t\tconst redactedBody = redactForModel(rawBody);\n\t\tawait this.ledger.append({\n\t\t\tactor: \"api\",\n\t\t\tkind: \"api.response\",\n\t\t\tactionId: action.actionId,\n\t\t\toutputHash: canonicalHash(rawBody),\n\t\t\tredactedOutputHash: canonicalHash(redactedBody),\n\t\t\toutcome: \"executed\",\n\t\t});\n\t\tconst verification = await this.verifier.verify(action.expectedPostconditions, {\n\t\t\tapiStatus: response.status,\n\t\t\tapiBody: rawBody,\n\t\t\treceiptId: readReceiptId(rawBody),\n\t\t});\n\t\tif (!verification.pass) {\n\t\t\treturn {\n\t\t\t\tkind: \"succeeded_unverified\",\n\t\t\t\tstatus: response.status,\n\t\t\t\tbodyHash: canonicalHash(rawBody),\n\t\t\t\tredactedBody,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tkind: \"succeeded\",\n\t\t\tstatus: response.status,\n\t\t\tbodyHash: canonicalHash(rawBody),\n\t\t\treceiptId: verification.receiptId,\n\t\t\tredactedBody,\n\t\t};\n\t}\n\n\tprivate async reconcileUnknown(\n\t\taction: ApiAction,\n\t\tidempotencyKey: string,\n\t\tprofile: AutonomyProfile,\n\t): Promise<ApiOutcome> {\n\t\tfor (let attempt = 0; attempt < profile.browser.maxUnknownOutcomeReconciliations; attempt++) {\n\t\t\tconst verification = await this.verifier.verify(action.expectedPostconditions, { receiptId: idempotencyKey });\n\t\t\tif (verification.pass) {\n\t\t\t\tawait this.ledger.append({\n\t\t\t\t\tactor: \"recovery\",\n\t\t\t\t\tkind: \"api.unknown.reconciled\",\n\t\t\t\t\tactionId: action.actionId,\n\t\t\t\t\toutcome: \"reconciled\",\n\t\t\t\t});\n\t\t\t\treturn { kind: \"succeeded\", receiptId: verification.receiptId };\n\t\t\t}\n\t\t}\n\t\tawait this.ledger.append({\n\t\t\tactor: \"recovery\",\n\t\t\tkind: \"api.unknown.unresolved\",\n\t\t\tactionId: action.actionId,\n\t\t\toutcome: \"unknown_after_dispatch\",\n\t\t});\n\t\treturn { kind: \"unknown_after_dispatch\" };\n\t}\n}\n\nexport interface ExecutionStrategy {\n\texecute: boolean;\n\trequirePostcondition: boolean;\n\trequireIdempotency: boolean;\n\trecovery: \"retry\" | \"repair\" | \"reconcile-and-compensate\";\n\tevidenceDepth: \"minimal\" | \"normal\" | \"deep\" | \"forensic\";\n}\n\nexport function strategyForRisk(risk: RiskLevel): ExecutionStrategy {\n\tif (risk === \"R0\") {\n\t\treturn {\n\t\t\texecute: true,\n\t\t\trequirePostcondition: false,\n\t\t\trequireIdempotency: false,\n\t\t\trecovery: \"retry\",\n\t\t\tevidenceDepth: \"minimal\",\n\t\t};\n\t}\n\tif (risk === \"R1\") {\n\t\treturn {\n\t\t\texecute: true,\n\t\t\trequirePostcondition: true,\n\t\t\trequireIdempotency: false,\n\t\t\trecovery: \"retry\",\n\t\t\tevidenceDepth: \"normal\",\n\t\t};\n\t}\n\tif (risk === \"R2\") {\n\t\treturn {\n\t\t\texecute: true,\n\t\t\trequirePostcondition: true,\n\t\t\trequireIdempotency: true,\n\t\t\trecovery: \"repair\",\n\t\t\tevidenceDepth: \"deep\",\n\t\t};\n\t}\n\treturn {\n\t\texecute: true,\n\t\trequirePostcondition: true,\n\t\trequireIdempotency: true,\n\t\trecovery: \"reconcile-and-compensate\",\n\t\tevidenceDepth: \"forensic\",\n\t};\n}\n\nexport interface ToolExecutionNeed {\n\tactionId: string;\n\trequiredCapability: Capability;\n\trisk: RiskLevel;\n\trequiredPostconditions: Postcondition[];\n\tcontextFingerprint?: string;\n}\n\nexport interface ToolExecutionCandidate {\n\ttoolId: string;\n\tcapability: Capability;\n\tschemaHash: string;\n\treliability: number;\n\tverificationStrength: number;\n\tavgLatencyMs: number;\n\tcostUsd: number;\n\tsupportsIdempotency: boolean;\n\tenabled: boolean;\n\tcontextFingerprint?: string;\n}\n\nexport interface ToolExecutionChoice {\n\tcandidate: ToolExecutionCandidate;\n\tscore: number;\n\tstrategy: ExecutionStrategy;\n\treasons: string[];\n}\n\nexport class DynamicToolPortfolioOptimizer {\n\trank(candidates: ToolExecutionCandidate[], need: ToolExecutionNeed): ToolExecutionChoice[] {\n\t\treturn candidates\n\t\t\t.filter((candidate) => candidate.enabled && candidate.capability === need.requiredCapability)\n\t\t\t.map((candidate) => this.scoreCandidate(candidate, need))\n\t\t\t.sort((left, right) => right.score - left.score);\n\t}\n\n\tscoreCandidate(candidate: ToolExecutionCandidate, need: ToolExecutionNeed): ToolExecutionChoice {\n\t\tconst strategy = strategyForRisk(need.risk);\n\t\tconst contextMatch =\n\t\t\tneed.contextFingerprint === undefined || candidate.contextFingerprint === need.contextFingerprint ? 1 : 0;\n\t\tconst idempotency = !strategy.requireIdempotency || candidate.supportsIdempotency ? 1 : 0;\n\t\tconst latency = Math.max(0, 1 - candidate.avgLatencyMs / 30000);\n\t\tconst cost = Math.max(0, 1 - candidate.costUsd / Math.max(1, AUTOPILOT_MAX.budgets.maxCostUsd));\n\t\tconst postconditionCoverage = need.requiredPostconditions.length > 0 ? candidate.verificationStrength : 1;\n\t\tconst score =\n\t\t\t0.32 * candidate.reliability +\n\t\t\t0.26 * postconditionCoverage +\n\t\t\t0.16 * idempotency +\n\t\t\t0.12 * contextMatch +\n\t\t\t0.08 * latency +\n\t\t\t0.06 * cost;\n\t\treturn {\n\t\t\tcandidate,\n\t\t\tscore: Number(score.toFixed(4)),\n\t\t\tstrategy,\n\t\t\treasons: [\n\t\t\t\t`reliability=${candidate.reliability}`,\n\t\t\t\t`verification=${postconditionCoverage}`,\n\t\t\t\t`idempotency=${idempotency}`,\n\t\t\t\t`context=${contextMatch}`,\n\t\t\t],\n\t\t};\n\t}\n}\n\nexport class ToolExecutionBroker {\n\tprivate readonly ledger: EvidenceLedger;\n\tprivate readonly profile: AutonomyProfile;\n\tprivate readonly optimizer: DynamicToolPortfolioOptimizer;\n\n\tconstructor(args: {\n\t\tledger: EvidenceLedger;\n\t\tprofile?: AutonomyProfile;\n\t\toptimizer?: DynamicToolPortfolioOptimizer;\n\t}) {\n\t\tthis.ledger = args.ledger;\n\t\tthis.profile = args.profile ?? AUTOPILOT_MAX;\n\t\tthis.optimizer = args.optimizer ?? new DynamicToolPortfolioOptimizer();\n\t}\n\n\tasync select(need: ToolExecutionNeed, candidates: ToolExecutionCandidate[]): Promise<ToolExecutionChoice> {\n\t\tconst choices = this.optimizer.rank(candidates, need);\n\t\tconst choice = choices[0];\n\t\tif (choice === undefined) {\n\t\t\tthrow new Error(`No enabled tool candidate for ${need.requiredCapability}`);\n\t\t}\n\t\tawait this.ledger.append({\n\t\t\tactor: \"tool\",\n\t\t\tkind: \"tool.execution.planned\",\n\t\t\tactionId: need.actionId,\n\t\t\tinputHash: canonicalHash(need),\n\t\t\tpolicyHash: canonicalHash(this.profile),\n\t\t\tschemaHash: choice.candidate.schemaHash,\n\t\t\toutcome: \"planned\",\n\t\t});\n\t\treturn choice;\n\t}\n\n\tasync recordResult(choice: ToolExecutionChoice, result: VerificationResult): Promise<EvidenceEvent> {\n\t\treturn this.ledger.append({\n\t\t\tactor: \"tool\",\n\t\t\tkind: \"tool.execution.result\",\n\t\t\tactionId: choice.candidate.toolId,\n\t\t\toutputHash: canonicalHash(result),\n\t\t\tschemaHash: choice.candidate.schemaHash,\n\t\t\toutcome: result.pass ? \"verified\" : \"unknown_after_dispatch\",\n\t\t});\n\t}\n}\n\nexport interface AutomationTraceAction {\n\tkind: \"tool\" | \"browser\" | \"api\" | \"mcp\" | \"extension\";\n\tverificationPass: boolean;\n\tschemaHashMatched?: boolean;\n\tenvUseLedgered?: boolean;\n\ttargetFingerprintMatched?: boolean;\n\toutcome?: \"unknown_after_dispatch\" | \"succeeded\" | \"failed\";\n\treconciled?: boolean;\n}\n\nexport interface AutomationTraceEnvApiUse {\n\tledgered: boolean;\n\texposedToModel: boolean;\n\texposedToLogs: boolean;\n}\n\nexport interface AutomationTraceContextPlan {\n\trenderedTokens: number;\n\tresourceBudget: number;\n\tplanHash: string;\n\trenderedHashLinkedPlanHash: string;\n\toutputReserveCountedOnce: boolean;\n}\n\nexport interface AutomationTrace {\n\tactions: AutomationTraceAction[];\n\tverifications: Array<{ conditionHash: string; pass: boolean }>;\n\thumanPrompts: number;\n\tenvApiUses: AutomationTraceEnvApiUse[];\n\tfailures: number;\n\tunknownOutcomes: number;\n\trecoveredFailures: number;\n\treconciledUnknowns: number;\n\tsecretLeaks: number;\n\tduplicateIrreversibleMutations: number;\n\tunledgeredEnvUses: number;\n\treplayMatches: boolean;\n\tcontextPlans: AutomationTraceContextPlan[];\n}\n\nexport interface AutomationHarnessScoreInput {\n\trequiredPostconditions: Postcondition[];\n\ttrace: AutomationTrace;\n}\n\nexport interface AutomationScoreBreakdown {\n\tscore: number;\n\tverifiedSuccess: boolean;\n\tenvApiUseCorrectness: number;\n\tduplicateMutations: number;\n\tsecretLeaks: number;\n\tcritical: boolean;\n}\n\nexport class AutomationHarnessScorer {\n\tscore(input: AutomationHarnessScoreInput): AutomationScoreBreakdown {\n\t\tconst verifiedSuccess = this.verifiedSuccess(input);\n\t\tconst autonomy = 1 - input.trace.humanPrompts / Math.max(1, input.trace.actions.length);\n\t\tconst toolUse = this.toolUseScore(input.trace);\n\t\tconst browserUse = this.browserUseScore(input.trace);\n\t\tconst envApi = this.envApiScore(input.trace);\n\t\tconst recovery = this.recoveryScore(input.trace);\n\t\tconst determinism = input.trace.replayMatches ? 1 : 0;\n\t\tconst context = this.contextScore(input.trace);\n\t\tconst critical =\n\t\t\tinput.trace.secretLeaks > 0 ||\n\t\t\tinput.trace.duplicateIrreversibleMutations > 0 ||\n\t\t\t(input.requiredPostconditions.length > 0 && verifiedSuccess < 1) ||\n\t\t\t!input.trace.replayMatches ||\n\t\t\tinput.trace.unledgeredEnvUses > 0 ||\n\t\t\tinput.trace.envApiUses.some((use) => !use.ledgered) ||\n\t\t\tinput.trace.actions.some(\n\t\t\t\t(action) =>\n\t\t\t\t\taction.schemaHashMatched === false ||\n\t\t\t\t\t(action.kind === \"browser\" && action.targetFingerprintMatched === false),\n\t\t\t);\n\t\tconst raw =\n\t\t\t20 * verifiedSuccess +\n\t\t\t15 * autonomy +\n\t\t\t15 * toolUse +\n\t\t\t15 * browserUse +\n\t\t\t10 * envApi +\n\t\t\t10 * recovery +\n\t\t\t10 * determinism +\n\t\t\t5 * context;\n\t\treturn {\n\t\t\tscore: critical ? Math.min(79, raw) : raw,\n\t\t\tverifiedSuccess: verifiedSuccess >= 0.93,\n\t\t\tenvApiUseCorrectness: envApi,\n\t\t\tduplicateMutations: input.trace.duplicateIrreversibleMutations,\n\t\t\tsecretLeaks: input.trace.secretLeaks,\n\t\t\tcritical,\n\t\t};\n\t}\n\n\tprivate verifiedSuccess(input: AutomationHarnessScoreInput): number {\n\t\tconst passed = input.requiredPostconditions.filter((condition) =>\n\t\t\tinput.trace.verifications.some(\n\t\t\t\t(verification) => verification.conditionHash === canonicalHash(condition) && verification.pass,\n\t\t\t),\n\t\t);\n\t\treturn passed.length / Math.max(1, input.requiredPostconditions.length);\n\t}\n\n\tprivate toolUseScore(trace: AutomationTrace): number {\n\t\tconst calls = trace.actions.filter((action) => action.kind === \"tool\");\n\t\tif (calls.length === 0) return 1;\n\t\tconst verified = calls.filter((action) => action.verificationPass).length;\n\t\tconst schemaStable = calls.filter((action) => action.schemaHashMatched === true).length;\n\t\tconst envLedgered = calls.filter((action) => action.envUseLedgered === true).length;\n\t\treturn (verified + schemaStable + envLedgered) / (3 * calls.length);\n\t}\n\n\tprivate browserUseScore(trace: AutomationTrace): number {\n\t\tconst actions = trace.actions.filter((action) => action.kind === \"browser\");\n\t\tif (actions.length === 0) return 1;\n\t\tconst verified = actions.filter((action) => action.verificationPass).length;\n\t\tconst targetStable = actions.filter((action) => action.targetFingerprintMatched === true).length;\n\t\tconst unknownResolved = actions.filter(\n\t\t\t(action) => action.outcome !== \"unknown_after_dispatch\" || action.reconciled === true,\n\t\t).length;\n\t\treturn (verified + targetStable + unknownResolved) / (3 * actions.length);\n\t}\n\n\tprivate envApiScore(trace: AutomationTrace): number {\n\t\tif (trace.envApiUses.length === 0) return 1;\n\t\tconst ledgered = trace.envApiUses.filter((use) => use.ledgered).length;\n\t\tconst notLeaked = trace.envApiUses.filter((use) => !use.exposedToModel && !use.exposedToLogs).length;\n\t\treturn (ledgered + notLeaked) / (2 * trace.envApiUses.length);\n\t}\n\n\tprivate recoveryScore(trace: AutomationTrace): number {\n\t\tconst failures = trace.failures + trace.unknownOutcomes;\n\t\tif (failures === 0) return 1;\n\t\treturn (trace.recoveredFailures + trace.reconciledUnknowns) / failures;\n\t}\n\n\tprivate contextScore(trace: AutomationTrace): number {\n\t\tif (trace.contextPlans.length === 0) return 1;\n\t\tconst valid = trace.contextPlans.filter(\n\t\t\t(plan) =>\n\t\t\t\tplan.renderedTokens <= plan.resourceBudget &&\n\t\t\t\tplan.planHash === plan.renderedHashLinkedPlanHash &&\n\t\t\t\tplan.outputReserveCountedOnce,\n\t\t).length;\n\t\treturn valid / trace.contextPlans.length;\n\t}\n}\n\nexport function classifyEnvKey(key: string, value: string): Sensitivity {\n\tconst normalizedKey = key.toUpperCase();\n\tif (\n\t\tnormalizedKey.includes(\"TOKEN\") ||\n\t\tnormalizedKey.includes(\"SECRET\") ||\n\t\tnormalizedKey.includes(\"PASSWORD\") ||\n\t\tnormalizedKey.includes(\"API_KEY\") ||\n\t\tnormalizedKey.endsWith(\"_KEY\") ||\n\t\tnormalizedKey.startsWith(\"AWS_\") ||\n\t\tnormalizedKey.startsWith(\"GCP_\") ||\n\t\tnormalizedKey.startsWith(\"AZURE_\") ||\n\t\tnormalizedKey.startsWith(\"OPENAI_\") ||\n\t\tnormalizedKey.startsWith(\"ANTHROPIC_\") ||\n\t\tnormalizedKey.startsWith(\"GITHUB_\") ||\n\t\tnormalizedKey.startsWith(\"NPM_\")\n\t) {\n\t\treturn \"credential\";\n\t}\n\tif (looksLikePaymentCredential(value)) return \"payment\";\n\tif (looksLikeSessionCookie(value)) return \"session\";\n\treturn \"public\";\n}\n\nexport function canonicalHash(value: unknown): string {\n\treturn sha256(stableStringify(value));\n}\n\nexport function redactForModel(value: unknown): unknown {\n\tif (typeof value === \"string\") return redactString(value);\n\tif (Array.isArray(value)) return value.map((item) => redactForModel(item));\n\tif (isRecord(value)) {\n\t\tconst out: Record<string, unknown> = {};\n\t\tfor (const [key, child] of Object.entries(value)) {\n\t\t\tout[key] =\n\t\t\t\tclassifyEnvKey(key, typeof child === \"string\" ? child : \"\") === \"public\"\n\t\t\t\t\t? redactForModel(child)\n\t\t\t\t\t: \"[REDACTED]\";\n\t\t}\n\t\treturn out;\n\t}\n\treturn value;\n}\n\nfunction booleanResult(pass: boolean, kind: string, description: string): VerificationResult {\n\treturn {\n\t\tpass,\n\t\tconfidence: pass ? 1 : 0,\n\t\tevidencePointers: pass ? [{ kind, description }] : [],\n\t\tfailures: pass ? [] : [`${kind} postcondition failed: ${description}`],\n\t};\n}\n\nasync function verifyFile(path: string, expectedHash: string | undefined, kind: string): Promise<VerificationResult> {\n\ttry {\n\t\tawait stat(path);\n\t\tconst content = await readFile(path);\n\t\tconst actualHash = createHash(\"sha256\").update(content).digest(\"hex\");\n\t\tconst pass = expectedHash === undefined || expectedHash === actualHash;\n\t\treturn {\n\t\t\tpass,\n\t\t\tconfidence: pass ? 1 : 0,\n\t\t\tevidencePointers: pass ? [{ kind, description: path, sha256: actualHash }] : [],\n\t\t\tfailures: pass ? [] : [`${kind} hash mismatch for ${path}`],\n\t\t};\n\t} catch {\n\t\treturn { pass: false, confidence: 0, evidencePointers: [], failures: [`${kind} missing: ${path}`] };\n\t}\n}\n\nfunction readJsonPath(value: unknown, path: string): unknown {\n\tif (path === \"$\") return value;\n\tif (!path.startsWith(\"$.\")) return undefined;\n\tlet current = value;\n\tfor (const segment of path.slice(2).split(\".\")) {\n\t\tif (!isRecord(current)) return undefined;\n\t\tcurrent = current[segment];\n\t}\n\treturn current;\n}\n\nfunction readReceiptId(value: unknown): string | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst receipt = value.receiptId ?? value.id;\n\treturn typeof receipt === \"string\" ? receipt : undefined;\n}\n\nasync function safeReadJsonOrText(response: BrokerFetchResponse): Promise<unknown> {\n\ttry {\n\t\treturn await response.json();\n\t} catch {\n\t\treturn response.text();\n\t}\n}\n\nfunction deriveIdempotencyKey(action: ApiAction): string {\n\treturn `omk-${canonicalHash({ method: action.method, url: action.url, body: action.body, actionId: action.actionId }).slice(0, 24)}`;\n}\n\nasync function defaultFetcher(url: string, init: BrokerFetchRequest): Promise<BrokerFetchResponse> {\n\tconst response = await fetch(url, init);\n\treturn {\n\t\tstatus: response.status,\n\t\tjson: () => response.json() as Promise<unknown>,\n\t\ttext: () => response.text(),\n\t};\n}\n\nfunction redactString(value: string): string {\n\treturn value\n\t\t.replace(/Bearer\\s+[A-Za-z0-9._~+/=-]{8,}/g, \"Bearer [REDACTED]\")\n\t\t.replace(/([?&]?(?:access_)?token=)[^&\\s]+/gi, \"$1[REDACTED]\")\n\t\t.replace(/((?:api[_-]?key|password|secret)=)[^&\\s]+/gi, \"$1[REDACTED]\");\n}\n\nfunction deepEqual(left: unknown, right: unknown): boolean {\n\treturn stableStringify(left) === stableStringify(right);\n}\n\nfunction stableStringify(value: unknown): string {\n\tif (value === null || typeof value !== \"object\") return JSON.stringify(value);\n\tif (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(\",\")}]`;\n\tconst record = value as Record<string, unknown>;\n\treturn `{${Object.keys(record)\n\t\t.sort()\n\t\t.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)\n\t\t.join(\",\")}}`;\n}\n\nfunction matchesAny(value: string, patterns: string[]): boolean {\n\treturn patterns.some((pattern) => pattern === \"*\" || globMatch(value, pattern));\n}\n\nfunction globMatch(value: string, pattern: string): boolean {\n\tconst escaped = pattern\n\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t.replace(/\\*/g, \".*\")\n\t\t.replace(/\\?/g, \".\");\n\treturn new RegExp(`^${escaped}$`, \"i\").test(value);\n}\n\nfunction sha256(value: string): string {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction looksLikePaymentCredential(value: string): boolean {\n\treturn /\\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\\b/.test(value);\n}\n\nfunction looksLikeSessionCookie(value: string): boolean {\n\treturn value.length >= 32 && /[A-Za-z0-9+/=_-]{32,}/.test(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { EventEmitter } from "events";
|
|
2
|
+
import { type Postcondition, type VerificationResult } from "./automation/index.ts";
|
|
2
3
|
export interface BrowserTask {
|
|
3
4
|
url: string;
|
|
4
5
|
task: string;
|
|
5
6
|
sessionId?: string;
|
|
7
|
+
postconditions?: Postcondition[];
|
|
6
8
|
}
|
|
7
9
|
export interface PageState {
|
|
8
10
|
url: string;
|
|
@@ -12,6 +14,9 @@ export interface PageState {
|
|
|
12
14
|
action: string;
|
|
13
15
|
fields: string[];
|
|
14
16
|
}[];
|
|
17
|
+
text?: string;
|
|
18
|
+
status?: number;
|
|
19
|
+
error?: string;
|
|
15
20
|
}
|
|
16
21
|
export interface BrowserUseResult {
|
|
17
22
|
success: boolean;
|
|
@@ -22,6 +27,8 @@ export interface BrowserUseResult {
|
|
|
22
27
|
safety: number;
|
|
23
28
|
overallScore: number;
|
|
24
29
|
screenshot?: string;
|
|
30
|
+
verification: VerificationResult;
|
|
31
|
+
repairsAttempted: number;
|
|
25
32
|
}
|
|
26
33
|
export declare class BrowserUseEngine extends EventEmitter {
|
|
27
34
|
navigate(url: string): Promise<PageState>;
|
|
@@ -37,6 +44,7 @@ export declare class BrowserUseAgent extends EventEmitter {
|
|
|
37
44
|
private engine;
|
|
38
45
|
private evaluator;
|
|
39
46
|
private sessions;
|
|
47
|
+
private verifier;
|
|
40
48
|
constructor();
|
|
41
49
|
execute(task: BrowserTask): Promise<BrowserUseResult>;
|
|
42
50
|
getSession(sessionId: string): PageState | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-use.d.ts","sourceRoot":"","sources":["../../src/core/browser-use.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"browser-use.d.ts","sourceRoot":"","sources":["../../src/core/browser-use.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,KAAK,aAAa,EAAyB,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3G,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,SAAS;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,kBAAkB,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAqB9C;IAED,OAAO,CAAC,SAAS;CAyBjB;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACpD,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAGrE;CACD;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAChD,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,QAAQ,CAAwB;IAExC,cAKC;IAEK,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuC1D;IAED,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEnD;CACD;AAED,eAAe,eAAe,CAAC","sourcesContent":["import { EventEmitter } from \"events\";\nimport { type Postcondition, PostconditionVerifier, type VerificationResult } from \"./automation/index.ts\";\n\nexport interface BrowserTask {\n\turl: string;\n\ttask: string;\n\tsessionId?: string;\n\tpostconditions?: Postcondition[];\n}\n\nexport interface PageState {\n\turl: string;\n\ttitle: string;\n\tlinks: string[];\n\tforms: { action: string; fields: string[] }[];\n\ttext?: string;\n\tstatus?: number;\n\terror?: string;\n}\n\nexport interface BrowserUseResult {\n\tsuccess: boolean;\n\tpageState: PageState;\n\ttaskCompletion: number;\n\tpageQuality: number;\n\tnavEfficiency: number;\n\tsafety: number;\n\toverallScore: number;\n\tscreenshot?: string;\n\tverification: VerificationResult;\n\trepairsAttempted: number;\n}\n\nexport class BrowserUseEngine extends EventEmitter {\n\tasync navigate(url: string): Promise<PageState> {\n\t\ttry {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst timeout = setTimeout(() => controller.abort(), 10000);\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(url, { signal: controller.signal });\n\t\t\t\tconst html = await response.text();\n\t\t\t\treturn this.parseHTML(html, response.url || url, response.status);\n\t\t\t} finally {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"Error\",\n\t\t\t\tlinks: [],\n\t\t\t\tforms: [],\n\t\t\t\ttext: \"\",\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate parseHTML(html: string, url: string, status: number): PageState {\n\t\tconst titleMatch = html.match(/<title>([^<]*)<\\/title>/i);\n\t\tconst links = [...html.matchAll(/href=\"([^\"]+)\"/gi)]\n\t\t\t.map((match) => match[1])\n\t\t\t.filter((link) => link.startsWith(\"http\"));\n\t\tconst forms = [...html.matchAll(/<form[^>]*action=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/form>/gi)].map((match) => ({\n\t\t\taction: match[1] || url,\n\t\t\tfields: [...match[2].matchAll(/name=\"([^\"]*)\"/gi)].map((field) => field[1]),\n\t\t}));\n\t\tconst text = html\n\t\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t\t.replace(/<[^>]+>/g, \" \")\n\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t.trim();\n\n\t\treturn {\n\t\t\turl,\n\t\t\ttitle: titleMatch?.[1] || \"No Title\",\n\t\t\tlinks: [...new Set(links)].slice(0, 20),\n\t\t\tforms,\n\t\t\ttext,\n\t\t\tstatus,\n\t\t};\n\t}\n}\n\nexport class BrowserUseEvaluator extends EventEmitter {\n\tevaluate(result: BrowserUseResult): { passed: boolean; score: number } {\n\t\tconst passed = result.overallScore >= 0.6 && result.safety >= 0.5 && result.verification.pass;\n\t\treturn { passed, score: result.overallScore };\n\t}\n}\n\nexport class BrowserUseAgent extends EventEmitter {\n\tprivate engine: BrowserUseEngine;\n\tprivate evaluator: BrowserUseEvaluator;\n\tprivate sessions: Map<string, PageState> = new Map();\n\tprivate verifier: PostconditionVerifier;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.engine = new BrowserUseEngine();\n\t\tthis.evaluator = new BrowserUseEvaluator();\n\t\tthis.verifier = new PostconditionVerifier();\n\t}\n\n\tasync execute(task: BrowserTask): Promise<BrowserUseResult> {\n\t\tconst pageState = await this.engine.navigate(task.url);\n\t\tthis.sessions.set(task.sessionId || \"default\", pageState);\n\t\tconst verification = await this.verifier.verify(task.postconditions ?? [{ kind: \"text\", pattern: \"\\\\S\" }], {\n\t\t\tcurrentUrl: pageState.url,\n\t\t\ttext: pageState.text ?? \"\",\n\t\t\tapiStatus: pageState.status,\n\t\t});\n\t\tconst observed = pageState.error === undefined && (pageState.status === undefined || pageState.status < 500);\n\t\tconst taskCompletion = verification.pass ? 1 : observed ? 0.4 : 0;\n\t\tconst pageQuality = observed\n\t\t\t? Math.min(\n\t\t\t\t\t1,\n\t\t\t\t\t(pageState.links.length > 0 ? 0.25 : 0) +\n\t\t\t\t\t\t(pageState.forms.length > 0 ? 0.25 : 0) +\n\t\t\t\t\t\t(pageState.text ? 0.5 : 0),\n\t\t\t\t)\n\t\t\t: 0;\n\t\tconst navEfficiency = observed ? 0.9 : 0;\n\t\tconst safety = verification.failures.length === 0 ? 1 : 0.7;\n\t\tconst overallScore = Number(\n\t\t\t(taskCompletion * 0.45 + pageQuality * 0.2 + navEfficiency * 0.2 + safety * 0.15).toFixed(2),\n\t\t);\n\t\tconst result: BrowserUseResult = {\n\t\t\tsuccess: observed && verification.pass,\n\t\t\tpageState,\n\t\t\ttaskCompletion,\n\t\t\tpageQuality,\n\t\t\tnavEfficiency,\n\t\t\tsafety,\n\t\t\toverallScore,\n\t\t\tverification,\n\t\t\trepairsAttempted: verification.pass ? 0 : 1,\n\t\t};\n\n\t\tconst evaluation = this.evaluator.evaluate(result);\n\t\tthis.emit(\"taskComplete\", { task, result, evaluation });\n\n\t\treturn result;\n\t}\n\n\tgetSession(sessionId: string): PageState | undefined {\n\t\treturn this.sessions.get(sessionId);\n\t}\n}\n\nexport default BrowserUseAgent;\n"]}
|
package/dist/core/browser-use.js
CHANGED
|
@@ -1,39 +1,58 @@
|
|
|
1
|
-
// OMK v6.2 — Browser Use Agent (TypeScript)
|
|
2
|
-
// ============================================
|
|
3
|
-
// packages/coding-agent/src/core/browser-use.ts
|
|
4
|
-
//
|
|
5
|
-
// Browser Use 오픈소스 통합 에이전트.
|
|
6
1
|
import { EventEmitter } from "events";
|
|
2
|
+
import { PostconditionVerifier } from "./automation/index.js";
|
|
7
3
|
export class BrowserUseEngine extends EventEmitter {
|
|
8
4
|
async navigate(url) {
|
|
9
|
-
// curl 기반 HTTP + 정규식 HTML 파싱
|
|
10
|
-
const { execSync } = require("child_process");
|
|
11
5
|
try {
|
|
12
|
-
const
|
|
13
|
-
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
8
|
+
try {
|
|
9
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
10
|
+
const html = await response.text();
|
|
11
|
+
return this.parseHTML(html, response.url || url, response.status);
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
clearTimeout(timeout);
|
|
15
|
+
}
|
|
14
16
|
}
|
|
15
|
-
catch {
|
|
16
|
-
return {
|
|
17
|
+
catch (error) {
|
|
18
|
+
return {
|
|
19
|
+
url,
|
|
20
|
+
title: "Error",
|
|
21
|
+
links: [],
|
|
22
|
+
forms: [],
|
|
23
|
+
text: "",
|
|
24
|
+
error: error instanceof Error ? error.message : String(error),
|
|
25
|
+
};
|
|
17
26
|
}
|
|
18
27
|
}
|
|
19
|
-
parseHTML(html, url) {
|
|
28
|
+
parseHTML(html, url, status) {
|
|
20
29
|
const titleMatch = html.match(/<title>([^<]*)<\/title>/i);
|
|
21
|
-
const links = [...html.matchAll(/href="([^"]+)"/gi)]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
const links = [...html.matchAll(/href="([^"]+)"/gi)]
|
|
31
|
+
.map((match) => match[1])
|
|
32
|
+
.filter((link) => link.startsWith("http"));
|
|
33
|
+
const forms = [...html.matchAll(/<form[^>]*action="([^"]*)"[^>]*>([\s\S]*?)<\/form>/gi)].map((match) => ({
|
|
34
|
+
action: match[1] || url,
|
|
35
|
+
fields: [...match[2].matchAll(/name="([^"]*)"/gi)].map((field) => field[1]),
|
|
25
36
|
}));
|
|
37
|
+
const text = html
|
|
38
|
+
.replace(/<script[\s\S]*?<\/script>/gi, "")
|
|
39
|
+
.replace(/<style[\s\S]*?<\/style>/gi, "")
|
|
40
|
+
.replace(/<[^>]+>/g, " ")
|
|
41
|
+
.replace(/\s+/g, " ")
|
|
42
|
+
.trim();
|
|
26
43
|
return {
|
|
27
44
|
url,
|
|
28
45
|
title: titleMatch?.[1] || "No Title",
|
|
29
46
|
links: [...new Set(links)].slice(0, 20),
|
|
30
47
|
forms,
|
|
48
|
+
text,
|
|
49
|
+
status,
|
|
31
50
|
};
|
|
32
51
|
}
|
|
33
52
|
}
|
|
34
53
|
export class BrowserUseEvaluator extends EventEmitter {
|
|
35
54
|
evaluate(result) {
|
|
36
|
-
const passed = result.overallScore >= 0.6 && result.safety >= 0.5;
|
|
55
|
+
const passed = result.overallScore >= 0.6 && result.safety >= 0.5 && result.verification.pass;
|
|
37
56
|
return { passed, score: result.overallScore };
|
|
38
57
|
}
|
|
39
58
|
}
|
|
@@ -41,22 +60,41 @@ export class BrowserUseAgent extends EventEmitter {
|
|
|
41
60
|
engine;
|
|
42
61
|
evaluator;
|
|
43
62
|
sessions = new Map();
|
|
63
|
+
verifier;
|
|
44
64
|
constructor() {
|
|
45
65
|
super();
|
|
46
66
|
this.engine = new BrowserUseEngine();
|
|
47
67
|
this.evaluator = new BrowserUseEvaluator();
|
|
68
|
+
this.verifier = new PostconditionVerifier();
|
|
48
69
|
}
|
|
49
70
|
async execute(task) {
|
|
50
71
|
const pageState = await this.engine.navigate(task.url);
|
|
51
72
|
this.sessions.set(task.sessionId || "default", pageState);
|
|
73
|
+
const verification = await this.verifier.verify(task.postconditions ?? [{ kind: "text", pattern: "\\S" }], {
|
|
74
|
+
currentUrl: pageState.url,
|
|
75
|
+
text: pageState.text ?? "",
|
|
76
|
+
apiStatus: pageState.status,
|
|
77
|
+
});
|
|
78
|
+
const observed = pageState.error === undefined && (pageState.status === undefined || pageState.status < 500);
|
|
79
|
+
const taskCompletion = verification.pass ? 1 : observed ? 0.4 : 0;
|
|
80
|
+
const pageQuality = observed
|
|
81
|
+
? Math.min(1, (pageState.links.length > 0 ? 0.25 : 0) +
|
|
82
|
+
(pageState.forms.length > 0 ? 0.25 : 0) +
|
|
83
|
+
(pageState.text ? 0.5 : 0))
|
|
84
|
+
: 0;
|
|
85
|
+
const navEfficiency = observed ? 0.9 : 0;
|
|
86
|
+
const safety = verification.failures.length === 0 ? 1 : 0.7;
|
|
87
|
+
const overallScore = Number((taskCompletion * 0.45 + pageQuality * 0.2 + navEfficiency * 0.2 + safety * 0.15).toFixed(2));
|
|
52
88
|
const result = {
|
|
53
|
-
success:
|
|
89
|
+
success: observed && verification.pass,
|
|
54
90
|
pageState,
|
|
55
|
-
taskCompletion
|
|
56
|
-
pageQuality
|
|
57
|
-
navEfficiency
|
|
58
|
-
safety
|
|
59
|
-
overallScore
|
|
91
|
+
taskCompletion,
|
|
92
|
+
pageQuality,
|
|
93
|
+
navEfficiency,
|
|
94
|
+
safety,
|
|
95
|
+
overallScore,
|
|
96
|
+
verification,
|
|
97
|
+
repairsAttempted: verification.pass ? 0 : 1,
|
|
60
98
|
};
|
|
61
99
|
const evaluation = this.evaluator.evaluate(result);
|
|
62
100
|
this.emit("taskComplete", { task, result, evaluation });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-use.js","sourceRoot":"","sources":["../../src/core/browser-use.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"browser-use.js","sourceRoot":"","sources":["../../src/core/browser-use.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"events\";\nimport { type Postcondition, PostconditionVerifier, type VerificationResult } from \"./automation/index.ts\";\n\nexport interface BrowserTask {\n\turl: string;\n\ttask: string;\n\tsessionId?: string;\n\tpostconditions?: Postcondition[];\n}\n\nexport interface PageState {\n\turl: string;\n\ttitle: string;\n\tlinks: string[];\n\tforms: { action: string; fields: string[] }[];\n\ttext?: string;\n\tstatus?: number;\n\terror?: string;\n}\n\nexport interface BrowserUseResult {\n\tsuccess: boolean;\n\tpageState: PageState;\n\ttaskCompletion: number;\n\tpageQuality: number;\n\tnavEfficiency: number;\n\tsafety: number;\n\toverallScore: number;\n\tscreenshot?: string;\n\tverification: VerificationResult;\n\trepairsAttempted: number;\n}\n\nexport class BrowserUseEngine extends EventEmitter {\n\tasync navigate(url: string): Promise<PageState> {\n\t\ttry {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst timeout = setTimeout(() => controller.abort(), 10000);\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(url, { signal: controller.signal });\n\t\t\t\tconst html = await response.text();\n\t\t\t\treturn this.parseHTML(html, response.url || url, response.status);\n\t\t\t} finally {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\turl,\n\t\t\t\ttitle: \"Error\",\n\t\t\t\tlinks: [],\n\t\t\t\tforms: [],\n\t\t\t\ttext: \"\",\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate parseHTML(html: string, url: string, status: number): PageState {\n\t\tconst titleMatch = html.match(/<title>([^<]*)<\\/title>/i);\n\t\tconst links = [...html.matchAll(/href=\"([^\"]+)\"/gi)]\n\t\t\t.map((match) => match[1])\n\t\t\t.filter((link) => link.startsWith(\"http\"));\n\t\tconst forms = [...html.matchAll(/<form[^>]*action=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/form>/gi)].map((match) => ({\n\t\t\taction: match[1] || url,\n\t\t\tfields: [...match[2].matchAll(/name=\"([^\"]*)\"/gi)].map((field) => field[1]),\n\t\t}));\n\t\tconst text = html\n\t\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t\t.replace(/<[^>]+>/g, \" \")\n\t\t\t.replace(/\\s+/g, \" \")\n\t\t\t.trim();\n\n\t\treturn {\n\t\t\turl,\n\t\t\ttitle: titleMatch?.[1] || \"No Title\",\n\t\t\tlinks: [...new Set(links)].slice(0, 20),\n\t\t\tforms,\n\t\t\ttext,\n\t\t\tstatus,\n\t\t};\n\t}\n}\n\nexport class BrowserUseEvaluator extends EventEmitter {\n\tevaluate(result: BrowserUseResult): { passed: boolean; score: number } {\n\t\tconst passed = result.overallScore >= 0.6 && result.safety >= 0.5 && result.verification.pass;\n\t\treturn { passed, score: result.overallScore };\n\t}\n}\n\nexport class BrowserUseAgent extends EventEmitter {\n\tprivate engine: BrowserUseEngine;\n\tprivate evaluator: BrowserUseEvaluator;\n\tprivate sessions: Map<string, PageState> = new Map();\n\tprivate verifier: PostconditionVerifier;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.engine = new BrowserUseEngine();\n\t\tthis.evaluator = new BrowserUseEvaluator();\n\t\tthis.verifier = new PostconditionVerifier();\n\t}\n\n\tasync execute(task: BrowserTask): Promise<BrowserUseResult> {\n\t\tconst pageState = await this.engine.navigate(task.url);\n\t\tthis.sessions.set(task.sessionId || \"default\", pageState);\n\t\tconst verification = await this.verifier.verify(task.postconditions ?? [{ kind: \"text\", pattern: \"\\\\S\" }], {\n\t\t\tcurrentUrl: pageState.url,\n\t\t\ttext: pageState.text ?? \"\",\n\t\t\tapiStatus: pageState.status,\n\t\t});\n\t\tconst observed = pageState.error === undefined && (pageState.status === undefined || pageState.status < 500);\n\t\tconst taskCompletion = verification.pass ? 1 : observed ? 0.4 : 0;\n\t\tconst pageQuality = observed\n\t\t\t? Math.min(\n\t\t\t\t\t1,\n\t\t\t\t\t(pageState.links.length > 0 ? 0.25 : 0) +\n\t\t\t\t\t\t(pageState.forms.length > 0 ? 0.25 : 0) +\n\t\t\t\t\t\t(pageState.text ? 0.5 : 0),\n\t\t\t\t)\n\t\t\t: 0;\n\t\tconst navEfficiency = observed ? 0.9 : 0;\n\t\tconst safety = verification.failures.length === 0 ? 1 : 0.7;\n\t\tconst overallScore = Number(\n\t\t\t(taskCompletion * 0.45 + pageQuality * 0.2 + navEfficiency * 0.2 + safety * 0.15).toFixed(2),\n\t\t);\n\t\tconst result: BrowserUseResult = {\n\t\t\tsuccess: observed && verification.pass,\n\t\t\tpageState,\n\t\t\ttaskCompletion,\n\t\t\tpageQuality,\n\t\t\tnavEfficiency,\n\t\t\tsafety,\n\t\t\toverallScore,\n\t\t\tverification,\n\t\t\trepairsAttempted: verification.pass ? 0 : 1,\n\t\t};\n\n\t\tconst evaluation = this.evaluator.evaluate(result);\n\t\tthis.emit(\"taskComplete\", { task, result, evaluation });\n\n\t\treturn result;\n\t}\n\n\tgetSession(sessionId: string): PageState | undefined {\n\t\treturn this.sessions.get(sessionId);\n\t}\n}\n\nexport default BrowserUseAgent;\n"]}
|
|
@@ -9,6 +9,8 @@ export interface ResourceCollision {
|
|
|
9
9
|
loserScope?: "user" | "project" | "temporary";
|
|
10
10
|
winnerOrigin?: "package" | "top-level";
|
|
11
11
|
loserOrigin?: "package" | "top-level";
|
|
12
|
+
resolutionReason?: string;
|
|
13
|
+
resolutionAction?: string;
|
|
12
14
|
}
|
|
13
15
|
export interface ResourceDiagnostic {
|
|
14
16
|
type: "warning" | "error" | "collision";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/core/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IACjC,YAAY,EAAE,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IAC/C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IAC9C,YAAY,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IACvC,WAAW,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/core/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IACjC,YAAY,EAAE,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IAC/C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IAC9C,YAAY,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IACvC,WAAW,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,iBAAiB,CAAC;CAC9B","sourcesContent":["export interface ResourceCollision {\n\tresourceType: \"extension\" | \"skill\" | \"prompt\" | \"theme\";\n\tname: string; // skill name, command/tool/flag name, prompt name, theme name\n\twinnerPath: string;\n\tloserPath: string;\n\twinnerSource?: string; // e.g., \"npm:foo\", \"git:...\", \"local\"\n\tloserSource?: string;\n\twinnerScope?: \"user\" | \"project\" | \"temporary\";\n\tloserScope?: \"user\" | \"project\" | \"temporary\";\n\twinnerOrigin?: \"package\" | \"top-level\";\n\tloserOrigin?: \"package\" | \"top-level\";\n\tresolutionReason?: string;\n\tresolutionAction?: string;\n}\n\nexport interface ResourceDiagnostic {\n\ttype: \"warning\" | \"error\" | \"collision\";\n\tmessage: string;\n\tpath?: string;\n\tcollision?: ResourceCollision;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/core/diagnostics.ts"],"names":[],"mappings":"","sourcesContent":["export interface ResourceCollision {\n\tresourceType: \"extension\" | \"skill\" | \"prompt\" | \"theme\";\n\tname: string; // skill name, command/tool/flag name, prompt name, theme name\n\twinnerPath: string;\n\tloserPath: string;\n\twinnerSource?: string; // e.g., \"npm:foo\", \"git:...\", \"local\"\n\tloserSource?: string;\n\twinnerScope?: \"user\" | \"project\" | \"temporary\";\n\tloserScope?: \"user\" | \"project\" | \"temporary\";\n\twinnerOrigin?: \"package\" | \"top-level\";\n\tloserOrigin?: \"package\" | \"top-level\";\n}\n\nexport interface ResourceDiagnostic {\n\ttype: \"warning\" | \"error\" | \"collision\";\n\tmessage: string;\n\tpath?: string;\n\tcollision?: ResourceCollision;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/core/diagnostics.ts"],"names":[],"mappings":"","sourcesContent":["export interface ResourceCollision {\n\tresourceType: \"extension\" | \"skill\" | \"prompt\" | \"theme\";\n\tname: string; // skill name, command/tool/flag name, prompt name, theme name\n\twinnerPath: string;\n\tloserPath: string;\n\twinnerSource?: string; // e.g., \"npm:foo\", \"git:...\", \"local\"\n\tloserSource?: string;\n\twinnerScope?: \"user\" | \"project\" | \"temporary\";\n\tloserScope?: \"user\" | \"project\" | \"temporary\";\n\twinnerOrigin?: \"package\" | \"top-level\";\n\tloserOrigin?: \"package\" | \"top-level\";\n\tresolutionReason?: string;\n\tresolutionAction?: string;\n}\n\nexport interface ResourceDiagnostic {\n\ttype: \"warning\" | \"error\" | \"collision\";\n\tmessage: string;\n\tpath?: string;\n\tcollision?: ResourceCollision;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"todo-checklist.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/todo-checklist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"todo-checklist.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/todo-checklist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CA2D7D","sourcesContent":["/**\n * Built-in TODO checklist extension.\n *\n * Exposes an `update_todo` tool the model calls to maintain a visible,\n * dynamically-generated checklist of the current plan. The checklist is NOT\n * hardcoded: the LLM emits the items on every call (replacing the previous\n * list), and they render live in the terminal UI above the editor.\n *\n * Design notes:\n * - State is held per-loaded-extension and reset on session_start.\n * - The widget is mounted via ctx.ui.setWidget with a factory that binds the\n * latest state snapshot, so each update re-renders with current items.\n * - Headless / no-UI sessions still update state and return a summary; the\n * setWidget call is wrapped so a missing UI never breaks the tool.\n * - Web/extension observations are never involved; this tool only carries the\n * model's own plan text.\n */\n\nimport { StringEnum, Type } from \"omk-ai\";\nimport { TodoChecklistComponent } from \"../../../modes/interactive/components/todo-checklist.ts\";\nimport { resetCurrentTodoState, setCurrentTodoState } from \"../../todo-runtime-state.ts\";\nimport type { TodoState, TodoStatus } from \"../../todo-state.ts\";\nimport { EMPTY_TODO_STATE, setTodoItems, summary } from \"../../todo-state.ts\";\nimport type { ExtensionAPI } from \"../types.ts\";\n\nexport default function todoChecklist(omk: ExtensionAPI): void {\n\tlet state: TodoState = EMPTY_TODO_STATE;\n\n\tomk.on(\"session_start\", () => {\n\t\tstate = EMPTY_TODO_STATE;\n\t\tresetCurrentTodoState();\n\t});\n\n\tomk.registerTool({\n\t\tname: \"update_todo\",\n\t\tlabel: \"Update TODO checklist\",\n\t\tdescription:\n\t\t\t\"Update the visible TODO checklist shown in the terminal UI with the current plan. Pass the FULL current list of tasks on every call (this replaces the previous list). Use this to keep the user informed of progress: mark items pending/active/done/blocked as work proceeds.\",\n\t\tpromptSnippet:\n\t\t\t\"Maintain a live TODO checklist in the terminal UI by calling update_todo with the current plan and item statuses.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Call update_todo at the start of non-trivial multi-step work and after each task transitions state.\",\n\t\t\t\"Pass the complete current list each call (the tool replaces, not appends). Keep labels short and verb-led.\",\n\t\t\t\"Set exactly one item to 'active' (the task in progress); mark finished items 'done' and blockers 'blocked'.\",\n\t\t],\n\t\tparameters: Type.Object({\n\t\t\titems: Type.Array(\n\t\t\t\tType.Object({\n\t\t\t\t\tid: Type.String({ description: \"Stable identifier for the task (reuse across updates).\" }),\n\t\t\t\t\tlabel: Type.String({ description: \"Short human-readable task description.\" }),\n\t\t\t\t\tstatus: StringEnum([\"pending\", \"active\", \"done\", \"blocked\"], {\n\t\t\t\t\t\tdescription: \"pending=not started, active=in progress, done=complete, blocked=stuck.\",\n\t\t\t\t\t}),\n\t\t\t\t\tdetail: Type.Optional(Type.String({ description: \"Optional extra context for the task.\" })),\n\t\t\t\t}),\n\t\t\t\t{ description: \"Full current list of checklist items.\" },\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n\t\t\tstate = setTodoItems(\n\t\t\t\tstate,\n\t\t\t\tparams.items.map((item) => ({ ...item, status: item.status as TodoStatus })),\n\t\t\t);\n\t\t\tsetCurrentTodoState(state);\n\t\t\tconst snapshot = state;\n\t\t\ttry {\n\t\t\t\tctx.ui.setWidget(\"omk-todo\", () => new TodoChecklistComponent(() => snapshot), {\n\t\t\t\t\tplacement: \"aboveEditor\",\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\t// UI may be unavailable in headless mode; state still updates.\n\t\t\t}\n\t\t\tconst s = summary(state);\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `TODO updated: ${s.done}/${s.total} done · ${s.active} active · ${s.pending} pending · ${s.blocked} blocked`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { summary: s, total: s.total },\n\t\t\t};\n\t\t},\n\t});\n}\n"]}
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { StringEnum, Type } from "omk-ai";
|
|
19
19
|
import { TodoChecklistComponent } from "../../../modes/interactive/components/todo-checklist.js";
|
|
20
|
+
import { resetCurrentTodoState, setCurrentTodoState } from "../../todo-runtime-state.js";
|
|
20
21
|
import { EMPTY_TODO_STATE, setTodoItems, summary } from "../../todo-state.js";
|
|
21
22
|
export default function todoChecklist(omk) {
|
|
22
23
|
let state = EMPTY_TODO_STATE;
|
|
23
24
|
omk.on("session_start", () => {
|
|
24
25
|
state = EMPTY_TODO_STATE;
|
|
26
|
+
resetCurrentTodoState();
|
|
25
27
|
});
|
|
26
28
|
omk.registerTool({
|
|
27
29
|
name: "update_todo",
|
|
@@ -45,6 +47,7 @@ export default function todoChecklist(omk) {
|
|
|
45
47
|
}),
|
|
46
48
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
47
49
|
state = setTodoItems(state, params.items.map((item) => ({ ...item, status: item.status })));
|
|
50
|
+
setCurrentTodoState(state);
|
|
48
51
|
const snapshot = state;
|
|
49
52
|
try {
|
|
50
53
|
ctx.ui.setWidget("omk-todo", () => new TodoChecklistComponent(() => snapshot), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"todo-checklist.js","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/todo-checklist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yDAAyD,CAAC;
|
|
1
|
+
{"version":3,"file":"todo-checklist.js","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/todo-checklist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yDAAyD,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAEzF,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAG9E,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,GAAiB,EAAQ;IAC9D,IAAI,KAAK,GAAc,gBAAgB,CAAC;IAExC,GAAG,CAAC,EAAE,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC;QAC7B,KAAK,GAAG,gBAAgB,CAAC;QACzB,qBAAqB,EAAE,CAAC;IAAA,CACxB,CAAC,CAAC;IAEH,GAAG,CAAC,YAAY,CAAC;QAChB,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EACV,iRAAiR;QAClR,aAAa,EACZ,mHAAmH;QACpH,gBAAgB,EAAE;YACjB,qGAAqG;YACrG,4GAA4G;YAC5G,6GAA6G;SAC7G;QACD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK,CAChB,IAAI,CAAC,MAAM,CAAC;gBACX,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;gBAC1F,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;gBAC7E,MAAM,EAAE,UAAU,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE;oBAC5D,WAAW,EAAE,wEAAwE;iBACrF,CAAC;gBACF,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,sCAAsC,EAAE,CAAC,CAAC;aAC3F,CAAC,EACF,EAAE,WAAW,EAAE,uCAAuC,EAAE,CACxD;SACD,CAAC;QACF,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE;YAC3D,KAAK,GAAG,YAAY,CACnB,KAAK,EACL,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAoB,EAAE,CAAC,CAAC,CAC5E,CAAC;YACF,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC;gBACJ,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,sBAAsB,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE;oBAC9E,SAAS,EAAE,aAAa;iBACxB,CAAC,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACR,+DAA+D;YAChE,CAAC;YACD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YACzB,OAAO;gBACN,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,iBAAiB,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,YAAW,CAAC,CAAC,MAAM,cAAa,CAAC,CAAC,OAAO,eAAc,CAAC,CAAC,OAAO,UAAU;qBAClH;iBACD;gBACD,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;aACvC,CAAC;QAAA,CACF;KACD,CAAC,CAAC;AAAA,CACH","sourcesContent":["/**\n * Built-in TODO checklist extension.\n *\n * Exposes an `update_todo` tool the model calls to maintain a visible,\n * dynamically-generated checklist of the current plan. The checklist is NOT\n * hardcoded: the LLM emits the items on every call (replacing the previous\n * list), and they render live in the terminal UI above the editor.\n *\n * Design notes:\n * - State is held per-loaded-extension and reset on session_start.\n * - The widget is mounted via ctx.ui.setWidget with a factory that binds the\n * latest state snapshot, so each update re-renders with current items.\n * - Headless / no-UI sessions still update state and return a summary; the\n * setWidget call is wrapped so a missing UI never breaks the tool.\n * - Web/extension observations are never involved; this tool only carries the\n * model's own plan text.\n */\n\nimport { StringEnum, Type } from \"omk-ai\";\nimport { TodoChecklistComponent } from \"../../../modes/interactive/components/todo-checklist.ts\";\nimport { resetCurrentTodoState, setCurrentTodoState } from \"../../todo-runtime-state.ts\";\nimport type { TodoState, TodoStatus } from \"../../todo-state.ts\";\nimport { EMPTY_TODO_STATE, setTodoItems, summary } from \"../../todo-state.ts\";\nimport type { ExtensionAPI } from \"../types.ts\";\n\nexport default function todoChecklist(omk: ExtensionAPI): void {\n\tlet state: TodoState = EMPTY_TODO_STATE;\n\n\tomk.on(\"session_start\", () => {\n\t\tstate = EMPTY_TODO_STATE;\n\t\tresetCurrentTodoState();\n\t});\n\n\tomk.registerTool({\n\t\tname: \"update_todo\",\n\t\tlabel: \"Update TODO checklist\",\n\t\tdescription:\n\t\t\t\"Update the visible TODO checklist shown in the terminal UI with the current plan. Pass the FULL current list of tasks on every call (this replaces the previous list). Use this to keep the user informed of progress: mark items pending/active/done/blocked as work proceeds.\",\n\t\tpromptSnippet:\n\t\t\t\"Maintain a live TODO checklist in the terminal UI by calling update_todo with the current plan and item statuses.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Call update_todo at the start of non-trivial multi-step work and after each task transitions state.\",\n\t\t\t\"Pass the complete current list each call (the tool replaces, not appends). Keep labels short and verb-led.\",\n\t\t\t\"Set exactly one item to 'active' (the task in progress); mark finished items 'done' and blockers 'blocked'.\",\n\t\t],\n\t\tparameters: Type.Object({\n\t\t\titems: Type.Array(\n\t\t\t\tType.Object({\n\t\t\t\t\tid: Type.String({ description: \"Stable identifier for the task (reuse across updates).\" }),\n\t\t\t\t\tlabel: Type.String({ description: \"Short human-readable task description.\" }),\n\t\t\t\t\tstatus: StringEnum([\"pending\", \"active\", \"done\", \"blocked\"], {\n\t\t\t\t\t\tdescription: \"pending=not started, active=in progress, done=complete, blocked=stuck.\",\n\t\t\t\t\t}),\n\t\t\t\t\tdetail: Type.Optional(Type.String({ description: \"Optional extra context for the task.\" })),\n\t\t\t\t}),\n\t\t\t\t{ description: \"Full current list of checklist items.\" },\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, ctx) {\n\t\t\tstate = setTodoItems(\n\t\t\t\tstate,\n\t\t\t\tparams.items.map((item) => ({ ...item, status: item.status as TodoStatus })),\n\t\t\t);\n\t\t\tsetCurrentTodoState(state);\n\t\t\tconst snapshot = state;\n\t\t\ttry {\n\t\t\t\tctx.ui.setWidget(\"omk-todo\", () => new TodoChecklistComponent(() => snapshot), {\n\t\t\t\t\tplacement: \"aboveEditor\",\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\t// UI may be unavailable in headless mode; state still updates.\n\t\t\t}\n\t\t\tconst s = summary(state);\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `TODO updated: ${s.done}/${s.total} done · ${s.active} active · ${s.pending} pending · ${s.blocked} blocked`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { summary: s, total: s.total },\n\t\t\t};\n\t\t},\n\t});\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type PiPackageIntakeSummary } from "./pi-package-intake.ts";
|
|
1
2
|
/**
|
|
2
3
|
* Provides git branch and extension statuses - data not otherwise accessible to extensions.
|
|
3
4
|
* Token stats, model info available via ctx.sessionManager and ctx.model.
|
|
@@ -39,6 +40,7 @@ export declare class FooterDataProvider {
|
|
|
39
40
|
getCpuPercent(): number | null;
|
|
40
41
|
/** Most recent process RSS memory size in bytes, or `null` if not yet sampled. */
|
|
41
42
|
getMemoryRssBytes(): number | null;
|
|
43
|
+
getPackageIntakeSummary(): PiPackageIntakeSummary;
|
|
42
44
|
/** Internal: update available provider count */
|
|
43
45
|
setAvailableProviderCount(count: number): void;
|
|
44
46
|
setCwd(cwd: string): void;
|
|
@@ -55,5 +57,5 @@ export declare class FooterDataProvider {
|
|
|
55
57
|
private setupGitWatcher;
|
|
56
58
|
}
|
|
57
59
|
/** Read-only view for extensions - excludes setExtensionStatus, setAvailableProviderCount and dispose */
|
|
58
|
-
export type ReadonlyFooterDataProvider = Pick<FooterDataProvider, "getGitBranch" | "getExtensionStatuses" | "getAvailableProviderCount" | "onBranchChange" | "getCpuPercent" | "getMemoryRssBytes">;
|
|
60
|
+
export type ReadonlyFooterDataProvider = Pick<FooterDataProvider, "getGitBranch" | "getExtensionStatuses" | "getAvailableProviderCount" | "onBranchChange" | "getCpuPercent" | "getMemoryRssBytes" | "getPackageIntakeSummary">;
|
|
59
61
|
//# sourceMappingURL=footer-data-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer-data-provider.d.ts","sourceRoot":"","sources":["../../src/core/footer-data-provider.ts"],"names":[],"mappings":"AA+FA;;;GAGG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAO;IAEhD,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,qBAAqB,CAA4D;IACzF,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,yBAAyB,CAA0B;IAC3D,OAAO,CAAC,sBAAsB,CAAuB;IACrD,OAAO,CAAC,qBAAqB,CAAyB;IACtD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAiB;IAEvC,YAAY,GAAG,EAAE,MAAM,EAMtB;IAED,2EAA2E;IAC3E,YAAY,IAAI,MAAM,GAAG,IAAI,CAK5B;IAED,wDAAwD;IACxD,oBAAoB,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAElD;IAED,qEAAqE;IACrE,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAG/C;IAED,qCAAqC;IACrC,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAM9D;IAED,yCAAyC;IACzC,sBAAsB,IAAI,IAAI,CAE7B;IAED,4EAA4E;IAC5E,yBAAyB,IAAI,MAAM,CAElC;IAED,6EAA6E;IAC7E,aAAa,IAAI,MAAM,GAAG,IAAI,CAE7B;IAED,kFAAkF;IAClF,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjC;IAED,gDAAgD;IAChD,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE7C;IAED,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAexB;IAED,wBAAwB;IACxB,OAAO,IAAI,IAAI,CASd;IAED,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,eAAe;YAYT,qBAAqB;IA0BnC,OAAO,CAAC,oBAAoB;YAcd,qBAAqB;IAgBnC,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,eAAe;CA2EvB;AAED,yGAAyG;AACzG,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC5C,kBAAkB,EAChB,cAAc,GACd,sBAAsB,GACtB,2BAA2B,GAC3B,gBAAgB,GAChB,eAAe,GACf,mBAAmB,CACrB,CAAC","sourcesContent":["import { type ExecFileException, execFile, spawnSync } from \"child_process\";\nimport { existsSync, type FSWatcher, readFileSync, type Stats, statSync, unwatchFile, watchFile } from \"fs\";\nimport { dirname, join, resolve } from \"path\";\nimport { closeWatcher, FS_WATCH_RETRY_DELAY_MS, watchWithErrorHandler } from \"../utils/fs-watch.ts\";\nimport { MetricsSampler } from \"./metrics-sampler.ts\";\n\ntype GitPaths = {\n\trepoDir: string;\n\tcommonGitDir: string;\n\theadPath: string;\n};\n\n/**\n * Find git metadata paths by walking up from cwd.\n * Handles both regular git repos (.git is a directory) and worktrees (.git is a file).\n */\nfunction findGitPaths(cwd: string): GitPaths | null {\n\tlet dir = cwd;\n\twhile (true) {\n\t\tconst gitPath = join(dir, \".git\");\n\t\tif (existsSync(gitPath)) {\n\t\t\ttry {\n\t\t\t\tconst stat = statSync(gitPath);\n\t\t\t\tif (stat.isFile()) {\n\t\t\t\t\tconst content = readFileSync(gitPath, \"utf8\").trim();\n\t\t\t\t\tif (content.startsWith(\"gitdir: \")) {\n\t\t\t\t\t\tconst gitDir = resolve(dir, content.slice(8).trim());\n\t\t\t\t\t\tconst headPath = join(gitDir, \"HEAD\");\n\t\t\t\t\t\tif (!existsSync(headPath)) return null;\n\t\t\t\t\t\tconst commonDirPath = join(gitDir, \"commondir\");\n\t\t\t\t\t\tconst commonGitDir = existsSync(commonDirPath)\n\t\t\t\t\t\t\t? resolve(gitDir, readFileSync(commonDirPath, \"utf8\").trim())\n\t\t\t\t\t\t\t: gitDir;\n\t\t\t\t\t\treturn { repoDir: dir, commonGitDir, headPath };\n\t\t\t\t\t}\n\t\t\t\t} else if (stat.isDirectory()) {\n\t\t\t\t\tconst headPath = join(gitPath, \"HEAD\");\n\t\t\t\t\tif (!existsSync(headPath)) return null;\n\t\t\t\t\treturn { repoDir: dir, commonGitDir: gitPath, headPath };\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) return null;\n\t\tdir = parent;\n\t}\n}\n\n/** Ask git for the current branch. Returns null on detached HEAD or if git is unavailable. */\nfunction resolveBranchWithGitSync(repoDir: string): string | null {\n\tconst result = spawnSync(\"git\", [\"--no-optional-locks\", \"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], {\n\t\tcwd: repoDir,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t});\n\tconst branch = result.status === 0 ? result.stdout.trim() : \"\";\n\treturn branch || null;\n}\n\n/** Ask git for the current branch asynchronously. Returns null on detached HEAD or if git is unavailable. */\nfunction resolveBranchWithGitAsync(repoDir: string): Promise<string | null> {\n\treturn new Promise((resolvePromise) => {\n\t\texecFile(\n\t\t\t\"git\",\n\t\t\t[\"--no-optional-locks\", \"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"],\n\t\t\t{\n\t\t\t\tcwd: repoDir,\n\t\t\t\tencoding: \"utf8\",\n\t\t\t},\n\t\t\t(error: ExecFileException | null, stdout: string) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tresolvePromise(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst branch = stdout.trim();\n\t\t\t\tresolvePromise(branch || null);\n\t\t\t},\n\t\t);\n\t});\n}\n\nfunction isWslEnvironment(): boolean {\n\treturn process.platform === \"linux\" && !!(process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP);\n}\n\nfunction isWindowsMountedRepoPath(repoDir: string): boolean {\n\treturn /^\\/mnt\\/[a-z](?:\\/|$)/i.test(repoDir);\n}\n\nfunction shouldPollGitHead(repoDir: string): boolean {\n\treturn isWslEnvironment() && isWindowsMountedRepoPath(repoDir);\n}\n\n/**\n * Provides git branch and extension statuses - data not otherwise accessible to extensions.\n * Token stats, model info available via ctx.sessionManager and ctx.model.\n */\nexport class FooterDataProvider {\n\tprivate cwd: string;\n\tprivate static readonly WATCH_DEBOUNCE_MS = 500;\n\n\tprivate extensionStatuses = new Map<string, string>();\n\tprivate cachedBranch: string | null | undefined = undefined;\n\tprivate gitPaths: GitPaths | null | undefined = undefined;\n\tprivate headWatcher: FSWatcher | null = null;\n\tprivate headWatchFilePath: string | null = null;\n\tprivate headWatchFileListener: ((current: Stats, previous: Stats) => void) | null = null;\n\tprivate reftableWatcher: FSWatcher | null = null;\n\tprivate reftableTablesListWatcher: FSWatcher | null = null;\n\tprivate reftableTablesListPath: string | null = null;\n\tprivate branchChangeCallbacks = new Set<() => void>();\n\tprivate availableProviderCount = 0;\n\tprivate refreshTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate gitWatcherRetryTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate refreshInFlight = false;\n\tprivate refreshPending = false;\n\tprivate disposed = false;\n\tprivate metricsSampler: MetricsSampler;\n\n\tconstructor(cwd: string) {\n\t\tthis.cwd = cwd;\n\t\tthis.gitPaths = findGitPaths(cwd);\n\t\tthis.setupGitWatcher();\n\t\tthis.metricsSampler = new MetricsSampler();\n\t\tthis.metricsSampler.start();\n\t}\n\n\t/** Current git branch, null if not in repo, \"detached\" if detached HEAD */\n\tgetGitBranch(): string | null {\n\t\tif (this.cachedBranch === undefined) {\n\t\t\tthis.cachedBranch = this.resolveGitBranchSync();\n\t\t}\n\t\treturn this.cachedBranch;\n\t}\n\n\t/** Extension status texts set via ctx.ui.setStatus() */\n\tgetExtensionStatuses(): ReadonlyMap<string, string> {\n\t\treturn this.extensionStatuses;\n\t}\n\n\t/** Subscribe to git branch changes. Returns unsubscribe function. */\n\tonBranchChange(callback: () => void): () => void {\n\t\tthis.branchChangeCallbacks.add(callback);\n\t\treturn () => this.branchChangeCallbacks.delete(callback);\n\t}\n\n\t/** Internal: set extension status */\n\tsetExtensionStatus(key: string, text: string | undefined): void {\n\t\tif (text === undefined) {\n\t\t\tthis.extensionStatuses.delete(key);\n\t\t} else {\n\t\t\tthis.extensionStatuses.set(key, text);\n\t\t}\n\t}\n\n\t/** Internal: clear extension statuses */\n\tclearExtensionStatuses(): void {\n\t\tthis.extensionStatuses.clear();\n\t}\n\n\t/** Number of unique providers with available models (for footer display) */\n\tgetAvailableProviderCount(): number {\n\t\treturn this.availableProviderCount;\n\t}\n\n\t/** Most recent process CPU percent (0-100), or `null` if not yet sampled. */\n\tgetCpuPercent(): number | null {\n\t\treturn this.metricsSampler.getCpuPercent();\n\t}\n\n\t/** Most recent process RSS memory size in bytes, or `null` if not yet sampled. */\n\tgetMemoryRssBytes(): number | null {\n\t\treturn this.metricsSampler.getMemoryRssBytes();\n\t}\n\n\t/** Internal: update available provider count */\n\tsetAvailableProviderCount(count: number): void {\n\t\tthis.availableProviderCount = count;\n\t}\n\n\tsetCwd(cwd: string): void {\n\t\tif (this.cwd === cwd) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.cwd = cwd;\n\t\tif (this.refreshTimer) {\n\t\t\tclearTimeout(this.refreshTimer);\n\t\t\tthis.refreshTimer = null;\n\t\t}\n\t\tthis.clearGitWatchers();\n\t\tthis.cachedBranch = undefined;\n\t\tthis.gitPaths = findGitPaths(cwd);\n\t\tthis.setupGitWatcher();\n\t\tthis.notifyBranchChange();\n\t}\n\n\t/** Internal: cleanup */\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tif (this.refreshTimer) {\n\t\t\tclearTimeout(this.refreshTimer);\n\t\t\tthis.refreshTimer = null;\n\t\t}\n\t\tthis.clearGitWatchers();\n\t\tthis.branchChangeCallbacks.clear();\n\t\tthis.metricsSampler.stop();\n\t}\n\n\tprivate notifyBranchChange(): void {\n\t\tfor (const cb of this.branchChangeCallbacks) cb();\n\t}\n\n\tprivate scheduleRefresh(): void {\n\t\tif (this.disposed || this.refreshTimer) return;\n\t\tif (this.refreshInFlight) {\n\t\t\tthis.refreshPending = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.refreshTimer = setTimeout(() => {\n\t\t\tthis.refreshTimer = null;\n\t\t\tvoid this.refreshGitBranchAsync();\n\t\t}, FooterDataProvider.WATCH_DEBOUNCE_MS);\n\t}\n\n\tprivate async refreshGitBranchAsync(): Promise<void> {\n\t\tif (this.disposed) return;\n\t\tif (this.refreshInFlight) {\n\t\t\tthis.refreshPending = true;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.refreshInFlight = true;\n\t\ttry {\n\t\t\tconst nextBranch = await this.resolveGitBranchAsync();\n\t\t\tif (this.disposed) return;\n\t\t\tif (this.cachedBranch !== undefined && this.cachedBranch !== nextBranch) {\n\t\t\t\tthis.cachedBranch = nextBranch;\n\t\t\t\tthis.notifyBranchChange();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.cachedBranch = nextBranch;\n\t\t} finally {\n\t\t\tthis.refreshInFlight = false;\n\t\t\tif (this.refreshPending && !this.disposed) {\n\t\t\t\tthis.refreshPending = false;\n\t\t\t\tthis.scheduleRefresh();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate resolveGitBranchSync(): string | null {\n\t\ttry {\n\t\t\tif (!this.gitPaths) return null;\n\t\t\tconst content = readFileSync(this.gitPaths.headPath, \"utf8\").trim();\n\t\t\tif (content.startsWith(\"ref: refs/heads/\")) {\n\t\t\t\tconst branch = content.slice(16);\n\t\t\t\treturn branch === \".invalid\" ? (resolveBranchWithGitSync(this.gitPaths.repoDir) ?? \"detached\") : branch;\n\t\t\t}\n\t\t\treturn \"detached\";\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate async resolveGitBranchAsync(): Promise<string | null> {\n\t\ttry {\n\t\t\tif (!this.gitPaths) return null;\n\t\t\tconst content = readFileSync(this.gitPaths.headPath, \"utf8\").trim();\n\t\t\tif (content.startsWith(\"ref: refs/heads/\")) {\n\t\t\t\tconst branch = content.slice(16);\n\t\t\t\treturn branch === \".invalid\"\n\t\t\t\t\t? ((await resolveBranchWithGitAsync(this.gitPaths.repoDir)) ?? \"detached\")\n\t\t\t\t\t: branch;\n\t\t\t}\n\t\t\treturn \"detached\";\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate clearGitWatchers(): void {\n\t\tcloseWatcher(this.headWatcher);\n\t\tthis.headWatcher = null;\n\t\tif (this.headWatchFilePath && this.headWatchFileListener) {\n\t\t\tunwatchFile(this.headWatchFilePath, this.headWatchFileListener);\n\t\t\tthis.headWatchFilePath = null;\n\t\t\tthis.headWatchFileListener = null;\n\t\t}\n\t\tcloseWatcher(this.reftableWatcher);\n\t\tthis.reftableWatcher = null;\n\t\tcloseWatcher(this.reftableTablesListWatcher);\n\t\tthis.reftableTablesListWatcher = null;\n\t\tif (this.reftableTablesListPath) {\n\t\t\tunwatchFile(this.reftableTablesListPath);\n\t\t\tthis.reftableTablesListPath = null;\n\t\t}\n\t\tif (this.gitWatcherRetryTimer) {\n\t\t\tclearTimeout(this.gitWatcherRetryTimer);\n\t\t\tthis.gitWatcherRetryTimer = null;\n\t\t}\n\t}\n\n\tprivate scheduleGitWatcherRetry(): void {\n\t\tif (this.disposed || this.gitWatcherRetryTimer) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.gitWatcherRetryTimer = setTimeout(() => {\n\t\t\tthis.gitWatcherRetryTimer = null;\n\t\t\tthis.setupGitWatcher();\n\t\t}, FS_WATCH_RETRY_DELAY_MS);\n\t}\n\n\tprivate handleGitWatcherError(): void {\n\t\tthis.clearGitWatchers();\n\t\tthis.scheduleGitWatcherRetry();\n\t}\n\n\tprivate setupGitWatcher(): void {\n\t\tthis.clearGitWatchers();\n\t\tif (!this.gitPaths) return;\n\n\t\tconst pollGitHead = shouldPollGitHead(this.gitPaths.repoDir);\n\n\t\t// Watch the directory containing HEAD, not HEAD itself.\n\t\t// Git uses atomic writes (write temp, rename over HEAD), which changes the inode.\n\t\t// fs.watch on a file stops working after the inode changes.\n\t\tthis.headWatcher = watchWithErrorHandler(\n\t\t\tdirname(this.gitPaths.headPath),\n\t\t\t(_eventType, filename) => {\n\t\t\t\tif (!filename || filename === \"HEAD\") {\n\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => this.handleGitWatcherError(),\n\t\t);\n\t\tif (pollGitHead) {\n\t\t\tthis.headWatchFilePath = this.gitPaths.headPath;\n\t\t\tthis.headWatchFileListener = (current, previous) => {\n\t\t\t\tif (\n\t\t\t\t\tcurrent.mtimeMs !== previous.mtimeMs ||\n\t\t\t\t\tcurrent.ctimeMs !== previous.ctimeMs ||\n\t\t\t\t\tcurrent.size !== previous.size\n\t\t\t\t) {\n\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t}\n\t\t\t};\n\t\t\twatchFile(this.headWatchFilePath, { interval: 1000 }, this.headWatchFileListener);\n\t\t}\n\t\tif (!this.headWatcher && !pollGitHead) {\n\t\t\treturn;\n\t\t}\n\n\t\t// In reftable repos, branch switches update files in the reftable directory\n\t\t// instead of HEAD. Watch it separately so the footer picks up those changes.\n\t\tconst reftableDir = join(this.gitPaths.commonGitDir, \"reftable\");\n\t\tif (existsSync(reftableDir)) {\n\t\t\tthis.reftableWatcher = watchWithErrorHandler(\n\t\t\t\treftableDir,\n\t\t\t\t() => {\n\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t},\n\t\t\t\t() => this.handleGitWatcherError(),\n\t\t\t);\n\t\t\tif (!this.reftableWatcher) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst tablesListPath = join(reftableDir, \"tables.list\");\n\t\t\tif (existsSync(tablesListPath)) {\n\t\t\t\tthis.reftableTablesListPath = tablesListPath;\n\t\t\t\tthis.reftableTablesListWatcher = watchWithErrorHandler(\n\t\t\t\t\ttablesListPath,\n\t\t\t\t\t() => {\n\t\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t\t},\n\t\t\t\t\t() => this.handleGitWatcherError(),\n\t\t\t\t);\n\t\t\t\tif (!this.reftableTablesListWatcher) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\twatchFile(tablesListPath, { interval: 250 }, (current, previous) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrent.mtimeMs !== previous.mtimeMs ||\n\t\t\t\t\t\tcurrent.ctimeMs !== previous.ctimeMs ||\n\t\t\t\t\t\tcurrent.size !== previous.size\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Read-only view for extensions - excludes setExtensionStatus, setAvailableProviderCount and dispose */\nexport type ReadonlyFooterDataProvider = Pick<\n\tFooterDataProvider,\n\t| \"getGitBranch\"\n\t| \"getExtensionStatuses\"\n\t| \"getAvailableProviderCount\"\n\t| \"onBranchChange\"\n\t| \"getCpuPercent\"\n\t| \"getMemoryRssBytes\"\n>;\n"]}
|
|
1
|
+
{"version":3,"file":"footer-data-provider.d.ts","sourceRoot":"","sources":["../../src/core/footer-data-provider.ts"],"names":[],"mappings":"AAKA,OAAO,EAA2B,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AA2F9F;;;GAGG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAO;IAEhD,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,qBAAqB,CAA4D;IACzF,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,yBAAyB,CAA0B;IAC3D,OAAO,CAAC,sBAAsB,CAAuB;IACrD,OAAO,CAAC,qBAAqB,CAAyB;IACtD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAiB;IAEvC,YAAY,GAAG,EAAE,MAAM,EAMtB;IAED,2EAA2E;IAC3E,YAAY,IAAI,MAAM,GAAG,IAAI,CAK5B;IAED,wDAAwD;IACxD,oBAAoB,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAElD;IAED,qEAAqE;IACrE,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAG/C;IAED,qCAAqC;IACrC,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAM9D;IAED,yCAAyC;IACzC,sBAAsB,IAAI,IAAI,CAE7B;IAED,4EAA4E;IAC5E,yBAAyB,IAAI,MAAM,CAElC;IAED,6EAA6E;IAC7E,aAAa,IAAI,MAAM,GAAG,IAAI,CAE7B;IAED,kFAAkF;IAClF,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjC;IAED,uBAAuB,IAAI,sBAAsB,CAEhD;IAED,gDAAgD;IAChD,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE7C;IAED,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAexB;IAED,wBAAwB;IACxB,OAAO,IAAI,IAAI,CASd;IAED,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,eAAe;YAYT,qBAAqB;IA0BnC,OAAO,CAAC,oBAAoB;YAcd,qBAAqB;IAgBnC,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,eAAe;CA2EvB;AAED,yGAAyG;AACzG,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC5C,kBAAkB,EAChB,cAAc,GACd,sBAAsB,GACtB,2BAA2B,GAC3B,gBAAgB,GAChB,eAAe,GACf,mBAAmB,GACnB,yBAAyB,CAC3B,CAAC","sourcesContent":["import { type ExecFileException, execFile, spawnSync } from \"child_process\";\nimport { existsSync, type FSWatcher, readFileSync, type Stats, statSync, unwatchFile, watchFile } from \"fs\";\nimport { dirname, join, resolve } from \"path\";\nimport { closeWatcher, FS_WATCH_RETRY_DELAY_MS, watchWithErrorHandler } from \"../utils/fs-watch.ts\";\nimport { MetricsSampler } from \"./metrics-sampler.ts\";\nimport { evaluatePiPackageIntake, type PiPackageIntakeSummary } from \"./pi-package-intake.ts\";\n\ntype GitPaths = {\n\trepoDir: string;\n\tcommonGitDir: string;\n\theadPath: string;\n};\n\n/**\n * Find git metadata paths by walking up from cwd.\n * Handles both regular git repos (.git is a directory) and worktrees (.git is a file).\n */\nfunction findGitPaths(cwd: string): GitPaths | null {\n\tlet dir = cwd;\n\twhile (true) {\n\t\tconst gitPath = join(dir, \".git\");\n\t\tif (existsSync(gitPath)) {\n\t\t\ttry {\n\t\t\t\tconst stat = statSync(gitPath);\n\t\t\t\tif (stat.isFile()) {\n\t\t\t\t\tconst content = readFileSync(gitPath, \"utf8\").trim();\n\t\t\t\t\tif (content.startsWith(\"gitdir: \")) {\n\t\t\t\t\t\tconst gitDir = resolve(dir, content.slice(8).trim());\n\t\t\t\t\t\tconst headPath = join(gitDir, \"HEAD\");\n\t\t\t\t\t\tif (!existsSync(headPath)) return null;\n\t\t\t\t\t\tconst commonDirPath = join(gitDir, \"commondir\");\n\t\t\t\t\t\tconst commonGitDir = existsSync(commonDirPath)\n\t\t\t\t\t\t\t? resolve(gitDir, readFileSync(commonDirPath, \"utf8\").trim())\n\t\t\t\t\t\t\t: gitDir;\n\t\t\t\t\t\treturn { repoDir: dir, commonGitDir, headPath };\n\t\t\t\t\t}\n\t\t\t\t} else if (stat.isDirectory()) {\n\t\t\t\t\tconst headPath = join(gitPath, \"HEAD\");\n\t\t\t\t\tif (!existsSync(headPath)) return null;\n\t\t\t\t\treturn { repoDir: dir, commonGitDir: gitPath, headPath };\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) return null;\n\t\tdir = parent;\n\t}\n}\n\n/** Ask git for the current branch. Returns null on detached HEAD or if git is unavailable. */\nfunction resolveBranchWithGitSync(repoDir: string): string | null {\n\tconst result = spawnSync(\"git\", [\"--no-optional-locks\", \"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], {\n\t\tcwd: repoDir,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t});\n\tconst branch = result.status === 0 ? result.stdout.trim() : \"\";\n\treturn branch || null;\n}\n\n/** Ask git for the current branch asynchronously. Returns null on detached HEAD or if git is unavailable. */\nfunction resolveBranchWithGitAsync(repoDir: string): Promise<string | null> {\n\treturn new Promise((resolvePromise) => {\n\t\texecFile(\n\t\t\t\"git\",\n\t\t\t[\"--no-optional-locks\", \"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"],\n\t\t\t{\n\t\t\t\tcwd: repoDir,\n\t\t\t\tencoding: \"utf8\",\n\t\t\t},\n\t\t\t(error: ExecFileException | null, stdout: string) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tresolvePromise(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst branch = stdout.trim();\n\t\t\t\tresolvePromise(branch || null);\n\t\t\t},\n\t\t);\n\t});\n}\n\nfunction isWslEnvironment(): boolean {\n\treturn process.platform === \"linux\" && !!(process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP);\n}\n\nfunction isWindowsMountedRepoPath(repoDir: string): boolean {\n\treturn /^\\/mnt\\/[a-z](?:\\/|$)/i.test(repoDir);\n}\n\nfunction shouldPollGitHead(repoDir: string): boolean {\n\treturn isWslEnvironment() && isWindowsMountedRepoPath(repoDir);\n}\n\n/**\n * Provides git branch and extension statuses - data not otherwise accessible to extensions.\n * Token stats, model info available via ctx.sessionManager and ctx.model.\n */\nexport class FooterDataProvider {\n\tprivate cwd: string;\n\tprivate static readonly WATCH_DEBOUNCE_MS = 500;\n\n\tprivate extensionStatuses = new Map<string, string>();\n\tprivate cachedBranch: string | null | undefined = undefined;\n\tprivate gitPaths: GitPaths | null | undefined = undefined;\n\tprivate headWatcher: FSWatcher | null = null;\n\tprivate headWatchFilePath: string | null = null;\n\tprivate headWatchFileListener: ((current: Stats, previous: Stats) => void) | null = null;\n\tprivate reftableWatcher: FSWatcher | null = null;\n\tprivate reftableTablesListWatcher: FSWatcher | null = null;\n\tprivate reftableTablesListPath: string | null = null;\n\tprivate branchChangeCallbacks = new Set<() => void>();\n\tprivate availableProviderCount = 0;\n\tprivate refreshTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate gitWatcherRetryTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate refreshInFlight = false;\n\tprivate refreshPending = false;\n\tprivate disposed = false;\n\tprivate metricsSampler: MetricsSampler;\n\n\tconstructor(cwd: string) {\n\t\tthis.cwd = cwd;\n\t\tthis.gitPaths = findGitPaths(cwd);\n\t\tthis.setupGitWatcher();\n\t\tthis.metricsSampler = new MetricsSampler();\n\t\tthis.metricsSampler.start();\n\t}\n\n\t/** Current git branch, null if not in repo, \"detached\" if detached HEAD */\n\tgetGitBranch(): string | null {\n\t\tif (this.cachedBranch === undefined) {\n\t\t\tthis.cachedBranch = this.resolveGitBranchSync();\n\t\t}\n\t\treturn this.cachedBranch;\n\t}\n\n\t/** Extension status texts set via ctx.ui.setStatus() */\n\tgetExtensionStatuses(): ReadonlyMap<string, string> {\n\t\treturn this.extensionStatuses;\n\t}\n\n\t/** Subscribe to git branch changes. Returns unsubscribe function. */\n\tonBranchChange(callback: () => void): () => void {\n\t\tthis.branchChangeCallbacks.add(callback);\n\t\treturn () => this.branchChangeCallbacks.delete(callback);\n\t}\n\n\t/** Internal: set extension status */\n\tsetExtensionStatus(key: string, text: string | undefined): void {\n\t\tif (text === undefined) {\n\t\t\tthis.extensionStatuses.delete(key);\n\t\t} else {\n\t\t\tthis.extensionStatuses.set(key, text);\n\t\t}\n\t}\n\n\t/** Internal: clear extension statuses */\n\tclearExtensionStatuses(): void {\n\t\tthis.extensionStatuses.clear();\n\t}\n\n\t/** Number of unique providers with available models (for footer display) */\n\tgetAvailableProviderCount(): number {\n\t\treturn this.availableProviderCount;\n\t}\n\n\t/** Most recent process CPU percent (0-100), or `null` if not yet sampled. */\n\tgetCpuPercent(): number | null {\n\t\treturn this.metricsSampler.getCpuPercent();\n\t}\n\n\t/** Most recent process RSS memory size in bytes, or `null` if not yet sampled. */\n\tgetMemoryRssBytes(): number | null {\n\t\treturn this.metricsSampler.getMemoryRssBytes();\n\t}\n\n\tgetPackageIntakeSummary(): PiPackageIntakeSummary {\n\t\treturn evaluatePiPackageIntake().summary;\n\t}\n\n\t/** Internal: update available provider count */\n\tsetAvailableProviderCount(count: number): void {\n\t\tthis.availableProviderCount = count;\n\t}\n\n\tsetCwd(cwd: string): void {\n\t\tif (this.cwd === cwd) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.cwd = cwd;\n\t\tif (this.refreshTimer) {\n\t\t\tclearTimeout(this.refreshTimer);\n\t\t\tthis.refreshTimer = null;\n\t\t}\n\t\tthis.clearGitWatchers();\n\t\tthis.cachedBranch = undefined;\n\t\tthis.gitPaths = findGitPaths(cwd);\n\t\tthis.setupGitWatcher();\n\t\tthis.notifyBranchChange();\n\t}\n\n\t/** Internal: cleanup */\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tif (this.refreshTimer) {\n\t\t\tclearTimeout(this.refreshTimer);\n\t\t\tthis.refreshTimer = null;\n\t\t}\n\t\tthis.clearGitWatchers();\n\t\tthis.branchChangeCallbacks.clear();\n\t\tthis.metricsSampler.stop();\n\t}\n\n\tprivate notifyBranchChange(): void {\n\t\tfor (const cb of this.branchChangeCallbacks) cb();\n\t}\n\n\tprivate scheduleRefresh(): void {\n\t\tif (this.disposed || this.refreshTimer) return;\n\t\tif (this.refreshInFlight) {\n\t\t\tthis.refreshPending = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.refreshTimer = setTimeout(() => {\n\t\t\tthis.refreshTimer = null;\n\t\t\tvoid this.refreshGitBranchAsync();\n\t\t}, FooterDataProvider.WATCH_DEBOUNCE_MS);\n\t}\n\n\tprivate async refreshGitBranchAsync(): Promise<void> {\n\t\tif (this.disposed) return;\n\t\tif (this.refreshInFlight) {\n\t\t\tthis.refreshPending = true;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.refreshInFlight = true;\n\t\ttry {\n\t\t\tconst nextBranch = await this.resolveGitBranchAsync();\n\t\t\tif (this.disposed) return;\n\t\t\tif (this.cachedBranch !== undefined && this.cachedBranch !== nextBranch) {\n\t\t\t\tthis.cachedBranch = nextBranch;\n\t\t\t\tthis.notifyBranchChange();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.cachedBranch = nextBranch;\n\t\t} finally {\n\t\t\tthis.refreshInFlight = false;\n\t\t\tif (this.refreshPending && !this.disposed) {\n\t\t\t\tthis.refreshPending = false;\n\t\t\t\tthis.scheduleRefresh();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate resolveGitBranchSync(): string | null {\n\t\ttry {\n\t\t\tif (!this.gitPaths) return null;\n\t\t\tconst content = readFileSync(this.gitPaths.headPath, \"utf8\").trim();\n\t\t\tif (content.startsWith(\"ref: refs/heads/\")) {\n\t\t\t\tconst branch = content.slice(16);\n\t\t\t\treturn branch === \".invalid\" ? (resolveBranchWithGitSync(this.gitPaths.repoDir) ?? \"detached\") : branch;\n\t\t\t}\n\t\t\treturn \"detached\";\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate async resolveGitBranchAsync(): Promise<string | null> {\n\t\ttry {\n\t\t\tif (!this.gitPaths) return null;\n\t\t\tconst content = readFileSync(this.gitPaths.headPath, \"utf8\").trim();\n\t\t\tif (content.startsWith(\"ref: refs/heads/\")) {\n\t\t\t\tconst branch = content.slice(16);\n\t\t\t\treturn branch === \".invalid\"\n\t\t\t\t\t? ((await resolveBranchWithGitAsync(this.gitPaths.repoDir)) ?? \"detached\")\n\t\t\t\t\t: branch;\n\t\t\t}\n\t\t\treturn \"detached\";\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate clearGitWatchers(): void {\n\t\tcloseWatcher(this.headWatcher);\n\t\tthis.headWatcher = null;\n\t\tif (this.headWatchFilePath && this.headWatchFileListener) {\n\t\t\tunwatchFile(this.headWatchFilePath, this.headWatchFileListener);\n\t\t\tthis.headWatchFilePath = null;\n\t\t\tthis.headWatchFileListener = null;\n\t\t}\n\t\tcloseWatcher(this.reftableWatcher);\n\t\tthis.reftableWatcher = null;\n\t\tcloseWatcher(this.reftableTablesListWatcher);\n\t\tthis.reftableTablesListWatcher = null;\n\t\tif (this.reftableTablesListPath) {\n\t\t\tunwatchFile(this.reftableTablesListPath);\n\t\t\tthis.reftableTablesListPath = null;\n\t\t}\n\t\tif (this.gitWatcherRetryTimer) {\n\t\t\tclearTimeout(this.gitWatcherRetryTimer);\n\t\t\tthis.gitWatcherRetryTimer = null;\n\t\t}\n\t}\n\n\tprivate scheduleGitWatcherRetry(): void {\n\t\tif (this.disposed || this.gitWatcherRetryTimer) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.gitWatcherRetryTimer = setTimeout(() => {\n\t\t\tthis.gitWatcherRetryTimer = null;\n\t\t\tthis.setupGitWatcher();\n\t\t}, FS_WATCH_RETRY_DELAY_MS);\n\t}\n\n\tprivate handleGitWatcherError(): void {\n\t\tthis.clearGitWatchers();\n\t\tthis.scheduleGitWatcherRetry();\n\t}\n\n\tprivate setupGitWatcher(): void {\n\t\tthis.clearGitWatchers();\n\t\tif (!this.gitPaths) return;\n\n\t\tconst pollGitHead = shouldPollGitHead(this.gitPaths.repoDir);\n\n\t\t// Watch the directory containing HEAD, not HEAD itself.\n\t\t// Git uses atomic writes (write temp, rename over HEAD), which changes the inode.\n\t\t// fs.watch on a file stops working after the inode changes.\n\t\tthis.headWatcher = watchWithErrorHandler(\n\t\t\tdirname(this.gitPaths.headPath),\n\t\t\t(_eventType, filename) => {\n\t\t\t\tif (!filename || filename === \"HEAD\") {\n\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => this.handleGitWatcherError(),\n\t\t);\n\t\tif (pollGitHead) {\n\t\t\tthis.headWatchFilePath = this.gitPaths.headPath;\n\t\t\tthis.headWatchFileListener = (current, previous) => {\n\t\t\t\tif (\n\t\t\t\t\tcurrent.mtimeMs !== previous.mtimeMs ||\n\t\t\t\t\tcurrent.ctimeMs !== previous.ctimeMs ||\n\t\t\t\t\tcurrent.size !== previous.size\n\t\t\t\t) {\n\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t}\n\t\t\t};\n\t\t\twatchFile(this.headWatchFilePath, { interval: 1000 }, this.headWatchFileListener);\n\t\t}\n\t\tif (!this.headWatcher && !pollGitHead) {\n\t\t\treturn;\n\t\t}\n\n\t\t// In reftable repos, branch switches update files in the reftable directory\n\t\t// instead of HEAD. Watch it separately so the footer picks up those changes.\n\t\tconst reftableDir = join(this.gitPaths.commonGitDir, \"reftable\");\n\t\tif (existsSync(reftableDir)) {\n\t\t\tthis.reftableWatcher = watchWithErrorHandler(\n\t\t\t\treftableDir,\n\t\t\t\t() => {\n\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t},\n\t\t\t\t() => this.handleGitWatcherError(),\n\t\t\t);\n\t\t\tif (!this.reftableWatcher) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst tablesListPath = join(reftableDir, \"tables.list\");\n\t\t\tif (existsSync(tablesListPath)) {\n\t\t\t\tthis.reftableTablesListPath = tablesListPath;\n\t\t\t\tthis.reftableTablesListWatcher = watchWithErrorHandler(\n\t\t\t\t\ttablesListPath,\n\t\t\t\t\t() => {\n\t\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t\t},\n\t\t\t\t\t() => this.handleGitWatcherError(),\n\t\t\t\t);\n\t\t\t\tif (!this.reftableTablesListWatcher) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\twatchFile(tablesListPath, { interval: 250 }, (current, previous) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrent.mtimeMs !== previous.mtimeMs ||\n\t\t\t\t\t\tcurrent.ctimeMs !== previous.ctimeMs ||\n\t\t\t\t\t\tcurrent.size !== previous.size\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.scheduleRefresh();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Read-only view for extensions - excludes setExtensionStatus, setAvailableProviderCount and dispose */\nexport type ReadonlyFooterDataProvider = Pick<\n\tFooterDataProvider,\n\t| \"getGitBranch\"\n\t| \"getExtensionStatuses\"\n\t| \"getAvailableProviderCount\"\n\t| \"onBranchChange\"\n\t| \"getCpuPercent\"\n\t| \"getMemoryRssBytes\"\n\t| \"getPackageIntakeSummary\"\n>;\n"]}
|