omk-agent-core 0.90.7 → 0.90.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +97 -1
  2. package/dist/agent-loop.d.ts +25 -2
  3. package/dist/agent-loop.d.ts.map +1 -1
  4. package/dist/agent-loop.js +524 -189
  5. package/dist/agent-loop.js.map +1 -1
  6. package/dist/agent.d.ts +29 -7
  7. package/dist/agent.d.ts.map +1 -1
  8. package/dist/agent.js +81 -46
  9. package/dist/agent.js.map +1 -1
  10. package/dist/builtin-tool-resource-claims.d.ts +19 -0
  11. package/dist/builtin-tool-resource-claims.d.ts.map +1 -0
  12. package/dist/builtin-tool-resource-claims.js +200 -0
  13. package/dist/builtin-tool-resource-claims.js.map +1 -0
  14. package/dist/index.d.ts +5 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +8 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/node-resource-resolver.d.ts +42 -0
  19. package/dist/node-resource-resolver.d.ts.map +1 -0
  20. package/dist/node-resource-resolver.js +149 -0
  21. package/dist/node-resource-resolver.js.map +1 -0
  22. package/dist/node.d.ts +1 -0
  23. package/dist/node.d.ts.map +1 -1
  24. package/dist/node.js +2 -0
  25. package/dist/node.js.map +1 -1
  26. package/dist/parallel-tool-batch.d.ts +12 -1
  27. package/dist/parallel-tool-batch.d.ts.map +1 -1
  28. package/dist/parallel-tool-batch.js +71 -49
  29. package/dist/parallel-tool-batch.js.map +1 -1
  30. package/dist/path-segments.d.ts +21 -1
  31. package/dist/path-segments.d.ts.map +1 -1
  32. package/dist/path-segments.js +91 -9
  33. package/dist/path-segments.js.map +1 -1
  34. package/dist/plain-data.d.ts +7 -0
  35. package/dist/plain-data.d.ts.map +1 -0
  36. package/dist/plain-data.js +70 -0
  37. package/dist/plain-data.js.map +1 -0
  38. package/dist/tool-dag-scheduler.d.ts +86 -0
  39. package/dist/tool-dag-scheduler.d.ts.map +1 -0
  40. package/dist/tool-dag-scheduler.js +171 -0
  41. package/dist/tool-dag-scheduler.js.map +1 -0
  42. package/dist/tool-execution-boundary.d.ts +52 -0
  43. package/dist/tool-execution-boundary.d.ts.map +1 -0
  44. package/dist/tool-execution-boundary.js +185 -0
  45. package/dist/tool-execution-boundary.js.map +1 -0
  46. package/dist/tool-resource-claims.d.ts +31 -0
  47. package/dist/tool-resource-claims.d.ts.map +1 -0
  48. package/dist/tool-resource-claims.js +128 -0
  49. package/dist/tool-resource-claims.js.map +1 -0
  50. package/dist/tool-timeout.d.ts +96 -0
  51. package/dist/tool-timeout.d.ts.map +1 -0
  52. package/dist/tool-timeout.js +173 -0
  53. package/dist/tool-timeout.js.map +1 -0
  54. package/dist/tool-transcript-integrity.d.ts +65 -0
  55. package/dist/tool-transcript-integrity.d.ts.map +1 -0
  56. package/dist/tool-transcript-integrity.js +223 -0
  57. package/dist/tool-transcript-integrity.js.map +1 -0
  58. package/dist/types.d.ts +219 -10
  59. package/dist/types.d.ts.map +1 -1
  60. package/dist/types.js +50 -1
  61. package/dist/types.js.map +1 -1
  62. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin-tool-resource-claims.js","sourceRoot":"","sources":["../src/builtin-tool-resource-claims.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ToolParallelPolicy } from \"./parallel-tool-batch.ts\";\nimport { NEVER_PARALLEL_TOOLS, PARALLEL_SAFE_TOOLS, PATH_SCOPED_TOOLS } from \"./parallel-tool-batch.ts\";\nimport {\n\tcanonicalizeLexicalPath,\n\tjoinPathSegments,\n\tnormalizePathSlashes,\n\tpathSegmentsOverlap,\n} from \"./path-segments.ts\";\nimport type {\n\tClaimableToolCall,\n\tRegisteredToolClaimDefinition,\n\tResolveToolClaimsOptions,\n\tToolClaimResolution,\n} from \"./tool-resource-claims.ts\";\nimport type { AgentTool, ResolvedResourceKeys, ToolResourceAccess, ToolResourceClaim } from \"./types.ts\";\n\nconst SEARCH_PATH_TOOLS = new Set<string>([\"grep\", \"find\", \"ls\", \"search_files\"]);\n\nexport function isPlainArguments(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function findRegisteredToolClaimDefinition(\n\tname: string,\n\tregisteredTools: readonly RegisteredToolClaimDefinition[] | undefined,\n): RegisteredToolClaimDefinition | undefined {\n\treturn registeredTools?.find((tool) => tool.name === name);\n}\n\n/** Bind a fixed call identity without spreading away prototype tool methods. */\nexport function bindToolIdentity(candidate: AgentTool, name: string): AgentTool {\n\tconst tool: AgentTool = Object.create(candidate);\n\tObject.defineProperty(tool, \"name\", { enumerable: true, value: name });\n\tObject.defineProperty(tool, \"execute\", { value: candidate.execute.bind(candidate) });\n\tif (candidate.prepareArguments) {\n\t\tObject.defineProperty(tool, \"prepareArguments\", { value: candidate.prepareArguments.bind(candidate) });\n\t}\n\tif (candidate.resourceClaims) {\n\t\tObject.defineProperty(tool, \"resourceClaims\", { value: candidate.resourceClaims.bind(candidate) });\n\t}\n\treturn Object.freeze(tool);\n}\n\nexport function resolveToolPolicy(name: string, options: ResolveToolClaimsOptions): ToolParallelPolicy | undefined {\n\treturn (\n\t\tfindRegisteredToolClaimDefinition(name, options.registeredTools)?.executionMode ?? options.toolPolicies?.get(name)\n\t);\n}\n\nexport function isBuiltinPathClaimTool(name: string): boolean {\n\treturn PATH_SCOPED_TOOLS.has(name) || SEARCH_PATH_TOOLS.has(name);\n}\n\nfunction normalizeLeadingSlashes(rawPath: string): string {\n\tconst normalized = normalizePathSlashes(rawPath);\n\treturn /^\\/{3,}/.test(normalized) ? normalized.replace(/^\\/+/, \"/\") : normalized;\n}\n\nfunction resolveCanonicalPathKey(rawPath: unknown, cwd: unknown): string | null {\n\tif (typeof rawPath !== \"string\" || rawPath.trim().length === 0 || typeof cwd !== \"string\") return null;\n\tconst normalized = normalizeLeadingSlashes(rawPath);\n\tconst canonicalCwd = canonicalizeLexicalPath(cwd);\n\tif (\n\t\tnormalized.startsWith(\"//\") ||\n\t\t/^[A-Za-z]:(?!\\/)/.test(normalized) ||\n\t\tcanonicalCwd === null ||\n\t\t!(canonicalCwd.startsWith(\"/\") || /^[A-Za-z]:\\//.test(canonicalCwd))\n\t) {\n\t\treturn null;\n\t}\n\n\tlet resolved: string;\n\tif (/^[A-Za-z]:\\//.test(normalized)) {\n\t\tresolved = normalized;\n\t} else if (normalized.startsWith(\"/\")) {\n\t\tconst cwdDrive = /^([A-Za-z]:)\\//.exec(canonicalCwd);\n\t\tresolved = cwdDrive ? `${cwdDrive[1]}${normalized}` : normalized;\n\t} else {\n\t\tresolved = joinPathSegments(canonicalCwd, normalized);\n\t}\n\tconst canonical = canonicalizeLexicalPath(resolved);\n\treturn canonical !== null && (canonical.startsWith(\"/\") || /^[A-Za-z]:\\//.test(canonical)) ? canonical : null;\n}\n\nfunction builtinRawPath(toolName: string, args: Record<string, unknown>, cwd: string): unknown {\n\tif (PATH_SCOPED_TOOLS.has(toolName)) return args.path;\n\tif (!SEARCH_PATH_TOOLS.has(toolName)) return undefined;\n\treturn typeof args.path === \"string\" && args.path.trim().length > 0 ? args.path : cwd;\n}\n\nfunction builtinPathAccess(toolName: string): ToolResourceAccess {\n\treturn toolName === \"read\" || SEARCH_PATH_TOOLS.has(toolName) ? \"read\" : \"write\";\n}\n\nexport function resolvePathClaimKey(toolName: string, args: Record<string, unknown>, cwd: string): string | null {\n\treturn isBuiltinPathClaimTool(toolName) ? resolveCanonicalPathKey(builtinRawPath(toolName, args, cwd), cwd) : null;\n}\n\nfunction canonicalizeResolvedPathKey(rawPath: unknown): string | null {\n\tif (typeof rawPath !== \"string\" || rawPath.trim().length === 0) return null;\n\tconst normalized = normalizeLeadingSlashes(rawPath);\n\tif (normalized.startsWith(\"//\")) {\n\t\tconst match = /^\\/\\/+([^/]+)\\/+([^/]+)(?:\\/+(.*))?$/.exec(normalized);\n\t\tif (!match) return null;\n\t\tconst suffix = match[3] ?? \"\";\n\t\tconst canonicalSuffix = suffix.length === 0 ? \"\" : canonicalizeLexicalPath(suffix);\n\t\tif (canonicalSuffix === null) return null;\n\t\tconst root = `//${match[1].toLowerCase()}/${match[2].toLowerCase()}`;\n\t\treturn canonicalSuffix.length === 0 ? root : `${root}/${canonicalSuffix}`;\n\t}\n\tconst canonical = canonicalizeLexicalPath(normalized);\n\tif (canonical === null) return null;\n\tconst drive = /^([A-Za-z]:)\\/(.*)$/.exec(canonical);\n\tif (drive) return `${drive[1].toLowerCase()}/${drive[2]}`;\n\treturn canonical.startsWith(\"/\") ? canonical : null;\n}\n\nfunction normalizeResolvedResourceKeys(value: unknown): ResolvedResourceKeys | null {\n\tif (!isPlainArguments(value)) return null;\n\tconst lexicalKey = canonicalizeResolvedPathKey(value.lexicalKey);\n\tif (lexicalKey === null) return null;\n\tconst realKey = value.realKey === undefined ? undefined : canonicalizeResolvedPathKey(value.realKey);\n\tif (realKey === null || (value.inodeKey !== undefined && (typeof value.inodeKey !== \"string\" || !value.inodeKey))) {\n\t\treturn null;\n\t}\n\tconst inodeKey = value.inodeKey;\n\tif (\n\t\t(lexicalKey.startsWith(\"//\") || /^[a-z]:\\//.test(lexicalKey)) &&\n\t\trealKey === undefined &&\n\t\tinodeKey === undefined\n\t) {\n\t\treturn null;\n\t}\n\treturn {\n\t\tlexicalKey,\n\t\t...(realKey === undefined ? {} : { realKey }),\n\t\t...(inodeKey === undefined ? {} : { inodeKey }),\n\t};\n}\n\nexport async function resolvePathClaimWithIdentity(\n\trawPath: unknown,\n\taccess: ToolResourceAccess,\n\toptions: ResolveToolClaimsOptions,\n): Promise<ToolClaimResolution> {\n\tif (typeof rawPath !== \"string\" || rawPath.trim().length === 0) return { kind: \"exclusive\" };\n\tconst resolver = options.resourceKeyResolver;\n\tif (!resolver) {\n\t\tconst key = resolveCanonicalPathKey(rawPath, options.cwd);\n\t\treturn key === null ? { kind: \"exclusive\" } : { kind: \"claims\", claims: [{ kind: \"path\", key, access }] };\n\t}\n\ttry {\n\t\tconst keys = normalizeResolvedResourceKeys(await resolver.resolvePath(rawPath, options.cwd));\n\t\tif (keys === null) return { kind: \"exclusive\" };\n\t\treturn {\n\t\t\tkind: \"claims\",\n\t\t\tclaims: [\n\t\t\t\t{\n\t\t\t\t\tkind: \"path\",\n\t\t\t\t\tkey: keys.lexicalKey,\n\t\t\t\t\taccess,\n\t\t\t\t\t...(keys.realKey === undefined ? {} : { realKey: keys.realKey }),\n\t\t\t\t\t...(keys.inodeKey === undefined ? {} : { inodeKey: keys.inodeKey }),\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t} catch {\n\t\treturn { kind: \"exclusive\" };\n\t}\n}\n\nexport function resolveBuiltinPathClaimWithIdentity(\n\ttoolCall: ClaimableToolCall,\n\toptions: ResolveToolClaimsOptions,\n): Promise<ToolClaimResolution> {\n\tif (!isPlainArguments(toolCall.arguments)) return Promise.resolve({ kind: \"exclusive\" });\n\treturn resolvePathClaimWithIdentity(\n\t\tbuiltinRawPath(toolCall.name, toolCall.arguments, options.cwd),\n\t\tbuiltinPathAccess(toolCall.name),\n\t\toptions,\n\t);\n}\n\nexport function resolveToolClaims(toolCall: ClaimableToolCall, options: ResolveToolClaimsOptions): ToolClaimResolution {\n\tif (!isPlainArguments(toolCall.arguments)) return { kind: \"exclusive\" };\n\tconst name = toolCall.name;\n\tif (NEVER_PARALLEL_TOOLS.has(name) || name === \"bash\" || resolveToolPolicy(name, options) === \"sequential\") {\n\t\treturn { kind: \"exclusive\" };\n\t}\n\tif (isBuiltinPathClaimTool(name)) {\n\t\tconst key = resolvePathClaimKey(name, toolCall.arguments, options.cwd);\n\t\treturn key === null\n\t\t\t? { kind: \"exclusive\" }\n\t\t\t: { kind: \"claims\", claims: [{ access: builtinPathAccess(name), kind: \"path\", key }] };\n\t}\n\tif (PARALLEL_SAFE_TOOLS.has(name)) return { kind: \"claims\", claims: [] };\n\tif (resolveToolPolicy(name, options) === \"parallel\") {\n\t\treturn options.strictExtensionClaims ? { kind: \"exclusive\" } : { kind: \"claims\", claims: [] };\n\t}\n\treturn { kind: \"exclusive\" };\n}\n\nfunction pathClaimKeys(claim: Extract<ToolResourceClaim, { kind: \"path\" }>): string[] {\n\treturn claim.realKey === undefined || claim.realKey === claim.key ? [claim.key] : [claim.key, claim.realKey];\n}\n\nfunction uncSegments(key: string): string[] | null {\n\treturn key.startsWith(\"//\")\n\t\t? key\n\t\t\t\t.slice(2)\n\t\t\t\t.split(\"/\")\n\t\t\t\t.filter((segment) => segment.length > 0)\n\t\t\t\t.map((segment) => segment.toLowerCase())\n\t\t: null;\n}\n\nfunction identityPathKeysOverlap(left: string, right: string): boolean {\n\tconst leftUnc = uncSegments(left);\n\tconst rightUnc = uncSegments(right);\n\tif (leftUnc === null || rightUnc === null) {\n\t\treturn leftUnc === null && rightUnc === null && pathSegmentsOverlap(left, right);\n\t}\n\tconst commonLength = Math.min(leftUnc.length, rightUnc.length);\n\tfor (let index = 0; index < commonLength; index++) {\n\t\tif (leftUnc[index] !== rightUnc[index]) return false;\n\t}\n\treturn true;\n}\n\nexport function pathClaimsOverlap(\n\tleft: Extract<ToolResourceClaim, { kind: \"path\" }>,\n\tright: Extract<ToolResourceClaim, { kind: \"path\" }>,\n): boolean {\n\tif (left.inodeKey !== undefined && left.inodeKey === right.inodeKey) return true;\n\treturn pathClaimKeys(left).some((leftKey) =>\n\t\tpathClaimKeys(right).some((rightKey) => identityPathKeysOverlap(leftKey, rightKey)),\n\t);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -16,7 +16,11 @@ export * from "./harness/system-prompt.ts";
16
16
  export * from "./harness/types.ts";
17
17
  export * from "./harness/utils/shell-output.ts";
18
18
  export * from "./harness/utils/truncate.ts";
19
- export { NEVER_PARALLEL_TOOLS, PARALLEL_SAFE_TOOLS, PATH_SCOPED_TOOLS, pathsOverlap, shouldParallelizeToolBatch, } from "./parallel-tool-batch.ts";
19
+ export { NEVER_PARALLEL_TOOLS, PARALLEL_SAFE_TOOLS, PATH_SCOPED_TOOLS, partitionToolBatchWaves, pathsOverlap, shouldParallelizeToolBatch, } from "./parallel-tool-batch.ts";
20
20
  export * from "./proxy.ts";
21
+ export { applyConcurrencyCap, assignDagLevels, computePlanKey, type DagSchedulePlan, type ResolvedClaimEntry, resolveBatchClaims, type ScheduleDagLevelsOptions, scheduleDagLevels, } from "./tool-dag-scheduler.ts";
22
+ export { type ClaimableToolCall, canonicalizeClaims, claimsConflict, compareClaims, type ResolveToolClaimsOptions, resolutionsConflict, resolvePathClaimKey, resolveToolClaims, type ToolClaimResolution, type ToolResourceAccess, type ToolResourceClaim, } from "./tool-resource-claims.ts";
23
+ export { createAbortedToolResult, createTimeoutToolResult, resolveToolExecutionPolicy, resolveToolTimeoutMs, type ToolDispositionEnvelope, type ToolLateSettlement, } from "./tool-timeout.ts";
24
+ export { createSyntheticToolResult, inspectTranscriptIntegrity, repairTranscriptIntegrity, TranscriptIntegrityError, type TranscriptIntegrityIssue, type TranscriptIntegrityIssueKind, type TranscriptIntegrityReport, } from "./tool-transcript-integrity.ts";
21
25
  export * from "./types.ts";
22
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAE3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAE3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAElC,cAAc,YAAY,CAAC;AAE3B,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAE3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAE3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAElC,cAAc,YAAY,CAAC;AAE3B,OAAO,EACN,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,iBAAiB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,KAAK,wBAAwB,EAC7B,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,GAC9B,MAAM,gCAAgC,CAAC;AAExC,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpartitionToolBatchWaves,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Deterministic resource-claim DAG scheduler (dag-v2)\nexport {\n\tapplyConcurrencyCap,\n\tassignDagLevels,\n\tcomputePlanKey,\n\ttype DagSchedulePlan,\n\ttype ResolvedClaimEntry,\n\tresolveBatchClaims,\n\ttype ScheduleDagLevelsOptions,\n\tscheduleDagLevels,\n} from \"./tool-dag-scheduler.ts\";\n// Resource-claim model (dag-v2)\nexport {\n\ttype ClaimableToolCall,\n\tcanonicalizeClaims,\n\tclaimsConflict,\n\tcompareClaims,\n\ttype ResolveToolClaimsOptions,\n\tresolutionsConflict,\n\tresolvePathClaimKey,\n\tresolveToolClaims,\n\ttype ToolClaimResolution,\n\ttype ToolResourceAccess,\n\ttype ToolResourceClaim,\n} from \"./tool-resource-claims.ts\";\n// Per-call timeout / cancellation / late settlement (ALG-004)\nexport {\n\tcreateAbortedToolResult,\n\tcreateTimeoutToolResult,\n\tresolveToolExecutionPolicy,\n\tresolveToolTimeoutMs,\n\ttype ToolDispositionEnvelope,\n\ttype ToolLateSettlement,\n} from \"./tool-timeout.ts\";\nexport {\n\tcreateSyntheticToolResult,\n\tinspectTranscriptIntegrity,\n\trepairTranscriptIntegrity,\n\tTranscriptIntegrityError,\n\ttype TranscriptIntegrityIssue,\n\ttype TranscriptIntegrityIssueKind,\n\ttype TranscriptIntegrityReport,\n} from \"./tool-transcript-integrity.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
package/dist/index.js CHANGED
@@ -20,9 +20,16 @@ export * from "./harness/types.js";
20
20
  export * from "./harness/utils/shell-output.js";
21
21
  export * from "./harness/utils/truncate.js";
22
22
  // Parallel tool batch policy
23
- export { NEVER_PARALLEL_TOOLS, PARALLEL_SAFE_TOOLS, PATH_SCOPED_TOOLS, pathsOverlap, shouldParallelizeToolBatch, } from "./parallel-tool-batch.js";
23
+ export { NEVER_PARALLEL_TOOLS, PARALLEL_SAFE_TOOLS, PATH_SCOPED_TOOLS, partitionToolBatchWaves, pathsOverlap, shouldParallelizeToolBatch, } from "./parallel-tool-batch.js";
24
24
  // Proxy utilities
25
25
  export * from "./proxy.js";
26
+ // Deterministic resource-claim DAG scheduler (dag-v2)
27
+ export { applyConcurrencyCap, assignDagLevels, computePlanKey, resolveBatchClaims, scheduleDagLevels, } from "./tool-dag-scheduler.js";
28
+ // Resource-claim model (dag-v2)
29
+ export { canonicalizeClaims, claimsConflict, compareClaims, resolutionsConflict, resolvePathClaimKey, resolveToolClaims, } from "./tool-resource-claims.js";
30
+ // Per-call timeout / cancellation / late settlement (ALG-004)
31
+ export { createAbortedToolResult, createTimeoutToolResult, resolveToolExecutionPolicy, resolveToolTimeoutMs, } from "./tool-timeout.js";
32
+ export { createSyntheticToolResult, inspectTranscriptIntegrity, repairTranscriptIntegrity, TranscriptIntegrityError, } from "./tool-transcript-integrity.js";
26
33
  // Types
27
34
  export * from "./types.js";
28
35
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,cAAc,YAAY,CAAC;AAC3B,iBAAiB;AACjB,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAIN,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,UAAU;AACV,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,6BAA6B;AAC7B,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAClC,kBAAkB;AAClB,cAAc,YAAY,CAAC;AAC3B,QAAQ;AACR,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,cAAc,YAAY,CAAC;AAC3B,iBAAiB;AACjB,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAIN,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,UAAU;AACV,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,6BAA6B;AAC7B,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAClC,kBAAkB;AAClB,cAAc,YAAY,CAAC;AAC3B,sDAAsD;AACtD,OAAO,EACN,mBAAmB,EACnB,eAAe,EACf,cAAc,EAGd,kBAAkB,EAElB,iBAAiB,GACjB,MAAM,yBAAyB,CAAC;AACjC,gCAAgC;AAChC,OAAO,EAEN,kBAAkB,EAClB,cAAc,EACd,aAAa,EAEb,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAIjB,MAAM,2BAA2B,CAAC;AACnC,8DAA8D;AAC9D,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,GAGpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,GAIxB,MAAM,gCAAgC,CAAC;AACxC,QAAQ;AACR,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpartitionToolBatchWaves,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Deterministic resource-claim DAG scheduler (dag-v2)\nexport {\n\tapplyConcurrencyCap,\n\tassignDagLevels,\n\tcomputePlanKey,\n\ttype DagSchedulePlan,\n\ttype ResolvedClaimEntry,\n\tresolveBatchClaims,\n\ttype ScheduleDagLevelsOptions,\n\tscheduleDagLevels,\n} from \"./tool-dag-scheduler.ts\";\n// Resource-claim model (dag-v2)\nexport {\n\ttype ClaimableToolCall,\n\tcanonicalizeClaims,\n\tclaimsConflict,\n\tcompareClaims,\n\ttype ResolveToolClaimsOptions,\n\tresolutionsConflict,\n\tresolvePathClaimKey,\n\tresolveToolClaims,\n\ttype ToolClaimResolution,\n\ttype ToolResourceAccess,\n\ttype ToolResourceClaim,\n} from \"./tool-resource-claims.ts\";\n// Per-call timeout / cancellation / late settlement (ALG-004)\nexport {\n\tcreateAbortedToolResult,\n\tcreateTimeoutToolResult,\n\tresolveToolExecutionPolicy,\n\tresolveToolTimeoutMs,\n\ttype ToolDispositionEnvelope,\n\ttype ToolLateSettlement,\n} from \"./tool-timeout.ts\";\nexport {\n\tcreateSyntheticToolResult,\n\tinspectTranscriptIntegrity,\n\trepairTranscriptIntegrity,\n\tTranscriptIntegrityError,\n\ttype TranscriptIntegrityIssue,\n\ttype TranscriptIntegrityIssueKind,\n\ttype TranscriptIntegrityReport,\n} from \"./tool-transcript-integrity.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Node-only resource-key identity resolver for the dag-v2 scheduler (§5.5
3
+ * stage 2). The browser-safe lexical layer in `path-segments.ts` cannot see
4
+ * symlinks, hardlinks, or platform path aliasing; this resolver adds that
5
+ * identity without ever weakening the lexical layer:
6
+ *
7
+ * 1. tilde expansion (Node adapter only), then lexical canonicalization
8
+ * 2. POSIX three-or-more leading slashes collapse to one rooted identity
9
+ * 3. unresolved Windows drive/UNC paths return `null` (exclusive scheduling)
10
+ * 4. nearest existing ancestor `realpath`, including dangling-symlink targets
11
+ * 5. `dev:ino` identity when the full path exists
12
+ * 6. filesystem failure falls back to the lexical POSIX key
13
+ *
14
+ * This module is exported from `omk-agent-core/node` only; the main package
15
+ * entry stays platform-free.
16
+ */
17
+ import type { ResourceKeyResolver } from "./types.ts";
18
+ export interface NodeResourceKeyResolverOptions {
19
+ /** Home directory used for tilde expansion. Default: `os.homedir`. */
20
+ homedir?: () => string;
21
+ /** Injectable realpath (tests / hardened environments). Default: `fs.promises.realpath`. */
22
+ realpath?: (path: string) => Promise<string>;
23
+ /** Injectable stat. Default: `fs.promises.stat`. */
24
+ stat?: (path: string) => Promise<{
25
+ dev: number | bigint;
26
+ ino: number | bigint;
27
+ }>;
28
+ /** Injectable lstat used to identify dangling symlinks. */
29
+ lstat?: (path: string) => Promise<{
30
+ isSymbolicLink(): boolean;
31
+ }>;
32
+ /** Injectable readlink used to resolve dangling symlink targets. */
33
+ readlink?: (path: string) => Promise<string>;
34
+ }
35
+ /**
36
+ * Create the Node identity resolver. Pure lexical work is synchronous and
37
+ * deterministic; filesystem identity is best-effort and every failure falls
38
+ * back to the lexical key so scheduling never gets *less* safe than the
39
+ * browser-safe layer.
40
+ */
41
+ export declare function createNodeResourceKeyResolver(options?: NodeResourceKeyResolverOptions): ResourceKeyResolver;
42
+ //# sourceMappingURL=node-resource-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-resource-resolver.d.ts","sourceRoot":"","sources":["../src/node-resource-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,OAAO,KAAK,EAAwB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAI5E,MAAM,WAAW,8BAA8B;IAC9C,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IACvB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,oDAAoD;IACpD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IACjF,2DAA2D;IAC3D,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,cAAc,IAAI,OAAO,CAAA;KAAE,CAAC,CAAC;IACjE,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7C;AAkBD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,GAAE,8BAAmC,GAAG,mBAAmB,CA4G/G","sourcesContent":["/**\n * Node-only resource-key identity resolver for the dag-v2 scheduler (§5.5\n * stage 2). The browser-safe lexical layer in `path-segments.ts` cannot see\n * symlinks, hardlinks, or platform path aliasing; this resolver adds that\n * identity without ever weakening the lexical layer:\n *\n * 1. tilde expansion (Node adapter only), then lexical canonicalization\n * 2. POSIX three-or-more leading slashes collapse to one rooted identity\n * 3. unresolved Windows drive/UNC paths return `null` (exclusive scheduling)\n * 4. nearest existing ancestor `realpath`, including dangling-symlink targets\n * 5. `dev:ino` identity when the full path exists\n * 6. filesystem failure falls back to the lexical POSIX key\n *\n * This module is exported from `omk-agent-core/node` only; the main package\n * entry stays platform-free.\n */\n\nimport {\n\tlstat as lstatAsync,\n\treadlink as readlinkAsync,\n\trealpath as realpathAsync,\n\tstat as statAsync,\n} from \"node:fs/promises\";\nimport { homedir as osHomedir } from \"node:os\";\nimport { canonicalizeLexicalPath, joinPathSegments, normalizePathSlashes } from \"./path-segments.ts\";\nimport type { ResolvedResourceKeys, ResourceKeyResolver } from \"./types.ts\";\n\nconst MAX_DANGLING_SYMLINK_DEPTH = 40;\n\nexport interface NodeResourceKeyResolverOptions {\n\t/** Home directory used for tilde expansion. Default: `os.homedir`. */\n\thomedir?: () => string;\n\t/** Injectable realpath (tests / hardened environments). Default: `fs.promises.realpath`. */\n\trealpath?: (path: string) => Promise<string>;\n\t/** Injectable stat. Default: `fs.promises.stat`. */\n\tstat?: (path: string) => Promise<{ dev: number | bigint; ino: number | bigint }>;\n\t/** Injectable lstat used to identify dangling symlinks. */\n\tlstat?: (path: string) => Promise<{ isSymbolicLink(): boolean }>;\n\t/** Injectable readlink used to resolve dangling symlink targets. */\n\treadlink?: (path: string) => Promise<string>;\n}\n\n/** Split a canonical rooted POSIX-style path into ancestor candidates, deepest first. */\nfunction ancestorPaths(canonical: string): string[] {\n\tconst ancestors: string[] = [];\n\tlet current = canonical;\n\twhile (current.length > 1) {\n\t\tconst slash = current.lastIndexOf(\"/\");\n\t\tif (slash <= 0) {\n\t\t\tancestors.push(\"/\");\n\t\t\treturn ancestors;\n\t\t}\n\t\tcurrent = current.slice(0, slash);\n\t\tancestors.push(current);\n\t}\n\treturn ancestors;\n}\n\n/**\n * Create the Node identity resolver. Pure lexical work is synchronous and\n * deterministic; filesystem identity is best-effort and every failure falls\n * back to the lexical key so scheduling never gets *less* safe than the\n * browser-safe layer.\n */\nexport function createNodeResourceKeyResolver(options: NodeResourceKeyResolverOptions = {}): ResourceKeyResolver {\n\tconst home = options.homedir ?? osHomedir;\n\tconst realpath = options.realpath ?? ((path: string) => realpathAsync(path));\n\tconst stat = options.stat ?? ((path: string) => statAsync(path));\n\tconst lstat = options.lstat ?? ((path: string) => lstatAsync(path));\n\tconst readlink = options.readlink ?? ((path: string) => readlinkAsync(path));\n\n\tconst suffixAfter = (path: string, ancestor: string): string =>\n\t\tpath.slice(ancestor.length === 1 ? 1 : ancestor.length + 1);\n\n\tasync function nearestRealKey(canonical: string): Promise<string | undefined> {\n\t\tfor (const ancestor of [canonical, ...ancestorPaths(canonical)]) {\n\t\t\tif (!(await stat(ancestor).catch(() => null))) continue;\n\t\t\tconst realAncestor = canonicalizeLexicalPath(normalizePathSlashes(await realpath(ancestor)));\n\t\t\tif (realAncestor === null) return undefined;\n\t\t\tconst suffix = suffixAfter(canonical, ancestor);\n\t\t\treturn suffix.length === 0 ? realAncestor : joinPathSegments(realAncestor, suffix);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tasync function danglingSymlinkTarget(canonical: string): Promise<string | null | undefined> {\n\t\tfor (const candidate of [canonical, ...ancestorPaths(canonical)]) {\n\t\t\tconst metadata = await lstat(candidate).catch(() => null);\n\t\t\tif (!metadata?.isSymbolicLink()) continue;\n\t\t\tlet target = normalizePathSlashes(await readlink(candidate));\n\t\t\tif (target.startsWith(\"/\")) target = target.replace(/^\\/+/, \"/\");\n\t\t\tconst slash = candidate.lastIndexOf(\"/\");\n\t\t\tconst parent = slash <= 0 ? \"/\" : candidate.slice(0, slash);\n\t\t\tconst canonicalTarget = canonicalizeLexicalPath(\n\t\t\t\ttarget.startsWith(\"/\") ? target : joinPathSegments(parent, target),\n\t\t\t);\n\t\t\tif (canonicalTarget === null) return null;\n\t\t\tconst suffix = suffixAfter(canonical, candidate);\n\t\t\treturn suffix.length === 0 ? canonicalTarget : joinPathSegments(canonicalTarget, suffix);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tasync function danglingSymlinkRealKey(canonical: string): Promise<string | undefined> {\n\t\tconst seen = new Set<string>();\n\t\tlet current = canonical;\n\t\tfor (let depth = 0; depth < MAX_DANGLING_SYMLINK_DEPTH; depth++) {\n\t\t\tif (seen.has(current)) return undefined;\n\t\t\tseen.add(current);\n\t\t\tconst target = await danglingSymlinkTarget(current);\n\t\t\tif (target === null) return undefined;\n\t\t\tif (target === undefined) return nearestRealKey(current);\n\t\t\tcurrent = target;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tasync function resolveIdentity(canonical: string): Promise<Pick<ResolvedResourceKeys, \"realKey\" | \"inodeKey\">> {\n\t\tconst identity: { realKey?: string; inodeKey?: string } = {};\n\t\ttry {\n\t\t\tconst target = await stat(canonical).catch(() => null);\n\t\t\tif (target) {\n\t\t\t\tidentity.inodeKey = `${target.dev}:${target.ino}`;\n\t\t\t\tidentity.realKey = await nearestRealKey(canonical);\n\t\t\t\treturn identity;\n\t\t\t}\n\t\t\tidentity.realKey = await danglingSymlinkRealKey(canonical);\n\t\t\treturn identity;\n\t\t} catch {\n\t\t\treturn {};\n\t\t}\n\t}\n\n\treturn {\n\t\tasync resolvePath(rawPath: string, cwd: string): Promise<ResolvedResourceKeys | null> {\n\t\t\tif (typeof rawPath !== \"string\" || rawPath.trim().length === 0 || typeof cwd !== \"string\") {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tlet normalized = normalizePathSlashes(rawPath);\n\t\t\tif (/^\\/{3,}/.test(normalized)) normalized = normalized.replace(/^\\/+/, \"/\");\n\t\t\t// Tilde expansion happens only in this Node adapter (§5.5 stage 1 note).\n\t\t\tif (normalized === \"~\" || normalized.startsWith(\"~/\")) {\n\t\t\t\ttry {\n\t\t\t\t\tnormalized = joinPathSegments(\n\t\t\t\t\t\tnormalizePathSlashes(home()),\n\t\t\t\t\t\tnormalized === \"~\" ? \"\" : normalized.slice(2),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// This POSIX resolver cannot establish filesystem identity for Windows\n\t\t\t// drive or UNC paths. Null makes each call exclusive instead of sharing an\n\t\t\t// unsafe lexical-only claim with another call.\n\t\t\tif (normalized.startsWith(\"//\") || /^[A-Za-z]:(?:\\/|$)/.test(normalized)) return null;\n\n\t\t\tconst joined = normalized.startsWith(\"/\") ? normalized : joinPathSegments(cwd, normalized);\n\t\t\tconst canonical = canonicalizeLexicalPath(joined);\n\t\t\tif (canonical === null) {\n\t\t\t\t// Root escapes, drive-relative forms, and other ambiguous shapes fail closed.\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (/^[A-Za-z]:\\//.test(canonical)) return null;\n\t\t\tif (!canonical.startsWith(\"/\")) {\n\t\t\t\t// Still relative after canonicalization (non-anchored cwd): fail closed.\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn { lexicalKey: canonical, ...(await resolveIdentity(canonical)) };\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Node-only resource-key identity resolver for the dag-v2 scheduler (§5.5
3
+ * stage 2). The browser-safe lexical layer in `path-segments.ts` cannot see
4
+ * symlinks, hardlinks, or platform path aliasing; this resolver adds that
5
+ * identity without ever weakening the lexical layer:
6
+ *
7
+ * 1. tilde expansion (Node adapter only), then lexical canonicalization
8
+ * 2. POSIX three-or-more leading slashes collapse to one rooted identity
9
+ * 3. unresolved Windows drive/UNC paths return `null` (exclusive scheduling)
10
+ * 4. nearest existing ancestor `realpath`, including dangling-symlink targets
11
+ * 5. `dev:ino` identity when the full path exists
12
+ * 6. filesystem failure falls back to the lexical POSIX key
13
+ *
14
+ * This module is exported from `omk-agent-core/node` only; the main package
15
+ * entry stays platform-free.
16
+ */
17
+ import { lstat as lstatAsync, readlink as readlinkAsync, realpath as realpathAsync, stat as statAsync, } from "node:fs/promises";
18
+ import { homedir as osHomedir } from "node:os";
19
+ import { canonicalizeLexicalPath, joinPathSegments, normalizePathSlashes } from "./path-segments.js";
20
+ const MAX_DANGLING_SYMLINK_DEPTH = 40;
21
+ /** Split a canonical rooted POSIX-style path into ancestor candidates, deepest first. */
22
+ function ancestorPaths(canonical) {
23
+ const ancestors = [];
24
+ let current = canonical;
25
+ while (current.length > 1) {
26
+ const slash = current.lastIndexOf("/");
27
+ if (slash <= 0) {
28
+ ancestors.push("/");
29
+ return ancestors;
30
+ }
31
+ current = current.slice(0, slash);
32
+ ancestors.push(current);
33
+ }
34
+ return ancestors;
35
+ }
36
+ /**
37
+ * Create the Node identity resolver. Pure lexical work is synchronous and
38
+ * deterministic; filesystem identity is best-effort and every failure falls
39
+ * back to the lexical key so scheduling never gets *less* safe than the
40
+ * browser-safe layer.
41
+ */
42
+ export function createNodeResourceKeyResolver(options = {}) {
43
+ const home = options.homedir ?? osHomedir;
44
+ const realpath = options.realpath ?? ((path) => realpathAsync(path));
45
+ const stat = options.stat ?? ((path) => statAsync(path));
46
+ const lstat = options.lstat ?? ((path) => lstatAsync(path));
47
+ const readlink = options.readlink ?? ((path) => readlinkAsync(path));
48
+ const suffixAfter = (path, ancestor) => path.slice(ancestor.length === 1 ? 1 : ancestor.length + 1);
49
+ async function nearestRealKey(canonical) {
50
+ for (const ancestor of [canonical, ...ancestorPaths(canonical)]) {
51
+ if (!(await stat(ancestor).catch(() => null)))
52
+ continue;
53
+ const realAncestor = canonicalizeLexicalPath(normalizePathSlashes(await realpath(ancestor)));
54
+ if (realAncestor === null)
55
+ return undefined;
56
+ const suffix = suffixAfter(canonical, ancestor);
57
+ return suffix.length === 0 ? realAncestor : joinPathSegments(realAncestor, suffix);
58
+ }
59
+ return undefined;
60
+ }
61
+ async function danglingSymlinkTarget(canonical) {
62
+ for (const candidate of [canonical, ...ancestorPaths(canonical)]) {
63
+ const metadata = await lstat(candidate).catch(() => null);
64
+ if (!metadata?.isSymbolicLink())
65
+ continue;
66
+ let target = normalizePathSlashes(await readlink(candidate));
67
+ if (target.startsWith("/"))
68
+ target = target.replace(/^\/+/, "/");
69
+ const slash = candidate.lastIndexOf("/");
70
+ const parent = slash <= 0 ? "/" : candidate.slice(0, slash);
71
+ const canonicalTarget = canonicalizeLexicalPath(target.startsWith("/") ? target : joinPathSegments(parent, target));
72
+ if (canonicalTarget === null)
73
+ return null;
74
+ const suffix = suffixAfter(canonical, candidate);
75
+ return suffix.length === 0 ? canonicalTarget : joinPathSegments(canonicalTarget, suffix);
76
+ }
77
+ return undefined;
78
+ }
79
+ async function danglingSymlinkRealKey(canonical) {
80
+ const seen = new Set();
81
+ let current = canonical;
82
+ for (let depth = 0; depth < MAX_DANGLING_SYMLINK_DEPTH; depth++) {
83
+ if (seen.has(current))
84
+ return undefined;
85
+ seen.add(current);
86
+ const target = await danglingSymlinkTarget(current);
87
+ if (target === null)
88
+ return undefined;
89
+ if (target === undefined)
90
+ return nearestRealKey(current);
91
+ current = target;
92
+ }
93
+ return undefined;
94
+ }
95
+ async function resolveIdentity(canonical) {
96
+ const identity = {};
97
+ try {
98
+ const target = await stat(canonical).catch(() => null);
99
+ if (target) {
100
+ identity.inodeKey = `${target.dev}:${target.ino}`;
101
+ identity.realKey = await nearestRealKey(canonical);
102
+ return identity;
103
+ }
104
+ identity.realKey = await danglingSymlinkRealKey(canonical);
105
+ return identity;
106
+ }
107
+ catch {
108
+ return {};
109
+ }
110
+ }
111
+ return {
112
+ async resolvePath(rawPath, cwd) {
113
+ if (typeof rawPath !== "string" || rawPath.trim().length === 0 || typeof cwd !== "string") {
114
+ return null;
115
+ }
116
+ let normalized = normalizePathSlashes(rawPath);
117
+ if (/^\/{3,}/.test(normalized))
118
+ normalized = normalized.replace(/^\/+/, "/");
119
+ // Tilde expansion happens only in this Node adapter (§5.5 stage 1 note).
120
+ if (normalized === "~" || normalized.startsWith("~/")) {
121
+ try {
122
+ normalized = joinPathSegments(normalizePathSlashes(home()), normalized === "~" ? "" : normalized.slice(2));
123
+ }
124
+ catch {
125
+ return null;
126
+ }
127
+ }
128
+ // This POSIX resolver cannot establish filesystem identity for Windows
129
+ // drive or UNC paths. Null makes each call exclusive instead of sharing an
130
+ // unsafe lexical-only claim with another call.
131
+ if (normalized.startsWith("//") || /^[A-Za-z]:(?:\/|$)/.test(normalized))
132
+ return null;
133
+ const joined = normalized.startsWith("/") ? normalized : joinPathSegments(cwd, normalized);
134
+ const canonical = canonicalizeLexicalPath(joined);
135
+ if (canonical === null) {
136
+ // Root escapes, drive-relative forms, and other ambiguous shapes fail closed.
137
+ return null;
138
+ }
139
+ if (/^[A-Za-z]:\//.test(canonical))
140
+ return null;
141
+ if (!canonical.startsWith("/")) {
142
+ // Still relative after canonicalization (non-anchored cwd): fail closed.
143
+ return null;
144
+ }
145
+ return { lexicalKey: canonical, ...(await resolveIdentity(canonical)) };
146
+ },
147
+ };
148
+ }
149
+ //# sourceMappingURL=node-resource-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-resource-resolver.js","sourceRoot":"","sources":["../src/node-resource-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Node-only resource-key identity resolver for the dag-v2 scheduler (§5.5\n * stage 2). The browser-safe lexical layer in `path-segments.ts` cannot see\n * symlinks, hardlinks, or platform path aliasing; this resolver adds that\n * identity without ever weakening the lexical layer:\n *\n * 1. tilde expansion (Node adapter only), then lexical canonicalization\n * 2. POSIX three-or-more leading slashes collapse to one rooted identity\n * 3. unresolved Windows drive/UNC paths return `null` (exclusive scheduling)\n * 4. nearest existing ancestor `realpath`, including dangling-symlink targets\n * 5. `dev:ino` identity when the full path exists\n * 6. filesystem failure falls back to the lexical POSIX key\n *\n * This module is exported from `omk-agent-core/node` only; the main package\n * entry stays platform-free.\n */\n\nimport {\n\tlstat as lstatAsync,\n\treadlink as readlinkAsync,\n\trealpath as realpathAsync,\n\tstat as statAsync,\n} from \"node:fs/promises\";\nimport { homedir as osHomedir } from \"node:os\";\nimport { canonicalizeLexicalPath, joinPathSegments, normalizePathSlashes } from \"./path-segments.ts\";\nimport type { ResolvedResourceKeys, ResourceKeyResolver } from \"./types.ts\";\n\nconst MAX_DANGLING_SYMLINK_DEPTH = 40;\n\nexport interface NodeResourceKeyResolverOptions {\n\t/** Home directory used for tilde expansion. Default: `os.homedir`. */\n\thomedir?: () => string;\n\t/** Injectable realpath (tests / hardened environments). Default: `fs.promises.realpath`. */\n\trealpath?: (path: string) => Promise<string>;\n\t/** Injectable stat. Default: `fs.promises.stat`. */\n\tstat?: (path: string) => Promise<{ dev: number | bigint; ino: number | bigint }>;\n\t/** Injectable lstat used to identify dangling symlinks. */\n\tlstat?: (path: string) => Promise<{ isSymbolicLink(): boolean }>;\n\t/** Injectable readlink used to resolve dangling symlink targets. */\n\treadlink?: (path: string) => Promise<string>;\n}\n\n/** Split a canonical rooted POSIX-style path into ancestor candidates, deepest first. */\nfunction ancestorPaths(canonical: string): string[] {\n\tconst ancestors: string[] = [];\n\tlet current = canonical;\n\twhile (current.length > 1) {\n\t\tconst slash = current.lastIndexOf(\"/\");\n\t\tif (slash <= 0) {\n\t\t\tancestors.push(\"/\");\n\t\t\treturn ancestors;\n\t\t}\n\t\tcurrent = current.slice(0, slash);\n\t\tancestors.push(current);\n\t}\n\treturn ancestors;\n}\n\n/**\n * Create the Node identity resolver. Pure lexical work is synchronous and\n * deterministic; filesystem identity is best-effort and every failure falls\n * back to the lexical key so scheduling never gets *less* safe than the\n * browser-safe layer.\n */\nexport function createNodeResourceKeyResolver(options: NodeResourceKeyResolverOptions = {}): ResourceKeyResolver {\n\tconst home = options.homedir ?? osHomedir;\n\tconst realpath = options.realpath ?? ((path: string) => realpathAsync(path));\n\tconst stat = options.stat ?? ((path: string) => statAsync(path));\n\tconst lstat = options.lstat ?? ((path: string) => lstatAsync(path));\n\tconst readlink = options.readlink ?? ((path: string) => readlinkAsync(path));\n\n\tconst suffixAfter = (path: string, ancestor: string): string =>\n\t\tpath.slice(ancestor.length === 1 ? 1 : ancestor.length + 1);\n\n\tasync function nearestRealKey(canonical: string): Promise<string | undefined> {\n\t\tfor (const ancestor of [canonical, ...ancestorPaths(canonical)]) {\n\t\t\tif (!(await stat(ancestor).catch(() => null))) continue;\n\t\t\tconst realAncestor = canonicalizeLexicalPath(normalizePathSlashes(await realpath(ancestor)));\n\t\t\tif (realAncestor === null) return undefined;\n\t\t\tconst suffix = suffixAfter(canonical, ancestor);\n\t\t\treturn suffix.length === 0 ? realAncestor : joinPathSegments(realAncestor, suffix);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tasync function danglingSymlinkTarget(canonical: string): Promise<string | null | undefined> {\n\t\tfor (const candidate of [canonical, ...ancestorPaths(canonical)]) {\n\t\t\tconst metadata = await lstat(candidate).catch(() => null);\n\t\t\tif (!metadata?.isSymbolicLink()) continue;\n\t\t\tlet target = normalizePathSlashes(await readlink(candidate));\n\t\t\tif (target.startsWith(\"/\")) target = target.replace(/^\\/+/, \"/\");\n\t\t\tconst slash = candidate.lastIndexOf(\"/\");\n\t\t\tconst parent = slash <= 0 ? \"/\" : candidate.slice(0, slash);\n\t\t\tconst canonicalTarget = canonicalizeLexicalPath(\n\t\t\t\ttarget.startsWith(\"/\") ? target : joinPathSegments(parent, target),\n\t\t\t);\n\t\t\tif (canonicalTarget === null) return null;\n\t\t\tconst suffix = suffixAfter(canonical, candidate);\n\t\t\treturn suffix.length === 0 ? canonicalTarget : joinPathSegments(canonicalTarget, suffix);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tasync function danglingSymlinkRealKey(canonical: string): Promise<string | undefined> {\n\t\tconst seen = new Set<string>();\n\t\tlet current = canonical;\n\t\tfor (let depth = 0; depth < MAX_DANGLING_SYMLINK_DEPTH; depth++) {\n\t\t\tif (seen.has(current)) return undefined;\n\t\t\tseen.add(current);\n\t\t\tconst target = await danglingSymlinkTarget(current);\n\t\t\tif (target === null) return undefined;\n\t\t\tif (target === undefined) return nearestRealKey(current);\n\t\t\tcurrent = target;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tasync function resolveIdentity(canonical: string): Promise<Pick<ResolvedResourceKeys, \"realKey\" | \"inodeKey\">> {\n\t\tconst identity: { realKey?: string; inodeKey?: string } = {};\n\t\ttry {\n\t\t\tconst target = await stat(canonical).catch(() => null);\n\t\t\tif (target) {\n\t\t\t\tidentity.inodeKey = `${target.dev}:${target.ino}`;\n\t\t\t\tidentity.realKey = await nearestRealKey(canonical);\n\t\t\t\treturn identity;\n\t\t\t}\n\t\t\tidentity.realKey = await danglingSymlinkRealKey(canonical);\n\t\t\treturn identity;\n\t\t} catch {\n\t\t\treturn {};\n\t\t}\n\t}\n\n\treturn {\n\t\tasync resolvePath(rawPath: string, cwd: string): Promise<ResolvedResourceKeys | null> {\n\t\t\tif (typeof rawPath !== \"string\" || rawPath.trim().length === 0 || typeof cwd !== \"string\") {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tlet normalized = normalizePathSlashes(rawPath);\n\t\t\tif (/^\\/{3,}/.test(normalized)) normalized = normalized.replace(/^\\/+/, \"/\");\n\t\t\t// Tilde expansion happens only in this Node adapter (§5.5 stage 1 note).\n\t\t\tif (normalized === \"~\" || normalized.startsWith(\"~/\")) {\n\t\t\t\ttry {\n\t\t\t\t\tnormalized = joinPathSegments(\n\t\t\t\t\t\tnormalizePathSlashes(home()),\n\t\t\t\t\t\tnormalized === \"~\" ? \"\" : normalized.slice(2),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// This POSIX resolver cannot establish filesystem identity for Windows\n\t\t\t// drive or UNC paths. Null makes each call exclusive instead of sharing an\n\t\t\t// unsafe lexical-only claim with another call.\n\t\t\tif (normalized.startsWith(\"//\") || /^[A-Za-z]:(?:\\/|$)/.test(normalized)) return null;\n\n\t\t\tconst joined = normalized.startsWith(\"/\") ? normalized : joinPathSegments(cwd, normalized);\n\t\t\tconst canonical = canonicalizeLexicalPath(joined);\n\t\t\tif (canonical === null) {\n\t\t\t\t// Root escapes, drive-relative forms, and other ambiguous shapes fail closed.\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (/^[A-Za-z]:\\//.test(canonical)) return null;\n\t\t\tif (!canonical.startsWith(\"/\")) {\n\t\t\t\t// Still relative after canonicalization (non-anchored cwd): fail closed.\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn { lexicalKey: canonical, ...(await resolveIdentity(canonical)) };\n\t\t},\n\t};\n}\n"]}
package/dist/node.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { NodeExecutionEnv } from "./harness/env/nodejs.ts";
2
2
  export * from "./index.ts";
3
+ export { createNodeResourceKeyResolver, type NodeResourceKeyResolverOptions, } from "./node-resource-resolver.ts";
3
4
  //# sourceMappingURL=node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,cAAc,YAAY,CAAC","sourcesContent":["export { NodeExecutionEnv } from \"./harness/env/nodejs.ts\";\nexport * from \"./index.ts\";\n"]}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,cAAc,YAAY,CAAC;AAE3B,OAAO,EACN,6BAA6B,EAC7B,KAAK,8BAA8B,GACnC,MAAM,6BAA6B,CAAC","sourcesContent":["export { NodeExecutionEnv } from \"./harness/env/nodejs.ts\";\nexport * from \"./index.ts\";\n// Node-only §5.5 identity resolver for the dag-v2 scheduler (fs/realpath/inode).\nexport {\n\tcreateNodeResourceKeyResolver,\n\ttype NodeResourceKeyResolverOptions,\n} from \"./node-resource-resolver.ts\";\n"]}
package/dist/node.js CHANGED
@@ -1,3 +1,5 @@
1
1
  export { NodeExecutionEnv } from "./harness/env/nodejs.js";
2
2
  export * from "./index.js";
3
+ // Node-only §5.5 identity resolver for the dag-v2 scheduler (fs/realpath/inode).
4
+ export { createNodeResourceKeyResolver, } from "./node-resource-resolver.js";
3
5
  //# sourceMappingURL=node.js.map
package/dist/node.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,cAAc,YAAY,CAAC","sourcesContent":["export { NodeExecutionEnv } from \"./harness/env/nodejs.ts\";\nexport * from \"./index.ts\";\n"]}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,cAAc,YAAY,CAAC;AAC3B,kFAAiF;AACjF,OAAO,EACN,6BAA6B,GAE7B,MAAM,6BAA6B,CAAC","sourcesContent":["export { NodeExecutionEnv } from \"./harness/env/nodejs.ts\";\nexport * from \"./index.ts\";\n// Node-only §5.5 identity resolver for the dag-v2 scheduler (fs/realpath/inode).\nexport {\n\tcreateNodeResourceKeyResolver,\n\ttype NodeResourceKeyResolverOptions,\n} from \"./node-resource-resolver.ts\";\n"]}
@@ -24,7 +24,18 @@ export declare function extractParallelScopePath(toolName: string, functionArgs:
24
24
  /** True when two normalized paths may refer to the same file or subtree. */
25
25
  export declare function pathsOverlap(left: string, right: string): boolean;
26
26
  /**
27
- * Return true when a tool-call batch is safe to run concurrently (Hermes-style policy, OMK tool names).
27
+ * Partition a tool-call batch into ordered, contiguous waves of original
28
+ * indices. Calls inside one wave may run concurrently; waves run one after
29
+ * another in source order, so cross-wave ordering always matches the model's
30
+ * emission order. Solo-classified calls become single-call waves, and a
31
+ * path-scoped call starts a new wave when its target overlaps a path already
32
+ * reserved in the current wave.
33
+ */
34
+ export declare function partitionToolBatchWaves(toolCalls: ParallelizableToolCall[], options?: ShouldParallelizeToolBatchOptions): number[][];
35
+ /**
36
+ * Return true when an entire tool-call batch is safe to run concurrently as a
37
+ * single wave (Hermes-style policy, OMK tool names). Wave-based execution in
38
+ * the agent loop uses partitionToolBatchWaves directly for partial parallelism.
28
39
  */
29
40
  export declare function shouldParallelizeToolBatch(toolCalls: ParallelizableToolCall[], options?: ShouldParallelizeToolBatchOptions): boolean;
30
41
  //# sourceMappingURL=parallel-tool-batch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-tool-batch.d.ts","sourceRoot":"","sources":["../src/parallel-tool-batch.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,eAAO,MAAM,oBAAoB,aAA+B,CAAC;AAEjE,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,aAY9B,CAAC;AAEH,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,aAA6C,CAAC;AAE5E,MAAM,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,UAAU,CAAC;AAE3D,MAAM,MAAM,iCAAiC,GAAG;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACvD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACrD,CAAC;AAMF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWjE;AAED,wBAAgB,wBAAwB,CACvC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,GAAG,GAAE,MAAsB,GACzB,MAAM,GAAG,IAAI,CAef;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACzC,SAAS,EAAE,sBAAsB,EAAE,EACnC,OAAO,GAAE,iCAAsC,GAC7C,OAAO,CAyET","sourcesContent":["import { joinPathSegments, normalizePathSlashes, pathSegmentsOverlap } from \"./path-segments.ts\";\n\n/** Tool names that must never run concurrently with other tool calls in a batch. */\nexport const NEVER_PARALLEL_TOOLS = new Set<string>([\"clarify\"]);\n\n/** Read-only tools with no shared mutable session state (OMK built-in / harness). */\nexport const PARALLEL_SAFE_TOOLS = new Set<string>([\n\t\"grep\",\n\t\"find\",\n\t\"ls\",\n\t\"read\",\n\t\"search_files\",\n\t\"session_search\",\n\t\"skill_view\",\n\t\"skills_list\",\n\t\"vision_analyze\",\n\t\"web_extract\",\n\t\"web_search\",\n]);\n\n/** File tools that may run concurrently when they target independent paths. */\nexport const PATH_SCOPED_TOOLS = new Set<string>([\"read\", \"write\", \"edit\"]);\n\nexport type ParallelizableToolCall = {\n\tname: string;\n\targuments: Record<string, unknown>;\n};\n\nexport type ToolParallelPolicy = \"sequential\" | \"parallel\";\n\nexport type ShouldParallelizeToolBatchOptions = {\n\tcwd?: string;\n\t/** Per-tool executionMode from AgentTool definitions (extension/custom tools). */\n\ttoolPolicies?: ReadonlyMap<string, ToolParallelPolicy>;\n\t/**\n\t * When a tool name is not in built-in parallel/path sets and has no explicit policy,\n\t * return true to allow parallel batching (e.g. test harness tools with executionMode=parallel).\n\t */\n\tallowUnknownParallel?: (toolName: string) => boolean;\n};\n\nconst DESTRUCTIVE_COMMAND =\n\t/(?:^|\\s|&&|\\|\\||;|`)(?:rm\\s|rmdir\\s|mv\\s|sed\\s+-i|truncate\\s|dd\\s|shred\\s|git\\s+(?:reset|clean|checkout)\\s)/;\nconst REDIRECT_OVERWRITE = /[^>]>[^>]|^>[^>]/;\n\nexport function isDestructiveBashCommand(command: string): boolean {\n\tif (!command) {\n\t\treturn false;\n\t}\n\tif (DESTRUCTIVE_COMMAND.test(command)) {\n\t\treturn true;\n\t}\n\tif (REDIRECT_OVERWRITE.test(command)) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nexport function extractParallelScopePath(\n\ttoolName: string,\n\tfunctionArgs: Record<string, unknown>,\n\tcwd: string = process.cwd(),\n): string | null {\n\tif (!PATH_SCOPED_TOOLS.has(toolName)) {\n\t\treturn null;\n\t}\n\tconst rawPath = functionArgs.path;\n\tif (typeof rawPath !== \"string\" || !rawPath.trim()) {\n\t\treturn null;\n\t}\n\tconst expanded = normalizePathSlashes(\n\t\trawPath.startsWith(\"~\") ? rawPath.replace(/^~/, process.env.HOME ?? \"\") : rawPath,\n\t);\n\tif (expanded.startsWith(\"/\")) {\n\t\treturn expanded;\n\t}\n\treturn joinPathSegments(cwd, expanded);\n}\n\n/** True when two normalized paths may refer to the same file or subtree. */\nexport function pathsOverlap(left: string, right: string): boolean {\n\treturn pathSegmentsOverlap(left, right);\n}\n\n/**\n * Return true when a tool-call batch is safe to run concurrently (Hermes-style policy, OMK tool names).\n */\nexport function shouldParallelizeToolBatch(\n\ttoolCalls: ParallelizableToolCall[],\n\toptions: ShouldParallelizeToolBatchOptions = {},\n): boolean {\n\tif (toolCalls.length <= 1) {\n\t\treturn false;\n\t}\n\n\tconst cwd = options.cwd;\n\tconst toolPolicies = options.toolPolicies;\n\tconst allowUnknownParallel = options.allowUnknownParallel;\n\n\tconst toolNames = toolCalls.map((tc) => tc.name);\n\tif (toolNames.some((name) => NEVER_PARALLEL_TOOLS.has(name))) {\n\t\treturn false;\n\t}\n\n\tfor (const name of toolNames) {\n\t\tif (toolPolicies?.get(name) === \"sequential\") {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tconst bashCount = toolNames.filter((name) => name === \"bash\").length;\n\tif (bashCount >= 2) {\n\t\treturn false;\n\t}\n\n\tconst reservedPaths: string[] = [];\n\n\tfor (const toolCall of toolCalls) {\n\t\tconst toolName = toolCall.name;\n\t\tconst functionArgs = toolCall.arguments;\n\t\tif (!functionArgs || typeof functionArgs !== \"object\" || Array.isArray(functionArgs)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (toolName === \"bash\") {\n\t\t\tconst command = functionArgs.command;\n\t\t\tif (typeof command !== \"string\") {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (isDestructiveBashCommand(command)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// bash is not parallel-safe with any other tool in the batch\n\t\t\tif (toolCalls.length > 1) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (PATH_SCOPED_TOOLS.has(toolName)) {\n\t\t\tconst scopedPath = extractParallelScopePath(toolName, functionArgs, cwd);\n\t\t\tif (scopedPath === null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (reservedPaths.some((existing) => pathsOverlap(scopedPath, existing))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treservedPaths.push(scopedPath);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (PARALLEL_SAFE_TOOLS.has(toolName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (toolPolicies?.get(toolName) === \"parallel\" || allowUnknownParallel?.(toolName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n"]}
1
+ {"version":3,"file":"parallel-tool-batch.d.ts","sourceRoot":"","sources":["../src/parallel-tool-batch.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,eAAO,MAAM,oBAAoB,aAA+B,CAAC;AAEjE,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,aAY9B,CAAC;AAEH,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,aAA6C,CAAC;AAE5E,MAAM,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,UAAU,CAAC;AAE3D,MAAM,MAAM,iCAAiC,GAAG;IAC/C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACvD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACrD,CAAC;AAMF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWjE;AAED,wBAAgB,wBAAwB,CACvC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,GAAG,GAAE,MAAsB,GACzB,MAAM,GAAG,IAAI,CAef;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjE;AAqCD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACtC,SAAS,EAAE,sBAAsB,EAAE,EACnC,OAAO,GAAE,iCAAsC,GAC7C,MAAM,EAAE,EAAE,CAqCZ;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACzC,SAAS,EAAE,sBAAsB,EAAE,EACnC,OAAO,GAAE,iCAAsC,GAC7C,OAAO,CAKT","sourcesContent":["import { joinPathSegments, normalizePathSlashes, pathSegmentsOverlap } from \"./path-segments.ts\";\n\n/** Tool names that must never run concurrently with other tool calls in a batch. */\nexport const NEVER_PARALLEL_TOOLS = new Set<string>([\"clarify\"]);\n\n/** Read-only tools with no shared mutable session state (OMK built-in / harness). */\nexport const PARALLEL_SAFE_TOOLS = new Set<string>([\n\t\"grep\",\n\t\"find\",\n\t\"ls\",\n\t\"read\",\n\t\"search_files\",\n\t\"session_search\",\n\t\"skill_view\",\n\t\"skills_list\",\n\t\"vision_analyze\",\n\t\"web_extract\",\n\t\"web_search\",\n]);\n\n/** File tools that may run concurrently when they target independent paths. */\nexport const PATH_SCOPED_TOOLS = new Set<string>([\"read\", \"write\", \"edit\"]);\n\nexport type ParallelizableToolCall = {\n\tname: string;\n\targuments: Record<string, unknown>;\n};\n\nexport type ToolParallelPolicy = \"sequential\" | \"parallel\";\n\nexport type ShouldParallelizeToolBatchOptions = {\n\tcwd?: string;\n\t/** Per-tool executionMode from AgentTool definitions (extension/custom tools). */\n\ttoolPolicies?: ReadonlyMap<string, ToolParallelPolicy>;\n\t/**\n\t * When a tool name is not in built-in parallel/path sets and has no explicit policy,\n\t * return true to allow parallel batching (e.g. test harness tools with executionMode=parallel).\n\t */\n\tallowUnknownParallel?: (toolName: string) => boolean;\n};\n\nconst DESTRUCTIVE_COMMAND =\n\t/(?:^|\\s|&&|\\|\\||;|`)(?:rm\\s|rmdir\\s|mv\\s|sed\\s+-i|truncate\\s|dd\\s|shred\\s|git\\s+(?:reset|clean|checkout)\\s)/;\nconst REDIRECT_OVERWRITE = /[^>]>[^>]|^>[^>]/;\n\nexport function isDestructiveBashCommand(command: string): boolean {\n\tif (!command) {\n\t\treturn false;\n\t}\n\tif (DESTRUCTIVE_COMMAND.test(command)) {\n\t\treturn true;\n\t}\n\tif (REDIRECT_OVERWRITE.test(command)) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nexport function extractParallelScopePath(\n\ttoolName: string,\n\tfunctionArgs: Record<string, unknown>,\n\tcwd: string = process.cwd(),\n): string | null {\n\tif (!PATH_SCOPED_TOOLS.has(toolName)) {\n\t\treturn null;\n\t}\n\tconst rawPath = functionArgs.path;\n\tif (typeof rawPath !== \"string\" || !rawPath.trim()) {\n\t\treturn null;\n\t}\n\tconst expanded = normalizePathSlashes(\n\t\trawPath.startsWith(\"~\") ? rawPath.replace(/^~/, process.env.HOME ?? \"\") : rawPath,\n\t);\n\tif (expanded.startsWith(\"/\")) {\n\t\treturn expanded;\n\t}\n\treturn joinPathSegments(cwd, expanded);\n}\n\n/** True when two normalized paths may refer to the same file or subtree. */\nexport function pathsOverlap(left: string, right: string): boolean {\n\treturn pathSegmentsOverlap(left, right);\n}\n\ntype ToolCallKind = \"solo\" | \"safe\" | \"path\";\n\n/**\n * Classify one tool call for wave scheduling. \"solo\" calls run alone in their\n * own wave (fail closed): clarify-style tools, sequential-policy tools, bash\n * (never parallel-safe with any other call), invalid argument shapes, and\n * unknown tools without an explicit parallel grant.\n */\nfunction classifyToolCall(toolCall: ParallelizableToolCall, options: ShouldParallelizeToolBatchOptions): ToolCallKind {\n\tconst name = toolCall.name;\n\tif (NEVER_PARALLEL_TOOLS.has(name)) {\n\t\treturn \"solo\";\n\t}\n\tif (options.toolPolicies?.get(name) === \"sequential\") {\n\t\treturn \"solo\";\n\t}\n\tconst functionArgs = toolCall.arguments;\n\tif (!functionArgs || typeof functionArgs !== \"object\" || Array.isArray(functionArgs)) {\n\t\treturn \"solo\";\n\t}\n\tif (name === \"bash\") {\n\t\treturn \"solo\";\n\t}\n\tif (PATH_SCOPED_TOOLS.has(name)) {\n\t\treturn \"path\";\n\t}\n\tif (PARALLEL_SAFE_TOOLS.has(name)) {\n\t\treturn \"safe\";\n\t}\n\tif (options.toolPolicies?.get(name) === \"parallel\" || options.allowUnknownParallel?.(name)) {\n\t\treturn \"safe\";\n\t}\n\treturn \"solo\";\n}\n\n/**\n * Partition a tool-call batch into ordered, contiguous waves of original\n * indices. Calls inside one wave may run concurrently; waves run one after\n * another in source order, so cross-wave ordering always matches the model's\n * emission order. Solo-classified calls become single-call waves, and a\n * path-scoped call starts a new wave when its target overlaps a path already\n * reserved in the current wave.\n */\nexport function partitionToolBatchWaves(\n\ttoolCalls: ParallelizableToolCall[],\n\toptions: ShouldParallelizeToolBatchOptions = {},\n): number[][] {\n\tconst waves: number[][] = [];\n\tlet wave: number[] = [];\n\tlet wavePaths: string[] = [];\n\n\tconst closeWave = (): void => {\n\t\tif (wave.length > 0) {\n\t\t\twaves.push(wave);\n\t\t\twave = [];\n\t\t\twavePaths = [];\n\t\t}\n\t};\n\n\tfor (let index = 0; index < toolCalls.length; index++) {\n\t\tconst toolCall = toolCalls[index];\n\t\tconst kind = classifyToolCall(toolCall, options);\n\t\tif (kind === \"solo\") {\n\t\t\tcloseWave();\n\t\t\twaves.push([index]);\n\t\t\tcontinue;\n\t\t}\n\t\tif (kind === \"path\") {\n\t\t\tconst scopedPath = extractParallelScopePath(toolCall.name, toolCall.arguments, options.cwd);\n\t\t\tif (scopedPath === null) {\n\t\t\t\tcloseWave();\n\t\t\t\twaves.push([index]);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (wavePaths.some((existing) => pathsOverlap(scopedPath, existing))) {\n\t\t\t\tcloseWave();\n\t\t\t}\n\t\t\twavePaths.push(scopedPath);\n\t\t}\n\t\twave.push(index);\n\t}\n\tcloseWave();\n\treturn waves;\n}\n\n/**\n * Return true when an entire tool-call batch is safe to run concurrently as a\n * single wave (Hermes-style policy, OMK tool names). Wave-based execution in\n * the agent loop uses partitionToolBatchWaves directly for partial parallelism.\n */\nexport function shouldParallelizeToolBatch(\n\ttoolCalls: ParallelizableToolCall[],\n\toptions: ShouldParallelizeToolBatchOptions = {},\n): boolean {\n\tif (toolCalls.length <= 1) {\n\t\treturn false;\n\t}\n\treturn partitionToolBatchWaves(toolCalls, options).length === 1;\n}\n"]}
@@ -50,68 +50,90 @@ export function pathsOverlap(left, right) {
50
50
  return pathSegmentsOverlap(left, right);
51
51
  }
52
52
  /**
53
- * Return true when a tool-call batch is safe to run concurrently (Hermes-style policy, OMK tool names).
53
+ * Classify one tool call for wave scheduling. "solo" calls run alone in their
54
+ * own wave (fail closed): clarify-style tools, sequential-policy tools, bash
55
+ * (never parallel-safe with any other call), invalid argument shapes, and
56
+ * unknown tools without an explicit parallel grant.
54
57
  */
55
- export function shouldParallelizeToolBatch(toolCalls, options = {}) {
56
- if (toolCalls.length <= 1) {
57
- return false;
58
+ function classifyToolCall(toolCall, options) {
59
+ const name = toolCall.name;
60
+ if (NEVER_PARALLEL_TOOLS.has(name)) {
61
+ return "solo";
58
62
  }
59
- const cwd = options.cwd;
60
- const toolPolicies = options.toolPolicies;
61
- const allowUnknownParallel = options.allowUnknownParallel;
62
- const toolNames = toolCalls.map((tc) => tc.name);
63
- if (toolNames.some((name) => NEVER_PARALLEL_TOOLS.has(name))) {
64
- return false;
63
+ if (options.toolPolicies?.get(name) === "sequential") {
64
+ return "solo";
65
65
  }
66
- for (const name of toolNames) {
67
- if (toolPolicies?.get(name) === "sequential") {
68
- return false;
69
- }
66
+ const functionArgs = toolCall.arguments;
67
+ if (!functionArgs || typeof functionArgs !== "object" || Array.isArray(functionArgs)) {
68
+ return "solo";
70
69
  }
71
- const bashCount = toolNames.filter((name) => name === "bash").length;
72
- if (bashCount >= 2) {
73
- return false;
70
+ if (name === "bash") {
71
+ return "solo";
72
+ }
73
+ if (PATH_SCOPED_TOOLS.has(name)) {
74
+ return "path";
74
75
  }
75
- const reservedPaths = [];
76
- for (const toolCall of toolCalls) {
77
- const toolName = toolCall.name;
78
- const functionArgs = toolCall.arguments;
79
- if (!functionArgs || typeof functionArgs !== "object" || Array.isArray(functionArgs)) {
80
- return false;
76
+ if (PARALLEL_SAFE_TOOLS.has(name)) {
77
+ return "safe";
78
+ }
79
+ if (options.toolPolicies?.get(name) === "parallel" || options.allowUnknownParallel?.(name)) {
80
+ return "safe";
81
+ }
82
+ return "solo";
83
+ }
84
+ /**
85
+ * Partition a tool-call batch into ordered, contiguous waves of original
86
+ * indices. Calls inside one wave may run concurrently; waves run one after
87
+ * another in source order, so cross-wave ordering always matches the model's
88
+ * emission order. Solo-classified calls become single-call waves, and a
89
+ * path-scoped call starts a new wave when its target overlaps a path already
90
+ * reserved in the current wave.
91
+ */
92
+ export function partitionToolBatchWaves(toolCalls, options = {}) {
93
+ const waves = [];
94
+ let wave = [];
95
+ let wavePaths = [];
96
+ const closeWave = () => {
97
+ if (wave.length > 0) {
98
+ waves.push(wave);
99
+ wave = [];
100
+ wavePaths = [];
81
101
  }
82
- if (toolName === "bash") {
83
- const command = functionArgs.command;
84
- if (typeof command !== "string") {
85
- return false;
86
- }
87
- if (isDestructiveBashCommand(command)) {
88
- return false;
89
- }
90
- // bash is not parallel-safe with any other tool in the batch
91
- if (toolCalls.length > 1) {
92
- return false;
93
- }
102
+ };
103
+ for (let index = 0; index < toolCalls.length; index++) {
104
+ const toolCall = toolCalls[index];
105
+ const kind = classifyToolCall(toolCall, options);
106
+ if (kind === "solo") {
107
+ closeWave();
108
+ waves.push([index]);
94
109
  continue;
95
110
  }
96
- if (PATH_SCOPED_TOOLS.has(toolName)) {
97
- const scopedPath = extractParallelScopePath(toolName, functionArgs, cwd);
111
+ if (kind === "path") {
112
+ const scopedPath = extractParallelScopePath(toolCall.name, toolCall.arguments, options.cwd);
98
113
  if (scopedPath === null) {
99
- return false;
114
+ closeWave();
115
+ waves.push([index]);
116
+ continue;
100
117
  }
101
- if (reservedPaths.some((existing) => pathsOverlap(scopedPath, existing))) {
102
- return false;
118
+ if (wavePaths.some((existing) => pathsOverlap(scopedPath, existing))) {
119
+ closeWave();
103
120
  }
104
- reservedPaths.push(scopedPath);
105
- continue;
106
- }
107
- if (PARALLEL_SAFE_TOOLS.has(toolName)) {
108
- continue;
109
- }
110
- if (toolPolicies?.get(toolName) === "parallel" || allowUnknownParallel?.(toolName)) {
111
- continue;
121
+ wavePaths.push(scopedPath);
112
122
  }
123
+ wave.push(index);
124
+ }
125
+ closeWave();
126
+ return waves;
127
+ }
128
+ /**
129
+ * Return true when an entire tool-call batch is safe to run concurrently as a
130
+ * single wave (Hermes-style policy, OMK tool names). Wave-based execution in
131
+ * the agent loop uses partitionToolBatchWaves directly for partial parallelism.
132
+ */
133
+ export function shouldParallelizeToolBatch(toolCalls, options = {}) {
134
+ if (toolCalls.length <= 1) {
113
135
  return false;
114
136
  }
115
- return true;
137
+ return partitionToolBatchWaves(toolCalls, options).length === 1;
116
138
  }
117
139
  //# sourceMappingURL=parallel-tool-batch.js.map