@oh-my-pi/pi-coding-agent 13.19.0 → 14.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 +266 -1
- package/package.json +86 -20
- package/scripts/format-prompts.ts +2 -2
- package/src/autoresearch/apply-contract-to-state.ts +24 -0
- package/src/autoresearch/contract.ts +0 -44
- package/src/autoresearch/dashboard.ts +1 -2
- package/src/autoresearch/git.ts +91 -0
- package/src/autoresearch/helpers.ts +49 -0
- package/src/autoresearch/index.ts +28 -187
- package/src/autoresearch/prompt.md +26 -9
- package/src/autoresearch/state.ts +0 -6
- package/src/autoresearch/tools/init-experiment.ts +202 -117
- package/src/autoresearch/tools/log-experiment.ts +83 -125
- package/src/autoresearch/tools/run-experiment.ts +48 -10
- package/src/autoresearch/types.ts +2 -2
- package/src/capability/index.ts +4 -2
- package/src/cli/file-processor.ts +3 -3
- package/src/cli/grep-cli.ts +8 -8
- package/src/cli/grievances-cli.ts +78 -0
- package/src/cli/read-cli.ts +67 -0
- package/src/cli/setup-cli.ts +4 -4
- package/src/cli/update-cli.ts +3 -3
- package/src/cli.ts +2 -0
- package/src/commands/grep.ts +6 -1
- package/src/commands/grievances.ts +20 -0
- package/src/commands/read.ts +33 -0
- package/src/commit/agentic/agent.ts +5 -5
- package/src/commit/agentic/index.ts +3 -4
- package/src/commit/agentic/tools/analyze-file.ts +3 -3
- package/src/commit/agentic/validation.ts +1 -1
- package/src/commit/analysis/conventional.ts +4 -4
- package/src/commit/analysis/summary.ts +3 -3
- package/src/commit/changelog/generate.ts +4 -4
- package/src/commit/map-reduce/map-phase.ts +4 -4
- package/src/commit/map-reduce/reduce-phase.ts +4 -4
- package/src/commit/pipeline.ts +3 -4
- package/src/config/prompt-templates.ts +44 -226
- package/src/config/resolve-config-value.ts +4 -2
- package/src/config/settings-schema.ts +54 -2
- package/src/config/settings.ts +25 -26
- package/src/dap/client.ts +674 -0
- package/src/dap/config.ts +150 -0
- package/src/dap/defaults.json +211 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1255 -0
- package/src/dap/types.ts +600 -0
- package/src/debug/log-viewer.ts +3 -2
- package/src/discovery/builtin.ts +1 -2
- package/src/discovery/codex.ts +2 -2
- package/src/discovery/github.ts +2 -1
- package/src/discovery/helpers.ts +2 -2
- package/src/discovery/opencode.ts +2 -2
- package/src/edit/diff.ts +818 -0
- package/src/edit/index.ts +309 -0
- package/src/edit/line-hash.ts +67 -0
- package/src/edit/modes/chunk.ts +454 -0
- package/src/{patch → edit/modes}/hashline.ts +741 -361
- package/src/{patch/applicator.ts → edit/modes/patch.ts} +420 -117
- package/src/{patch/fuzzy.ts → edit/modes/replace.ts} +519 -197
- package/src/{patch → edit}/normalize.ts +97 -76
- package/src/{patch/shared.ts → edit/renderer.ts} +181 -108
- package/src/exec/bash-executor.ts +4 -2
- package/src/exec/idle-timeout-watchdog.ts +126 -0
- package/src/exec/non-interactive-env.ts +5 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +2 -2
- package/src/extensibility/custom-commands/bundled/review/index.ts +2 -2
- package/src/extensibility/custom-commands/loader.ts +1 -2
- package/src/extensibility/custom-tools/loader.ts +34 -11
- package/src/extensibility/extensions/loader.ts +9 -4
- package/src/extensibility/extensions/runner.ts +24 -1
- package/src/extensibility/extensions/types.ts +1 -1
- package/src/extensibility/hooks/loader.ts +5 -6
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/extensibility/plugins/doctor.ts +2 -1
- package/src/extensibility/slash-commands.ts +3 -7
- package/src/index.ts +2 -1
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/ipy/executor.ts +58 -17
- package/src/ipy/gateway-coordinator.ts +6 -4
- package/src/ipy/kernel.ts +45 -22
- package/src/ipy/runtime.ts +2 -2
- package/src/lsp/client.ts +7 -4
- package/src/lsp/clients/lsp-linter-client.ts +4 -4
- package/src/lsp/config.ts +2 -2
- package/src/lsp/defaults.json +688 -154
- package/src/lsp/index.ts +234 -45
- package/src/lsp/lspmux.ts +2 -2
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +12 -1
- package/src/lsp/utils.ts +8 -1
- package/src/main.ts +102 -46
- package/src/memories/index.ts +4 -5
- package/src/modes/acp/acp-agent.ts +563 -163
- package/src/modes/acp/acp-event-mapper.ts +9 -1
- package/src/modes/acp/acp-mode.ts +4 -2
- package/src/modes/components/agent-dashboard.ts +3 -4
- package/src/modes/components/diff.ts +6 -7
- package/src/modes/components/read-tool-group.ts +6 -12
- package/src/modes/components/settings-defs.ts +5 -0
- package/src/modes/components/tool-execution.ts +1 -1
- package/src/modes/components/welcome.ts +1 -1
- package/src/modes/controllers/btw-controller.ts +2 -2
- package/src/modes/controllers/command-controller.ts +3 -2
- package/src/modes/controllers/input-controller.ts +12 -8
- package/src/modes/index.ts +20 -2
- package/src/modes/interactive-mode.ts +94 -37
- package/src/modes/rpc/host-tools.ts +186 -0
- package/src/modes/rpc/rpc-client.ts +178 -13
- package/src/modes/rpc/rpc-mode.ts +73 -3
- package/src/modes/rpc/rpc-types.ts +53 -1
- package/src/modes/theme/theme.ts +80 -8
- package/src/modes/types.ts +2 -2
- package/src/prompts/system/system-prompt.md +2 -1
- package/src/prompts/tools/chunk-edit.md +219 -0
- package/src/prompts/tools/debug.md +43 -0
- package/src/prompts/tools/grep.md +3 -0
- package/src/prompts/tools/lsp.md +5 -5
- package/src/prompts/tools/read-chunk.md +17 -0
- package/src/prompts/tools/read.md +19 -5
- package/src/sdk.ts +190 -154
- package/src/secrets/obfuscator.ts +1 -1
- package/src/session/agent-session.ts +306 -256
- package/src/session/agent-storage.ts +12 -12
- package/src/session/compaction/branch-summarization.ts +3 -3
- package/src/session/compaction/compaction.ts +5 -6
- package/src/session/compaction/utils.ts +3 -3
- package/src/session/history-storage.ts +62 -19
- package/src/session/messages.ts +3 -3
- package/src/session/session-dump-format.ts +203 -0
- package/src/session/session-storage.ts +4 -2
- package/src/session/streaming-output.ts +1 -1
- package/src/session/tool-choice-queue.ts +213 -0
- package/src/slash-commands/builtin-registry.ts +56 -8
- package/src/ssh/connection-manager.ts +2 -2
- package/src/ssh/sshfs-mount.ts +5 -5
- package/src/stt/downloader.ts +4 -4
- package/src/stt/recorder.ts +4 -4
- package/src/stt/transcriber.ts +2 -2
- package/src/system-prompt.ts +21 -13
- package/src/task/agents.ts +5 -6
- package/src/task/commands.ts +2 -5
- package/src/task/executor.ts +4 -4
- package/src/task/index.ts +3 -4
- package/src/task/template.ts +2 -2
- package/src/task/worktree.ts +4 -4
- package/src/tools/ask.ts +2 -3
- package/src/tools/ast-edit.ts +7 -7
- package/src/tools/ast-grep.ts +7 -7
- package/src/tools/auto-generated-guard.ts +36 -41
- package/src/tools/await-tool.ts +2 -2
- package/src/tools/bash.ts +5 -23
- package/src/tools/browser.ts +4 -5
- package/src/tools/calculator.ts +2 -3
- package/src/tools/cancel-job.ts +2 -2
- package/src/tools/checkpoint.ts +3 -3
- package/src/tools/debug.ts +1007 -0
- package/src/tools/exit-plan-mode.ts +2 -3
- package/src/tools/fetch.ts +67 -3
- package/src/tools/find.ts +4 -5
- package/src/tools/fs-cache-invalidation.ts +5 -0
- package/src/tools/gemini-image.ts +13 -5
- package/src/tools/gh.ts +10 -11
- package/src/tools/grep.ts +57 -9
- package/src/tools/index.ts +44 -22
- package/src/tools/inspect-image.ts +4 -4
- package/src/tools/output-meta.ts +1 -1
- package/src/tools/python.ts +19 -6
- package/src/tools/read.ts +198 -67
- package/src/tools/render-mermaid.ts +2 -3
- package/src/tools/render-utils.ts +20 -6
- package/src/tools/renderers.ts +3 -1
- package/src/tools/report-tool-issue.ts +80 -0
- package/src/tools/resolve.ts +70 -39
- package/src/tools/search-tool-bm25.ts +2 -2
- package/src/tools/ssh.ts +2 -2
- package/src/tools/todo-write.ts +2 -2
- package/src/tools/tool-timeouts.ts +1 -0
- package/src/tools/write.ts +5 -6
- package/src/tui/tree-list.ts +3 -1
- package/src/utils/clipboard.ts +80 -0
- package/src/utils/commit-message-generator.ts +2 -3
- package/src/utils/edit-mode.ts +49 -0
- package/src/utils/file-display-mode.ts +6 -5
- package/src/utils/file-mentions.ts +8 -7
- package/src/utils/git.ts +4 -4
- package/src/utils/image-loading.ts +98 -0
- package/src/utils/title-generator.ts +2 -3
- package/src/utils/tools-manager.ts +6 -6
- package/src/web/scrapers/choosealicense.ts +1 -1
- package/src/web/search/index.ts +3 -3
- package/src/autoresearch/command-initialize.md +0 -34
- package/src/patch/diff.ts +0 -433
- package/src/patch/index.ts +0 -888
- package/src/patch/parser.ts +0 -532
- package/src/patch/types.ts +0 -292
- package/src/prompts/agents/oracle.md +0 -77
- package/src/tools/pending-action.ts +0 -49
- package/src/utils/child-process.ts +0 -88
- package/src/utils/frontmatter.ts +0 -117
- package/src/utils/image-input.ts +0 -274
- package/src/utils/mime.ts +0 -53
- package/src/utils/prompt-format.ts +0 -170
package/src/sdk.ts
CHANGED
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
type ThinkingLevel,
|
|
8
8
|
} from "@oh-my-pi/pi-agent-core";
|
|
9
9
|
import type { Message, Model } from "@oh-my-pi/pi-ai";
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import {
|
|
11
|
+
getOpenAICodexTransportDetails,
|
|
12
|
+
prewarmOpenAICodexResponses,
|
|
13
|
+
} from "@oh-my-pi/pi-ai/providers/openai-codex-responses";
|
|
12
14
|
import { SearchDb } from "@oh-my-pi/pi-natives";
|
|
13
15
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
14
16
|
import {
|
|
@@ -19,6 +21,7 @@ import {
|
|
|
19
21
|
getSearchDbDir,
|
|
20
22
|
logger,
|
|
21
23
|
postmortem,
|
|
24
|
+
prompt,
|
|
22
25
|
} from "@oh-my-pi/pi-utils";
|
|
23
26
|
import chalk from "chalk";
|
|
24
27
|
import { AsyncJobManager } from "./async";
|
|
@@ -27,11 +30,7 @@ import { loadCapability } from "./capability";
|
|
|
27
30
|
import { type Rule, ruleCapability } from "./capability/rule";
|
|
28
31
|
import { ModelRegistry } from "./config/model-registry";
|
|
29
32
|
import { formatModelString, parseModelPattern, parseModelString, resolveModelRoleValue } from "./config/model-resolver";
|
|
30
|
-
import {
|
|
31
|
-
loadPromptTemplates as loadPromptTemplatesInternal,
|
|
32
|
-
type PromptTemplate,
|
|
33
|
-
renderPromptTemplate,
|
|
34
|
-
} from "./config/prompt-templates";
|
|
33
|
+
import { loadPromptTemplates as loadPromptTemplatesInternal, type PromptTemplate } from "./config/prompt-templates";
|
|
35
34
|
import { Settings, type SkillsSettings } from "./config/settings";
|
|
36
35
|
import { CursorExecHandlers } from "./cursor";
|
|
37
36
|
import "./discovery";
|
|
@@ -74,6 +73,7 @@ import {
|
|
|
74
73
|
SkillProtocolHandler,
|
|
75
74
|
} from "./internal-urls";
|
|
76
75
|
import { disposeAllKernelSessions } from "./ipy/executor";
|
|
76
|
+
import { LSP_STARTUP_EVENT_CHANNEL, type LspStartupEvent } from "./lsp/startup-events";
|
|
77
77
|
import { discoverAndLoadMCPTools, type MCPManager, type MCPToolsLoadResult } from "./mcp";
|
|
78
78
|
import {
|
|
79
79
|
collectDiscoverableMCPTools,
|
|
@@ -107,12 +107,14 @@ import {
|
|
|
107
107
|
BashTool,
|
|
108
108
|
BUILTIN_TOOLS,
|
|
109
109
|
createTools,
|
|
110
|
+
discoverStartupLspServers,
|
|
110
111
|
EditTool,
|
|
111
112
|
FindTool,
|
|
112
113
|
GrepTool,
|
|
113
114
|
getSearchTools,
|
|
114
115
|
HIDDEN_TOOLS,
|
|
115
116
|
isSearchProviderPreference,
|
|
117
|
+
type LspStartupServerInfo,
|
|
116
118
|
loadSshTool,
|
|
117
119
|
PythonTool,
|
|
118
120
|
ReadTool,
|
|
@@ -128,8 +130,9 @@ import {
|
|
|
128
130
|
import { ToolContextStore } from "./tools/context";
|
|
129
131
|
import { getGeminiImageTools } from "./tools/gemini-image";
|
|
130
132
|
import { wrapToolWithMetaNotice } from "./tools/output-meta";
|
|
131
|
-
import {
|
|
133
|
+
import { queueResolveHandler } from "./tools/resolve";
|
|
132
134
|
import { EventBus } from "./utils/event-bus";
|
|
135
|
+
import { buildNamedToolChoice } from "./utils/tool-choice";
|
|
133
136
|
|
|
134
137
|
// Types
|
|
135
138
|
export interface CreateAgentSessionOptions {
|
|
@@ -233,8 +236,8 @@ export interface CreateAgentSessionResult {
|
|
|
233
236
|
mcpManager?: MCPManager;
|
|
234
237
|
/** Warning if session was restored with a different model than saved */
|
|
235
238
|
modelFallbackMessage?: string;
|
|
236
|
-
/** LSP servers
|
|
237
|
-
lspServers?:
|
|
239
|
+
/** LSP servers detected for startup; warmup may continue in the background */
|
|
240
|
+
lspServers?: LspStartupServerInfo[];
|
|
238
241
|
/** Shared event bus for tool/extension communication */
|
|
239
242
|
eventBus: EventBus;
|
|
240
243
|
}
|
|
@@ -646,17 +649,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
646
649
|
registerPythonCleanup();
|
|
647
650
|
|
|
648
651
|
// Use provided or create AuthStorage and ModelRegistry
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
const modelRegistry = options.modelRegistry ?? new ModelRegistry(authStorage);
|
|
652
|
-
return { authStorage, modelRegistry };
|
|
653
|
-
});
|
|
652
|
+
const authStorage = options.authStorage ?? (await logger.time("discoverModels", discoverAuthStorage, agentDir));
|
|
653
|
+
const modelRegistry = options.modelRegistry ?? new ModelRegistry(authStorage);
|
|
654
654
|
|
|
655
|
-
const settings = await logger.
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
);
|
|
659
|
-
logger.time("initializeWithSettings", initializeWithSettings, settings);
|
|
655
|
+
const settings = options.settings ?? (await logger.time("settings", Settings.init, { cwd, agentDir }));
|
|
656
|
+
logger.time("initializeWithSettings");
|
|
657
|
+
initializeWithSettings(settings);
|
|
660
658
|
if (!options.modelRegistry) {
|
|
661
659
|
modelRegistry.refreshInBackground();
|
|
662
660
|
}
|
|
@@ -703,7 +701,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
703
701
|
// reflect actual loaded secrets, not just the setting toggle.
|
|
704
702
|
let obfuscator: SecretObfuscator | undefined;
|
|
705
703
|
if (settings.get("secrets.enabled")) {
|
|
706
|
-
const fileEntries = await logger.
|
|
704
|
+
const fileEntries = await logger.time("loadSecrets", loadSecrets, cwd, agentDir);
|
|
707
705
|
const envEntries = collectEnvSecrets();
|
|
708
706
|
const allEntries = [...envEntries, ...fileEntries];
|
|
709
707
|
if (allEntries.length > 0) {
|
|
@@ -713,10 +711,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
713
711
|
const secretsEnabled = obfuscator?.hasSecrets() === true;
|
|
714
712
|
|
|
715
713
|
// Check if session has existing data to restore
|
|
716
|
-
const existingSession = logger.time("
|
|
714
|
+
const existingSession = logger.time("loadSessionContext", () =>
|
|
717
715
|
deobfuscateSessionContext(sessionManager.buildSessionContext(), obfuscator),
|
|
718
716
|
);
|
|
719
|
-
const existingBranch = sessionManager.getBranch();
|
|
717
|
+
const existingBranch = logger.time("getSessionBranch", () => sessionManager.getBranch());
|
|
720
718
|
const hasExistingSession = existingBranch.length > 0;
|
|
721
719
|
const hasThinkingEntry = existingBranch.some(entry => entry.type === "thinking_level_change");
|
|
722
720
|
const hasServiceTierEntry = existingBranch.some(entry => entry.type === "service_tier_change");
|
|
@@ -725,34 +723,41 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
725
723
|
const modelMatchPreferences = {
|
|
726
724
|
usageOrder: settings.getStorage()?.getModelUsageOrder(),
|
|
727
725
|
};
|
|
728
|
-
const defaultRoleSpec =
|
|
729
|
-
settings,
|
|
730
|
-
|
|
731
|
-
|
|
726
|
+
const defaultRoleSpec = logger.time("resolveDefaultModelRole", () =>
|
|
727
|
+
resolveModelRoleValue(settings.getModelRole("default"), modelRegistry.getAvailable(), {
|
|
728
|
+
settings,
|
|
729
|
+
matchPreferences: modelMatchPreferences,
|
|
730
|
+
}),
|
|
731
|
+
);
|
|
732
732
|
let model = options.model;
|
|
733
733
|
let modelFallbackMessage: string | undefined;
|
|
734
734
|
// If session has data, try to restore model from it.
|
|
735
735
|
// Skip restore when an explicit model was requested.
|
|
736
736
|
const defaultModelStr = existingSession.models.default;
|
|
737
737
|
if (!hasExplicitModel && !model && hasExistingSession && defaultModelStr) {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
738
|
+
await logger.time("restoreSessionModel", async () => {
|
|
739
|
+
const parsedModel = parseModelString(defaultModelStr);
|
|
740
|
+
if (parsedModel) {
|
|
741
|
+
const restoredModel = modelRegistry.find(parsedModel.provider, parsedModel.id);
|
|
742
|
+
if (restoredModel && (await hasModelApiKey(restoredModel))) {
|
|
743
|
+
model = restoredModel;
|
|
744
|
+
}
|
|
743
745
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
746
|
+
if (!model) {
|
|
747
|
+
modelFallbackMessage = `Could not restore model ${defaultModelStr}`;
|
|
748
|
+
}
|
|
749
|
+
});
|
|
748
750
|
}
|
|
749
751
|
|
|
750
752
|
// If still no model, try settings default.
|
|
751
753
|
// Skip settings fallback when an explicit model was requested.
|
|
752
754
|
if (!hasExplicitModel && !model && defaultRoleSpec.model) {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
755
|
+
const settingsDefaultModel = defaultRoleSpec.model;
|
|
756
|
+
logger.time("resolveSettingsDefaultModel", () => {
|
|
757
|
+
// defaultRoleSpec.model already comes from modelRegistry.getAvailable(),
|
|
758
|
+
// so re-validating auth here just repeats the expensive lookup path.
|
|
759
|
+
model = settingsDefaultModel;
|
|
760
|
+
});
|
|
756
761
|
}
|
|
757
762
|
|
|
758
763
|
const taskDepth = options.taskDepth ?? 0;
|
|
@@ -773,7 +778,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
773
778
|
thinkingLevel = settings.get("defaultThinkingLevel");
|
|
774
779
|
}
|
|
775
780
|
if (model) {
|
|
776
|
-
|
|
781
|
+
const resolvedModel = model;
|
|
782
|
+
thinkingLevel = logger.time("resolveThinkingLevelForModel", () =>
|
|
783
|
+
resolveThinkingLevelForModel(resolvedModel, thinkingLevel),
|
|
784
|
+
);
|
|
777
785
|
}
|
|
778
786
|
|
|
779
787
|
let skills: Skill[];
|
|
@@ -782,55 +790,44 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
782
790
|
skills = options.skills;
|
|
783
791
|
skillWarnings = [];
|
|
784
792
|
} else {
|
|
785
|
-
const discovered = await logger.
|
|
786
|
-
|
|
793
|
+
const discovered = await logger.time(
|
|
794
|
+
"discoverSkills",
|
|
795
|
+
() => discoveredSkillsPromise ?? Promise.resolve({ skills: [], warnings: [] }),
|
|
787
796
|
);
|
|
788
797
|
skills = discovered.skills;
|
|
789
798
|
skillWarnings = discovered.warnings;
|
|
790
799
|
}
|
|
791
800
|
|
|
792
|
-
// Discover rules
|
|
793
|
-
const { ttsrManager,
|
|
794
|
-
"
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
registeredTtsrRuleNames.add(rule.name);
|
|
807
|
-
}
|
|
808
|
-
}
|
|
801
|
+
// Discover rules and bucket them in one pass to avoid repeated scans over large rule sets.
|
|
802
|
+
const { ttsrManager, rulebookRules, alwaysApplyRules } = await logger.time("discoverTtsrRules", async () => {
|
|
803
|
+
const ttsrSettings = settings.getGroup("ttsr");
|
|
804
|
+
const ttsrManager = new TtsrManager(ttsrSettings);
|
|
805
|
+
const rulesResult =
|
|
806
|
+
options.rules !== undefined
|
|
807
|
+
? { items: options.rules, warnings: undefined }
|
|
808
|
+
: await loadCapability<Rule>(ruleCapability.id, { cwd });
|
|
809
|
+
const rulebookRules: Rule[] = [];
|
|
810
|
+
const alwaysApplyRules: Rule[] = [];
|
|
811
|
+
for (const rule of rulesResult.items) {
|
|
812
|
+
const isTtsrRule = rule.condition && rule.condition.length > 0 ? ttsrManager.addRule(rule) : false;
|
|
813
|
+
if (isTtsrRule) {
|
|
814
|
+
continue;
|
|
809
815
|
}
|
|
810
|
-
if (
|
|
811
|
-
|
|
816
|
+
if (rule.alwaysApply === true) {
|
|
817
|
+
alwaysApplyRules.push(rule);
|
|
818
|
+
continue;
|
|
812
819
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
if (rule.alwaysApply) return false;
|
|
822
|
-
if (!rule.description) return false;
|
|
823
|
-
return true;
|
|
824
|
-
}),
|
|
825
|
-
);
|
|
826
|
-
|
|
827
|
-
// collect alwaysApply rules — full content injected into system prompt
|
|
828
|
-
const alwaysApplyRules = rulesResult.items.filter((rule: Rule) => {
|
|
829
|
-
if (registeredTtsrRuleNames.has(rule.name)) return false;
|
|
830
|
-
return rule.alwaysApply === true;
|
|
820
|
+
if (rule.description) {
|
|
821
|
+
rulebookRules.push(rule);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
if (existingSession.injectedTtsrRules.length > 0) {
|
|
825
|
+
ttsrManager.restoreInjected(existingSession.injectedTtsrRules);
|
|
826
|
+
}
|
|
827
|
+
return { ttsrManager, rulebookRules, alwaysApplyRules };
|
|
831
828
|
});
|
|
832
829
|
|
|
833
|
-
const contextFiles = await logger.
|
|
830
|
+
const contextFiles = await logger.time(
|
|
834
831
|
"discoverContextFiles",
|
|
835
832
|
async () => options.contextFiles ?? (await discoverContextFiles(cwd, agentDir)),
|
|
836
833
|
);
|
|
@@ -869,7 +866,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
869
866
|
onJobComplete: async (jobId, result, job) => {
|
|
870
867
|
if (!session) return;
|
|
871
868
|
const formattedResult = await formatAsyncResultForFollowUp(result);
|
|
872
|
-
const message =
|
|
869
|
+
const message = prompt.render(asyncResultTemplate, { jobId, result: formattedResult });
|
|
873
870
|
const durationMs = job ? Math.max(0, Date.now() - job.startTime) : undefined;
|
|
874
871
|
await session.sendCustomMessage(
|
|
875
872
|
{
|
|
@@ -891,7 +888,6 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
891
888
|
: undefined;
|
|
892
889
|
|
|
893
890
|
const searchDb = options.searchDb ?? new SearchDb(getSearchDbDir(agentDir));
|
|
894
|
-
const pendingActionStore = new PendingActionStore();
|
|
895
891
|
const toolSession: ToolSession = {
|
|
896
892
|
cwd,
|
|
897
893
|
hasUI: options.hasUI ?? false,
|
|
@@ -928,6 +924,22 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
928
924
|
activateDiscoveredMCPTools: toolNames => session.activateDiscoveredMCPTools(toolNames),
|
|
929
925
|
getCheckpointState: () => session.getCheckpointState(),
|
|
930
926
|
setCheckpointState: state => session.setCheckpointState(state ?? undefined),
|
|
927
|
+
getToolChoiceQueue: () => session.toolChoiceQueue,
|
|
928
|
+
buildToolChoice: name => {
|
|
929
|
+
const m = session.model;
|
|
930
|
+
return m ? buildNamedToolChoice(name, m) : undefined;
|
|
931
|
+
},
|
|
932
|
+
steer: msg =>
|
|
933
|
+
session.agent.steer({
|
|
934
|
+
role: "custom",
|
|
935
|
+
customType: msg.customType,
|
|
936
|
+
content: msg.content,
|
|
937
|
+
display: false,
|
|
938
|
+
details: msg.details,
|
|
939
|
+
attribution: "agent",
|
|
940
|
+
timestamp: Date.now(),
|
|
941
|
+
}),
|
|
942
|
+
peekQueueInvoker: () => session.peekQueueInvoker(),
|
|
931
943
|
allocateOutputArtifact: async toolType => {
|
|
932
944
|
try {
|
|
933
945
|
return await sessionManager.allocateArtifactPath(toolType);
|
|
@@ -939,7 +951,6 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
939
951
|
authStorage,
|
|
940
952
|
modelRegistry,
|
|
941
953
|
asyncJobManager,
|
|
942
|
-
pendingActionStore,
|
|
943
954
|
searchDb,
|
|
944
955
|
};
|
|
945
956
|
|
|
@@ -980,29 +991,27 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
980
991
|
);
|
|
981
992
|
|
|
982
993
|
// Create built-in tools (already wrapped with meta notice formatting)
|
|
983
|
-
const builtinTools = await logger.
|
|
994
|
+
const builtinTools = await logger.time("createAllTools", createTools, toolSession, options.toolNames);
|
|
984
995
|
|
|
985
996
|
// Discover MCP tools from .mcp.json files
|
|
986
997
|
let mcpManager: MCPManager | undefined;
|
|
987
998
|
const enableMCP = options.enableMCP ?? true;
|
|
988
999
|
const customTools: CustomTool[] = [];
|
|
989
1000
|
if (enableMCP) {
|
|
990
|
-
const mcpResult = await logger.
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
}),
|
|
1005
|
-
);
|
|
1001
|
+
const mcpResult = await logger.time("discoverAndLoadMCPTools", discoverAndLoadMCPTools, cwd, {
|
|
1002
|
+
onConnecting: serverNames => {
|
|
1003
|
+
if (options.hasUI && serverNames.length > 0) {
|
|
1004
|
+
process.stderr.write(`${chalk.gray(`Connecting to MCP servers: ${serverNames.join(", ")}…`)}\n`);
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
enableProjectConfig: settings.get("mcp.enableProjectConfig") ?? true,
|
|
1008
|
+
// Always filter Exa - we have native integration
|
|
1009
|
+
filterExa: true,
|
|
1010
|
+
// Filter browser MCP servers when builtin browser tool is active
|
|
1011
|
+
filterBrowser: settings.get("browser.enabled") ?? false,
|
|
1012
|
+
cacheStorage: settings.getStorage(),
|
|
1013
|
+
authStorage,
|
|
1014
|
+
});
|
|
1006
1015
|
mcpManager = mcpResult.manager;
|
|
1007
1016
|
toolSession.mcpManager = mcpManager;
|
|
1008
1017
|
|
|
@@ -1026,7 +1035,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1026
1035
|
}
|
|
1027
1036
|
|
|
1028
1037
|
// Add Gemini image tools if GEMINI_API_KEY (or GOOGLE_API_KEY) is available
|
|
1029
|
-
const geminiImageTools = await logger.
|
|
1038
|
+
const geminiImageTools = await logger.time("getGeminiImageTools", getGeminiImageTools);
|
|
1030
1039
|
if (geminiImageTools.length > 0) {
|
|
1031
1040
|
customTools.push(...(geminiImageTools as unknown as CustomTool[]));
|
|
1032
1041
|
}
|
|
@@ -1038,13 +1047,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1038
1047
|
|
|
1039
1048
|
// Discover and load custom tools from .omp/tools/, .claude/tools/, etc.
|
|
1040
1049
|
const builtInToolNames = builtinTools.map(t => t.name);
|
|
1041
|
-
const discoveredCustomTools = await logger.
|
|
1050
|
+
const discoveredCustomTools = await logger.time(
|
|
1042
1051
|
"discoverAndLoadCustomTools",
|
|
1043
1052
|
discoverAndLoadCustomTools,
|
|
1044
1053
|
[],
|
|
1045
1054
|
cwd,
|
|
1046
1055
|
builtInToolNames,
|
|
1047
|
-
|
|
1056
|
+
action => queueResolveHandler(toolSession, action),
|
|
1048
1057
|
);
|
|
1049
1058
|
for (const { path, error } of discoveredCustomTools.errors) {
|
|
1050
1059
|
logger.error("Custom tool load failed", { path, error });
|
|
@@ -1063,7 +1072,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1063
1072
|
let extensionsResult: LoadExtensionsResult;
|
|
1064
1073
|
if (options.disableExtensionDiscovery) {
|
|
1065
1074
|
const configuredPaths = options.additionalExtensionPaths ?? [];
|
|
1066
|
-
extensionsResult = await logger.
|
|
1075
|
+
extensionsResult = await logger.time("loadExtensions", loadExtensions, configuredPaths, cwd, eventBus);
|
|
1067
1076
|
for (const { path, error } of extensionsResult.errors) {
|
|
1068
1077
|
logger.error("Failed to load extension", { path, error });
|
|
1069
1078
|
}
|
|
@@ -1073,7 +1082,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1073
1082
|
// Merge CLI extension paths with settings extension paths
|
|
1074
1083
|
const configuredPaths = [...(options.additionalExtensionPaths ?? []), ...(settings.get("extensions") ?? [])];
|
|
1075
1084
|
const disabledExtensionIds = settings.get("disabledExtensions") ?? [];
|
|
1076
|
-
extensionsResult = await logger.
|
|
1085
|
+
extensionsResult = await logger.time(
|
|
1077
1086
|
"discoverAndLoadExtensions",
|
|
1078
1087
|
discoverAndLoadExtensions,
|
|
1079
1088
|
configuredPaths,
|
|
@@ -1154,7 +1163,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1154
1163
|
// Discover custom commands (TypeScript slash commands)
|
|
1155
1164
|
const customCommandsResult: CustomCommandsLoadResult = options.disableExtensionDiscovery
|
|
1156
1165
|
? { commands: [], errors: [] }
|
|
1157
|
-
: await logger.
|
|
1166
|
+
: await logger.time("discoverCustomCommands", loadCustomCommandsInternal, { cwd, agentDir });
|
|
1158
1167
|
if (!options.disableExtensionDiscovery) {
|
|
1159
1168
|
for (const { path, error } of customCommandsResult.errors) {
|
|
1160
1169
|
logger.error("Failed to load custom command", { path, error });
|
|
@@ -1237,7 +1246,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1237
1246
|
if (!hasDeferrableTools) {
|
|
1238
1247
|
toolRegistry.delete("resolve");
|
|
1239
1248
|
} else if (!toolRegistry.has("resolve")) {
|
|
1240
|
-
const resolveTool = await logger.
|
|
1249
|
+
const resolveTool = await logger.time("createTools:resolve:session", HIDDEN_TOOLS.resolve, toolSession);
|
|
1241
1250
|
if (resolveTool) {
|
|
1242
1251
|
toolRegistry.set(resolveTool.name, wrapToolWithMetaNotice(resolveTool));
|
|
1243
1252
|
}
|
|
@@ -1387,20 +1396,14 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1387
1396
|
}
|
|
1388
1397
|
}
|
|
1389
1398
|
|
|
1390
|
-
const systemPrompt = await logger.
|
|
1391
|
-
"buildSystemPrompt",
|
|
1392
|
-
rebuildSystemPrompt,
|
|
1393
|
-
initialToolNames,
|
|
1394
|
-
toolRegistry,
|
|
1395
|
-
);
|
|
1399
|
+
const systemPrompt = await logger.time("buildSystemPrompt", rebuildSystemPrompt, initialToolNames, toolRegistry);
|
|
1396
1400
|
|
|
1397
1401
|
const promptTemplates =
|
|
1398
|
-
options.promptTemplates ??
|
|
1399
|
-
(await logger.timeAsync("discoverPromptTemplates", discoverPromptTemplates, cwd, agentDir));
|
|
1402
|
+
options.promptTemplates ?? (await logger.time("discoverPromptTemplates", discoverPromptTemplates, cwd, agentDir));
|
|
1400
1403
|
toolSession.promptTemplates = promptTemplates;
|
|
1401
1404
|
|
|
1402
1405
|
const slashCommands =
|
|
1403
|
-
options.slashCommands ?? (await logger.
|
|
1406
|
+
options.slashCommands ?? (await logger.time("discoverSlashCommands", discoverSlashCommands, cwd));
|
|
1404
1407
|
|
|
1405
1408
|
// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)
|
|
1406
1409
|
const convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {
|
|
@@ -1515,13 +1518,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1515
1518
|
return result;
|
|
1516
1519
|
},
|
|
1517
1520
|
intentTracing: !!intentField,
|
|
1518
|
-
getToolChoice: () =>
|
|
1519
|
-
if (pendingActionStore.hasPending) {
|
|
1520
|
-
return { type: "function", name: "resolve" };
|
|
1521
|
-
}
|
|
1522
|
-
return session?.consumeNextToolChoiceOverride();
|
|
1523
|
-
},
|
|
1521
|
+
getToolChoice: () => session?.nextToolChoice(),
|
|
1524
1522
|
});
|
|
1523
|
+
|
|
1525
1524
|
cursorEventEmitter = event => agent.emitExternalEvent(event);
|
|
1526
1525
|
|
|
1527
1526
|
// Restore messages if session has existing data
|
|
@@ -1562,51 +1561,87 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1562
1561
|
ttsrManager,
|
|
1563
1562
|
obfuscator,
|
|
1564
1563
|
asyncJobManager,
|
|
1565
|
-
pendingActionStore,
|
|
1566
1564
|
searchDb,
|
|
1567
1565
|
});
|
|
1568
1566
|
|
|
1569
1567
|
if (model?.api === "openai-codex-responses") {
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1568
|
+
const codexModel = model;
|
|
1569
|
+
const codexTransport = getOpenAICodexTransportDetails(codexModel, {
|
|
1570
|
+
sessionId: providerSessionId,
|
|
1571
|
+
baseUrl: codexModel.baseUrl,
|
|
1572
|
+
preferWebsockets: preferOpenAICodexWebsockets,
|
|
1573
|
+
providerSessionState: session.providerSessionState,
|
|
1574
|
+
});
|
|
1575
|
+
if (codexTransport.websocketPreferred) {
|
|
1576
|
+
void (async () => {
|
|
1577
|
+
try {
|
|
1578
|
+
const codexPrewarmApiKey = await modelRegistry.getApiKey(codexModel, providerSessionId);
|
|
1579
|
+
if (!codexPrewarmApiKey) return;
|
|
1580
|
+
await logger.time("prewarmOpenAICodexResponses", prewarmOpenAICodexResponses, codexModel, {
|
|
1581
|
+
apiKey: codexPrewarmApiKey,
|
|
1582
|
+
sessionId: providerSessionId,
|
|
1583
|
+
preferWebsockets: preferOpenAICodexWebsockets,
|
|
1584
|
+
providerSessionState: session.providerSessionState,
|
|
1585
|
+
});
|
|
1586
|
+
} catch (error) {
|
|
1587
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1588
|
+
logger.debug("Codex websocket prewarm failed", {
|
|
1589
|
+
error: errorMessage,
|
|
1590
|
+
provider: codexModel.provider,
|
|
1591
|
+
model: codexModel.id,
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
})();
|
|
1583
1595
|
}
|
|
1584
1596
|
}
|
|
1585
1597
|
|
|
1586
|
-
//
|
|
1598
|
+
// Start LSP warmup in the background so startup does not block on language server initialization.
|
|
1587
1599
|
let lspServers: CreateAgentSessionResult["lspServers"];
|
|
1588
1600
|
if (enableLsp && settings.get("lsp.diagnosticsOnWrite")) {
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1601
|
+
lspServers = discoverStartupLspServers(cwd);
|
|
1602
|
+
if (lspServers.length > 0) {
|
|
1603
|
+
void (async () => {
|
|
1604
|
+
try {
|
|
1605
|
+
const result = await logger.time("warmupLspServers", warmupLspServers, cwd);
|
|
1606
|
+
const serversByName = new Map(result.servers.map(server => [server.name, server] as const));
|
|
1607
|
+
for (const server of lspServers ?? []) {
|
|
1608
|
+
const next = serversByName.get(server.name);
|
|
1609
|
+
if (!next) continue;
|
|
1610
|
+
server.status = next.status;
|
|
1611
|
+
server.fileTypes = next.fileTypes;
|
|
1612
|
+
server.error = next.error;
|
|
1594
1613
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1614
|
+
const event: LspStartupEvent = {
|
|
1615
|
+
type: "completed",
|
|
1616
|
+
servers: result.servers,
|
|
1617
|
+
};
|
|
1618
|
+
eventBus.emit(LSP_STARTUP_EVENT_CHANNEL, event);
|
|
1619
|
+
} catch (error) {
|
|
1620
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1621
|
+
logger.warn("LSP server warmup failed", { cwd, error: errorMessage });
|
|
1622
|
+
for (const server of lspServers ?? []) {
|
|
1623
|
+
server.status = "error";
|
|
1624
|
+
server.error = errorMessage;
|
|
1625
|
+
}
|
|
1626
|
+
const event: LspStartupEvent = {
|
|
1627
|
+
type: "failed",
|
|
1628
|
+
error: errorMessage,
|
|
1629
|
+
};
|
|
1630
|
+
eventBus.emit(LSP_STARTUP_EVENT_CHANNEL, event);
|
|
1631
|
+
}
|
|
1632
|
+
})();
|
|
1600
1633
|
}
|
|
1601
1634
|
}
|
|
1602
1635
|
|
|
1603
|
-
startMemoryStartupTask(
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1636
|
+
logger.time("startMemoryStartupTask", () =>
|
|
1637
|
+
startMemoryStartupTask({
|
|
1638
|
+
session,
|
|
1639
|
+
settings,
|
|
1640
|
+
modelRegistry,
|
|
1641
|
+
agentDir,
|
|
1642
|
+
taskDepth,
|
|
1643
|
+
}),
|
|
1644
|
+
);
|
|
1610
1645
|
|
|
1611
1646
|
// Wire MCP manager callbacks to session for reactive tool updates
|
|
1612
1647
|
if (mcpManager) {
|
|
@@ -1646,6 +1681,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1646
1681
|
});
|
|
1647
1682
|
}
|
|
1648
1683
|
|
|
1684
|
+
logger.time("createAgentSession:return");
|
|
1649
1685
|
return {
|
|
1650
1686
|
session,
|
|
1651
1687
|
extensionsResult,
|
|
@@ -172,7 +172,7 @@ export class SecretObfuscator {
|
|
|
172
172
|
|
|
173
173
|
/** Deobfuscate obfuscate-mode placeholders back to original secrets. Replace-mode is NOT reversed. */
|
|
174
174
|
deobfuscate(text: string): string {
|
|
175
|
-
if (!this.#hasAny) return text;
|
|
175
|
+
if (!this.#hasAny || !text.includes("#")) return text;
|
|
176
176
|
return text.replace(PLACEHOLDER_RE, match => {
|
|
177
177
|
return this.#deobfuscateMap.get(match) ?? match;
|
|
178
178
|
});
|