@oh-my-pi/pi-coding-agent 17.0.1 → 17.0.2
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 +92 -20
- package/dist/cli.js +3485 -3448
- package/dist/types/advisor/config.d.ts +14 -6
- package/dist/types/advisor/runtime.d.ts +20 -11
- package/dist/types/autolearn/controller.d.ts +1 -0
- package/dist/types/config/model-discovery.d.ts +17 -0
- package/dist/types/config/model-resolver.d.ts +6 -2
- package/dist/types/config/settings-schema.d.ts +32 -7
- package/dist/types/config/settings.d.ts +50 -0
- package/dist/types/cursor.d.ts +11 -0
- package/dist/types/discovery/helpers.d.ts +5 -2
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/extensibility/extensions/managed-timers.d.ts +15 -0
- package/dist/types/extensibility/extensions/runner.d.ts +7 -0
- package/dist/types/extensibility/extensions/types.d.ts +18 -0
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +40 -0
- package/dist/types/extensibility/shared-events.d.ts +6 -0
- package/dist/types/extensibility/utils.d.ts +2 -2
- package/dist/types/mcp/transports/stdio.d.ts +13 -1
- package/dist/types/modes/components/advisor-config.d.ts +8 -1
- package/dist/types/modes/components/hook-editor.d.ts +7 -0
- package/dist/types/modes/components/model-hub.d.ts +5 -2
- package/dist/types/modes/components/session-selector.d.ts +2 -0
- package/dist/types/modes/controllers/command-controller.d.ts +8 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +3 -1
- package/dist/types/modes/print-mode.d.ts +1 -1
- package/dist/types/modes/warp-events.d.ts +24 -0
- package/dist/types/modes/warp-events.test.d.ts +1 -0
- package/dist/types/plan-mode/model-transition.d.ts +47 -0
- package/dist/types/plan-mode/model-transition.test.d.ts +1 -0
- package/dist/types/registry/agent-lifecycle.d.ts +26 -1
- package/dist/types/sdk.d.ts +13 -2
- package/dist/types/session/agent-session.d.ts +34 -10
- package/dist/types/session/session-history-format.d.ts +10 -0
- package/dist/types/session/session-manager.d.ts +14 -0
- package/dist/types/slash-commands/helpers/active-oauth-account.d.ts +9 -0
- package/dist/types/task/label.d.ts +1 -1
- package/dist/types/telemetry-export.d.ts +34 -9
- package/dist/types/tools/approval.d.ts +8 -0
- package/dist/types/tools/bash.d.ts +2 -0
- package/dist/types/tools/essential-tools.d.ts +29 -0
- package/dist/types/tools/image-gen.d.ts +2 -1
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/xdev.d.ts +11 -2
- package/dist/types/utils/title-generator.d.ts +2 -1
- package/dist/types/web/search/providers/kimi.d.ts +4 -1
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +21 -16
- package/src/advisor/__tests__/advisor.test.ts +1304 -42
- package/src/advisor/__tests__/config.test.ts +58 -2
- package/src/advisor/config.ts +76 -24
- package/src/advisor/runtime.ts +445 -92
- package/src/autolearn/controller.ts +23 -28
- package/src/cli.ts +5 -1
- package/src/config/model-discovery.ts +81 -21
- package/src/config/model-registry.ts +25 -6
- package/src/config/model-resolver.ts +14 -7
- package/src/config/settings-schema.ts +42 -6
- package/src/config/settings.ts +405 -25
- package/src/cursor.ts +20 -3
- package/src/debug/report-bundle.ts +40 -4
- package/src/discovery/helpers.ts +28 -5
- package/src/exec/bash-executor.ts +14 -5
- package/src/extensibility/custom-tools/loader.ts +3 -3
- package/src/extensibility/custom-tools/wrapper.ts +2 -1
- package/src/extensibility/extensions/loader.ts +3 -3
- package/src/extensibility/extensions/managed-timers.ts +83 -0
- package/src/extensibility/extensions/runner.ts +26 -0
- package/src/extensibility/extensions/types.ts +18 -0
- package/src/extensibility/extensions/wrapper.ts +2 -1
- package/src/extensibility/hooks/loader.ts +3 -3
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +96 -1
- package/src/extensibility/plugins/legacy-pi-compat.ts +225 -22
- package/src/extensibility/plugins/manager.ts +2 -2
- package/src/extensibility/shared-events.ts +6 -0
- package/src/extensibility/utils.ts +91 -25
- package/src/irc/bus.ts +22 -3
- package/src/launch/broker.ts +3 -2
- package/src/launch/client.ts +2 -2
- package/src/launch/presence.ts +2 -2
- package/src/lsp/client.ts +1 -1
- package/src/main.ts +11 -8
- package/src/mcp/manager.ts +9 -3
- package/src/mcp/transports/stdio.ts +103 -23
- package/src/modes/components/advisor-config.ts +65 -3
- package/src/modes/components/ask-dialog.ts +1 -1
- package/src/modes/components/hook-editor.ts +18 -3
- package/src/modes/components/model-hub.ts +138 -42
- package/src/modes/components/session-selector.ts +4 -0
- package/src/modes/components/status-line/component.test.ts +1 -0
- package/src/modes/components/status-line/segments.ts +21 -6
- package/src/modes/controllers/command-controller.ts +167 -47
- package/src/modes/controllers/event-controller.ts +5 -0
- package/src/modes/controllers/extension-ui-controller.ts +4 -22
- package/src/modes/controllers/input-controller.ts +12 -12
- package/src/modes/controllers/selector-controller.ts +191 -31
- package/src/modes/interactive-mode.ts +139 -54
- package/src/modes/print-mode.ts +3 -3
- package/src/modes/rpc/host-tools.ts +2 -1
- package/src/modes/rpc/rpc-mode.ts +19 -4
- package/src/modes/warp-events.test.ts +794 -0
- package/src/modes/warp-events.ts +232 -0
- package/src/plan-mode/model-transition.test.ts +60 -0
- package/src/plan-mode/model-transition.ts +51 -0
- package/src/registry/agent-lifecycle.ts +133 -18
- package/src/sdk.ts +221 -42
- package/src/session/agent-session.ts +1285 -348
- package/src/session/session-history-format.ts +20 -5
- package/src/session/session-manager.ts +48 -0
- package/src/slash-commands/builtin-registry.ts +7 -0
- package/src/slash-commands/helpers/active-oauth-account.ts +16 -0
- package/src/task/executor.ts +1 -1
- package/src/task/label.ts +2 -0
- package/src/telemetry-export.ts +453 -97
- package/src/tools/approval.ts +11 -0
- package/src/tools/bash.ts +71 -38
- package/src/tools/essential-tools.ts +45 -0
- package/src/tools/gh.ts +169 -2
- package/src/tools/image-gen.ts +69 -7
- package/src/tools/index.ts +7 -5
- package/src/tools/read.ts +48 -3
- package/src/tools/write.ts +22 -4
- package/src/tools/xdev.ts +14 -3
- package/src/utils/title-generator.ts +15 -4
- package/src/web/search/providers/kimi.ts +18 -12
- package/src/web/search/types.ts +6 -1
|
@@ -201,9 +201,13 @@ describe("WATCHDOG.yml file round-trip", () => {
|
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
const doc: WatchdogConfigDoc = {
|
|
204
|
-
instructions: 'Shared baseline.\nSecond line with: a colon and "quotes".',
|
|
204
|
+
instructions: 'Shared baseline.\n\nSecond line with: a colon and "quotes".',
|
|
205
205
|
advisors: [
|
|
206
|
-
{
|
|
206
|
+
{
|
|
207
|
+
name: "Architecture",
|
|
208
|
+
model: "x-ai/grok-code-fast:high",
|
|
209
|
+
instructions: "Watch module boundaries.\nReport coupling.",
|
|
210
|
+
},
|
|
207
211
|
{ name: "Security", tools: ["read", "grep"] },
|
|
208
212
|
],
|
|
209
213
|
};
|
|
@@ -222,11 +226,25 @@ describe("WATCHDOG.yml file round-trip", () => {
|
|
|
222
226
|
// Block style (not the flow `{...}` form), so it stays hand-editable.
|
|
223
227
|
expect(text).toContain("advisors:");
|
|
224
228
|
expect(text).not.toMatch(/^\{/);
|
|
229
|
+
expect(text).toContain('instructions: |2-\n Shared baseline.\n \n Second line with: a colon and "quotes".');
|
|
230
|
+
expect(text).toContain(" instructions: |2-\n Watch module boundaries.\n Report coupling.");
|
|
231
|
+
expect(text).not.toContain("\\n");
|
|
225
232
|
const { advisors, sharedInstructions } = await discoverAdvisorConfigs(tmp, tmp);
|
|
226
233
|
expect(advisors.map(a => a.name)).toEqual(["Architecture", "Security"]);
|
|
227
234
|
expect(sharedInstructions).toContain("Shared baseline.");
|
|
228
235
|
});
|
|
229
236
|
|
|
237
|
+
it("preserves significant leading whitespace and trailing newlines in block scalars", async () => {
|
|
238
|
+
const file = path.join(tmp, "WATCHDOG.yml");
|
|
239
|
+
const whitespaceDoc: WatchdogConfigDoc = {
|
|
240
|
+
instructions: " indented first line\nplain second line\n\n",
|
|
241
|
+
advisors: [{ name: "Whitespace", instructions: "\n indented after blank\nplain" }],
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
await saveWatchdogConfigFile(file, whitespaceDoc);
|
|
245
|
+
expect(await loadWatchdogConfigFile(file)).toEqual(whitespaceDoc);
|
|
246
|
+
});
|
|
247
|
+
|
|
230
248
|
it("round-trips an explicit empty tools list without collapsing it into the default", async () => {
|
|
231
249
|
const file = path.join(tmp, "WATCHDOG.yml");
|
|
232
250
|
const explicitNoToolsDoc: WatchdogConfigDoc = {
|
|
@@ -291,3 +309,41 @@ describe("resolveAdvisorConfigEditPath", () => {
|
|
|
291
309
|
expect(await resolveAdvisorConfigEditPath("project", dirs(tmp))).toBe(path.join(tmp, "WATCHDOG.yml"));
|
|
292
310
|
});
|
|
293
311
|
});
|
|
312
|
+
|
|
313
|
+
describe("per-advisor enabled field", () => {
|
|
314
|
+
it("preserves explicit true, explicit false, and absence through save and discovery", async () => {
|
|
315
|
+
const tmp = await fsp.mkdtemp(path.join(os.tmpdir(), "omp-advisor-enabled-"));
|
|
316
|
+
try {
|
|
317
|
+
const doc: WatchdogConfigDoc = {
|
|
318
|
+
advisors: [
|
|
319
|
+
{ name: "Explicit On", model: "test/model-a", enabled: true },
|
|
320
|
+
{ name: "Explicit Off", model: "test/model-b", enabled: false },
|
|
321
|
+
{ name: "Default", model: "test/model-c" },
|
|
322
|
+
],
|
|
323
|
+
};
|
|
324
|
+
const file = path.join(tmp, "WATCHDOG.yml");
|
|
325
|
+
await saveWatchdogConfigFile(file, doc);
|
|
326
|
+
|
|
327
|
+
const loaded = await loadWatchdogConfigFile(file);
|
|
328
|
+
expect(loaded.advisors.map(advisor => advisor.enabled)).toEqual([true, false, undefined]);
|
|
329
|
+
|
|
330
|
+
const { advisors } = await discoverAdvisorConfigs(tmp, tmp);
|
|
331
|
+
expect(advisors.map(advisor => advisor.enabled)).toEqual([true, false, undefined]);
|
|
332
|
+
} finally {
|
|
333
|
+
await fsp.rm(tmp, { recursive: true, force: true });
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it("emits explicit boolean values but omits an absent enabled field", () => {
|
|
338
|
+
const text = serializeWatchdogConfig({
|
|
339
|
+
advisors: [
|
|
340
|
+
{ name: "Explicit On", enabled: true },
|
|
341
|
+
{ name: "Explicit Off", enabled: false },
|
|
342
|
+
{ name: "Default" },
|
|
343
|
+
],
|
|
344
|
+
});
|
|
345
|
+
expect(text).toContain("enabled: true");
|
|
346
|
+
expect(text).toContain("enabled: false");
|
|
347
|
+
expect(text.match(/enabled:/g)).toHaveLength(2);
|
|
348
|
+
});
|
|
349
|
+
});
|
package/src/advisor/config.ts
CHANGED
|
@@ -22,8 +22,23 @@ export interface AdvisorConfig {
|
|
|
22
22
|
model?: string;
|
|
23
23
|
tools?: string[];
|
|
24
24
|
instructions?: string;
|
|
25
|
+
/** Per-advisor on/off toggle (default `true`). When `false`, the advisor
|
|
26
|
+
* stays in the roster but its runtime is never built — it shows `○` in
|
|
27
|
+
* the status line and `/advisor status` rather than disappearing. */
|
|
28
|
+
enabled?: boolean;
|
|
25
29
|
}
|
|
26
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Runtime health of a single advisor, surfaced in stats and the status line.
|
|
33
|
+
* - `running` — actively processing primary turns
|
|
34
|
+
* - `paused` — user-toggled off via per-advisor switch (runtime disposed)
|
|
35
|
+
* - `quota_exhausted` — provider returned a quota/rate-limit error; the
|
|
36
|
+
* runtime auto-retries after a cooldown so it can resume without user action
|
|
37
|
+
* - `error` — repeated transient failures; backlog dropped to prevent stall
|
|
38
|
+
* - `no_model` — no model resolved for this advisor's role/explicit model
|
|
39
|
+
*/
|
|
40
|
+
export type AdvisorRuntimeStatus = "running" | "paused" | "quota_exhausted" | "error" | "no_model";
|
|
41
|
+
|
|
27
42
|
/**
|
|
28
43
|
* The result of walking the `WATCHDOG.yml`/`WATCHDOG.yaml` search path: the
|
|
29
44
|
* deduped advisor roster plus the concatenated top-level `instructions` baseline
|
|
@@ -39,6 +54,7 @@ const advisorEntrySchema = type({
|
|
|
39
54
|
"model?": "string",
|
|
40
55
|
"tools?": "string[]",
|
|
41
56
|
"instructions?": "string",
|
|
57
|
+
"enabled?": "boolean",
|
|
42
58
|
});
|
|
43
59
|
|
|
44
60
|
const watchdogYamlSchema = type({
|
|
@@ -156,6 +172,7 @@ export async function discoverAdvisorConfigs(cwd: string, agentDir?: string): Pr
|
|
|
156
172
|
model: entry.model?.trim() || undefined,
|
|
157
173
|
tools: filterAdvisorTools(entry.tools, item.path),
|
|
158
174
|
instructions,
|
|
175
|
+
enabled: entry.enabled,
|
|
159
176
|
});
|
|
160
177
|
}
|
|
161
178
|
}
|
|
@@ -236,38 +253,73 @@ export async function loadWatchdogConfigFile(filePath: string): Promise<Watchdog
|
|
|
236
253
|
logger.warn("Advisor config: invalid schema for edit", { path: filePath, error: result.summary });
|
|
237
254
|
return { advisors: [] };
|
|
238
255
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
};
|
|
256
|
+
const advisors = (result.advisors ?? []).map(a => {
|
|
257
|
+
const advisor: AdvisorConfig = { name: a.name };
|
|
258
|
+
if (a.model?.trim()) advisor.model = a.model;
|
|
259
|
+
if (a.tools !== undefined) advisor.tools = [...a.tools];
|
|
260
|
+
if (a.instructions?.trim()) advisor.instructions = a.instructions;
|
|
261
|
+
if (a.enabled !== undefined) advisor.enabled = a.enabled;
|
|
262
|
+
return advisor;
|
|
263
|
+
});
|
|
264
|
+
const doc: WatchdogConfigDoc = { advisors };
|
|
265
|
+
if (result.instructions?.trim()) doc.instructions = result.instructions;
|
|
266
|
+
return doc;
|
|
248
267
|
}
|
|
249
268
|
|
|
250
269
|
/**
|
|
251
|
-
* Serialize an editable doc back to
|
|
252
|
-
*
|
|
253
|
-
*
|
|
270
|
+
* Serialize an editable doc back to canonical, hand-editable `WATCHDOG.yml`.
|
|
271
|
+
* Multiline instruction fields use literal block scalars while scalar quoting
|
|
272
|
+
* delegates to Bun's YAML encoder. Round-trips through {@link loadWatchdogConfigFile}.
|
|
254
273
|
* Returns `""` for an empty doc.
|
|
255
274
|
*/
|
|
275
|
+
|
|
276
|
+
function appendYamlString(lines: string[], indent: string, key: string, value: string): void {
|
|
277
|
+
const hasSignificantLeadingWhitespace = value.split("\n").some(line => /^[ \t]/.test(line));
|
|
278
|
+
if (!value.includes("\n") || hasSignificantLeadingWhitespace) {
|
|
279
|
+
lines.push(`${indent}${key}: ${YAML.stringify(value)}`);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const normalized = value.replaceAll("\r\n", "\n");
|
|
283
|
+
let trailingNewlines = 0;
|
|
284
|
+
for (let index = normalized.length - 1; index >= 0 && normalized[index] === "\n"; index--) {
|
|
285
|
+
trailingNewlines++;
|
|
286
|
+
}
|
|
287
|
+
const chomp = trailingNewlines === 0 ? "|2-" : trailingNewlines === 1 ? "|2" : "|2+";
|
|
288
|
+
const body = trailingNewlines === 0 ? normalized : normalized.slice(0, -trailingNewlines);
|
|
289
|
+
lines.push(`${indent}${key}: ${chomp}`);
|
|
290
|
+
for (const line of body.split("\n")) {
|
|
291
|
+
lines.push(`${indent} ${line}`);
|
|
292
|
+
}
|
|
293
|
+
for (let index = 1; index < trailingNewlines; index++) {
|
|
294
|
+
lines.push(`${indent} `);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
256
298
|
export function serializeWatchdogConfig(doc: WatchdogConfigDoc): string {
|
|
257
|
-
const
|
|
258
|
-
if (doc.instructions?.trim())
|
|
299
|
+
const lines: string[] = [];
|
|
300
|
+
if (doc.instructions?.trim()) appendYamlString(lines, "", "instructions", doc.instructions);
|
|
259
301
|
if (doc.advisors.length > 0) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
|
|
302
|
+
lines.push("advisors:");
|
|
303
|
+
for (const advisor of doc.advisors) {
|
|
304
|
+
lines.push(` - name: ${YAML.stringify(advisor.name)}`);
|
|
305
|
+
if (advisor.model?.trim()) lines.push(` model: ${YAML.stringify(advisor.model)}`);
|
|
306
|
+
if (advisor.tools !== undefined) {
|
|
307
|
+
if (advisor.tools.length === 0) {
|
|
308
|
+
lines.push(" tools: []");
|
|
309
|
+
} else {
|
|
310
|
+
lines.push(" tools:");
|
|
311
|
+
for (const tool of advisor.tools) {
|
|
312
|
+
lines.push(` - ${YAML.stringify(tool)}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (advisor.instructions?.trim()) {
|
|
317
|
+
appendYamlString(lines, " ", "instructions", advisor.instructions);
|
|
318
|
+
}
|
|
319
|
+
if (advisor.enabled !== undefined) lines.push(` enabled: ${advisor.enabled}`);
|
|
320
|
+
}
|
|
267
321
|
}
|
|
268
|
-
|
|
269
|
-
const text = YAML.stringify(out, null, 2);
|
|
270
|
-
return text.endsWith("\n") ? text : `${text}\n`;
|
|
322
|
+
return lines.length === 0 ? "" : `${lines.join("\n")}\n`;
|
|
271
323
|
}
|
|
272
324
|
|
|
273
325
|
/**
|