specrails-core 5.3.0 → 5.4.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/dist/agent-runtime/capabilities.d.ts +27 -0
- package/dist/agent-runtime/capabilities.js +73 -0
- package/dist/agent-runtime/capabilities.js.map +1 -0
- package/dist/agent-runtime/cli-executor.d.ts +9 -0
- package/dist/agent-runtime/cli-executor.js +100 -30
- package/dist/agent-runtime/cli-executor.js.map +1 -1
- package/dist/agent-runtime/cli.d.ts +1 -0
- package/dist/agent-runtime/cli.js +59 -11
- package/dist/agent-runtime/cli.js.map +1 -1
- package/dist/agent-runtime/codex-schema.d.ts +4 -0
- package/dist/agent-runtime/codex-schema.js +31 -0
- package/dist/agent-runtime/codex-schema.js.map +1 -0
- package/dist/agent-runtime/config.d.ts +4 -0
- package/dist/agent-runtime/config.js +110 -9
- package/dist/agent-runtime/config.js.map +1 -1
- package/dist/agent-runtime/core-host.d.ts +9 -1
- package/dist/agent-runtime/core-host.js +55 -20
- package/dist/agent-runtime/core-host.js.map +1 -1
- package/dist/agent-runtime/efficiency-summary.d.ts +67 -0
- package/dist/agent-runtime/efficiency-summary.js +52 -0
- package/dist/agent-runtime/efficiency-summary.js.map +1 -0
- package/dist/agent-runtime/efficiency-types.d.ts +60 -0
- package/dist/agent-runtime/efficiency-types.js +8 -0
- package/dist/agent-runtime/efficiency-types.js.map +1 -0
- package/dist/agent-runtime/efficiency.d.ts +5 -0
- package/dist/agent-runtime/efficiency.js +35 -0
- package/dist/agent-runtime/efficiency.js.map +1 -0
- package/dist/agent-runtime/evaluation-corpus.d.ts +13 -0
- package/dist/agent-runtime/evaluation-corpus.js +8 -0
- package/dist/agent-runtime/evaluation-corpus.js.map +1 -0
- package/dist/agent-runtime/evaluation.d.ts +43 -0
- package/dist/agent-runtime/evaluation.js +171 -0
- package/dist/agent-runtime/evaluation.js.map +1 -0
- package/dist/agent-runtime/executor-types.d.ts +35 -2
- package/dist/agent-runtime/executor-types.js.map +1 -1
- package/dist/agent-runtime/executors.d.ts +1 -0
- package/dist/agent-runtime/executors.js +4 -0
- package/dist/agent-runtime/executors.js.map +1 -1
- package/dist/agent-runtime/graph/artifacts.d.ts +8 -22
- package/dist/agent-runtime/graph/artifacts.js +99 -73
- package/dist/agent-runtime/graph/artifacts.js.map +1 -1
- package/dist/agent-runtime/graph/nodes.d.ts +3 -0
- package/dist/agent-runtime/graph/nodes.js +73 -26
- package/dist/agent-runtime/graph/nodes.js.map +1 -1
- package/dist/agent-runtime/graph/roles.d.ts +4 -1
- package/dist/agent-runtime/graph/roles.js +100 -36
- package/dist/agent-runtime/graph/roles.js.map +1 -1
- package/dist/agent-runtime/graph/state.d.ts +8 -0
- package/dist/agent-runtime/graph/state.js.map +1 -1
- package/dist/agent-runtime/index.d.ts +7 -1
- package/dist/agent-runtime/index.js +7 -1
- package/dist/agent-runtime/index.js.map +1 -1
- package/dist/agent-runtime/kimi-acp.d.ts +4 -0
- package/dist/agent-runtime/kimi-acp.js +20 -9
- package/dist/agent-runtime/kimi-acp.js.map +1 -1
- package/dist/agent-runtime/openai-executor.d.ts +8 -0
- package/dist/agent-runtime/openai-executor.js +28 -10
- package/dist/agent-runtime/openai-executor.js.map +1 -1
- package/dist/agent-runtime/openspec-tool-server.d.ts +1 -0
- package/dist/agent-runtime/openspec-tool-server.js +37 -0
- package/dist/agent-runtime/openspec-tool-server.js.map +1 -0
- package/dist/agent-runtime/openspec.d.ts +123 -0
- package/dist/agent-runtime/openspec.js +263 -0
- package/dist/agent-runtime/openspec.js.map +1 -0
- package/dist/agent-runtime/prompts.d.ts +5 -1
- package/dist/agent-runtime/prompts.js +59 -40
- package/dist/agent-runtime/prompts.js.map +1 -1
- package/dist/agent-runtime/provider-diagnostic.d.ts +2 -0
- package/dist/agent-runtime/provider-diagnostic.js +25 -0
- package/dist/agent-runtime/provider-diagnostic.js.map +1 -0
- package/dist/agent-runtime/repository-context.d.ts +25 -0
- package/dist/agent-runtime/repository-context.js +100 -0
- package/dist/agent-runtime/repository-context.js.map +1 -0
- package/dist/agent-runtime/review-context.d.ts +14 -0
- package/dist/agent-runtime/review-context.js +41 -0
- package/dist/agent-runtime/review-context.js.map +1 -0
- package/dist/agent-runtime/role-routing.d.ts +10 -0
- package/dist/agent-runtime/role-routing.js +29 -0
- package/dist/agent-runtime/role-routing.js.map +1 -0
- package/dist/agent-runtime/role-state.d.ts +19 -0
- package/dist/agent-runtime/role-state.js +24 -0
- package/dist/agent-runtime/role-state.js.map +1 -0
- package/dist/agent-runtime/runtime-identity.d.ts +11 -0
- package/dist/agent-runtime/runtime-identity.js +33 -0
- package/dist/agent-runtime/runtime-identity.js.map +1 -0
- package/dist/agent-runtime/tool-event.d.ts +3 -0
- package/dist/agent-runtime/tool-event.js +24 -0
- package/dist/agent-runtime/tool-event.js.map +1 -0
- package/dist/agent-runtime/verification-plan.d.ts +55 -0
- package/dist/agent-runtime/verification-plan.js +206 -0
- package/dist/agent-runtime/verification-plan.js.map +1 -0
- package/dist/agent-runtime/workflow-types.d.ts +17 -1
- package/dist/agent-runtime/workflow.js +28 -1
- package/dist/agent-runtime/workflow.js.map +1 -1
- package/dist/agent-runtime/workspace-tools.d.ts +4 -0
- package/dist/agent-runtime/workspace-tools.js +182 -20
- package/dist/agent-runtime/workspace-tools.js.map +1 -1
- package/dist/installer/phases/scaffold.js +39 -109
- package/dist/installer/phases/scaffold.js.map +1 -1
- package/dist/installer/runtime/pipeline-state.d.ts +142 -1
- package/dist/installer/runtime/pipeline-state.js +477 -28
- package/dist/installer/runtime/pipeline-state.js.map +1 -1
- package/docs/agent-runtime-efficiency.md +65 -0
- package/docs/agent-runtime.md +86 -15
- package/integration-contract.json +2 -1
- package/package.json +5 -2
- package/schemas/agent-runtime.schema.json +25 -3
- package/schemas/fixtures/runtime-efficiency-summary.v1.json +790 -0
- package/templates/codex-skills/batch-implement/SKILL.md +33 -58
- package/templates/codex-skills/implement/SKILL.md +21 -124
- package/templates/codex-skills/retry/SKILL.md +8 -34
- package/templates/commands/specrails/batch-implement.md +21 -16
- package/templates/commands/specrails/implement.md +17 -276
- package/templates/commands/specrails/retry.md +6 -34
- package/templates/gemini-commands/batch-implement.toml +34 -28
- package/templates/gemini-commands/implement.toml +34 -55
- package/templates/gemini-commands/retry.toml +10 -16
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AgentRole } from './executor-types.js';
|
|
2
|
+
import type { RepositoryContextSnapshot } from './repository-context.js';
|
|
3
|
+
export interface RoleSession {
|
|
4
|
+
identity: string;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
context: RepositoryContextSnapshot;
|
|
7
|
+
}
|
|
8
|
+
export interface RoleExecutionState {
|
|
9
|
+
sessions: Partial<Record<AgentRole, RoleSession>>;
|
|
10
|
+
routes: Partial<Record<AgentRole, {
|
|
11
|
+
tier: 'base' | 'escalation';
|
|
12
|
+
reason: string;
|
|
13
|
+
attemptId: string;
|
|
14
|
+
}>>;
|
|
15
|
+
}
|
|
16
|
+
/** Host-owned auxiliary state lives under the workflow's existing run lease.
|
|
17
|
+
* A corrupted packet fails explicitly; it is never used as missing context. */
|
|
18
|
+
export declare function readRoleState(directory: string): RoleExecutionState;
|
|
19
|
+
export declare function writeRoleState(directory: string, data: RoleExecutionState): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fingerprint } from './durable-store.js';
|
|
4
|
+
import { write } from './graph/artifacts.js';
|
|
5
|
+
/** Host-owned auxiliary state lives under the workflow's existing run lease.
|
|
6
|
+
* A corrupted packet fails explicitly; it is never used as missing context. */
|
|
7
|
+
export function readRoleState(directory) {
|
|
8
|
+
const file = path.join(directory, 'role-execution.json');
|
|
9
|
+
if (!existsSync(file))
|
|
10
|
+
return { sessions: {}, routes: {} };
|
|
11
|
+
if (statSync(file).size > 2 * 1024 * 1024)
|
|
12
|
+
throw new Error('Role execution state exceeds its size limit');
|
|
13
|
+
const envelope = JSON.parse(readFileSync(file, 'utf8'));
|
|
14
|
+
if (envelope.schemaVersion !== 1 || envelope.checksum !== fingerprint(envelope.data) || !envelope.data?.sessions || !envelope.data?.routes)
|
|
15
|
+
throw new Error('Role execution state failed its integrity check');
|
|
16
|
+
return envelope.data;
|
|
17
|
+
}
|
|
18
|
+
export function writeRoleState(directory, data) {
|
|
19
|
+
const content = JSON.stringify({ schemaVersion: 1, checksum: fingerprint(data), data }) + '\n';
|
|
20
|
+
if (Buffer.byteLength(content) > 2 * 1024 * 1024)
|
|
21
|
+
throw new Error('Role execution state exceeds its size limit');
|
|
22
|
+
write(path.join(directory, 'role-execution.json'), content);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=role-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-state.js","sourceRoot":"","sources":["../../src/agent-runtime/role-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAa5C;+EAC+E;AAC/E,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAA;IACxD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAC1D,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;IACzG,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IACvD,IAAI,QAAQ,CAAC,aAAa,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,KAAK,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IAC9M,OAAO,QAAQ,CAAC,IAA0B,CAAA;AAC5C,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,IAAwB;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IAC9F,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;IAChH,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EAAE,OAAO,CAAC,CAAA;AAC7D,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface RuntimeIdentity {
|
|
2
|
+
packageVersion: string;
|
|
3
|
+
workflowVersion: string;
|
|
4
|
+
instructionsVersion: string;
|
|
5
|
+
packageIntegrity: string;
|
|
6
|
+
apiVersion: 1;
|
|
7
|
+
}
|
|
8
|
+
/** Hash the executable package, not a mutable path or its advertised version.
|
|
9
|
+
* Dependencies are retained/verified by the host package snapshot separately. */
|
|
10
|
+
export declare function runtimePackageIntegrity(root?: string): string;
|
|
11
|
+
export declare function sameRuntimeIdentity(left: RuntimeIdentity, right: RuntimeIdentity): boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
/** Hash the executable package, not a mutable path or its advertised version.
|
|
6
|
+
* Dependencies are retained/verified by the host package snapshot separately. */
|
|
7
|
+
export function runtimePackageIntegrity(root = fileURLToPath(new URL('../../', import.meta.url))) {
|
|
8
|
+
const hash = createHash('sha256');
|
|
9
|
+
const visit = (relative) => {
|
|
10
|
+
const file = path.join(root, relative);
|
|
11
|
+
const stat = lstatSync(file);
|
|
12
|
+
if (stat.isSymbolicLink())
|
|
13
|
+
throw new Error('Runtime package contains an unsupported symbolic link: ' + relative);
|
|
14
|
+
if (stat.isDirectory()) {
|
|
15
|
+
for (const name of readdirSync(file).sort())
|
|
16
|
+
visit(path.posix.join(relative, name));
|
|
17
|
+
}
|
|
18
|
+
else if (stat.isFile()) {
|
|
19
|
+
hash.update(JSON.stringify([relative, stat.size])).update('\0').update(readFileSync(file)).update('\0');
|
|
20
|
+
}
|
|
21
|
+
else
|
|
22
|
+
throw new Error('Runtime package contains a nonregular file: ' + relative);
|
|
23
|
+
};
|
|
24
|
+
for (const entry of ['package.json', 'dist', 'bin', 'templates', 'schemas', 'commands', 'integration-contract.json', 'pinned-versions.json']) {
|
|
25
|
+
if (existsSync(path.join(root, entry)))
|
|
26
|
+
visit(entry);
|
|
27
|
+
}
|
|
28
|
+
return 'sha256:' + hash.digest('hex');
|
|
29
|
+
}
|
|
30
|
+
export function sameRuntimeIdentity(left, right) {
|
|
31
|
+
return ['packageVersion', 'workflowVersion', 'instructionsVersion', 'packageIntegrity', 'apiVersion'].every(key => left[key] === right[key]);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=runtime-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-identity.js","sourceRoot":"","sources":["../../src/agent-runtime/runtime-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC1E,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AASxC;iFACiF;AACjF,MAAM,UAAU,uBAAuB,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9F,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IACjC,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAQ,EAAE;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,IAAI,CAAC,cAAc,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,GAAG,QAAQ,CAAC,CAAA;QAChH,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;QACrF,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACzG,CAAC;;YAAM,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,QAAQ,CAAC,CAAA;IACnF,CAAC,CAAA;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,2BAA2B,EAAE,sBAAsB,CAAC,EAAE,CAAC;QAC7I,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAqB,EAAE,KAAsB;IAC/E,OAAO,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,YAAY,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAA4B,CAAC,KAAK,KAAK,CAAC,GAA4B,CAAC,CAAC,CAAA;AAChM,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function object(value) { return value && typeof value === 'object' && !Array.isArray(value) ? value : {}; }
|
|
2
|
+
function shorten(value, limit = 160) {
|
|
3
|
+
if (typeof value !== 'string' || !value.trim())
|
|
4
|
+
return undefined;
|
|
5
|
+
const single = value.replace(/\s+/g, ' ').trim();
|
|
6
|
+
return single.length > limit ? single.slice(0, limit - 1) + '…' : single;
|
|
7
|
+
}
|
|
8
|
+
/** Short, human-readable tool activity for host logs; never a transcript. */
|
|
9
|
+
export function toolEvent(tool, input) {
|
|
10
|
+
if (typeof input === 'string') {
|
|
11
|
+
try {
|
|
12
|
+
input = JSON.parse(input);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
input = {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const args = object(input);
|
|
19
|
+
const detail = shorten(args.file_path ?? args.path ?? (Array.isArray(args.paths) ? args.paths[0] : undefined) ?? args.command ?? args.pattern ?? args.query ?? args.notebook_path ?? args.url ?? (typeof args.action === 'string' ? [args.action, args.artifact].filter(Boolean).join(' ') : undefined));
|
|
20
|
+
const targetPaths = [args.file_path, args.path, args.notebook_path, ...(Array.isArray(args.paths) ? args.paths : [])].filter((value) => typeof value === 'string' && value.length > 0);
|
|
21
|
+
const cwd = args.workdir ?? args.cwd;
|
|
22
|
+
return { kind: 'tool-start', tool, ...(detail ? { detail } : {}), ...(targetPaths.length ? { targetPaths } : {}), ...(typeof cwd === 'string' ? { cwd } : {}) };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=tool-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-event.js","sourceRoot":"","sources":["../../src/agent-runtime/tool-event.ts"],"names":[],"mappings":"AACA,SAAS,MAAM,CAAC,KAAc,IAA6B,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAgC,CAAC,CAAC,CAAC,EAAE,CAAA,CAAC,CAAC;AACvK,SAAS,OAAO,CAAC,KAAc,EAAE,KAAK,GAAG,GAAG;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,SAAS,CAAA;IAChE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IAChD,OAAO,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAA;AAC1E,CAAC;AACD,6EAA6E;AAC7E,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAc;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAAC,IAAI,CAAC;YAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,KAAK,GAAG,EAAE,CAAA;QAAC,CAAC;IAAC,CAAC;IACzF,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;IACxS,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACvM,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAA;IACpC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;AACjK,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type PipelineContext, type VerificationCommand } from '../installer/runtime/pipeline-state.js';
|
|
2
|
+
export interface ProposedCheck {
|
|
3
|
+
kind: 'command' | 'harness';
|
|
4
|
+
key: string;
|
|
5
|
+
repositoryId: string;
|
|
6
|
+
label: string;
|
|
7
|
+
command: string;
|
|
8
|
+
args: string[];
|
|
9
|
+
cwd?: string;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
entrypoint?: string;
|
|
12
|
+
files?: Array<{
|
|
13
|
+
path: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export interface HarnessSource {
|
|
18
|
+
path: string;
|
|
19
|
+
hash: string;
|
|
20
|
+
byteCount: number;
|
|
21
|
+
}
|
|
22
|
+
export interface PlanEntry {
|
|
23
|
+
id: string;
|
|
24
|
+
key: string;
|
|
25
|
+
label: string;
|
|
26
|
+
origins: Array<'host' | 'architect' | 'developer'>;
|
|
27
|
+
command: VerificationCommand;
|
|
28
|
+
harness?: {
|
|
29
|
+
hash: string;
|
|
30
|
+
entrypoint: string;
|
|
31
|
+
sources: HarnessSource[];
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface VerificationPlan {
|
|
35
|
+
schemaVersion: 1;
|
|
36
|
+
runId: string;
|
|
37
|
+
revision: number;
|
|
38
|
+
planHash: string;
|
|
39
|
+
integrity: string;
|
|
40
|
+
scopeHash: string;
|
|
41
|
+
executionPolicy: {
|
|
42
|
+
maxConcurrency: number;
|
|
43
|
+
};
|
|
44
|
+
baseline: PlanEntry[];
|
|
45
|
+
developer: PlanEntry[];
|
|
46
|
+
entries: PlanEntry[];
|
|
47
|
+
}
|
|
48
|
+
/** All declarations are validated before any source is materialized. */
|
|
49
|
+
export declare function validateProposedChecks(context: PipelineContext, raw: unknown): ProposedCheck[];
|
|
50
|
+
export declare function readVerificationPlan(context: PipelineContext): VerificationPlan | null;
|
|
51
|
+
export declare function initializeVerificationPlan(context: PipelineContext, host: VerificationCommand[], architect: VerificationCommand[], maxConcurrency?: number): VerificationPlan;
|
|
52
|
+
export declare function addDeveloperChecks(context: PipelineContext, proposals: ProposedCheck[]): VerificationPlan;
|
|
53
|
+
export declare function expandedPlanCommands(context: PipelineContext, plan: VerificationPlan): VerificationCommand[];
|
|
54
|
+
/** Bind the exact manifest and every source to lifecycle gates. */
|
|
55
|
+
export declare function bindPlan(context: PipelineContext, plan: VerificationPlan): void;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { bindVerificationPlan, pipelineStateDirectory, validateVerificationRequest } from '../installer/runtime/pipeline-state.js';
|
|
5
|
+
import { fingerprint } from './durable-store.js';
|
|
6
|
+
import { child, write } from './graph/artifacts.js';
|
|
7
|
+
const SAFE_ID = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;
|
|
8
|
+
const bytesHash = (text) => createHash('sha256').update(text).digest('hex');
|
|
9
|
+
function text(value, field, limit) {
|
|
10
|
+
if (typeof value !== 'string' || !value.trim() || value.includes('\0') || value.length > limit)
|
|
11
|
+
throw new Error('Invalid verification proposal ' + field);
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
function sourcePath(value) {
|
|
15
|
+
const file = text(value, 'file path', 1024);
|
|
16
|
+
if (/^[a-z]:/i.test(file) || path.isAbsolute(file) || file.includes('\\') || /[\x00-\x1f\x7f]/.test(file) || file.split('/').some(part => !part || part === '.' || part === '..' || /[. ]$/.test(part) || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(part)))
|
|
17
|
+
throw new Error('Invalid verification proposal file path');
|
|
18
|
+
return file;
|
|
19
|
+
}
|
|
20
|
+
/** All declarations are validated before any source is materialized. */
|
|
21
|
+
export function validateProposedChecks(context, raw) {
|
|
22
|
+
if (raw === undefined)
|
|
23
|
+
return [];
|
|
24
|
+
if (!Array.isArray(raw) || raw.length > 20)
|
|
25
|
+
throw new Error('Invalid verificationChecks: expected at most 20 checks');
|
|
26
|
+
let bytes = 0;
|
|
27
|
+
const keys = new Set();
|
|
28
|
+
return raw.map(value => {
|
|
29
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
30
|
+
throw new Error('Invalid verification proposal');
|
|
31
|
+
const check = value;
|
|
32
|
+
for (const key of Object.keys(check))
|
|
33
|
+
if (!['kind', 'key', 'repositoryId', 'label', 'command', 'args', 'cwd', 'timeoutMs', 'entrypoint', 'files'].includes(key))
|
|
34
|
+
throw new Error('Invalid verification proposal field: ' + key);
|
|
35
|
+
if (!['command', 'harness'].includes(String(check.kind)) || typeof check.key !== 'string' || !SAFE_ID.test(check.key) || keys.has(check.key))
|
|
36
|
+
throw new Error('Invalid or duplicate verification proposal key/kind');
|
|
37
|
+
keys.add(check.key);
|
|
38
|
+
text(check.label, 'label', 256);
|
|
39
|
+
text(check.command, 'command', 4096);
|
|
40
|
+
if (!Array.isArray(check.args) || check.args.length > 128 || check.args.some(arg => typeof arg !== 'string' || arg.includes('\0') || arg.length > 4096))
|
|
41
|
+
throw new Error('Invalid verification proposal args');
|
|
42
|
+
validateVerificationRequest(context, { kind: 'scoped', commands: [check] });
|
|
43
|
+
if (check.kind === 'command') {
|
|
44
|
+
if (check.entrypoint !== undefined || check.files !== undefined)
|
|
45
|
+
throw new Error('Invalid command proposal: harness fields are forbidden');
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const entrypoint = sourcePath(check.entrypoint);
|
|
49
|
+
if (!Array.isArray(check.files) || !check.files.length || check.files.length > 8)
|
|
50
|
+
throw new Error('Invalid harness files: expected 1–8 files');
|
|
51
|
+
const paths = new Set();
|
|
52
|
+
for (const raw of check.files) {
|
|
53
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
54
|
+
throw new Error('Invalid harness source');
|
|
55
|
+
const file = raw;
|
|
56
|
+
if (Object.keys(file).some(key => !['path', 'content'].includes(key)))
|
|
57
|
+
throw new Error('Invalid harness source fields');
|
|
58
|
+
const filePath = sourcePath(file.path);
|
|
59
|
+
if ([...paths].some(prior => prior === filePath.toLowerCase() || prior.startsWith(filePath.toLowerCase() + '/') || filePath.toLowerCase().startsWith(prior + '/')))
|
|
60
|
+
throw new Error('Duplicate harness source path');
|
|
61
|
+
paths.add(filePath.toLowerCase());
|
|
62
|
+
if (typeof file.content !== 'string')
|
|
63
|
+
throw new Error('Invalid harness source content');
|
|
64
|
+
const length = Buffer.byteLength(file.content);
|
|
65
|
+
if (length > 64 * 1024 || (bytes += length) > 256 * 1024)
|
|
66
|
+
throw new Error('Invalid harness source size');
|
|
67
|
+
}
|
|
68
|
+
if (!check.files.some(file => file.path === entrypoint))
|
|
69
|
+
throw new Error('Invalid harness entrypoint: source is missing');
|
|
70
|
+
}
|
|
71
|
+
return structuredClone(check);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function normalized(command) {
|
|
75
|
+
return JSON.parse(JSON.stringify({ ...command, args: [...command.args], cwd: command.cwd ?? '.', timeoutMs: command.timeoutMs ?? 15 * 60_000 }));
|
|
76
|
+
}
|
|
77
|
+
function entry(key, label, command, origin, harness) {
|
|
78
|
+
const definition = normalized(command);
|
|
79
|
+
delete definition.key;
|
|
80
|
+
delete definition.label;
|
|
81
|
+
return { key, label, command: definition, origins: [origin], ...(harness ? { harness } : {}), id: fingerprint({ key, command: definition, harness: harness ?? null }) };
|
|
82
|
+
}
|
|
83
|
+
function mergePolicy(left, right) {
|
|
84
|
+
return {
|
|
85
|
+
reuse: left?.reuse === 'snapshot-local' && right?.reuse === 'snapshot-local' ? 'snapshot-local' : 'never',
|
|
86
|
+
deterministic: left?.deterministic === true && right?.deterministic === true,
|
|
87
|
+
readOnly: left?.readOnly === true && right?.readOnly === true,
|
|
88
|
+
inputs: [...new Set([...(left?.inputs ?? []), ...(right?.inputs ?? [])])].sort(),
|
|
89
|
+
toolchainInputs: [...new Set([...(left?.toolchainInputs ?? []), ...(right?.toolchainInputs ?? [])])].sort(),
|
|
90
|
+
...(left?.independentGroup && left.independentGroup === right?.independentGroup && left.resources && right.resources ? { independentGroup: left.independentGroup, resources: [...new Set([...left.resources, ...right.resources])].sort() } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function coalesce(entries) {
|
|
94
|
+
const results = new Map();
|
|
95
|
+
for (const item of entries) {
|
|
96
|
+
const { policy: _policy, ...command } = item.command;
|
|
97
|
+
const semantic = fingerprint({ command, harness: item.harness ?? null });
|
|
98
|
+
const old = results.get(semantic);
|
|
99
|
+
if (!old) {
|
|
100
|
+
results.set(semantic, structuredClone(item));
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (item.origins.some(origin => origin !== 'developer'))
|
|
104
|
+
old.command.policy = mergePolicy(old.command.policy, item.command.policy);
|
|
105
|
+
old.origins = [...new Set([...old.origins, ...item.origins])];
|
|
106
|
+
}
|
|
107
|
+
return [...results.values()];
|
|
108
|
+
}
|
|
109
|
+
function planFile(context) { return child(pipelineStateDirectory(context), 'verification/plan.json'); }
|
|
110
|
+
export function readVerificationPlan(context) {
|
|
111
|
+
const file = planFile(context);
|
|
112
|
+
if (!existsSync(file))
|
|
113
|
+
return null;
|
|
114
|
+
if (statSync(file).size > 2 * 1024 * 1024)
|
|
115
|
+
throw new Error('Verification plan exceeds its size limit');
|
|
116
|
+
const value = JSON.parse(readFileSync(file, 'utf8'));
|
|
117
|
+
const { integrity, ...payload } = value;
|
|
118
|
+
if (integrity !== fingerprint(payload))
|
|
119
|
+
throw new Error('Verification plan failed its integrity check');
|
|
120
|
+
if (value.scopeHash !== fingerprint(context) || value.schemaVersion !== 1 || value.runId !== context.runId || !Array.isArray(value.baseline) || !Array.isArray(value.developer) || !Array.isArray(value.entries) || value.entries.length > 100 || value.planHash !== fingerprint({ policyVersion: 1, scopeHash: value.scopeHash, executionPolicy: value.executionPolicy, entries: value.entries }))
|
|
121
|
+
throw new Error('Verification plan failed its integrity check');
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
export function initializeVerificationPlan(context, host, architect, maxConcurrency = 1) {
|
|
125
|
+
const previous = readVerificationPlan(context);
|
|
126
|
+
const baseline = [['host', host], ['architect', architect]].flatMap(([origin, commands]) => commands.map((command, i) => entry(`${origin}:${command.key ?? `${i}-${fingerprint(normalized(command)).slice(0, 12)}`}`, command.label ?? [command.command, ...command.args].join(' ').slice(0, 256), command, origin)));
|
|
127
|
+
if (!Number.isSafeInteger(maxConcurrency) || maxConcurrency < 1 || maxConcurrency > 4)
|
|
128
|
+
throw new Error('Invalid verification concurrency');
|
|
129
|
+
if (previous && fingerprint(previous.baseline) !== fingerprint(baseline))
|
|
130
|
+
throw new Error('Verification baseline is immutable');
|
|
131
|
+
return savePlan(context, baseline, previous?.developer ?? [], previous, { maxConcurrency });
|
|
132
|
+
}
|
|
133
|
+
function buildPlan(context, baseline, developer, previous, executionPolicy = previous?.executionPolicy ?? { maxConcurrency: 1 }) {
|
|
134
|
+
const entries = coalesce([...baseline, ...developer]);
|
|
135
|
+
if (entries.length > 100)
|
|
136
|
+
throw new Error('Invalid verification plan: maximum 100 effective checks');
|
|
137
|
+
const scopeHash = fingerprint(context);
|
|
138
|
+
const planHash = fingerprint({ policyVersion: 1, scopeHash, executionPolicy, entries });
|
|
139
|
+
const payload = { schemaVersion: 1, runId: context.runId, revision: (previous?.revision ?? 0) + (previous?.planHash === planHash ? 0 : 1), planHash, scopeHash, executionPolicy, baseline, developer, entries };
|
|
140
|
+
const plan = { ...payload, integrity: fingerprint(payload) };
|
|
141
|
+
const serialized = JSON.stringify(plan) + '\n';
|
|
142
|
+
if (Buffer.byteLength(serialized) > 2 * 1024 * 1024)
|
|
143
|
+
throw new Error('Verification plan exceeds 2 MiB');
|
|
144
|
+
return plan;
|
|
145
|
+
}
|
|
146
|
+
function savePlan(context, baseline, developer, previous, executionPolicy = previous?.executionPolicy ?? { maxConcurrency: 1 }) {
|
|
147
|
+
const plan = buildPlan(context, baseline, developer, previous, executionPolicy);
|
|
148
|
+
write(planFile(context), JSON.stringify(plan) + '\n');
|
|
149
|
+
return plan;
|
|
150
|
+
}
|
|
151
|
+
export function addDeveloperChecks(context, proposals) {
|
|
152
|
+
const previous = readVerificationPlan(context);
|
|
153
|
+
if (!previous)
|
|
154
|
+
throw new Error('Verification baseline is unavailable');
|
|
155
|
+
const checked = validateProposedChecks(context, proposals);
|
|
156
|
+
const developer = new Map(previous.developer.map(item => [item.key, item]));
|
|
157
|
+
const sources = [];
|
|
158
|
+
for (const check of checked) {
|
|
159
|
+
const command = { repositoryId: check.repositoryId, command: check.command, args: check.args, ...(check.cwd === undefined ? {} : { cwd: check.cwd }), ...(check.timeoutMs === undefined ? {} : { timeoutMs: check.timeoutMs }) };
|
|
160
|
+
const files = check.files?.slice().sort((a, b) => a.path.localeCompare(b.path)).map(file => ({ path: file.path, hash: bytesHash(file.content), byteCount: Buffer.byteLength(file.content) }));
|
|
161
|
+
const harness = files ? { hash: fingerprint(files), entrypoint: check.entrypoint, sources: files } : undefined;
|
|
162
|
+
const item = entry('dev:' + check.key, check.label, command, 'developer', harness);
|
|
163
|
+
developer.set(item.key, item);
|
|
164
|
+
for (const file of check.files ?? [])
|
|
165
|
+
sources.push({ file: child(pipelineStateDirectory(context), `verification/harnesses/${item.id}/${harness.hash}/${file.path}`), content: file.content });
|
|
166
|
+
}
|
|
167
|
+
const plan = buildPlan(context, previous.baseline, [...developer.values()], previous);
|
|
168
|
+
// An interrupted write cannot activate a partial harness. Old immutable
|
|
169
|
+
// revisions remain readable; only the new manifest changes the active plan.
|
|
170
|
+
for (const source of sources) {
|
|
171
|
+
if (existsSync(source.file) && readFileSync(source.file, 'utf8') !== source.content)
|
|
172
|
+
throw new Error('Immutable verification source changed');
|
|
173
|
+
}
|
|
174
|
+
for (const source of sources) {
|
|
175
|
+
if (!existsSync(source.file))
|
|
176
|
+
write(source.file, source.content);
|
|
177
|
+
}
|
|
178
|
+
write(planFile(context), JSON.stringify(plan) + '\n');
|
|
179
|
+
return plan;
|
|
180
|
+
}
|
|
181
|
+
export function expandedPlanCommands(context, plan) {
|
|
182
|
+
return plan.entries.map(item => {
|
|
183
|
+
if (!item.harness)
|
|
184
|
+
return { ...item.command, key: item.id, label: item.label };
|
|
185
|
+
const repository = context.repositories.find(repo => repo.id === item.command.repositoryId);
|
|
186
|
+
if (!repository)
|
|
187
|
+
throw new Error('Harness repository is no longer admitted');
|
|
188
|
+
for (const source of item.harness.sources) {
|
|
189
|
+
const file = child(pipelineStateDirectory(context), `verification/harnesses/${item.id}/${item.harness.hash}/${source.path}`);
|
|
190
|
+
if (bytesHash(readFileSync(file, 'utf8')) !== source.hash)
|
|
191
|
+
throw new Error('Verification harness source changed');
|
|
192
|
+
}
|
|
193
|
+
const entrypoint = child(pipelineStateDirectory(context), `verification/harnesses/${item.id}/${item.harness.hash}/${item.harness.entrypoint}`);
|
|
194
|
+
return { ...item.command, key: item.id, label: item.label, args: [...item.command.args, entrypoint], env: { SPECRAILS_CHECK_REPO_ROOT: repository.path } };
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/** Bind the exact manifest and every source to lifecycle gates. */
|
|
198
|
+
export function bindPlan(context, plan) {
|
|
199
|
+
const files = [{ path: 'verification/plan.json', hash: bytesHash(readFileSync(planFile(context), 'utf8')) }];
|
|
200
|
+
for (const item of plan.entries)
|
|
201
|
+
for (const source of item.harness?.sources ?? []) {
|
|
202
|
+
files.push({ path: `verification/harnesses/${item.id}/${item.harness.hash}/${source.path}`, hash: source.hash });
|
|
203
|
+
}
|
|
204
|
+
bindVerificationPlan(context, plan.planHash, files);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=verification-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-plan.js","sourceRoot":"","sources":["../../src/agent-runtime/verification-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,2BAA2B,EAAwE,MAAM,wCAAwC,CAAA;AACxM,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAmCnD,MAAM,OAAO,GAAG,oCAAoC,CAAA;AACpD,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC3F,SAAS,IAAI,CAAC,KAAc,EAAE,KAAa,EAAE,KAAa;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,KAAK,CAAC,CAAA;IACzJ,OAAO,KAAK,CAAA;AACd,CAAC;AACD,SAAS,UAAU,CAAC,KAAc;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAA;IAC3C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,+CAA+C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IACjU,OAAO,IAAI,CAAA;AACb,CAAC;AACD,wEAAwE;AACxE,MAAM,UAAU,sBAAsB,CAAC,OAAwB,EAAE,GAAY;IAC3E,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IACrH,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QACrB,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;QACjH,MAAM,KAAK,GAAG,KAAgC,CAAA;QAC9C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,GAAG,CAAC,CAAA;QAC/N,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;QACpN,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACnB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;QACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;QAC9M,2BAA2B,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC3E,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;QAC5I,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;YAC9I,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;YAC/B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC9B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;gBACpG,MAAM,IAAI,GAAG,GAA8B,CAAA;gBAC3C,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;gBACvH,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACtC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;gBACpN,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;gBACjC,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;oBAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;gBACvF,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC9C,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAC1G,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAC3H,CAAC;QACD,OAAO,eAAe,CAAC,KAAK,CAA6B,CAAA;IAC3D,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,OAA4B;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;AAClJ,CAAC;AACD,SAAS,KAAK,CAAC,GAAW,EAAE,KAAa,EAAE,OAA4B,EAAE,MAAoC,EAAE,OAA8B;IAC3I,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;IACtC,OAAO,UAAU,CAAC,GAAG,CAAC;IAAC,OAAO,UAAU,CAAC,KAAK,CAAA;IAC9C,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,CAAC,EAAE,CAAA;AACzK,CAAC;AACD,SAAS,WAAW,CAAC,IAAsB,EAAE,KAAuB;IAClE,OAAO;QACL,KAAK,EAAE,IAAI,EAAE,KAAK,KAAK,gBAAgB,IAAI,KAAK,EAAE,KAAK,KAAK,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO;QACzG,aAAa,EAAE,IAAI,EAAE,aAAa,KAAK,IAAI,IAAI,KAAK,EAAE,aAAa,KAAK,IAAI;QAC5E,QAAQ,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,IAAI,KAAK,EAAE,QAAQ,KAAK,IAAI;QAC7D,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;QAChF,eAAe,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,eAAe,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;QAC3G,GAAG,CAAC,IAAI,EAAE,gBAAgB,IAAI,IAAI,CAAC,gBAAgB,KAAK,KAAK,EAAE,gBAAgB,IAAI,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClP,CAAA;AACH,CAAC;AACD,SAAS,QAAQ,CAAC,OAAoB;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAA;IAC5C,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACpD,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC,CAAA;QACxE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACjC,IAAI,CAAC,GAAG,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YAAC,SAAQ;QAAC,CAAC;QACpE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,WAAW,CAAC;YAAE,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAClI,GAAG,CAAC,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC/D,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AAC9B,CAAC;AACD,SAAS,QAAQ,CAAC,OAAwB,IAAY,OAAO,KAAK,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,wBAAwB,CAAC,CAAA,CAAC,CAAC;AAC/H,MAAM,UAAU,oBAAoB,CAAC,OAAwB;IAC3D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IACtG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IACpD,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAA;IACvC,IAAI,SAAS,KAAK,WAAW,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACvG,IAAI,KAAK,CAAC,SAAS,KAAK,WAAW,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,WAAW,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACnc,OAAO,KAAyB,CAAA;AAClC,CAAC;AACD,MAAM,UAAU,0BAA0B,CAAC,OAAwB,EAAE,IAA2B,EAAE,SAAgC,EAAE,cAAc,GAAG,CAAC;IACpJ,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAC9C,MAAM,QAAQ,GAAI,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAW,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IAChU,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,CAAC,IAAI,cAAc,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IAC1I,IAAI,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,WAAW,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IAC/H,OAAO,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,CAAC,CAAA;AAC7F,CAAC;AACD,SAAS,SAAS,CAAC,OAAwB,EAAE,QAAqB,EAAE,SAAsB,EAAE,QAAiC,EAAE,eAAe,GAAG,QAAQ,EAAE,eAAe,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE;IACjM,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,CAAC,CAAC,CAAA;IACrD,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAA;IACpG,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,CAAA;IACvF,MAAM,OAAO,GAAG,EAAE,aAAa,EAAE,CAAU,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAA;IACxN,MAAM,IAAI,GAAqB,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAA;IAC9E,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC9C,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACvG,OAAO,IAAI,CAAA;AACb,CAAC;AACD,SAAS,QAAQ,CAAC,OAAwB,EAAE,QAAqB,EAAE,SAAsB,EAAE,QAAiC,EAAE,eAAe,GAAG,QAAQ,EAAE,eAAe,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE;IAChM,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAA;IAC/E,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;IACrD,OAAO,IAAI,CAAA;AACb,CAAC;AACD,MAAM,UAAU,kBAAkB,CAAC,OAAwB,EAAE,SAA0B;IACrF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAC9C,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACtE,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAC1D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IAC3E,MAAM,OAAO,GAA6C,EAAE,CAAA;IAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAwB,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,CAAA;QACrP,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;QAC7L,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAW,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;QAC/G,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;QAClF,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,0BAA0B,IAAI,CAAC,EAAE,IAAI,OAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;IAChM,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAA;IACrF,wEAAwE;IACxE,4EAA4E;IAC5E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;IAC/I,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IAClE,CAAC;IACD,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;IACrD,OAAO,IAAI,CAAA;AACb,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,OAAwB,EAAE,IAAsB;IACnF,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAA;QAC9E,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAC3F,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;QAC5E,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,0BAA0B,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;YAC5H,IAAI,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACnH,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,0BAA0B,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;QAC9I,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE,yBAAyB,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,CAAA;IAC5J,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,QAAQ,CAAC,OAAwB,EAAE,IAAsB;IACvE,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAA;IAC5G,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO;QAAE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YAClF,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,0BAA0B,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,OAAQ,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QACnH,CAAC;IACD,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;AACrD,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnnotationRoot } from '@langchain/langgraph';
|
|
2
|
+
import type { ProviderInvocation } from './efficiency-types.js';
|
|
2
3
|
/** JSON-only contracts keep checkpoints portable and independent of executors. */
|
|
3
4
|
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
4
5
|
[key: string]: JsonValue;
|
|
@@ -62,10 +63,18 @@ export interface WorkflowStepContext {
|
|
|
62
63
|
interrupt<R extends InterruptResume = InterruptResume>(request: InterruptRequest): R;
|
|
63
64
|
/** Account provider spend as soon as it is known; a later pause or failure keeps it. */
|
|
64
65
|
reportUsage(usage: StepUsage): void;
|
|
66
|
+
/** Persist a completed provider call with its already-reported usage. Optional for custom hosts. */
|
|
67
|
+
reportEfficiencyActivity?(kind: string, payload: Record<string, string | number | null>): Promise<void>;
|
|
68
|
+
reportInvocationStarted?(invocation: Omit<import('./efficiency-types.js').PendingProviderInvocation, 'invocationId' | 'ordinal'>): Promise<{
|
|
69
|
+
invocationId: string;
|
|
70
|
+
ordinal: number;
|
|
71
|
+
}>;
|
|
72
|
+
reportInvocation?(invocation: ProviderInvocation): Promise<void>;
|
|
65
73
|
/** Budget left for the next provider call, after everything reported so far. */
|
|
66
74
|
remainingBudget(): {
|
|
67
75
|
maxTokens?: number;
|
|
68
76
|
maxCostUsd?: number;
|
|
77
|
+
maxDurationMs?: number;
|
|
69
78
|
};
|
|
70
79
|
}
|
|
71
80
|
export interface WorkflowNode<S extends Record<string, unknown>> {
|
|
@@ -115,6 +124,8 @@ export interface StepAttemptRecord {
|
|
|
115
124
|
output?: JsonValue;
|
|
116
125
|
error?: string;
|
|
117
126
|
usage?: StepUsage;
|
|
127
|
+
pendingInvocations?: import('./efficiency-types.js').PendingProviderInvocation[];
|
|
128
|
+
invocations?: ProviderInvocation[];
|
|
118
129
|
}
|
|
119
130
|
export interface WorkflowEvent {
|
|
120
131
|
id: string;
|
|
@@ -123,7 +134,12 @@ export interface WorkflowEvent {
|
|
|
123
134
|
/** Trace correlation: the run's trace and the attempt span this event belongs to. */
|
|
124
135
|
traceId: string;
|
|
125
136
|
spanId?: string;
|
|
126
|
-
|
|
137
|
+
efficiencyActivity?: {
|
|
138
|
+
kind: string;
|
|
139
|
+
payload: Record<string, string | number | null>;
|
|
140
|
+
};
|
|
141
|
+
efficiency?: ProviderInvocation;
|
|
142
|
+
type: 'efficiency_updated' | 'workflow_started' | 'workflow_resumed' | 'workflow_invalidated' | 'workflow_succeeded' | 'workflow_failed' | 'workflow_blocked' | 'workflow_paused' | 'workflow_cancelled' | 'step_started' | 'step_succeeded' | 'step_failed' | 'step_blocked' | 'step_paused' | 'step_interrupted';
|
|
127
143
|
timestamp: string;
|
|
128
144
|
stepId?: string;
|
|
129
145
|
attemptId?: string;
|
|
@@ -271,7 +271,12 @@ export async function runWorkflow(options) {
|
|
|
271
271
|
}
|
|
272
272
|
let forkTarget;
|
|
273
273
|
if (invalid.size) {
|
|
274
|
-
|
|
274
|
+
let first = Math.min(...Array.from(invalid, id => ids.indexOf(id)));
|
|
275
|
+
// A stale later receipt must never jump over an unfinished correction.
|
|
276
|
+
// This also repairs checkpoints whose previous resume chose that receipt.
|
|
277
|
+
const unfinished = ids.findIndex((id, index) => index < first && ['blocked', 'failed'].includes(state.steps[id].status));
|
|
278
|
+
if (unfinished >= 0)
|
|
279
|
+
first = unfinished;
|
|
275
280
|
for (const id of ids.slice(first))
|
|
276
281
|
resetRecord(state, id);
|
|
277
282
|
forkTarget = ids[first];
|
|
@@ -391,7 +396,29 @@ export async function runWorkflow(options) {
|
|
|
391
396
|
return interrupt(request);
|
|
392
397
|
},
|
|
393
398
|
reportUsage: usage => { validateUsage(usage); accountUsage(state, usage); reported = addUsage(reported ?? { costUsd: 0, inputTokens: 0, outputTokens: 0 }, usage); },
|
|
399
|
+
reportEfficiencyActivity: async (kind, payload) => { await commit({ type: 'efficiency_updated', stepId: id, attemptId, efficiencyActivity: { kind, payload } }); },
|
|
400
|
+
reportInvocationStarted: async (invocation) => {
|
|
401
|
+
const ordinal = (history.invocations?.length ?? 0) + (history.pendingInvocations?.length ?? 0) + 1;
|
|
402
|
+
const identity = { invocationId: `${attemptId}:call:${ordinal}`, ordinal };
|
|
403
|
+
(history.pendingInvocations ??= []).push({ ...clone(invocation), ...identity });
|
|
404
|
+
await persist();
|
|
405
|
+
return identity;
|
|
406
|
+
},
|
|
407
|
+
reportInvocation: async (invocation) => {
|
|
408
|
+
validateUsage(invocation.usage);
|
|
409
|
+
if (!Number.isFinite(invocation.durationMs) || invocation.durationMs < 0 || !Number.isSafeInteger(invocation.toolCalls) || invocation.toolCalls < 0)
|
|
410
|
+
throw new TypeError('Invalid invocation measurement');
|
|
411
|
+
if (invocation.invocationId && history.invocations?.some(item => item.invocationId === invocation.invocationId))
|
|
412
|
+
return;
|
|
413
|
+
(history.invocations ??= []).push(clone(invocation));
|
|
414
|
+
if (invocation.invocationId)
|
|
415
|
+
history.pendingInvocations = history.pendingInvocations?.filter(item => item.invocationId !== invocation.invocationId);
|
|
416
|
+
if (reported)
|
|
417
|
+
history.usage = reported;
|
|
418
|
+
await commit({ type: 'efficiency_updated', stepId: id, attemptId, efficiency: clone(invocation) });
|
|
419
|
+
},
|
|
394
420
|
remainingBudget: () => ({
|
|
421
|
+
...(state.budget.maxDurationMs === undefined ? {} : { maxDurationMs: Math.max(0, state.budget.maxDurationMs - state.usage.durationMs - (performance.now() - elapsedMark)) }),
|
|
395
422
|
...(state.budget.maxTokens === undefined ? {} : { maxTokens: Math.max(0, state.budget.maxTokens - state.usage.knownTokens) }),
|
|
396
423
|
...(state.budget.maxCostUsd === undefined ? {} : { maxCostUsd: Math.max(0, state.budget.maxCostUsd - state.usage.knownCostUsd) }),
|
|
397
424
|
}),
|