titan-agent 5.0.2 → 5.0.3
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/agent/agent.js +48 -3
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/agentLoop.js +83 -5
- package/dist/agent/agentLoop.js.map +1 -1
- package/dist/agent/commandPost.js +1 -1
- package/dist/agent/commandPost.js.map +1 -1
- package/dist/agent/goalProposer.js +2 -2
- package/dist/agent/goalProposer.js.map +1 -1
- package/dist/agent/missionDriver.js +1 -1
- package/dist/agent/missionDriver.js.map +1 -1
- package/dist/agent/promptBudget.js +85 -0
- package/dist/agent/promptBudget.js.map +1 -0
- package/dist/agent/structuredSpawn.js +1 -1
- package/dist/agent/structuredSpawn.js.map +1 -1
- package/dist/agent/subtaskTaxonomy.js +1 -1
- package/dist/agent/subtaskTaxonomy.js.map +1 -1
- package/dist/agent/systemPromptParts.js +10 -1
- package/dist/agent/systemPromptParts.js.map +1 -1
- package/dist/agent/toolRunner.js +16 -0
- package/dist/agent/toolRunner.js.map +1 -1
- package/dist/agent/toolSearch.js +4 -1
- package/dist/agent/toolSearch.js.map +1 -1
- package/dist/analytics/bugReports.js +1 -1
- package/dist/analytics/bugReports.js.map +1 -1
- package/dist/channels/messenger.js +1 -1
- package/dist/channels/messenger.js.map +1 -1
- package/dist/eval/harness.js +141 -0
- package/dist/eval/harness.js.map +1 -0
- package/dist/gateway/server.js +374 -74
- package/dist/gateway/server.js.map +1 -1
- package/dist/hooks/shellHooks.js +1 -1
- package/dist/hooks/shellHooks.js.map +1 -1
- package/dist/lib/auto-heal/repair-strategies.js.map +1 -1
- package/dist/memory/promptIncludes.js +58 -0
- package/dist/memory/promptIncludes.js.map +1 -0
- package/dist/organism/alertsStore.js +70 -0
- package/dist/organism/alertsStore.js.map +1 -0
- package/dist/plugins/memoryRetrieval.js.map +1 -1
- package/dist/providers/ollama.js +7 -7
- package/dist/providers/ollama.js.map +1 -1
- package/dist/safety/invariants.js +60 -0
- package/dist/safety/invariants.js.map +1 -0
- package/dist/safety/opusReview.js +1 -1
- package/dist/safety/opusReview.js.map +1 -1
- package/dist/security/commandScanner.js +2 -2
- package/dist/security/commandScanner.js.map +1 -1
- package/dist/security/secretGuard.js +4 -4
- package/dist/security/secretGuard.js.map +1 -1
- package/dist/skills/builtin/widget_gallery.js +28 -1
- package/dist/skills/builtin/widget_gallery.js.map +1 -1
- package/dist/skills/frontmatterLoader.js +119 -0
- package/dist/skills/frontmatterLoader.js.map +1 -0
- package/dist/skills/registry.js +20 -0
- package/dist/skills/registry.js.map +1 -1
- package/dist/testing/testHealthMonitor.js +1 -2
- package/dist/testing/testHealthMonitor.js.map +1 -1
- package/dist/utils/constants.js +2 -2
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/replyQuality.js +1 -1
- package/dist/utils/replyQuality.js.map +1 -1
- package/dist/utils/tokens.js +1 -1
- package/dist/utils/tokens.js.map +1 -1
- package/docs/bleeding-edge-agents-2026.md +450 -0
- package/docs/langchain-analysis.md +598 -0
- package/docs/langchain-code-analysis.md +363 -0
- package/docs/space-agent-analysis.md +300 -0
- package/package.json +1 -1
- package/ui/dist/assets/{AuditPanel-G7YA1HzV.js → AuditPanel-B84Mp16G.js} +2 -2
- package/ui/dist/assets/AutonomyPanel-DOtiTFxV.js +11 -0
- package/ui/dist/assets/{AutopilotPanel-CHRjxdh0.js → AutopilotPanel-nTb1Dnru.js} +1 -1
- package/ui/dist/assets/AutoresearchPanel-D46mX8VF.js +6 -0
- package/ui/dist/assets/BackupPanel-DGM1XXbG.js +1 -0
- package/ui/dist/assets/BrowserPanel-Cn1tTN3y.js +6 -0
- package/ui/dist/assets/{CPAgents-D5533PhK.js → CPAgents-CEraUkME.js} +1 -1
- package/ui/dist/assets/{CPDashboard-C-GgqDsI.js → CPDashboard-B_yidGAe.js} +2 -2
- package/ui/dist/assets/CPFiles-BBS8jtYH.js +1 -0
- package/ui/dist/assets/CPGoals-DL5v21TZ.js +1 -0
- package/ui/dist/assets/CPInbox-CyLQJBYF.js +11 -0
- package/ui/dist/assets/{CPSocial-mUQsrSh5.js → CPSocial-BkEtQ1Um.js} +3 -3
- package/ui/dist/assets/ChannelsPanel-CD2kHhA5.js +1 -0
- package/ui/dist/assets/CheckpointsPanel-BrUTFPu_.js +1 -0
- package/ui/dist/assets/CommandPostHub-BPPaUv1B.js +29 -0
- package/ui/dist/assets/CronPanel-CsfQctFp.js +1 -0
- package/ui/dist/assets/DaemonPanel-CNUggBbL.js +1 -0
- package/ui/dist/assets/DataTable-DuAEp_QJ.js +1 -0
- package/ui/dist/assets/{EmptyState-D60-wQrz.js → EmptyState-DFrAEZDm.js} +1 -1
- package/ui/dist/assets/EvalPanel-DEX0a5-b.js +1 -0
- package/ui/dist/assets/{FilesPanel-BNN3h_HW.js → FilesPanel-DATsiAqG.js} +1 -1
- package/ui/dist/assets/FleetPanel-QYQKqx4W.js +1 -0
- package/ui/dist/assets/{HomelabPanel-1mfhRBh6.js → HomelabPanel-DhuXd3ZD.js} +2 -2
- package/ui/dist/assets/{InfraView-Df6SFI7b.js → InfraView-eS7cpESw.js} +2 -2
- package/ui/dist/assets/InlineEditableField-zIAnW4AR.js +1 -0
- package/ui/dist/assets/{Input-DYukme8A.js → Input-bFsLI0fq.js} +1 -1
- package/ui/dist/assets/IntegrationsPanel-C_FswSRN.js +1 -0
- package/ui/dist/assets/IntelligenceView-smQ6aBwx.js +2 -0
- package/ui/dist/assets/{LearningPanel-BPx05bBu.js → LearningPanel-BEgF_iND.js} +1 -1
- package/ui/dist/assets/{LogsPanel-D3Qfp2SE.js → LogsPanel-Br1P8ST6.js} +1 -1
- package/ui/dist/assets/McpPanel-ByvQ12J_.js +1 -0
- package/ui/dist/assets/{MemoryGraphPanel-BFovwaSG.js → MemoryGraphPanel-BGOeSaET.js} +1 -1
- package/ui/dist/assets/MemoryWikiPanel-CR8btd66.js +11 -0
- package/ui/dist/assets/MeshPanel-BjkcSOMz.js +11 -0
- package/ui/dist/assets/NvidiaPanel-NYt42w7L.js +1 -0
- package/ui/dist/assets/OrganismPanel-PHvISvVn.js +1 -0
- package/ui/dist/assets/OverviewPanel-q35zdMr6.js +6 -0
- package/ui/dist/assets/{PageHeader-BdvxKoad.js → PageHeader-Cwn3OALc.js} +1 -1
- package/ui/dist/assets/PaperclipPanel-BDpQki0d.js +1 -0
- package/ui/dist/assets/{PersonasPanel-BpI6Npxv.js → PersonasPanel-DxrGW5C4.js} +1 -1
- package/ui/dist/assets/RecipesPanel-CYRdBx5u.js +1 -0
- package/ui/dist/assets/{SecurityPanel-CBDsEAFz.js → SecurityPanel-i1QMctV0.js} +1 -1
- package/ui/dist/assets/SelfImprovePanel-DbybAZWp.js +1 -0
- package/ui/dist/assets/SelfProposalsPanel-DtcTUDDd.js +2 -0
- package/ui/dist/assets/SessionsPanel-B7QmOizR.js +1 -0
- package/ui/dist/assets/SessionsTab-BdJj_vsI.js +1 -0
- package/ui/dist/assets/{SettingsPanel-BiWHsOAJ.js → SettingsPanel-DnEvJUFe.js} +1 -1
- package/ui/dist/assets/SettingsView-C39dk_yr.js +2 -0
- package/ui/dist/assets/{SkeletonLoader-CGtpZJ-7.js → SkeletonLoader-CsiR8ED9.js} +1 -1
- package/ui/dist/assets/{SkillsPanel-Z_9jA6dU.js → SkillsPanel-DM4qBFDS.js} +1 -1
- package/ui/dist/assets/{SomaView-AP3BXqf-.js → SomaView-CWnPKEQI.js} +1 -1
- package/ui/dist/assets/{StatCard-CrnvXPg5.js → StatCard-CY8lgeWm.js} +1 -1
- package/ui/dist/assets/{StatusBadge-B6r5EWBA.js → StatusBadge-CGvKbP7R.js} +1 -1
- package/ui/dist/assets/TeamsPanel-Bf6GaUni.js +1 -0
- package/ui/dist/assets/{TelemetryPanel-D6o14H-i.js → TelemetryPanel-JZ90gJXC.js} +1 -1
- package/ui/dist/assets/TitanCanvas-Hk49NFcA.js +1092 -0
- package/ui/dist/assets/ToolsView-Cq7Fuq3i.js +2 -0
- package/ui/dist/assets/{Tooltip-DNsYGHC9.js → Tooltip-CcoZrKsl.js} +1 -1
- package/ui/dist/assets/{TraceViewer-TOpdmqLF.js → TraceViewer-ojGf0drx.js} +1 -1
- package/ui/dist/assets/TrainingPanel-CWnP4H2l.js +1 -0
- package/ui/dist/assets/{VoiceOverlay-XIyCbAP7.js → VoiceOverlay-Dn6iaYgd.js} +1 -1
- package/ui/dist/assets/VramPanel-CLd9Ggck.js +1 -0
- package/ui/dist/assets/WatchView-CQBemwsm.js +13 -0
- package/ui/dist/assets/WorkTab-BOfTN-Bd.js +1 -0
- package/ui/dist/assets/WorkflowsPanel-qzNS0p0u.js +11 -0
- package/ui/dist/assets/{arrow-left-CQF-yBIU.js → arrow-left-c-8OFZUV.js} +1 -1
- package/ui/dist/assets/{chart-column-1smg0GbX.js → chart-column-x6L66Qw7.js} +1 -1
- package/ui/dist/assets/{circle-check-big-BiMDFx6C.js → circle-check-big-WaW3U3Xl.js} +1 -1
- package/ui/dist/assets/{dollar-sign-DMYH4Q_a.js → dollar-sign-D2Oce4Ru.js} +1 -1
- package/ui/dist/assets/{download-BYFd-yl6.js → download-YvPDLlFJ.js} +1 -1
- package/ui/dist/assets/eye-off-DIMcxsdQ.js +6 -0
- package/ui/dist/assets/{funnel-pWBglhfw.js → funnel-DqD9srZu.js} +1 -1
- package/ui/dist/assets/{git-branch-Cgqic2Us.js → git-branch-0FamUEbU.js} +1 -1
- package/ui/dist/assets/index-D932CbpQ.css +1 -0
- package/ui/dist/assets/index-NatBSFxj.js +227 -0
- package/ui/dist/assets/{legacy-BHbi-Nm_.js → legacy-DOO7F5cq.js} +1 -1
- package/ui/dist/assets/{lightbulb-D_y0Mtyq.js → lightbulb-Bk6KlR6q.js} +1 -1
- package/ui/dist/assets/pause-DDC_zUiJ.js +6 -0
- package/ui/dist/assets/{play-2xR4_zUG.js → play-BPXbHToG.js} +1 -1
- package/ui/dist/assets/{plug-DhvhYYy_.js → plug-Dxp-sWVF.js} +1 -1
- package/ui/dist/assets/proxy-vU7v4NVM.js +9 -0
- package/ui/dist/assets/square-Bn_0tYME.js +6 -0
- package/ui/dist/assets/target-BrtxUtzl.js +6 -0
- package/ui/dist/assets/toggle-right-CYphlpN5.js +11 -0
- package/ui/dist/assets/{trash-2-DmRaMz9e.js → trash-2-C_Jsp23A.js} +1 -1
- package/ui/dist/assets/{trending-up-DsDcs3Jo.js → trending-up-DrtLViSm.js} +1 -1
- package/ui/dist/assets/trophy-DdRzAOfo.js +6 -0
- package/ui/dist/index.html +2 -2
- package/ui/dist/assets/CPFiles-G7veSjMg.js +0 -6
- package/ui/dist/assets/CPGoals-C3DlKJrJ.js +0 -1
- package/ui/dist/assets/CPInbox-D10curQs.js +0 -16
- package/ui/dist/assets/ChannelsPanel-M3pO2htW.js +0 -1
- package/ui/dist/assets/CommandPostHub-CW9OY1A4.js +0 -37
- package/ui/dist/assets/InlineEditableField-CH-jR3LC.js +0 -11
- package/ui/dist/assets/IntegrationsPanel-EaN999Te.js +0 -1
- package/ui/dist/assets/IntelligenceView-Q4DBmJpJ.js +0 -2
- package/ui/dist/assets/McpPanel-zC7jTaSx.js +0 -6
- package/ui/dist/assets/MeshPanel-CqtYZ74K.js +0 -11
- package/ui/dist/assets/NvidiaPanel-BVIZFHet.js +0 -1
- package/ui/dist/assets/SelfImprovePanel-PSCYO6sx.js +0 -11
- package/ui/dist/assets/SessionsTab-Cn3dGgjX.js +0 -1
- package/ui/dist/assets/SettingsView-3BSIzAfW.js +0 -2
- package/ui/dist/assets/TitanCanvas-cnb7R1gS.js +0 -1056
- package/ui/dist/assets/ToolsView-Dp-xUWJG.js +0 -2
- package/ui/dist/assets/WorkTab-Pgq-iLz9.js +0 -1
- package/ui/dist/assets/WorkflowsPanel-B91LeW7r.js +0 -21
- package/ui/dist/assets/eye-BfW7UcEC.js +0 -11
- package/ui/dist/assets/index-BWSnB6Kr.js +0 -227
- package/ui/dist/assets/index-Dtw1pbjc.css +0 -1
package/dist/hooks/shellHooks.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/shellHooks.ts"],"sourcesContent":["/**\n * TITAN v5.0 — Shell Hooks (Hermes v0.11.0 parity)\n *\n * Execute shell scripts as lifecycle hooks without writing Python plugins.\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\nimport type { ShellHookEvent, ShellHookEnv, ShellHookResult } from './types.js';\n\nconst COMPONENT = 'ShellHooks';\nconst execAsync = promisify(exec);\n\nconst DANGEROUS_COMMANDS = [\n /rm\\s+-rf\\s+\\//,\n /:\\(\\)\\{\\s*:\\|:\\s
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/shellHooks.ts"],"sourcesContent":["/**\n * TITAN v5.0 — Shell Hooks (Hermes v0.11.0 parity)\n *\n * Execute shell scripts as lifecycle hooks without writing Python plugins.\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { loadConfig } from '../config/config.js';\nimport logger from '../utils/logger.js';\nimport type { ShellHookEvent, ShellHookEnv, ShellHookResult } from './types.js';\n\nconst COMPONENT = 'ShellHooks';\nconst execAsync = promisify(exec);\n\nconst DANGEROUS_COMMANDS = [\n /rm\\s+-rf\\s+\\//,\n /:\\(\\)\\{\\s*:\\|:\\s*&\\s*\\};:\\s*:/,\n />\\s*\\/dev\\/sda/,\n /mkfs\\./,\n /curl\\s+.*\\|\\s*(?:sh|bash)/,\n /wget\\s+.*\\|\\s*(?:sh|bash)/,\n];\n\nfunction isDangerous(command: string): boolean {\n return DANGEROUS_COMMANDS.some(re => re.test(command));\n}\n\nfunction buildEnv(base: ShellHookEnv): NodeJS.ProcessEnv {\n return {\n ...process.env,\n TITAN_SESSION_ID: base.TITAN_SESSION_ID,\n TITAN_AGENT_ID: base.TITAN_AGENT_ID,\n ...(base.TITAN_TOOL_NAME && { TITAN_TOOL_NAME: base.TITAN_TOOL_NAME }),\n ...(base.TITAN_TOOL_ARGS && { TITAN_TOOL_ARGS: base.TITAN_TOOL_ARGS }),\n ...(base.TITAN_TOOL_RESULT && { TITAN_TOOL_RESULT: base.TITAN_TOOL_RESULT }),\n ...(base.TITAN_ROUND && { TITAN_ROUND: base.TITAN_ROUND }),\n };\n}\n\n/** Run shell hooks for a given event */\nexport async function runShellHooks(\n event: ShellHookEvent,\n env: ShellHookEnv,\n): Promise<ShellHookResult[]> {\n const config = loadConfig();\n const hooksConfig = config.hooks?.shell;\n if (!hooksConfig?.enabled) return [];\n\n const commands = (hooksConfig[event] as string[]) ?? [];\n if (commands.length === 0) return [];\n\n const results: ShellHookResult[] = [];\n\n for (const command of commands) {\n if (isDangerous(command)) {\n logger.warn(COMPONENT, `Skipping dangerous shell hook: ${command.slice(0, 100)}`);\n results.push({ exitCode: 1, stdout: '', stderr: 'Dangerous command blocked by deny-list', blocked: true, blockReason: 'Deny-list match' });\n continue;\n }\n\n try {\n const { stdout, stderr } = await execAsync(command, {\n env: buildEnv(env),\n timeout: 10_000,\n cwd: process.cwd(),\n });\n results.push({ exitCode: 0, stdout: stdout.trim(), stderr: stderr.trim() });\n } catch (err) {\n const e = err as { code?: number; stdout?: string; stderr?: string };\n results.push({\n exitCode: e.code ?? 1,\n stdout: (e.stdout ?? '').trim(),\n stderr: (e.stderr ?? String(err)).trim(),\n });\n }\n }\n\n return results;\n}\n\n/** Run pre-tool hooks. Returns { allow, reason?, modifiedArgs? } */\nexport async function runPreToolShellHooks(\n toolName: string,\n args: Record<string, unknown>,\n sessionId: string,\n agentId: string,\n round: number,\n): Promise<{ allow: boolean; reason?: string; modifiedArgs?: Record<string, unknown> }> {\n const results = await runShellHooks('pre_tool_call', {\n TITAN_SESSION_ID: sessionId,\n TITAN_AGENT_ID: agentId,\n TITAN_TOOL_NAME: toolName,\n TITAN_TOOL_ARGS: JSON.stringify(args),\n TITAN_ROUND: String(round),\n });\n\n for (const r of results) {\n if (r.exitCode !== 0) {\n return { allow: false, reason: r.stderr || 'Shell hook blocked execution' };\n }\n }\n\n // If last hook printed valid JSON to stdout, treat it as modified args\n const last = results[results.length - 1];\n if (last?.stdout) {\n try {\n const parsed = JSON.parse(last.stdout);\n if (typeof parsed === 'object' && parsed !== null) {\n return { allow: true, modifiedArgs: parsed as Record<string, unknown> };\n }\n } catch {\n // Not JSON — ignore\n }\n }\n\n return { allow: true };\n}\n\n/** Run post-tool hooks */\nexport async function runPostToolShellHooks(\n toolName: string,\n args: Record<string, unknown>,\n result: string,\n sessionId: string,\n agentId: string,\n round: number,\n): Promise<string | undefined> {\n const results = await runShellHooks('post_tool_call', {\n TITAN_SESSION_ID: sessionId,\n TITAN_AGENT_ID: agentId,\n TITAN_TOOL_NAME: toolName,\n TITAN_TOOL_ARGS: JSON.stringify(args),\n TITAN_TOOL_RESULT: result,\n TITAN_ROUND: String(round),\n });\n\n const last = results[results.length - 1];\n if (last?.stdout) {\n try {\n const parsed = JSON.parse(last.stdout);\n if (typeof parsed === 'object' && parsed !== null && 'content' in parsed) {\n return String(parsed.content);\n }\n } catch {\n // Not JSON — return raw stdout as modified result\n return last.stdout;\n }\n }\n return undefined;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/auto-heal/repair-strategies.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport {\n DependencyIssue,\n RepairAction,\n RepairResult,\n AutoHealConfig,\n DEFAULT_AUTO_HEAL_CONFIG,\n} from './types.js';\n\nexport class MissingPackageRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'missing_package' && this.config.enabledCategories.includes('missing_package');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const pkg = issue.packageName;\n if (!pkg) return [];\n return [\n { type: 'install', description: `Install missing package ${pkg}`, command: `npm install ${pkg}` },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class BrokenImportRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'broken_import' && this.config.enabledCategories.includes('broken_import');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const actions: RepairAction[] = [];\n if (issue.packageName) {\n actions.push({ type: 'reinstall', description: `Reinstall ${issue.packageName} to fix broken import`, command: `npm install ${issue.packageName}@latest` });\n }\n if (issue.importPath) {\n actions.push({ type: 'fix_import', description: `Clear node_modules cache for ${issue.importPath}` });\n }\n return actions;\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class VersionMismatchRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'version_mismatch' && this.config.enabledCategories.includes('version_mismatch');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const pkg = issue.packageName;\n const ver = issue.requiredVersion;\n if (!pkg) return [];\n const target = ver ? `${pkg}@${ver}` : `${pkg}@latest`;\n return [\n { type: 'update', description: `Update ${pkg} to ${ver || 'latest'}`, command: `npm install ${target}` },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class OrphanModuleRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'orphan_module' && this.config.enabledCategories.includes('orphan_module');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const pkg = issue.packageName;\n if (!pkg) return [];\n return [\n { type: 'remove', description: `Remove orphan package ${pkg}`, command: `npm uninstall ${pkg}` },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class ConfigErrorRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'config_error' && this.config.enabledCategories.includes('config_error');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n return [\n { type: 'fix_config', description: `Regenerate package-lock.json and node_modules`, command: 'npm ci' },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 180000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class BuildFailureRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'build_failure' && this.config.enabledCategories.includes('build_failure');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n return [\n { type: 'fix_config', description: 'Clean install dependencies', command: 'rm -rf node_modules && npm install' },\n { type: 'restart', description: 'Clear Next.js build cache', command: 'rm -rf .next' },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 300000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/auto-heal/repair-strategies.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport type {\n DependencyIssue,\n RepairAction,\n RepairResult,\n AutoHealConfig} from './types.js';\nimport {\n DEFAULT_AUTO_HEAL_CONFIG,\n} from './types.js';\n\nexport class MissingPackageRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'missing_package' && this.config.enabledCategories.includes('missing_package');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const pkg = issue.packageName;\n if (!pkg) return [];\n return [\n { type: 'install', description: `Install missing package ${pkg}`, command: `npm install ${pkg}` },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class BrokenImportRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'broken_import' && this.config.enabledCategories.includes('broken_import');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const actions: RepairAction[] = [];\n if (issue.packageName) {\n actions.push({ type: 'reinstall', description: `Reinstall ${issue.packageName} to fix broken import`, command: `npm install ${issue.packageName}@latest` });\n }\n if (issue.importPath) {\n actions.push({ type: 'fix_import', description: `Clear node_modules cache for ${issue.importPath}` });\n }\n return actions;\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class VersionMismatchRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'version_mismatch' && this.config.enabledCategories.includes('version_mismatch');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const pkg = issue.packageName;\n const ver = issue.requiredVersion;\n if (!pkg) return [];\n const target = ver ? `${pkg}@${ver}` : `${pkg}@latest`;\n return [\n { type: 'update', description: `Update ${pkg} to ${ver || 'latest'}`, command: `npm install ${target}` },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class OrphanModuleRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'orphan_module' && this.config.enabledCategories.includes('orphan_module');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n const pkg = issue.packageName;\n if (!pkg) return [];\n return [\n { type: 'remove', description: `Remove orphan package ${pkg}`, command: `npm uninstall ${pkg}` },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 120000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class ConfigErrorRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'config_error' && this.config.enabledCategories.includes('config_error');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n return [\n { type: 'fix_config', description: `Regenerate package-lock.json and node_modules`, command: 'npm ci' },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 180000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}\n\nexport class BuildFailureRepair {\n private config: AutoHealConfig;\n\n constructor(config: AutoHealConfig = DEFAULT_AUTO_HEAL_CONFIG) {\n this.config = config;\n }\n\n canHandle(issue: DependencyIssue): boolean {\n return issue.category === 'build_failure' && this.config.enabledCategories.includes('build_failure');\n }\n\n planActions(issue: DependencyIssue): RepairAction[] {\n return [\n { type: 'fix_config', description: 'Clean install dependencies', command: 'rm -rf node_modules && npm install' },\n { type: 'restart', description: 'Clear Next.js build cache', command: 'rm -rf .next' },\n ];\n }\n\n async execute(issue: DependencyIssue): Promise<RepairResult> {\n const startedAt = Date.now();\n const actions = this.planActions(issue);\n let output = '';\n let status: RepairResult['status'] = 'succeeded';\n\n if (this.config.dryRun) {\n return { issueId: issue.id, status: 'skipped', actions, output: 'DRY RUN', attempts: 1, startedAt, completedAt: Date.now() };\n }\n\n for (const action of actions) {\n if (!action.command) continue;\n try {\n output += execSync(action.command, { encoding: 'utf-8', timeout: 300000, stdio: ['pipe', 'pipe', 'pipe'] });\n } catch (err: any) {\n status = 'failed';\n output += err.stdout || '' + (err.stderr || err.message);\n }\n }\n\n return { issueId: issue.id, status, actions, output, attempts: 1, startedAt, completedAt: Date.now() };\n }\n}"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import logger from "../utils/logger.js";
|
|
6
|
+
const COMPONENT = "PromptIncludes";
|
|
7
|
+
const INCLUDES_DIR = join(homedir(), ".titan", "includes");
|
|
8
|
+
function discoverIncludes() {
|
|
9
|
+
if (!existsSync(INCLUDES_DIR)) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const files = [];
|
|
13
|
+
let entries = [];
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(INCLUDES_DIR);
|
|
16
|
+
} catch {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
for (const name of entries) {
|
|
20
|
+
if (!name.endsWith(".include.md")) continue;
|
|
21
|
+
let category = null;
|
|
22
|
+
if (name.endsWith(".system.include.md")) category = "system";
|
|
23
|
+
else if (name.endsWith(".transient.include.md")) category = "transient";
|
|
24
|
+
else if (name.endsWith(".user.include.md")) category = "user";
|
|
25
|
+
if (!category) continue;
|
|
26
|
+
const path = join(INCLUDES_DIR, name);
|
|
27
|
+
try {
|
|
28
|
+
const content = readFileSync(path, "utf-8").trim();
|
|
29
|
+
if (content.length > 0) {
|
|
30
|
+
files.push({ filename: name, category, content });
|
|
31
|
+
}
|
|
32
|
+
} catch (e) {
|
|
33
|
+
logger.warn(COMPONENT, `Failed to read ${path}: ${e.message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
files.sort((a, b) => a.filename.localeCompare(b.filename));
|
|
37
|
+
return files;
|
|
38
|
+
}
|
|
39
|
+
function buildBlock(include) {
|
|
40
|
+
return `<!-- include: ${include.filename} -->
|
|
41
|
+
${include.content}`;
|
|
42
|
+
}
|
|
43
|
+
function buildPromptIncludes(category) {
|
|
44
|
+
const includes = discoverIncludes().filter((i) => i.category === category);
|
|
45
|
+
if (includes.length === 0) return "";
|
|
46
|
+
const blocks = includes.map(buildBlock);
|
|
47
|
+
return blocks.join("\n\n");
|
|
48
|
+
}
|
|
49
|
+
function getIncludeSummary() {
|
|
50
|
+
const includes = discoverIncludes();
|
|
51
|
+
if (includes.length === 0) return "";
|
|
52
|
+
return includes.map((i) => `- ${i.filename} (${i.category})`).join("\n");
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
buildPromptIncludes,
|
|
56
|
+
getIncludeSummary
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=promptIncludes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/memory/promptIncludes.ts"],"sourcesContent":["/**\n * TITAN — Prompt-Include Memory System\n *\n * Auto-discovers and injects markdown files from ~/.titan/includes/\n * Inspired by space-agent's prompt-include pattern.\n *\n * File naming convention:\n * *.system.include.md → injected into system prompt (permanent memory, high primacy)\n * *.transient.include.md → injected into context appendix (temporary, trimmed first)\n * *.user.include.md → user facts injected after identity block\n */\n\nimport { existsSync, readdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'PromptIncludes';\nconst INCLUDES_DIR = join(homedir(), '.titan', 'includes');\n\nexport type IncludeCategory = 'system' | 'transient' | 'user';\n\nexport interface PromptInclude {\n filename: string;\n category: IncludeCategory;\n content: string;\n}\n\nfunction discoverIncludes(): PromptInclude[] {\n if (!existsSync(INCLUDES_DIR)) {\n return [];\n }\n\n const files: PromptInclude[] = [];\n let entries: string[] = [];\n try {\n entries = readdirSync(INCLUDES_DIR);\n } catch {\n return [];\n }\n\n for (const name of entries) {\n if (!name.endsWith('.include.md')) continue;\n\n let category: IncludeCategory | null = null;\n if (name.endsWith('.system.include.md')) category = 'system';\n else if (name.endsWith('.transient.include.md')) category = 'transient';\n else if (name.endsWith('.user.include.md')) category = 'user';\n\n if (!category) continue;\n\n const path = join(INCLUDES_DIR, name);\n try {\n const content = readFileSync(path, 'utf-8').trim();\n if (content.length > 0) {\n files.push({ filename: name, category, content });\n }\n } catch (e) {\n logger.warn(COMPONENT, `Failed to read ${path}: ${(e as Error).message}`);\n }\n }\n\n // Sort by filename for deterministic ordering\n files.sort((a, b) => a.filename.localeCompare(b.filename));\n return files;\n}\n\nfunction buildBlock(include: PromptInclude): string {\n return `<!-- include: ${include.filename} -->\\n${include.content}`;\n}\n\nexport function buildPromptIncludes(category: IncludeCategory): string {\n const includes = discoverIncludes().filter(i => i.category === category);\n if (includes.length === 0) return '';\n\n const blocks = includes.map(buildBlock);\n return blocks.join('\\n\\n');\n}\n\nexport function getIncludeSummary(): string {\n const includes = discoverIncludes();\n if (includes.length === 0) return '';\n return includes.map(i => `- ${i.filename} (${i.category})`).join('\\n');\n}\n"],"mappings":";AAYA,SAAS,YAAY,aAAa,oBAAoB;AACtD,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,OAAO,YAAY;AAEnB,MAAM,YAAY;AAClB,MAAM,eAAe,KAAK,QAAQ,GAAG,UAAU,UAAU;AAUzD,SAAS,mBAAoC;AAC3C,MAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,QAAyB,CAAC;AAChC,MAAI,UAAoB,CAAC;AACzB,MAAI;AACF,cAAU,YAAY,YAAY;AAAA,EACpC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,aAAW,QAAQ,SAAS;AAC1B,QAAI,CAAC,KAAK,SAAS,aAAa,EAAG;AAEnC,QAAI,WAAmC;AACvC,QAAI,KAAK,SAAS,oBAAoB,EAAG,YAAW;AAAA,aAC3C,KAAK,SAAS,uBAAuB,EAAG,YAAW;AAAA,aACnD,KAAK,SAAS,kBAAkB,EAAG,YAAW;AAEvD,QAAI,CAAC,SAAU;AAEf,UAAM,OAAO,KAAK,cAAc,IAAI;AACpC,QAAI;AACF,YAAM,UAAU,aAAa,MAAM,OAAO,EAAE,KAAK;AACjD,UAAI,QAAQ,SAAS,GAAG;AACtB,cAAM,KAAK,EAAE,UAAU,MAAM,UAAU,QAAQ,CAAC;AAAA,MAClD;AAAA,IACF,SAAS,GAAG;AACV,aAAO,KAAK,WAAW,kBAAkB,IAAI,KAAM,EAAY,OAAO,EAAE;AAAA,IAC1E;AAAA,EACF;AAGA,QAAM,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,cAAc,EAAE,QAAQ,CAAC;AACzD,SAAO;AACT;AAEA,SAAS,WAAW,SAAgC;AAClD,SAAO,iBAAiB,QAAQ,QAAQ;AAAA,EAAS,QAAQ,OAAO;AAClE;AAEO,SAAS,oBAAoB,UAAmC;AACrE,QAAM,WAAW,iBAAiB,EAAE,OAAO,OAAK,EAAE,aAAa,QAAQ;AACvE,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,QAAM,SAAS,SAAS,IAAI,UAAU;AACtC,SAAO,OAAO,KAAK,MAAM;AAC3B;AAEO,SAAS,oBAA4B;AAC1C,QAAM,WAAW,iBAAiB;AAClC,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,SAAO,SAAS,IAAI,OAAK,KAAK,EAAE,QAAQ,KAAK,EAAE,QAAQ,GAAG,EAAE,KAAK,IAAI;AACvE;","names":[]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
const ALERTS_PATH = join(homedir(), ".titan", "organism-alerts.json");
|
|
6
|
+
function readAlerts() {
|
|
7
|
+
if (!existsSync(ALERTS_PATH)) return [];
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(readFileSync(ALERTS_PATH, "utf-8"));
|
|
10
|
+
} catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function writeAlerts(alerts) {
|
|
15
|
+
try {
|
|
16
|
+
writeFileSync(ALERTS_PATH, JSON.stringify(alerts, null, 2));
|
|
17
|
+
} catch {
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function getAlerts() {
|
|
21
|
+
return readAlerts();
|
|
22
|
+
}
|
|
23
|
+
function getAlertStats() {
|
|
24
|
+
const alerts = readAlerts();
|
|
25
|
+
const acked = alerts.filter((a) => a.acknowledged).length;
|
|
26
|
+
return { total: alerts.length, acked, unacked: alerts.length - acked };
|
|
27
|
+
}
|
|
28
|
+
function acknowledgeAlert(id) {
|
|
29
|
+
const alerts = readAlerts();
|
|
30
|
+
const alert = alerts.find((a) => a.id === id);
|
|
31
|
+
if (!alert) return false;
|
|
32
|
+
alert.acknowledged = true;
|
|
33
|
+
writeAlerts(alerts);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
function addAlert(alert) {
|
|
37
|
+
const alerts = readAlerts();
|
|
38
|
+
const newAlert = {
|
|
39
|
+
...alert,
|
|
40
|
+
id: `alert-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
41
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
42
|
+
acknowledged: false
|
|
43
|
+
};
|
|
44
|
+
alerts.push(newAlert);
|
|
45
|
+
writeAlerts(alerts);
|
|
46
|
+
return newAlert;
|
|
47
|
+
}
|
|
48
|
+
function deleteOldAlerts(maxAgeDays = 30) {
|
|
49
|
+
const alerts = readAlerts();
|
|
50
|
+
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
|
|
51
|
+
const kept = alerts.filter((a) => new Date(a.timestamp).getTime() > cutoff);
|
|
52
|
+
const removed = alerts.length - kept.length;
|
|
53
|
+
writeAlerts(kept);
|
|
54
|
+
return removed;
|
|
55
|
+
}
|
|
56
|
+
function getAlertConfig() {
|
|
57
|
+
return { enabled: true, maxAgeDays: 30, channels: ["ui", "log"] };
|
|
58
|
+
}
|
|
59
|
+
function setAlertConfig(_config) {
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
acknowledgeAlert,
|
|
63
|
+
addAlert,
|
|
64
|
+
deleteOldAlerts,
|
|
65
|
+
getAlertConfig,
|
|
66
|
+
getAlertStats,
|
|
67
|
+
getAlerts,
|
|
68
|
+
setAlertConfig
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=alertsStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/organism/alertsStore.ts"],"sourcesContent":["/**\n * TITAN — Organism Alert Store\n * Simple file-backed alert storage for the organism subsystem.\n */\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nconst ALERTS_PATH = join(homedir(), '.titan', 'organism-alerts.json');\n\nexport interface OrganismAlert {\n id: string;\n severity: 'info' | 'warning' | 'critical';\n title: string;\n message: string;\n source: string;\n timestamp: string;\n acknowledged: boolean;\n data?: Record<string, unknown>;\n}\n\nfunction readAlerts(): OrganismAlert[] {\n if (!existsSync(ALERTS_PATH)) return [];\n try {\n return JSON.parse(readFileSync(ALERTS_PATH, 'utf-8')) as OrganismAlert[];\n } catch { return []; }\n}\n\nfunction writeAlerts(alerts: OrganismAlert[]): void {\n try {\n writeFileSync(ALERTS_PATH, JSON.stringify(alerts, null, 2));\n } catch { /* ignore */ }\n}\n\nexport function getAlerts(): OrganismAlert[] {\n return readAlerts();\n}\n\nexport function getAlertStats(): { total: number; acked: number; unacked: number } {\n const alerts = readAlerts();\n const acked = alerts.filter(a => a.acknowledged).length;\n return { total: alerts.length, acked, unacked: alerts.length - acked };\n}\n\nexport function acknowledgeAlert(id: string): boolean {\n const alerts = readAlerts();\n const alert = alerts.find(a => a.id === id);\n if (!alert) return false;\n alert.acknowledged = true;\n writeAlerts(alerts);\n return true;\n}\n\nexport function addAlert(alert: Omit<OrganismAlert, 'id' | 'timestamp' | 'acknowledged'>): OrganismAlert {\n const alerts = readAlerts();\n const newAlert: OrganismAlert = {\n ...alert,\n id: `alert-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n timestamp: new Date().toISOString(),\n acknowledged: false,\n };\n alerts.push(newAlert);\n writeAlerts(alerts);\n return newAlert;\n}\n\nexport function deleteOldAlerts(maxAgeDays = 30): number {\n const alerts = readAlerts();\n const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;\n const kept = alerts.filter(a => new Date(a.timestamp).getTime() > cutoff);\n const removed = alerts.length - kept.length;\n writeAlerts(kept);\n return removed;\n}\n\nexport function getAlertConfig(): Record<string, unknown> {\n return { enabled: true, maxAgeDays: 30, channels: ['ui', 'log'] };\n}\n\nexport function setAlertConfig(_config: Record<string, unknown>): void {\n // Stub — persist to file if needed later\n}\n"],"mappings":";AAIA,SAAS,cAAc,eAAe,kBAAkB;AACxD,SAAS,YAAY;AACrB,SAAS,eAAe;AAExB,MAAM,cAAc,KAAK,QAAQ,GAAG,UAAU,sBAAsB;AAapE,SAAS,aAA8B;AACrC,MAAI,CAAC,WAAW,WAAW,EAAG,QAAO,CAAC;AACtC,MAAI;AACF,WAAO,KAAK,MAAM,aAAa,aAAa,OAAO,CAAC;AAAA,EACtD,QAAQ;AAAE,WAAO,CAAC;AAAA,EAAG;AACvB;AAEA,SAAS,YAAY,QAA+B;AAClD,MAAI;AACF,kBAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC5D,QAAQ;AAAA,EAAe;AACzB;AAEO,SAAS,YAA6B;AAC3C,SAAO,WAAW;AACpB;AAEO,SAAS,gBAAmE;AACjF,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,OAAO,OAAK,EAAE,YAAY,EAAE;AACjD,SAAO,EAAE,OAAO,OAAO,QAAQ,OAAO,SAAS,OAAO,SAAS,MAAM;AACvE;AAEO,SAAS,iBAAiB,IAAqB;AACpD,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,OAAK,EAAE,OAAO,EAAE;AAC1C,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,eAAe;AACrB,cAAY,MAAM;AAClB,SAAO;AACT;AAEO,SAAS,SAAS,OAAgF;AACvG,QAAM,SAAS,WAAW;AAC1B,QAAM,WAA0B;AAAA,IAC9B,GAAG;AAAA,IACH,IAAI,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,IACjE,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,cAAc;AAAA,EAChB;AACA,SAAO,KAAK,QAAQ;AACpB,cAAY,MAAM;AAClB,SAAO;AACT;AAEO,SAAS,gBAAgB,aAAa,IAAY;AACvD,QAAM,SAAS,WAAW;AAC1B,QAAM,SAAS,KAAK,IAAI,IAAI,aAAa,KAAK,KAAK,KAAK;AACxD,QAAM,OAAO,OAAO,OAAO,OAAK,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,MAAM;AACxE,QAAM,UAAU,OAAO,SAAS,KAAK;AACrC,cAAY,IAAI;AAChB,SAAO;AACT;AAEO,SAAS,iBAA0C;AACxD,SAAO,EAAE,SAAS,MAAM,YAAY,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE;AAClE;AAEO,SAAS,eAAe,SAAwC;AAEvE;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/memoryRetrieval.ts"],"sourcesContent":["/**\n * TITAN — Memory Retrieval Plugin (v4.13+)\n *\n * On every user turn, semantically searches TITAN's full memory (graph,\n * episodic, memory_skill) for content relevant to the user's message and\n * injects the top hits as a system message. Without this, only pre-\n * ingested RAG documents were being searched — the 500 graph entries,\n * the episodic log, and the memory-tool entries were all invisible to\n * the agent during normal chat.\n *\n * Sources searched (besides the existing rag-documents path which is\n * handled by injectRagContext):\n * - graph — knowledge graph entities + relationships\n * - episodic — past events / corrections / learnings\n * - memory — explicit memory-tool entries\n *\n * Injection shape: one system message titled 'Relevant memories' with up\n * to N bullet points, each `[source/score] text`. Injected right before\n * the user message so the LLM sees it as immediate context.\n */\nimport type { ContextEnginePlugin } from './contextEngine.js';\nimport type { ChatMessage } from '../providers/base.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'MemoryRetrieval';\n\n// Tunables — override via bootstrap opts\nconst DEFAULT_TOP_K_PER_SOURCE = 3;\nconst DEFAULT_MIN_SCORE = 0.45;\nconst DEFAULT_MAX_HITS = 8;\nconst DEFAULT_MAX_TEXT_LEN = 400;\nconst SEARCH_SOURCES = ['graph', 'episodic', 'memory'] as const;\n\nexport class MemoryRetrievalPlugin implements ContextEnginePlugin {\n readonly name = 'memoryRetrieval';\n readonly version = '1.0.0';\n\n private topKPerSource = DEFAULT_TOP_K_PER_SOURCE;\n private minScore = DEFAULT_MIN_SCORE;\n private maxHits = DEFAULT_MAX_HITS;\n private maxTextLen = DEFAULT_MAX_TEXT_LEN;\n\n async bootstrap(config: Record<string, unknown>): Promise<void> {\n if (typeof config.topKPerSource === 'number') this.topKPerSource = config.topKPerSource;\n if (typeof config.minScore === 'number') this.minScore = config.minScore;\n if (typeof config.maxHits === 'number') this.maxHits = config.maxHits;\n if (typeof config.maxTextLen === 'number') this.maxTextLen = config.maxTextLen;\n logger.info(COMPONENT, `Bootstrapped: topKPerSource=${this.topKPerSource}, minScore=${this.minScore}, maxHits=${this.maxHits}`);\n }\n\n async assemble(context: ChatMessage[], userMessage: string): Promise<ChatMessage[]> {\n logger.info(COMPONENT, `assemble called for query: \"${(userMessage||'').slice(0,80)}\"`);\n const query = (userMessage || '').trim();\n if (!query || query.length < 6) return context;\n\n try {\n const { searchVectors, isVectorSearchAvailable } = await import('../memory/vectors.js');\n if (!isVectorSearchAvailable()) {\n logger.info(COMPONENT, 'vector search unavailable — skipping');\n return context;\n }\n logger.info(COMPONENT, `searching ${SEARCH_SOURCES.length} sources for query (minScore=${this.minScore}, topK=${this.topKPerSource})`);\n\n // Fan out across sources in parallel\n const perSource = await Promise.all(\n SEARCH_SOURCES.map(async (src) => {\n try {\n const hits = await searchVectors(query, this.topKPerSource, src, this.minScore);\n return hits.map(h => ({ ...h, source: src }));\n } catch (e) {\n logger.debug(COMPONENT, `source ${src} search failed: ${(e as Error).message}`);\n return [];\n }\n }),\n );\n\n // Merge, sort by score, cap\n const merged = perSource.flat().sort((a, b) => b.score - a.score).slice(0, this.maxHits);\n logger.info(COMPONENT, `search produced ${merged.length} merged hits (perSource: ${perSource.map(p=>p.length).join(\",\")})`);\n if (merged.length === 0) return context;\n\n const lines = merged.map(h => {\n const text = (h.text || '').slice(0, this.maxTextLen);\n return `- [${h.source} / ${h.score.toFixed(2)}] ${text}`;\n });\n const injected: ChatMessage = {\n role: 'system',\n content: `[Relevant memories — top ${merged.length} from semantic search]\\n${lines.join('\\n')}`,\n };\n\n // Insert right before the last user message\n const result = [...context];\n let lastUserIdx = -1;\n for (let i = result.length - 1; i >= 0; i--) {\n if (result[i].role === 'user') { lastUserIdx = i; break; }\n }\n if (lastUserIdx >= 0) {\n result.splice(lastUserIdx, 0, injected);\n } else {\n result.push(injected);\n }\n logger.info(COMPONENT, `[HIT] Injected ${merged.length} hit(s) for query:
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/memoryRetrieval.ts"],"sourcesContent":["/**\n * TITAN — Memory Retrieval Plugin (v4.13+)\n *\n * On every user turn, semantically searches TITAN's full memory (graph,\n * episodic, memory_skill) for content relevant to the user's message and\n * injects the top hits as a system message. Without this, only pre-\n * ingested RAG documents were being searched — the 500 graph entries,\n * the episodic log, and the memory-tool entries were all invisible to\n * the agent during normal chat.\n *\n * Sources searched (besides the existing rag-documents path which is\n * handled by injectRagContext):\n * - graph — knowledge graph entities + relationships\n * - episodic — past events / corrections / learnings\n * - memory — explicit memory-tool entries\n *\n * Injection shape: one system message titled 'Relevant memories' with up\n * to N bullet points, each `[source/score] text`. Injected right before\n * the user message so the LLM sees it as immediate context.\n */\nimport type { ContextEnginePlugin } from './contextEngine.js';\nimport type { ChatMessage } from '../providers/base.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'MemoryRetrieval';\n\n// Tunables — override via bootstrap opts\nconst DEFAULT_TOP_K_PER_SOURCE = 3;\nconst DEFAULT_MIN_SCORE = 0.45;\nconst DEFAULT_MAX_HITS = 8;\nconst DEFAULT_MAX_TEXT_LEN = 400;\nconst SEARCH_SOURCES = ['graph', 'episodic', 'memory'] as const;\n\nexport class MemoryRetrievalPlugin implements ContextEnginePlugin {\n readonly name = 'memoryRetrieval';\n readonly version = '1.0.0';\n\n private topKPerSource = DEFAULT_TOP_K_PER_SOURCE;\n private minScore = DEFAULT_MIN_SCORE;\n private maxHits = DEFAULT_MAX_HITS;\n private maxTextLen = DEFAULT_MAX_TEXT_LEN;\n\n async bootstrap(config: Record<string, unknown>): Promise<void> {\n if (typeof config.topKPerSource === 'number') this.topKPerSource = config.topKPerSource;\n if (typeof config.minScore === 'number') this.minScore = config.minScore;\n if (typeof config.maxHits === 'number') this.maxHits = config.maxHits;\n if (typeof config.maxTextLen === 'number') this.maxTextLen = config.maxTextLen;\n logger.info(COMPONENT, `Bootstrapped: topKPerSource=${this.topKPerSource}, minScore=${this.minScore}, maxHits=${this.maxHits}`);\n }\n\n async assemble(context: ChatMessage[], userMessage: string): Promise<ChatMessage[]> {\n logger.info(COMPONENT, `assemble called for query: \"${(userMessage||'').slice(0,80)}\"`);\n const query = (userMessage || '').trim();\n if (!query || query.length < 6) return context;\n\n try {\n const { searchVectors, isVectorSearchAvailable } = await import('../memory/vectors.js');\n if (!isVectorSearchAvailable()) {\n logger.info(COMPONENT, 'vector search unavailable — skipping');\n return context;\n }\n logger.info(COMPONENT, `searching ${SEARCH_SOURCES.length} sources for query (minScore=${this.minScore}, topK=${this.topKPerSource})`);\n\n // Fan out across sources in parallel\n const perSource = await Promise.all(\n SEARCH_SOURCES.map(async (src) => {\n try {\n const hits = await searchVectors(query, this.topKPerSource, src, this.minScore);\n return hits.map(h => ({ ...h, source: src }));\n } catch (e) {\n logger.debug(COMPONENT, `source ${src} search failed: ${(e as Error).message}`);\n return [];\n }\n }),\n );\n\n // Merge, sort by score, cap\n const merged = perSource.flat().sort((a, b) => b.score - a.score).slice(0, this.maxHits);\n logger.info(COMPONENT, `search produced ${merged.length} merged hits (perSource: ${perSource.map(p=>p.length).join(\",\")})`);\n if (merged.length === 0) return context;\n\n const lines = merged.map(h => {\n const text = (h.text || '').slice(0, this.maxTextLen);\n return `- [${h.source} / ${h.score.toFixed(2)}] ${text}`;\n });\n const injected: ChatMessage = {\n role: 'system',\n content: `[Relevant memories — top ${merged.length} from semantic search]\\n${lines.join('\\n')}`,\n };\n\n // Insert right before the last user message\n const result = [...context];\n let lastUserIdx = -1;\n for (let i = result.length - 1; i >= 0; i--) {\n if (result[i].role === 'user') { lastUserIdx = i; break; }\n }\n if (lastUserIdx >= 0) {\n result.splice(lastUserIdx, 0, injected);\n } else {\n result.push(injected);\n }\n logger.info(COMPONENT, `[HIT] Injected ${merged.length} hit(s) for query: \"${query.slice(0, 60)}\"`);\n return result;\n } catch (e) {\n logger.warn(COMPONENT, `assemble failed: ${(e as Error).message}`);\n return context;\n }\n }\n}\n\n/** Factory — keeps the registration pattern consistent with topFacts. */\nexport function createMemoryRetrievalPlugin(): ContextEnginePlugin {\n return new MemoryRetrievalPlugin();\n}\n"],"mappings":"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","names":[]}
|
package/dist/providers/ollama.js
CHANGED
|
@@ -352,10 +352,10 @@ class OllamaProvider extends LLMProvider {
|
|
|
352
352
|
const caps = getModelCapabilities(model);
|
|
353
353
|
if (options.thinking === false) {
|
|
354
354
|
body.think = false;
|
|
355
|
+
} else if (!caps.thinkingWithTools) {
|
|
356
|
+
body.think = false;
|
|
355
357
|
} else if (options.thinking === true) {
|
|
356
358
|
body.think = true;
|
|
357
|
-
} else if (isCloudModel && !caps.thinkingWithTools) {
|
|
358
|
-
body.think = false;
|
|
359
359
|
}
|
|
360
360
|
if (hasToolRoleMessages && body.think !== false) {
|
|
361
361
|
const priorIntent = body.think === void 0 ? "unset" : String(body.think);
|
|
@@ -426,7 +426,7 @@ ${msgs[firstUserIdx].content}`;
|
|
|
426
426
|
}, { timeoutMs });
|
|
427
427
|
if (!response.ok) {
|
|
428
428
|
const errorText = await response.text();
|
|
429
|
-
if (response.status === 400 && errorText.includes("does not support tools")
|
|
429
|
+
if (response.status === 400 && body.tools && (errorText.includes("does not support tools") || errorText.includes("tokenization") || errorText.includes("tokenize") || errorText.includes("Invalid JSON"))) {
|
|
430
430
|
logger.warn(COMPONENT, `Model ${model} does not support native tool calling \u2014 running in chat-only mode`);
|
|
431
431
|
delete body.tools;
|
|
432
432
|
response = await fetchWithRetry(`${this.baseUrl}/api/chat`, {
|
|
@@ -453,7 +453,7 @@ ${msgs[firstUserIdx].content}`;
|
|
|
453
453
|
const message = data.message;
|
|
454
454
|
logger.info(COMPONENT, `Response from ${model}: tool_calls=${JSON.stringify(message.tool_calls)}, content_length=${(message.content || "").length}`);
|
|
455
455
|
const toolCalls = [];
|
|
456
|
-
if (message.tool_calls) {
|
|
456
|
+
if (message.tool_calls && options.tools && options.tools.length > 0) {
|
|
457
457
|
for (const tc of message.tool_calls) {
|
|
458
458
|
const fn = tc.function;
|
|
459
459
|
const thoughtSig = tc.thought_signature ?? tc.thoughtSignature ?? fn.thought_signature ?? fn.thoughtSignature;
|
|
@@ -539,10 +539,10 @@ ${msgs[firstUserIdx].content}`;
|
|
|
539
539
|
const caps = getModelCapabilities(model);
|
|
540
540
|
if (options.thinking === false) {
|
|
541
541
|
body.think = false;
|
|
542
|
+
} else if (!caps.thinkingWithTools) {
|
|
543
|
+
body.think = false;
|
|
542
544
|
} else if (options.thinking === true) {
|
|
543
545
|
body.think = true;
|
|
544
|
-
} else if (isCloudModel && !caps.thinkingWithTools) {
|
|
545
|
-
body.think = false;
|
|
546
546
|
}
|
|
547
547
|
if (hasToolRoleMessages && body.think !== false) {
|
|
548
548
|
const priorIntent = body.think === void 0 ? "unset" : String(body.think);
|
|
@@ -651,7 +651,7 @@ ${msgs2[firstUserIdx].content}`;
|
|
|
651
651
|
}
|
|
652
652
|
if (text) yield { type: "text", content: text };
|
|
653
653
|
}
|
|
654
|
-
if (chunk.message?.tool_calls) {
|
|
654
|
+
if (chunk.message?.tool_calls && options.tools && options.tools.length > 0) {
|
|
655
655
|
for (const tc of chunk.message.tool_calls) {
|
|
656
656
|
const fn = tc.function;
|
|
657
657
|
yield {
|