@cydm/pie 1.0.49 → 1.0.51

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 (31) hide show
  1. package/README.md +1 -1
  2. package/dist/builtin/extensions/ask-user/index.js +4 -11
  3. package/dist/builtin/extensions/ask-user/package.json +0 -7
  4. package/dist/builtin/extensions/changelog/index.js +15 -20
  5. package/dist/builtin/extensions/document-attachments/index.js +51 -1
  6. package/dist/builtin/extensions/document-attachments/package.json +1 -1
  7. package/dist/builtin/extensions/init/index.js +0 -13
  8. package/dist/builtin/extensions/plan-mode/index.js +31 -19
  9. package/dist/builtin/extensions/subagent/index.js +19 -40
  10. package/dist/builtin/extensions/todo/index.js +6 -10
  11. package/dist/builtin/skills/skill-creator/SKILL.md +15 -43
  12. package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.mjs +1 -1
  13. package/dist/builtin/skills/skill-creator/eval-viewer/viewer.html +2 -2
  14. package/dist/builtin/skills/skill-creator/references/schemas.md +1 -1
  15. package/dist/builtin/skills/skill-creator/scripts/generate_report.mjs +1 -1
  16. package/dist/builtin/skills/skill-creator/scripts/improve_description.mjs +3 -3
  17. package/dist/builtin/skills/skill-creator/scripts/pie_runner.mjs +32 -4
  18. package/dist/builtin/skills/skill-creator/scripts/run_loop.mjs +1 -1
  19. package/dist/chunks/{chunk-7RYOIXA2.js → chunk-A644H2XX.js} +104 -20
  20. package/dist/chunks/{chunk-FKAO25XH.js → chunk-B3SMW2XW.js} +1 -1
  21. package/dist/chunks/{chunk-J6PEH6ST.js → chunk-KDPAGHYY.js} +2 -2
  22. package/dist/chunks/{chunk-K6ZOCJ4V.js → chunk-S2J3SZZX.js} +44 -1
  23. package/dist/chunks/{src-HYZFAW4V.js → src-UKCIAX6F.js} +2 -2
  24. package/dist/chunks/{test-stream-5T7E7C25.js → test-stream-NCBFPM2I.js} +1 -1
  25. package/dist/cli.js +49 -22
  26. package/package.json +3 -3
  27. package/dist/builtin/extensions/deploy/index.js +0 -11
  28. package/dist/builtin/extensions/deploy/package.json +0 -11
  29. package/dist/builtin/extensions/files/index.js +0 -10
  30. package/dist/builtin/extensions/files/package.json +0 -14
  31. package/dist/builtin/skills/skill-creator/scripts/claude_cli.mjs +0 -115
package/README.md CHANGED
@@ -274,7 +274,7 @@ That is part of what makes Pie embeddable: the CLI is only one interface on top
274
274
 
275
275
  Extensions are discovered from four sources in ascending priority (later sources shadow earlier ones by stable extension identity):
276
276
 
277
- 1. `builtin` — shipped with the CLI (`ask-user`, `todo`, `plan-mode`, `subagent`, `init`, `changelog`, `deploy`, `files`, attachment handlers)
277
+ 1. `builtin` — shipped with the CLI (`ask-user`, `todo`, `plan-mode`, `subagent`, `init`, `changelog`, attachment handlers)
278
278
  2. `global` — `~/.pie/extensions/`
279
279
  3. `project` — `./.pie/extensions/`
280
280
  4. `configured` — repeated `--extension-path <dir>` flags
@@ -1,23 +1,16 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createAskUserCapability
4
- } from "../../../chunks/chunk-7RYOIXA2.js";
5
- import "../../../chunks/chunk-FKAO25XH.js";
6
- import "../../../chunks/chunk-K6ZOCJ4V.js";
4
+ } from "../../../chunks/chunk-A644H2XX.js";
5
+ import "../../../chunks/chunk-B3SMW2XW.js";
6
+ import "../../../chunks/chunk-S2J3SZZX.js";
7
7
  import "../../../chunks/chunk-LZQXQOPJ.js";
8
8
 
9
9
  // builtin/extensions/ask-user/index.ts
10
10
  function askUserExtension(ctx) {
11
11
  ctx.log("Ask user extension loaded");
12
12
  const capability = createAskUserCapability();
13
- const tool = capability.tools[0];
14
- ctx.registerTool({
15
- ...tool,
16
- async execute(args) {
17
- ctx.log(`[${tool.name}] Called: ${JSON.stringify(args)}`);
18
- return tool.execute(args);
19
- }
20
- });
13
+ ctx.registerTool(capability.tools[0]);
21
14
  }
22
15
  export {
23
16
  askUserExtension as default
@@ -2,15 +2,8 @@
2
2
  "name": "@pie/ask-user-extension",
3
3
  "version": "1.0.0",
4
4
  "type": "module",
5
- "main": "dist/index.js",
6
5
  "pie": {
7
6
  "name": "ask-user",
8
7
  "main": "index.ts"
9
- },
10
- "scripts": {
11
- "build": "tsc"
12
- },
13
- "dependencies": {
14
- "@sinclair/typebox": "^0.34.0"
15
8
  }
16
9
  }
@@ -1,12 +1,14 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
- import {
3
- __require
4
- } from "../../../chunks/chunk-LZQXQOPJ.js";
2
+ import "../../../chunks/chunk-LZQXQOPJ.js";
5
3
 
6
4
  // builtin/extensions/changelog/index.ts
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import { spawnSync } from "node:child_process";
8
+ var RECENT_COMMIT_COUNT = 15;
9
+ var RECENT_COMMIT_RANGE = "HEAD~5";
7
10
  function getRecentCommits(cwd, count = 10) {
8
11
  try {
9
- const { spawnSync } = __require("child_process");
10
12
  const result = spawnSync(
11
13
  "git",
12
14
  ["log", `--max-count=${count}`, "--pretty=format:%h %s", "--no-merges"],
@@ -19,10 +21,9 @@ function getRecentCommits(cwd, count = 10) {
19
21
  }
20
22
  function getChangedFiles(cwd) {
21
23
  try {
22
- const { spawnSync } = __require("child_process");
23
24
  const result = spawnSync(
24
25
  "git",
25
- ["diff", "HEAD~5", "--name-only", "--stat"],
26
+ ["diff", RECENT_COMMIT_RANGE, "--name-only", "--stat"],
26
27
  { cwd, encoding: "utf8" }
27
28
  );
28
29
  return result.status === 0 ? result.stdout : "";
@@ -32,8 +33,6 @@ function getChangedFiles(cwd) {
32
33
  }
33
34
  async function readChangelog(cwd) {
34
35
  try {
35
- const fs = await import("fs");
36
- const path = await import("path");
37
36
  const changelogPath = path.join(cwd, "CHANGELOG.md");
38
37
  if (fs.existsSync(changelogPath)) {
39
38
  return fs.readFileSync(changelogPath, "utf-8");
@@ -48,8 +47,6 @@ function changelogExtension(ctx) {
48
47
  path: ["tools", "changelog"],
49
48
  description: "Smart changelog management with gap detection",
50
49
  handler: async (ctx2, args) => {
51
- const fs = await import("fs");
52
- const path = await import("path");
53
50
  const changelogPath = path.join(ctx2.cwd, "CHANGELOG.md");
54
51
  if (args?.includes("--show")) {
55
52
  if (!fs.existsSync(changelogPath)) {
@@ -59,7 +56,7 @@ function changelogExtension(ctx) {
59
56
  return "Current CHANGELOG:\n\n" + content.slice(0, 2e3) + (content.length > 2e3 ? "\n\n..." : "");
60
57
  }
61
58
  if (args?.trim() === "check") {
62
- const commits2 = getRecentCommits(ctx2.cwd, 15);
59
+ const commits2 = getRecentCommits(ctx2.cwd, RECENT_COMMIT_COUNT);
63
60
  const changelog2 = await readChangelog(ctx2.cwd);
64
61
  const changedFiles2 = getChangedFiles(ctx2.cwd);
65
62
  if (!commits2) {
@@ -97,8 +94,7 @@ ${existingChangelog ? `
97
94
  Use this existing style as reference:
98
95
  \`\`\`
99
96
  ${existingChangelog.slice(0, 800)}
100
- ...
101
- \`\`\`` : ""}
97
+ ...\`\`\`` : ""}
102
98
 
103
99
  Requirements:
104
100
  1. Choose the right category: **Added** / **Changed** / **Fixed** / **Removed** / **Deprecated** / **Security**.
@@ -118,16 +114,15 @@ Use the write tool to update CHANGELOG.md:
118
114
  const versionHint = args.slice(7).trim();
119
115
  const existingChangelog = await readChangelog(ctx2.cwd);
120
116
  if (!existingChangelog) {
121
- return "No CHANGELOG.md found. Create one first with /changelog";
117
+ return "No CHANGELOG.md found. Create one first with /tools changelog";
122
118
  }
123
- ctx2.ui.notify(`\u{1F4DD} Preparing release ${versionHint || "..."}`, "info");
119
+ ctx2.ui.notify(`Preparing release ${versionHint || "..."}`, "info");
124
120
  return `Prepare the [Unreleased] section as a new release.
125
121
 
126
122
  Current CHANGELOG:
127
123
  \`\`\`
128
124
  ${existingChangelog.slice(0, 1500)}
129
- ...
130
- \`\`\`
125
+ ...\`\`\`
131
126
 
132
127
  Version hint: ${versionHint || "infer from changes (patch/minor/major)"}
133
128
 
@@ -146,11 +141,11 @@ Tasks:
146
141
 
147
142
  Use the write tool to update CHANGELOG.md.`;
148
143
  }
149
- const commits = getRecentCommits(ctx2.cwd, 15);
144
+ const commits = getRecentCommits(ctx2.cwd, RECENT_COMMIT_COUNT);
150
145
  const changelog = await readChangelog(ctx2.cwd);
151
146
  const changedFiles = getChangedFiles(ctx2.cwd);
152
147
  if (!commits && !changelog) {
153
- return "No git history or CHANGELOG.md found. Initialize with: /changelog add <description>";
148
+ return "No git history or CHANGELOG.md found. Initialize with: /tools changelog add <description>";
154
149
  }
155
150
  ctx2.ui.notify("Analyzing changes and checking for missing changelog entries...", "info");
156
151
  return `Smart changelog update
@@ -164,7 +159,7 @@ ${commits || "(git history unavailable)"}
164
159
  ${changedFiles || "(unavailable)"}
165
160
 
166
161
  ## Current CHANGELOG.md
167
- ${changelog ? "\n```\n" + changelog.slice(0, 2e3) + "\n...\n```" : "(file does not exist; create it if needed)"}
162
+ ${changelog ? "\n```\n" + changelog.slice(0, 2e3) + "\n...```" : "(file does not exist; create it if needed)"}
168
163
 
169
164
  ## Tasks
170
165
 
@@ -8,12 +8,27 @@ import { spawnSync } from "node:child_process";
8
8
  var MAX_TEXT_CHARS = 24e3;
9
9
  var PYTHON_CANDIDATES = [
10
10
  process.env.PYTHON,
11
- "/opt/anaconda3/bin/python3",
12
11
  "python3"
13
12
  ].filter((value) => Boolean(value));
14
13
  function isTextCapable(model) {
15
14
  return (model.input ?? []).includes("text");
16
15
  }
16
+ function supportsInputKind(model, kind) {
17
+ return (model.input ?? []).includes(kind);
18
+ }
19
+ function mediaKindFor(mimeType) {
20
+ if (mimeType.startsWith("image/")) return "image";
21
+ if (mimeType.startsWith("video/")) return "video";
22
+ return void 0;
23
+ }
24
+ var DEFAULT_INLINE_LIMIT_MB = {
25
+ image: 10,
26
+ video: 15
27
+ };
28
+ function inlineLimitMb(model, kind) {
29
+ const configured = model.fileCapabilities?.[kind]?.maxFileSizeMb;
30
+ return typeof configured === "number" && configured > 0 ? configured : DEFAULT_INLINE_LIMIT_MB[kind];
31
+ }
17
32
  function isSupportedDocument(attachment) {
18
33
  return attachment.mimeType === "application/pdf" || attachment.mimeType === "text/html" || attachment.mimeType === "text/plain" || attachment.mimeType === "text/markdown" || attachment.mimeType === "application/json" || attachment.name.endsWith(".html") || attachment.name.endsWith(".htm") || attachment.name.endsWith(".md") || attachment.name.endsWith(".txt") || attachment.name.endsWith(".json") || attachment.name.endsWith(".pdf");
19
34
  }
@@ -139,6 +154,41 @@ function documentAttachmentsExtension(ctx) {
139
154
  };
140
155
  }
141
156
  });
157
+ ctx.registerAttachmentHandler({
158
+ name: "local-media-inline",
159
+ priority: 20,
160
+ matches(model, attachment) {
161
+ const kind = mediaKindFor(attachment.mimeType);
162
+ return Boolean(kind) && supportsInputKind(model, kind) && Boolean(attachment.path);
163
+ },
164
+ async prepare(model, attachment, prepareCtx) {
165
+ prepareCtx.log(`Media handler inlining ${attachment.mimeType} attachment ${attachment.name}`);
166
+ const kind = mediaKindFor(attachment.mimeType);
167
+ const limitMb = inlineLimitMb(model, kind);
168
+ const sizeMb = fs.statSync(attachment.path).size / (1024 * 1024);
169
+ if (sizeMb > limitMb) {
170
+ prepareCtx.log(`Media handler skipped ${attachment.name}: ${sizeMb.toFixed(1)}MB exceeds the ${limitMb}MB inline limit`);
171
+ return {
172
+ items: [
173
+ {
174
+ type: "text",
175
+ text: `[${attachment.name}: ${sizeMb.toFixed(1)}MB exceeds the ${limitMb}MB inline limit for this model \u2014 not attached. Compress or shrink the file first.]`
176
+ }
177
+ ],
178
+ warnings: [`${attachment.name} (${sizeMb.toFixed(1)}MB) exceeds the ${limitMb}MB inline limit and was not attached`]
179
+ };
180
+ }
181
+ return {
182
+ items: [
183
+ {
184
+ type: kind,
185
+ mimeType: attachment.mimeType,
186
+ path: attachment.path
187
+ }
188
+ ]
189
+ };
190
+ }
191
+ });
142
192
  }
143
193
  export {
144
194
  documentAttachmentsExtension as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pie/extension-document-attachments",
3
3
  "version": "1.0.0",
4
- "description": "Document attachment handlers (PDF, DOCX, etc.)",
4
+ "description": "Local document attachment preprocessing (PDF, HTML, plain text)",
5
5
  "main": "index.ts",
6
6
  "type": "module",
7
7
  "pie": {
@@ -96,24 +96,11 @@ CLI file tools use the project root as their access boundary; do not pass an ext
96
96
  }
97
97
  async function initExtension(ctx) {
98
98
  ctx.log("Init extension loaded");
99
- let cachedKnowledge = null;
100
- try {
101
- const existing = await loadExistingKnowledge(ctx.cwd);
102
- cachedKnowledge = existing.content;
103
- if (cachedKnowledge) {
104
- ctx.log(`Pre-loaded root AGENTS.md (${cachedKnowledge.length} chars) from ${existing.target.agentsPath}`);
105
- } else {
106
- ctx.log(`No existing root AGENTS.md found at ${existing.target.agentsPath}`);
107
- }
108
- } catch (err) {
109
- ctx.log(`Failed to pre-load root AGENTS.md: ${err}`);
110
- }
111
99
  const handler = async (ctx2, args) => {
112
100
  const existing = await loadExistingKnowledge(ctx2.cwd);
113
101
  const existingContent = existing.content;
114
102
  const isUpdate = !!existing.content;
115
103
  const userIntent = args?.trim();
116
- cachedKnowledge = existingContent;
117
104
  if (isUpdate) {
118
105
  if (userIntent) {
119
106
  ctx2.ui.notify(`Updating project knowledge (${userIntent})...`, "info");
@@ -7,11 +7,11 @@ import {
7
7
  isPlanModeSafeCommand,
8
8
  markCompletedPlanSteps,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-7RYOIXA2.js";
11
- import "../../../chunks/chunk-FKAO25XH.js";
10
+ } from "../../../chunks/chunk-A644H2XX.js";
11
+ import "../../../chunks/chunk-B3SMW2XW.js";
12
12
  import {
13
13
  Type
14
- } from "../../../chunks/chunk-K6ZOCJ4V.js";
14
+ } from "../../../chunks/chunk-S2J3SZZX.js";
15
15
  import "../../../chunks/chunk-LZQXQOPJ.js";
16
16
 
17
17
  // builtin/extensions/plan-mode/index.ts
@@ -21,11 +21,10 @@ import os from "node:os";
21
21
  import path from "node:path";
22
22
  var SESSION_METADATA_KEY = "planModeEnabled";
23
23
  var EXECUTION_METADATA_KEY = "executionState";
24
+ var EXECUTION_FLAG_KEY = "planExecution";
24
25
  var SCRATCH_METADATA_KEY = "planScratchId";
25
26
  var SCRATCH_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/;
26
27
  var MAX_SCRATCH_CHARS = 64e3;
27
- var planModeEnabled = false;
28
- var executionMode = false;
29
28
  function toPlanTodoItems(state) {
30
29
  return state.steps.map((step) => ({
31
30
  step: step.id,
@@ -35,6 +34,18 @@ function toPlanTodoItems(state) {
35
34
  }
36
35
  function planModeExtension(ctx) {
37
36
  const capability = createPlanCapability();
37
+ let planModeEnabled = false;
38
+ let executingPlan = false;
39
+ function setExecutingPlan(value) {
40
+ executingPlan = value;
41
+ ctx.setSessionMetadata(EXECUTION_FLAG_KEY, value);
42
+ }
43
+ function readPersistedPlanMode() {
44
+ return ctx.getSessionMetadata()?.[SESSION_METADATA_KEY] === true;
45
+ }
46
+ function readPersistedExecuting() {
47
+ return ctx.getSessionMetadata()?.[EXECUTION_FLAG_KEY] === true;
48
+ }
38
49
  function scratchDirectory() {
39
50
  const metadata = ctx.getSessionMetadata();
40
51
  let id = metadata?.[SCRATCH_METADATA_KEY];
@@ -91,9 +102,6 @@ function planModeExtension(ctx) {
91
102
  }
92
103
  }
93
104
  });
94
- function readPersistedPlanMode() {
95
- return ctx.getSessionMetadata()?.[SESSION_METADATA_KEY] === true;
96
- }
97
105
  function readExecutionState() {
98
106
  return restoreExecutionState(ctx.getSessionMetadata()?.[EXECUTION_METADATA_KEY] ?? ctx.getExecutionState());
99
107
  }
@@ -106,7 +114,7 @@ function planModeExtension(ctx) {
106
114
  }
107
115
  function updateStatus() {
108
116
  const state = readExecutionState();
109
- if (executionMode && state.steps.length > 0) {
117
+ if (executingPlan && state.steps.length > 0) {
110
118
  const completed = state.steps.filter((step) => step.status === "completed").length;
111
119
  ctx.ui.notify(`\u{1F4CB} Plan: ${completed}/${state.steps.length} completed`, "info");
112
120
  } else if (planModeEnabled) {
@@ -115,14 +123,14 @@ function planModeExtension(ctx) {
115
123
  }
116
124
  function applyPlanModeState(enabled, forcePromptInjection = false) {
117
125
  planModeEnabled = enabled;
118
- if (!enabled) {
119
- executionMode = false;
126
+ if (enabled) {
127
+ setExecutingPlan(false);
120
128
  }
121
129
  ctx.setPlanMode(enabled, { forcePromptInjection });
122
130
  }
123
131
  function togglePlanMode() {
124
132
  planModeEnabled = !planModeEnabled;
125
- executionMode = false;
133
+ setExecutingPlan(false);
126
134
  writeExecutionState(null);
127
135
  ctx.setSessionMetadata(SESSION_METADATA_KEY, planModeEnabled);
128
136
  applyPlanModeState(planModeEnabled, true);
@@ -146,8 +154,8 @@ function planModeExtension(ctx) {
146
154
  });
147
155
  ctx.on("tool:call", async (event) => {
148
156
  if (!planModeEnabled || event.toolName !== "bash") return;
149
- const command = event.args?.command;
150
- if (command && !isPlanModeSafeCommand(command)) {
157
+ const command = typeof event.args === "object" && event.args !== null ? event.args.command : void 0;
158
+ if (typeof command === "string" && !isPlanModeSafeCommand(command)) {
151
159
  ctx.ui.notify(
152
160
  `Plan mode: Command blocked. Use read-only commands, or plan_scratch for temporary drafts. Use /plan to leave Plan mode.
153
161
  Command: ${command}`,
@@ -159,16 +167,18 @@ Command: ${command}`,
159
167
  ctx.on("agent:start", async () => {
160
168
  const persisted = readPersistedPlanMode();
161
169
  applyPlanModeState(persisted);
170
+ executingPlan = !persisted && readPersistedExecuting();
162
171
  writeExecutionState(readExecutionState());
163
172
  });
164
173
  ctx.on("session:changed", async () => {
165
174
  const enabled = readPersistedPlanMode();
166
175
  applyPlanModeState(enabled, enabled);
176
+ executingPlan = !enabled && readPersistedExecuting();
167
177
  writeExecutionState(readExecutionState());
168
178
  });
169
179
  ctx.on("turn:end", async (event) => {
170
180
  const state = readExecutionState();
171
- if (!executionMode || state.steps.length === 0) return;
181
+ if (!executingPlan || state.steps.length === 0) return;
172
182
  const message = event.message;
173
183
  if (message?.role !== "assistant" || !Array.isArray(message.content)) return;
174
184
  const text = message.content.filter((item) => item.type === "text").map((item) => item.text).join("\n");
@@ -180,13 +190,13 @@ Command: ${command}`,
180
190
  });
181
191
  ctx.on("agent:end", async (event) => {
182
192
  const state = readExecutionState();
183
- if (executionMode && state.steps.length > 0) {
193
+ if (executingPlan && state.steps.length > 0) {
184
194
  if (state.steps.every((step) => step.status === "completed")) {
185
195
  const completedList = state.steps.map((step) => `\u2713 ${step.title}`).join("\n");
186
196
  ctx.ui.notify(`**Plan Complete!** \u2713
187
197
 
188
198
  ${completedList}`, "info");
189
- executionMode = false;
199
+ setExecutingPlan(false);
190
200
  writeExecutionState(null);
191
201
  }
192
202
  return;
@@ -197,7 +207,9 @@ ${completedList}`, "info");
197
207
  (message) => message.role === "assistant" && Array.isArray(message.content)
198
208
  );
199
209
  if (!lastAssistant) return;
200
- const text = lastAssistant.content.filter((item) => item.type === "text").map((item) => item.text).join("\n");
210
+ const content = lastAssistant.content;
211
+ if (!Array.isArray(content)) return;
212
+ const text = content.filter((item) => item.type === "text").map((item) => item.text).join("\n");
201
213
  const extracted = extractPlanTodoItems(text);
202
214
  if (extracted.length === 0) return;
203
215
  const extractedState = writeExecutionState(createExecutionStateFromPlan(extracted));
@@ -211,7 +223,7 @@ ${todoListText}`, "info");
211
223
  ]);
212
224
  if (choice?.startsWith("Execute")) {
213
225
  planModeEnabled = false;
214
- executionMode = extractedState.steps.length > 0;
226
+ setExecutingPlan(extractedState.steps.length > 0);
215
227
  ctx.setSessionMetadata(SESSION_METADATA_KEY, false);
216
228
  ctx.setPlanMode(false);
217
229
  updateStatus();
@@ -1,64 +1,43 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createCliHostCapabilities
4
- } from "../../../chunks/chunk-J6PEH6ST.js";
4
+ } from "../../../chunks/chunk-KDPAGHYY.js";
5
5
  import {
6
6
  createSharedFileSystemTools,
7
7
  createSubagentCapability
8
- } from "../../../chunks/chunk-7RYOIXA2.js";
9
- import "../../../chunks/chunk-FKAO25XH.js";
10
- import "../../../chunks/chunk-K6ZOCJ4V.js";
8
+ } from "../../../chunks/chunk-A644H2XX.js";
9
+ import "../../../chunks/chunk-B3SMW2XW.js";
10
+ import "../../../chunks/chunk-S2J3SZZX.js";
11
11
  import "../../../chunks/chunk-LZQXQOPJ.js";
12
12
 
13
13
  // builtin/extensions/subagent/index.ts
14
14
  import * as os from "os";
15
15
  import * as path from "path";
16
- import * as fs from "fs";
17
- function debugLog(module, message, data) {
18
- try {
19
- const homeDir = process.env.HOME || process.env.USERPROFILE || ".";
20
- const logDir = path.join(homeDir, ".pie", "sessions");
21
- const files = fs.readdirSync(logDir).filter((f) => f.endsWith(".log")).sort().reverse();
22
- if (files.length > 0) {
23
- const logPath = path.join(logDir, files[0]);
24
- const entry = `[${(/* @__PURE__ */ new Date()).toISOString()}] [subagent:${module}] ${message}${data ? " " + JSON.stringify(data) : ""}
25
- `;
26
- fs.appendFileSync(logPath, entry);
27
- }
28
- } catch {
29
- }
30
- }
31
16
  function subagentExtension(ctx) {
32
17
  ctx.log("Subagent extension loaded (transparent parallel mode)");
33
- const apiKey = ctx.apiKey || process.env.KIMI_API_KEY || process.env.OPENAI_API_KEY;
34
- let model = ctx.model;
35
- if (!model) {
36
- model = {
37
- id: process.env.PIE_MODEL_ID || "kimi-api/kimi-k2.5",
38
- name: "Default Model",
39
- reasoning: false,
40
- input: ["text"],
41
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
42
- contextWindow: 2e5,
43
- maxTokens: 8192
44
- };
45
- }
18
+ const resolveRuntimePair = () => {
19
+ if (ctx.model && ctx.apiKey) return { model: ctx.model, apiKey: ctx.apiKey };
20
+ const fallback = ctx.resolveModelClass?.("balanced");
21
+ if (fallback?.model && fallback?.apiKey) return { model: fallback.model, apiKey: fallback.apiKey };
22
+ return {};
23
+ };
46
24
  const skills = ctx.skills || [];
47
- if (!apiKey) {
48
- ctx.log("Warning: No API key available for subagent.");
49
- }
50
25
  const capability = createSubagentCapability({
51
- apiKey,
52
- model,
26
+ get apiKey() {
27
+ return resolveRuntimePair().apiKey;
28
+ },
29
+ get model() {
30
+ return resolveRuntimePair().model;
31
+ },
53
32
  skills,
54
33
  yoloMode: ctx.yoloMode,
55
34
  getParentTools: () => ctx.getAllTools(),
56
35
  log: (message) => ctx.log(message),
57
- notify: ctx.hasUI ? (message, type) => ctx.ui.notify(message, type) : void 0,
58
- debugLog,
36
+ notify: ctx.hasUI ? (message, type) => ctx.ui.notify(message, type === "success" ? "info" : type) : void 0,
37
+ debugLog: (module, message, data) => ctx.log(`[subagent:${module}] ${message}${data !== void 0 ? ` ${JSON.stringify(data)}` : ""}`),
59
38
  resolveModelClass: (modelClass) => ctx.resolveModelClass?.(modelClass),
60
39
  createRuntimeTools: () => {
61
- const parentRuntimeTools = ctx.getRuntimeTools?.();
40
+ const parentRuntimeTools = ctx.getRuntimeTools();
62
41
  if (Array.isArray(parentRuntimeTools) && parentRuntimeTools.length > 0) {
63
42
  return parentRuntimeTools.filter((tool) => tool?.name !== "spawn_subagents_parallel");
64
43
  }
@@ -1,5 +1,6 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
+ MANAGE_TODO_LIST_TOOL_DESCRIPTION,
3
4
  ManageTodoListParamsSchema,
4
5
  buildExecutionReminder,
5
6
  createExecutionStateFromTodos,
@@ -7,18 +8,13 @@ import {
7
8
  executeManageTodoList,
8
9
  executionStateToTodos,
9
10
  restoreExecutionState
10
- } from "../../../chunks/chunk-7RYOIXA2.js";
11
- import "../../../chunks/chunk-FKAO25XH.js";
12
- import "../../../chunks/chunk-K6ZOCJ4V.js";
11
+ } from "../../../chunks/chunk-A644H2XX.js";
12
+ import "../../../chunks/chunk-B3SMW2XW.js";
13
+ import "../../../chunks/chunk-S2J3SZZX.js";
13
14
  import "../../../chunks/chunk-LZQXQOPJ.js";
14
15
 
15
16
  // builtin/extensions/todo/index.ts
16
17
  var EXECUTION_METADATA_KEY = "executionState";
17
- var TOOL_DESCRIPTION = `Manage a session-local todo list. Use when the user explicitly asks to use the todo tool, create/manage todos, track tasks, follow a todo list, show tasks, or mark a task done.
18
- NEVER use for: internal planning, tracking your own progress, remembering subtasks, or creating checklists for yourself.
19
- Use action=create with items to create a list; the tool starts item 1 automatically. Use action=complete_current after finishing the current item; the tool advances to the next item or clears the list after the final item.
20
- When a todo list exists, keep executing from the current in-progress item until it is cleared. If the work cannot continue, explain the failure and use action=clear with a reason.
21
- Actions: create, read, complete_current, clear.`;
22
18
  function persistExecutionState(ctx, state) {
23
19
  const nextState = state ?? restoreExecutionState(null);
24
20
  ctx.setSessionMetadata(EXECUTION_METADATA_KEY, nextState);
@@ -27,7 +23,7 @@ function persistExecutionState(ctx, state) {
27
23
  return nextState;
28
24
  }
29
25
  function notifyWidget(ctx, state) {
30
- if (!ctx.hasUI || !ctx.ui) return;
26
+ if (!ctx.hasUI) return;
31
27
  const steps = createTodoWidgetView(state);
32
28
  if (steps.length === 0) return;
33
29
  const completed = steps.filter((step) => step.status === "completed").length;
@@ -37,7 +33,7 @@ function todoExtension(ctx) {
37
33
  ctx.registerTool({
38
34
  name: "manage_todo_list",
39
35
  label: "manage_todo_list",
40
- description: TOOL_DESCRIPTION,
36
+ description: MANAGE_TODO_LIST_TOOL_DESCRIPTION,
41
37
  parameters: ManageTodoListParamsSchema,
42
38
  async execute(args) {
43
39
  const currentTodos = executionStateToTodos(ctx.getExecutionState());