@ai-sdk/harness-pi 1.0.93 → 1.0.95

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,29 @@
1
1
  # @ai-sdk/harness-pi
2
2
 
3
+ ## 1.0.95
4
+
5
+ ### Patch Changes
6
+
7
+ - f7fa993: fix(harness-pi): allow configuring Pi sessions with the `max` thinking level
8
+ - 7608210: feat(harness): add `model` parameter to `HarnessAgent` instead of having each harness adapter support it on their own constructor functions
9
+ - f7bd978: chore(harness): update underlying adapter SDKs to their latest versions
10
+ - 14d4fc0: feat(harness): allow changing harness settings between turns via `prepareCall()` support on `HarnessAgent`
11
+ - Updated dependencies [cc9f6ce]
12
+ - Updated dependencies [7608210]
13
+ - Updated dependencies [6f8a2d7]
14
+ - Updated dependencies [14d4fc0]
15
+ - Updated dependencies [90192f1]
16
+ - @ai-sdk/harness@1.0.93
17
+ - @ai-sdk/provider-utils@5.0.33
18
+
19
+ ## 1.0.94
20
+
21
+ ### Patch Changes
22
+
23
+ - e0d7cfb: feat(harness): allow harness sessions to optionally authenticate from an isolated environment supplied through the `auth` option, and remove support for the formerly deprecated legacy auth options types
24
+ - Updated dependencies [e0d7cfb]
25
+ - @ai-sdk/harness@1.0.92
26
+
3
27
  ## 1.0.93
4
28
 
5
29
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,35 +1,14 @@
1
1
  import * as _ai_sdk_harness from '@ai-sdk/harness';
2
- import { HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
2
+ import { HarnessV1Authentication, HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
3
3
  import { ExtensionFactory } from '@earendil-works/pi-coding-agent';
4
4
 
5
5
  /**
6
6
  * Pi auth options. Choose an explicit mode or rely on 'auto' (precedence:
7
7
  * explicit gateway, then OpenAI / Anthropic / custom environment variables).
8
8
  */
9
- type PiAuthenticationMode = 'auto' | 'openai' | 'anthropic' | 'custom' | 'ai-gateway';
10
- /**
11
- * @deprecated Passing an object to auth options is deprecated. Use a `PiAuthenticationMode` string value ("auto" | "openai" | "anthropic" | "custom" | "ai-gateway") instead, and pass credentials via environment variables.
12
- */
13
- type LegacyPiAuthOptions = {
14
- readonly gateway?: {
15
- readonly apiKey?: string;
16
- readonly baseUrl?: string;
17
- };
18
- /**
19
- * Resolved environment-variable pairs of the form `<PREFIX>_API_KEY` and
20
- * (optionally) `<PREFIX>_BASE_URL`. Special-cased prefixes:
21
- * - `AI_GATEWAY` → registers `vercel-ai-gateway`
22
- * - `OPENAI` → registers `openai`
23
- * - `ANTHROPIC` → registers `anthropic` (`ANTHROPIC_AUTH_TOKEN` adds a
24
- * bearer auth header)
25
- * Any other `<PREFIX>_API_KEY` with a matching `<PREFIX>_BASE_URL` is
26
- * registered as the lowercased, dash-separated prefix.
27
- */
28
- readonly customEnv?: Record<string, string>;
29
- };
30
- type PiAuthOptions = PiAuthenticationMode | LegacyPiAuthOptions;
9
+ type PiAuthenticationMode = HarnessV1Authentication<'openai' | 'anthropic' | 'custom'>;
31
10
 
32
- type PiThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
11
+ type PiThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
33
12
 
34
13
  /**
35
14
  * Configuration knobs for `createPi`. Pi runs as an in-process Node library
@@ -37,11 +16,13 @@ type PiThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
37
16
  */
38
17
  type PiHarnessSettings = {
39
18
  /** Where Pi sources API keys / gateway credentials from. */
40
- readonly auth?: PiAuthOptions;
19
+ readonly auth?: PiAuthenticationMode;
41
20
  /**
42
21
  * Pi model id (or name). Leaving this unset falls back to the AI Gateway
43
22
  * default when `AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN` is set, and to
44
23
  * Pi's own resolution otherwise.
24
+ *
25
+ * @deprecated Use `model` on `HarnessAgent` instead.
45
26
  */
46
27
  readonly model?: string;
47
28
  /**
@@ -143,4 +124,4 @@ declare const pi: _ai_sdk_harness.HarnessV1<{
143
124
  readonly ls: _ai_sdk_harness.HarnessV1BuiltinTool;
144
125
  }>;
145
126
 
146
- export { type PiAuthOptions, type PiAuthenticationMode, type PiHarnessSettings, VERSION, createPi, pi };
127
+ export { type PiAuthenticationMode, type PiHarnessSettings, VERSION, createPi, pi };
package/dist/index.js CHANGED
@@ -108,7 +108,6 @@ import {
108
108
  DefaultResourceLoader,
109
109
  defineTool,
110
110
  ModelRegistry,
111
- ModelRuntime,
112
111
  SessionManager,
113
112
  SettingsManager
114
113
  } from "@earendil-works/pi-coding-agent";
@@ -125,16 +124,121 @@ import {
125
124
  } from "@ai-sdk/harness/utils";
126
125
 
127
126
  // src/pi-auth.ts
128
- import { getAiGatewayAuthFromEnv } from "@ai-sdk/harness/utils";
127
+ import {
128
+ ModelRuntime
129
+ } from "@earendil-works/pi-coding-agent";
130
+ import {
131
+ getAiGatewayAuthFromEnv,
132
+ isHarnessAuthenticationEnvironment
133
+ } from "@ai-sdk/harness/utils";
134
+ import { access } from "fs/promises";
129
135
 
130
136
  // src/version.ts
131
- var VERSION = true ? "1.0.93" : "0.0.0-test";
137
+ var VERSION = true ? "1.0.95" : "0.0.0-test";
132
138
 
133
139
  // src/pi-auth.ts
134
140
  var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
135
141
  var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
136
142
  var DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
137
143
  var HARNESS_CLIENT_APP = `ai-sdk/harness-pi/${VERSION}`;
144
+ function createIsolatedPiCredentialStore() {
145
+ let initializing = true;
146
+ const bootstrapEnvironment = new Proxy(
147
+ {},
148
+ {
149
+ get: (_target, property) => typeof property === "string" ? "harness-pi-authentication-bootstrap" : void 0
150
+ }
151
+ );
152
+ const bootstrapCredential = {
153
+ type: "api_key",
154
+ key: "harness-pi-authentication-bootstrap",
155
+ env: bootstrapEnvironment
156
+ };
157
+ const credentials = {
158
+ async read() {
159
+ return initializing ? bootstrapCredential : void 0;
160
+ },
161
+ async list() {
162
+ return [];
163
+ },
164
+ async modify(..._input) {
165
+ return void 0;
166
+ },
167
+ async delete() {
168
+ }
169
+ };
170
+ return {
171
+ credentials,
172
+ finishInitialization() {
173
+ initializing = false;
174
+ }
175
+ };
176
+ }
177
+ function scopePiProviderEnvironment({
178
+ modelRuntime,
179
+ authenticationEnvironment
180
+ }) {
181
+ for (const provider of modelRuntime.getProviders()) {
182
+ const apiKeyAuthentication = provider.auth.apiKey;
183
+ if (!apiKeyAuthentication) continue;
184
+ provider.auth = {
185
+ ...provider.auth,
186
+ apiKey: {
187
+ ...apiKeyAuthentication,
188
+ resolve: async (input) => {
189
+ const result = await apiKeyAuthentication.resolve(input);
190
+ return result ? {
191
+ ...result,
192
+ env: {
193
+ ...authenticationEnvironment,
194
+ ...result.env
195
+ }
196
+ } : void 0;
197
+ }
198
+ }
199
+ };
200
+ }
201
+ }
202
+ async function createPiModelRuntime({
203
+ auth,
204
+ authPath,
205
+ modelsPath
206
+ }) {
207
+ if (!isHarnessAuthenticationEnvironment(auth)) {
208
+ return ModelRuntime.create({
209
+ authPath,
210
+ modelsPath,
211
+ allowModelNetwork: false
212
+ });
213
+ }
214
+ const isolatedCredentials = createIsolatedPiCredentialStore();
215
+ const modelRuntime = await ModelRuntime.create({
216
+ credentials: isolatedCredentials.credentials,
217
+ modelsPath: null,
218
+ allowModelNetwork: false
219
+ });
220
+ modelRuntime.models.authContext = {
221
+ async env(name) {
222
+ return auth[name];
223
+ },
224
+ async fileExists(filePath) {
225
+ if (filePath !== auth.GOOGLE_APPLICATION_CREDENTIALS) return false;
226
+ try {
227
+ await access(filePath);
228
+ return true;
229
+ } catch {
230
+ return false;
231
+ }
232
+ }
233
+ };
234
+ scopePiProviderEnvironment({
235
+ modelRuntime,
236
+ authenticationEnvironment: auth
237
+ });
238
+ isolatedCredentials.finishInitialization();
239
+ await modelRuntime.refresh({ allowNetwork: false });
240
+ return modelRuntime;
241
+ }
138
242
  function createGatewayProviderConfig({
139
243
  apiKey,
140
244
  baseUrl,
@@ -159,53 +263,41 @@ async function register({
159
263
  registries.modelRegistry.registerProvider(provider, config);
160
264
  await registries.modelRuntime.setRuntimeApiKey(provider, apiKey);
161
265
  }
162
- function hasConfiguredValue(value) {
163
- if (value == null) return false;
164
- if (typeof value === "string") return value.length > 0;
165
- if (typeof value !== "object") return true;
166
- return Object.values(value).some(hasConfiguredValue);
167
- }
168
266
  function resolvePiEnv({
169
267
  options,
170
268
  env
171
269
  }) {
172
- const normalizedOptions = normalizePiAuthToLegacyAuth(options);
173
- const customEnvConfigured = hasConfiguredValue(normalizedOptions?.customEnv);
174
- if (customEnvConfigured) {
175
- return resolveCustomEnv({ customEnv: normalizedOptions.customEnv ?? {} });
176
- }
177
- const gatewayConfigured = hasConfiguredValue(normalizedOptions?.gateway);
178
- const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env });
179
- if (gatewayConfigured) {
180
- const apiKey = normalizedOptions.gateway?.apiKey ?? gatewayAuthFromEnv.apiKey;
181
- const baseUrl = normalizedOptions.gateway?.baseUrl ?? gatewayAuthFromEnv.baseUrl;
182
- if (apiKey) {
183
- return { AI_GATEWAY_API_KEY: apiKey, AI_GATEWAY_BASE_URL: baseUrl };
184
- }
185
- return {};
186
- }
270
+ const suppliedEnvironment = isHarnessAuthenticationEnvironment(options);
271
+ const authenticationEnvironment = suppliedEnvironment ? options : env;
272
+ const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({
273
+ env: authenticationEnvironment
274
+ });
187
275
  if (typeof options === "string") {
188
276
  switch (options) {
189
277
  case "openai":
190
- if (env.OPENAI_API_KEY) {
278
+ if (authenticationEnvironment.OPENAI_API_KEY) {
191
279
  return {
192
- OPENAI_API_KEY: env.OPENAI_API_KEY,
193
- ...env.OPENAI_BASE_URL ? { OPENAI_BASE_URL: env.OPENAI_BASE_URL } : {}
280
+ OPENAI_API_KEY: authenticationEnvironment.OPENAI_API_KEY,
281
+ ...authenticationEnvironment.OPENAI_BASE_URL ? { OPENAI_BASE_URL: authenticationEnvironment.OPENAI_BASE_URL } : {}
194
282
  };
195
283
  }
196
284
  return {};
197
285
  case "anthropic":
198
- if (env.ANTHROPIC_API_KEY) {
286
+ if (authenticationEnvironment.ANTHROPIC_API_KEY) {
199
287
  return {
200
- ANTHROPIC_API_KEY: env.ANTHROPIC_API_KEY,
201
- ...env.ANTHROPIC_BASE_URL ? { ANTHROPIC_BASE_URL: env.ANTHROPIC_BASE_URL } : {},
202
- ...env.ANTHROPIC_AUTH_TOKEN ? { ANTHROPIC_AUTH_TOKEN: env.ANTHROPIC_AUTH_TOKEN } : {}
288
+ ANTHROPIC_API_KEY: authenticationEnvironment.ANTHROPIC_API_KEY,
289
+ ...authenticationEnvironment.ANTHROPIC_BASE_URL ? {
290
+ ANTHROPIC_BASE_URL: authenticationEnvironment.ANTHROPIC_BASE_URL
291
+ } : {},
292
+ ...authenticationEnvironment.ANTHROPIC_AUTH_TOKEN ? {
293
+ ANTHROPIC_AUTH_TOKEN: authenticationEnvironment.ANTHROPIC_AUTH_TOKEN
294
+ } : {}
203
295
  };
204
296
  }
205
297
  return {};
206
298
  case "custom": {
207
299
  const result = {};
208
- for (const [key, value] of Object.entries(env)) {
300
+ for (const [key, value] of Object.entries(authenticationEnvironment)) {
209
301
  if (value && (key.endsWith("_API_KEY") || key.endsWith("_BASE_URL") || key === "ANTHROPIC_AUTH_TOKEN")) {
210
302
  result[key] = value;
211
303
  }
@@ -232,7 +324,7 @@ function resolvePiEnv({
232
324
  };
233
325
  }
234
326
  const ambient = {};
235
- for (const [key, value] of Object.entries(env)) {
327
+ for (const [key, value] of Object.entries(authenticationEnvironment)) {
236
328
  if (value && (key.endsWith("_API_KEY") || key.endsWith("_BASE_URL") || key === "ANTHROPIC_AUTH_TOKEN")) {
237
329
  ambient[key] = value;
238
330
  }
@@ -245,21 +337,14 @@ async function registerPiProviders({
245
337
  registries,
246
338
  clientApp = HARNESS_CLIENT_APP
247
339
  }) {
248
- const normalizedOptions = normalizePiAuthToLegacyAuth(options);
249
- if (hasConfiguredValue(normalizedOptions?.customEnv)) {
250
- await registerCustomProviders({
251
- customEnv: normalizedOptions.customEnv ?? {},
252
- registries,
253
- clientApp
254
- });
255
- return;
256
- }
257
- const mode = typeof options === "string" ? options : options == null ? "auto" : "legacy";
340
+ const suppliedEnvironment = isHarnessAuthenticationEnvironment(options);
341
+ const authenticationEnvironment = suppliedEnvironment ? options : process.env;
342
+ const mode = typeof options === "string" ? options : "auto";
258
343
  switch (mode) {
259
344
  case "openai": {
260
345
  const env = pickOpenAIEnv(resolvedEnv);
261
346
  await registerCustomProviders({
262
- customEnv: { ...pickOpenAIEnv(process.env), ...env },
347
+ customEnv: { ...pickOpenAIEnv(authenticationEnvironment), ...env },
263
348
  registries,
264
349
  clientApp
265
350
  });
@@ -268,7 +353,7 @@ async function registerPiProviders({
268
353
  case "anthropic": {
269
354
  const env = pickAnthropicEnv(resolvedEnv);
270
355
  await registerCustomProviders({
271
- customEnv: { ...pickAnthropicEnv(process.env), ...env },
356
+ customEnv: { ...pickAnthropicEnv(authenticationEnvironment), ...env },
272
357
  registries,
273
358
  clientApp
274
359
  });
@@ -277,14 +362,16 @@ async function registerPiProviders({
277
362
  case "custom": {
278
363
  const env = pickProviderEnv(resolvedEnv);
279
364
  await registerCustomProviders({
280
- customEnv: { ...pickProviderEnv(process.env), ...env },
365
+ customEnv: { ...pickProviderEnv(authenticationEnvironment), ...env },
281
366
  registries,
282
367
  clientApp
283
368
  });
284
369
  return;
285
370
  }
286
371
  case "ai-gateway": {
287
- const gatewayAuth = getAiGatewayAuthFromEnv({ env: process.env });
372
+ const gatewayAuth = getAiGatewayAuthFromEnv({
373
+ env: authenticationEnvironment
374
+ });
288
375
  const gatewayApiKey = resolvedEnv.AI_GATEWAY_API_KEY ?? gatewayAuth.apiKey;
289
376
  const gatewayBaseUrl = resolvedEnv.AI_GATEWAY_BASE_URL ?? gatewayAuth.baseUrl;
290
377
  if (!gatewayApiKey) return;
@@ -300,12 +387,11 @@ async function registerPiProviders({
300
387
  });
301
388
  return;
302
389
  }
303
- case "legacy":
304
- break;
305
- // handled below
306
390
  case "auto":
307
391
  default: {
308
- const gatewayAuth = getAiGatewayAuthFromEnv({ env: process.env });
392
+ const gatewayAuth = getAiGatewayAuthFromEnv({
393
+ env: authenticationEnvironment
394
+ });
309
395
  const gatewayApiKey = resolvedEnv.AI_GATEWAY_API_KEY ?? gatewayAuth.apiKey;
310
396
  const gatewayBaseUrl = resolvedEnv.AI_GATEWAY_BASE_URL ?? gatewayAuth.baseUrl;
311
397
  if (gatewayApiKey) {
@@ -323,22 +409,13 @@ async function registerPiProviders({
323
409
  }
324
410
  const env = pickProviderEnv(resolvedEnv);
325
411
  await registerCustomProviders({
326
- customEnv: { ...pickProviderEnv(process.env), ...env },
412
+ customEnv: { ...pickProviderEnv(authenticationEnvironment), ...env },
327
413
  registries,
328
414
  clientApp
329
415
  });
330
416
  return;
331
417
  }
332
418
  }
333
- const apiKey = resolvedEnv.AI_GATEWAY_API_KEY;
334
- const baseUrl = resolvedEnv.AI_GATEWAY_BASE_URL;
335
- if (!apiKey || !baseUrl) return;
336
- await register({
337
- registries,
338
- provider: "vercel-ai-gateway",
339
- apiKey,
340
- config: createGatewayProviderConfig({ apiKey, baseUrl, clientApp })
341
- });
342
419
  }
343
420
  function pickOpenAIEnv(env) {
344
421
  const result = {};
@@ -364,37 +441,6 @@ function pickProviderEnv(env) {
364
441
  }
365
442
  return result;
366
443
  }
367
- function normalizePiAuthToLegacyAuth(options) {
368
- if (options == null || options === "auto") {
369
- return void 0;
370
- }
371
- if (typeof options === "string") {
372
- switch (options) {
373
- case "ai-gateway":
374
- return { gateway: {} };
375
- case "custom":
376
- case "openai":
377
- case "anthropic":
378
- return { customEnv: {} };
379
- default:
380
- return void 0;
381
- }
382
- }
383
- console.warn(
384
- '[pi] Passing an object to auth options is deprecated. Use a string mode ("auto" | "openai" | "anthropic" | "custom" | "ai-gateway") instead, and pass credentials via environment variables.'
385
- );
386
- return options;
387
- }
388
- function resolveCustomEnv({
389
- customEnv
390
- }) {
391
- const apiKey = customEnv.AI_GATEWAY_API_KEY;
392
- if (!apiKey) return {};
393
- return {
394
- AI_GATEWAY_API_KEY: apiKey,
395
- AI_GATEWAY_BASE_URL: customEnv.AI_GATEWAY_BASE_URL ?? DEFAULT_GATEWAY_BASE_URL
396
- };
397
- }
398
444
  async function registerCustomProviders({
399
445
  customEnv,
400
446
  registries,
@@ -938,7 +984,7 @@ function createPiRemoteOps(options) {
938
984
  import path4 from "path";
939
985
  import { writeSkills } from "@ai-sdk/harness/utils";
940
986
  async function writePiSkills(args) {
941
- await writeSkills({
987
+ return writeSkills({
942
988
  sandbox: args.sandbox,
943
989
  rootDir: path4.posix.join(args.sandboxHomeDir, ".agents", "skills"),
944
990
  skills: args.skills,
@@ -1913,21 +1959,12 @@ async function createPiSession(input) {
1913
1959
  sessionId: input.sessionId
1914
1960
  });
1915
1961
  const permissionMode = input.permissionMode ?? "allow-all";
1916
- let sandboxSkillRootDir;
1962
+ const sandboxSkillRootDir = path7.posix.join(
1963
+ sandboxHomeDir,
1964
+ ".agents",
1965
+ "skills"
1966
+ );
1917
1967
  let harnessSkills = [];
1918
- if (input.skills.length > 0) {
1919
- sandboxSkillRootDir = path7.posix.join(sandboxHomeDir, ".agents", "skills");
1920
- harnessSkills = createHarnessPiSkills({
1921
- skills: input.skills,
1922
- sandboxSkillRootDir
1923
- });
1924
- await writePiSkills({
1925
- sandbox: toolSafeSandboxSession,
1926
- sandboxHomeDir,
1927
- skills: input.skills,
1928
- ...input.abortSignal ? { abortSignal: input.abortSignal } : {}
1929
- });
1930
- }
1931
1968
  let resumeSessionFilePath;
1932
1969
  if (input.isResume && input.resumeSessionFileName) {
1933
1970
  const resumeSessionFileName = safePiSessionFileName(
@@ -1951,13 +1988,13 @@ async function createPiSession(input) {
1951
1988
  const paths = createPiPathMapper({
1952
1989
  hostWorkDir,
1953
1990
  sandboxWorkDir: sessionWorkDir,
1954
- readableRoots: sandboxSkillRootDir ? [{ sandboxDir: sandboxSkillRootDir }] : []
1991
+ readableRoots: [{ sandboxDir: sandboxSkillRootDir }]
1955
1992
  });
1956
1993
  const agentDir = input.agentDir ?? hostAgentDir;
1957
- const modelRuntime = await ModelRuntime.create({
1994
+ const modelRuntime = await createPiModelRuntime({
1995
+ auth: input.settings.auth,
1958
1996
  authPath: path7.join(agentDir, "auth.json"),
1959
- modelsPath: path7.join(agentDir, "models.json"),
1960
- allowModelNetwork: false
1997
+ modelsPath: path7.join(agentDir, "models.json")
1961
1998
  });
1962
1999
  const modelRegistry = new ModelRegistry(modelRuntime);
1963
2000
  const settingsManager = input.agentDir != null ? SettingsManager.create(hostWorkDir, agentDir) : SettingsManager.inMemory();
@@ -2203,6 +2240,7 @@ async function createPiSession(input) {
2203
2240
  try {
2204
2241
  const control = await runTurn({
2205
2242
  text: "",
2243
+ skills: continueOpts.skills,
2206
2244
  tools: continueOpts.tools ?? [],
2207
2245
  instructions: continueOpts.instructions,
2208
2246
  emit: continueOpts.emit,
@@ -2414,6 +2452,19 @@ async function createPiSession(input) {
2414
2452
  if (stopped) {
2415
2453
  throw new Error("Pi session has been stopped.");
2416
2454
  }
2455
+ const skillWriteResult = await writePiSkills({
2456
+ sandbox: toolSafeSandboxSession,
2457
+ sandboxHomeDir,
2458
+ skills: turnOpts.skills,
2459
+ abortSignal: turnOpts.abortSignal
2460
+ });
2461
+ harnessSkills = createHarnessPiSkills({
2462
+ skills: turnOpts.skills,
2463
+ sandboxSkillRootDir
2464
+ });
2465
+ if (piSession != null && skillWriteResult.changed) {
2466
+ await reloadResourcesOnly();
2467
+ }
2417
2468
  const userTools = turnOpts.tools;
2418
2469
  currentEmit = turnOpts.emit;
2419
2470
  const turnAbortController = new AbortController();
@@ -2600,6 +2651,7 @@ async function createPiSession(input) {
2600
2651
  }
2601
2652
  return runTurn({
2602
2653
  text: extractUserText(promptOpts.prompt),
2654
+ skills: promptOpts.skills,
2603
2655
  tools: promptOpts.tools ?? [],
2604
2656
  instructions: promptOpts.instructions,
2605
2657
  emit: promptOpts.emit,
@@ -2635,6 +2687,7 @@ async function createPiSession(input) {
2635
2687
  }
2636
2688
  return runTurn({
2637
2689
  text: "",
2690
+ skills: continueOpts.skills,
2638
2691
  tools: continueOpts.tools ?? [],
2639
2692
  instructions: continueOpts.instructions,
2640
2693
  emit: continueOpts.emit,
@@ -3055,16 +3108,16 @@ function createPi(settings = {}) {
3055
3108
  supportsBuiltinToolFiltering: true,
3056
3109
  lifecycleStateSchema: piResumeStateSchema,
3057
3110
  doStart: async (startOpts) => {
3111
+ const model = startOpts.model ?? settings.model;
3058
3112
  const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
3059
3113
  const resumeData = lifecycleState?.data;
3060
3114
  return createPiSession({
3061
3115
  sessionId: startOpts.sessionId,
3062
3116
  sandboxSession: startOpts.sandboxSession,
3063
3117
  sessionWorkDir: startOpts.sessionWorkDir,
3064
- skills: startOpts.skills ?? [],
3065
3118
  settings: {
3066
3119
  ...settings.auth ? { auth: settings.auth } : {},
3067
- ...settings.model ? { model: settings.model } : {},
3120
+ ...model == null ? {} : { model },
3068
3121
  ...settings.thinkingLevel ? { thinkingLevel: settings.thinkingLevel } : {},
3069
3122
  ...settings.mcpServers ? { mcpServers: settings.mcpServers } : {},
3070
3123
  ...settings.extensionFactories ? { extensionFactories: settings.extensionFactories } : {}