pi-long-task 0.3.11 → 0.3.12

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/README.md CHANGED
@@ -429,6 +429,8 @@ cd /path/to/pi-long-task
429
429
  npm run check
430
430
  ```
431
431
 
432
+ The development SDK tracks current Pi releases. Pi Long Task uses Pi's `ModelRuntime` worker API on Pi 0.80.8 and newer, with a legacy worker-model fallback for older compatible Pi releases.
433
+
432
434
  Check that Pi can load the extension:
433
435
 
434
436
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-long-task",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "type": "module",
5
5
  "description": "Pi extension for breaking down and running long coding tasks safely.",
6
6
  "keywords": [
@@ -38,9 +38,9 @@
38
38
  "typebox": "*"
39
39
  },
40
40
  "devDependencies": {
41
- "@earendil-works/pi-ai": "^0.74.2",
42
- "@earendil-works/pi-coding-agent": "^0.74.2",
43
- "@earendil-works/pi-tui": "^0.74.2",
41
+ "@earendil-works/pi-ai": "^0.81.1",
42
+ "@earendil-works/pi-coding-agent": "^0.81.1",
43
+ "@earendil-works/pi-tui": "^0.81.1",
44
44
  "@eslint/js": "^10.0.1",
45
45
  "@types/node": "^25.9.3",
46
46
  "eslint": "^10.5.0",
@@ -1,3 +1,5 @@
1
+ import path from "node:path";
2
+
1
3
  import { coverageGoalAction, coverageGoalVerification, parseCoverageGoal } from "./coverage_goal.ts";
2
4
  import { hasTaskResult, hasTaskResultStatus, isDoneStatus, parseReportedStatus } from "./result_writer.ts";
3
5
  import type { Task } from "./todo_parser.ts";
@@ -243,7 +245,10 @@ export interface CreateWorkerSessionOptions {
243
245
  model?: unknown;
244
246
  modelName?: string;
245
247
  thinkingLevel?: string;
248
+ modelRuntime?: unknown;
249
+ /** @deprecated Compatibility injection for Pi SDK versions before 0.80.8. */
246
250
  authStorage?: unknown;
251
+ /** @deprecated Compatibility injection for Pi SDK versions before 0.80.8. */
247
252
  modelRegistry?: unknown;
248
253
  settingsManager?: unknown;
249
254
  resourceLoader?: unknown;
@@ -306,14 +311,72 @@ remaining:
306
311
  - <remaining item or "none">`;
307
312
  }
308
313
 
314
+ interface WorkerPiSdkModelExports {
315
+ ModelRuntime?: {
316
+ create(options?: { authPath?: string; modelsPath?: string | null }): Promise<unknown>;
317
+ };
318
+ AuthStorage?: {
319
+ create(authPath?: string): unknown;
320
+ };
321
+ ModelRegistry?: {
322
+ create?(authStorage: unknown, modelsPath?: string): unknown;
323
+ };
324
+ }
325
+
326
+ export interface WorkerModelContext {
327
+ resolver: unknown;
328
+ sessionOptions: Record<string, unknown>;
329
+ api: "modelRuntime" | "legacy";
330
+ }
331
+
332
+ export async function createWorkerModelContext(
333
+ sdk: WorkerPiSdkModelExports,
334
+ options: Pick<CreateWorkerSessionOptions, "modelRuntime" | "authStorage" | "modelRegistry">,
335
+ agentDir: string,
336
+ ): Promise<WorkerModelContext> {
337
+ if (options.modelRuntime) {
338
+ return {
339
+ resolver: options.modelRuntime,
340
+ sessionOptions: { modelRuntime: options.modelRuntime },
341
+ api: "modelRuntime",
342
+ };
343
+ }
344
+
345
+ if (sdk.ModelRuntime?.create) {
346
+ const modelRuntime = await sdk.ModelRuntime.create({
347
+ authPath: path.join(agentDir, "auth.json"),
348
+ modelsPath: path.join(agentDir, "models.json"),
349
+ });
350
+ return {
351
+ resolver: modelRuntime,
352
+ sessionOptions: { modelRuntime },
353
+ api: "modelRuntime",
354
+ };
355
+ }
356
+
357
+ const authStorage = options.authStorage ?? sdk.AuthStorage?.create(path.join(agentDir, "auth.json"));
358
+ const modelRegistry =
359
+ options.modelRegistry ?? sdk.ModelRegistry?.create?.(authStorage, path.join(agentDir, "models.json"));
360
+ if (!authStorage || !modelRegistry) {
361
+ throw new Error(
362
+ "Pi Long Task cannot initialize worker model services: this Pi SDK exposes neither ModelRuntime.create() nor the legacy AuthStorage.create()/ModelRegistry.create() API.",
363
+ );
364
+ }
365
+
366
+ return {
367
+ resolver: modelRegistry,
368
+ sessionOptions: { authStorage, modelRegistry },
369
+ api: "legacy",
370
+ };
371
+ }
372
+
309
373
  export async function createIsolatedWorkerSession(
310
374
  options: CreateWorkerSessionOptions,
311
375
  ): Promise<WorkerSessionFactoryResult> {
312
376
  const pi = await import("@earendil-works/pi-coding-agent");
313
377
  const cwd = options.cwd;
314
378
  const agentDir = options.agentDir ?? pi.getAgentDir();
315
- const authStorage = options.authStorage ?? pi.AuthStorage.create();
316
- const modelRegistry = options.modelRegistry ?? pi.ModelRegistry.create(authStorage as never);
379
+ const modelContext = await createWorkerModelContext(pi as unknown as WorkerPiSdkModelExports, options, agentDir);
317
380
  const settingsManager = options.settingsManager ?? pi.SettingsManager.create(cwd, agentDir);
318
381
 
319
382
  applyWorkerSettingsDefaults(settingsManager);
@@ -330,12 +393,12 @@ export async function createIsolatedWorkerSession(
330
393
  await resourceLoader.reload();
331
394
 
332
395
  const model =
333
- options.model ?? (options.modelName ? await resolveWorkerModel(modelRegistry, options.modelName) : undefined);
396
+ options.model ??
397
+ (options.modelName ? await resolveWorkerModel(modelContext.resolver, options.modelName) : undefined);
334
398
  const createOptions: Record<string, unknown> = {
335
399
  cwd,
336
400
  agentDir,
337
- authStorage,
338
- modelRegistry,
401
+ ...modelContext.sessionOptions,
339
402
  settingsManager,
340
403
  resourceLoader,
341
404
  tools: [...(options.tools ?? DEFAULT_WORKER_TOOLS)],
@@ -672,24 +735,18 @@ function applyWorkerSettingsDefaults(settingsManager: unknown): void {
672
735
  }
673
736
  }
674
737
 
675
- async function resolveWorkerModel(modelRegistry: unknown, modelName: string): Promise<unknown> {
738
+ async function resolveWorkerModel(modelResolver: unknown, modelName: string): Promise<unknown> {
676
739
  const [provider, ...modelIdParts] = modelName.split("/");
677
740
  const modelId = modelIdParts.join("/");
678
- if (provider && modelId && isRecord(modelRegistry) && typeof modelRegistry.find === "function") {
679
- const registryModel = modelRegistry.find(provider, modelId);
680
- if (registryModel) {
681
- return registryModel;
682
- }
741
+ if (!provider || !modelId || !isRecord(modelResolver)) {
742
+ return undefined;
683
743
  }
684
744
 
685
- try {
686
- const ai = await import("@earendil-works/pi-ai");
687
- if (typeof ai.getModel === "function" && provider && modelId) {
688
- const getModel = ai.getModel as (providerName: string, modelId: string) => unknown;
689
- return getModel(provider, modelId);
690
- }
691
- } catch {
692
- // Optional peer resolution can fail in tests that inject a session factory.
745
+ if (typeof modelResolver.getModel === "function") {
746
+ return modelResolver.getModel(provider, modelId);
747
+ }
748
+ if (typeof modelResolver.find === "function") {
749
+ return modelResolver.find(provider, modelId);
693
750
  }
694
751
  return undefined;
695
752
  }