@ai-sdk/harness 1.0.0-canary.6 → 1.0.0-canary.8

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @ai-sdk/harness
2
2
 
3
+ ## 1.0.0-canary.8
4
+
5
+ ### Patch Changes
6
+
7
+ - aae0138: fix(harness): make listening for sandbox bridge readiness compatible with Bun
8
+
9
+ ## 1.0.0-canary.7
10
+
11
+ ### Patch Changes
12
+
13
+ - 3d87086: fix(harness): guard against invalid resuming a session vs continuing a turn
14
+ - 1ea15a3: fix(harness): fix various bugs with harness skills not being correctly processed by the harness adapters
15
+ - Updated dependencies [aeda373]
16
+ - Updated dependencies [25a64f8]
17
+ - Updated dependencies [375fdd7]
18
+ - Updated dependencies [f18b08f]
19
+ - Updated dependencies [b4507d5]
20
+ - @ai-sdk/provider-utils@5.0.0-canary.48
21
+ - ai@7.0.0-canary.172
22
+
3
23
  ## 1.0.0-canary.6
4
24
 
5
25
  ### Patch Changes
@@ -381,12 +381,6 @@ type HarnessV1LifecycleStateBase = {
381
381
  * responsible for any necessary encoding.
382
382
  */
383
383
  readonly data: JSONValue;
384
- /**
385
- * Framework-owned pending approval records. These are intentionally outside
386
- * adapter-defined `data` so callers can persist the entire lifecycle payload
387
- * without the harness framework owning storage.
388
- */
389
- readonly pendingToolApprovals?: readonly HarnessV1PendingToolApproval[];
390
384
  };
391
385
  /**
392
386
  * Opaque payload returned by between-turn session lifecycle methods and
@@ -395,6 +389,11 @@ type HarnessV1LifecycleStateBase = {
395
389
  */
396
390
  type HarnessV1ResumeSessionState = HarnessV1LifecycleStateBase & {
397
391
  readonly type: 'resume-session';
392
+ /**
393
+ * Optional unfinished-turn state. When present, the session must be resumed
394
+ * before the turn is continued.
395
+ */
396
+ readonly continueFrom?: HarnessV1ContinueTurnState;
398
397
  };
399
398
  /**
400
399
  * Opaque payload returned by `doSuspendTurn` and accepted by a future
@@ -403,28 +402,45 @@ type HarnessV1ResumeSessionState = HarnessV1LifecycleStateBase & {
403
402
  */
404
403
  type HarnessV1ContinueTurnState = HarnessV1LifecycleStateBase & {
405
404
  readonly type: 'continue-turn';
405
+ /**
406
+ * Framework-owned pending approval records. These are intentionally outside
407
+ * adapter-defined `data` so callers can persist the entire lifecycle payload
408
+ * without the harness framework owning storage.
409
+ */
410
+ readonly pendingToolApprovals?: readonly HarnessV1PendingToolApproval[];
406
411
  };
407
412
  type HarnessV1LifecycleState = HarnessV1ResumeSessionState | HarnessV1ContinueTurnState;
408
413
 
409
414
  /**
410
415
  * A self-contained instruction bundle the underlying runtime can load into
411
- * its context. Adapters decide how to surface skills to the runtime — the
412
- * `claude` CLI auto-discovers skills materialised as Markdown files in
413
- * `.claude/skills`, while the `codex` CLI has no skill mechanism and the
414
- * adapter inlines them into every user message.
416
+ * its context. Adapters decide how to surface skills to the runtime.
415
417
  */
416
418
  type HarnessV1Skill = {
417
419
  /** Stable identifier for the skill (kebab-case slug). */
418
420
  readonly name: string;
419
421
  /**
420
- * Short, model-facing description. For runtimes that auto-select skills
421
- * (Claude Code), this is what the runtime sees to decide whether the
422
- * skill is relevant; for runtimes that load every skill on every turn
423
- * (Codex), it appears alongside the content.
422
+ * Short, model-facing description. This is what the runtime sees to
423
+ * decide whether the skill is relevant.
424
424
  */
425
425
  readonly description: string;
426
426
  /** Full skill content the model loads when the skill is active. */
427
427
  readonly content: string;
428
+ /**
429
+ * Additional files that belong to this skill. Adapters with native skill
430
+ * directories materialize these next to `SKILL.md`; adapters without native
431
+ * skill files include them with the skill content.
432
+ */
433
+ readonly files?: ReadonlyArray<HarnessV1SkillFile>;
434
+ };
435
+ type HarnessV1SkillFile = {
436
+ /**
437
+ * Skill-relative POSIX path, for example `reference.md` or
438
+ * `references/codes.md`. Absolute paths and `..` segments are rejected by
439
+ * adapters before writing.
440
+ */
441
+ readonly path: string;
442
+ /** UTF-8 text content for the file. */
443
+ readonly content: string;
428
444
  };
429
445
 
430
446
  /**
@@ -585,21 +601,19 @@ type HarnessV1StartOptions = {
585
601
  readonly sessionId: string;
586
602
  /**
587
603
  * Skills made available to the underlying runtime for the lifetime of
588
- * the session. Adapters decide how to surface them — the `claude` CLI
589
- * picks them up from `.claude/skills/*.md`, while the `codex` adapter
590
- * inlines them into every user message.
604
+ * the session. Adapters decide how to surface them.
591
605
  */
592
606
  readonly skills?: ReadonlyArray<HarnessV1Skill>;
593
607
  /**
594
- * Optional resume payload returned by a prior between-turn session lifecycle
595
- * method. When provided, the adapter should resume the existing session before
596
- * accepting a new prompt.
608
+ * Optional resume payload returned by a prior session lifecycle method. When
609
+ * provided, the adapter should resume the existing session before accepting a
610
+ * new prompt or continuing a nested unfinished turn.
597
611
  */
598
612
  readonly resumeFrom?: HarnessV1ResumeSessionState;
599
613
  /**
600
- * Optional continuation payload returned by `doSuspendTurn`. When provided,
601
- * the adapter should resume the existing session in a shape ready for
602
- * `doContinueTurn` rather than for a fresh prompt.
614
+ * Optional continuation payload returned by `doSuspendTurn`, or nested in
615
+ * `resumeFrom`. When provided, the adapter should resume the existing session
616
+ * in a shape ready for `doContinueTurn` rather than for a fresh prompt.
603
617
  */
604
618
  readonly continueFrom?: HarnessV1ContinueTurnState;
605
619
  /**
@@ -1151,6 +1165,7 @@ type HarnessAgentTurnResult<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Conte
1151
1165
  result: StreamTextResult<TOOLS, RUNTIME_CONTEXT, never>;
1152
1166
  done: Promise<void>;
1153
1167
  };
1168
+ type HarnessAgentTurnState = 'idle' | 'running' | 'awaiting-approval' | 'suspended';
1154
1169
  /**
1155
1170
  * Live harness session held by the caller.
1156
1171
  *
@@ -1180,7 +1195,10 @@ declare class HarnessAgentSession {
1180
1195
  private leasedBridgePort;
1181
1196
  private readonly toolApproval;
1182
1197
  private readonly pendingToolApprovals;
1183
- private stopped;
1198
+ private sessionState;
1199
+ private turnState;
1200
+ private turnSequence;
1201
+ private activeTurnSequence;
1184
1202
  /**
1185
1203
  * Whether this session was created from `resumeFrom` or `continueFrom`.
1186
1204
  * Captured at construction so it survives lifecycle cleanup.
@@ -1196,6 +1214,7 @@ declare class HarnessAgentSession {
1196
1214
  sessionWorkDir: string;
1197
1215
  toolApproval: HarnessAgentToolApprovalConfiguration | undefined;
1198
1216
  pendingToolApprovals?: readonly HarnessAgentPendingToolApproval[];
1217
+ turnState?: HarnessAgentTurnState;
1199
1218
  });
1200
1219
  promptTurn<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context>(options: {
1201
1220
  prompt: HarnessAgentPrompt;
@@ -1247,11 +1266,11 @@ declare class HarnessAgentSession {
1247
1266
  /**
1248
1267
  * Gracefully freeze the active turn at the slice boundary and return the
1249
1268
  * continuation payload, **leaving the sandbox/runtime running** so the next
1250
- * process can continue. Resolves once the in-flight `stream()`/`continueTurn()`
1251
- * has cleanly wound down at a precise cursor (see
1269
+ * process can continue. Resolves once the in-flight `stream()` /
1270
+ * `continueStream()` has cleanly wound down at a precise cursor (see
1252
1271
  * `doSuspendTurn`).
1253
1272
  *
1254
- * After this call the session is marked stopped. This in-process handle no
1273
+ * After this call the session is detached. This in-process handle no
1255
1274
  * longer drives turns; a future slice creates a fresh session from the
1256
1275
  * returned state. The sandbox is **not** stopped and no port lease is
1257
1276
  * released, because bridge-backed adapters may still have a live bridge on
@@ -1259,7 +1278,15 @@ declare class HarnessAgentSession {
1259
1278
  */
1260
1279
  suspendTurn(): Promise<HarnessAgentContinueTurnState>;
1261
1280
  private getPendingToolApprovals;
1262
- private withPendingToolApprovals;
1281
+ private addPendingToolApprovals;
1282
+ private suspendCurrentTurn;
1283
+ private toResumeStateWithContinuation;
1284
+ private requirePromptableTurn;
1285
+ private requireContinuableTurn;
1286
+ private markAwaitingApprovalIfActive;
1287
+ private startTrackedTurn;
1288
+ private trackTurnCompletion;
1289
+ private finishTrackedTurn;
1263
1290
  private endLocalHandle;
1264
1291
  private releasePortLease;
1265
1292
  private requireReusableSession;
@@ -1304,7 +1331,8 @@ interface HarnessAgentCallExtensions {
1304
1331
  * `session.stop()`. The framework validates `resumeFrom` against the
1305
1332
  * harness's `lifecycleStateSchema` before handing it to the adapter.
1306
1333
  * `createSession({ sessionId, continueFrom })` resumes from state returned
1307
- * by `session.suspendTurn()` before `continueTurn()`.
1334
+ * by `session.suspendTurn()` before `continueStream()` /
1335
+ * `continueGenerate()`.
1308
1336
  * - **Host tool execution.** User tools passed in `settings.tools` are
1309
1337
  * executed on the host whenever the underlying runtime calls them;
1310
1338
  * the result is fed back to the harness via `submitToolResult`.
@@ -1365,6 +1393,16 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1365
1393
  }): Promise<HarnessAgentSession>;
1366
1394
  generate(options: AgentCallParameters<never, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT> & HarnessAgentCallExtensions): Promise<GenerateTextResult<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT, never>>;
1367
1395
  stream(options: AgentStreamParameters<never, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT> & HarnessAgentCallExtensions): Promise<StreamTextResult<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT, never>>;
1396
+ /**
1397
+ * Continue the in-flight turn **without a new prompt**, draining it like
1398
+ * {@link generate}. Used after `createSession({ continueFrom })` to finish
1399
+ * consuming a turn that crossed a process boundary.
1400
+ */
1401
+ continueGenerate(options: {
1402
+ session: HarnessAgentSession;
1403
+ toolApprovalContinuations?: readonly HarnessAgentToolApprovalContinuation[];
1404
+ abortSignal?: AbortSignal;
1405
+ }): Promise<GenerateTextResult<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT, never>>;
1368
1406
  /**
1369
1407
  * Continue the in-flight turn **without a new prompt**, streaming its events
1370
1408
  * like {@link stream}. Used to keep consuming a turn that is still running
@@ -1373,7 +1411,7 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1373
1411
  * `doContinueTurn`; what it can guarantee (lossless attach vs. lossy rerun)
1374
1412
  * follows from how the adapter resumed the session.
1375
1413
  */
1376
- continueTurn(options: {
1414
+ continueStream(options: {
1377
1415
  session: HarnessAgentSession;
1378
1416
  toolApprovalContinuations?: readonly HarnessAgentToolApprovalContinuation[];
1379
1417
  abortSignal?: AbortSignal;