@ai-sdk/harness-pi 1.0.94 → 1.0.96

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,31 @@
1
1
  # @ai-sdk/harness-pi
2
2
 
3
+ ## 1.0.96
4
+
5
+ ### Patch Changes
6
+
7
+ - 8961fde: feat(harness): allow changing `model` between turns via call options
8
+ - Updated dependencies [8961fde]
9
+ - Updated dependencies [eb59f2a]
10
+ - @ai-sdk/harness@1.0.94
11
+ - @ai-sdk/provider-utils@5.0.34
12
+
13
+ ## 1.0.95
14
+
15
+ ### Patch Changes
16
+
17
+ - f7fa993: fix(harness-pi): allow configuring Pi sessions with the `max` thinking level
18
+ - 7608210: feat(harness): add `model` parameter to `HarnessAgent` instead of having each harness adapter support it on their own constructor functions
19
+ - f7bd978: chore(harness): update underlying adapter SDKs to their latest versions
20
+ - 14d4fc0: feat(harness): allow changing harness settings between turns via `prepareCall()` support on `HarnessAgent`
21
+ - Updated dependencies [cc9f6ce]
22
+ - Updated dependencies [7608210]
23
+ - Updated dependencies [6f8a2d7]
24
+ - Updated dependencies [14d4fc0]
25
+ - Updated dependencies [90192f1]
26
+ - @ai-sdk/harness@1.0.93
27
+ - @ai-sdk/provider-utils@5.0.33
28
+
3
29
  ## 1.0.94
4
30
 
5
31
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import { ExtensionFactory } from '@earendil-works/pi-coding-agent';
8
8
  */
9
9
  type PiAuthenticationMode = HarnessV1Authentication<'openai' | 'anthropic' | 'custom'>;
10
10
 
11
- type PiThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
11
+ type PiThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
12
12
 
13
13
  /**
14
14
  * Configuration knobs for `createPi`. Pi runs as an in-process Node library
@@ -21,6 +21,8 @@ type PiHarnessSettings = {
21
21
  * Pi model id (or name). Leaving this unset falls back to the AI Gateway
22
22
  * default when `AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN` is set, and to
23
23
  * Pi's own resolution otherwise.
24
+ *
25
+ * @deprecated Use `model` on `HarnessAgent` instead.
24
26
  */
25
27
  readonly model?: string;
26
28
  /**
package/dist/index.js CHANGED
@@ -134,7 +134,7 @@ import {
134
134
  import { access } from "fs/promises";
135
135
 
136
136
  // src/version.ts
137
- var VERSION = true ? "1.0.94" : "0.0.0-test";
137
+ var VERSION = true ? "1.0.96" : "0.0.0-test";
138
138
 
139
139
  // src/pi-auth.ts
140
140
  var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
@@ -984,7 +984,7 @@ function createPiRemoteOps(options) {
984
984
  import path4 from "path";
985
985
  import { writeSkills } from "@ai-sdk/harness/utils";
986
986
  async function writePiSkills(args) {
987
- await writeSkills({
987
+ return writeSkills({
988
988
  sandbox: args.sandbox,
989
989
  rootDir: path4.posix.join(args.sandboxHomeDir, ".agents", "skills"),
990
990
  skills: args.skills,
@@ -1959,21 +1959,12 @@ async function createPiSession(input) {
1959
1959
  sessionId: input.sessionId
1960
1960
  });
1961
1961
  const permissionMode = input.permissionMode ?? "allow-all";
1962
- let sandboxSkillRootDir;
1962
+ const sandboxSkillRootDir = path7.posix.join(
1963
+ sandboxHomeDir,
1964
+ ".agents",
1965
+ "skills"
1966
+ );
1963
1967
  let harnessSkills = [];
1964
- if (input.skills.length > 0) {
1965
- sandboxSkillRootDir = path7.posix.join(sandboxHomeDir, ".agents", "skills");
1966
- harnessSkills = createHarnessPiSkills({
1967
- skills: input.skills,
1968
- sandboxSkillRootDir
1969
- });
1970
- await writePiSkills({
1971
- sandbox: toolSafeSandboxSession,
1972
- sandboxHomeDir,
1973
- skills: input.skills,
1974
- ...input.abortSignal ? { abortSignal: input.abortSignal } : {}
1975
- });
1976
- }
1977
1968
  let resumeSessionFilePath;
1978
1969
  if (input.isResume && input.resumeSessionFileName) {
1979
1970
  const resumeSessionFileName = safePiSessionFileName(
@@ -1997,7 +1988,7 @@ async function createPiSession(input) {
1997
1988
  const paths = createPiPathMapper({
1998
1989
  hostWorkDir,
1999
1990
  sandboxWorkDir: sessionWorkDir,
2000
- readableRoots: sandboxSkillRootDir ? [{ sandboxDir: sandboxSkillRootDir }] : []
1991
+ readableRoots: [{ sandboxDir: sandboxSkillRootDir }]
2001
1992
  });
2002
1993
  const agentDir = input.agentDir ?? hostAgentDir;
2003
1994
  const modelRuntime = await createPiModelRuntime({
@@ -2024,7 +2015,7 @@ async function createPiSession(input) {
2024
2015
  modelRegistry,
2025
2016
  env: resolverEnv
2026
2017
  });
2027
- const resolvedModel = resolveModel(input.settings.model);
2018
+ let activeResolvedModel = resolveModel(input.settings.model);
2028
2019
  const mcpServers = resolvePiMcpServers({
2029
2020
  mcpServers: input.settings.mcpServers
2030
2021
  });
@@ -2249,6 +2240,8 @@ async function createPiSession(input) {
2249
2240
  try {
2250
2241
  const control = await runTurn({
2251
2242
  text: "",
2243
+ ...continueOpts.model ? { model: continueOpts.model } : {},
2244
+ skills: continueOpts.skills,
2252
2245
  tools: continueOpts.tools ?? [],
2253
2246
  instructions: continueOpts.instructions,
2254
2247
  emit: continueOpts.emit,
@@ -2427,7 +2420,7 @@ async function createPiSession(input) {
2427
2420
  customTools,
2428
2421
  ...hasMcpServers ? { noTools: "builtin" } : { tools: toolNames },
2429
2422
  ...input.settings.thinkingLevel ? { thinkingLevel: input.settings.thinkingLevel } : {},
2430
- ...resolvedModel ? { model: resolvedModel } : {}
2423
+ ...activeResolvedModel ? { model: activeResolvedModel } : {}
2431
2424
  });
2432
2425
  piSession = session;
2433
2426
  if (hasMcpServers) {
@@ -2460,6 +2453,19 @@ async function createPiSession(input) {
2460
2453
  if (stopped) {
2461
2454
  throw new Error("Pi session has been stopped.");
2462
2455
  }
2456
+ const skillWriteResult = await writePiSkills({
2457
+ sandbox: toolSafeSandboxSession,
2458
+ sandboxHomeDir,
2459
+ skills: turnOpts.skills,
2460
+ abortSignal: turnOpts.abortSignal
2461
+ });
2462
+ harnessSkills = createHarnessPiSkills({
2463
+ skills: turnOpts.skills,
2464
+ sandboxSkillRootDir
2465
+ });
2466
+ if (piSession != null && skillWriteResult.changed) {
2467
+ await reloadResourcesOnly();
2468
+ }
2463
2469
  const userTools = turnOpts.tools;
2464
2470
  currentEmit = turnOpts.emit;
2465
2471
  const turnAbortController = new AbortController();
@@ -2478,6 +2484,8 @@ async function createPiSession(input) {
2478
2484
  await applySessionInstructions(turnOpts.instructions);
2479
2485
  turnAbortController.signal.throwIfAborted();
2480
2486
  const didAppendDeliveredHostToolResults = appendDeliveredHostToolResults();
2487
+ const nextModel = turnOpts.model == null ? void 0 : resolveModel(turnOpts.model);
2488
+ if (nextModel != null) activeResolvedModel = nextModel;
2481
2489
  const signature = JSON.stringify(userTools.map((t) => t.name).sort());
2482
2490
  const needsRebuild = piSession == null || signature !== lastToolsSignature;
2483
2491
  let resourcesReloaded = false;
@@ -2488,6 +2496,9 @@ async function createPiSession(input) {
2488
2496
  );
2489
2497
  turnAbortController.signal.throwIfAborted();
2490
2498
  lastToolsSignature = signature;
2499
+ } else if (nextModel != null && piSession != null && (piSession.model?.provider !== nextModel.provider || piSession.model.id !== nextModel.id)) {
2500
+ await piSession.setModel(nextModel);
2501
+ turnAbortController.signal.throwIfAborted();
2491
2502
  }
2492
2503
  if (!resourcesReloaded) {
2493
2504
  await reloadResourcesOnly();
@@ -2504,7 +2515,10 @@ async function createPiSession(input) {
2504
2515
  hostToolNames: userTools.map((tool2) => tool2.name),
2505
2516
  nativeToCommon: NATIVE_TO_COMMON
2506
2517
  });
2507
- currentEmit?.({ type: "stream-start" });
2518
+ currentEmit?.({
2519
+ type: "stream-start",
2520
+ ...piSession?.model?.id ? { modelId: piSession.model.id } : {}
2521
+ });
2508
2522
  if (didAppendDeliveredHostToolResults) {
2509
2523
  currentEmit?.({
2510
2524
  type: "finish-step",
@@ -2631,9 +2645,6 @@ async function createPiSession(input) {
2631
2645
  const sessionImpl = {
2632
2646
  sessionId: input.sessionId,
2633
2647
  isResume: input.isResume,
2634
- // The model Pi actually resolves to (the configured id, or its default when
2635
- // unset) — `gen_ai.request.model`.
2636
- ...resolvedModel?.id ? { modelId: resolvedModel.id } : {},
2637
2648
  // Pi has no bridge to attach to and no on-disk event log to replay; its
2638
2649
  // only resume path is restoring the session file on a fresh/snapshotted
2639
2650
  // sandbox, i.e. `rerun`.
@@ -2646,6 +2657,8 @@ async function createPiSession(input) {
2646
2657
  }
2647
2658
  return runTurn({
2648
2659
  text: extractUserText(promptOpts.prompt),
2660
+ ...promptOpts.model ? { model: promptOpts.model } : {},
2661
+ skills: promptOpts.skills,
2649
2662
  tools: promptOpts.tools ?? [],
2650
2663
  instructions: promptOpts.instructions,
2651
2664
  emit: promptOpts.emit,
@@ -2681,6 +2694,8 @@ async function createPiSession(input) {
2681
2694
  }
2682
2695
  return runTurn({
2683
2696
  text: "",
2697
+ ...continueOpts.model ? { model: continueOpts.model } : {},
2698
+ skills: continueOpts.skills,
2684
2699
  tools: continueOpts.tools ?? [],
2685
2700
  instructions: continueOpts.instructions,
2686
2701
  emit: continueOpts.emit,
@@ -3107,10 +3122,9 @@ function createPi(settings = {}) {
3107
3122
  sessionId: startOpts.sessionId,
3108
3123
  sandboxSession: startOpts.sandboxSession,
3109
3124
  sessionWorkDir: startOpts.sessionWorkDir,
3110
- skills: startOpts.skills ?? [],
3111
3125
  settings: {
3112
3126
  ...settings.auth ? { auth: settings.auth } : {},
3113
- ...settings.model ? { model: settings.model } : {},
3127
+ ...settings.model == null ? {} : { model: settings.model },
3114
3128
  ...settings.thinkingLevel ? { thinkingLevel: settings.thinkingLevel } : {},
3115
3129
  ...settings.mcpServers ? { mcpServers: settings.mcpServers } : {},
3116
3130
  ...settings.extensionFactories ? { extensionFactories: settings.extensionFactories } : {}