@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
|
@@ -46,6 +46,15 @@ export interface HistoryFormatOptions {
|
|
|
46
46
|
* this so it sees what changed without re-reading the file.
|
|
47
47
|
*/
|
|
48
48
|
expandEditDiffs?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Chunked rendering support: a caller formatting one logical transcript in
|
|
51
|
+
* several calls (the advisor's chunked delta render) passes a result index
|
|
52
|
+
* built over the WHOLE delta plus one shared consumed-id set, so a toolCall
|
|
53
|
+
* finds its toolResult across chunk boundaries and the result is never
|
|
54
|
+
* re-rendered as an orphan in a later chunk.
|
|
55
|
+
*/
|
|
56
|
+
toolResultIndex?: ReadonlyMap<string, ToolResultMessage>;
|
|
57
|
+
consumedToolCallIds?: Set<string>;
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
/** Max length of the primary-arg summary inside `→ tool(...)` lines. */
|
|
@@ -273,13 +282,19 @@ export function formatSessionHistoryMarkdown(messages: unknown[], opts?: History
|
|
|
273
282
|
}
|
|
274
283
|
|
|
275
284
|
// Index tool results by call id so each toolCall collapses to one line.
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
285
|
+
// Chunked callers supply a whole-delta index + shared consumed set so
|
|
286
|
+
// call/result pairs resolve across chunk boundaries.
|
|
287
|
+
let resultsByCallId = opts?.toolResultIndex;
|
|
288
|
+
if (!resultsByCallId) {
|
|
289
|
+
const local = new Map<string, ToolResultMessage>();
|
|
290
|
+
for (const msg of typed) {
|
|
291
|
+
if (msg.role === "toolResult") {
|
|
292
|
+
local.set(msg.toolCallId, msg);
|
|
293
|
+
}
|
|
280
294
|
}
|
|
295
|
+
resultsByCallId = local;
|
|
281
296
|
}
|
|
282
|
-
const consumed = new Set<string>();
|
|
297
|
+
const consumed = opts?.consumedToolCallIds ?? new Set<string>();
|
|
283
298
|
// In watched mode, consecutive same-role messages collapse under one label
|
|
284
299
|
// (the watched agent emits one assistant message per tool call, so otherwise
|
|
285
300
|
// every call repeats `**agent**:`). Cleared whenever a
|
|
@@ -935,6 +935,26 @@ export class SessionManager {
|
|
|
935
935
|
};
|
|
936
936
|
}
|
|
937
937
|
|
|
938
|
+
/**
|
|
939
|
+
* Create an independent manager for the current logical session and branch.
|
|
940
|
+
* The clone shares the storage backend but owns its entry index and writer, so
|
|
941
|
+
* callers can finish session-owned work after this manager switches elsewhere.
|
|
942
|
+
* Set `persist` false when the original session is intentionally being dropped.
|
|
943
|
+
*/
|
|
944
|
+
cloneCurrentSession(options?: { persist?: boolean }): SessionManager {
|
|
945
|
+
const persist = options?.persist ?? this.#persist;
|
|
946
|
+
const clone = new SessionManager(this.#cwd, this.#sessionDir, persist, this.#storage);
|
|
947
|
+
clone.#suppressBreadcrumb = true;
|
|
948
|
+
clone.restoreState(this.captureState());
|
|
949
|
+
if (!persist) {
|
|
950
|
+
clone.#sessionFile = undefined;
|
|
951
|
+
clone.#fileIsCurrent = false;
|
|
952
|
+
clone.#rewriteRequired = false;
|
|
953
|
+
clone.#forceFileCreation = false;
|
|
954
|
+
}
|
|
955
|
+
return clone;
|
|
956
|
+
}
|
|
957
|
+
|
|
938
958
|
restoreState(snapshot: SessionManagerStateSnapshot): void {
|
|
939
959
|
this.#closeWriterEventually();
|
|
940
960
|
this.#diskTail = Promise.resolve();
|
|
@@ -1470,6 +1490,34 @@ export class SessionManager {
|
|
|
1470
1490
|
return entry.id;
|
|
1471
1491
|
}
|
|
1472
1492
|
|
|
1493
|
+
/**
|
|
1494
|
+
* Append to a non-active branch without changing the current leaf.
|
|
1495
|
+
* Used by work that retains ownership of a branch across tree navigation.
|
|
1496
|
+
*/
|
|
1497
|
+
appendMessageToBranch(
|
|
1498
|
+
message:
|
|
1499
|
+
| Message
|
|
1500
|
+
| CustomMessage
|
|
1501
|
+
| HookMessage
|
|
1502
|
+
| BashExecutionMessage
|
|
1503
|
+
| PythonExecutionMessage
|
|
1504
|
+
| FileMentionMessage,
|
|
1505
|
+
parentId: string | null,
|
|
1506
|
+
): string {
|
|
1507
|
+
if (parentId !== null && !this.#index.has(parentId)) throw new Error(`Entry ${parentId} not found`);
|
|
1508
|
+
const activeLeafId = this.#index.leafId();
|
|
1509
|
+
const entry: SessionMessageEntry = {
|
|
1510
|
+
type: "message",
|
|
1511
|
+
id: generateId(this.#index),
|
|
1512
|
+
parentId,
|
|
1513
|
+
timestamp: nowIso(),
|
|
1514
|
+
message,
|
|
1515
|
+
};
|
|
1516
|
+
this.#recordEntry(entry);
|
|
1517
|
+
this.#index.setLeaf(activeLeafId);
|
|
1518
|
+
return entry.id;
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1473
1521
|
/** Append a thinking level change as child of current leaf, then advance leaf. Returns entry id. */
|
|
1474
1522
|
appendThinkingLevelChange(thinkingLevel?: string, configured?: string): string {
|
|
1475
1523
|
const entry: ThinkingLevelChangeEntry = {
|
|
@@ -1389,6 +1389,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
1389
1389
|
},
|
|
1390
1390
|
{
|
|
1391
1391
|
name: "new",
|
|
1392
|
+
aliases: ["clear"],
|
|
1392
1393
|
description: "Start a new session",
|
|
1393
1394
|
handleTui: async (_command, runtime) => {
|
|
1394
1395
|
runtime.ctx.editor.setText("");
|
|
@@ -1704,6 +1705,11 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
1704
1705
|
} catch {
|
|
1705
1706
|
return usage(`Directory does not exist: ${resolvedPath}`, runtime);
|
|
1706
1707
|
}
|
|
1708
|
+
try {
|
|
1709
|
+
await runtime.settings.flush();
|
|
1710
|
+
} catch (err) {
|
|
1711
|
+
return usage(`Failed to save pending settings: ${errorMessage(err)}`, runtime);
|
|
1712
|
+
}
|
|
1707
1713
|
try {
|
|
1708
1714
|
await runtime.sessionManager.moveTo(resolvedPath);
|
|
1709
1715
|
} catch (err) {
|
|
@@ -2320,6 +2326,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
2320
2326
|
},
|
|
2321
2327
|
{
|
|
2322
2328
|
name: "quit",
|
|
2329
|
+
aliases: ["q"],
|
|
2323
2330
|
description: "Quit the application",
|
|
2324
2331
|
handleTui: shutdownHandlerTui,
|
|
2325
2332
|
},
|
|
@@ -5,6 +5,22 @@ function normalizeIdentityValue(value: unknown): string | undefined {
|
|
|
5
5
|
return typeof value === "string" && value.trim() ? value.trim().toLowerCase() : undefined;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Session marker label for an active OAuth identity: the base identifier
|
|
10
|
+
* (email → accountId → projectId) suffixed with the organization when present
|
|
11
|
+
* and distinct. Same-email Anthropic multi-org accounts share the base, so the
|
|
12
|
+
* org suffix is the only field that tells the session's quota pool apart —
|
|
13
|
+
* mirrors the account-list rows (`formatUsageReportAccount`) and login success.
|
|
14
|
+
* Returns `undefined` when no identifier is recoverable.
|
|
15
|
+
*/
|
|
16
|
+
export function formatActiveAccountLabel(identity: OAuthAccountIdentity | undefined): string | undefined {
|
|
17
|
+
if (!identity) return undefined;
|
|
18
|
+
const base = identity.email || identity.accountId || identity.projectId;
|
|
19
|
+
if (!base) return undefined;
|
|
20
|
+
const org = identity.orgName || identity.orgId;
|
|
21
|
+
return org && org !== base ? `${base} (${org})` : base;
|
|
22
|
+
}
|
|
23
|
+
|
|
8
24
|
/**
|
|
9
25
|
* True when a single usage-limit column belongs to the given OAuth identity.
|
|
10
26
|
*
|
package/src/task/executor.ts
CHANGED
|
@@ -1052,7 +1052,7 @@ function createSubagentRunMonitor(args: RunMonitorArgs): SubagentRunMonitor {
|
|
|
1052
1052
|
// failures just leave the label unset.
|
|
1053
1053
|
const labelSource = assignment?.trim();
|
|
1054
1054
|
if (!args.description && args.modelRegistry && args.settings && labelSource) {
|
|
1055
|
-
generateTaskLabel(labelSource, args.modelRegistry, args.settings, id)
|
|
1055
|
+
generateTaskLabel(labelSource, args.modelRegistry, args.settings, id, abortSignal)
|
|
1056
1056
|
.then(label => {
|
|
1057
1057
|
if (!label || abortSignal.aborted || progress.description) return;
|
|
1058
1058
|
progress.description = label;
|
package/src/task/label.ts
CHANGED
|
@@ -15,6 +15,7 @@ export async function generateTaskLabel(
|
|
|
15
15
|
registry: ModelRegistry,
|
|
16
16
|
settings: Settings,
|
|
17
17
|
sessionId?: string,
|
|
18
|
+
signal?: AbortSignal,
|
|
18
19
|
): Promise<string | null> {
|
|
19
20
|
const text = assignment.trim();
|
|
20
21
|
if (!text) return null;
|
|
@@ -27,6 +28,7 @@ export async function generateTaskLabel(
|
|
|
27
28
|
undefined,
|
|
28
29
|
undefined,
|
|
29
30
|
TASK_LABEL_SYSTEM_PROMPT,
|
|
31
|
+
signal,
|
|
30
32
|
);
|
|
31
33
|
} catch (err) {
|
|
32
34
|
logger.debug("task-label: generation failed", {
|