@askexenow/exe-os 0.9.63 → 0.9.64

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.
@@ -1264,7 +1264,7 @@ function commandHasAnyMarker(command, markers) {
1264
1264
  function isLegacySplitPostToolCommand(command) {
1265
1265
  return commandHasAnyMarker(command, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS);
1266
1266
  }
1267
- var EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
1267
+ var EXE_HOOKS, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
1268
1268
  var init_runtime_hook_manifest = __esm({
1269
1269
  "src/adapters/runtime-hook-manifest.ts"() {
1270
1270
  "use strict";
@@ -1282,116 +1282,6 @@ var init_runtime_hook_manifest = __esm({
1282
1282
  notification: "dist/hooks/notification.js",
1283
1283
  instructionsLoaded: "dist/hooks/instructions-loaded.js"
1284
1284
  };
1285
- EXE_HOOK_MANIFEST = [
1286
- {
1287
- key: "postToolCombined",
1288
- event: "PostToolUse",
1289
- commandMarker: EXE_HOOKS.postToolCombined,
1290
- owner: "exe-os",
1291
- purpose: "Single PostToolUse entrypoint for ingestion, error recall, summaries, and bug detection.",
1292
- runtimes: ["claude", "codex", "opencode"],
1293
- checkpointRole: "none"
1294
- },
1295
- {
1296
- key: "sessionStart",
1297
- event: "SessionStart",
1298
- commandMarker: EXE_HOOKS.sessionStart,
1299
- owner: "exe-os",
1300
- purpose: "Loads agent identity, procedures, and boot context.",
1301
- runtimes: ["claude", "codex", "opencode"],
1302
- checkpointRole: "none"
1303
- },
1304
- {
1305
- key: "promptSubmit",
1306
- event: "UserPromptSubmit",
1307
- commandMarker: EXE_HOOKS.promptSubmit,
1308
- owner: "exe-os",
1309
- purpose: "Injects current tasks, pending reviews, and local context before each prompt.",
1310
- runtimes: ["claude", "codex", "opencode"],
1311
- checkpointRole: "none"
1312
- },
1313
- {
1314
- key: "heartbeat",
1315
- event: "UserPromptSubmit",
1316
- commandMarker: EXE_HOOKS.heartbeat,
1317
- owner: "exe-os",
1318
- purpose: "Lightweight heartbeat/status sidecar for Claude Code sessions.",
1319
- runtimes: ["claude"],
1320
- checkpointRole: "none"
1321
- },
1322
- {
1323
- key: "stop",
1324
- event: "Stop",
1325
- commandMarker: EXE_HOOKS.stop,
1326
- owner: "exe-os",
1327
- purpose: "Finalizes task state, capacity signals, and emergency checkpointing.",
1328
- runtimes: ["claude", "codex", "opencode"],
1329
- checkpointRole: "capacity_checkpoint"
1330
- },
1331
- {
1332
- key: "preToolUse",
1333
- event: "PreToolUse",
1334
- commandMarker: EXE_HOOKS.preToolUse,
1335
- owner: "exe-os",
1336
- purpose: "Preflight guardrails before shell/tool execution.",
1337
- runtimes: ["claude", "codex", "opencode"],
1338
- checkpointRole: "none"
1339
- },
1340
- {
1341
- key: "subagentStop",
1342
- event: "SubagentStop",
1343
- commandMarker: EXE_HOOKS.subagentStop,
1344
- owner: "exe-os",
1345
- purpose: "Captures subagent completion context.",
1346
- runtimes: ["claude"],
1347
- checkpointRole: "none"
1348
- },
1349
- {
1350
- key: "preCompact",
1351
- event: "PreCompact",
1352
- commandMarker: EXE_HOOKS.preCompact,
1353
- owner: "exe-os",
1354
- purpose: "Writes active-task snapshot and compaction recovery context.",
1355
- runtimes: ["claude"],
1356
- checkpointRole: "recovery_context"
1357
- },
1358
- {
1359
- key: "postCompact",
1360
- event: "PostCompact",
1361
- commandMarker: EXE_HOOKS.postCompact,
1362
- owner: "exe-os",
1363
- purpose: "Rehydrates recovery context after compaction.",
1364
- runtimes: ["claude"],
1365
- checkpointRole: "recovery_context"
1366
- },
1367
- {
1368
- key: "sessionEnd",
1369
- event: "SessionEnd",
1370
- commandMarker: EXE_HOOKS.sessionEnd,
1371
- owner: "exe-os",
1372
- purpose: "Stores session-end checkpoint and triages orphaned in-progress tasks.",
1373
- runtimes: ["claude"],
1374
- checkpointRole: "session_summary"
1375
- },
1376
- {
1377
- key: "notification",
1378
- event: "Notification",
1379
- commandMarker: EXE_HOOKS.notification,
1380
- owner: "exe-os",
1381
- purpose: "Captures runtime notifications and nudges.",
1382
- runtimes: ["claude"],
1383
- checkpointRole: "none"
1384
- },
1385
- {
1386
- key: "instructionsLoaded",
1387
- event: "InstructionsLoaded",
1388
- commandMarker: EXE_HOOKS.instructionsLoaded,
1389
- owner: "exe-os",
1390
- purpose: "Applies runtime instruction post-processing.",
1391
- runtimes: ["claude"],
1392
- checkpointRole: "none"
1393
- }
1394
- ];
1395
1285
  LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS = [
1396
1286
  "dist/hooks/ingest.js",
1397
1287
  "dist/hooks/error-recall.js",
@@ -3948,7 +3948,7 @@ function commandHasAnyMarker(command, markers) {
3948
3948
  function isLegacySplitPostToolCommand(command) {
3949
3949
  return commandHasAnyMarker(command, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS);
3950
3950
  }
3951
- var EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
3951
+ var EXE_HOOKS, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
3952
3952
  var init_runtime_hook_manifest = __esm({
3953
3953
  "src/adapters/runtime-hook-manifest.ts"() {
3954
3954
  "use strict";
@@ -3966,116 +3966,6 @@ var init_runtime_hook_manifest = __esm({
3966
3966
  notification: "dist/hooks/notification.js",
3967
3967
  instructionsLoaded: "dist/hooks/instructions-loaded.js"
3968
3968
  };
3969
- EXE_HOOK_MANIFEST = [
3970
- {
3971
- key: "postToolCombined",
3972
- event: "PostToolUse",
3973
- commandMarker: EXE_HOOKS.postToolCombined,
3974
- owner: "exe-os",
3975
- purpose: "Single PostToolUse entrypoint for ingestion, error recall, summaries, and bug detection.",
3976
- runtimes: ["claude", "codex", "opencode"],
3977
- checkpointRole: "none"
3978
- },
3979
- {
3980
- key: "sessionStart",
3981
- event: "SessionStart",
3982
- commandMarker: EXE_HOOKS.sessionStart,
3983
- owner: "exe-os",
3984
- purpose: "Loads agent identity, procedures, and boot context.",
3985
- runtimes: ["claude", "codex", "opencode"],
3986
- checkpointRole: "none"
3987
- },
3988
- {
3989
- key: "promptSubmit",
3990
- event: "UserPromptSubmit",
3991
- commandMarker: EXE_HOOKS.promptSubmit,
3992
- owner: "exe-os",
3993
- purpose: "Injects current tasks, pending reviews, and local context before each prompt.",
3994
- runtimes: ["claude", "codex", "opencode"],
3995
- checkpointRole: "none"
3996
- },
3997
- {
3998
- key: "heartbeat",
3999
- event: "UserPromptSubmit",
4000
- commandMarker: EXE_HOOKS.heartbeat,
4001
- owner: "exe-os",
4002
- purpose: "Lightweight heartbeat/status sidecar for Claude Code sessions.",
4003
- runtimes: ["claude"],
4004
- checkpointRole: "none"
4005
- },
4006
- {
4007
- key: "stop",
4008
- event: "Stop",
4009
- commandMarker: EXE_HOOKS.stop,
4010
- owner: "exe-os",
4011
- purpose: "Finalizes task state, capacity signals, and emergency checkpointing.",
4012
- runtimes: ["claude", "codex", "opencode"],
4013
- checkpointRole: "capacity_checkpoint"
4014
- },
4015
- {
4016
- key: "preToolUse",
4017
- event: "PreToolUse",
4018
- commandMarker: EXE_HOOKS.preToolUse,
4019
- owner: "exe-os",
4020
- purpose: "Preflight guardrails before shell/tool execution.",
4021
- runtimes: ["claude", "codex", "opencode"],
4022
- checkpointRole: "none"
4023
- },
4024
- {
4025
- key: "subagentStop",
4026
- event: "SubagentStop",
4027
- commandMarker: EXE_HOOKS.subagentStop,
4028
- owner: "exe-os",
4029
- purpose: "Captures subagent completion context.",
4030
- runtimes: ["claude"],
4031
- checkpointRole: "none"
4032
- },
4033
- {
4034
- key: "preCompact",
4035
- event: "PreCompact",
4036
- commandMarker: EXE_HOOKS.preCompact,
4037
- owner: "exe-os",
4038
- purpose: "Writes active-task snapshot and compaction recovery context.",
4039
- runtimes: ["claude"],
4040
- checkpointRole: "recovery_context"
4041
- },
4042
- {
4043
- key: "postCompact",
4044
- event: "PostCompact",
4045
- commandMarker: EXE_HOOKS.postCompact,
4046
- owner: "exe-os",
4047
- purpose: "Rehydrates recovery context after compaction.",
4048
- runtimes: ["claude"],
4049
- checkpointRole: "recovery_context"
4050
- },
4051
- {
4052
- key: "sessionEnd",
4053
- event: "SessionEnd",
4054
- commandMarker: EXE_HOOKS.sessionEnd,
4055
- owner: "exe-os",
4056
- purpose: "Stores session-end checkpoint and triages orphaned in-progress tasks.",
4057
- runtimes: ["claude"],
4058
- checkpointRole: "session_summary"
4059
- },
4060
- {
4061
- key: "notification",
4062
- event: "Notification",
4063
- commandMarker: EXE_HOOKS.notification,
4064
- owner: "exe-os",
4065
- purpose: "Captures runtime notifications and nudges.",
4066
- runtimes: ["claude"],
4067
- checkpointRole: "none"
4068
- },
4069
- {
4070
- key: "instructionsLoaded",
4071
- event: "InstructionsLoaded",
4072
- commandMarker: EXE_HOOKS.instructionsLoaded,
4073
- owner: "exe-os",
4074
- purpose: "Applies runtime instruction post-processing.",
4075
- runtimes: ["claude"],
4076
- checkpointRole: "none"
4077
- }
4078
- ];
4079
3969
  LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS = [
4080
3970
  "dist/hooks/ingest.js",
4081
3971
  "dist/hooks/error-recall.js",
@@ -3934,7 +3934,7 @@ var init_preferences = __esm({
3934
3934
  function textHasLegacySplitPostToolHook(text) {
3935
3935
  return [EXE_HOOK_FILES.ingest, EXE_HOOK_FILES.errorRecall, EXE_HOOK_FILES.ingestWorker].some((file) => text.includes(file));
3936
3936
  }
3937
- var EXE_HOOK_FILES, EXE_HOOKS, EXE_HOOK_MANIFEST;
3937
+ var EXE_HOOK_FILES;
3938
3938
  var init_runtime_hook_manifest = __esm({
3939
3939
  "src/adapters/runtime-hook-manifest.ts"() {
3940
3940
  "use strict";
@@ -3944,130 +3944,6 @@ var init_runtime_hook_manifest = __esm({
3944
3944
  errorRecall: "error-recall.js",
3945
3945
  ingestWorker: "ingest-worker.js"
3946
3946
  };
3947
- EXE_HOOKS = {
3948
- postToolCombined: "dist/hooks/post-tool-combined.js",
3949
- sessionStart: "dist/hooks/session-start.js",
3950
- promptSubmit: "dist/hooks/prompt-submit.js",
3951
- heartbeat: "dist/hooks/exe-heartbeat-hook.js",
3952
- stop: "dist/hooks/stop.js",
3953
- preToolUse: "dist/hooks/pre-tool-use.js",
3954
- subagentStop: "dist/hooks/subagent-stop.js",
3955
- preCompact: "dist/hooks/pre-compact.js",
3956
- postCompact: "dist/hooks/post-compact.js",
3957
- sessionEnd: "dist/hooks/session-end.js",
3958
- notification: "dist/hooks/notification.js",
3959
- instructionsLoaded: "dist/hooks/instructions-loaded.js"
3960
- };
3961
- EXE_HOOK_MANIFEST = [
3962
- {
3963
- key: "postToolCombined",
3964
- event: "PostToolUse",
3965
- commandMarker: EXE_HOOKS.postToolCombined,
3966
- owner: "exe-os",
3967
- purpose: "Single PostToolUse entrypoint for ingestion, error recall, summaries, and bug detection.",
3968
- runtimes: ["claude", "codex", "opencode"],
3969
- checkpointRole: "none"
3970
- },
3971
- {
3972
- key: "sessionStart",
3973
- event: "SessionStart",
3974
- commandMarker: EXE_HOOKS.sessionStart,
3975
- owner: "exe-os",
3976
- purpose: "Loads agent identity, procedures, and boot context.",
3977
- runtimes: ["claude", "codex", "opencode"],
3978
- checkpointRole: "none"
3979
- },
3980
- {
3981
- key: "promptSubmit",
3982
- event: "UserPromptSubmit",
3983
- commandMarker: EXE_HOOKS.promptSubmit,
3984
- owner: "exe-os",
3985
- purpose: "Injects current tasks, pending reviews, and local context before each prompt.",
3986
- runtimes: ["claude", "codex", "opencode"],
3987
- checkpointRole: "none"
3988
- },
3989
- {
3990
- key: "heartbeat",
3991
- event: "UserPromptSubmit",
3992
- commandMarker: EXE_HOOKS.heartbeat,
3993
- owner: "exe-os",
3994
- purpose: "Lightweight heartbeat/status sidecar for Claude Code sessions.",
3995
- runtimes: ["claude"],
3996
- checkpointRole: "none"
3997
- },
3998
- {
3999
- key: "stop",
4000
- event: "Stop",
4001
- commandMarker: EXE_HOOKS.stop,
4002
- owner: "exe-os",
4003
- purpose: "Finalizes task state, capacity signals, and emergency checkpointing.",
4004
- runtimes: ["claude", "codex", "opencode"],
4005
- checkpointRole: "capacity_checkpoint"
4006
- },
4007
- {
4008
- key: "preToolUse",
4009
- event: "PreToolUse",
4010
- commandMarker: EXE_HOOKS.preToolUse,
4011
- owner: "exe-os",
4012
- purpose: "Preflight guardrails before shell/tool execution.",
4013
- runtimes: ["claude", "codex", "opencode"],
4014
- checkpointRole: "none"
4015
- },
4016
- {
4017
- key: "subagentStop",
4018
- event: "SubagentStop",
4019
- commandMarker: EXE_HOOKS.subagentStop,
4020
- owner: "exe-os",
4021
- purpose: "Captures subagent completion context.",
4022
- runtimes: ["claude"],
4023
- checkpointRole: "none"
4024
- },
4025
- {
4026
- key: "preCompact",
4027
- event: "PreCompact",
4028
- commandMarker: EXE_HOOKS.preCompact,
4029
- owner: "exe-os",
4030
- purpose: "Writes active-task snapshot and compaction recovery context.",
4031
- runtimes: ["claude"],
4032
- checkpointRole: "recovery_context"
4033
- },
4034
- {
4035
- key: "postCompact",
4036
- event: "PostCompact",
4037
- commandMarker: EXE_HOOKS.postCompact,
4038
- owner: "exe-os",
4039
- purpose: "Rehydrates recovery context after compaction.",
4040
- runtimes: ["claude"],
4041
- checkpointRole: "recovery_context"
4042
- },
4043
- {
4044
- key: "sessionEnd",
4045
- event: "SessionEnd",
4046
- commandMarker: EXE_HOOKS.sessionEnd,
4047
- owner: "exe-os",
4048
- purpose: "Stores session-end checkpoint and triages orphaned in-progress tasks.",
4049
- runtimes: ["claude"],
4050
- checkpointRole: "session_summary"
4051
- },
4052
- {
4053
- key: "notification",
4054
- event: "Notification",
4055
- commandMarker: EXE_HOOKS.notification,
4056
- owner: "exe-os",
4057
- purpose: "Captures runtime notifications and nudges.",
4058
- runtimes: ["claude"],
4059
- checkpointRole: "none"
4060
- },
4061
- {
4062
- key: "instructionsLoaded",
4063
- event: "InstructionsLoaded",
4064
- commandMarker: EXE_HOOKS.instructionsLoaded,
4065
- owner: "exe-os",
4066
- purpose: "Applies runtime instruction post-processing.",
4067
- runtimes: ["claude"],
4068
- checkpointRole: "none"
4069
- }
4070
- ];
4071
3947
  }
4072
3948
  });
4073
3949
 
@@ -615,7 +615,7 @@ function commandHasAnyMarker(command, markers) {
615
615
  function isLegacySplitPostToolCommand(command) {
616
616
  return commandHasAnyMarker(command, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS);
617
617
  }
618
- var EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
618
+ var EXE_HOOKS, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
619
619
  var init_runtime_hook_manifest = __esm({
620
620
  "src/adapters/runtime-hook-manifest.ts"() {
621
621
  "use strict";
@@ -633,116 +633,6 @@ var init_runtime_hook_manifest = __esm({
633
633
  notification: "dist/hooks/notification.js",
634
634
  instructionsLoaded: "dist/hooks/instructions-loaded.js"
635
635
  };
636
- EXE_HOOK_MANIFEST = [
637
- {
638
- key: "postToolCombined",
639
- event: "PostToolUse",
640
- commandMarker: EXE_HOOKS.postToolCombined,
641
- owner: "exe-os",
642
- purpose: "Single PostToolUse entrypoint for ingestion, error recall, summaries, and bug detection.",
643
- runtimes: ["claude", "codex", "opencode"],
644
- checkpointRole: "none"
645
- },
646
- {
647
- key: "sessionStart",
648
- event: "SessionStart",
649
- commandMarker: EXE_HOOKS.sessionStart,
650
- owner: "exe-os",
651
- purpose: "Loads agent identity, procedures, and boot context.",
652
- runtimes: ["claude", "codex", "opencode"],
653
- checkpointRole: "none"
654
- },
655
- {
656
- key: "promptSubmit",
657
- event: "UserPromptSubmit",
658
- commandMarker: EXE_HOOKS.promptSubmit,
659
- owner: "exe-os",
660
- purpose: "Injects current tasks, pending reviews, and local context before each prompt.",
661
- runtimes: ["claude", "codex", "opencode"],
662
- checkpointRole: "none"
663
- },
664
- {
665
- key: "heartbeat",
666
- event: "UserPromptSubmit",
667
- commandMarker: EXE_HOOKS.heartbeat,
668
- owner: "exe-os",
669
- purpose: "Lightweight heartbeat/status sidecar for Claude Code sessions.",
670
- runtimes: ["claude"],
671
- checkpointRole: "none"
672
- },
673
- {
674
- key: "stop",
675
- event: "Stop",
676
- commandMarker: EXE_HOOKS.stop,
677
- owner: "exe-os",
678
- purpose: "Finalizes task state, capacity signals, and emergency checkpointing.",
679
- runtimes: ["claude", "codex", "opencode"],
680
- checkpointRole: "capacity_checkpoint"
681
- },
682
- {
683
- key: "preToolUse",
684
- event: "PreToolUse",
685
- commandMarker: EXE_HOOKS.preToolUse,
686
- owner: "exe-os",
687
- purpose: "Preflight guardrails before shell/tool execution.",
688
- runtimes: ["claude", "codex", "opencode"],
689
- checkpointRole: "none"
690
- },
691
- {
692
- key: "subagentStop",
693
- event: "SubagentStop",
694
- commandMarker: EXE_HOOKS.subagentStop,
695
- owner: "exe-os",
696
- purpose: "Captures subagent completion context.",
697
- runtimes: ["claude"],
698
- checkpointRole: "none"
699
- },
700
- {
701
- key: "preCompact",
702
- event: "PreCompact",
703
- commandMarker: EXE_HOOKS.preCompact,
704
- owner: "exe-os",
705
- purpose: "Writes active-task snapshot and compaction recovery context.",
706
- runtimes: ["claude"],
707
- checkpointRole: "recovery_context"
708
- },
709
- {
710
- key: "postCompact",
711
- event: "PostCompact",
712
- commandMarker: EXE_HOOKS.postCompact,
713
- owner: "exe-os",
714
- purpose: "Rehydrates recovery context after compaction.",
715
- runtimes: ["claude"],
716
- checkpointRole: "recovery_context"
717
- },
718
- {
719
- key: "sessionEnd",
720
- event: "SessionEnd",
721
- commandMarker: EXE_HOOKS.sessionEnd,
722
- owner: "exe-os",
723
- purpose: "Stores session-end checkpoint and triages orphaned in-progress tasks.",
724
- runtimes: ["claude"],
725
- checkpointRole: "session_summary"
726
- },
727
- {
728
- key: "notification",
729
- event: "Notification",
730
- commandMarker: EXE_HOOKS.notification,
731
- owner: "exe-os",
732
- purpose: "Captures runtime notifications and nudges.",
733
- runtimes: ["claude"],
734
- checkpointRole: "none"
735
- },
736
- {
737
- key: "instructionsLoaded",
738
- event: "InstructionsLoaded",
739
- commandMarker: EXE_HOOKS.instructionsLoaded,
740
- owner: "exe-os",
741
- purpose: "Applies runtime instruction post-processing.",
742
- runtimes: ["claude"],
743
- checkpointRole: "none"
744
- }
745
- ];
746
636
  LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS = [
747
637
  "dist/hooks/ingest.js",
748
638
  "dist/hooks/error-recall.js",
@@ -189,7 +189,13 @@ async function runStackUpdate(options) {
189
189
  writeFileSync(tmp, patched, { mode: 384 });
190
190
  renameSync(tmp, options.envFile);
191
191
  const composeArgs = ["compose", "--file", options.composeFile, "--env-file", options.envFile];
192
+ let registryForLogout;
192
193
  try {
194
+ const creds = await fetchImageCredentials(options);
195
+ if (creds) {
196
+ (options.dockerLogin ?? defaultDockerLogin)(creds);
197
+ registryForLogout = creds.registry;
198
+ }
193
199
  exec("docker", [...composeArgs, "pull"]);
194
200
  exec("docker", [...composeArgs, "up", "-d"]);
195
201
  await verifyReleaseHealth(plan.release, options.healthRetries ?? 12, options.healthDelayMs ?? 5e3);
@@ -205,8 +211,28 @@ async function runStackUpdate(options) {
205
211
  const reason = err instanceof Error ? err.message : String(err);
206
212
  await postDeployAudit(options, "failed", plan.targetVersion, previousVersion, reason, { rollbackAttempted: true });
207
213
  throw new Error(`Stack update failed and rollback was attempted: ${reason}`);
214
+ } finally {
215
+ if (registryForLogout) {
216
+ try {
217
+ (options.dockerLogout ?? defaultDockerLogout)(registryForLogout);
218
+ } catch {
219
+ }
220
+ }
208
221
  }
209
222
  }
223
+ async function fetchImageCredentials(options) {
224
+ if (!options.imageCredentialsUrl) return null;
225
+ const res = await fetch(options.imageCredentialsUrl, {
226
+ method: "POST",
227
+ headers: {
228
+ "content-type": "application/json",
229
+ ...options.manifestAuthToken ? { authorization: `Bearer ${options.manifestAuthToken}` } : {}
230
+ },
231
+ body: JSON.stringify({ deviceId: options.deviceId, licenseKey: options.licenseKey })
232
+ });
233
+ if (!res.ok) throw new Error(`Failed to fetch image credentials: HTTP ${res.status}`);
234
+ return await res.json();
235
+ }
210
236
  function readCurrentStackVersion(lockFile) {
211
237
  if (!existsSync(lockFile)) return void 0;
212
238
  try {
@@ -270,6 +296,15 @@ function httpStatus(urlString) {
270
296
  function defaultExec(cmd, args, opts) {
271
297
  execFileSync(cmd, args, { stdio: "inherit", cwd: opts?.cwd });
272
298
  }
299
+ function defaultDockerLogin(creds) {
300
+ execFileSync("docker", ["login", creds.registry, "-u", creds.username, "--password-stdin"], {
301
+ input: creds.password,
302
+ stdio: ["pipe", "inherit", "inherit"]
303
+ });
304
+ }
305
+ function defaultDockerLogout(registry) {
306
+ execFileSync("docker", ["logout", registry], { stdio: "ignore" });
307
+ }
273
308
  async function defaultFetchText(ref, authToken) {
274
309
  const res = await fetch(ref, {
275
310
  headers: authToken ? { authorization: `Bearer ${authToken}` } : void 0
@@ -296,6 +331,7 @@ function defaultStackPaths() {
296
331
  envFile: process.env.EXE_STACK_ENV_FILE || (existsSync(cwdEnv) ? cwdEnv : "/opt/exe-stack/.env"),
297
332
  manifestRef: process.env.EXE_STACK_MANIFEST || "https://update.askexe.com/stack-manifest.json",
298
333
  auditUrl: process.env.EXE_STACK_AUDIT_URL || "https://update.askexe.com/v1/deploy-audits",
334
+ imageCredentialsUrl: process.env.EXE_STACK_IMAGE_CREDENTIALS_URL || "https://update.askexe.com/v1/image-credentials",
299
335
  manifestAuthToken: process.env.EXE_STACK_UPDATE_TOKEN,
300
336
  manifestPublicKey: loadDefaultPublicKey()
301
337
  };
@@ -316,6 +352,7 @@ function parseArgs(args) {
316
352
  composeFile: defaults.composeFile,
317
353
  envFile: defaults.envFile,
318
354
  auditUrl: defaults.auditUrl,
355
+ imageCredentialsUrl: defaults.imageCredentialsUrl,
319
356
  manifestAuthToken: defaults.manifestAuthToken,
320
357
  manifestPublicKey: defaults.manifestPublicKey,
321
358
  deviceId: process.env.EXE_DEVICE_ID,
@@ -345,6 +382,9 @@ function parseArgs(args) {
345
382
  else if (arg === "--auth-token-env") opts.manifestAuthToken = process.env[next()] ?? "";
346
383
  else if (arg === "--audit-url") opts.auditUrl = next();
347
384
  else if (arg.startsWith("--audit-url=")) opts.auditUrl = arg.split("=").slice(1).join("=");
385
+ else if (arg === "--image-credentials-url") opts.imageCredentialsUrl = next();
386
+ else if (arg.startsWith("--image-credentials-url=")) opts.imageCredentialsUrl = arg.split("=").slice(1).join("=");
387
+ else if (arg === "--no-image-credentials") opts.imageCredentialsUrl = void 0;
348
388
  else if (arg === "--device-id") opts.deviceId = next();
349
389
  else if (arg.startsWith("--device-id=")) opts.deviceId = arg.split("=").slice(1).join("=");
350
390
  else if (arg === "--license-key") opts.licenseKey = next();
@@ -382,6 +422,8 @@ Options:
382
422
  --auth-token <token> Bearer token for private update manifest/audit API
383
423
  --auth-token-env <name> Read bearer token from an environment variable
384
424
  --audit-url <url> Deploy-audit endpoint (default: EXE_STACK_AUDIT_URL/update.askexe.com)
425
+ --image-credentials-url <url> Registry credential broker endpoint
426
+ --no-image-credentials Skip registry credential broker / Docker login
385
427
  --device-id <id> Device ID to include in deploy audit
386
428
  --license-key <key> License key to include in deploy audit
387
429
  --rollback Restore latest backed-up .env and restart stack