thoth-agents 0.3.11 → 0.4.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.
Files changed (74) hide show
  1. package/README.md +182 -389
  2. package/dist/agents/prompt-dialects.d.ts +4 -1
  3. package/dist/agents/prompt-sections.d.ts +2 -1
  4. package/dist/{chunk-CB3EBA7H.js → chunk-5EBXGMOK.js} +1 -1
  5. package/dist/chunk-62L3ORXN.js +30 -0
  6. package/dist/{chunk-GIUU6FNE.js → chunk-Q6SDM4KP.js} +208 -106
  7. package/dist/chunk-SECDI3TL.js +312 -0
  8. package/dist/{chunk-ZEAAWBF2.js → chunk-WJ2YMM2E.js} +2877 -290
  9. package/dist/cli/codex-plugin-install.d.ts +16 -2
  10. package/dist/cli/index.js +188 -15
  11. package/dist/cli/install-completion.d.ts +13 -0
  12. package/dist/cli/install-ledger.d.ts +1 -1
  13. package/dist/cli/install.d.ts +11 -1
  14. package/dist/cli/operations/pi.d.ts +43 -0
  15. package/dist/cli/owned-skills.d.ts +17 -0
  16. package/dist/cli/pi-effort.d.ts +10 -0
  17. package/dist/cli/pi-install.d.ts +131 -0
  18. package/dist/cli/pi-migration.d.ts +12 -0
  19. package/dist/cli/pi-native-probe.d.ts +34 -0
  20. package/dist/cli/pi-package-receipt.d.ts +59 -0
  21. package/dist/cli/pi-paths.d.ts +20 -0
  22. package/dist/cli/pi-resources.d.ts +15 -0
  23. package/dist/cli/skills.d.ts +1 -1
  24. package/dist/cli/tui/index.js +12 -4
  25. package/dist/cli/tui/operations.d.ts +1 -0
  26. package/dist/cli/types.d.ts +4 -2
  27. package/dist/harness/adapters/pi.d.ts +8 -0
  28. package/dist/harness/core/agent-pack.d.ts +26 -6
  29. package/dist/harness/core/sdd.d.ts +27 -15
  30. package/dist/harness/pi-specialists.d.ts +6 -0
  31. package/dist/harness/types.d.ts +2 -2
  32. package/dist/harness/writers/codex-plugin-package.d.ts +1 -0
  33. package/dist/harness/writers/pi-agent.d.ts +16 -0
  34. package/dist/index.js +6 -4
  35. package/dist/pi.d.ts +11 -0
  36. package/dist/pi.js +46 -0
  37. package/package.json +17 -6
  38. package/pi/.thoth-agents-assets.json +12 -0
  39. package/pi/agents/thoth-deep.md +81 -0
  40. package/pi/agents/thoth-designer.md +81 -0
  41. package/pi/agents/thoth-explorer.md +81 -0
  42. package/pi/agents/thoth-librarian.md +83 -0
  43. package/pi/agents/thoth-oracle.md +83 -0
  44. package/pi/agents/thoth-quick.md +81 -0
  45. package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +2 -2
  46. package/plugin/.claude-plugin/plugin.json +1 -1
  47. package/plugin/.codex-plugin/plugin.json +1 -1
  48. package/plugin/agents/oracle.md +3 -3
  49. package/plugin/agents/orchestrator.md +35 -30
  50. package/plugin/skills/plan-reviewer/SKILL.md +54 -15
  51. package/plugin/skills/thoth-archive/SKILL.md +5 -0
  52. package/plugin/skills/thoth-constitution/SKILL.md +5 -0
  53. package/plugin/skills/thoth-constitution/templates/constitution.md +19 -2
  54. package/plugin/skills/thoth-init/SKILL.md +5 -0
  55. package/plugin/skills/thoth-sdd/SKILL.md +35 -10
  56. package/plugin/skills/thoth-sdd/references/phases/implement.md +13 -2
  57. package/plugin/skills/thoth-sdd/references/phases/tasks.md +23 -2
  58. package/plugin/skills/thoth-sdd/references/phases/verify.md +7 -5
  59. package/plugin/skills/thoth-sdd/scripts/validate.mjs +263 -30
  60. package/plugin/skills/thoth-sdd/templates/tasks.md +18 -2
  61. package/skills/README.md +2 -1
  62. package/skills/plan-reviewer/SKILL.md +54 -15
  63. package/skills/thoth-archive/SKILL.md +5 -0
  64. package/skills/thoth-constitution/SKILL.md +5 -0
  65. package/skills/thoth-constitution/templates/constitution.md +19 -2
  66. package/skills/thoth-init/SKILL.md +5 -0
  67. package/skills/thoth-sdd/SKILL.md +35 -10
  68. package/skills/thoth-sdd/references/phases/implement.md +13 -2
  69. package/skills/thoth-sdd/references/phases/tasks.md +23 -2
  70. package/skills/thoth-sdd/references/phases/verify.md +7 -5
  71. package/skills/thoth-sdd/scripts/validate.mjs +263 -30
  72. package/skills/thoth-sdd/templates/tasks.md +18 -2
  73. package/.agents/plugins/marketplace.json +0 -20
  74. package/.claude-plugin/marketplace.json +0 -21
@@ -1,4 +1,12 @@
1
1
  export type CodexPluginSetupAction = 'register-marketplace' | 'install-plugin';
2
+ export type CodexPluginCleanupAction = 'remove-legacy-plugin' | 'remove-legacy-marketplace' | 'remove-legacy-root';
3
+ export interface CodexLegacyCleanupRoot {
4
+ kind: 'cache' | 'snapshot';
5
+ marketplaceName: string;
6
+ path: string;
7
+ realPath: string;
8
+ relativePath: string;
9
+ }
2
10
  export interface CodexCommandResult {
3
11
  exitCode: number;
4
12
  stdout: string;
@@ -17,22 +25,28 @@ export interface CodexCommandInvocation {
17
25
  }
18
26
  export type CodexCommandExecutor = (command: string, args: readonly string[], options: CodexCommandOptions) => CodexCommandResult;
19
27
  export interface CodexPluginInstallConfig {
28
+ codexHome?: string;
20
29
  dryRun?: boolean;
30
+ expectedVersion: string;
31
+ homeDir?: string;
21
32
  projectRoot: string;
22
33
  commandExecutor?: CodexCommandExecutor;
23
34
  }
24
35
  export interface CodexPluginSetupPlanItem {
25
- action: CodexPluginSetupAction;
36
+ action: CodexPluginSetupAction | CodexPluginCleanupAction;
26
37
  targetPath: string;
27
38
  description: string;
28
- command: {
39
+ command?: {
29
40
  executable: 'codex';
30
41
  args: string[];
31
42
  cwd: string;
32
43
  };
44
+ cleanupRoot?: CodexLegacyCleanupRoot;
33
45
  }
34
46
  export interface CodexPluginSetupPlan {
47
+ codexHome: string;
35
48
  dryRun: boolean;
49
+ expectedVersion: string;
36
50
  items: CodexPluginSetupPlanItem[];
37
51
  diagnostics: string[];
38
52
  ready: boolean;
package/dist/cli/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  getOpenCodeVersion,
5
5
  isOpenCodeInstalled,
6
6
  opencodeAdapter
7
- } from "../chunk-CB3EBA7H.js";
7
+ } from "../chunk-5EBXGMOK.js";
8
8
  import {
9
9
  CODEX_ROLE_NAMES,
10
10
  REQUIRED_SKILLS,
@@ -15,6 +15,8 @@ import {
15
15
  applyCodexPluginSetup,
16
16
  applyCodexSetup,
17
17
  applyOpenCodePlan,
18
+ applyPiPlan,
19
+ applyPiSetup,
18
20
  buildClaudeCodeModelPlan,
19
21
  buildClaudeCodeSetupPlan,
20
22
  buildClaudeCodeSyncPlan,
@@ -27,13 +29,19 @@ import {
27
29
  buildOpenCodeModelPlan,
28
30
  buildOpenCodeSyncPlan,
29
31
  buildOpenCodeUpdatePlan,
32
+ buildPiModelPlan,
33
+ buildPiSetupPlan,
34
+ buildPiSyncPlan,
35
+ buildPiUpdatePlan,
30
36
  claudeCodeAdapter,
31
37
  codexAdapter,
32
38
  defaultClaudeCodeModelRoles,
39
+ defaultPiModelRoles,
33
40
  finalizeHarnessInstall,
34
41
  formatClaudeCodeSetupPlan,
35
42
  formatCodexPluginSetupPlan,
36
43
  formatCodexSetupPlan,
44
+ formatPiSetupPlan,
37
45
  getClaudeCodeModelRoles,
38
46
  getClaudeCodeStatus,
39
47
  getCodexModelRoles,
@@ -42,12 +50,20 @@ import {
42
50
  getOpenCodeModelRoles,
43
51
  getOpenCodeStatus,
44
52
  getOperationHarness,
53
+ getPiModelRoles,
54
+ getPiStatus,
45
55
  getRequiredSkillInstallCommand,
56
+ inspectPiPackageSkills,
46
57
  installRequiredSkill,
47
58
  listOperationHarnesses,
48
59
  normalizeEffortSelection,
60
+ recordHarnessInstallCompletion,
49
61
  syncOpenCodeOwnedSkills
50
- } from "../chunk-ZEAAWBF2.js";
62
+ } from "../chunk-WJ2YMM2E.js";
63
+ import "../chunk-62L3ORXN.js";
64
+ import {
65
+ piAdapter
66
+ } from "../chunk-SECDI3TL.js";
51
67
  import {
52
68
  ALL_AGENT_NAMES,
53
69
  detectCurrentConfig,
@@ -58,7 +74,7 @@ import {
58
74
  resolveExecutingPackageVersion,
59
75
  updateOpenCodeMainConfig,
60
76
  writeLiteConfig
61
- } from "../chunk-GIUU6FNE.js";
77
+ } from "../chunk-Q6SDM4KP.js";
62
78
 
63
79
  // src/cli/index.ts
64
80
  import { pathToFileURL } from "url";
@@ -67,7 +83,8 @@ import { pathToFileURL } from "url";
67
83
  var HARNESS_ADAPTERS = {
68
84
  opencode: opencodeAdapter,
69
85
  codex: codexAdapter,
70
- claude: claudeCodeAdapter
86
+ claude: claudeCodeAdapter,
87
+ pi: piAdapter
71
88
  };
72
89
  var SUPPORTED_HARNESSES = Object.keys(HARNESS_ADAPTERS);
73
90
  function getHarnessAdapter(harness) {
@@ -77,6 +94,7 @@ function getHarnessAdapter(harness) {
77
94
  // src/cli/install.ts
78
95
  import { existsSync } from "fs";
79
96
  import { homedir } from "os";
97
+ import { join } from "path";
80
98
  import { cwd } from "process";
81
99
  var GREEN = "\x1B[32m";
82
100
  var BLUE = "\x1B[34m";
@@ -250,6 +268,9 @@ function finalizeInstallForHarness(harness, dryRun, version, dependencies) {
250
268
  });
251
269
  const providerComplete = printThothMemSetupResult(result.provider, dryRun);
252
270
  if (!providerComplete) return false;
271
+ return printInstallLedgerResult(result);
272
+ }
273
+ function printInstallLedgerResult(result) {
253
274
  if (!result.success) {
254
275
  printError(result.error ?? "Failed to record the completed CLI install.");
255
276
  return false;
@@ -261,6 +282,25 @@ function finalizeInstallForHarness(harness, dryRun, version, dependencies) {
261
282
  }
262
283
  return true;
263
284
  }
285
+ function finalizeLocalPiInstall(dryRun, version, dependencies) {
286
+ printWarning(
287
+ "Local thoth-agents install omits thoth-mem setup; install thoth-mem separately from its local checkout."
288
+ );
289
+ printInfo(
290
+ 'Separate command: node <thoth-mem-root>/dist/index.js setup pi --local-package-root "<absolute-thoth-mem-root>"'
291
+ );
292
+ const record = dependencies.recordHarnessInstallCompletion ?? recordHarnessInstallCompletion;
293
+ return printInstallLedgerResult(
294
+ record({
295
+ harness: "pi",
296
+ version,
297
+ dryRun,
298
+ ledgerOptions: dependencies.installLedgerOptions ?? {
299
+ homeDir: dependencies.homeDir ?? homedir()
300
+ }
301
+ })
302
+ );
303
+ }
264
304
  async function runInstall(config, dependencies, pluginVersion) {
265
305
  const detected = detectCurrentConfig();
266
306
  const isUpdate = detected.isInstalled;
@@ -356,10 +396,93 @@ ${JSON.stringify(liteConfig, null, 2)}
356
396
  );
357
397
  return 0;
358
398
  }
399
+ async function runPiInstall(config, dependencies, packageVersion, executingPackageRoot) {
400
+ const buildPlan = dependencies.buildPiSetupPlan ?? buildPiSetupPlan;
401
+ const applyPlan = dependencies.applyPiSetup ?? applyPiSetup;
402
+ const plan = buildPlan({
403
+ dryRun: config.dryRun,
404
+ homeDir: dependencies.homeDir ?? homedir(),
405
+ cwd: cwd(),
406
+ commandExecutor: dependencies.piCommandExecutor,
407
+ expectedVersion: packageVersion,
408
+ packageRoot: executingPackageRoot,
409
+ ...config.localPackageRoot ? { firstPartySource: config.localPackageRoot } : {},
410
+ receiptOptions: dependencies.installLedgerOptions,
411
+ verifyFirstParty: dependencies.verifyPiFirstParty
412
+ });
413
+ console.log(formatPiSetupPlan(plan));
414
+ for (const diagnostic of [...plan.diagnostics, ...plan.disclaimers]) {
415
+ printInfo(diagnostic);
416
+ }
417
+ if (!plan.ready) {
418
+ for (const blocker of plan.blockers) printError(blocker);
419
+ return 1;
420
+ }
421
+ const applied = applyPlan(plan);
422
+ for (const diagnostic of applied.diagnostics) printInfo(diagnostic);
423
+ if (!applied.success) {
424
+ printError(
425
+ `Pi install failed after ${applied.installedPackages.length} package step(s): ${applied.error ?? "unknown error"}`
426
+ );
427
+ return 1;
428
+ }
429
+ if (config.dryRun) {
430
+ printInfo(
431
+ "Pi package-declared skills remain unavailable until the first-party package is receipt-validated."
432
+ );
433
+ } else {
434
+ if (!applied.configuredPackageRoot) {
435
+ printError("Verified configured Pi package root is unavailable.");
436
+ return 1;
437
+ }
438
+ const packageSkills = (dependencies.inspectPiPackageSkills ?? inspectPiPackageSkills)({ packageRoot: applied.configuredPackageRoot });
439
+ for (const skill of packageSkills.skills)
440
+ printInfo(
441
+ ` - ${skill.name}: ${join(skill.destinationPath, "SKILL.md")}`
442
+ );
443
+ if (!packageSkills.success) {
444
+ printError(
445
+ `Failed to inspect package-declared Pi skills: ${packageSkills.error ?? "unknown error"}`
446
+ );
447
+ return 1;
448
+ }
449
+ }
450
+ if (config.dryRun) {
451
+ if (!installRequiredSkillsForHarness("pi", true, dependencies.homeDir)) {
452
+ return 1;
453
+ }
454
+ } else {
455
+ const installSkill = dependencies.installRequiredSkill ?? installRequiredSkill;
456
+ for (const skill of REQUIRED_SKILLS) {
457
+ const result = installSkill(skill, "pi", {
458
+ homeDir: dependencies.homeDir ?? homedir()
459
+ });
460
+ if (result.status === "failed") {
461
+ printError(`Failed to install required Pi skill: ${skill.name}`);
462
+ return 1;
463
+ }
464
+ printInfo(` - ${skill.name}: ${result.skillPath}`);
465
+ }
466
+ }
467
+ const finalized = config.localPackageRoot ? finalizeLocalPiInstall(config.dryRun, packageVersion, dependencies) : finalizeInstallForHarness(
468
+ "pi",
469
+ config.dryRun,
470
+ packageVersion,
471
+ dependencies
472
+ );
473
+ if (!finalized) {
474
+ return 1;
475
+ }
476
+ printSuccess(
477
+ config.dryRun ? `Pi dry-run complete; no packages, files, provider state, or ledger state changed${config.localPackageRoot ? "; thoth-mem remains a separate local install" : ""}` : `Complete Pi native package, agent, skill, research, and ledger setup applied${config.localPackageRoot ? "; thoth-mem remains a separate local install" : ", including provider setup"}`
478
+ );
479
+ return 0;
480
+ }
359
481
  function createInstallConfig(args) {
360
482
  return {
361
483
  agent: args.agent ?? "opencode",
362
484
  hasTmux: args.tmux === "yes",
485
+ ...args.localPackageRoot ? { localPackageRoot: args.localPackageRoot } : {},
363
486
  dryRun: args.dryRun,
364
487
  reset: args.reset ?? false
365
488
  };
@@ -378,6 +501,8 @@ async function install(args, dependencies = {}) {
378
501
  const projectRoot = cwd();
379
502
  const pluginPlan = buildCodexPluginSetupPlan({
380
503
  dryRun: config.dryRun,
504
+ expectedVersion: packageVersion.version,
505
+ homeDir: dependencies.homeDir,
381
506
  projectRoot
382
507
  });
383
508
  console.log(formatCodexPluginSetupPlan(pluginPlan));
@@ -416,7 +541,7 @@ async function install(args, dependencies = {}) {
416
541
  return 1;
417
542
  }
418
543
  printSuccess(
419
- config.dryRun ? "Codex dry-run complete; no files written" : "Codex plugin installed as thoth-agents@thoth-agents and agent-pack setup complete (restart Codex to activate)"
544
+ config.dryRun ? "Codex dry-run complete; no files written" : "Codex plugin installed as thoth-agents@thoth-plugins and agent-pack setup complete (restart Codex to activate)"
420
545
  );
421
546
  return 0;
422
547
  }
@@ -449,10 +574,18 @@ async function install(args, dependencies = {}) {
449
574
  return 1;
450
575
  }
451
576
  printSuccess(
452
- config.dryRun ? "Claude Code dry-run complete; no files written" : "Claude Code plugin installed as thoth-agents@thoth-agents through the native manager (restart Claude Code or run /reload-plugins to activate)"
577
+ config.dryRun ? "Claude Code dry-run complete; no files written" : "Claude Code plugin installed as thoth-agents@thoth-plugins through the native manager (restart Claude Code or run /reload-plugins to activate)"
453
578
  );
454
579
  return 0;
455
580
  }
581
+ if (config.agent === "pi") {
582
+ return runPiInstall(
583
+ config,
584
+ dependencies,
585
+ packageVersion.version,
586
+ packageVersion.packageRoot
587
+ );
588
+ }
456
589
  return runInstall(config, dependencies, packageVersion.version);
457
590
  }
458
591
 
@@ -613,7 +746,7 @@ Usage: thoth-agents [COMMAND] [OPTIONS]
613
746
 
614
747
  Commands:
615
748
  (no command) Open the interactive TUI in a TTY; fall back to OpenCode install in CI/non-TTY
616
- install Install OpenCode, Codex, or Claude Code agent assets
749
+ install Install OpenCode, Codex, Claude Code, or Pi agent assets
617
750
  generate Generate harness-specific artifacts
618
751
  status Show official CLI-managed versions and managed install status
619
752
  list List managed surfaces and actions
@@ -627,9 +760,11 @@ Options:
627
760
  --dry-run Simulate install without writing files
628
761
  --apply Apply a reviewed update, sync, or model plan
629
762
  --reset Repair managed installer-owned targets
630
- --agent=opencode|codex|claude
631
- Select OpenCode plugin install (default), Codex agent-pack, or Claude Code plugin setup
632
- --harness=... Select harness for status/update/sync/model (opencode|codex|claude)
763
+ --agent=opencode|codex|claude|pi
764
+ Select OpenCode plugin install (default), Codex/Claude setup, or complete Pi-native setup
765
+ --local-package-root=PATH
766
+ Install local thoth-agents with --agent=pi; thoth-mem is installed separately
767
+ --harness=... Select harness for status/update/sync/model (opencode|codex|claude|pi)
633
768
  --role-effort=role=effort
634
769
  Set a repeatable role effort; use inherit or default for no override
635
770
  -h, --help Show this help message
@@ -671,6 +806,8 @@ Examples:
671
806
  pnpm dlx thoth-agents@latest install --agent=codex --dry-run
672
807
  pnpm dlx thoth-agents@latest install --agent=claude
673
808
  pnpm dlx thoth-agents@latest install --agent=claude --dry-run
809
+ pnpm dlx thoth-agents@latest install --agent=pi --dry-run
810
+ node dist/cli/index.js install --agent=pi --local-package-root="<absolute-path>"
674
811
  pnpm dlx thoth-agents install --no-tui --tmux=no
675
812
  pnpm dlx thoth-agents install --dry-run
676
813
  pnpm dlx thoth-agents install --reset
@@ -689,6 +826,7 @@ function statusReports(args, context = operationContext()) {
689
826
  return harnesses.map((harness) => {
690
827
  if (harness === "opencode") return getOpenCodeStatus(context);
691
828
  if (harness === "claude") return getClaudeCodeStatus(context);
829
+ if (harness === "pi") return getPiStatus(context);
692
830
  return getCodexStatus(context);
693
831
  });
694
832
  }
@@ -700,6 +838,9 @@ function buildOperationPlan(command, args, context = operationContext()) {
700
838
  if (harness === "claude") {
701
839
  return command === "update" ? buildClaudeCodeUpdatePlan(context) : buildClaudeCodeSyncPlan(context);
702
840
  }
841
+ if (harness === "pi") {
842
+ return command === "update" ? buildPiUpdatePlan(context) : buildPiSyncPlan(context);
843
+ }
703
844
  return command === "update" ? buildCodexUpdatePlan(context) : buildCodexSyncPlan(context);
704
845
  }
705
846
  function defaultModelRoles(harness) {
@@ -712,6 +853,7 @@ function defaultModelRoles(harness) {
712
853
  if (harness === "claude") {
713
854
  return defaultClaudeCodeModelRoles();
714
855
  }
856
+ if (harness === "pi") return defaultPiModelRoles();
715
857
  return ALL_AGENT_NAMES.map((role) => ({
716
858
  role,
717
859
  model: getDefaultOpenCodeModel(role),
@@ -745,6 +887,7 @@ var defaultModelCommandServices = {
745
887
  modelRoles(harness) {
746
888
  if (harness === "opencode") return getOpenCodeModelRoles();
747
889
  if (harness === "claude") return getClaudeCodeModelRoles();
890
+ if (harness === "pi") return getPiModelRoles();
748
891
  return getCodexModelRoles();
749
892
  },
750
893
  modelOptions: getModelOptions
@@ -777,11 +920,13 @@ async function buildModelPlan(args, services) {
777
920
  };
778
921
  if (harness === "opencode") return buildOpenCodeModelPlan(input, context);
779
922
  if (harness === "claude") return buildClaudeCodeModelPlan(input, context);
923
+ if (harness === "pi") return buildPiModelPlan(input, context);
780
924
  return buildCodexModelPlan(input, context);
781
925
  }
782
926
  function applyOperationPlan(plan) {
783
927
  if (plan.harness === "opencode") return applyOpenCodePlan(plan);
784
928
  if (plan.harness === "claude") return applyClaudeCodePlan(plan);
929
+ if (plan.harness === "pi") return applyPiPlan(plan);
785
930
  return applyCodexPlan(plan);
786
931
  }
787
932
  function printPlanOrApply(plan, args, applyPlan) {
@@ -869,6 +1014,9 @@ async function runCliCommand(parsed, modelServices = defaultModelCommandServices
869
1014
  );
870
1015
  }
871
1016
 
1017
+ // src/cli/parser.ts
1018
+ import { isAbsolute, resolve } from "path";
1019
+
872
1020
  // src/cli/runtime.ts
873
1021
  var automationEnvironmentKeys = [
874
1022
  "CI",
@@ -920,9 +1068,9 @@ function parseBooleanArg(name, value) {
920
1068
  return value;
921
1069
  }
922
1070
  function parseOperationHarness(value) {
923
- if (value !== "opencode" && value !== "codex" && value !== "claude") {
1071
+ if (value !== "opencode" && value !== "codex" && value !== "claude" && value !== "pi") {
924
1072
  throw new Error(
925
- `Unsupported operation harness: ${value}. Supported harnesses: opencode, codex, claude.`
1073
+ `Unsupported operation harness: ${value}. Supported harnesses: opencode, codex, claude, pi.`
926
1074
  );
927
1075
  }
928
1076
  return value;
@@ -1025,7 +1173,9 @@ function parseInstallArgs(args) {
1025
1173
  tui: true,
1026
1174
  agent: "opencode"
1027
1175
  };
1028
- for (const arg of args) {
1176
+ for (let index = 0; index < args.length; index += 1) {
1177
+ const arg = args[index];
1178
+ if (arg === void 0) break;
1029
1179
  if (arg === "--no-tui") {
1030
1180
  result.tui = false;
1031
1181
  } else if (arg.startsWith("--tmux=")) {
@@ -1036,18 +1186,41 @@ function parseInstallArgs(args) {
1036
1186
  result.reset = true;
1037
1187
  } else if (arg.startsWith("--agent=")) {
1038
1188
  const agent = arg.split("=")[1];
1039
- if (agent !== "opencode" && agent !== "codex" && agent !== "claude") {
1189
+ if (agent !== "opencode" && agent !== "codex" && agent !== "claude" && agent !== "pi") {
1040
1190
  throw new Error(
1041
- `Unsupported install agent: ${agent}. Supported agents: opencode, codex, claude.`
1191
+ `Unsupported install agent: ${agent}. Supported agents: opencode, codex, claude, pi.`
1042
1192
  );
1043
1193
  }
1044
1194
  result.agent = agent;
1195
+ } else if (arg === "--local-package-root" || arg.startsWith("--local-package-root=")) {
1196
+ if (result.localPackageRoot !== void 0) {
1197
+ throw new Error("--local-package-root cannot be repeated.");
1198
+ }
1199
+ let localPackageRoot;
1200
+ if (arg === "--local-package-root") {
1201
+ index += 1;
1202
+ localPackageRoot = args[index];
1203
+ } else {
1204
+ localPackageRoot = arg.slice("--local-package-root=".length);
1205
+ }
1206
+ if (!localPackageRoot || localPackageRoot.startsWith("--")) {
1207
+ throw new Error("--local-package-root requires a value.");
1208
+ }
1209
+ if (!isAbsolute(localPackageRoot) || resolve(localPackageRoot) !== localPackageRoot) {
1210
+ throw new Error(
1211
+ "--local-package-root requires a normalized absolute path."
1212
+ );
1213
+ }
1214
+ result.localPackageRoot = localPackageRoot;
1045
1215
  } else if (arg === "-h" || arg === "--help") {
1046
1216
  throw new Error("help");
1047
1217
  } else {
1048
1218
  throw new Error(`Unsupported install option: ${arg}`);
1049
1219
  }
1050
1220
  }
1221
+ if (result.localPackageRoot !== void 0 && result.agent !== "pi") {
1222
+ throw new Error("--local-package-root is supported only with --agent=pi.");
1223
+ }
1051
1224
  return result;
1052
1225
  }
1053
1226
  function parseGenerateArgs(args) {
@@ -22,6 +22,18 @@ export interface HarnessInstallCompletionResult {
22
22
  ledger: InstallCompletionLedgerResult;
23
23
  error?: string;
24
24
  }
25
+ export interface HarnessInstallLedgerCompletionResult {
26
+ success: boolean;
27
+ ledger: InstallCompletionLedgerResult;
28
+ error?: string;
29
+ }
30
+ export interface RecordHarnessInstallCompletionOptions {
31
+ harness: InstallHarnessId;
32
+ version: string;
33
+ dryRun?: boolean;
34
+ recordCompletedInstall?: (options: Parameters<typeof recordCompletedInstall>[0]) => RecordCompletedInstallResult;
35
+ ledgerOptions?: InstallLedgerOptions;
36
+ }
25
37
  export interface FinalizeHarnessInstallOptions {
26
38
  harness: InstallHarnessId;
27
39
  version: string;
@@ -31,4 +43,5 @@ export interface FinalizeHarnessInstallOptions {
31
43
  recordCompletedInstall?: (options: Parameters<typeof recordCompletedInstall>[0]) => RecordCompletedInstallResult;
32
44
  ledgerOptions?: InstallLedgerOptions;
33
45
  }
46
+ export declare function recordHarnessInstallCompletion(options: RecordHarnessInstallCompletionOptions): HarnessInstallLedgerCompletionResult;
34
47
  export declare function finalizeHarnessInstall(options: FinalizeHarnessInstallOptions): HarnessInstallCompletionResult;
@@ -1,5 +1,5 @@
1
1
  export declare const INSTALL_LEDGER_SCHEMA_VERSION: 1;
2
- export type InstallHarnessId = 'opencode' | 'codex' | 'claude';
2
+ export type InstallHarnessId = 'opencode' | 'codex' | 'claude' | 'pi';
3
3
  export interface InstallLedger {
4
4
  schemaVersion: typeof INSTALL_LEDGER_SCHEMA_VERSION;
5
5
  harnesses: Partial<Record<InstallHarnessId, {
@@ -1,7 +1,10 @@
1
1
  import { updateOpenCodeMainConfig } from './config-manager';
2
- import { finalizeHarnessInstall } from './install-completion';
2
+ import { finalizeHarnessInstall, recordHarnessInstallCompletion } from './install-completion';
3
3
  import type { InstallLedgerOptions } from './install-ledger';
4
+ import { inspectPiPackageSkills } from './owned-skills';
4
5
  import { type ExecutingPackageVersionResult } from './package-version';
6
+ import { applyPiSetup, buildPiSetupPlan, type PiCommandExecutor, type PiSetupOptions } from './pi-install';
7
+ import { installRequiredSkill } from './skills';
5
8
  import type { ThothMemSetupOptions, ThothMemSetupResult } from './thoth-mem-install';
6
9
  import type { InstallArgs, InstallConfig } from './types';
7
10
  export interface InstallDependencies {
@@ -11,7 +14,14 @@ export interface InstallDependencies {
11
14
  resolveExecutingPackageVersion?: () => ExecutingPackageVersionResult;
12
15
  updateOpenCodeMainConfig?: typeof updateOpenCodeMainConfig;
13
16
  finalizeHarnessInstall?: typeof finalizeHarnessInstall;
17
+ recordHarnessInstallCompletion?: typeof recordHarnessInstallCompletion;
14
18
  installLedgerOptions?: InstallLedgerOptions;
19
+ piCommandExecutor?: PiCommandExecutor;
20
+ buildPiSetupPlan?: typeof buildPiSetupPlan;
21
+ applyPiSetup?: typeof applyPiSetup;
22
+ inspectPiPackageSkills?: typeof inspectPiPackageSkills;
23
+ verifyPiFirstParty?: PiSetupOptions['verifyFirstParty'];
24
+ installRequiredSkill?: typeof installRequiredSkill;
15
25
  }
16
26
  export declare function createInstallConfig(args: InstallArgs): InstallConfig;
17
27
  export declare function install(args: InstallArgs, dependencies?: InstallDependencies): Promise<number>;
@@ -0,0 +1,43 @@
1
+ import type { ProviderEvidenceInput } from '../../harness/types';
2
+ import { type FinalizeHarnessInstallOptions, finalizeHarnessInstall } from '../install-completion';
3
+ import { type InstallLedgerOptions } from '../install-ledger';
4
+ import { inspectPiPackageSkills } from '../owned-skills';
5
+ import { applyPiSetup, buildPiSetupPlan, type PiCommandExecutor } from '../pi-install';
6
+ import { installRequiredSkill } from '../skills';
7
+ import type { HarnessAction, HarnessStatusReport, ModelConfigInput, ModelRoleInput, OperationApplyResult, OperationContext, OperationPlan } from './types';
8
+ export interface PiOperationContext extends OperationContext {
9
+ homeDir?: string;
10
+ packageRoot?: string;
11
+ env?: Readonly<Record<string, string | undefined>>;
12
+ installLedgerOptions?: InstallLedgerOptions;
13
+ buildPiSetupPlan?: typeof buildPiSetupPlan;
14
+ applyPiSetup?: typeof applyPiSetup;
15
+ inspectPiPackageSkills?: typeof inspectPiPackageSkills;
16
+ piCommandExecutor?: PiCommandExecutor;
17
+ installRequiredSkill?: typeof installRequiredSkill;
18
+ finalizeHarnessInstall?: (options: FinalizeHarnessInstallOptions) => ReturnType<typeof finalizeHarnessInstall>;
19
+ runThothMemSetup?: FinalizeHarnessInstallOptions['runThothMemSetup'];
20
+ }
21
+ export type PiResearchProviderId = 'context7' | 'web-access' | 'grep';
22
+ export type PiResearchRuntimeState = 'ready' | 'unverified' | 'credential-required' | 'unreachable' | 'drifted' | 'failed';
23
+ export interface PiResearchRuntimeEvidence {
24
+ state: PiResearchRuntimeState;
25
+ basis: readonly string[];
26
+ }
27
+ export interface PiStatusEvidence extends ProviderEvidenceInput {
28
+ research?: Partial<Record<PiResearchProviderId, PiResearchRuntimeEvidence>>;
29
+ }
30
+ export declare const piOperationAdapter: {
31
+ readonly id: "pi";
32
+ readonly displayName: "Pi";
33
+ readonly available: true;
34
+ readonly description: "Pi-native packages, ambient root, six specialists, skills, and hybrid research stack.";
35
+ readonly actions: HarnessAction[];
36
+ };
37
+ export declare function getPiStatus(context?: PiOperationContext, evidence?: PiStatusEvidence): HarnessStatusReport;
38
+ export declare function buildPiInstallPlan(context?: PiOperationContext): OperationPlan;
39
+ export declare function buildPiUpdatePlan(context?: PiOperationContext): OperationPlan;
40
+ export declare function buildPiSyncPlan(context?: PiOperationContext): OperationPlan;
41
+ export declare function defaultPiModelRoles(context?: PiOperationContext): ModelRoleInput[];
42
+ export declare function buildPiModelPlan(input: ModelConfigInput, context?: PiOperationContext): OperationPlan;
43
+ export declare function applyPiPlan(plan: OperationPlan): OperationApplyResult;
@@ -15,6 +15,23 @@ export interface OpenCodeOwnedSkillSyncResult {
15
15
  skills: OpenCodeOwnedSkillSyncEntry[];
16
16
  error?: string;
17
17
  }
18
+ export interface PiPackageSkillInspectionResult {
19
+ success: boolean;
20
+ state: 'available' | 'unavailable';
21
+ skills: OpenCodeOwnedSkillSyncEntry[];
22
+ issues: Array<{
23
+ name: ThothOwnedSkillName;
24
+ state: 'missing' | 'drift';
25
+ message: string;
26
+ }>;
27
+ error?: string;
28
+ }
18
29
  export declare function resolveOwnedSkillPackageRoot(moduleUrl: string): string;
19
30
  export declare function getOpenCodeOwnedSkillEntries(options?: Pick<OpenCodeOwnedSkillSyncOptions, 'homeDir' | 'packageRoot'>): OpenCodeOwnedSkillSyncEntry[];
31
+ export declare function getPiOwnedSkillEntries(options: {
32
+ packageRoot: string;
33
+ }): OpenCodeOwnedSkillSyncEntry[];
20
34
  export declare function syncOpenCodeOwnedSkills(options?: OpenCodeOwnedSkillSyncOptions): OpenCodeOwnedSkillSyncResult;
35
+ export declare function inspectPiPackageSkills(options: {
36
+ packageRoot: string;
37
+ }): PiPackageSkillInspectionResult;
@@ -0,0 +1,10 @@
1
+ import type { ModelRoleInput } from './operations/types';
2
+ export declare const PI_EFFORT_VALUES: readonly ["off", "minimal", "low", "medium", "high", "xhigh"];
3
+ export type PiEffortResolution = {
4
+ ok: true;
5
+ effort: string | undefined;
6
+ } | {
7
+ ok: false;
8
+ message: string;
9
+ };
10
+ export declare function resolvePiEffort(input: Pick<ModelRoleInput, 'availableEfforts' | 'effort' | 'model'>): PiEffortResolution;