@aiwg/cli 2026.7.25 → 2026.8.1

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 (79) hide show
  1. package/README.md +33 -0
  2. package/agentic/code/providers/capability-matrix.yaml +511 -0
  3. package/agentic/code/providers/model-capabilities.v1.json +120 -0
  4. package/agentic/code/providers/model-catalog.v1.json +96 -0
  5. package/agentic/code/providers/model-policy-evaluations.v1.json +50 -0
  6. package/agentic/code/providers/premium-model-allowlist.v1.json +36 -0
  7. package/bin/aiwg.mjs +14 -10
  8. package/dist/src/api/index.d.ts +1 -0
  9. package/dist/src/api/index.js +1 -0
  10. package/dist/src/artifacts/cli.js +55 -10
  11. package/dist/src/artifacts/fortemi-shard-export.js +107 -18
  12. package/dist/src/artifacts/types.js +4 -0
  13. package/dist/src/auth/client.js +209 -0
  14. package/dist/src/auth/config.js +38 -0
  15. package/dist/src/auth/credential-store.js +141 -0
  16. package/dist/src/auth/resource-credentials.js +25 -0
  17. package/dist/src/auth/types.js +2 -0
  18. package/dist/src/channel/manager.mjs +5 -5
  19. package/dist/src/cli/handlers/auth.js +125 -0
  20. package/dist/src/cli/handlers/help.js +1 -0
  21. package/dist/src/cli/handlers/index.js +6 -2
  22. package/dist/src/cli/handlers/job.js +97 -0
  23. package/dist/src/cli/handlers/resource-versions.js +2 -0
  24. package/dist/src/cli/handlers/runtime-info.js +2 -2
  25. package/dist/src/cli/handlers/serve.js +2 -2
  26. package/dist/src/cli/handlers/sessions.js +211 -5
  27. package/dist/src/cli/handlers/steward.js +16 -3
  28. package/dist/src/cli/handlers/subcommands.js +10 -1
  29. package/dist/src/cli/handlers/use.js +342 -43
  30. package/dist/src/config/gitignore.js +1 -0
  31. package/dist/src/extensions/commands/definitions.js +49 -5
  32. package/dist/src/extensions/manifest.js +1 -0
  33. package/dist/src/features/catalog.js +3 -3
  34. package/dist/src/jobs/executor.js +83 -0
  35. package/dist/src/jobs/flow.js +106 -0
  36. package/dist/src/jobs/gitea.js +91 -0
  37. package/dist/src/jobs/render.js +53 -0
  38. package/dist/src/jobs/runner.js +315 -0
  39. package/dist/src/jobs/types.js +3 -0
  40. package/dist/src/memory/canonical-context.js +342 -0
  41. package/dist/src/memory/context-pack.js +282 -0
  42. package/dist/src/memory/index.js +4 -0
  43. package/dist/src/memory/intake.js +118 -0
  44. package/dist/src/providers/capability-matrix.js +11 -4
  45. package/dist/src/providers/capability-matrix.yaml +39 -42
  46. package/dist/src/resources/resolver.js +1 -0
  47. package/dist/src/resources/web-release.d.ts +3 -1
  48. package/dist/src/resources/web-release.js +14 -6
  49. package/dist/src/serve/agentic-sandbox-fleet-client.js +213 -0
  50. package/dist/src/serve/fleet-mission-conductor.js +293 -0
  51. package/dist/src/sessions/analytics.js +303 -0
  52. package/dist/src/sessions/importer.js +7 -1
  53. package/dist/src/sessions/index.js +2 -0
  54. package/dist/src/sessions/output-registration.js +338 -0
  55. package/dist/src/sessions/policy.js +1 -1
  56. package/dist/src/sessions/promotion.js +73 -2
  57. package/dist/src/sessions/repository.js +215 -1
  58. package/dist/src/update/notifier.mjs +13 -2
  59. package/package.json +17 -10
  60. package/tools/_resolve-impl.mjs +74 -0
  61. package/tools/agents/deploy-agents.mjs +962 -0
  62. package/tools/agents/providers/base.mjs +2954 -0
  63. package/tools/agents/providers/claude.mjs +711 -0
  64. package/tools/agents/providers/codex.mjs +699 -0
  65. package/tools/agents/providers/copilot.mjs +659 -0
  66. package/tools/agents/providers/cursor.mjs +714 -0
  67. package/tools/agents/providers/factory.mjs +1130 -0
  68. package/tools/agents/providers/hermes.mjs +663 -0
  69. package/tools/agents/providers/hook-capabilities.mjs +85 -0
  70. package/tools/agents/providers/model-role.mjs +56 -0
  71. package/tools/agents/providers/openclaw-translator.mjs +348 -0
  72. package/tools/agents/providers/openclaw.mjs +680 -0
  73. package/tools/agents/providers/opencode.mjs +675 -0
  74. package/tools/agents/providers/openhuman.mjs +292 -0
  75. package/tools/agents/providers/warp.mjs +413 -0
  76. package/tools/agents/providers/windsurf.mjs +748 -0
  77. package/tools/commands/deploy-prompts-codex.mjs +336 -0
  78. package/tools/plugin/package-plugins.mjs +1013 -0
  79. package/tools/skills/deploy-skills-codex.mjs +571 -0
@@ -0,0 +1,118 @@
1
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, writeFileSync, } from 'node:fs';
2
+ import { createHash } from 'node:crypto';
3
+ import { basename, dirname, extname, relative, resolve, sep } from 'node:path';
4
+ function sha256(value) {
5
+ return `sha256:${createHash('sha256').update(value).digest('hex')}`;
6
+ }
7
+ function safeProjectFile(projectRoot, requested) {
8
+ const root = realpathSync(projectRoot);
9
+ const candidate = realpathSync(resolve(root, requested));
10
+ if (candidate !== root && !candidate.startsWith(`${root}${sep}`)) {
11
+ throw new Error('intake source must resolve inside the project');
12
+ }
13
+ const segments = relative(root, candidate).split(sep);
14
+ if (segments.some(segment => segment === '.env' || segment === '.ssh'
15
+ || /^(?:credentials?|secrets?|tokens?)(?:\.|$)/i.test(segment))) {
16
+ throw new Error('protected paths cannot be ingested into ordinary project memory');
17
+ }
18
+ return { absolute: candidate, locator: segments.join('/') };
19
+ }
20
+ function kindFor(filePath) {
21
+ const extension = extname(filePath).toLocaleLowerCase();
22
+ if (['.jsonl', '.transcript'].includes(extension))
23
+ return 'session-transcript';
24
+ if (['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'].includes(extension))
25
+ return 'image';
26
+ if (extension === '.pdf')
27
+ return 'pdf';
28
+ if (['.yaml', '.yml', '.json'].includes(extension))
29
+ return 'structured';
30
+ if (['.md', '.txt', '.html', '.htm'].includes(extension))
31
+ return 'document';
32
+ return 'artifact';
33
+ }
34
+ function assertFuturePathInsideProject(projectRoot, target) {
35
+ let ancestor = target;
36
+ while (!existsSync(ancestor))
37
+ ancestor = dirname(ancestor);
38
+ const actual = realpathSync(ancestor);
39
+ if (actual !== projectRoot && !actual.startsWith(`${projectRoot}${sep}`)) {
40
+ throw new Error('intake storage cannot traverse a link outside the project');
41
+ }
42
+ }
43
+ function atomicJson(filePath, value) {
44
+ mkdirSync(dirname(filePath), { recursive: true });
45
+ const temporary = `${filePath}.${process.pid}.${Date.now()}.tmp`;
46
+ writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
47
+ renameSync(temporary, filePath);
48
+ }
49
+ export class MemoryIntakeCoordinator {
50
+ projectRoot;
51
+ rawRoot;
52
+ receiptRoot;
53
+ constructor(projectRoot) {
54
+ this.projectRoot = realpathSync(projectRoot);
55
+ this.rawRoot = resolve(this.projectRoot, '.aiwg/wiki/raw');
56
+ this.receiptRoot = resolve(this.projectRoot, '.aiwg/memory/compound-memory/intake-receipts');
57
+ assertFuturePathInsideProject(this.projectRoot, this.rawRoot);
58
+ assertFuturePathInsideProject(this.projectRoot, this.receiptRoot);
59
+ }
60
+ preview(requested) {
61
+ const source = safeProjectFile(this.projectRoot, requested);
62
+ const stat = statSync(source.absolute);
63
+ if (!stat.isFile())
64
+ throw new Error('intake source must be a regular file');
65
+ const bytes = readFileSync(source.absolute);
66
+ const digest = sha256(bytes);
67
+ const kind = kindFor(source.absolute);
68
+ const safeName = basename(source.absolute).replace(/[^a-zA-Z0-9._-]+/g, '-');
69
+ const rawLocator = `.aiwg/wiki/raw/${digest.slice(7, 23)}-${safeName}`;
70
+ const rawPath = resolve(this.projectRoot, rawLocator);
71
+ const duplicate = existsSync(rawPath) && sha256(readFileSync(rawPath)) === digest;
72
+ const identity = {
73
+ source: { locator: source.locator, digest, byteLength: bytes.length, kind },
74
+ rawLocator,
75
+ route: kind === 'session-transcript' ? 'sessions' : 'llm-wiki',
76
+ };
77
+ return {
78
+ schemaVersion: 'aiwg.compound-memory.intake-preview.v1',
79
+ operationId: sha256(JSON.stringify(identity)),
80
+ ...identity,
81
+ duplicate,
82
+ confirmationRequired: true,
83
+ mutation: { wouldCopyRaw: !duplicate, wouldPromoteKnowledge: false },
84
+ };
85
+ }
86
+ confirm(requested, operationId) {
87
+ const preview = this.preview(requested);
88
+ const receiptPath = resolve(this.receiptRoot, `${operationId.replace(':', '_')}.json`);
89
+ if (existsSync(receiptPath)) {
90
+ return { ...JSON.parse(readFileSync(receiptPath, 'utf8')), duplicate: true };
91
+ }
92
+ if (preview.operationId !== operationId) {
93
+ throw new Error('intake confirmation requires the exact current preview');
94
+ }
95
+ const source = safeProjectFile(this.projectRoot, requested);
96
+ const rawPath = resolve(this.projectRoot, preview.rawLocator);
97
+ mkdirSync(this.rawRoot, { recursive: true, mode: 0o700 });
98
+ if (!preview.duplicate)
99
+ copyFileSync(source.absolute, rawPath, 1);
100
+ if (sha256(readFileSync(rawPath)) !== preview.source.digest) {
101
+ throw new Error('immutable raw copy digest does not match the source preview');
102
+ }
103
+ const receipt = {
104
+ schemaVersion: 'aiwg.compound-memory.intake-receipt.v1',
105
+ receiptId: sha256(`${operationId}\0${preview.rawLocator}`),
106
+ operationId,
107
+ sourceLocator: preview.source.locator,
108
+ sourceDigest: preview.source.digest,
109
+ rawLocator: preview.rawLocator,
110
+ route: preview.route,
111
+ duplicate: preview.duplicate,
112
+ registeredAt: new Date().toISOString(),
113
+ };
114
+ atomicJson(receiptPath, receipt);
115
+ return receipt;
116
+ }
117
+ }
118
+ //# sourceMappingURL=intake.js.map
@@ -13,6 +13,9 @@ import { resolve, dirname } from 'path';
13
13
  import { fileURLToPath } from 'url';
14
14
  import { load as loadYaml } from 'js-yaml';
15
15
  import { findPackageRoot } from '../cli/find-package-root.js';
16
+ export function isExternalStrategy(strategy) {
17
+ return strategy === 'external-trigger';
18
+ }
16
19
  // ---------------------------------------------------------------------------
17
20
  // Loader
18
21
  // ---------------------------------------------------------------------------
@@ -257,6 +260,8 @@ export function formatCapabilityTable() {
257
260
  if (caps.native_features[f])
258
261
  return padRight('NATIVE', 15);
259
262
  const emu = caps.emulation[f];
263
+ if (isExternalStrategy(emu))
264
+ return padRight('EXTERNAL', 15);
260
265
  if (emu)
261
266
  return padRight(emu, 15);
262
267
  return padRight('--', 15);
@@ -264,7 +269,7 @@ export function formatCapabilityTable() {
264
269
  lines.push([padRight(caps.display_name, 18), ...cells].join('| '));
265
270
  }
266
271
  lines.push('');
267
- lines.push('Legend: NATIVE = built-in support, aiwg-* = AIWG emulation, -- = unsupported');
272
+ lines.push('Legend: NATIVE = built-in support, aiwg-* = AIWG emulation, EXTERNAL = host/CI owns the trigger, -- = unsupported');
268
273
  return lines.join('\n');
269
274
  }
270
275
  /**
@@ -287,9 +292,11 @@ export function formatFeatureSupport(feature) {
287
292
  const strategy = caps.emulation[feature];
288
293
  const status = native
289
294
  ? 'NATIVE'
290
- : strategy
291
- ? `emulated (${strategy})`
292
- : 'unsupported';
295
+ : isExternalStrategy(strategy)
296
+ ? 'external trigger'
297
+ : strategy
298
+ ? `emulated (${strategy})`
299
+ : 'unsupported';
293
300
  lines.push(` ${padRight(caps.display_name, 18)} ${status}`);
294
301
  }
295
302
  return lines.join('\n');
@@ -16,8 +16,8 @@ providers:
16
16
  claude-code:
17
17
  display_name: Claude Code
18
18
  status: stable
19
- daemon_tier: native
20
- daemon_pty_adapter: true
19
+ daemon_tier: unsupported
20
+ daemon_pty_adapter: false
21
21
  artifact_paths:
22
22
  agents: .claude/agents/
23
23
  commands: .claude/commands/
@@ -31,7 +31,7 @@ providers:
31
31
  mcp: true
32
32
  behaviors: false
33
33
  mission_control: false
34
- daemon: true
34
+ daemon: false
35
35
  emulation:
36
36
  cron: native
37
37
  agent_teams: native
@@ -39,7 +39,7 @@ providers:
39
39
  mcp: native
40
40
  behaviors: hooks
41
41
  mission_control: aiwg-mc
42
- daemon: native
42
+ daemon: null
43
43
  hook_wiring:
44
44
  at_link_support: true
45
45
  hook_file: AIWG.md
@@ -80,8 +80,8 @@ providers:
80
80
  aliases:
81
81
  - openai
82
82
  status: stable
83
- daemon_tier: native
84
- daemon_pty_adapter: true
83
+ daemon_tier: unsupported
84
+ daemon_pty_adapter: false
85
85
  artifact_paths:
86
86
  agents: .codex/agents/
87
87
  commands: "~/.codex/prompts/"
@@ -100,15 +100,15 @@ providers:
100
100
  mcp: false
101
101
  behaviors: false
102
102
  mission_control: false
103
- daemon: true
103
+ daemon: false
104
104
  emulation:
105
- cron: aiwg-schedule
105
+ cron: external-trigger
106
106
  agent_teams: aiwg-mc
107
107
  tasks: aiwg-mc
108
108
  mcp: null
109
109
  behaviors: aiwg-mc
110
110
  mission_control: aiwg-mc
111
- daemon: native
111
+ daemon: null
112
112
  hook_wiring:
113
113
  at_link_support: false
114
114
  hook_file: AIWG-codex.md
@@ -164,7 +164,7 @@ providers:
164
164
  mission_control: false
165
165
  daemon: false
166
166
  emulation:
167
- cron: aiwg-schedule
167
+ cron: null
168
168
  agent_teams: aiwg-mc
169
169
  tasks: aiwg-mc
170
170
  mcp: null
@@ -183,8 +183,8 @@ providers:
183
183
  display_name: Factory AI
184
184
  status: stable
185
185
  # droid CLI runs headless via `droid exec`; AIWG daemon provides persistence layer
186
- daemon_tier: tier1
187
- daemon_pty_adapter: true
186
+ daemon_tier: unsupported
187
+ daemon_pty_adapter: false
188
188
  artifact_paths:
189
189
  agents: .factory/droids/
190
190
  commands: .factory/commands/
@@ -198,15 +198,15 @@ providers:
198
198
  mcp: true # Native MCP support (stdio + HTTP transports)
199
199
  behaviors: false
200
200
  mission_control: true # Factory Missions maps to MC concept
201
- daemon: false # No native persistent daemon; AIWG daemon wraps droid exec
201
+ daemon: false
202
202
  emulation:
203
- cron: aiwg-schedule
203
+ cron: null
204
204
  agent_teams: null # native Missions
205
205
  tasks: null # native Task tool
206
206
  mcp: null # native MCP
207
207
  behaviors: aiwg-mc
208
208
  mission_control: null # native Missions
209
- daemon: aiwg-daemon # AIWG daemon provides persistence for headless droid exec
209
+ daemon: null
210
210
  hook_wiring:
211
211
  at_link_support: false
212
212
  hook_file: AIWG-factory.md
@@ -236,7 +236,7 @@ providers:
236
236
  mission_control: false
237
237
  daemon: false
238
238
  emulation:
239
- cron: aiwg-schedule
239
+ cron: null
240
240
  agent_teams: aiwg-mc
241
241
  tasks: aiwg-mc
242
242
  mcp: null
@@ -254,7 +254,7 @@ providers:
254
254
  opencode:
255
255
  display_name: OpenCode
256
256
  status: stable
257
- daemon_tier: native
257
+ daemon_tier: unsupported
258
258
  daemon_pty_adapter: false
259
259
  artifact_paths:
260
260
  agents: .opencode/agent/
@@ -269,15 +269,15 @@ providers:
269
269
  mcp: false
270
270
  behaviors: false
271
271
  mission_control: false
272
- daemon: true
272
+ daemon: false
273
273
  emulation:
274
- cron: aiwg-schedule
274
+ cron: null
275
275
  agent_teams: aiwg-mc
276
276
  tasks: aiwg-mc
277
277
  mcp: null
278
278
  behaviors: aiwg-mc
279
279
  mission_control: aiwg-mc
280
- daemon: native
280
+ daemon: null
281
281
  hook_wiring:
282
282
  at_link_support: true
283
283
  hook_file: AIWG-opencode.md
@@ -289,7 +289,7 @@ providers:
289
289
  warp:
290
290
  display_name: Warp Terminal
291
291
  status: stable
292
- daemon_tier: native
292
+ daemon_tier: unsupported
293
293
  daemon_pty_adapter: false
294
294
  artifact_paths:
295
295
  agents: .warp/agents/
@@ -305,15 +305,15 @@ providers:
305
305
  mcp: false
306
306
  behaviors: false
307
307
  mission_control: false
308
- daemon: true
308
+ daemon: false
309
309
  emulation:
310
- cron: aiwg-schedule
310
+ cron: null
311
311
  agent_teams: aiwg-mc
312
312
  tasks: aiwg-mc
313
313
  mcp: null
314
314
  behaviors: aiwg-mc
315
315
  mission_control: aiwg-mc
316
- daemon: native
316
+ daemon: null
317
317
  hook_wiring:
318
318
  at_link_support: true
319
319
  hook_file: AIWG-warp.md
@@ -344,7 +344,7 @@ providers:
344
344
  mission_control: false
345
345
  daemon: false
346
346
  emulation:
347
- cron: aiwg-schedule
347
+ cron: null
348
348
  agent_teams: aiwg-mc
349
349
  tasks: aiwg-mc
350
350
  mcp: null
@@ -362,7 +362,7 @@ providers:
362
362
  hermes:
363
363
  display_name: Hermes
364
364
  status: experimental
365
- daemon_tier: native
365
+ daemon_tier: unsupported
366
366
  daemon_pty_adapter: false
367
367
  artifact_paths:
368
368
  # MCP is OPTIONAL for Hermes (validated v2026.5.13, #1527): it integrates
@@ -382,15 +382,15 @@ providers:
382
382
  mcp: true
383
383
  behaviors: false
384
384
  mission_control: false
385
- daemon: true
385
+ daemon: false
386
386
  emulation:
387
- cron: aiwg-schedule
387
+ cron: null
388
388
  agent_teams: aiwg-mc
389
389
  tasks: aiwg-mc
390
390
  mcp: native
391
391
  behaviors: aiwg-mc
392
392
  mission_control: aiwg-mc
393
- daemon: native
393
+ daemon: null
394
394
  hook_wiring:
395
395
  at_link_support: false
396
396
  hook_file: .hermes.md
@@ -402,7 +402,7 @@ providers:
402
402
  openclaw:
403
403
  display_name: OpenClaw
404
404
  status: stable
405
- daemon_tier: native
405
+ daemon_tier: unsupported
406
406
  daemon_pty_adapter: false
407
407
  artifact_paths:
408
408
  agents: "~/.openclaw/agents/"
@@ -417,15 +417,15 @@ providers:
417
417
  mcp: true
418
418
  behaviors: true
419
419
  mission_control: false
420
- daemon: true
420
+ daemon: false
421
421
  emulation:
422
- cron: aiwg-schedule
422
+ cron: null
423
423
  agent_teams: aiwg-mc
424
424
  tasks: aiwg-mc
425
425
  mcp: native
426
426
  behaviors: native
427
427
  mission_control: aiwg-mc
428
- daemon: native
428
+ daemon: null
429
429
  hook_wiring:
430
430
  at_link_support: false
431
431
  context_file: "~/.openclaw/config.yaml"
@@ -457,7 +457,7 @@ providers:
457
457
  mission_control: false
458
458
  daemon: false
459
459
  emulation:
460
- cron: aiwg-schedule
460
+ cron: null
461
461
  agent_teams: aiwg-mc
462
462
  tasks: aiwg-mc
463
463
  mcp: null
@@ -477,7 +477,7 @@ features:
477
477
  description: Scheduled task execution (recurring triggers)
478
478
  native_example: Claude Code CronCreate/CronList/CronDelete tools
479
479
  emulation_strategies:
480
- aiwg-schedule: AIWG schedule CLI with remote triggers
480
+ external-trigger: System cron, systemd timers, or CI own time and launch a reviewed provider command
481
481
  agent_teams:
482
482
  description: Multi-agent orchestration with team coordination
483
483
  native_example: Claude Code native agent teams
@@ -505,10 +505,7 @@ features:
505
505
  aiwg-mc: AIWG mc start/dispatch/status/watch CLI
506
506
  daemon:
507
507
  description: >
508
- Persistent background process for headless/unattended operation.
509
- Tier 1 (native): full daemon support via aiwg daemon start/stop/status.
510
- Tier 2 (pty-adapter): PTY bridge for platforms with a TUI but no headless mode.
511
- Tier 3 (unsupported): requires a display server or IDE host; daemon not applicable.
512
- native_example: aiwg daemon start (Claude Code, OpenCode, Warp, OpenClaw, Codex)
513
- emulation_strategies:
514
- pty-adapter: node-pty bridge for TUI platforms (Claude Code, Codex secondary mode)
508
+ Resident AIWG daemon lifecycle. The current production CLI does not expose
509
+ a daemon command; bundled daemon sources are non-routable development artifacts.
510
+ native_example: null
511
+ emulation_strategies: {}
@@ -117,6 +117,7 @@ export async function resolveAiwgResourceBytes(logicalId, options) {
117
117
  const bytes = await fetchVerifiedRawResource(webRelease, parsed.rawPath, {
118
118
  baseUrl: options.webReleaseOptions?.baseUrl,
119
119
  fetcher: options.webReleaseOptions?.fetcher,
120
+ credentialProvider: options.webReleaseOptions?.credentialProvider,
120
121
  allowInsecureLoopbackHttp: options.webReleaseOptions?.allowInsecureLoopbackHttp,
121
122
  offline: options.offline,
122
123
  });
@@ -45,6 +45,8 @@ export interface WebReleaseOptions {
45
45
  cacheRoot?: string;
46
46
  publicKeyPem?: string | Buffer;
47
47
  fetcher?: ResourceFetcher;
48
+ /** Returns a bearer token at request time. Tokens never participate in URLs or cache keys. */
49
+ credentialProvider?: () => Promise<string | null>;
48
50
  /** Test/development escape hatch. HTTP remains restricted to loopback. */
49
51
  allowInsecureLoopbackHttp?: boolean;
50
52
  }
@@ -72,7 +74,7 @@ export interface VerifiedWebRelease {
72
74
  channelSequence?: number;
73
75
  descriptors: ReadonlyMap<string, VerifiedReleaseDescriptor>;
74
76
  }
75
- export interface VerifiedRawResourceOptions extends Pick<WebReleaseOptions, "baseUrl" | "fetcher" | "allowInsecureLoopbackHttp"> {
77
+ export interface VerifiedRawResourceOptions extends Pick<WebReleaseOptions, "baseUrl" | "fetcher" | "credentialProvider" | "allowInsecureLoopbackHttp"> {
76
78
  offline?: boolean;
77
79
  }
78
80
  export declare function verifySignedResourceBytes(bytes: Uint8Array, signatureBytes: Uint8Array, publicKeyPem?: string | Buffer, label?: string): string;
@@ -297,7 +297,7 @@ function resourceUrl(base, relativePath) {
297
297
  url.pathname = `${prefix}/${relativePath}`;
298
298
  return url.toString();
299
299
  }
300
- async function fetchBytes(fetcher, url, label, maxBytes) {
300
+ async function fetchBytes(fetcher, url, label, maxBytes, bearerToken) {
301
301
  if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
302
302
  throw new Error(`${label} has an invalid network size limit`);
303
303
  const controller = new AbortController();
@@ -315,7 +315,10 @@ async function fetchBytes(fetcher, url, label, maxBytes) {
315
315
  const response = await Promise.race([
316
316
  fetcher(url, {
317
317
  redirect: "error",
318
- headers: { "accept-encoding": "identity" },
318
+ headers: {
319
+ "accept-encoding": "identity",
320
+ ...(bearerToken ? { authorization: `Bearer ${bearerToken}` } : {}),
321
+ },
319
322
  signal: controller.signal,
320
323
  }),
321
324
  timeoutFailure,
@@ -904,16 +907,21 @@ export async function resolveWebRelease(options = {}) {
904
907
  const base = normalizeBaseUrl(options.baseUrl ?? DEFAULT_RESOURCE_BASE_URL, options.allowInsecureLoopbackHttp === true);
905
908
  // Validate injected trust material before reading cache or making requests.
906
909
  loadTrustRoot(publicKeyPem);
910
+ const bearerToken = options.offline ? null : await options.credentialProvider?.() ?? null;
911
+ const authorize = async (input, init = {}) => {
912
+ const headers = { ...(init.headers || {}), ...(bearerToken ? { authorization: `Bearer ${bearerToken}` } : {}) };
913
+ return (options.fetcher ?? globalThis.fetch)(input, { ...init, headers });
914
+ };
907
915
  if (selector.kind === "exact") {
908
916
  if (options.offline)
909
917
  return resolveOfflineExact(cacheRoot, selector, selector.value, publicKeyPem, base);
910
- const fetcher = options.fetcher ?? globalThis.fetch;
918
+ const fetcher = authorize;
911
919
  if (!fetcher)
912
920
  throw new Error("No fetch implementation is available for AIWG web resources");
913
921
  return fetchAndCacheRelease(base, fetcher, cacheRoot, selector, selector.value, publicKeyPem);
914
922
  }
915
923
  if (selector.kind === "range" || selector.kind === "digest") {
916
- const fetcher = options.fetcher ?? globalThis.fetch;
924
+ const fetcher = authorize;
917
925
  const index = await resolveVersionIndex(base, fetcher, cacheRoot, publicKeyPem, options.offline);
918
926
  const selected = selectVersionFromIndex(index, selector);
919
927
  if (options.offline) {
@@ -929,7 +937,7 @@ export async function resolveWebRelease(options = {}) {
929
937
  throw new Error(`AIWG resource channel ${selector.value} is not cached; offline mode cannot fetch it`);
930
938
  return resolveOfflineExact(cacheRoot, selector, cached.manifest.version, publicKeyPem, base, cached.manifest.releaseManifestSha256, cached.manifest.sequence);
931
939
  }
932
- const fetcher = options.fetcher ?? globalThis.fetch;
940
+ const fetcher = authorize;
933
941
  if (!fetcher)
934
942
  throw new Error("No fetch implementation is available for AIWG web resources");
935
943
  const channelPrefix = `resources/channels/${selector.value}`;
@@ -989,7 +997,7 @@ export async function fetchVerifiedRawResource(release, resourcePath, options =
989
997
  const fetcher = options.fetcher ?? globalThis.fetch;
990
998
  if (!fetcher)
991
999
  throw new Error("No fetch implementation is available for AIWG web resources");
992
- const bytes = await fetchBytes(fetcher, resourceUrl(base, `resources/${release.version}/${resourcePath}`), `raw resource ${resourcePath}`, Math.min(descriptor.size, MAX_RAW_RESOURCE_BYTES));
1000
+ const bytes = await fetchBytes(fetcher, resourceUrl(base, `resources/${release.version}/${resourcePath}`), `raw resource ${resourcePath}`, Math.min(descriptor.size, MAX_RAW_RESOURCE_BYTES), await options.credentialProvider?.() ?? null);
993
1001
  verifyDescriptor(bytes, descriptor);
994
1002
  const stagingRoot = path.join(release.cacheDir, ".raw-staging");
995
1003
  fs.mkdirSync(stagingRoot, { recursive: true });