oh-my-opencode 3.15.1 → 3.15.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/dist/agents/hephaestus/gpt-5-4.d.ts +22 -1
- package/dist/cli/index.js +51 -31
- package/dist/create-runtime-tmux-config.d.ts +1 -0
- package/dist/features/background-agent/spawner.d.ts +3 -0
- package/dist/features/claude-code-plugin-loader/discovery.d.ts +2 -1
- package/dist/features/claude-code-plugin-loader/loader.d.ts +1 -0
- package/dist/features/claude-code-plugin-loader/types.d.ts +10 -0
- package/dist/hooks/auto-update-checker/constants.d.ts +3 -3
- package/dist/index.js +381 -316
- package/dist/plugin/tool-registry.d.ts +1 -0
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -17496,7 +17496,7 @@ function getOpenCodeConfigPaths(options) {
|
|
|
17496
17496
|
configJson: join6(configDir, "opencode.json"),
|
|
17497
17497
|
configJsonc: join6(configDir, "opencode.jsonc"),
|
|
17498
17498
|
packageJson: join6(configDir, "package.json"),
|
|
17499
|
-
omoConfig: join6(configDir,
|
|
17499
|
+
omoConfig: join6(configDir, `${CONFIG_BASENAME}.json`)
|
|
17500
17500
|
};
|
|
17501
17501
|
}
|
|
17502
17502
|
// src/shared/opencode-version.ts
|
|
@@ -62294,11 +62294,11 @@ function getPluginsBaseDir() {
|
|
|
62294
62294
|
}
|
|
62295
62295
|
return join18(homedir6(), ".claude", "plugins");
|
|
62296
62296
|
}
|
|
62297
|
-
function getInstalledPluginsPath() {
|
|
62298
|
-
return join18(getPluginsBaseDir(), "installed_plugins.json");
|
|
62297
|
+
function getInstalledPluginsPath(pluginsBaseDir) {
|
|
62298
|
+
return join18(pluginsBaseDir ?? getPluginsBaseDir(), "installed_plugins.json");
|
|
62299
62299
|
}
|
|
62300
|
-
function loadInstalledPlugins() {
|
|
62301
|
-
const dbPath = getInstalledPluginsPath();
|
|
62300
|
+
function loadInstalledPlugins(pluginsBaseDir) {
|
|
62301
|
+
const dbPath = getInstalledPluginsPath(pluginsBaseDir);
|
|
62302
62302
|
if (!existsSync14(dbPath)) {
|
|
62303
62303
|
return null;
|
|
62304
62304
|
}
|
|
@@ -62402,7 +62402,8 @@ function extractPluginEntries(db) {
|
|
|
62402
62402
|
return Object.entries(db.plugins).map(([key, installations]) => [key, installations[0]]);
|
|
62403
62403
|
}
|
|
62404
62404
|
function discoverInstalledPlugins(options) {
|
|
62405
|
-
const
|
|
62405
|
+
const pluginsBaseDir = options?.pluginsHomeOverride ?? getPluginsBaseDir();
|
|
62406
|
+
const db = loadInstalledPlugins(pluginsBaseDir);
|
|
62406
62407
|
const settings = loadClaudeSettings();
|
|
62407
62408
|
const plugins = [];
|
|
62408
62409
|
const errors = [];
|
|
@@ -62411,6 +62412,7 @@ function discoverInstalledPlugins(options) {
|
|
|
62411
62412
|
}
|
|
62412
62413
|
const settingsEnabledPlugins = settings?.enabledPlugins;
|
|
62413
62414
|
const overrideEnabledPlugins = options?.enabledPluginsOverride;
|
|
62415
|
+
const pluginManifestLoader = options?.loadPluginManifestOverride ?? loadPluginManifest;
|
|
62414
62416
|
for (const [pluginKey, installation] of extractPluginEntries(db)) {
|
|
62415
62417
|
if (!installation)
|
|
62416
62418
|
continue;
|
|
@@ -62427,7 +62429,7 @@ function discoverInstalledPlugins(options) {
|
|
|
62427
62429
|
});
|
|
62428
62430
|
continue;
|
|
62429
62431
|
}
|
|
62430
|
-
const manifest =
|
|
62432
|
+
const manifest = pluginManifestLoader(installPath);
|
|
62431
62433
|
const pluginName = manifest?.name || derivePluginNameFromKey(pluginKey);
|
|
62432
62434
|
const loadedPlugin = {
|
|
62433
62435
|
name: pluginName,
|
|
@@ -62928,11 +62930,21 @@ function loadPluginHooksConfigs(plugins) {
|
|
|
62928
62930
|
}
|
|
62929
62931
|
|
|
62930
62932
|
// src/features/claude-code-plugin-loader/loader.ts
|
|
62933
|
+
var cachedPluginComponentsByKey = new Map;
|
|
62934
|
+
function clonePluginComponentsResult(result) {
|
|
62935
|
+
return structuredClone(result);
|
|
62936
|
+
}
|
|
62931
62937
|
function isClaudeCodePluginsDisabled() {
|
|
62932
62938
|
const disableFlag = process.env.OPENCODE_DISABLE_CLAUDE_CODE;
|
|
62933
62939
|
const disablePluginsFlag = process.env.OPENCODE_DISABLE_CLAUDE_CODE_PLUGINS;
|
|
62934
62940
|
return disableFlag === "true" || disableFlag === "1" || disablePluginsFlag === "true" || disablePluginsFlag === "1";
|
|
62935
62941
|
}
|
|
62942
|
+
function getPluginComponentsCacheKey(options) {
|
|
62943
|
+
const overrideEntries = Object.entries(options?.enabledPluginsOverride ?? {}).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey));
|
|
62944
|
+
return JSON.stringify({
|
|
62945
|
+
enabledPluginsOverride: overrideEntries
|
|
62946
|
+
});
|
|
62947
|
+
}
|
|
62936
62948
|
async function loadAllPluginComponents(options) {
|
|
62937
62949
|
if (isClaudeCodePluginsDisabled()) {
|
|
62938
62950
|
log("Claude Code plugin loading disabled via OPENCODE_DISABLE_CLAUDE_CODE env var");
|
|
@@ -62946,6 +62958,11 @@ async function loadAllPluginComponents(options) {
|
|
|
62946
62958
|
errors: []
|
|
62947
62959
|
};
|
|
62948
62960
|
}
|
|
62961
|
+
const cacheKey = getPluginComponentsCacheKey(options);
|
|
62962
|
+
const cachedPluginComponents = cachedPluginComponentsByKey.get(cacheKey);
|
|
62963
|
+
if (cachedPluginComponents) {
|
|
62964
|
+
return clonePluginComponentsResult(cachedPluginComponents);
|
|
62965
|
+
}
|
|
62949
62966
|
const { plugins, errors } = discoverInstalledPlugins(options);
|
|
62950
62967
|
const [commands, skills, agents, mcpServers, hooksConfigs] = await Promise.all([
|
|
62951
62968
|
Promise.resolve(loadPluginCommands(plugins)),
|
|
@@ -62955,7 +62972,7 @@ async function loadAllPluginComponents(options) {
|
|
|
62955
62972
|
Promise.resolve(loadPluginHooksConfigs(plugins))
|
|
62956
62973
|
]);
|
|
62957
62974
|
log(`Loaded ${plugins.length} plugins with ${Object.keys(commands).length} commands, ${Object.keys(skills).length} skills, ${Object.keys(agents).length} agents, ${Object.keys(mcpServers).length} MCP servers`);
|
|
62958
|
-
|
|
62975
|
+
const result = {
|
|
62959
62976
|
commands,
|
|
62960
62977
|
skills,
|
|
62961
62978
|
agents,
|
|
@@ -62964,6 +62981,8 @@ async function loadAllPluginComponents(options) {
|
|
|
62964
62981
|
plugins,
|
|
62965
62982
|
errors
|
|
62966
62983
|
};
|
|
62984
|
+
cachedPluginComponentsByKey.set(cacheKey, clonePluginComponentsResult(result));
|
|
62985
|
+
return clonePluginComponentsResult(result);
|
|
62967
62986
|
}
|
|
62968
62987
|
// src/shared/plugin-command-discovery.ts
|
|
62969
62988
|
function discoverPluginCommandDefinitions(options) {
|
|
@@ -82203,6 +82222,7 @@ var RETRYABLE_MESSAGE_PATTERNS = [
|
|
|
82203
82222
|
"over limit",
|
|
82204
82223
|
"overloaded",
|
|
82205
82224
|
"bad gateway",
|
|
82225
|
+
"bad request",
|
|
82206
82226
|
"unknown provider",
|
|
82207
82227
|
"provider not found",
|
|
82208
82228
|
"model_not_supported",
|
|
@@ -82529,13 +82549,15 @@ init_logger();
|
|
|
82529
82549
|
import { existsSync as existsSync39 } from "fs";
|
|
82530
82550
|
import { join as join42 } from "path";
|
|
82531
82551
|
var CONFIG_CACHE_TTL_MS2 = 30000;
|
|
82532
|
-
var USER_CONFIG_PATH = join42(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
|
|
82533
82552
|
var configCache2 = new Map;
|
|
82553
|
+
function getUserConfigPath() {
|
|
82554
|
+
return join42(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json");
|
|
82555
|
+
}
|
|
82534
82556
|
function getProjectConfigPath() {
|
|
82535
82557
|
return join42(process.cwd(), ".opencode", "opencode-cc-plugin.json");
|
|
82536
82558
|
}
|
|
82537
82559
|
function getCacheKey2() {
|
|
82538
|
-
return process.cwd()
|
|
82560
|
+
return `${process.cwd()}::${getUserConfigPath()}`;
|
|
82539
82561
|
}
|
|
82540
82562
|
function getCachedConfig2(cacheKey) {
|
|
82541
82563
|
const cachedEntry = configCache2.get(cacheKey);
|
|
@@ -82582,7 +82604,7 @@ async function loadPluginExtendedConfig() {
|
|
|
82582
82604
|
if (cachedConfig) {
|
|
82583
82605
|
return cachedConfig;
|
|
82584
82606
|
}
|
|
82585
|
-
const userConfig = await loadConfigFromPath(
|
|
82607
|
+
const userConfig = await loadConfigFromPath(getUserConfigPath());
|
|
82586
82608
|
const projectConfig = await loadConfigFromPath(getProjectConfigPath());
|
|
82587
82609
|
const merged = {
|
|
82588
82610
|
disabledHooks: mergeDisabledHooks(userConfig?.disabledHooks, projectConfig?.disabledHooks)
|
|
@@ -84427,26 +84449,33 @@ function getWindowsAppdataDir2() {
|
|
|
84427
84449
|
return null;
|
|
84428
84450
|
return process.env.APPDATA ?? path5.join(os4.homedir(), "AppData", "Roaming");
|
|
84429
84451
|
}
|
|
84430
|
-
|
|
84431
|
-
|
|
84432
|
-
|
|
84452
|
+
function getUserConfigDir() {
|
|
84453
|
+
return getOpenCodeConfigDir({ binary: "opencode" });
|
|
84454
|
+
}
|
|
84455
|
+
function getUserOpencodeConfig() {
|
|
84456
|
+
return path5.join(getUserConfigDir(), "opencode.json");
|
|
84457
|
+
}
|
|
84458
|
+
function getUserOpencodeConfigJsonc() {
|
|
84459
|
+
return path5.join(getUserConfigDir(), "opencode.jsonc");
|
|
84460
|
+
}
|
|
84433
84461
|
var INSTALLED_PACKAGE_JSON = path5.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
|
|
84434
84462
|
|
|
84435
84463
|
// src/hooks/auto-update-checker/checker/config-paths.ts
|
|
84436
84464
|
import * as os5 from "os";
|
|
84437
84465
|
import * as path6 from "path";
|
|
84438
84466
|
function getConfigPaths2(directory) {
|
|
84467
|
+
const userConfigDir = getUserConfigDir();
|
|
84439
84468
|
const paths = [
|
|
84440
84469
|
path6.join(directory, ".opencode", "opencode.json"),
|
|
84441
84470
|
path6.join(directory, ".opencode", "opencode.jsonc"),
|
|
84442
|
-
|
|
84443
|
-
|
|
84471
|
+
getUserOpencodeConfig(),
|
|
84472
|
+
getUserOpencodeConfigJsonc()
|
|
84444
84473
|
];
|
|
84445
84474
|
if (process.platform === "win32") {
|
|
84446
84475
|
const crossPlatformDir = path6.join(os5.homedir(), ".config");
|
|
84447
84476
|
const appdataDir = getWindowsAppdataDir2();
|
|
84448
84477
|
if (appdataDir) {
|
|
84449
|
-
const alternateDir =
|
|
84478
|
+
const alternateDir = userConfigDir === crossPlatformDir ? appdataDir : crossPlatformDir;
|
|
84450
84479
|
const alternateConfig = path6.join(alternateDir, "opencode", "opencode.json");
|
|
84451
84480
|
const alternateConfigJsonc = path6.join(alternateDir, "opencode", "opencode.jsonc");
|
|
84452
84481
|
if (!paths.includes(alternateConfig)) {
|
|
@@ -84937,8 +84966,9 @@ function removeFromBunLock(packageName) {
|
|
|
84937
84966
|
}
|
|
84938
84967
|
function invalidatePackage(packageName = PACKAGE_NAME) {
|
|
84939
84968
|
try {
|
|
84969
|
+
const userConfigDir = getUserConfigDir();
|
|
84940
84970
|
const pkgDirs = [
|
|
84941
|
-
path10.join(
|
|
84971
|
+
path10.join(userConfigDir, "node_modules", packageName),
|
|
84942
84972
|
path10.join(CACHE_DIR, "node_modules", packageName)
|
|
84943
84973
|
];
|
|
84944
84974
|
let packageRemoved = false;
|
|
@@ -98309,7 +98339,7 @@ function mergeConfigs(base, override) {
|
|
|
98309
98339
|
function loadPluginConfig(directory, ctx) {
|
|
98310
98340
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
98311
98341
|
const userDetected = detectPluginConfigFile(configDir);
|
|
98312
|
-
let userConfigPath = userDetected.format !== "none" ? userDetected.path : path11.join(configDir,
|
|
98342
|
+
let userConfigPath = userDetected.format !== "none" ? userDetected.path : path11.join(configDir, `${CONFIG_BASENAME}.json`);
|
|
98313
98343
|
if (userDetected.legacyPath) {
|
|
98314
98344
|
log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
|
|
98315
98345
|
canonicalPath: userDetected.path,
|
|
@@ -98317,12 +98347,15 @@ function loadPluginConfig(directory, ctx) {
|
|
|
98317
98347
|
});
|
|
98318
98348
|
}
|
|
98319
98349
|
if (userDetected.format !== "none" && path11.basename(userDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
|
|
98320
|
-
migrateLegacyConfigFile(userDetected.path);
|
|
98321
|
-
|
|
98350
|
+
const migrated = migrateLegacyConfigFile(userDetected.path);
|
|
98351
|
+
const canonicalPath = path11.join(path11.dirname(userDetected.path), `${CONFIG_BASENAME}${path11.extname(userDetected.path)}`);
|
|
98352
|
+
if (migrated || fs18.existsSync(canonicalPath)) {
|
|
98353
|
+
userConfigPath = canonicalPath;
|
|
98354
|
+
}
|
|
98322
98355
|
}
|
|
98323
98356
|
const projectBasePath = path11.join(directory, ".opencode");
|
|
98324
98357
|
const projectDetected = detectPluginConfigFile(projectBasePath);
|
|
98325
|
-
let projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path11.join(projectBasePath,
|
|
98358
|
+
let projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : path11.join(projectBasePath, `${CONFIG_BASENAME}.json`);
|
|
98326
98359
|
if (projectDetected.legacyPath) {
|
|
98327
98360
|
log("Canonical plugin config detected alongside legacy config. Remove the legacy file to avoid confusion.", {
|
|
98328
98361
|
canonicalPath: projectDetected.path,
|
|
@@ -98330,8 +98363,11 @@ function loadPluginConfig(directory, ctx) {
|
|
|
98330
98363
|
});
|
|
98331
98364
|
}
|
|
98332
98365
|
if (projectDetected.format !== "none" && path11.basename(projectDetected.path).startsWith(LEGACY_CONFIG_BASENAME)) {
|
|
98333
|
-
migrateLegacyConfigFile(projectDetected.path);
|
|
98334
|
-
|
|
98366
|
+
const projectMigrated = migrateLegacyConfigFile(projectDetected.path);
|
|
98367
|
+
const canonicalProjectPath = path11.join(path11.dirname(projectDetected.path), `${CONFIG_BASENAME}${path11.extname(projectDetected.path)}`);
|
|
98368
|
+
if (projectMigrated || fs18.existsSync(canonicalProjectPath)) {
|
|
98369
|
+
projectConfigPath = canonicalProjectPath;
|
|
98370
|
+
}
|
|
98335
98371
|
}
|
|
98336
98372
|
const userConfig = loadConfigFromPath2(userConfigPath, ctx);
|
|
98337
98373
|
let config2 = userConfig ?? OhMyOpenCodeConfigSchema.parse({});
|
|
@@ -117509,7 +117545,48 @@ async function readSessionTodos(sessionID) {
|
|
|
117509
117545
|
}
|
|
117510
117546
|
return getFileSessionTodos(sessionID);
|
|
117511
117547
|
}
|
|
117548
|
+
async function readSessionTranscript(sessionID) {
|
|
117549
|
+
return getFileSessionTranscript(sessionID);
|
|
117550
|
+
}
|
|
117512
117551
|
async function getSessionInfo(sessionID) {
|
|
117552
|
+
if (isSqliteBackend() && sdkClient) {
|
|
117553
|
+
try {
|
|
117554
|
+
const sdkMessages = await getSdkSessionMessages(sdkClient, sessionID);
|
|
117555
|
+
if (sdkMessages.length > 0) {
|
|
117556
|
+
const agentsUsed = new Set;
|
|
117557
|
+
let firstMessage;
|
|
117558
|
+
let lastMessage;
|
|
117559
|
+
for (const msg of sdkMessages) {
|
|
117560
|
+
if (msg.agent)
|
|
117561
|
+
agentsUsed.add(msg.agent);
|
|
117562
|
+
if (msg.time?.created) {
|
|
117563
|
+
const date9 = new Date(msg.time.created);
|
|
117564
|
+
if (!firstMessage || date9 < firstMessage)
|
|
117565
|
+
firstMessage = date9;
|
|
117566
|
+
if (!lastMessage || date9 > lastMessage)
|
|
117567
|
+
lastMessage = date9;
|
|
117568
|
+
}
|
|
117569
|
+
}
|
|
117570
|
+
const todos = await readSessionTodos(sessionID);
|
|
117571
|
+
const transcriptEntries = await readSessionTranscript(sessionID);
|
|
117572
|
+
return {
|
|
117573
|
+
id: sessionID,
|
|
117574
|
+
message_count: sdkMessages.length,
|
|
117575
|
+
first_message: firstMessage,
|
|
117576
|
+
last_message: lastMessage,
|
|
117577
|
+
agents_used: Array.from(agentsUsed),
|
|
117578
|
+
has_todos: todos.length > 0,
|
|
117579
|
+
has_transcript: transcriptEntries > 0,
|
|
117580
|
+
todos,
|
|
117581
|
+
transcript_entries: transcriptEntries
|
|
117582
|
+
};
|
|
117583
|
+
}
|
|
117584
|
+
} catch (error92) {
|
|
117585
|
+
if (!shouldFallbackFromSdkError(error92))
|
|
117586
|
+
throw error92;
|
|
117587
|
+
log("[session-manager] falling back to file session info after SDK unavailable error", { error: String(error92), sessionID });
|
|
117588
|
+
}
|
|
117589
|
+
}
|
|
117513
117590
|
return getFileSessionInfo(sessionID);
|
|
117514
117591
|
}
|
|
117515
117592
|
|
|
@@ -124046,6 +124123,9 @@ var builtinTools = {
|
|
|
124046
124123
|
function isTmuxIntegrationEnabled(pluginConfig) {
|
|
124047
124124
|
return pluginConfig.tmux?.enabled ?? false;
|
|
124048
124125
|
}
|
|
124126
|
+
function isInteractiveBashEnabled(which = Bun.which) {
|
|
124127
|
+
return which("tmux") !== null;
|
|
124128
|
+
}
|
|
124049
124129
|
function createRuntimeTmuxConfig(pluginConfig) {
|
|
124050
124130
|
return TmuxConfigSchema.parse(pluginConfig.tmux ?? {});
|
|
124051
124131
|
}
|
|
@@ -124594,6 +124674,40 @@ function createHooks(args) {
|
|
|
124594
124674
|
}
|
|
124595
124675
|
};
|
|
124596
124676
|
}
|
|
124677
|
+
// src/features/background-agent/constants.ts
|
|
124678
|
+
var TASK_TTL_MS = 30 * 60 * 1000;
|
|
124679
|
+
var TERMINAL_TASK_TTL_MS = 30 * 60 * 1000;
|
|
124680
|
+
var MIN_STABILITY_TIME_MS2 = 10 * 1000;
|
|
124681
|
+
var DEFAULT_STALE_TIMEOUT_MS = 2700000;
|
|
124682
|
+
var DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 3600000;
|
|
124683
|
+
var DEFAULT_MAX_TOOL_CALLS = 4000;
|
|
124684
|
+
var DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD = 20;
|
|
124685
|
+
var DEFAULT_CIRCUIT_BREAKER_ENABLED = true;
|
|
124686
|
+
var MIN_RUNTIME_BEFORE_STALE_MS = 30000;
|
|
124687
|
+
var DEFAULT_SESSION_GONE_TIMEOUT_MS = 60000;
|
|
124688
|
+
var MIN_IDLE_TIME_MS = 5000;
|
|
124689
|
+
var POLLING_INTERVAL_MS = 3000;
|
|
124690
|
+
var TASK_CLEANUP_DELAY_MS = 10 * 60 * 1000;
|
|
124691
|
+
|
|
124692
|
+
// src/features/background-agent/spawner.ts
|
|
124693
|
+
var FALLBACK_AGENT = "general";
|
|
124694
|
+
function isAgentNotFoundError(error92) {
|
|
124695
|
+
const message = typeof error92 === "string" ? error92 : error92 instanceof Error ? error92.message : typeof error92 === "object" && error92 !== null && typeof error92.message === "string" ? error92.message : String(error92);
|
|
124696
|
+
return message.includes("Agent not found") || message.includes("agent.name");
|
|
124697
|
+
}
|
|
124698
|
+
function buildFallbackBody(originalBody, fallbackAgent) {
|
|
124699
|
+
return {
|
|
124700
|
+
...originalBody,
|
|
124701
|
+
agent: fallbackAgent,
|
|
124702
|
+
tools: {
|
|
124703
|
+
task: false,
|
|
124704
|
+
call_omo_agent: true,
|
|
124705
|
+
question: false,
|
|
124706
|
+
...getAgentToolRestrictions(fallbackAgent)
|
|
124707
|
+
}
|
|
124708
|
+
};
|
|
124709
|
+
}
|
|
124710
|
+
|
|
124597
124711
|
// src/features/background-agent/task-history.ts
|
|
124598
124712
|
var MAX_ENTRIES_PER_PARENT = 100;
|
|
124599
124713
|
|
|
@@ -124751,21 +124865,6 @@ class ConcurrencyManager {
|
|
|
124751
124865
|
}
|
|
124752
124866
|
}
|
|
124753
124867
|
|
|
124754
|
-
// src/features/background-agent/constants.ts
|
|
124755
|
-
var TASK_TTL_MS = 30 * 60 * 1000;
|
|
124756
|
-
var TERMINAL_TASK_TTL_MS = 30 * 60 * 1000;
|
|
124757
|
-
var MIN_STABILITY_TIME_MS2 = 10 * 1000;
|
|
124758
|
-
var DEFAULT_STALE_TIMEOUT_MS = 2700000;
|
|
124759
|
-
var DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 3600000;
|
|
124760
|
-
var DEFAULT_MAX_TOOL_CALLS = 4000;
|
|
124761
|
-
var DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD = 20;
|
|
124762
|
-
var DEFAULT_CIRCUIT_BREAKER_ENABLED = true;
|
|
124763
|
-
var MIN_RUNTIME_BEFORE_STALE_MS = 30000;
|
|
124764
|
-
var DEFAULT_SESSION_GONE_TIMEOUT_MS = 60000;
|
|
124765
|
-
var MIN_IDLE_TIME_MS = 5000;
|
|
124766
|
-
var POLLING_INTERVAL_MS = 3000;
|
|
124767
|
-
var TASK_CLEANUP_DELAY_MS = 10 * 60 * 1000;
|
|
124768
|
-
|
|
124769
124868
|
// src/features/background-agent/duration-formatter.ts
|
|
124770
124869
|
function formatDuration3(start, end) {
|
|
124771
124870
|
const duration5 = (end ?? new Date).getTime() - start.getTime();
|
|
@@ -125957,32 +126056,52 @@ class BackgroundManager {
|
|
|
125957
126056
|
if (input.model) {
|
|
125958
126057
|
applySessionPromptParams(sessionID, input.model);
|
|
125959
126058
|
}
|
|
126059
|
+
const promptBody = {
|
|
126060
|
+
agent: input.agent,
|
|
126061
|
+
...launchModel ? { model: launchModel } : {},
|
|
126062
|
+
...launchVariant ? { variant: launchVariant } : {},
|
|
126063
|
+
system: input.skillContent,
|
|
126064
|
+
tools: (() => {
|
|
126065
|
+
const tools = {
|
|
126066
|
+
task: false,
|
|
126067
|
+
call_omo_agent: true,
|
|
126068
|
+
question: false,
|
|
126069
|
+
...getAgentToolRestrictions(input.agent)
|
|
126070
|
+
};
|
|
126071
|
+
setSessionTools(sessionID, tools);
|
|
126072
|
+
return tools;
|
|
126073
|
+
})(),
|
|
126074
|
+
parts: [createInternalAgentTextPart(input.prompt)]
|
|
126075
|
+
};
|
|
125960
126076
|
promptWithModelSuggestionRetry(this.client, {
|
|
125961
126077
|
path: { id: sessionID },
|
|
125962
|
-
body:
|
|
125963
|
-
agent: input.agent,
|
|
125964
|
-
...launchModel ? { model: launchModel } : {},
|
|
125965
|
-
...launchVariant ? { variant: launchVariant } : {},
|
|
125966
|
-
system: input.skillContent,
|
|
125967
|
-
tools: (() => {
|
|
125968
|
-
const tools = {
|
|
125969
|
-
task: false,
|
|
125970
|
-
call_omo_agent: true,
|
|
125971
|
-
question: false,
|
|
125972
|
-
...getAgentToolRestrictions(input.agent)
|
|
125973
|
-
};
|
|
125974
|
-
setSessionTools(sessionID, tools);
|
|
125975
|
-
return tools;
|
|
125976
|
-
})(),
|
|
125977
|
-
parts: [createInternalAgentTextPart(input.prompt)]
|
|
125978
|
-
}
|
|
126078
|
+
body: promptBody
|
|
125979
126079
|
}).catch(async (error92) => {
|
|
126080
|
+
if (isAgentNotFoundError(error92) && input.agent !== FALLBACK_AGENT) {
|
|
126081
|
+
log("[background-agent] Agent not found, retrying with fallback agent", {
|
|
126082
|
+
original: input.agent,
|
|
126083
|
+
fallback: FALLBACK_AGENT,
|
|
126084
|
+
taskId: task.id
|
|
126085
|
+
});
|
|
126086
|
+
try {
|
|
126087
|
+
const fallbackBody = buildFallbackBody(promptBody, FALLBACK_AGENT);
|
|
126088
|
+
setSessionTools(sessionID, fallbackBody.tools);
|
|
126089
|
+
await promptWithModelSuggestionRetry(this.client, {
|
|
126090
|
+
path: { id: sessionID },
|
|
126091
|
+
body: fallbackBody
|
|
126092
|
+
});
|
|
126093
|
+
task.agent = FALLBACK_AGENT;
|
|
126094
|
+
return;
|
|
126095
|
+
} catch (retryError) {
|
|
126096
|
+
log("[background-agent] Fallback agent also failed:", retryError);
|
|
126097
|
+
}
|
|
126098
|
+
}
|
|
125980
126099
|
log("[background-agent] promptAsync error:", error92);
|
|
125981
126100
|
const existingTask = this.findBySession(sessionID);
|
|
125982
126101
|
if (existingTask) {
|
|
125983
126102
|
existingTask.status = "interrupt";
|
|
125984
126103
|
const errorMessage = error92 instanceof Error ? error92.message : String(error92);
|
|
125985
|
-
if (errorMessage.includes("agent.name") || errorMessage.includes("undefined")) {
|
|
126104
|
+
if (errorMessage.includes("agent.name") || errorMessage.includes("undefined") || isAgentNotFoundError(error92)) {
|
|
125986
126105
|
existingTask.error = `Agent "${input.agent}" not found. Make sure the agent is registered in your opencode.json or provided by a plugin.`;
|
|
125987
126106
|
} else {
|
|
125988
126107
|
existingTask.error = errorMessage;
|
|
@@ -126493,6 +126612,13 @@ class BackgroundManager {
|
|
|
126493
126612
|
}
|
|
126494
126613
|
async handleSessionErrorEvent(args) {
|
|
126495
126614
|
const { task, errorInfo, errorMessage, errorName } = args;
|
|
126615
|
+
if (isAgentNotFoundError({ message: errorInfo.message })) {
|
|
126616
|
+
log("[background-agent] Skipping session.error fallback for agent-not-found (handled by prompt catch)", {
|
|
126617
|
+
taskId: task.id,
|
|
126618
|
+
errorMessage: errorInfo.message?.slice(0, 100)
|
|
126619
|
+
});
|
|
126620
|
+
return;
|
|
126621
|
+
}
|
|
126496
126622
|
if (await this.tryFallbackRetry(task, errorInfo, "session.error")) {
|
|
126497
126623
|
return;
|
|
126498
126624
|
}
|
|
@@ -138815,43 +138941,39 @@ function buildTodoDisciplineSection3(useTaskSystem) {
|
|
|
138815
138941
|
if (useTaskSystem) {
|
|
138816
138942
|
return `## Task Discipline (NON-NEGOTIABLE)
|
|
138817
138943
|
|
|
138818
|
-
Track ALL multi-step work with tasks. This is your execution backbone
|
|
138944
|
+
**Track ALL multi-step work with tasks. This is your execution backbone.**
|
|
138819
138945
|
|
|
138820
138946
|
### When to Create Tasks (MANDATORY)
|
|
138821
138947
|
|
|
138822
|
-
- 2+ step task - \`task_create\` FIRST, atomic breakdown
|
|
138823
|
-
- Uncertain scope - \`task_create\` to clarify thinking
|
|
138824
|
-
- Complex single task -
|
|
138948
|
+
- **2+ step task** - \`task_create\` FIRST, atomic breakdown
|
|
138949
|
+
- **Uncertain scope** - \`task_create\` to clarify thinking
|
|
138950
|
+
- **Complex single task** - Break down into trackable steps
|
|
138825
138951
|
|
|
138826
138952
|
### Workflow (STRICT)
|
|
138827
138953
|
|
|
138828
|
-
1. On task start
|
|
138829
|
-
2. Before each step
|
|
138830
|
-
3. After each step
|
|
138831
|
-
4. Scope changes
|
|
138832
|
-
|
|
138833
|
-
Tasks prevent drift, enable recovery if interrupted, and make each commitment explicit. Skipping tasks on multi-step work, batch-completing, or proceeding without \`in_progress\` are blocking violations.
|
|
138954
|
+
1. **On task start**: \`task_create\` with atomic steps-no announcements, just create
|
|
138955
|
+
2. **Before each step**: \`task_update(status="in_progress")\` (ONE at a time)
|
|
138956
|
+
3. **After each step**: \`task_update(status="completed")\` IMMEDIATELY (NEVER batch)
|
|
138957
|
+
4. **Scope changes**: Update tasks BEFORE proceeding
|
|
138834
138958
|
|
|
138835
138959
|
**NO TASKS ON MULTI-STEP WORK = INCOMPLETE WORK.**`;
|
|
138836
138960
|
}
|
|
138837
138961
|
return `## Todo Discipline (NON-NEGOTIABLE)
|
|
138838
138962
|
|
|
138839
|
-
Track ALL multi-step work with todos. This is your execution backbone
|
|
138963
|
+
**Track ALL multi-step work with todos. This is your execution backbone.**
|
|
138840
138964
|
|
|
138841
138965
|
### When to Create Todos (MANDATORY)
|
|
138842
138966
|
|
|
138843
|
-
- 2+ step task - \`todowrite\` FIRST, atomic breakdown
|
|
138844
|
-
- Uncertain scope - \`todowrite\` to clarify thinking
|
|
138845
|
-
- Complex single task -
|
|
138967
|
+
- **2+ step task** - \`todowrite\` FIRST, atomic breakdown
|
|
138968
|
+
- **Uncertain scope** - \`todowrite\` to clarify thinking
|
|
138969
|
+
- **Complex single task** - Break down into trackable steps
|
|
138846
138970
|
|
|
138847
138971
|
### Workflow (STRICT)
|
|
138848
138972
|
|
|
138849
|
-
1. On task start
|
|
138850
|
-
2. Before each step
|
|
138851
|
-
3. After each step
|
|
138852
|
-
4. Scope changes
|
|
138853
|
-
|
|
138854
|
-
Todos prevent drift, enable recovery if interrupted, and make each commitment explicit. Skipping todos on multi-step work, batch-completing, or proceeding without \`in_progress\` are blocking violations.
|
|
138973
|
+
1. **On task start**: \`todowrite\` with atomic steps-no announcements, just create
|
|
138974
|
+
2. **Before each step**: Mark \`in_progress\` (ONE at a time)
|
|
138975
|
+
3. **After each step**: Mark \`completed\` IMMEDIATELY (NEVER batch)
|
|
138976
|
+
4. **Scope changes**: Update todos BEFORE proceeding
|
|
138855
138977
|
|
|
138856
138978
|
**NO TODOS ON MULTI-STEP WORK = INCOMPLETE WORK.**`;
|
|
138857
138979
|
}
|
|
@@ -138865,313 +138987,243 @@ function buildHephaestusPrompt3(availableAgents = [], availableTools = [], avail
|
|
|
138865
138987
|
const oracleSection = buildOracleSection(availableAgents);
|
|
138866
138988
|
const hardBlocks = buildHardBlocksSection();
|
|
138867
138989
|
const antiPatterns = buildAntiPatternsSection();
|
|
138990
|
+
const antiDuplication = buildAntiDuplicationSection();
|
|
138868
138991
|
const todoDiscipline = buildTodoDisciplineSection3(useTaskSystem);
|
|
138869
|
-
|
|
138870
|
-
|
|
138871
|
-
## Identity
|
|
138872
|
-
|
|
138873
|
-
You build context by examining the codebase first without making assumptions. You think through the nuances of the code you encounter. You do not stop early. You complete.
|
|
138874
|
-
|
|
138875
|
-
Persist until the task is fully handled end-to-end within the current turn. Persevere even when tool calls fail. Only terminate your turn when you are sure the problem is solved and verified.
|
|
138876
|
-
|
|
138877
|
-
When blocked: try a different approach \u2192 decompose the problem \u2192 challenge assumptions \u2192 explore how others solved it. Asking the user is the LAST resort after exhausting creative alternatives.
|
|
138878
|
-
|
|
138879
|
-
### Do NOT Ask - Just Do
|
|
138880
|
-
|
|
138881
|
-
**FORBIDDEN:**
|
|
138882
|
-
- Asking permission in any form ("Should I proceed?", "Would you like me to...?", "I can do X if you want") \u2192 JUST DO IT.
|
|
138883
|
-
- "Do you want me to run tests?" \u2192 RUN THEM.
|
|
138884
|
-
- "I noticed Y, should I fix it?" \u2192 FIX IT OR NOTE IN FINAL MESSAGE.
|
|
138885
|
-
- Stopping after partial implementation \u2192 100% OR NOTHING.
|
|
138886
|
-
- Answering a question then stopping \u2192 The question implies action. DO THE ACTION.
|
|
138887
|
-
- "I'll do X" / "I recommend X" then ending turn \u2192 You COMMITTED to X. DO X NOW before ending.
|
|
138888
|
-
- Explaining findings without acting on them \u2192 ACT on your findings immediately.
|
|
138889
|
-
|
|
138890
|
-
**CORRECT:**
|
|
138891
|
-
- Keep going until COMPLETELY done
|
|
138892
|
-
- Run verification (lint, tests, build) WITHOUT asking
|
|
138893
|
-
- Make decisions. Course-correct only on CONCRETE failure
|
|
138894
|
-
- Note assumptions in final message, not as questions mid-work
|
|
138895
|
-
- Need context? Fire explore/librarian in background IMMEDIATELY - continue only with non-overlapping work while they search
|
|
138896
|
-
- User asks "did you do X?" and you didn't \u2192 Acknowledge briefly, DO X immediately
|
|
138897
|
-
- User asks a question implying work \u2192 Answer briefly, DO the implied work in the same turn
|
|
138898
|
-
- You wrote a plan in your response \u2192 EXECUTE the plan before ending turn - plans are starting lines, not finish lines
|
|
138899
|
-
|
|
138900
|
-
### Task Scope Clarification
|
|
138992
|
+
const identityBlock = `<identity>
|
|
138993
|
+
You are Hephaestus, an autonomous deep worker for software engineering.
|
|
138901
138994
|
|
|
138902
|
-
You
|
|
138995
|
+
You communicate warmly and directly, like a senior colleague walking through a problem together. You explain the why behind decisions, not just the what. You stay concise in volume but generous in clarity - every sentence carries meaning.
|
|
138903
138996
|
|
|
138904
|
-
|
|
138997
|
+
You build context by examining the codebase first without assumptions. You think through the nuances of the code you encounter. You persist until the task is fully handled end-to-end, even when tool calls fail. You only end your turn when the problem is solved and verified.
|
|
138905
138998
|
|
|
138906
|
-
|
|
138999
|
+
You are autonomous. When you see work to do, do it - run tests, fix issues, make decisions. Course-correct only on concrete failure. State assumptions in your final message, not as questions along the way. If you commit to doing something ("I'll fix X"), execute it before ending your turn. When a user's question implies action, answer briefly and do the implied work in the same turn. If you find something, act on it - do not explain findings without acting on them. Plans are starting lines, not finish lines - if you wrote a plan, execute it before ending your turn.
|
|
138907
139000
|
|
|
138908
|
-
|
|
138909
|
-
|
|
138910
|
-
## Phase 0 - Intent Gate (EVERY task)
|
|
139001
|
+
When blocked: try a different approach, decompose the problem, challenge your assumptions, explore how others solved it. Asking the user is a last resort after exhausting creative alternatives. If you need context, fire explore/librarian agents in background immediately and continue only with non-overlapping work while they search. Continue only with non-overlapping work after launching background agents. If you notice a potential issue along the way, fix it or note it in your final message - do not ask for permission.
|
|
138911
139002
|
|
|
139003
|
+
You handle multi-step sub-tasks of a single goal. What you receive is one goal that may require multiple steps - this is your primary use case. Only flag when given genuinely independent goals in one request.
|
|
139004
|
+
</identity>`;
|
|
139005
|
+
const intentBlock = `<intent>
|
|
138912
139006
|
${keyTriggers}
|
|
138913
139007
|
|
|
138914
|
-
|
|
138915
|
-
### Step 0: Extract True Intent (BEFORE Classification)
|
|
138916
|
-
|
|
138917
|
-
You are an autonomous deep worker. Users chose you for ACTION, not analysis.
|
|
139008
|
+
You are an autonomous deep worker. Users chose you for ACTION, not analysis. Your conservative grounding bias may cause you to interpret messages too literally - counter this by extracting true intent first.
|
|
138918
139009
|
|
|
138919
|
-
Every
|
|
138920
|
-
|
|
138921
|
-
**Intent Mapping (act on TRUE intent, not surface form):**
|
|
139010
|
+
Every message has a surface form and a true intent. Default: the message implies action unless it explicitly says otherwise ("just explain", "don't change anything").
|
|
138922
139011
|
|
|
138923
|
-
|
|
139012
|
+
<intent_mapping>
|
|
139013
|
+
| Surface Form | True Intent | Your Move |
|
|
138924
139014
|
|---|---|---|
|
|
138925
|
-
| "Did you do X?" (and you didn't) |
|
|
138926
|
-
| "How does X work?" | Understand
|
|
138927
|
-
| "Can you look into Y?" | Investigate
|
|
138928
|
-
| "What's the best way to do Z?" |
|
|
138929
|
-
| "Why is A broken?" / "I'm seeing error B" | Fix A / Fix B | Diagnose
|
|
138930
|
-
| "What do you think about C?" | Evaluate
|
|
138931
|
-
|
|
138932
|
-
Pure question (NO action) ONLY when ALL of these are true: user explicitly says "just explain" / "don't change anything" / "I'm just curious", no actionable codebase context, and no problem or improvement is mentioned or implied.
|
|
138933
|
-
|
|
138934
|
-
DEFAULT: Message implies action unless explicitly stated otherwise.
|
|
138935
|
-
|
|
138936
|
-
Verbalize your classification before acting:
|
|
139015
|
+
| "Did you do X?" (and you didn't) | Do X now | Acknowledge briefly, do X |
|
|
139016
|
+
| "How does X work?" | Understand to fix/improve | Explore, then implement/fix |
|
|
139017
|
+
| "Can you look into Y?" | Investigate and resolve | Investigate, then resolve |
|
|
139018
|
+
| "What's the best way to do Z?" | Do Z the best way | Decide, then implement |
|
|
139019
|
+
| "Why is A broken?" / "I'm seeing error B" | Fix A / Fix B | Diagnose, then fix |
|
|
139020
|
+
| "What do you think about C?" | Evaluate and implement | Evaluate, then implement best option |
|
|
139021
|
+
</intent_mapping>
|
|
138937
139022
|
|
|
138938
|
-
|
|
138939
|
-
|
|
138940
|
-
This verbalization commits you to action. Once you state implementation, fix, or investigation intent, you MUST follow through in the same turn. Only "pure question" permits ending without action.
|
|
138941
|
-
</intent_extraction>
|
|
138942
|
-
|
|
138943
|
-
### Step 1: Classify Task Type
|
|
139023
|
+
Pure question (no action) only when ALL of these are true: user explicitly says "just explain" / "don't change anything", no actionable codebase context, and no problem or improvement is mentioned.
|
|
138944
139024
|
|
|
138945
|
-
|
|
138946
|
-
- **Explicit**: Specific file/line, clear command - Execute directly
|
|
138947
|
-
- **Exploratory**: "How does X work?", "Find Y" - Fire explore (1-3) + tools in parallel \u2192 then ACT on findings (see Step 0 true intent)
|
|
138948
|
-
- **Open-ended**: "Improve", "Refactor", "Add feature" - Full Execution Loop required
|
|
138949
|
-
- **Ambiguous**: Unclear scope, multiple interpretations - Ask ONE clarifying question
|
|
139025
|
+
State your read before acting: "I detect [intent type] - [reason]. [What I'm doing now]." This commits you to follow through in the same turn.
|
|
138950
139026
|
|
|
138951
|
-
|
|
138952
|
-
|
|
138953
|
-
-
|
|
138954
|
-
-
|
|
138955
|
-
-
|
|
138956
|
-
-
|
|
138957
|
-
|
|
138958
|
-
|
|
138959
|
-
|
|
139027
|
+
Complexity:
|
|
139028
|
+
- Trivial (single file, <10 lines) - direct tools, unless a key trigger fires
|
|
139029
|
+
- Explicit (specific file/line) - execute directly
|
|
139030
|
+
- Exploratory ("how does X work?") - fire explore agents + tools in parallel, then act on findings
|
|
139031
|
+
- Open-ended ("improve", "refactor") - full execution loop
|
|
139032
|
+
- Ambiguous - explore first, cover all likely intents comprehensively rather than asking
|
|
139033
|
+
- Uncertain scope - create todos to clarify thinking, then proceed
|
|
139034
|
+
|
|
139035
|
+
Before asking the user anything, exhaust this hierarchy:
|
|
139036
|
+
1. Direct tools: \`grep\`, \`rg\`, file reads, \`gh\`, \`git log\`
|
|
138960
139037
|
2. Explore agents: fire 2-3 parallel background searches
|
|
138961
139038
|
3. Librarian agents: check docs, GitHub, external sources
|
|
138962
139039
|
4. Context inference: educated guess from surrounding context
|
|
138963
|
-
5.
|
|
139040
|
+
5. Only when 1-4 all fail: ask one precise question
|
|
138964
139041
|
|
|
138965
|
-
|
|
139042
|
+
Before acting, check:
|
|
139043
|
+
- Do I have implicit assumptions? Is the search scope clear?
|
|
139044
|
+
- Is there a skill whose domain overlaps? Load it immediately.
|
|
139045
|
+
- Is there a specialized agent that matches this? What category + skills to equip?
|
|
139046
|
+
- Can I do it myself for the best result? Default to delegation for complex tasks.
|
|
138966
139047
|
|
|
138967
|
-
|
|
139048
|
+
If the user's approach seems problematic, explain your concern and the alternative, then proceed with the better approach. Flag major risks before implementing.
|
|
139049
|
+
</intent>`;
|
|
139050
|
+
const exploreBlock = `<explore>
|
|
139051
|
+
${toolSelection}
|
|
138968
139052
|
|
|
138969
|
-
|
|
139053
|
+
${exploreSection}
|
|
138970
139054
|
|
|
138971
|
-
|
|
138972
|
-
0. Find relevant skills to load - load them IMMEDIATELY.
|
|
138973
|
-
1. Is there a specialized agent that perfectly matches this request?
|
|
138974
|
-
2. If not, what \`task\` category + skills to equip? \u2192 \`task(load_skills=[{skill1}, ...])\`
|
|
138975
|
-
3. Can I do it myself for the best result, FOR SURE?
|
|
139055
|
+
${librarianSection}
|
|
138976
139056
|
|
|
138977
|
-
|
|
139057
|
+
<tool_usage_rules>
|
|
139058
|
+
- Parallelize independent tool calls: multiple file reads, grep searches, agent fires - all at once
|
|
139059
|
+
- Explore/Librarian = background grep. ALWAYS \`run_in_background=true\`, ALWAYS parallel
|
|
139060
|
+
- After any file edit: restate what changed, where, and what validation follows
|
|
139061
|
+
- Prefer tools over guessing whenever you need specific data (files, configs, patterns)
|
|
139062
|
+
</tool_usage_rules>
|
|
138978
139063
|
|
|
138979
|
-
|
|
139064
|
+
<tool_call_philosophy>
|
|
139065
|
+
More tool calls = more accuracy. Ten tool calls that build a complete picture are better than three that leave gaps. Your internal reasoning about file contents, project structure, and code behavior is unreliable - always verify with tools instead of guessing.
|
|
138980
139066
|
|
|
138981
|
-
|
|
139067
|
+
Treat every tool call as an investment in correctness, not a cost to minimize. When you are unsure whether to make a tool call, make it. When you think you have enough context, make one more call to verify. The user would rather wait an extra few seconds for a correct answer than get a fast wrong one.
|
|
139068
|
+
</tool_call_philosophy>
|
|
138982
139069
|
|
|
138983
|
-
|
|
139070
|
+
<tool_persistence>
|
|
139071
|
+
Do not stop calling tools just to save calls. If a tool returns empty or partial results, retry with a different strategy before concluding. Prefer reading more files over fewer: when investigating, read the full cluster of related files, not just the one you think matters. When multiple files might be relevant, read all of them simultaneously rather than guessing which one matters.
|
|
139072
|
+
</tool_persistence>
|
|
138984
139073
|
|
|
138985
|
-
|
|
139074
|
+
<dig_deeper>
|
|
139075
|
+
Do not stop at the first plausible answer. Look for second-order issues, edge cases, and missing constraints. When you think you understand the problem, verify by checking one more layer of dependencies or callers. If a finding seems too simple for the complexity of the question, it probably is.
|
|
139076
|
+
</dig_deeper>
|
|
138986
139077
|
|
|
138987
|
-
|
|
139078
|
+
<dependency_checks>
|
|
139079
|
+
Before taking an action, check whether prerequisite discovery or lookup is required. Do not skip prerequisite steps just because the intended final action seems obvious. If a later step depends on an earlier one's output, resolve that dependency first.
|
|
139080
|
+
</dependency_checks>
|
|
138988
139081
|
|
|
138989
|
-
|
|
139082
|
+
Prefer tools over guessing whenever you need specific data (files, configs, patterns). Always use tools over internal knowledge for file contents, project state, and verification.
|
|
138990
139083
|
|
|
138991
|
-
|
|
139084
|
+
<parallel_execution>
|
|
139085
|
+
Parallelize aggressively - this is where you gain the most speed and accuracy. Every independent operation should run simultaneously, not sequentially:
|
|
139086
|
+
- Multiple file reads: read 5 files at once, not one by one
|
|
139087
|
+
- Grep + file reads: search and read in the same turn
|
|
139088
|
+
- Multiple explore/librarian agents: fire 3-5 agents in parallel for different angles on the same question
|
|
139089
|
+
- Agent fires + direct tool calls: launch background agents AND do direct reads simultaneously
|
|
138992
139090
|
|
|
138993
|
-
|
|
138994
|
-
|
|
138995
|
-
Parallelize EVERYTHING. Independent reads, searches, and agents run SIMULTANEOUSLY.
|
|
138996
|
-
|
|
138997
|
-
<tool_usage_rules>
|
|
138998
|
-
- Parallelize independent tool calls: multiple file reads, grep searches, agent fires - all at once.
|
|
138999
|
-
- Explore/Librarian = background grep. ALWAYS \`run_in_background=true\`, ALWAYS parallel.
|
|
139000
|
-
- Never chain together bash commands with separators like \`&&\`, \`;\`, or \`|\` in a single call. Run each command as a separate tool invocation.
|
|
139001
|
-
- After any file edit: restate what changed, where, and what validation follows.
|
|
139002
|
-
- Prefer tools over guessing whenever you need specific data (files, configs, patterns).
|
|
139003
|
-
</tool_usage_rules>
|
|
139091
|
+
Fire 2-5 explore agents in parallel for any non-trivial codebase question. Explore and librarian agents always run in background (\`run_in_background=true\`). Never use \`run_in_background=false\` for explore/librarian. After launching, continue only with non-overlapping work. Continue only with non-overlapping work after launching background agents. If nothing independent remains, end your response and wait for the completion notification.
|
|
139092
|
+
</parallel_execution>
|
|
139004
139093
|
|
|
139005
|
-
|
|
139094
|
+
How to call explore/librarian:
|
|
139006
139095
|
\`\`\`
|
|
139007
|
-
// Codebase search
|
|
139096
|
+
// Codebase search
|
|
139008
139097
|
task(subagent_type="explore", run_in_background=true, load_skills=[], description="Find [what]", prompt="[CONTEXT]: ... [GOAL]: ... [REQUEST]: ...")
|
|
139009
139098
|
|
|
139010
|
-
// External docs/OSS search
|
|
139099
|
+
// External docs/OSS search
|
|
139011
139100
|
task(subagent_type="librarian", run_in_background=true, load_skills=[], description="Find [what]", prompt="[CONTEXT]: ... [GOAL]: ... [REQUEST]: ...")
|
|
139012
|
-
|
|
139013
139101
|
\`\`\`
|
|
139014
139102
|
|
|
139015
|
-
|
|
139016
|
-
- [CONTEXT]: Task, files/modules involved, approach
|
|
139017
|
-
- [GOAL]: Specific outcome needed - what decision this unblocks
|
|
139018
|
-
- [DOWNSTREAM]: How results will be used
|
|
139019
|
-
- [REQUEST]: What to find, format to return, what to SKIP
|
|
139103
|
+
Never chain together bash commands with separators like \`&&\`, \`;\`, or \`|\` in a single call. Run each command as a separate tool invocation.
|
|
139020
139104
|
|
|
139021
|
-
|
|
139022
|
-
- Fire 2-5 explore agents in parallel for any non-trivial codebase question
|
|
139023
|
-
- Parallelize independent file reads - don't read files one at a time
|
|
139024
|
-
- NEVER use \`run_in_background=false\` for explore/librarian
|
|
139025
|
-
- Continue only with non-overlapping work after launching background agents
|
|
139026
|
-
- Collect results with \`background_output(task_id="...")\` when needed
|
|
139027
|
-
- BEFORE final answer, cancel DISPOSABLE tasks individually: \`background_cancel(taskId="bg_explore_xxx")\`, \`background_cancel(taskId="bg_librarian_xxx")\`
|
|
139028
|
-
- **NEVER use \`background_cancel(all=true)\`** - it kills tasks whose results you haven't collected yet
|
|
139105
|
+
After any file edit, briefly restate what changed, where, and what validation follows.
|
|
139029
139106
|
|
|
139030
|
-
|
|
139107
|
+
Once you delegate exploration to background agents, do not repeat the same search yourself. Continue only with non-overlapping work only. Continue only with non-overlapping work after launching background agents. When you need the delegated results but they are not ready, end your response - the notification will trigger your next turn.
|
|
139031
139108
|
|
|
139032
|
-
|
|
139109
|
+
Agent prompt structure:
|
|
139110
|
+
- [CONTEXT]: Task, files/modules involved, approach
|
|
139111
|
+
- [GOAL]: Specific outcome needed - what decision this unblocks
|
|
139112
|
+
- [DOWNSTREAM]: How results will be used
|
|
139113
|
+
- [REQUEST]: What to find, format to return, what to skip
|
|
139033
139114
|
|
|
139034
|
-
|
|
139115
|
+
Background task management:
|
|
139116
|
+
- Collect results with \`background_output(task_id="...")\` when completed
|
|
139117
|
+
- Before final answer, cancel disposable tasks individually: \`background_cancel(taskId="...")\`
|
|
139118
|
+
- Never use \`background_cancel(all=true)\` - it kills tasks whose results you have not collected yet
|
|
139035
139119
|
|
|
139036
|
-
|
|
139120
|
+
${antiDuplication}
|
|
139037
139121
|
|
|
139038
|
-
|
|
139122
|
+
Stop searching when you have enough context, the same info repeats, or two iterations found nothing new.
|
|
139123
|
+
</explore>`;
|
|
139124
|
+
const constraintsBlock = `<constraints>
|
|
139125
|
+
${hardBlocks}
|
|
139039
139126
|
|
|
139040
|
-
|
|
139041
|
-
|
|
139042
|
-
|
|
139043
|
-
|
|
139044
|
-
|
|
139127
|
+
${antiPatterns}
|
|
139128
|
+
</constraints>`;
|
|
139129
|
+
const executionBlock = `<execution>
|
|
139130
|
+
1. **Explore**: Fire 2-5 explore/librarian agents in parallel + direct tool reads. Goal: complete understanding, not just enough context.
|
|
139131
|
+
2. **Plan**: List files to modify, specific changes, dependencies, complexity estimate.
|
|
139132
|
+
3. **Decide**: Trivial (<10 lines, single file) -> self. Complex (multi-file, >100 lines) -> delegate.
|
|
139133
|
+
4. **Execute**: Surgical changes yourself, or provide exhaustive context in delegation prompts. Match existing patterns. Minimal diff. Search the codebase for similar patterns before writing code. Default to ASCII. Add comments only for non-obvious blocks.
|
|
139134
|
+
5. **Verify**: \`lsp_diagnostics\` on all modified files (zero errors) -> run related tests (\`foo.ts\` -> \`foo.test.ts\`) -> typecheck -> build if applicable (exit 0). Fix only issues your changes caused.
|
|
139045
139135
|
|
|
139046
|
-
If verification fails
|
|
139136
|
+
If verification fails, return to step 1 with a materially different approach. After three attempts: stop, revert to last working state, document what you tried, consult Oracle. If Oracle cannot resolve, ask the user.
|
|
139047
139137
|
|
|
139048
|
-
|
|
139138
|
+
While working, you may notice unexpected changes you did not make - likely from the user or autogeneration. If they directly conflict with your task, ask. Otherwise, focus on your task.
|
|
139049
139139
|
|
|
139050
|
-
|
|
139140
|
+
<completion_check>
|
|
139141
|
+
When you think you are done: re-read the original request. Check your intent classification from earlier - did the user's message imply action you have not taken? Verify every item is fully implemented - not partially, not "extend later." Run verification once more. Then report what you did, what you verified, and the results.
|
|
139142
|
+
</completion_check>
|
|
139051
139143
|
|
|
139052
|
-
|
|
139144
|
+
<failure_recovery>
|
|
139145
|
+
Fix root causes, not symptoms. Re-verify after every attempt. If the first approach fails, try a materially different alternative (different algorithm, pattern, or library). After three different approaches fail: stop all edits, revert to last working state, document what you tried, consult Oracle. If Oracle cannot resolve, ask the user with a clear explanation.
|
|
139053
139146
|
|
|
139147
|
+
Never leave code broken, delete failing tests, or make random changes hoping something works.
|
|
139148
|
+
</failure_recovery>
|
|
139149
|
+
</execution>`;
|
|
139150
|
+
const trackingBlock = `<tracking>
|
|
139054
139151
|
${todoDiscipline}
|
|
139152
|
+
</tracking>`;
|
|
139153
|
+
const progressBlock = `<progress>
|
|
139154
|
+
Report progress at meaningful phase transitions. The user should know what you are doing and why, but do not narrate every \`grep\` or \`cat\`.
|
|
139055
139155
|
|
|
139056
|
-
|
|
139057
|
-
|
|
139058
|
-
## Progress Updates
|
|
139059
|
-
|
|
139060
|
-
Report progress proactively every ~30 seconds. The user should always know what you're doing and why.
|
|
139061
|
-
|
|
139062
|
-
When to update (MANDATORY):
|
|
139156
|
+
When to update:
|
|
139063
139157
|
- Before exploration: "Checking the repo structure for auth patterns..."
|
|
139064
139158
|
- After discovery: "Found the config in \`src/config/\`. The pattern uses factory functions."
|
|
139065
139159
|
- Before large edits: "About to refactor the handler - touching 3 files."
|
|
139066
139160
|
- On phase transitions: "Exploration done. Moving to implementation."
|
|
139067
139161
|
- On blockers: "Hit a snag with the types - trying generics instead."
|
|
139068
139162
|
|
|
139069
|
-
Style:
|
|
139070
|
-
|
|
139071
|
-
|
|
139072
|
-
|
|
139073
|
-
## Implementation
|
|
139074
|
-
|
|
139163
|
+
Style: one sentence, concrete, with at least one specific detail (file path, pattern found, decision made). Explain the why behind technical decisions. Keep updates varied in structure.
|
|
139164
|
+
</progress>`;
|
|
139165
|
+
const delegationBlock = `<delegation>
|
|
139075
139166
|
${categorySkillsGuide}
|
|
139076
139167
|
|
|
139077
|
-
|
|
139078
|
-
|
|
139079
|
-
|
|
139080
|
-
|
|
139081
|
-
-
|
|
139082
|
-
- **Browser testing**: \`playwright\` - Browser automation, screenshots, verification
|
|
139083
|
-
- **Git operations**: \`git-master\` - Atomic commits, rebase/squash, blame/bisect
|
|
139084
|
-
- **Tauri desktop app**: \`tauri-macos-craft\` - macOS-native UI, vibrancy, traffic lights
|
|
139085
|
-
|
|
139086
|
-
User-installed skills get PRIORITY. Always evaluate ALL available skills before delegating.
|
|
139168
|
+
When delegating, check all available skills. User-installed skills get priority. Always evaluate all available skills before delegating. Example domain-skill mappings:
|
|
139169
|
+
- Frontend/UI work: \`frontend-ui-ux\` - Anti-slop design: bold typography, intentional color, meaningful motion
|
|
139170
|
+
- Browser testing: \`playwright\` - Browser automation, screenshots, verification
|
|
139171
|
+
- Git operations: \`git-master\` - Atomic commits, rebase/squash, blame/bisect
|
|
139172
|
+
- Tauri desktop app: \`tauri-macos-craft\` - macOS-native UI, vibrancy, traffic lights
|
|
139087
139173
|
|
|
139088
139174
|
${delegationTable}
|
|
139089
139175
|
|
|
139090
|
-
|
|
139176
|
+
<delegation_prompt>
|
|
139177
|
+
Every delegation prompt needs these 6 sections:
|
|
139178
|
+
1. TASK: atomic goal
|
|
139179
|
+
2. EXPECTED OUTCOME: deliverables + success criteria
|
|
139180
|
+
3. REQUIRED TOOLS: explicit whitelist
|
|
139181
|
+
4. MUST DO: exhaustive requirements - leave nothing implicit
|
|
139182
|
+
5. MUST NOT DO: forbidden actions - anticipate rogue behavior
|
|
139183
|
+
6. CONTEXT: file paths, existing patterns, constraints
|
|
139184
|
+
</delegation_prompt>
|
|
139091
139185
|
|
|
139092
|
-
|
|
139093
|
-
1. TASK: Atomic, specific goal (one action per delegation)
|
|
139094
|
-
2. EXPECTED OUTCOME: Concrete deliverables with success criteria
|
|
139095
|
-
3. REQUIRED TOOLS: Explicit tool whitelist
|
|
139096
|
-
4. MUST DO: Exhaustive requirements - leave NOTHING implicit
|
|
139097
|
-
5. MUST NOT DO: Forbidden actions - anticipate and block rogue behavior
|
|
139098
|
-
6. CONTEXT: File paths, existing patterns, constraints
|
|
139099
|
-
\`\`\`
|
|
139100
|
-
|
|
139101
|
-
Vague prompts = rejected. Be exhaustive.
|
|
139102
|
-
|
|
139103
|
-
After delegation, ALWAYS verify: works as expected? follows codebase pattern? MUST DO / MUST NOT DO respected? NEVER trust subagent self-reports. ALWAYS verify with your own tools.
|
|
139104
|
-
|
|
139105
|
-
### Session Continuity
|
|
139106
|
-
|
|
139107
|
-
Every \`task()\` output includes a session_id. USE IT for follow-ups.
|
|
139186
|
+
After delegation, verify by reading every file the subagent touched. Check: works as expected? follows codebase pattern? Do not trust self-reports.
|
|
139108
139187
|
|
|
139109
|
-
|
|
139110
|
-
|
|
139111
|
-
-
|
|
139188
|
+
<session_continuity>
|
|
139189
|
+
Every \`task()\` returns a session_id. Use it for all follow-ups:
|
|
139190
|
+
- Task failed/incomplete: \`session_id="{id}", prompt="Fix: {error}"\`
|
|
139191
|
+
- Follow-up on result: \`session_id="{id}", prompt="Also: {question}"\`
|
|
139192
|
+
- Verification failed: \`session_id="{id}", prompt="Failed: {error}. Fix."\`
|
|
139112
139193
|
|
|
139194
|
+
This preserves full context, avoids repeated exploration, saves 70%+ tokens.
|
|
139195
|
+
</session_continuity>
|
|
139113
139196
|
${oracleSection ? `
|
|
139114
|
-
${oracleSection}
|
|
139115
|
-
|
|
139116
|
-
|
|
139117
|
-
|
|
139118
|
-
|
|
139119
|
-
<output_contract>
|
|
139120
|
-
Always favor conciseness. Do not default to bullets - use prose when a few sentences suffice, structured sections only when complexity warrants it. Group findings by outcome rather than enumerating every detail.
|
|
139121
|
-
|
|
139122
|
-
For simple or single-file tasks, prefer 1-2 short paragraphs. For larger tasks, use at most 2-4 high-level sections. Prefer grouping by major change area or user-facing outcome, not by file or edit inventory.
|
|
139123
|
-
|
|
139124
|
-
Do not begin responses with conversational interjections or meta commentary. NEVER open with: "Done -", "Got it", "Great question!", "That's a great idea!", "You're right to call that out".
|
|
139125
|
-
|
|
139126
|
-
DO send clear context before significant actions - explain what you're doing and why in plain language so anyone can follow. When explaining technical decisions, explain the WHY, not just the WHAT.
|
|
139127
|
-
|
|
139128
|
-
Updates at meaningful milestones must include a concrete outcome ("Found X", "Updated Y"). Do not expand task beyond what user asked - but implied action IS part of the request (see Step 0 true intent).
|
|
139129
|
-
</output_contract>
|
|
139130
|
-
|
|
139131
|
-
## Code Quality & Verification
|
|
139132
|
-
|
|
139133
|
-
### Before Writing Code (MANDATORY)
|
|
139134
|
-
|
|
139135
|
-
1. SEARCH existing codebase for similar patterns/styles
|
|
139136
|
-
2. Match naming, indentation, import styles, error handling conventions
|
|
139137
|
-
3. Default to ASCII. Add comments only for non-obvious blocks
|
|
139138
|
-
|
|
139139
|
-
### After Implementation (MANDATORY - DO NOT SKIP)
|
|
139140
|
-
|
|
139141
|
-
1. \`lsp_diagnostics\` on ALL modified files - zero errors required
|
|
139142
|
-
2. Run related tests - pattern: modified \`foo.ts\` \u2192 look for \`foo.test.ts\`
|
|
139143
|
-
3. Run typecheck if TypeScript project
|
|
139144
|
-
4. Run build if applicable - exit code 0 required
|
|
139145
|
-
5. Tell user what you verified and the results
|
|
139197
|
+
${oracleSection}` : ""}
|
|
139198
|
+
</delegation>`;
|
|
139199
|
+
const communicationBlock = `<communication>
|
|
139200
|
+
Your output is the one part the user actually sees. Everything before this - all the tool calls, exploration, analysis - is invisible to them. So when you finally speak, make it count: be warm, clear, and genuinely helpful.
|
|
139146
139201
|
|
|
139147
|
-
|
|
139202
|
+
Write in complete, natural sentences that anyone can follow. Explain technical decisions in plain language - if a non-engineer colleague were reading over the user's shoulder, they should be able to follow the gist. Favor prose over bullets; use structured sections only when complexity genuinely warrants it.
|
|
139148
139203
|
|
|
139149
|
-
|
|
139204
|
+
For simple tasks, 1-2 short paragraphs. For larger tasks, at most 2-4 sections grouped by outcome, not by file. Group findings by outcome rather than enumerating every detail.
|
|
139150
139205
|
|
|
139151
|
-
|
|
139206
|
+
When explaining what you did: lead with the result ("Fixed the auth bug - the token was expiring before the refresh check"), then add supporting detail only if it helps understanding. Include concrete details: file paths, patterns found, decisions made. Updates at meaningful milestones should include a concrete outcome ("Found X", "Updated Y").
|
|
139152
139207
|
|
|
139153
|
-
|
|
139154
|
-
|
|
139208
|
+
Do not pad responses with conversational openers ("Done -", "Got it", "Great question!"), meta commentary, or acknowledgements. Do not repeat the user's request back. Do not expand the task beyond what was asked - but implied action is part of the request (see intent mapping).
|
|
139209
|
+
</communication>`;
|
|
139210
|
+
return `${identityBlock}
|
|
139155
139211
|
|
|
139156
|
-
|
|
139157
|
-
2. Did you write "I'll do X" or "I recommend X"? \u2192 Did you then DO X?
|
|
139158
|
-
3. Did you offer to do something ("Would you like me to...?") \u2192 VIOLATION. Go back and do it.
|
|
139159
|
-
4. Did you answer a question and stop? \u2192 Was there implied work? If yes, do it now.
|
|
139212
|
+
${intentBlock}
|
|
139160
139213
|
|
|
139161
|
-
|
|
139162
|
-
</turn_end_self_check>
|
|
139214
|
+
${exploreBlock}
|
|
139163
139215
|
|
|
139164
|
-
|
|
139216
|
+
${constraintsBlock}
|
|
139165
139217
|
|
|
139166
|
-
|
|
139218
|
+
${executionBlock}
|
|
139167
139219
|
|
|
139168
|
-
|
|
139220
|
+
${trackingBlock}
|
|
139169
139221
|
|
|
139170
|
-
|
|
139222
|
+
${progressBlock}
|
|
139171
139223
|
|
|
139172
|
-
|
|
139224
|
+
${delegationBlock}
|
|
139173
139225
|
|
|
139174
|
-
|
|
139226
|
+
${communicationBlock}`;
|
|
139175
139227
|
}
|
|
139176
139228
|
|
|
139177
139229
|
// src/agents/hephaestus/agent.ts
|
|
@@ -143551,7 +143603,9 @@ function createConfigHandler(deps) {
|
|
|
143551
143603
|
// src/create-managers.ts
|
|
143552
143604
|
function createManagers(args) {
|
|
143553
143605
|
const { ctx, pluginConfig, tmuxConfig, modelCacheState, backgroundNotificationHookEnabled } = args;
|
|
143554
|
-
|
|
143606
|
+
if (tmuxConfig.enabled) {
|
|
143607
|
+
markServerRunningInProcess();
|
|
143608
|
+
}
|
|
143555
143609
|
const tmuxSessionManager = new TmuxSessionManager(ctx, tmuxConfig);
|
|
143556
143610
|
registerManagerForCleanup({
|
|
143557
143611
|
shutdown: async () => {
|
|
@@ -143751,8 +143805,14 @@ function trimToolsToCap(filteredTools, maxTools) {
|
|
|
143751
143805
|
log(`[tool-registry] Trimmed ${removed} tools to satisfy max_tools=${maxTools}. Final plugin tool count=${currentCount}.`);
|
|
143752
143806
|
}
|
|
143753
143807
|
function createToolRegistry(args) {
|
|
143754
|
-
const {
|
|
143755
|
-
|
|
143808
|
+
const {
|
|
143809
|
+
ctx,
|
|
143810
|
+
pluginConfig,
|
|
143811
|
+
managers,
|
|
143812
|
+
skillContext,
|
|
143813
|
+
availableCategories,
|
|
143814
|
+
interactiveBashEnabled = isInteractiveBashEnabled()
|
|
143815
|
+
} = args;
|
|
143756
143816
|
const backgroundTools = createBackgroundTools(managers.backgroundManager, ctx.client);
|
|
143757
143817
|
const callOmoAgent = createCallOmoAgent(ctx, managers.backgroundManager, pluginConfig.disabled_agents ?? [], pluginConfig.agents, pluginConfig.categories);
|
|
143758
143818
|
const isMultimodalLookerEnabled = !(pluginConfig.disabled_agents ?? []).some((agent) => agent.toLowerCase() === "multimodal-looker");
|
|
@@ -143829,7 +143889,7 @@ function createToolRegistry(args) {
|
|
|
143829
143889
|
task: delegateTask,
|
|
143830
143890
|
skill_mcp: skillMcpTool,
|
|
143831
143891
|
skill: skillTool,
|
|
143832
|
-
...
|
|
143892
|
+
...interactiveBashEnabled ? { interactive_bash } : {},
|
|
143833
143893
|
...taskToolsRecord,
|
|
143834
143894
|
...hashlineToolsRecord
|
|
143835
143895
|
};
|
|
@@ -144680,7 +144740,8 @@ function isCompactionAgent5(agent) {
|
|
|
144680
144740
|
return agent.toLowerCase() === "compaction";
|
|
144681
144741
|
}
|
|
144682
144742
|
function createEventHandler2(args) {
|
|
144683
|
-
const { ctx, firstMessageVariantGate, managers, hooks: hooks2 } = args;
|
|
144743
|
+
const { ctx, pluginConfig, firstMessageVariantGate, managers, hooks: hooks2 } = args;
|
|
144744
|
+
const tmuxIntegrationEnabled = isTmuxIntegrationEnabled(pluginConfig);
|
|
144684
144745
|
const pluginContext = ctx;
|
|
144685
144746
|
const isRuntimeFallbackEnabled = hooks2.runtimeFallback !== null && hooks2.runtimeFallback !== undefined && (typeof args.pluginConfig.runtime_fallback === "boolean" ? args.pluginConfig.runtime_fallback : args.pluginConfig.runtime_fallback?.enabled ?? false);
|
|
144686
144747
|
const isModelFallbackEnabled = hooks2.modelFallback !== null && hooks2.modelFallback !== undefined;
|
|
@@ -144823,7 +144884,7 @@ function createEventHandler2(args) {
|
|
|
144823
144884
|
}
|
|
144824
144885
|
const { event } = input;
|
|
144825
144886
|
const props = event.properties;
|
|
144826
|
-
if (TMUX_ACTIVITY_EVENT_TYPES.has(event.type)) {
|
|
144887
|
+
if (tmuxIntegrationEnabled && TMUX_ACTIVITY_EVENT_TYPES.has(event.type)) {
|
|
144827
144888
|
managers.tmuxSessionManager.onEvent?.(event);
|
|
144828
144889
|
}
|
|
144829
144890
|
if (event.type === "session.created") {
|
|
@@ -144832,7 +144893,9 @@ function createEventHandler2(args) {
|
|
|
144832
144893
|
setMainSession(sessionInfo?.id);
|
|
144833
144894
|
}
|
|
144834
144895
|
firstMessageVariantGate.markSessionCreated(sessionInfo);
|
|
144835
|
-
|
|
144896
|
+
if (tmuxIntegrationEnabled) {
|
|
144897
|
+
await managers.tmuxSessionManager.onSessionCreated(event);
|
|
144898
|
+
}
|
|
144836
144899
|
}
|
|
144837
144900
|
if (event.type === "session.deleted") {
|
|
144838
144901
|
const sessionInfo = props?.info;
|
|
@@ -144860,9 +144923,11 @@ function createEventHandler2(args) {
|
|
|
144860
144923
|
deleteSessionTools(sessionInfo.id);
|
|
144861
144924
|
await managers.skillMcpManager.disconnectSession(sessionInfo.id);
|
|
144862
144925
|
await lspManager.cleanupTempDirectoryClients();
|
|
144863
|
-
|
|
144864
|
-
|
|
144865
|
-
|
|
144926
|
+
if (tmuxIntegrationEnabled) {
|
|
144927
|
+
await managers.tmuxSessionManager.onSessionDeleted({
|
|
144928
|
+
sessionID: sessionInfo.id
|
|
144929
|
+
});
|
|
144930
|
+
}
|
|
144866
144931
|
}
|
|
144867
144932
|
}
|
|
144868
144933
|
if (event.type === "message.removed") {
|