@aiwg/cli 2026.10.3 → 2026.10.4

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 (279) hide show
  1. package/README.md +2 -2
  2. package/agentic/code/providers/model-capabilities.v1.json +96 -4
  3. package/bin/aiwg.mjs +50 -27
  4. package/dist/src/agents/grounding/knowledge-base.js +54 -6
  5. package/dist/src/artifacts/browser-export.js +6 -0
  6. package/dist/src/artifacts/checksum-manifest.js +1 -0
  7. package/dist/src/artifacts/citation-parser.js +173 -92
  8. package/dist/src/artifacts/citation-table-schema.js +59 -0
  9. package/dist/src/artifacts/cli.js +57 -18
  10. package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
  11. package/dist/src/artifacts/corpus-tools/vision-extract.js +2 -0
  12. package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
  13. package/dist/src/artifacts/corpus-views/renderers.js +3 -3
  14. package/dist/src/artifacts/discovery-eval.js +6 -4
  15. package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
  16. package/dist/src/artifacts/fortemi-core-sync.js +166 -40
  17. package/dist/src/artifacts/framework-capabilities.js +171 -0
  18. package/dist/src/artifacts/framework-index-paths.js +73 -0
  19. package/dist/src/artifacts/framework-source-digest.js +75 -0
  20. package/dist/src/artifacts/index-builder.js +285 -131
  21. package/dist/src/artifacts/index-files.js +132 -18
  22. package/dist/src/artifacts/index-preparation.js +65 -0
  23. package/dist/src/artifacts/index-refresh.js +576 -0
  24. package/dist/src/artifacts/index-worker.mjs +9 -0
  25. package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
  26. package/dist/src/artifacts/prebuilt-deployment.js +46 -0
  27. package/dist/src/artifacts/prebuilt-relations.js +80 -0
  28. package/dist/src/artifacts/query-engine.js +410 -88
  29. package/dist/src/artifacts/relations-builder.js +168 -0
  30. package/dist/src/artifacts/relations.js +148 -0
  31. package/dist/src/artifacts/stats.js +5 -2
  32. package/dist/src/artifacts/types.js +30 -10
  33. package/dist/src/artifacts/watcher.js +1 -1
  34. package/dist/src/auth/credential-store.js +2 -1
  35. package/dist/src/catalog/cli.d.mts +5 -0
  36. package/dist/src/channel/manager.d.mts +20 -0
  37. package/dist/src/channel/manager.mjs +19 -2
  38. package/dist/src/cli/command-log.js +2 -3
  39. package/dist/src/cli/handlers/artifacts.js +3 -0
  40. package/dist/src/cli/handlers/auth.js +3 -0
  41. package/dist/src/cli/handlers/decision.js +19 -12
  42. package/dist/src/cli/handlers/diagnose.js +4 -3
  43. package/dist/src/cli/handlers/effect.js +4 -2
  44. package/dist/src/cli/handlers/evidence.js +3 -0
  45. package/dist/src/cli/handlers/help.js +1 -0
  46. package/dist/src/cli/handlers/index.js +3 -1
  47. package/dist/src/cli/handlers/init.js +4 -1
  48. package/dist/src/cli/handlers/lint.js +5 -0
  49. package/dist/src/cli/handlers/models.js +104 -8
  50. package/dist/src/cli/handlers/ralph-launcher.js +2 -0
  51. package/dist/src/cli/handlers/refresh.js +12 -0
  52. package/dist/src/cli/handlers/resource-versions.js +3 -0
  53. package/dist/src/cli/handlers/rules.js +195 -0
  54. package/dist/src/cli/handlers/run.js +4 -0
  55. package/dist/src/cli/handlers/runtime-info.js +1 -2
  56. package/dist/src/cli/handlers/script-runner.js +3 -2
  57. package/dist/src/cli/handlers/session.js +19 -9
  58. package/dist/src/cli/handlers/sessions.js +98 -37
  59. package/dist/src/cli/handlers/setup-manifest.js +39 -44
  60. package/dist/src/cli/handlers/setup.js +41 -0
  61. package/dist/src/cli/handlers/steward.js +11 -0
  62. package/dist/src/cli/handlers/subcommands.js +57 -2
  63. package/dist/src/cli/handlers/uhp.js +3 -0
  64. package/dist/src/cli/handlers/use.js +294 -55
  65. package/dist/src/cli/handlers/utilities.js +26 -10
  66. package/dist/src/cli/handlers/version.js +8 -0
  67. package/dist/src/cli/router.js +15 -1
  68. package/dist/src/cli/services/deployment-verification.js +19 -9
  69. package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
  70. package/dist/src/cli/skill-usage.js +2 -3
  71. package/dist/src/config/aiwg-config.js +87 -37
  72. package/dist/src/config/cli.js +111 -5
  73. package/dist/src/config/decision-config.js +106 -0
  74. package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
  75. package/dist/src/config/gitignore.js +50 -0
  76. package/dist/src/config/index-graph-overrides.js +36 -0
  77. package/dist/src/config/project-artifacts-health.d.mts +37 -0
  78. package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
  79. package/dist/src/config/user-config-dir.d.mts +9 -0
  80. package/dist/src/config/user-config.js +2 -1
  81. package/dist/src/config/user-registry.js +23 -15
  82. package/dist/src/config/user-state.js +7 -0
  83. package/dist/src/decision/ask.js +203 -43
  84. package/dist/src/decision/context-live-qualification.js +2 -2
  85. package/dist/src/decision/driver.js +13 -8
  86. package/dist/src/decision/ensemble/aggregate.js +23 -10
  87. package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
  88. package/dist/src/decision/entry.js +2 -15
  89. package/dist/src/decision/graph-live-qualification.js +1 -1
  90. package/dist/src/decision/graph-run.js +9 -0
  91. package/dist/src/decision/heldout/collector.js +5 -13
  92. package/dist/src/decision/heldout/contract.js +30 -7
  93. package/dist/src/decision/jev-credentials.js +15 -1
  94. package/dist/src/decision/ledger.js +131 -28
  95. package/dist/src/decision/offload-activation.js +137 -0
  96. package/dist/src/decision/offload.js +550 -0
  97. package/dist/src/decision/qualification/load.js +4 -6
  98. package/dist/src/decision/savings.js +28 -0
  99. package/dist/src/effects/types.js +5 -1
  100. package/dist/src/effects/verifiers/git.js +2 -1
  101. package/dist/src/effects/verifiers/tracker.js +26 -14
  102. package/dist/src/extensions/commands/definitions.js +19 -0
  103. package/dist/src/extensions/project-local-remove.js +36 -1
  104. package/dist/src/gates/providers/loader.js +61 -17
  105. package/dist/src/installation/manager-command.d.mts +18 -0
  106. package/dist/src/installation/manager-command.mjs +14 -2
  107. package/dist/src/installation/manager.d.mts +49 -0
  108. package/dist/src/installation/manager.mjs +78 -3
  109. package/dist/src/issues/cli.js +4 -4
  110. package/dist/src/issues/local.js +24 -5
  111. package/dist/src/jobs/runner.js +1 -1
  112. package/dist/src/lint/cli.js +27 -1
  113. package/dist/src/lint/loader.js +2 -1
  114. package/dist/src/lint/reporters.js +25 -1
  115. package/dist/src/lint/rule-activation.js +43 -0
  116. package/dist/src/lint/runner.js +137 -62
  117. package/dist/src/mcp/adapters/codex-runtime.js +7 -1
  118. package/dist/src/mcp/claude-install.d.mts +4 -0
  119. package/dist/src/mcp/claude-install.mjs +41 -0
  120. package/dist/src/mcp/cli.d.mts +1 -0
  121. package/dist/src/mcp/cli.mjs +36 -11
  122. package/dist/src/mcp/config-file.d.mts +28 -0
  123. package/dist/src/mcp/config-layers.d.mts +36 -0
  124. package/dist/src/mcp/credentials.d.mts +51 -0
  125. package/dist/src/mcp/grok-build-config.d.mts +6 -0
  126. package/dist/src/mcp/grok-build-config.mjs +1 -1
  127. package/dist/src/mcp/helpers.mjs +3 -2
  128. package/dist/src/mcp/muse-native-config.d.mts +13 -0
  129. package/dist/src/mcp/muse-native-config.mjs +1 -0
  130. package/dist/src/mcp/omp-config.d.mts +4 -0
  131. package/dist/src/mcp/registry.js +3 -93
  132. package/dist/src/mcp/registry.mjs +3 -87
  133. package/dist/src/mcp/server-config.d.mts +3 -0
  134. package/dist/src/mcp/server-config.mjs +89 -0
  135. package/dist/src/mcp/server.mjs +37 -375
  136. package/dist/src/mcp/test-simple.mjs +2 -1
  137. package/dist/src/mcp/toml-editor.d.mts +4 -0
  138. package/dist/src/mcp/toml-string.d.mts +1 -0
  139. package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
  140. package/dist/src/mcp/tool-filters.d.mts +46 -0
  141. package/dist/src/mcp/tools/decision.mjs +12 -11
  142. package/dist/src/mcp/tools/discovery.mjs +62 -55
  143. package/dist/src/mcp/tools/orchestration.mjs +12 -2
  144. package/dist/src/mcp/tools/worker-invoke.mjs +1340 -23
  145. package/dist/src/mcp/tools/worker-shell-control.mjs +52 -21
  146. package/dist/src/mcp/tools/worker-stdin-runtime.mjs +3 -3
  147. package/dist/src/mission-protocol/codecs.js +8 -0
  148. package/dist/src/models/config-loader.js +7 -2
  149. package/dist/src/models/model-capabilities.v1.json +96 -4
  150. package/dist/src/models/model-discovery.js +76 -11
  151. package/dist/src/models/provider-policy.js +101 -7
  152. package/dist/src/models/qualification-digest.d.mts +2 -0
  153. package/dist/src/models/resolver.js +12 -10
  154. package/dist/src/models/worker-direct-readiness.js +65 -44
  155. package/dist/src/models/worker-dispatch-offer.js +3 -3
  156. package/dist/src/models/worker-health-readiness.js +16 -3
  157. package/dist/src/models/worker-installation.d.mts +39 -0
  158. package/dist/src/models/worker-installation.mjs +135 -28
  159. package/dist/src/process/bounded-child-process.d.mts +84 -0
  160. package/dist/src/process/bounded-child-process.mjs +43 -0
  161. package/dist/src/process/cli-command.d.mts +16 -0
  162. package/dist/src/process/signal-child.d.mts +6 -0
  163. package/dist/src/process/signal-child.mjs +7 -0
  164. package/dist/src/providers/deployed-skill-roots.js +20 -0
  165. package/dist/src/providers/grok-build-acp.js +3 -2
  166. package/dist/src/providers/grok-build-headless.js +12 -4
  167. package/dist/src/providers/grok-build-inspect.js +1 -0
  168. package/dist/src/providers/omp-agent.d.mts +8 -0
  169. package/dist/src/providers/omp-diagnostics.d.mts +1 -0
  170. package/dist/src/providers/omp-paths.d.mts +13 -0
  171. package/dist/src/providers/skill-ownership.d.mts +9 -0
  172. package/dist/src/providers/skill-ownership.mjs +88 -0
  173. package/dist/src/rules/activation.d.mts +21 -0
  174. package/dist/src/rules/activation.mjs +62 -0
  175. package/dist/src/rules/inline-budget.d.mts +26 -0
  176. package/dist/src/rules/inline-budget.mjs +66 -0
  177. package/dist/src/rules/inventory.js +129 -0
  178. package/dist/src/rules/pin-state.js +73 -0
  179. package/dist/src/rules/pins.d.mts +14 -0
  180. package/dist/src/rules/pins.mjs +112 -0
  181. package/dist/src/rules/rule-frontmatter.schema.json +197 -0
  182. package/dist/src/serve/mission-conductor.js +38 -12
  183. package/dist/src/serve/worker-invocation.js +30 -10
  184. package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
  185. package/dist/src/sessions/adapter-registry.js +23 -19
  186. package/dist/src/sessions/adapters/claude.js +39 -54
  187. package/dist/src/sessions/adapters/codex.js +82 -67
  188. package/dist/src/sessions/adapters/copilot.js +4 -4
  189. package/dist/src/sessions/adapters/cursor.js +40 -57
  190. package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
  191. package/dist/src/sessions/adapters/factory.js +31 -27
  192. package/dist/src/sessions/adapters/generic.js +10 -10
  193. package/dist/src/sessions/adapters/grok-build.js +11 -11
  194. package/dist/src/sessions/adapters/grokbot.js +24 -13
  195. package/dist/src/sessions/adapters/hermes.js +27 -29
  196. package/dist/src/sessions/adapters/muse-workspace-scan.js +31 -11
  197. package/dist/src/sessions/adapters/muse.js +150 -93
  198. package/dist/src/sessions/adapters/omp.js +28 -14
  199. package/dist/src/sessions/adapters/openclaw.js +89 -79
  200. package/dist/src/sessions/adapters/opencode.js +27 -24
  201. package/dist/src/sessions/adapters/openhuman.js +18 -60
  202. package/dist/src/sessions/adapters/pi.js +29 -14
  203. package/dist/src/sessions/adapters/warp.js +3 -3
  204. package/dist/src/sessions/adapters/windsurf.js +19 -48
  205. package/dist/src/sessions/batch-contracts.js +16 -8
  206. package/dist/src/sessions/batch-import.js +51 -11
  207. package/dist/src/sessions/contracts.js +40 -2
  208. package/dist/src/sessions/coverage-preflight.js +1 -1
  209. package/dist/src/sessions/export-plan.js +4 -3
  210. package/dist/src/sessions/import-exclusions.js +72 -0
  211. package/dist/src/sessions/import-lease.js +34 -18
  212. package/dist/src/sessions/import-limits.js +37 -0
  213. package/dist/src/sessions/importer.js +60 -38
  214. package/dist/src/sessions/lifecycle.js +45 -0
  215. package/dist/src/sessions/policy.js +133 -25
  216. package/dist/src/sessions/readers.js +106 -53
  217. package/dist/src/sessions/refresh.js +106 -0
  218. package/dist/src/sessions/repository.js +147 -52
  219. package/dist/src/sessions/workspace-discovery.js +221 -56
  220. package/dist/src/sessions/workspace-matching.js +107 -0
  221. package/dist/src/skills/importer.js +1 -0
  222. package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
  223. package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
  224. package/dist/src/smiths/context-pipeline/finalization.js +6 -5
  225. package/dist/src/smiths/context-pipeline/generator.js +21 -4
  226. package/dist/src/smiths/context-pipeline/parallelism-section.js +7 -15
  227. package/dist/src/smiths/mcpsmith/generator.js +1 -1
  228. package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
  229. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +76 -18
  230. package/dist/src/storage/backends/fs.js +18 -76
  231. package/dist/src/storage/backends/obsidian.js +1 -0
  232. package/dist/src/tracker/forge-http.js +2 -1
  233. package/dist/src/update/checker.d.mts +2 -0
  234. package/dist/src/update/service.d.mts +22 -0
  235. package/dist/src/utils/contained-filesystem.d.mts +37 -0
  236. package/dist/src/utils/contained-filesystem.mjs +683 -0
  237. package/dist/src/utils/temporary-directory.js +36 -0
  238. package/dist/src/writing/example-generator.js +1 -1
  239. package/package.json +15 -2
  240. package/schemas/models/model-catalog.v1.schema.json +1 -1
  241. package/schemas/models/provider-model-capabilities.v1.schema.json +6 -0
  242. package/tools/_resolve-impl.mjs +13 -15
  243. package/tools/agents/deploy-agents.mjs +49 -21
  244. package/tools/agents/providers/base.mjs +104 -134
  245. package/tools/agents/providers/claude.mjs +8 -24
  246. package/tools/agents/providers/codex.mjs +18 -11
  247. package/tools/agents/providers/cursor.mjs +19 -18
  248. package/tools/agents/providers/grok-build.mjs +3 -1
  249. package/tools/agents/providers/hermes.mjs +57 -47
  250. package/tools/agents/providers/openclaw.mjs +9 -4
  251. package/tools/agents/providers/pi.mjs +5 -0
  252. package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
  253. package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
  254. package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
  255. package/tools/agents/providers/rule-delivery.mjs +1270 -0
  256. package/tools/agents/providers/warp.mjs +20 -26
  257. package/tools/cli/decision-offload-report.mjs +40 -0
  258. package/tools/cli/workspace-status.mjs +862 -0
  259. package/tools/plugin/package-plugins.mjs +186 -8
  260. package/tools/plugin/plugin-links.mjs +114 -0
  261. package/tools/providers/antigravity-transport.mjs +3 -1
  262. package/tools/providers/deepseek-harness-transport.mjs +6 -4
  263. package/tools/providers/omp-transport.mjs +4 -2
  264. package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
  265. package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
  266. package/tools/ralph-external/lib/omp-adapter.mjs +1 -1
  267. package/tools/ralph-external/lib/pi-adapter.mjs +0 -4
  268. package/tools/ralph-external/lib/provider-adapter.mjs +59 -1
  269. package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
  270. package/tools/ralph-external/lib/session-environment.mjs +28 -0
  271. package/tools/ralph-external/lib/systemd-client.mjs +49 -0
  272. package/tools/ralph-external/lib/worker-health.mjs +1 -1
  273. package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
  274. package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
  275. package/tools/ralph-external/process-monitor.mjs +1017 -0
  276. package/tools/ralph-external/session-launcher.mjs +5057 -0
  277. package/tools/scripts/resource-preflight.mjs +541 -0
  278. package/tools/skills/deploy-skills-codex.mjs +2 -1
  279. package/vscode-extension/schemas/aiwg.config.v1.json +1194 -231
@@ -1,7 +1,7 @@
1
1
  import { basename } from 'node:path';
2
2
  import { z } from 'zod';
3
- import { SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
4
- import { readBoundedJsonLines, streamBoundedJsonLines, } from '../readers.js';
3
+ import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
4
+ import { streamBoundedJsonLines, } from '../readers.js';
5
5
  export const DEVIN_DESKTOP_ADAPTER_VERSION = '1.1.0';
6
6
  export const DEVIN_DESKTOP_TRANSCRIPT_SCHEMA_VERSION = '1.0.0';
7
7
  /** @deprecated Compatibility export. */
@@ -38,19 +38,14 @@ export class DevinDesktopSessionAdapter {
38
38
  // Deliberately empty: hook enablement and transcript selection are explicit user actions.
39
39
  }
40
40
  async inspect(source) {
41
- const parsed = await this.readSource(source);
42
- return {
43
- sourceSchemaVersion: parsed.schemaVersion,
44
- consistency: 'provisional',
45
- operationalState: 'available',
46
- };
41
+ const records = this.stream(source);
42
+ let result = await records.next();
43
+ while (!result.done)
44
+ result = await records.next();
45
+ return result.value;
47
46
  }
48
47
  async *stream(source, cursor) {
49
- if (!isCurrentHookLocator(source.locatorClass)) {
50
- // Preserve the precise unsupported-operation diagnostics.
51
- await this.readSource(source);
52
- return;
53
- }
48
+ this.assertSupportedLocator(source);
54
49
  const start = parseCursor(cursor?.value);
55
50
  const input = await streamBoundedJsonLines({
56
51
  selectedPath: source.locator,
@@ -62,12 +57,12 @@ export class DevinDesktopSessionAdapter {
62
57
  for await (const line of input) {
63
58
  const parsed = StepSchema.safeParse(line.value);
64
59
  if (!parsed.success) {
65
- throw new SessionContractError('MALFORMED_SOURCE', 'Windsurf transcript step is malformed');
60
+ throw new SessionContractError('MALFORMED_SOURCE', 'Windsurf transcript step is malformed', schemaRejectionDetail(parsed.error));
66
61
  }
67
62
  const step = parsed.data;
68
63
  const currentVersion = step.schema_version ?? DEVIN_DESKTOP_TRANSCRIPT_SCHEMA_VERSION;
69
64
  if (schemaVersion && schemaVersion !== currentVersion) {
70
- throw new SessionContractError('SCHEMA_DRIFT', 'mixed Windsurf transcript schemas');
65
+ throw new SessionContractError('SCHEMA_DRIFT', 'mixed Windsurf transcript schemas', schemaIssueDetail('schema_version'));
71
66
  }
72
67
  schemaVersion = currentVersion;
73
68
  assertSupportedSchemaMajor(schemaVersion);
@@ -75,7 +70,7 @@ export class DevinDesktopSessionAdapter {
75
70
  ?? nativeSessionId
76
71
  ?? basename(source.locator, '.jsonl');
77
72
  if (step.trajectory_id && nativeSessionId && step.trajectory_id !== nativeSessionId) {
78
- throw new SessionContractError('SCHEMA_DRIFT', 'mixed Windsurf trajectory identities');
73
+ throw new SessionContractError('SCHEMA_DRIFT', 'mixed Windsurf trajectory identities', schemaIssueDetail('trajectory_id'));
79
74
  }
80
75
  nativeSessionId = currentSession;
81
76
  if (seen++ < start)
@@ -83,45 +78,21 @@ export class DevinDesktopSessionAdapter {
83
78
  yield normalizeStep(step, currentSession, line.sequence, line.byteOffset, canonicalLocatorClass(source.locatorClass), schemaVersion);
84
79
  }
85
80
  if (seen === 0) {
86
- throw new SessionContractError('MALFORMED_SOURCE', 'Windsurf transcript is empty or malformed');
81
+ throw new SessionContractError('MALFORMED_SOURCE', 'Windsurf transcript is empty or malformed', schemaIssueDetail('<root>'));
87
82
  }
83
+ return {
84
+ sourceSchemaVersion: schemaVersion,
85
+ consistency: 'provisional',
86
+ operationalState: 'available',
87
+ };
88
88
  }
89
- async readSource(source) {
89
+ assertSupportedLocator(source) {
90
90
  if (isLegacyLocator(source.locatorClass)) {
91
91
  throw new SessionContractError('UNSUPPORTED_OPERATION', 'legacy Devin Desktop/Windsurf protobuf stores are unsupported; enable post_cascade_response_with_transcript and select its JSONL output');
92
92
  }
93
93
  if (!isCurrentHookLocator(source.locatorClass)) {
94
94
  throw new SessionContractError('UNSUPPORTED_OPERATION', 'Devin Desktop (Windsurf compatibility) requires an explicitly selected post_cascade_response_with_transcript JSONL file');
95
95
  }
96
- const input = await readBoundedJsonLines({
97
- selectedPath: source.locator,
98
- allowedRoots: source.authorizedScope.allowedRoots,
99
- }, { consistency: 'provisional', limits: this.limits });
100
- if (input.records.length === 0) {
101
- throw new SessionContractError('MALFORMED_SOURCE', 'Windsurf transcript is empty or malformed');
102
- }
103
- const steps = input.records.map((record) => {
104
- const parsed = StepSchema.safeParse(record.value);
105
- if (!parsed.success) {
106
- throw new SessionContractError('MALFORMED_SOURCE', 'Windsurf transcript step is malformed');
107
- }
108
- return { ...record, value: parsed.data };
109
- });
110
- const versions = new Set(steps.map(({ value }) => value.schema_version ?? DEVIN_DESKTOP_TRANSCRIPT_SCHEMA_VERSION));
111
- if (versions.size !== 1) {
112
- throw new SessionContractError('SCHEMA_DRIFT', 'mixed Windsurf transcript schemas');
113
- }
114
- const schemaVersion = [...versions][0];
115
- assertSupportedSchemaMajor(schemaVersion);
116
- const trajectoryIds = new Set(steps.flatMap(({ value }) => value.trajectory_id ? [value.trajectory_id] : []));
117
- if (trajectoryIds.size > 1) {
118
- throw new SessionContractError('SCHEMA_DRIFT', 'mixed Windsurf trajectory identities');
119
- }
120
- const nativeSessionId = [...trajectoryIds][0] ?? basename(source.locator, '.jsonl');
121
- return {
122
- schemaVersion,
123
- records: steps.map(({ value, sequence, byteOffset }) => normalizeStep(value, nativeSessionId, sequence, byteOffset, canonicalLocatorClass(source.locatorClass), schemaVersion)),
124
- };
125
96
  }
126
97
  }
127
98
  /** @deprecated Use DevinDesktopSessionAdapter; retained through the alias window. */
@@ -206,7 +177,7 @@ function parseCursor(value) {
206
177
  if (!value)
207
178
  return 0;
208
179
  if (!/^\d+$/.test(value))
209
- throw new SessionContractError('SCHEMA_DRIFT', 'invalid Windsurf cursor');
180
+ throw new SessionContractError('SCHEMA_DRIFT', 'invalid Windsurf cursor', schemaIssueDetail('cursor'));
210
181
  return Number(value);
211
182
  }
212
183
  //# sourceMappingURL=windsurf.js.map
@@ -1,6 +1,6 @@
1
1
  import { reconcileCoveragePreflight } from './coverage-preflight.js';
2
- export const BATCH_IMPORT_VERSION = '1.0.0';
3
- export const COVERAGE_VERSION = '1.0.0';
2
+ export const BATCH_IMPORT_VERSION = '2.0.0';
3
+ export const COVERAGE_VERSION = '2.0.0';
4
4
  export function coverageFromBatchRun(run, now = new Date(), staleAfterMs = 24 * 60 * 60 * 1_000) {
5
5
  if (!run)
6
6
  return unknownCoverage();
@@ -9,6 +9,7 @@ export function coverageFromBatchRun(run, now = new Date(), staleAfterMs = 24 *
9
9
  ]);
10
10
  const accepted = run.sources.filter((source) => source.status === 'committed').length;
11
11
  const rejected = run.sources.filter((source) => source.status === 'rejected').length;
12
+ const excluded = run.sources.filter(source => source.status === 'excluded').length;
12
13
  const skipped = run.sources.filter((source) => source.status === 'skipped').length;
13
14
  const duplicated = run.sources.filter((source) => source.status === 'duplicate').length;
14
15
  const previouslyCommitted = run.sources.filter((source) => source.status === 'previously-committed').length;
@@ -20,9 +21,12 @@ export function coverageFromBatchRun(run, now = new Date(), staleAfterMs = 24 *
20
21
  const manifestAgeMs = Math.max(0, now.getTime() - Date.parse(run.manifestCreatedAt));
21
22
  const isStale = manifestAgeMs > staleAfterMs;
22
23
  const preflight = run.preflight ? reconcileCoveragePreflight(run.preflight, run.sources) : undefined;
23
- const incomplete = !preflight || preflight.status !== 'complete'
24
- || unavailable.length > 0 || accepted + duplicated + previouslyCommitted === 0
25
- || rejected > 0 || pending > 0 || skipped > 0
24
+ const unresolvedProviders = preflight?.unresolvedProviders
25
+ ?? [...new Set([...unavailable, ...exportRequired, ...notChecked])].sort();
26
+ const acquisitionIncomplete = rejected > 0 || pending > 0 || skipped > 0
27
+ || (preflight?.expectedProviderBasis === 'explicit' && unresolvedProviders.length > 0);
28
+ const incomplete = acquisitionIncomplete || !preflight || preflight.status !== 'complete'
29
+ || unavailable.length > 0 || accepted + duplicated + previouslyCommitted + excluded === 0
26
30
  || exportRequired.length > 0 || notChecked.length > 0;
27
31
  const rejectionCounts = {};
28
32
  for (const source of run.sources) {
@@ -54,7 +58,8 @@ export function coverageFromBatchRun(run, now = new Date(), staleAfterMs = 24 *
54
58
  return {
55
59
  schemaVersion: COVERAGE_VERSION,
56
60
  status: isStale ? 'stale' : incomplete ? 'partial' : 'complete',
57
- acquisitionStatus: incomplete ? 'partial' : 'complete',
61
+ acquisitionStatus: acquisitionIncomplete ? 'partial' : 'complete',
62
+ unresolvedProviders,
58
63
  preflight,
59
64
  semanticReview: 'not-assessed',
60
65
  workspaceId: run.workspaceId,
@@ -67,6 +72,7 @@ export function coverageFromBatchRun(run, now = new Date(), staleAfterMs = 24 *
67
72
  discovered: run.sources.length,
68
73
  accepted,
69
74
  rejected,
75
+ excluded,
70
76
  skipped,
71
77
  duplicated,
72
78
  previouslyCommitted,
@@ -74,9 +80,9 @@ export function coverageFromBatchRun(run, now = new Date(), staleAfterMs = 24 *
74
80
  },
75
81
  sessionsAccepted: run.sources.reduce((sum, source) => sum + source.sessionsAccepted, 0),
76
82
  eventsAccepted: run.sources.reduce((sum, source) => sum + source.eventsAccepted, 0),
77
- coverageRatio: run.sources.length === 0
83
+ coverageRatio: run.sources.length === excluded
78
84
  ? null
79
- : (accepted + duplicated + previouslyCommitted) / run.sources.length,
85
+ : (accepted + duplicated + previouslyCommitted) / (run.sources.length - excluded),
80
86
  rejectionCounts,
81
87
  sourceDateRange: {
82
88
  earliest: sourceTimestamps.at(0) ?? null,
@@ -100,6 +106,7 @@ function unknownCoverage() {
100
106
  schemaVersion: COVERAGE_VERSION,
101
107
  status: 'unknown',
102
108
  acquisitionStatus: 'unknown',
109
+ unresolvedProviders: [],
103
110
  semanticReview: 'not-assessed',
104
111
  workspaceId: '',
105
112
  manifestId: null,
@@ -116,6 +123,7 @@ function unknownCoverage() {
116
123
  discovered: 0,
117
124
  accepted: 0,
118
125
  rejected: 0,
126
+ excluded: 0,
119
127
  skipped: 0,
120
128
  duplicated: 0,
121
129
  previouslyCommitted: 0,
@@ -1,11 +1,17 @@
1
1
  import { stat } from 'node:fs/promises';
2
2
  import { createSessionAdapterRegistry } from './adapter-registry.js';
3
3
  import { coveragePreflight, sessionRuntimeIdentity } from './coverage-preflight.js';
4
- import { SESSION_CONTRACT_VERSION, SessionContractError, SessionSourceSchema, sha256, } from './contracts.js';
4
+ import { SESSION_CONTRACT_VERSION, SessionContractError, schemaIssueDetail, SessionSourceSchema, sha256, } from './contracts.js';
5
5
  import { BATCH_IMPORT_VERSION, coverageFromBatchRun, } from './batch-contracts.js';
6
6
  import { IncrementalSessionImporter, SessionImportFailure } from './importer.js';
7
+ import { matchImportExclusion, resolveImportExclusions } from './import-exclusions.js';
8
+ import { resolveImportLimits } from './import-limits.js';
7
9
  import { fingerprintSourceFile } from './readers.js';
8
10
  export async function importDiscoveryManifest(options) {
11
+ const exclusions = resolveImportExclusions(undefined, options.exclude);
12
+ const limits = { ...resolveImportLimits(undefined, {
13
+ maxRecordBytes: options.limits?.maxRecordBytes, maxSourceBytes: options.limits?.maxTotalBytes,
14
+ }), ...options.limits };
9
15
  const now = options.now ?? (() => new Date());
10
16
  const runId = sha256([
11
17
  'workspace-import-v1',
@@ -17,6 +23,7 @@ export async function importDiscoveryManifest(options) {
17
23
  if (run.runId !== runId) {
18
24
  throw new SessionContractError('IMPORT_CONFLICT', 'discovery manifest is already associated with a different batch run');
19
25
  }
26
+ run.schemaVersion = BATCH_IMPORT_VERSION;
20
27
  run.preflight = coveragePreflight({
21
28
  expectedProviders: options.manifest.preflight?.expectedProviders,
22
29
  expectedProviderBasis: options.manifest.preflight?.expectedProviderBasis ?? 'legacy',
@@ -33,6 +40,12 @@ export async function importDiscoveryManifest(options) {
33
40
  if (!disposition) {
34
41
  throw new SessionContractError('IMPORT_CONFLICT', `batch run is missing discovered source ${manifestSource.sourceId}`);
35
42
  }
43
+ const exclusion = matchImportExclusion(manifestSource, exclusions) ?? manifestSource.exclusion;
44
+ if (exclusion) {
45
+ excludeSource(disposition, exclusion, now());
46
+ continue;
47
+ }
48
+ delete disposition.exclusion;
36
49
  if (isAccepted(disposition.status)) {
37
50
  disposition.status = 'previously-committed';
38
51
  disposition.updatedAt = now().toISOString();
@@ -48,6 +61,7 @@ export async function importDiscoveryManifest(options) {
48
61
  disposition.attempts += 1;
49
62
  disposition.errorCode = null;
50
63
  disposition.diagnostic = null;
64
+ disposition.detail = null;
51
65
  disposition.updatedAt = now().toISOString();
52
66
  persistProgress(options.repository, run, now());
53
67
  try {
@@ -62,7 +76,7 @@ export async function importDiscoveryManifest(options) {
62
76
  allowedRoots: [manifestSource.authorizedRoot],
63
77
  },
64
78
  };
65
- const adapter = adapterFor(manifestSource.provider);
79
+ const adapter = adapterFor(manifestSource.provider, limits);
66
80
  const source = await sessionSource(selectedSource, adapter);
67
81
  const receipts = await new IncrementalSessionImporter(options.repository).import({
68
82
  source,
@@ -74,6 +88,7 @@ export async function importDiscoveryManifest(options) {
74
88
  publish: false,
75
89
  signal: options.signal,
76
90
  inactivityThresholdMs: options.inactivityThresholdMs,
91
+ limits,
77
92
  });
78
93
  await assertManifestSourceUnchanged(manifestSource);
79
94
  const totals = options.repository.sourceImportTotals(manifestSource.sourceId, run.runId);
@@ -89,10 +104,12 @@ export async function importDiscoveryManifest(options) {
89
104
  catch (error) {
90
105
  disposition.status = 'rejected';
91
106
  disposition.errorCode = importErrorCode(error);
107
+ disposition.detail = error instanceof SessionContractError ? error.detail ?? null : null;
92
108
  disposition.diagnostic = [
93
109
  `provider=${manifestSource.provider}`,
94
110
  `source=${manifestSource.sourceId}`,
95
111
  `code=${disposition.errorCode}`,
112
+ ...(disposition.detail ? [`detail=${JSON.stringify(disposition.detail)}`] : []),
96
113
  ].join(' ');
97
114
  }
98
115
  disposition.updatedAt = now().toISOString();
@@ -101,14 +118,14 @@ export async function importDiscoveryManifest(options) {
101
118
  }
102
119
  const rejected = run.sources.some((source) => source.status === 'rejected');
103
120
  const pending = run.sources.some((source) => source.status === 'pending' || source.status === 'running');
104
- const providerGap = coverageFromBatchRun(run, now()).acquisitionStatus !== 'complete';
121
+ const acquisitionIncomplete = coverageFromBatchRun(run, now()).acquisitionStatus !== 'complete';
105
122
  const publishable = run.sources
106
123
  .filter((source) => isAccepted(source.status))
107
124
  .map((source) => source.sourceId);
108
125
  injectFault(options, run, 'before-publication');
109
126
  options.repository.commitStagedBatch(run.runId, publishable);
110
127
  injectFault(options, run, 'after-publication');
111
- run.status = pending ? 'interrupted' : rejected || providerGap ? 'partial' : 'complete';
128
+ run.status = pending ? 'interrupted' : rejected || acquisitionIncomplete ? 'partial' : 'complete';
112
129
  run.updatedAt = now().toISOString();
113
130
  run.completedAt = pending ? null : run.updatedAt;
114
131
  options.repository.saveBatchImportRun(run);
@@ -128,10 +145,20 @@ function injectFault(options, run, boundary, sourceId) {
128
145
  throw error;
129
146
  }
130
147
  }
131
- export function previewDiscoveryImport(manifest, existing, now = new Date()) {
148
+ export function previewDiscoveryImport(manifest, existing, now = new Date(), exclude = []) {
132
149
  const run = existing ?? newBatchRun(manifest, sha256(['workspace-import-v1', manifest.manifestId, manifest.workspaceId].join('\0')), now);
150
+ const exclusions = resolveImportExclusions(undefined, exclude);
133
151
  return receiptFor({
134
152
  ...run,
153
+ sources: run.sources.map(source => {
154
+ const manifestSource = manifest.sources.find(candidate => candidate.sourceId === source.sourceId);
155
+ const exclusion = matchImportExclusion(manifestSource, exclusions) ?? manifestSource.exclusion;
156
+ if (!exclusion)
157
+ return source;
158
+ const disposition = { ...source };
159
+ excludeSource(disposition, exclusion, now);
160
+ return disposition;
161
+ }),
135
162
  preflight: coveragePreflight({
136
163
  expectedProviders: manifest.preflight?.expectedProviders,
137
164
  expectedProviderBasis: manifest.preflight?.expectedProviderBasis ?? 'legacy',
@@ -157,7 +184,8 @@ function newBatchRun(manifest, runId, now) {
157
184
  sources: manifest.sources.map((source) => ({
158
185
  sourceId: source.sourceId,
159
186
  provider: source.provider,
160
- status: 'pending',
187
+ status: source.status ?? 'pending',
188
+ ...(source.exclusion ? { exclusion: source.exclusion } : {}),
161
189
  attempts: 0,
162
190
  sessionsAccepted: 0,
163
191
  eventsAccepted: 0,
@@ -173,10 +201,12 @@ function receiptFor(run, now) {
173
201
  schemaVersion: BATCH_IMPORT_VERSION,
174
202
  run,
175
203
  coverage,
204
+ interruptedRuns: [],
176
205
  totals: {
177
206
  discovered: coverage.sources.discovered,
178
207
  accepted: coverage.sources.accepted,
179
208
  rejected: coverage.sources.rejected,
209
+ excluded: coverage.sources.excluded,
180
210
  skipped: coverage.sources.skipped,
181
211
  duplicated: coverage.sources.duplicated,
182
212
  previouslyCommitted: coverage.sources.previouslyCommitted,
@@ -186,6 +216,16 @@ function receiptFor(run, now) {
186
216
  },
187
217
  };
188
218
  }
219
+ function excludeSource(source, exclusion, now) {
220
+ source.status = 'excluded';
221
+ source.exclusion = exclusion;
222
+ source.errorCode = null;
223
+ source.diagnostic = null;
224
+ source.detail = null;
225
+ source.sessionsAccepted = 0;
226
+ source.eventsAccepted = 0;
227
+ source.updatedAt = now.toISOString();
228
+ }
189
229
  function persistProgress(repository, run, now) {
190
230
  run.updatedAt = now.toISOString();
191
231
  repository.saveBatchImportRun(run);
@@ -196,21 +236,21 @@ async function assertManifestSourceUnchanged(source) {
196
236
  details = await stat(source.locator);
197
237
  }
198
238
  catch {
199
- throw new SessionContractError('SCHEMA_DRIFT', 'discovered source is no longer available; run discovery again');
239
+ throw new SessionContractError('SCHEMA_DRIFT', 'discovered source is no longer available; run discovery again', schemaIssueDetail('locator'));
200
240
  }
201
241
  if (details.size !== source.sizeBytes || details.mtime.toISOString() !== source.modifiedAt) {
202
- throw new SessionContractError('SCHEMA_DRIFT', 'discovered source changed after manifest creation; run discovery again');
242
+ throw new SessionContractError('SCHEMA_DRIFT', 'discovered source changed after manifest creation; run discovery again', schemaIssueDetail(details.size !== source.sizeBytes ? 'sizeBytes' : 'modifiedAt'));
203
243
  }
204
244
  const fingerprint = await fingerprintSourceFile({
205
245
  selectedPath: source.locator,
206
246
  allowedRoots: [source.authorizedRoot],
207
247
  });
208
248
  if (fingerprint.digest !== source.digest || fingerprint.size !== source.sizeBytes) {
209
- throw new SessionContractError('SCHEMA_DRIFT', 'discovered source content changed after manifest creation; run discovery again');
249
+ throw new SessionContractError('SCHEMA_DRIFT', 'discovered source content changed after manifest creation; run discovery again', schemaIssueDetail('digest'));
210
250
  }
211
251
  }
212
- function adapterFor(provider) {
213
- return createSessionAdapterRegistry().get(provider);
252
+ function adapterFor(provider, limits) {
253
+ return createSessionAdapterRegistry(limits).get(provider);
214
254
  }
215
255
  async function sessionSource(selected, adapter) {
216
256
  const probe = await adapter.inspect(selected);
@@ -1,5 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { z } from 'zod';
3
+ import { redactSessionText, redactSessionValue } from './policy.js';
3
4
  export const SESSION_CONTRACT_VERSION = '1.0.0';
4
5
  export const SESSION_PROVIDER_IDS = [
5
6
  'claude', 'codex', 'copilot', 'cursor', 'factory', 'hermes',
@@ -362,11 +363,48 @@ export function sha256(value) {
362
363
  function stableId(prefix, ...parts) {
363
364
  return `${prefix}_${createHash('sha256').update(parts.join('\0')).digest('hex')}`;
364
365
  }
366
+ export const SessionRejectionDetailSchema = z.union([
367
+ z.object({ limit: z.string(), configured: z.number(), observed: z.number(),
368
+ setting: z.string().optional(), origin: z.enum(['flag', 'env', 'config', 'default']).optional() }),
369
+ z.object({ issues: z.array(z.object({ path: z.string(), code: z.string() })) }),
370
+ ]);
371
+ export function schemaIssueDetail(path, code = 'custom') {
372
+ return { issues: [{ path, code }] };
373
+ }
374
+ export function assertSessionResourceLimit(limit, configured, observed) {
375
+ if (observed > configured) {
376
+ throw new SessionContractError('RESOURCE_LIMIT_EXCEEDED', 'session resource limit exceeded', {
377
+ limit, configured, observed,
378
+ });
379
+ }
380
+ }
381
+ /** Extract schema locations and validator codes without messages or input values. */
382
+ export function schemaRejectionDetail(error) {
383
+ const issues = [];
384
+ const visit = (entries) => {
385
+ for (const issue of entries) {
386
+ if (issues.length >= 20)
387
+ return;
388
+ if (issue.code === 'invalid_union') {
389
+ for (const branch of issue.unionErrors)
390
+ visit(branch.issues);
391
+ }
392
+ else {
393
+ issues.push({ path: issue.path.join('.') || '<root>', code: issue.code });
394
+ }
395
+ }
396
+ };
397
+ visit(error.issues);
398
+ return redactSessionValue({ issues }).value;
399
+ }
365
400
  export class SessionContractError extends Error {
366
401
  code;
367
- constructor(code, message) {
368
- super(message);
402
+ detail;
403
+ constructor(code, message, detail) {
404
+ super(redactSessionText(message).text);
369
405
  this.code = code;
406
+ this.detail = detail;
407
+ this.detail = redactSessionValue(detail).value;
370
408
  this.name = 'SessionContractError';
371
409
  }
372
410
  }
@@ -114,7 +114,7 @@ export function reconcileCoveragePreflight(preflight, sources) {
114
114
  return entry;
115
115
  const selected = sources.filter((source) => source.provider === entry.provider);
116
116
  const imported = selected.length === entry.sourceCount && selected.length > 0
117
- && selected.every((source) => accepted.has(source.status) && source.eventsAccepted > 0);
117
+ && selected.every((source) => source.status === 'excluded' || (accepted.has(source.status) && source.eventsAccepted > 0));
118
118
  return {
119
119
  ...entry,
120
120
  disposition: !imported ? 'import-incomplete'
@@ -13,6 +13,7 @@ import { SessionContractError } from './contracts.js';
13
13
  import { buildSessionAiwgFortemiIndexExport, SESSION_EXPORT_INDEX_SCHEMA_VERSION, } from './fortemi-export-mapping.js';
14
14
  import { discoverSessionOutputCandidates } from './output-lineage.js';
15
15
  import { FilesystemDerivedOutputIndex } from './output-registration.js';
16
+ import { redactSessionValue } from './policy.js';
16
17
  export const SESSION_EXPORT_PLAN_SCHEMA_VERSION = '1.1.0';
17
18
  function eventDigestSummary(events) {
18
19
  const hash = createHash('sha256');
@@ -43,7 +44,7 @@ function localEventAttachment(event, projectRoot) {
43
44
  && value.dataBytes.every((item) => Number.isInteger(item) && Number(item) >= 0 && Number(item) <= 255)) {
44
45
  return { filename, mediaType, bytes: Uint8Array.from(value.dataBytes) };
45
46
  }
46
- if (typeof value.dataUrl === 'string') {
47
+ if (typeof value.dataUrl === 'string' && !value.dataUrl.startsWith('[REDACTED:')) {
47
48
  const match = /^data:([^;,]*)(;base64)?,(.*)$/s.exec(value.dataUrl);
48
49
  if (!match)
49
50
  throw new SessionContractError('MALFORMED_SOURCE', `invalid data URL attachment: ${event.eventId}`);
@@ -52,7 +53,7 @@ function localEventAttachment(event, projectRoot) {
52
53
  : Buffer.from(decodeURIComponent(match[3]), 'utf8');
53
54
  return { filename, mediaType: match[1] || mediaType, bytes };
54
55
  }
55
- if (typeof value.fileUrl === 'string') {
56
+ if (typeof value.fileUrl === 'string' && !value.fileUrl.startsWith('[REDACTED:')) {
56
57
  if (!projectRoot)
57
58
  throw new SessionContractError('SOURCE_NOT_AUTHORIZED', 'project root is required for file attachments');
58
59
  const root = realpathSync(projectRoot);
@@ -157,7 +158,7 @@ export function buildSessionExportPlan(repository, options) {
157
158
  sampleRecordIds: index.items.slice(0, sampleSize).map((item) => item.id),
158
159
  },
159
160
  };
160
- return { plan, sessions, eventsBySessionId };
161
+ return { plan: redactSessionValue(plan).value, sessions, eventsBySessionId };
161
162
  }
162
163
  /**
163
164
  * Re-selects the plan's sessions from the repository and compares digests
@@ -0,0 +1,72 @@
1
+ import { homedir } from 'node:os';
2
+ import { basename, dirname, extname, isAbsolute } from 'node:path';
3
+ import { SessionContractError } from './contracts.js';
4
+ import { grokbotConversationIdFromLocator } from './adapters/grokbot-locator.js';
5
+ export function validateImportExclusions(value) {
6
+ if (!Array.isArray(value) || !value.every(entry => typeof entry === 'string' && entry.trim().length > 0)) {
7
+ throw new SessionContractError('INVALID_ARGUMENT', 'sessions.import.exclude must be an array of non-empty strings');
8
+ }
9
+ for (const entry of value) {
10
+ if (!isAbsolute(entry) && entry !== '~' && !entry.startsWith('~/') && /[/*?\\~]/.test(entry)) {
11
+ throw new SessionContractError('INVALID_ARGUMENT', 'sessions.import.exclude path globs must be absolute or ~/ prefixed');
12
+ }
13
+ }
14
+ }
15
+ export function resolveImportExclusions(config, flags = [], env = process.env) {
16
+ const configured = config?.exclude === undefined ? [] : config.exclude;
17
+ validateImportExclusions(configured);
18
+ const entries = [...configured, ...(env.AIWG_SESSIONS_IMPORT_EXCLUDE === undefined
19
+ ? [] : env.AIWG_SESSIONS_IMPORT_EXCLUDE.split(',').map(entry => entry.trim())), ...flags];
20
+ validateImportExclusions(entries);
21
+ return [...new Set(entries)];
22
+ }
23
+ /** Use only discovery metadata and locator names; never inspect source content. */
24
+ export function matchImportExclusion(source, entries) {
25
+ const ids = [source.nativeSessionId, nativeSessionIdFromLocator(source)];
26
+ for (const entry of entries) {
27
+ if (isAbsolute(entry) || entry === '~' || entry.startsWith('~/')) {
28
+ const pattern = entry.startsWith('~') ? homedir() + entry.slice(1) : entry;
29
+ if (globExpression(pattern).test(source.locator))
30
+ return { entry, kind: 'path-glob' };
31
+ }
32
+ else if (ids.includes(entry))
33
+ return { entry, kind: 'session-id' };
34
+ }
35
+ return undefined;
36
+ }
37
+ export function nativeSessionIdFromLocator(source) {
38
+ if (source.provider === 'grokbot')
39
+ return grokbotConversationIdFromLocator(source.locator) ?? undefined;
40
+ if (source.provider === 'muse')
41
+ return basename(dirname(source.locator));
42
+ const name = basename(source.locator, extname(source.locator));
43
+ if (source.provider === 'codex' || source.provider === 'pi') {
44
+ return /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i.exec(name)?.[1] ?? name;
45
+ }
46
+ return name;
47
+ }
48
+ function globExpression(pattern) {
49
+ let expression = '^';
50
+ for (let index = 0; index < pattern.length; index++) {
51
+ const character = pattern[index];
52
+ if (character === '*') {
53
+ if (pattern[index + 1] === '*') {
54
+ index++;
55
+ if (pattern[index + 1] === '/') {
56
+ expression += '(?:.*/)?';
57
+ index++;
58
+ }
59
+ else
60
+ expression += '.*';
61
+ }
62
+ else
63
+ expression += '[^/]*';
64
+ }
65
+ else if (character === '?')
66
+ expression += '[^/]';
67
+ else
68
+ expression += character.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
69
+ }
70
+ return new RegExp(expression + '$');
71
+ }
72
+ //# sourceMappingURL=import-exclusions.js.map