titan-agent 6.4.3 → 6.4.4

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.
@@ -1278,66 +1278,81 @@ CRITICAL: Widgets are NOT files. Do NOT use write_file, edit_file, or any file t
1278
1278
  }
1279
1279
  modelUsed = activeModel;
1280
1280
  let activeTools = tools;
1281
- if (earlyPersona) {
1282
- const { applyPersonaToolFilter } = await import("./personaProfiles.js");
1281
+ let allToolsBackup = activeTools;
1282
+ let toolSearchEnabled = true;
1283
+ const explicitAllowList = overrides?.allowedTools;
1284
+ if (explicitAllowList && explicitAllowList.length > 0) {
1285
+ const allow = new Set(explicitAllowList);
1283
1286
  const before = activeTools.length;
1284
- activeTools = applyPersonaToolFilter(activeTools, earlyPersona);
1285
- if (activeTools.length !== before) {
1286
- logger.info(COMPONENT, `[Persona:${earlyPersona.id}] tools ${before} \u2192 ${activeTools.length}`);
1287
+ activeTools = tools.filter((t) => allow.has(t.function.name));
1288
+ allToolsBackup = activeTools;
1289
+ logger.info(COMPONENT, `[AllowedTools] override bound ${activeTools.length}/${explicitAllowList.length} requested tools (filter chain bypassed): [${activeTools.map((t) => t.function.name).join(", ")}] from pool of ${before}`);
1290
+ const missing = explicitAllowList.filter((name) => !activeTools.some((t) => t.function.name === name));
1291
+ if (missing.length > 0) {
1292
+ logger.warn(COMPONENT, `[AllowedTools] caller asked for tools that aren't registered: [${missing.join(", ")}]`);
1287
1293
  }
1288
- }
1289
- const SMALL_MODEL_PATTERNS = ["llama3.2", "llama3.1:8b", "phi", "gemma:2b", "qwen3.5:4b", "tinyllama", "dolphin3"];
1290
- const isSmallModel = SMALL_MODEL_PATTERNS.some((p) => activeModel.toLowerCase().includes(p));
1291
- if (isSmallModel) {
1292
- const CORE_TOOL_NAMES = ["shell", "read_file", "write_file", "edit_file", "list_dir", "memory"];
1293
- const coreTools = activeTools.filter((t) => CORE_TOOL_NAMES.includes(t.function.name));
1294
- logger.info(COMPONENT, `[SmallModel] Reducing tools from ${activeTools.length} to ${coreTools.length} for ${activeModel}`);
1295
- activeTools = coreTools;
1296
- }
1297
- if (!voiceFastPath && !isSmallModel && isBrainAvailable()) {
1298
- const brainFiltered = await brainSelectTools(message, activeTools);
1299
- if (brainFiltered.length > 0 && brainFiltered.length < activeTools.length) {
1300
- logger.info(COMPONENT, `[Brain] Filtered: ${activeTools.length} \u2192 ${brainFiltered.length} tools`);
1301
- activeTools = brainFiltered;
1294
+ } else {
1295
+ if (earlyPersona) {
1296
+ const { applyPersonaToolFilter } = await import("./personaProfiles.js");
1297
+ const before = activeTools.length;
1298
+ activeTools = applyPersonaToolFilter(activeTools, earlyPersona);
1299
+ if (activeTools.length !== before) {
1300
+ logger.info(COMPONENT, `[Persona:${earlyPersona.id}] tools ${before} \u2192 ${activeTools.length}`);
1301
+ }
1302
1302
  }
1303
- }
1304
- const toolSearchConfig = config.toolSearch;
1305
- const toolSearchEnabled = toolSearchConfig?.enabled ?? true;
1306
- const allToolsBackup = activeTools;
1307
- if (pipelineEnsureTools.length > 0 && !(toolSearchEnabled && !isSmallModel && activeTools.length > 12)) {
1308
- const activeNames = new Set(activeTools.map((t) => t.function.name));
1309
- const missing = pipelineEnsureTools.filter((name) => !activeNames.has(name));
1310
- if (missing.length > 0) {
1311
- const rescued = allToolsBackup.filter((t) => missing.includes(t.function.name));
1312
- activeTools.push(...rescued);
1313
- if (rescued.length > 0) {
1314
- logger.info(COMPONENT, `[Pipeline:${pipelineType}] Ensured ${rescued.length} tools (no-compact): [${rescued.map((t) => t.function.name).join(", ")}]`);
1303
+ const SMALL_MODEL_PATTERNS = ["llama3.2", "llama3.1:8b", "phi", "gemma:2b", "qwen3.5:4b", "tinyllama", "dolphin3"];
1304
+ const isSmallModel = SMALL_MODEL_PATTERNS.some((p) => activeModel.toLowerCase().includes(p));
1305
+ if (isSmallModel) {
1306
+ const CORE_TOOL_NAMES = ["shell", "read_file", "write_file", "edit_file", "list_dir", "memory"];
1307
+ const coreTools = activeTools.filter((t) => CORE_TOOL_NAMES.includes(t.function.name));
1308
+ logger.info(COMPONENT, `[SmallModel] Reducing tools from ${activeTools.length} to ${coreTools.length} for ${activeModel}`);
1309
+ activeTools = coreTools;
1310
+ }
1311
+ if (!voiceFastPath && !isSmallModel && isBrainAvailable()) {
1312
+ const brainFiltered = await brainSelectTools(message, activeTools);
1313
+ if (brainFiltered.length > 0 && brainFiltered.length < activeTools.length) {
1314
+ logger.info(COMPONENT, `[Brain] Filtered: ${activeTools.length} \u2192 ${brainFiltered.length} tools`);
1315
+ activeTools = brainFiltered;
1315
1316
  }
1316
1317
  }
1317
- }
1318
- if (toolSearchEnabled && !isSmallModel && activeTools.length > 12) {
1319
- const VOICE_CORE_TOOLS = ["shell", "web_search", "weather", "memory", "ha_control", "ha_devices", "ha_status", "ha_setup", "tool_search"];
1320
- const configCoreTools = toolSearchConfig?.coreTools;
1321
- const effectiveCoreTools = configCoreTools && configCoreTools.length > 0 ? configCoreTools : DEFAULT_CORE_TOOLS;
1322
- const pipelineMerged = pipelineEnsureTools.length > 0 ? [.../* @__PURE__ */ new Set([...effectiveCoreTools, ...pipelineEnsureTools])] : effectiveCoreTools;
1323
- const coreNames = new Set(voiceFastPath ? VOICE_CORE_TOOLS : pipelineMerged);
1324
- activeTools = activeTools.filter((t) => coreNames.has(t.function.name));
1325
- if (pipelineEnsureTools.length > 0) {
1318
+ const toolSearchConfig = config.toolSearch;
1319
+ toolSearchEnabled = toolSearchConfig?.enabled ?? true;
1320
+ allToolsBackup = activeTools;
1321
+ if (pipelineEnsureTools.length > 0 && !(toolSearchEnabled && !isSmallModel && activeTools.length > 12)) {
1326
1322
  const activeNames = new Set(activeTools.map((t) => t.function.name));
1327
1323
  const missing = pipelineEnsureTools.filter((name) => !activeNames.has(name));
1328
1324
  if (missing.length > 0) {
1329
1325
  const rescued = allToolsBackup.filter((t) => missing.includes(t.function.name));
1330
1326
  activeTools.push(...rescued);
1331
1327
  if (rescued.length > 0) {
1332
- logger.info(COMPONENT, `[Pipeline:${pipelineType}] Rescued ${rescued.length} tools: [${rescued.map((t) => t.function.name).join(", ")}]`);
1328
+ logger.info(COMPONENT, `[Pipeline:${pipelineType}] Ensured ${rescued.length} tools (no-compact): [${rescued.map((t) => t.function.name).join(", ")}]`);
1333
1329
  }
1334
1330
  }
1335
1331
  }
1336
- logger.info(COMPONENT, `[ToolSearch] Compact mode: ${allToolsBackup.length} \u2192 ${activeTools.length} tools (${allToolsBackup.length - activeTools.length} discoverable via tool_search)`);
1337
- }
1338
- if (dangerous) {
1339
- activeTools = [];
1340
- logger.info(COMPONENT, "[Safety] Stripped all tools \u2014 dangerous command detected");
1332
+ if (toolSearchEnabled && !isSmallModel && activeTools.length > 12) {
1333
+ const VOICE_CORE_TOOLS = ["shell", "web_search", "weather", "memory", "ha_control", "ha_devices", "ha_status", "ha_setup", "tool_search"];
1334
+ const configCoreTools = toolSearchConfig?.coreTools;
1335
+ const effectiveCoreTools = configCoreTools && configCoreTools.length > 0 ? configCoreTools : DEFAULT_CORE_TOOLS;
1336
+ const pipelineMerged = pipelineEnsureTools.length > 0 ? [.../* @__PURE__ */ new Set([...effectiveCoreTools, ...pipelineEnsureTools])] : effectiveCoreTools;
1337
+ const coreNames = new Set(voiceFastPath ? VOICE_CORE_TOOLS : pipelineMerged);
1338
+ activeTools = activeTools.filter((t) => coreNames.has(t.function.name));
1339
+ if (pipelineEnsureTools.length > 0) {
1340
+ const activeNames = new Set(activeTools.map((t) => t.function.name));
1341
+ const missing = pipelineEnsureTools.filter((name) => !activeNames.has(name));
1342
+ if (missing.length > 0) {
1343
+ const rescued = allToolsBackup.filter((t) => missing.includes(t.function.name));
1344
+ activeTools.push(...rescued);
1345
+ if (rescued.length > 0) {
1346
+ logger.info(COMPONENT, `[Pipeline:${pipelineType}] Rescued ${rescued.length} tools: [${rescued.map((t) => t.function.name).join(", ")}]`);
1347
+ }
1348
+ }
1349
+ }
1350
+ logger.info(COMPONENT, `[ToolSearch] Compact mode: ${allToolsBackup.length} \u2192 ${activeTools.length} tools (${allToolsBackup.length - activeTools.length} discoverable via tool_search)`);
1351
+ }
1352
+ if (dangerous) {
1353
+ activeTools = [];
1354
+ logger.info(COMPONENT, "[Safety] Stripped all tools \u2014 dangerous command detected");
1355
+ }
1341
1356
  }
1342
1357
  setAutonomousMode(isAutonomous);
1343
1358
  heartbeat(session.id);