@yaag/extension 0.6.2 → 0.8.0

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.
@@ -64,11 +64,14 @@ function resumeHint(record: RunRecord): string {
64
64
  // backslash, or a newline, and the hint must stay a call the model can copy.
65
65
  const resume = JSON.stringify(artifact);
66
66
  const { launch } = record;
67
+ // The Run Config path goes with the hint, so a copied call reads the same
68
+ // config layers the stopped Run read (ADR-0040).
69
+ const config = launch.config === undefined ? "" : `, config: ${JSON.stringify(launch.config)}`;
67
70
  switch (launch.kind) {
68
71
  case "inline":
69
- return ` Resume it with yaag_run({ resume: ${resume} }) and no file and no script; yaag reuses the program source it stored.`;
72
+ return ` Resume it with yaag_run({ resume: ${resume}${config} }) and no file and no script; yaag reuses the program source it stored.`;
70
73
  case "file":
71
- return ` Resume it with yaag_run({ file: ${JSON.stringify(launch.file)}, resume: ${resume} }).`;
74
+ return ` Resume it with yaag_run({ file: ${JSON.stringify(launch.file)}, resume: ${resume}${config} }).`;
72
75
  default: {
73
76
  const never: never = launch;
74
77
  return never;
@@ -2,6 +2,7 @@ import type {
2
2
  AgentActivity,
3
3
  AgentInfo,
4
4
  LifecycleEvent,
5
+ ModelFallbackInfo,
5
6
  NodeInfo,
6
7
  RunSummary,
7
8
  TokenBreakdown,
@@ -58,7 +59,8 @@ function isSummaryBase(value: Record<string, unknown>): boolean {
58
59
  nullableTokens(value.tokens) &&
59
60
  typeof value.incomplete === "boolean" &&
60
61
  natural(value.durationMs) &&
61
- natural(value.worstFrameGapMs)
62
+ natural(value.worstFrameGapMs) &&
63
+ (value.modelFallbacks === undefined || natural(value.modelFallbacks))
62
64
  );
63
65
  }
64
66
 
@@ -78,9 +80,11 @@ function normalizeAgents(value: RunSummary): RunSummary {
78
80
  ...agent,
79
81
  nodes: agent.nodes ?? [],
80
82
  finishedNodesPruned: agent.finishedNodesPruned ?? 0,
83
+ modelFallbacks: agent.modelFallbacks ?? [],
84
+ modelFallbacksPruned: agent.modelFallbacksPruned ?? 0,
81
85
  };
82
86
  }
83
- return { ...value, agents };
87
+ return { ...value, agents, modelFallbacks: value.modelFallbacks ?? 0 };
84
88
  }
85
89
 
86
90
  function optionalNodes(value: unknown): boolean {
@@ -103,6 +107,24 @@ function isNodeState(value: unknown): boolean {
103
107
  return value === "running" || value === "exited" || value === "failed";
104
108
  }
105
109
 
110
+ function optionalFallbacks(value: unknown): boolean {
111
+ return value === undefined || (Array.isArray(value) && value.every(isFallback));
112
+ }
113
+
114
+ function isFallback(value: unknown): value is ModelFallbackInfo {
115
+ return (
116
+ isRecord(value) &&
117
+ strings(value.failedModel, value.resolvedModel) &&
118
+ isReason(value.reason) &&
119
+ natural(value.attempt) &&
120
+ nullableNumber(value.at)
121
+ );
122
+ }
123
+
124
+ function isReason(value: unknown): boolean {
125
+ return value === "not_found" || value === "auth" || value === "rate_limited";
126
+ }
127
+
106
128
  function optionalNodeUsage(value: unknown): boolean {
107
129
  if (value === undefined) return true;
108
130
  if (!isRecord(value)) return false;
@@ -142,7 +164,9 @@ function isAgentBase(value: Record<string, unknown>): boolean {
142
164
  nullableNumber(value.usageUpdatedAt) &&
143
165
  nullableNumber(value.askStartedAt) &&
144
166
  optionalNodes(value.nodes) &&
145
- (value.finishedNodesPruned === undefined || natural(value.finishedNodesPruned))
167
+ (value.finishedNodesPruned === undefined || natural(value.finishedNodesPruned)) &&
168
+ optionalFallbacks(value.modelFallbacks) &&
169
+ (value.modelFallbacksPruned === undefined || natural(value.modelFallbacksPruned))
146
170
  );
147
171
  }
148
172
 
@@ -191,6 +215,12 @@ function isEvent(value: unknown): value is LifecycleEvent {
191
215
  typeof value.ok === "boolean" &&
192
216
  (value.maxFrameGapMs === undefined || natural(value.maxFrameGapMs))
193
217
  );
218
+ case "model_fallback":
219
+ return (
220
+ strings(value.agent, value.failedModel, value.resolvedModel) &&
221
+ natural(value.attempt) &&
222
+ isReason(value.reason)
223
+ );
194
224
  case "agent_usage":
195
225
  return strings(value.agent) && isTokens(value.tokens) && number(value.cost);
196
226
  case "agent_exit":