@gh-symphony/cli 0.0.17 → 0.0.18

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.
@@ -1,139 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // ../core/dist/contracts/status-surface.js
4
- var WORKFLOW_EXECUTION_PHASES = [
5
- "planning",
6
- "human-review",
7
- "implementation",
8
- "awaiting-merge",
9
- "completed"
10
- ];
11
- function isWorkflowExecutionPhase(value) {
12
- return typeof value === "string" && WORKFLOW_EXECUTION_PHASES.includes(value);
13
- }
14
- var SESSION_EXIT_CLASSIFICATIONS = [
15
- "completed",
16
- "budget-exceeded",
17
- "convergence-detected",
18
- "max-turns-reached",
19
- "user-input-required",
20
- "timeout",
21
- "error"
22
- ];
23
- function isSessionExitClassification(value) {
24
- return typeof value === "string" && SESSION_EXIT_CLASSIFICATIONS.includes(value);
25
- }
26
-
27
- // ../core/dist/contracts/run-attempt-phase.js
28
- var RUN_ATTEMPT_PHASES = [
29
- "preparing_workspace",
30
- "building_prompt",
31
- "launching_agent",
32
- "initializing_session",
33
- "streaming_turn",
34
- "finishing",
35
- "succeeded",
36
- "failed",
37
- "timed_out",
38
- "stalled",
39
- "canceled_by_reconciliation"
40
- ];
41
- function isRunAttemptPhase(value) {
42
- return typeof value === "string" && RUN_ATTEMPT_PHASES.includes(value);
43
- }
44
-
45
- // ../core/dist/contracts/orchestrator-channel.js
46
- function isRecord(value) {
47
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
48
- }
49
- function isTokenUsage(value) {
50
- if (!isRecord(value)) {
51
- return false;
52
- }
53
- return typeof value.inputTokens === "number" && typeof value.outputTokens === "number" && typeof value.totalTokens === "number";
54
- }
55
- function isSessionInfo(value) {
56
- if (!isRecord(value)) {
57
- return false;
58
- }
59
- return (typeof value.threadId === "string" || value.threadId === null) && (typeof value.turnId === "string" || value.turnId === null) && typeof value.turnCount === "number" && (typeof value.sessionId === "string" || value.sessionId === null) && (!("exitClassification" in value) || value.exitClassification === void 0 || value.exitClassification === null || isSessionExitClassification(value.exitClassification));
60
- }
61
- function isNullableString(value) {
62
- return typeof value === "string" || value === null;
63
- }
64
- function isTurnEventBase(value) {
65
- return typeof value.startedAt === "string" && isNullableString(value.threadId) && isNullableString(value.turnId) && typeof value.turnCount === "number" && isNullableString(value.sessionId);
66
- }
67
- function isOrchestratorChannelEvent(value) {
68
- if (!isRecord(value)) {
69
- return false;
70
- }
71
- if (typeof value.issueId !== "string") {
72
- return false;
73
- }
74
- if (value.type === "codex_update") {
75
- if (typeof value.lastEventAt !== "string") {
76
- return false;
77
- }
78
- if ("event" in value && value.event !== void 0 && typeof value.event !== "string") {
79
- return false;
80
- }
81
- if ("tokenUsage" in value && value.tokenUsage !== void 0 && !isTokenUsage(value.tokenUsage)) {
82
- return false;
83
- }
84
- if ("rateLimits" in value && value.rateLimits !== void 0 && !isRecord(value.rateLimits)) {
85
- return false;
86
- }
87
- if ("sessionInfo" in value && value.sessionInfo !== void 0 && !isSessionInfo(value.sessionInfo)) {
88
- return false;
89
- }
90
- if ("executionPhase" in value && value.executionPhase !== void 0 && value.executionPhase !== null && !isWorkflowExecutionPhase(value.executionPhase)) {
91
- return false;
92
- }
93
- if ("runPhase" in value && value.runPhase !== void 0 && value.runPhase !== null && !isRunAttemptPhase(value.runPhase)) {
94
- return false;
95
- }
96
- if ("lastError" in value && value.lastError !== void 0 && value.lastError !== null && typeof value.lastError !== "string") {
97
- return false;
98
- }
99
- return true;
100
- }
101
- if (value.type === "heartbeat") {
102
- if (value.lastEventAt !== null && typeof value.lastEventAt !== "string") {
103
- return false;
104
- }
105
- if (!isTokenUsage(value.tokenUsage)) {
106
- return false;
107
- }
108
- if (value.rateLimits !== null && !isRecord(value.rateLimits)) {
109
- return false;
110
- }
111
- if (value.sessionInfo !== null && !isSessionInfo(value.sessionInfo)) {
112
- return false;
113
- }
114
- if (value.executionPhase !== null && !isWorkflowExecutionPhase(value.executionPhase)) {
115
- return false;
116
- }
117
- if (value.runPhase !== null && !isRunAttemptPhase(value.runPhase)) {
118
- return false;
119
- }
120
- if (value.lastError !== null && typeof value.lastError !== "string") {
121
- return false;
122
- }
123
- return true;
124
- }
125
- if (value.type === "turn_started") {
126
- return isTurnEventBase(value);
127
- }
128
- if (value.type === "turn_completed") {
129
- return isTurnEventBase(value) && typeof value.completedAt === "string" && typeof value.durationMs === "number" && isTokenUsage(value.tokenUsage);
130
- }
131
- if (value.type === "turn_failed") {
132
- return isTurnEventBase(value) && typeof value.failedAt === "string" && typeof value.durationMs === "number" && isTokenUsage(value.tokenUsage) && isNullableString(value.error);
133
- }
134
- return false;
135
- }
136
-
137
3
  // ../core/dist/workflow/lifecycle.js
138
4
  var DEFAULT_WORKFLOW_LIFECYCLE = {
139
5
  stateFieldName: "Status",
@@ -164,6 +30,7 @@ var DEFAULT_MAX_RETRY_BACKOFF_MS = 3e5;
164
30
  var DEFAULT_MAX_DELAY_MS = DEFAULT_MAX_RETRY_BACKOFF_MS;
165
31
  var DEFAULT_BASE_DELAY_MS = 1e4;
166
32
  var DEFAULT_MAX_TURNS = 20;
33
+ var DEFAULT_MAX_FAILURE_RETRIES = 10;
167
34
  var DEFAULT_READ_TIMEOUT_MS = 5e3;
168
35
  var DEFAULT_TURN_TIMEOUT_MS = 36e5;
169
36
  var DEFAULT_STALL_TIMEOUT_MS = 3e5;
@@ -194,6 +61,7 @@ var DEFAULT_WORKFLOW_AGENT = {
194
61
  maxConcurrentAgents: DEFAULT_MAX_CONCURRENT_AGENTS,
195
62
  maxRetryBackoffMs: DEFAULT_MAX_RETRY_BACKOFF_MS,
196
63
  maxConcurrentAgentsByState: {},
64
+ maxFailureRetries: DEFAULT_MAX_FAILURE_RETRIES,
197
65
  maxTurns: DEFAULT_MAX_TURNS,
198
66
  retryBaseDelayMs: DEFAULT_BASE_DELAY_MS
199
67
  };
@@ -282,6 +150,7 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
282
150
  maxConcurrentAgents: readOptionalIntegerLike(agent, "max_concurrent_agents") ?? DEFAULT_MAX_CONCURRENT_AGENTS,
283
151
  maxRetryBackoffMs: readOptionalIntegerLike(agent, "max_retry_backoff_ms") ?? DEFAULT_MAX_RETRY_BACKOFF_MS,
284
152
  maxConcurrentAgentsByState,
153
+ maxFailureRetries: readOptionalIntegerLike(agent, "max_failure_retries") ?? DEFAULT_MAX_FAILURE_RETRIES,
285
154
  maxTurns: readOptionalIntegerLike(agent, "max_turns") ?? DEFAULT_MAX_TURNS,
286
155
  retryBaseDelayMs: readOptionalIntegerLike(agent, "retry_base_delay_ms") ?? DEFAULT_BASE_DELAY_MS
287
156
  },
@@ -536,6 +405,207 @@ function matchOptionalSection(markdown, heading) {
536
405
  return match?.[1]?.trim() ?? null;
537
406
  }
538
407
 
408
+ // ../core/dist/contracts/status-surface.js
409
+ var WORKFLOW_EXECUTION_PHASES = [
410
+ "planning",
411
+ "human-review",
412
+ "implementation",
413
+ "awaiting-merge",
414
+ "completed"
415
+ ];
416
+ function isWorkflowExecutionPhase(value) {
417
+ return typeof value === "string" && WORKFLOW_EXECUTION_PHASES.includes(value);
418
+ }
419
+ var SESSION_EXIT_CLASSIFICATIONS = [
420
+ "completed",
421
+ "budget-exceeded",
422
+ "convergence-detected",
423
+ "max-turns-reached",
424
+ "user-input-required",
425
+ "timeout",
426
+ "error"
427
+ ];
428
+ function isSessionExitClassification(value) {
429
+ return typeof value === "string" && SESSION_EXIT_CLASSIFICATIONS.includes(value);
430
+ }
431
+
432
+ // ../core/dist/contracts/run-attempt-phase.js
433
+ var RUN_ATTEMPT_PHASES = [
434
+ "preparing_workspace",
435
+ "building_prompt",
436
+ "launching_agent",
437
+ "initializing_session",
438
+ "streaming_turn",
439
+ "finishing",
440
+ "succeeded",
441
+ "failed",
442
+ "timed_out",
443
+ "stalled",
444
+ "canceled_by_reconciliation"
445
+ ];
446
+ function isRunAttemptPhase(value) {
447
+ return typeof value === "string" && RUN_ATTEMPT_PHASES.includes(value);
448
+ }
449
+
450
+ // ../core/dist/contracts/orchestrator-channel.js
451
+ function isRecord(value) {
452
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
453
+ }
454
+ function isTokenUsage(value) {
455
+ if (!isRecord(value)) {
456
+ return false;
457
+ }
458
+ return typeof value.inputTokens === "number" && typeof value.outputTokens === "number" && typeof value.totalTokens === "number";
459
+ }
460
+ function isSessionInfo(value) {
461
+ if (!isRecord(value)) {
462
+ return false;
463
+ }
464
+ return (typeof value.threadId === "string" || value.threadId === null) && (typeof value.turnId === "string" || value.turnId === null) && typeof value.turnCount === "number" && (typeof value.sessionId === "string" || value.sessionId === null) && (!("exitClassification" in value) || value.exitClassification === void 0 || value.exitClassification === null || isSessionExitClassification(value.exitClassification));
465
+ }
466
+ function isNullableString(value) {
467
+ return typeof value === "string" || value === null;
468
+ }
469
+ function isTurnEventBase(value) {
470
+ return typeof value.startedAt === "string" && isNullableString(value.threadId) && isNullableString(value.turnId) && typeof value.turnCount === "number" && isNullableString(value.sessionId);
471
+ }
472
+ function isOrchestratorChannelEvent(value) {
473
+ if (!isRecord(value)) {
474
+ return false;
475
+ }
476
+ if (typeof value.issueId !== "string") {
477
+ return false;
478
+ }
479
+ if (value.type === "codex_update") {
480
+ if (typeof value.lastEventAt !== "string") {
481
+ return false;
482
+ }
483
+ if ("event" in value && value.event !== void 0 && typeof value.event !== "string") {
484
+ return false;
485
+ }
486
+ if ("tokenUsage" in value && value.tokenUsage !== void 0 && !isTokenUsage(value.tokenUsage)) {
487
+ return false;
488
+ }
489
+ if ("rateLimits" in value && value.rateLimits !== void 0 && !isRecord(value.rateLimits)) {
490
+ return false;
491
+ }
492
+ if ("sessionInfo" in value && value.sessionInfo !== void 0 && !isSessionInfo(value.sessionInfo)) {
493
+ return false;
494
+ }
495
+ if ("executionPhase" in value && value.executionPhase !== void 0 && value.executionPhase !== null && !isWorkflowExecutionPhase(value.executionPhase)) {
496
+ return false;
497
+ }
498
+ if ("runPhase" in value && value.runPhase !== void 0 && value.runPhase !== null && !isRunAttemptPhase(value.runPhase)) {
499
+ return false;
500
+ }
501
+ if ("lastError" in value && value.lastError !== void 0 && value.lastError !== null && typeof value.lastError !== "string") {
502
+ return false;
503
+ }
504
+ return true;
505
+ }
506
+ if (value.type === "heartbeat") {
507
+ if (value.lastEventAt !== null && typeof value.lastEventAt !== "string") {
508
+ return false;
509
+ }
510
+ if (!isTokenUsage(value.tokenUsage)) {
511
+ return false;
512
+ }
513
+ if (value.rateLimits !== null && !isRecord(value.rateLimits)) {
514
+ return false;
515
+ }
516
+ if (value.sessionInfo !== null && !isSessionInfo(value.sessionInfo)) {
517
+ return false;
518
+ }
519
+ if (value.executionPhase !== null && !isWorkflowExecutionPhase(value.executionPhase)) {
520
+ return false;
521
+ }
522
+ if (value.runPhase !== null && !isRunAttemptPhase(value.runPhase)) {
523
+ return false;
524
+ }
525
+ if (value.lastError !== null && typeof value.lastError !== "string") {
526
+ return false;
527
+ }
528
+ return true;
529
+ }
530
+ if (value.type === "turn_started") {
531
+ return isTurnEventBase(value);
532
+ }
533
+ if (value.type === "turn_completed") {
534
+ return isTurnEventBase(value) && typeof value.completedAt === "string" && typeof value.durationMs === "number" && isTokenUsage(value.tokenUsage);
535
+ }
536
+ if (value.type === "turn_failed") {
537
+ return isTurnEventBase(value) && typeof value.failedAt === "string" && typeof value.durationMs === "number" && isTokenUsage(value.tokenUsage) && isNullableString(value.error);
538
+ }
539
+ return false;
540
+ }
541
+
542
+ // ../core/dist/workflow/loader.js
543
+ import { createHash } from "crypto";
544
+ import { access, readFile, stat } from "fs/promises";
545
+ import { constants } from "fs";
546
+ var WorkflowConfigStore = class {
547
+ cache = /* @__PURE__ */ new Map();
548
+ async load(workflowPath, env = process.env) {
549
+ await access(workflowPath, constants.R_OK);
550
+ const fileStat = await stat(workflowPath);
551
+ const fingerprint = `${fileStat.mtimeMs}:${fileStat.size}`;
552
+ const cached = this.cache.get(workflowPath);
553
+ if (cached && cached.fingerprint === fingerprint) {
554
+ return toWorkflowResolution(workflowPath, cached.workflow, {
555
+ isValid: true,
556
+ usedLastKnownGood: false,
557
+ validationError: null
558
+ });
559
+ }
560
+ const markdown = await readFile(workflowPath, "utf8");
561
+ try {
562
+ const workflow = parseWorkflowMarkdown(markdown, env);
563
+ this.cache.set(workflowPath, {
564
+ fingerprint,
565
+ workflow,
566
+ loadedAt: (/* @__PURE__ */ new Date()).toISOString()
567
+ });
568
+ return toWorkflowResolution(workflowPath, workflow, {
569
+ isValid: true,
570
+ usedLastKnownGood: false,
571
+ validationError: null
572
+ });
573
+ } catch (error) {
574
+ if (cached) {
575
+ return toWorkflowResolution(workflowPath, cached.workflow, {
576
+ isValid: false,
577
+ usedLastKnownGood: true,
578
+ validationError: error instanceof Error ? error.message : "Invalid workflow definition."
579
+ });
580
+ }
581
+ throw error;
582
+ }
583
+ }
584
+ };
585
+ function createDefaultWorkflowResolution() {
586
+ return createInvalidWorkflowResolution(null, "missing_workflow_file");
587
+ }
588
+ function createInvalidWorkflowResolution(workflowPath, validationError) {
589
+ return toWorkflowResolution(workflowPath, DEFAULT_WORKFLOW_DEFINITION, {
590
+ isValid: false,
591
+ usedLastKnownGood: false,
592
+ validationError
593
+ });
594
+ }
595
+ function toWorkflowResolution(workflowPath, workflow, metadata) {
596
+ return {
597
+ workflowPath,
598
+ workflow,
599
+ lifecycle: workflow.lifecycle,
600
+ promptTemplate: workflow.promptTemplate,
601
+ agentCommand: workflow.agentCommand,
602
+ hookPath: workflow.hookPath ?? "",
603
+ isValid: metadata.isValid,
604
+ usedLastKnownGood: metadata.usedLastKnownGood,
605
+ validationError: metadata.validationError
606
+ };
607
+ }
608
+
539
609
  // ../core/dist/workflow/render.js
540
610
  import { Liquid, ParseError, RenderError, TokenizationError, UndefinedVariableError } from "liquidjs";
541
611
  function buildPromptVariables(issue, options) {
@@ -665,9 +735,12 @@ function readEnvFile(path) {
665
735
  }, {});
666
736
  }
667
737
 
738
+ // ../core/dist/workspace/safety.js
739
+ import { resolve } from "path";
740
+
668
741
  // ../core/dist/workspace/identity.js
669
- import { resolve, join } from "path";
670
- import { createHash } from "crypto";
742
+ import { resolve as resolve2, join } from "path";
743
+ import { createHash as createHash2 } from "crypto";
671
744
  function deriveIssueWorkspaceKey(identity, issueIdentifier) {
672
745
  if (issueIdentifier) {
673
746
  return deriveIssueWorkspaceKeyFromIdentifier(issueIdentifier);
@@ -687,11 +760,11 @@ function deriveLegacyIssueWorkspaceKey(identity) {
687
760
  identity.adapter,
688
761
  identity.issueSubjectId
689
762
  ].join(":");
690
- return createHash("sha256").update(input).digest("hex").slice(0, 16);
763
+ return createHash2("sha256").update(input).digest("hex").slice(0, 16);
691
764
  }
692
765
  function resolveIssueWorkspaceDirectory(projectDirectory, workspaceKey) {
693
- const normalizedProjectDirectory = resolve(projectDirectory);
694
- const candidate = resolve(normalizedProjectDirectory, "issues", workspaceKey);
766
+ const normalizedProjectDirectory = resolve2(projectDirectory);
767
+ const candidate = resolve2(normalizedProjectDirectory, "issues", workspaceKey);
695
768
  if (!candidate.startsWith(`${normalizedProjectDirectory}/`)) {
696
769
  throw new Error("Issue workspace path escapes the configured project directory.");
697
770
  }
@@ -836,6 +909,7 @@ function normalizeHookCommand(command) {
836
909
  // ../core/dist/observability/snapshot-builder.js
837
910
  function buildProjectSnapshot(input) {
838
911
  const { project, activeRuns, allRuns, summary, lastTickAt, lastError, rateLimits } = input;
912
+ const cumulativeTokenUsageByIssue = aggregateTokenUsageByIssue(allRuns ?? activeRuns);
839
913
  return {
840
914
  projectId: project.projectId,
841
915
  slug: project.slug,
@@ -867,7 +941,7 @@ function buildProjectSnapshot(input) {
867
941
  lastEventAt: run.lastEventAt ?? null,
868
942
  executionPhase: run.executionPhase ?? null,
869
943
  runPhase: run.runPhase ?? null,
870
- tokenUsage: run.tokenUsage
944
+ tokenUsage: attachCumulativeTokenUsage(run.tokenUsage, cumulativeTokenUsageByIssue.get(run.issueId))
871
945
  })),
872
946
  retryQueue: activeRuns.filter((run) => run.status === "retrying" && run.retryKind).map((run) => ({
873
947
  runId: run.runId,
@@ -880,6 +954,35 @@ function buildProjectSnapshot(input) {
880
954
  rateLimits: rateLimits ?? null
881
955
  };
882
956
  }
957
+ function aggregateTokenUsageByIssue(runs) {
958
+ const totals = /* @__PURE__ */ new Map();
959
+ for (const run of runs) {
960
+ if (!run.tokenUsage) {
961
+ continue;
962
+ }
963
+ const current = totals.get(run.issueId) ?? {
964
+ inputTokens: 0,
965
+ outputTokens: 0,
966
+ totalTokens: 0
967
+ };
968
+ current.inputTokens += run.tokenUsage.inputTokens;
969
+ current.outputTokens += run.tokenUsage.outputTokens;
970
+ current.totalTokens += run.tokenUsage.totalTokens;
971
+ totals.set(run.issueId, current);
972
+ }
973
+ return totals;
974
+ }
975
+ function attachCumulativeTokenUsage(tokenUsage, cumulative) {
976
+ if (!tokenUsage) {
977
+ return void 0;
978
+ }
979
+ return {
980
+ ...tokenUsage,
981
+ cumulativeInputTokens: cumulative?.inputTokens ?? tokenUsage.inputTokens,
982
+ cumulativeOutputTokens: cumulative?.outputTokens ?? tokenUsage.outputTokens,
983
+ cumulativeTotalTokens: cumulative?.totalTokens ?? tokenUsage.totalTokens
984
+ };
985
+ }
883
986
  function aggregateTokenUsage(runs, lastTickAt) {
884
987
  let inputTokens = 0;
885
988
  let outputTokens = 0;
@@ -908,10 +1011,10 @@ function aggregateTokenUsage(runs, lastTickAt) {
908
1011
  }
909
1012
 
910
1013
  // ../core/dist/observability/fs-reader.js
911
- import { readFile, readdir } from "fs/promises";
1014
+ import { readFile as readFile2, readdir } from "fs/promises";
912
1015
  async function readJsonFile(path) {
913
1016
  try {
914
- const raw = await readFile(path, "utf8");
1017
+ const raw = await readFile2(path, "utf8");
915
1018
  return JSON.parse(raw);
916
1019
  } catch (error) {
917
1020
  if (isFileMissing(error)) {
@@ -1020,82 +1123,13 @@ function mapIssueOrchestrationStateToStatus(state) {
1020
1123
  }
1021
1124
  }
1022
1125
 
1023
- // ../core/dist/workflow/loader.js
1024
- import { createHash as createHash2 } from "crypto";
1025
- import { access, readFile as readFile2, stat } from "fs/promises";
1026
- import { constants } from "fs";
1027
- var WorkflowConfigStore = class {
1028
- cache = /* @__PURE__ */ new Map();
1029
- async load(workflowPath, env = process.env) {
1030
- await access(workflowPath, constants.R_OK);
1031
- const fileStat = await stat(workflowPath);
1032
- const fingerprint = `${fileStat.mtimeMs}:${fileStat.size}`;
1033
- const cached = this.cache.get(workflowPath);
1034
- if (cached && cached.fingerprint === fingerprint) {
1035
- return toWorkflowResolution(workflowPath, cached.workflow, {
1036
- isValid: true,
1037
- usedLastKnownGood: false,
1038
- validationError: null
1039
- });
1040
- }
1041
- const markdown = await readFile2(workflowPath, "utf8");
1042
- try {
1043
- const workflow = parseWorkflowMarkdown(markdown, env);
1044
- this.cache.set(workflowPath, {
1045
- fingerprint,
1046
- workflow,
1047
- loadedAt: (/* @__PURE__ */ new Date()).toISOString()
1048
- });
1049
- return toWorkflowResolution(workflowPath, workflow, {
1050
- isValid: true,
1051
- usedLastKnownGood: false,
1052
- validationError: null
1053
- });
1054
- } catch (error) {
1055
- if (cached) {
1056
- return toWorkflowResolution(workflowPath, cached.workflow, {
1057
- isValid: false,
1058
- usedLastKnownGood: true,
1059
- validationError: error instanceof Error ? error.message : "Invalid workflow definition."
1060
- });
1061
- }
1062
- throw error;
1063
- }
1064
- }
1065
- };
1066
- function createDefaultWorkflowResolution() {
1067
- return createInvalidWorkflowResolution(null, "missing_workflow_file");
1068
- }
1069
- function createInvalidWorkflowResolution(workflowPath, validationError) {
1070
- return toWorkflowResolution(workflowPath, DEFAULT_WORKFLOW_DEFINITION, {
1071
- isValid: false,
1072
- usedLastKnownGood: false,
1073
- validationError
1074
- });
1075
- }
1076
- function toWorkflowResolution(workflowPath, workflow, metadata) {
1077
- return {
1078
- workflowPath,
1079
- workflow,
1080
- lifecycle: workflow.lifecycle,
1081
- promptTemplate: workflow.promptTemplate,
1082
- agentCommand: workflow.agentCommand,
1083
- hookPath: workflow.hookPath ?? "",
1084
- isValid: metadata.isValid,
1085
- usedLastKnownGood: metadata.usedLastKnownGood,
1086
- validationError: metadata.validationError
1087
- };
1088
- }
1089
-
1090
- // ../core/dist/workspace/safety.js
1091
- import { resolve as resolve2 } from "path";
1092
-
1093
1126
  export {
1094
1127
  isOrchestratorChannelEvent,
1095
1128
  DEFAULT_WORKFLOW_LIFECYCLE,
1096
1129
  isStateActive,
1097
1130
  isStateTerminal,
1098
1131
  matchesWorkflowState,
1132
+ DEFAULT_MAX_FAILURE_RETRIES,
1099
1133
  parseWorkflowMarkdown,
1100
1134
  WorkflowConfigStore,
1101
1135
  createDefaultWorkflowResolution,
@@ -19,7 +19,7 @@ import {
19
19
  import {
20
20
  handleMissingManagedProjectConfig,
21
21
  resolveManagedProjectConfig
22
- } from "./chunk-TH5QPO3Y.js";
22
+ } from "./chunk-C7G7RJ4G.js";
23
23
 
24
24
  // src/commands/status.ts
25
25
  import { readFile } from "fs/promises";
@@ -30,7 +30,7 @@ var COL_ID = 24;
30
30
  var COL_STATUS = 14;
31
31
  var COL_PID = 8;
32
32
  var COL_AGE_TURN = 12;
33
- var COL_TOKENS = 10;
33
+ var COL_TOKENS = 17;
34
34
  var COL_SESSION = 14;
35
35
  var COL_ID_HEADER = COL_ID + 2;
36
36
  var identity = (s) => s;
@@ -63,6 +63,11 @@ function compactSessionId(id) {
63
63
  function fmtTokens(n) {
64
64
  return n.toLocaleString("en-US");
65
65
  }
66
+ function fmtTokenPair(delta, cumulative) {
67
+ const left = fmtTokens(delta ?? 0);
68
+ const right = fmtTokens(cumulative ?? delta ?? 0);
69
+ return `${left} / ${right}`;
70
+ }
66
71
  function fmtAge(startedAt, now) {
67
72
  if (!startedAt) return "0m";
68
73
  const diffMs = now - new Date(startedAt).getTime();
@@ -173,7 +178,10 @@ function activeRunRow(run, now, evtWidth, c) {
173
178
  const turn = run.turnCount ?? 0;
174
179
  const ageTurn = pad(`${age}/${turn}`, COL_AGE_TURN);
175
180
  const tokens = pad(
176
- fmtTokens(run.tokenUsage?.totalTokens ?? 0),
181
+ fmtTokenPair(
182
+ run.tokenUsage?.totalTokens,
183
+ run.tokenUsage?.cumulativeTotalTokens
184
+ ),
177
185
  COL_TOKENS,
178
186
  "right"
179
187
  );
@@ -260,6 +268,15 @@ function truncate(s, len) {
260
268
  if (s.length <= len) return s;
261
269
  return s.slice(0, len - 3) + "...";
262
270
  }
271
+ function formatTokenPair(delta, cumulative) {
272
+ return `${delta.toLocaleString("en-US")} / ${cumulative.toLocaleString("en-US")}`;
273
+ }
274
+ function resolveProjectTokenDelta(snapshot) {
275
+ return snapshot.activeRuns.reduce(
276
+ (sum, run) => sum + (run.tokenUsage?.totalTokens ?? 0),
277
+ 0
278
+ );
279
+ }
263
280
  function renderLegacyStatus(snapshot, noColor) {
264
281
  const apply = noColor ? (s) => stripAnsi(s) : (s) => s;
265
282
  const lines = [];
@@ -326,12 +343,13 @@ function renderLegacyStatus(snapshot, noColor) {
326
343
  lines.push("");
327
344
  }
328
345
  if (snapshot.codexTotals) {
346
+ const tokenDelta = resolveProjectTokenDelta(snapshot);
329
347
  const tokenStr = apply(
330
- `Tokens: ${snapshot.codexTotals.inputTokens} in / ${snapshot.codexTotals.outputTokens} out / ${snapshot.codexTotals.totalTokens} total`
348
+ `Tokens: ${formatTokenPair(tokenDelta, snapshot.codexTotals.totalTokens)} total`
331
349
  );
332
350
  lines.push(` ${tokenStr}`);
333
351
  } else {
334
- lines.push(" Tokens: 0 in / 0 out / 0 total");
352
+ lines.push(" Tokens: 0 / 0 total");
335
353
  }
336
354
  return lines.join("\n");
337
355
  }
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  handleMissingManagedProjectConfig,
4
4
  resolveManagedProjectConfig
5
- } from "./chunk-TH5QPO3Y.js";
5
+ } from "./chunk-C7G7RJ4G.js";
6
6
  import {
7
7
  daemonPidPath
8
8
  } from "./chunk-ROGRTUFI.js";