@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
package/src/sdk.ts
CHANGED
|
@@ -2,13 +2,21 @@ import {
|
|
|
2
2
|
Agent,
|
|
3
3
|
type AgentEvent,
|
|
4
4
|
type AgentMessage,
|
|
5
|
+
type AgentOptions,
|
|
5
6
|
type AgentTelemetryConfig,
|
|
6
7
|
type AgentTool,
|
|
7
8
|
AppendOnlyContextManager,
|
|
8
9
|
filterProviderReplayMessages,
|
|
9
10
|
type ThinkingLevel,
|
|
10
11
|
} from "@oh-my-pi/pi-agent-core";
|
|
11
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
Context,
|
|
14
|
+
CredentialDisabledEvent,
|
|
15
|
+
Message,
|
|
16
|
+
Model,
|
|
17
|
+
ProviderSessionState,
|
|
18
|
+
SimpleStreamOptions,
|
|
19
|
+
} from "@oh-my-pi/pi-ai";
|
|
12
20
|
import type { Dialect } from "@oh-my-pi/pi-ai/dialect";
|
|
13
21
|
import {
|
|
14
22
|
getOpenAICodexTransportDetails,
|
|
@@ -154,6 +162,7 @@ import {
|
|
|
154
162
|
createTools,
|
|
155
163
|
createVibeTools,
|
|
156
164
|
type DeferredDiagnosticsEntry,
|
|
165
|
+
defaultLoadModeForToolName,
|
|
157
166
|
discoverStartupLspServers,
|
|
158
167
|
EditTool,
|
|
159
168
|
EvalTool,
|
|
@@ -890,7 +899,7 @@ function customToolToDefinition(tool: CustomTool): ToolDefinition {
|
|
|
890
899
|
description: tool.description,
|
|
891
900
|
parameters: tool.parameters,
|
|
892
901
|
hidden: tool.hidden,
|
|
893
|
-
loadMode: tool.loadMode
|
|
902
|
+
loadMode: defaultLoadModeForToolName(tool.name, tool.loadMode),
|
|
894
903
|
deferrable: tool.deferrable,
|
|
895
904
|
approval: typeof tool.approval === "function" ? tool.approval.bind(tool) : tool.approval,
|
|
896
905
|
mcpServerName: tool.mcpServerName,
|
|
@@ -1055,6 +1064,88 @@ function buildMCPPromptCommands(manager: MCPManager): LoadedCustomCommand[] {
|
|
|
1055
1064
|
}
|
|
1056
1065
|
return commands;
|
|
1057
1066
|
}
|
|
1067
|
+
|
|
1068
|
+
/** Dependencies used to construct an isolated auto-learn capture agent. */
|
|
1069
|
+
export interface AutoLearnCaptureRunnerOptions {
|
|
1070
|
+
sourceAgent: Agent;
|
|
1071
|
+
captureTools: AgentTool[];
|
|
1072
|
+
createAgent: (options: AgentOptions) => Agent;
|
|
1073
|
+
onPayload?: SimpleStreamOptions["onPayload"];
|
|
1074
|
+
onResponse?: SimpleStreamOptions["onResponse"];
|
|
1075
|
+
createSessionId?: () => string;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/** Build a private capture runner over a detached message snapshot and provider session. */
|
|
1079
|
+
export function createAutoLearnCaptureRunner(
|
|
1080
|
+
options: AutoLearnCaptureRunnerOptions,
|
|
1081
|
+
): (content: string, signal?: AbortSignal) => Promise<void> {
|
|
1082
|
+
return async (content, signal) => {
|
|
1083
|
+
if (options.captureTools.length === 0 || signal?.aborted) return;
|
|
1084
|
+
const captureModel = options.sourceAgent.state.model;
|
|
1085
|
+
if (!captureModel) return;
|
|
1086
|
+
|
|
1087
|
+
const captureSessionId = options.createSessionId?.() ?? Bun.randomUUIDv7();
|
|
1088
|
+
const captureProviderSessionState = new Map<string, ProviderSessionState>();
|
|
1089
|
+
const captureMessages = options.sourceAgent.state.messages.map((message): AgentMessage => {
|
|
1090
|
+
if (message.role === "assistant") {
|
|
1091
|
+
return { ...message, responseId: undefined, providerPayload: undefined };
|
|
1092
|
+
}
|
|
1093
|
+
if (message.role === "user" || message.role === "developer") {
|
|
1094
|
+
return { ...message, providerPayload: undefined };
|
|
1095
|
+
}
|
|
1096
|
+
return message;
|
|
1097
|
+
});
|
|
1098
|
+
const captureAgent = options.createAgent({
|
|
1099
|
+
initialState: {
|
|
1100
|
+
systemPrompt: [...options.sourceAgent.state.systemPrompt],
|
|
1101
|
+
model: captureModel,
|
|
1102
|
+
thinkingLevel: options.sourceAgent.state.thinkingLevel,
|
|
1103
|
+
disableReasoning: options.sourceAgent.state.disableReasoning,
|
|
1104
|
+
tools: options.captureTools,
|
|
1105
|
+
messages: captureMessages,
|
|
1106
|
+
},
|
|
1107
|
+
sessionId: captureSessionId,
|
|
1108
|
+
promptCacheKey: captureSessionId,
|
|
1109
|
+
providerSessionState: captureProviderSessionState,
|
|
1110
|
+
getApiKey: requestModel => options.sourceAgent.getApiKey?.(requestModel),
|
|
1111
|
+
onPayload: options.onPayload,
|
|
1112
|
+
onResponse: options.onResponse,
|
|
1113
|
+
});
|
|
1114
|
+
captureAgent.setMetadataResolver(provider => options.sourceAgent.metadataForProvider(provider));
|
|
1115
|
+
const captureMessage: CustomMessage = {
|
|
1116
|
+
role: "custom",
|
|
1117
|
+
customType: "autolearn-nudge",
|
|
1118
|
+
content,
|
|
1119
|
+
display: false,
|
|
1120
|
+
attribution: "agent",
|
|
1121
|
+
timestamp: Date.now(),
|
|
1122
|
+
};
|
|
1123
|
+
const abortCapture = () => captureAgent.abort(signal?.reason);
|
|
1124
|
+
signal?.addEventListener("abort", abortCapture, { once: true });
|
|
1125
|
+
try {
|
|
1126
|
+
if (signal?.aborted) {
|
|
1127
|
+
abortCapture();
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
await captureAgent.prompt(captureMessage);
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
if (!signal?.aborted) throw error;
|
|
1133
|
+
} finally {
|
|
1134
|
+
signal?.removeEventListener("abort", abortCapture);
|
|
1135
|
+
for (const [providerKey, state] of captureProviderSessionState) {
|
|
1136
|
+
try {
|
|
1137
|
+
state.close();
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
logger.warn("Failed to close auto-learn capture provider state", {
|
|
1140
|
+
providerKey,
|
|
1141
|
+
error: String(error),
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
captureProviderSessionState.clear();
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1058
1149
|
/**
|
|
1059
1150
|
* Create an AgentSession with the specified options.
|
|
1060
1151
|
*
|
|
@@ -2247,31 +2338,50 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2247
2338
|
builtInRegistryToolNames.delete("edit");
|
|
2248
2339
|
}
|
|
2249
2340
|
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
// plan mode unable to exit through the intended path.
|
|
2257
|
-
const hasDeferrableTools = Array.from(toolRegistry.values()).some(tool => tool.deferrable === true);
|
|
2258
|
-
const hasXdevTools = (toolSession.xdevRegistry?.size ?? 0) > 0;
|
|
2259
|
-
const planModeAvailable = settings.get("plan.enabled");
|
|
2260
|
-
if ((hasDeferrableTools || hasXdevTools || planModeAvailable) && !toolRegistry.has("write")) {
|
|
2261
|
-
const writeTool = await logger.time("createTools:write:session", BUILTIN_TOOLS.write, toolSession);
|
|
2262
|
-
if (writeTool) {
|
|
2341
|
+
let writeRegistration: Promise<boolean> | undefined;
|
|
2342
|
+
const ensureWriteRegistered = (): Promise<boolean> => {
|
|
2343
|
+
if (toolRegistry.has("write")) return Promise.resolve(builtInRegistryToolNames.has("write"));
|
|
2344
|
+
writeRegistration ??= (async () => {
|
|
2345
|
+
const writeTool = await logger.time("createTools:write:session", BUILTIN_TOOLS.write, toolSession);
|
|
2346
|
+
if (!writeTool || toolRegistry.has("write")) return builtInRegistryToolNames.has("write");
|
|
2263
2347
|
toolRegistry.set(
|
|
2264
2348
|
writeTool.name,
|
|
2265
2349
|
new ExtensionToolWrapper(wrapToolWithMetaNotice(writeTool), extensionRunner) as Tool,
|
|
2266
2350
|
);
|
|
2267
2351
|
builtInRegistryToolNames.add(writeTool.name);
|
|
2268
|
-
|
|
2352
|
+
return true;
|
|
2353
|
+
})().finally(() => {
|
|
2354
|
+
writeRegistration = undefined;
|
|
2355
|
+
});
|
|
2356
|
+
return writeRegistration;
|
|
2357
|
+
};
|
|
2358
|
+
|
|
2359
|
+
// Existing staged/device paths need write registered before active-set assembly.
|
|
2360
|
+
// Deferred MCP also registers it now, but refresh activates it only after a server connects.
|
|
2361
|
+
const hasDeferrableTools = Array.from(toolRegistry.values()).some(tool => tool.deferrable === true);
|
|
2362
|
+
const hasXdevTools = (toolSession.xdevRegistry?.size ?? 0) > 0;
|
|
2363
|
+
const planModeAvailable = settings.get("plan.enabled");
|
|
2364
|
+
if (hasDeferrableTools || hasXdevTools || planModeAvailable || deferMCPDiscoveryForUI) {
|
|
2365
|
+
await ensureWriteRegistered();
|
|
2269
2366
|
}
|
|
2270
2367
|
|
|
2271
2368
|
let cursorEventEmitter: ((event: AgentEvent) => void) | undefined;
|
|
2369
|
+
// Built-in xd:// devices (ast_edit, debug, browser, lsp, web_search) are
|
|
2370
|
+
// mounted in createTools BEFORE this loop wraps registry entries in
|
|
2371
|
+
// ExtensionToolWrapper, so the registry holds them unwrapped. The normal
|
|
2372
|
+
// `write xd://<tool>` path runs approval through the wrapped `write` tool's
|
|
2373
|
+
// tier gate, but Cursor invokes advertised devices via `tool.execute()`
|
|
2374
|
+
// directly — so wrap unwrapped devices here to keep the approval/deny/prompt
|
|
2375
|
+
// gate. Dynamic mounts (custom/MCP) already come from the wrapped registry.
|
|
2376
|
+
const resolveCursorDevice = (name: string): AgentTool | undefined => {
|
|
2377
|
+
const device = toolSession.xdevRegistry?.get(name);
|
|
2378
|
+
if (!device) return undefined;
|
|
2379
|
+
return device instanceof ExtensionToolWrapper ? device : new ExtensionToolWrapper(device, extensionRunner);
|
|
2380
|
+
};
|
|
2272
2381
|
const cursorExecHandlers = new CursorExecHandlers({
|
|
2273
2382
|
cwd,
|
|
2274
2383
|
tools: toolRegistry,
|
|
2384
|
+
getTool: resolveCursorDevice,
|
|
2275
2385
|
getToolContext: () => toolContextStore.getContext(),
|
|
2276
2386
|
emitEvent: event => cursorEventEmitter?.(event),
|
|
2277
2387
|
});
|
|
@@ -2413,11 +2523,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2413
2523
|
}
|
|
2414
2524
|
const requestedToolNames = explicitlyRequestedToolNames ?? toolNamesFromRegistry;
|
|
2415
2525
|
const normalizedRequested = requestedToolNames.filter(name => toolRegistry.has(name));
|
|
2416
|
-
const requestedToolNameSet = new Set(normalizedRequested);
|
|
2417
2526
|
const defaultInactiveToolNames = new Set(
|
|
2418
2527
|
registeredTools.filter(tool => tool.definition.defaultInactive).map(tool => tool.definition.name),
|
|
2419
2528
|
);
|
|
2420
2529
|
const requestedActiveToolNames = normalizedRequested.filter(name => name !== "goal");
|
|
2530
|
+
const explicitlyRequestedToolNameSet = explicitlyRequestedToolNames
|
|
2531
|
+
? new Set(explicitlyRequestedToolNames)
|
|
2532
|
+
: undefined;
|
|
2533
|
+
const xdevReadAvailable =
|
|
2534
|
+
builtInRegistryToolNames.has("read") &&
|
|
2535
|
+
(explicitlyRequestedToolNameSet === undefined || explicitlyRequestedToolNameSet.has("read"));
|
|
2421
2536
|
const initialRequestedActiveToolNames = options.toolNames
|
|
2422
2537
|
? requestedActiveToolNames
|
|
2423
2538
|
: requestedActiveToolNames.filter(name => !defaultInactiveToolNames.has(name));
|
|
@@ -2449,24 +2564,32 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2449
2564
|
});
|
|
2450
2565
|
hasRegistered = true;
|
|
2451
2566
|
|
|
2452
|
-
// Partition the initial enabled set for the xd:// transport:
|
|
2453
|
-
// tools become mounted devices
|
|
2454
|
-
//
|
|
2455
|
-
//
|
|
2456
|
-
//
|
|
2457
|
-
// never ship a schema. Presentation only — selection already happened.
|
|
2567
|
+
// Partition the initial enabled set for the xd:// transport: ambient
|
|
2568
|
+
// discoverable tools become mounted devices, while explicitly requested
|
|
2569
|
+
// tools keep their top-level presentation. The registry already holds the
|
|
2570
|
+
// default-set built-in devices from createTools; this reconciles dynamic
|
|
2571
|
+
// mounts (image-gen, TTS, startup MCP, active extension tools).
|
|
2458
2572
|
let initialMountedXdevToolNames: string[] = [];
|
|
2459
2573
|
if (toolSession.xdevRegistry) {
|
|
2460
2574
|
const topLevelToolNames: string[] = [];
|
|
2461
2575
|
const mountedTools: Tool[] = [];
|
|
2462
2576
|
for (const name of initialToolNames) {
|
|
2463
2577
|
const tool = toolRegistry.get(name);
|
|
2464
|
-
|
|
2578
|
+
const explicitlyRequested = explicitlyRequestedToolNameSet?.has(name) === true;
|
|
2579
|
+
if (tool && xdevReadAvailable && !explicitlyRequested && isMountableUnderXdev(tool))
|
|
2580
|
+
mountedTools.push(tool);
|
|
2465
2581
|
else topLevelToolNames.push(name);
|
|
2466
2582
|
}
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2583
|
+
const writeTransportAvailable = mountedTools.length === 0 || (await ensureWriteRegistered());
|
|
2584
|
+
if (writeTransportAvailable) {
|
|
2585
|
+
toolSession.xdevRegistry.reconcile(mountedTools);
|
|
2586
|
+
initialMountedXdevToolNames = mountedTools.map(tool => tool.name);
|
|
2587
|
+
initialToolNames = topLevelToolNames;
|
|
2588
|
+
if (initialMountedXdevToolNames.length > 0 && !initialToolNames.includes("write"))
|
|
2589
|
+
initialToolNames.push("write");
|
|
2590
|
+
} else {
|
|
2591
|
+
toolSession.xdevRegistry.reconcile([]);
|
|
2592
|
+
}
|
|
2470
2593
|
}
|
|
2471
2594
|
|
|
2472
2595
|
setActiveToolNames(initialToolNames);
|
|
@@ -2551,6 +2674,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2551
2674
|
const initialTools = initialToolNames
|
|
2552
2675
|
.map(name => toolRegistry.get(name))
|
|
2553
2676
|
.filter((tool): tool is AgentTool => tool !== undefined);
|
|
2677
|
+
const autoLearnCaptureTools = initialTools.filter(tool => tool.name === "manage_skill" || tool.name === "learn");
|
|
2554
2678
|
|
|
2555
2679
|
const openaiWebsocketSetting = settings.get("providers.openaiWebsockets") ?? "off";
|
|
2556
2680
|
const preferOpenAICodexWebsockets =
|
|
@@ -2577,6 +2701,17 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2577
2701
|
settings,
|
|
2578
2702
|
createSettingsAwareStreamFn(settings),
|
|
2579
2703
|
);
|
|
2704
|
+
const transformToolCallArguments = (args: Record<string, unknown>): Record<string, unknown> => {
|
|
2705
|
+
let result = args;
|
|
2706
|
+
const maxTimeout = settings.get("tools.maxTimeout");
|
|
2707
|
+
if (maxTimeout > 0 && typeof result.timeout === "number") {
|
|
2708
|
+
result = { ...result, timeout: Math.min(result.timeout, maxTimeout) };
|
|
2709
|
+
}
|
|
2710
|
+
if (obfuscator?.hasSecrets()) {
|
|
2711
|
+
result = deobfuscateToolArguments(obfuscator, result);
|
|
2712
|
+
}
|
|
2713
|
+
return result;
|
|
2714
|
+
};
|
|
2580
2715
|
agent = new Agent({
|
|
2581
2716
|
initialState: {
|
|
2582
2717
|
systemPrompt,
|
|
@@ -2629,17 +2764,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2629
2764
|
return settingsAwareStreamFn(streamModel, context, streamOptions);
|
|
2630
2765
|
},
|
|
2631
2766
|
cursorExecHandlers,
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
const maxTimeout = settings.get("tools.maxTimeout");
|
|
2635
|
-
if (maxTimeout > 0 && typeof result.timeout === "number") {
|
|
2636
|
-
result = { ...result, timeout: Math.min(result.timeout, maxTimeout) };
|
|
2637
|
-
}
|
|
2638
|
-
if (obfuscator?.hasSecrets()) {
|
|
2639
|
-
result = deobfuscateToolArguments(obfuscator, result);
|
|
2640
|
-
}
|
|
2641
|
-
return result;
|
|
2642
|
-
},
|
|
2767
|
+
getCursorTools: () => [...(toolSession.xdevRegistry?.list() ?? [])],
|
|
2768
|
+
transformToolCallArguments,
|
|
2643
2769
|
intentTracing: !!intentField,
|
|
2644
2770
|
pruneToolDescriptions: inlineToolDescriptors,
|
|
2645
2771
|
dialect: resolveDialect(settings.get("tools.format"), model),
|
|
@@ -2761,8 +2887,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2761
2887
|
getXdevToolEntries: () => toolSession.xdevRegistry?.entries() ?? [],
|
|
2762
2888
|
xdevRegistry: toolSession.xdevRegistry,
|
|
2763
2889
|
initialMountedXdevToolNames,
|
|
2764
|
-
|
|
2890
|
+
presentationPinnedToolNames: explicitlyRequestedToolNameSet,
|
|
2765
2891
|
setActiveToolNames,
|
|
2892
|
+
ensureWriteRegistered,
|
|
2766
2893
|
getMcpServerInstructions: mcpManager
|
|
2767
2894
|
? () => {
|
|
2768
2895
|
const raw = mcpManager.getServerInstructions();
|
|
@@ -2922,8 +3049,56 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2922
3049
|
});
|
|
2923
3050
|
};
|
|
2924
3051
|
|
|
2925
|
-
|
|
2926
|
-
|
|
3052
|
+
const runAutoLearnCapture = createAutoLearnCaptureRunner({
|
|
3053
|
+
sourceAgent: agent,
|
|
3054
|
+
captureTools: autoLearnCaptureTools,
|
|
3055
|
+
onPayload,
|
|
3056
|
+
onResponse,
|
|
3057
|
+
createAgent: captureOptions => {
|
|
3058
|
+
const captureModel = captureOptions.initialState?.model;
|
|
3059
|
+
const captureSessionId = captureOptions.sessionId;
|
|
3060
|
+
if (!captureModel || !captureSessionId) throw new Error("Auto-learn capture identity is incomplete");
|
|
3061
|
+
return new Agent({
|
|
3062
|
+
...captureOptions,
|
|
3063
|
+
cwd: sessionManager.getCwd(),
|
|
3064
|
+
cwdResolver: () => sessionManager.getCwd(),
|
|
3065
|
+
convertToLlm: convertToLlmFinal,
|
|
3066
|
+
transformContext: async messages => wrapSteeringForModel(messages),
|
|
3067
|
+
transformProviderContext: async (context, transformModel) => {
|
|
3068
|
+
const transformed = obfuscator ? obfuscateProviderContext(obfuscator, context) : context;
|
|
3069
|
+
return clampProviderContextImages(transformed, transformModel);
|
|
3070
|
+
},
|
|
3071
|
+
thinkingBudgets: agent.thinkingBudgets,
|
|
3072
|
+
temperature: agent.temperature,
|
|
3073
|
+
topP: agent.topP,
|
|
3074
|
+
topK: agent.topK,
|
|
3075
|
+
minP: agent.minP,
|
|
3076
|
+
presencePenalty: agent.presencePenalty,
|
|
3077
|
+
repetitionPenalty: agent.repetitionPenalty,
|
|
3078
|
+
serviceTierResolver: agent.serviceTierResolver,
|
|
3079
|
+
hideThinkingSummary: agent.hideThinkingSummary,
|
|
3080
|
+
maxRetryDelayMs: agent.maxRetryDelayMs,
|
|
3081
|
+
kimiApiFormat: settings.get("providers.kimiApiFormat") ?? "anthropic",
|
|
3082
|
+
preferWebsockets: preferOpenAICodexWebsockets,
|
|
3083
|
+
getToolContext: toolCall => toolContextStore.getContext(toolCall),
|
|
3084
|
+
streamFn: settingsAwareStreamFn,
|
|
3085
|
+
transformToolCallArguments,
|
|
3086
|
+
intentTracing: !!intentField,
|
|
3087
|
+
pruneToolDescriptions: inlineToolDescriptors,
|
|
3088
|
+
dialect: resolveDialect(settings.get("tools.format"), captureModel),
|
|
3089
|
+
abortOnFabricatedToolResult: settings.get("tools.abortOnFabricatedResult"),
|
|
3090
|
+
appendOnlyContext: shouldEnableAppendOnlyContext(
|
|
3091
|
+
settings.get("provider.appendOnlyContext"),
|
|
3092
|
+
captureModel,
|
|
3093
|
+
)
|
|
3094
|
+
? new AppendOnlyContextManager()
|
|
3095
|
+
: undefined,
|
|
3096
|
+
});
|
|
3097
|
+
},
|
|
3098
|
+
});
|
|
3099
|
+
|
|
3100
|
+
// Auto-learn can immediately trigger a private capture after the first real
|
|
3101
|
+
// stop. When a memory backend is selected, install that backend's
|
|
2927
3102
|
// per-session state first so the capture turn's `learn` tool observes the
|
|
2928
3103
|
// same initialized state as normal memory tools. Other sessions keep memory
|
|
2929
3104
|
// startup in the background to preserve the existing startup profile.
|
|
@@ -2938,7 +3113,11 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2938
3113
|
// reference is intentionally discarded (the listener retains it).
|
|
2939
3114
|
if (settings.get("autolearn.enabled") && taskDepth === 0) {
|
|
2940
3115
|
await logger.time("startMemoryStartupTask", startMemoryBackend);
|
|
2941
|
-
new AutoLearnController({
|
|
3116
|
+
new AutoLearnController({
|
|
3117
|
+
session,
|
|
3118
|
+
settings,
|
|
3119
|
+
capture: content => session.runAutolearnCapture(signal => runAutoLearnCapture(content, signal)),
|
|
3120
|
+
});
|
|
2942
3121
|
} else {
|
|
2943
3122
|
void logger.time("startMemoryStartupTask", startMemoryBackend);
|
|
2944
3123
|
}
|