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/gateway/server.js
CHANGED
|
@@ -1596,14 +1596,14 @@ ${msg.content}
|
|
|
1596
1596
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1597
1597
|
}
|
|
1598
1598
|
});
|
|
1599
|
-
app.post("/api/sessions/:id/steer", (req, res) => {
|
|
1599
|
+
app.post("/api/sessions/:id/steer", async (req, res) => {
|
|
1600
1600
|
try {
|
|
1601
1601
|
const { message } = req.body;
|
|
1602
1602
|
if (!message || typeof message !== "string") {
|
|
1603
1603
|
res.status(400).json({ error: "message is required" });
|
|
1604
1604
|
return;
|
|
1605
1605
|
}
|
|
1606
|
-
const { pushSteer } =
|
|
1606
|
+
const { pushSteer } = await import("../agent/agentLoop.js");
|
|
1607
1607
|
pushSteer(req.params.id, message);
|
|
1608
1608
|
res.json({ ok: true, sessionId: req.params.id });
|
|
1609
1609
|
} catch (e) {
|
|
@@ -1611,9 +1611,9 @@ ${msg.content}
|
|
|
1611
1611
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1612
1612
|
}
|
|
1613
1613
|
});
|
|
1614
|
-
app.get("/api/sessions/:id/checkpoints", (req, res) => {
|
|
1614
|
+
app.get("/api/sessions/:id/checkpoints", async (req, res) => {
|
|
1615
1615
|
try {
|
|
1616
|
-
const { listCheckpoints } =
|
|
1616
|
+
const { listCheckpoints } = await import("../checkpoint/manager.js");
|
|
1617
1617
|
const checkpoints = listCheckpoints(req.params.id);
|
|
1618
1618
|
res.json({ checkpoints });
|
|
1619
1619
|
} catch (e) {
|
|
@@ -1621,9 +1621,9 @@ ${msg.content}
|
|
|
1621
1621
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1622
1622
|
}
|
|
1623
1623
|
});
|
|
1624
|
-
app.post("/api/sessions/:id/checkpoints/:checkpointId/restore", (req, res) => {
|
|
1624
|
+
app.post("/api/sessions/:id/checkpoints/:checkpointId/restore", async (req, res) => {
|
|
1625
1625
|
try {
|
|
1626
|
-
const { restoreCheckpoint } =
|
|
1626
|
+
const { restoreCheckpoint } = await import("../checkpoint/manager.js");
|
|
1627
1627
|
const result = restoreCheckpoint(req.params.id, req.params.checkpointId);
|
|
1628
1628
|
res.json({ ok: result.success, restored: result.restored, errors: result.errors });
|
|
1629
1629
|
} catch (e) {
|
|
@@ -1631,9 +1631,9 @@ ${msg.content}
|
|
|
1631
1631
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1632
1632
|
}
|
|
1633
1633
|
});
|
|
1634
|
-
app.post("/api/guest", (_req, res) => {
|
|
1634
|
+
app.post("/api/guest", async (_req, res) => {
|
|
1635
1635
|
try {
|
|
1636
|
-
const { createGuestSession } =
|
|
1636
|
+
const { createGuestSession } = await import("../agent/session.js");
|
|
1637
1637
|
const session = createGuestSession();
|
|
1638
1638
|
res.json({ id: session.id, userId: session.userId, createdAt: session.createdAt });
|
|
1639
1639
|
} catch (e) {
|
|
@@ -1641,11 +1641,11 @@ ${msg.content}
|
|
|
1641
1641
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1642
1642
|
}
|
|
1643
1643
|
});
|
|
1644
|
-
app.get("/api/sessions/:id/history", (req, res) => {
|
|
1644
|
+
app.get("/api/sessions/:id/history", async (req, res) => {
|
|
1645
1645
|
try {
|
|
1646
|
-
const { listCheckpoints } =
|
|
1646
|
+
const { listCheckpoints } = await import("../checkpoint/manager.js");
|
|
1647
1647
|
const checkpoints = listCheckpoints(req.params.id);
|
|
1648
|
-
const { getHistory: getHistory2 } =
|
|
1648
|
+
const { getHistory: getHistory2 } = await import("../memory/memory.js");
|
|
1649
1649
|
const messages = getHistory2(req.params.id, 100);
|
|
1650
1650
|
res.json({ checkpoints, messages, sessionId: req.params.id });
|
|
1651
1651
|
} catch (e) {
|
|
@@ -1653,9 +1653,9 @@ ${msg.content}
|
|
|
1653
1653
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1654
1654
|
}
|
|
1655
1655
|
});
|
|
1656
|
-
app.get("/api/prompt-includes", (_req, res) => {
|
|
1656
|
+
app.get("/api/prompt-includes", async (_req, res) => {
|
|
1657
1657
|
try {
|
|
1658
|
-
const { discoverPromptIncludes } =
|
|
1658
|
+
const { discoverPromptIncludes } = await import("../promptincludes/discover.js");
|
|
1659
1659
|
const includes = discoverPromptIncludes();
|
|
1660
1660
|
res.json({ includes });
|
|
1661
1661
|
} catch (e) {
|
|
@@ -1771,9 +1771,9 @@ ${msg.content}
|
|
|
1771
1771
|
return;
|
|
1772
1772
|
}
|
|
1773
1773
|
const shareId = `${req.params.id}-${Date.now().toString(36)}`;
|
|
1774
|
-
const sharePath = `${
|
|
1775
|
-
|
|
1776
|
-
|
|
1774
|
+
const sharePath = `${homedir()}/.titan/shares/${shareId}.json`;
|
|
1775
|
+
fs.mkdirSync(dirname(sharePath), { recursive: true });
|
|
1776
|
+
fs.writeFileSync(sharePath, JSON.stringify({ sessionId: req.params.id, format, history, createdAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
1777
1777
|
res.json({ ok: true, shareId, url: `/api/shares/${shareId}` });
|
|
1778
1778
|
} catch (e) {
|
|
1779
1779
|
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
@@ -1782,12 +1782,12 @@ ${msg.content}
|
|
|
1782
1782
|
});
|
|
1783
1783
|
app.get("/api/shares/:shareId", async (req, res) => {
|
|
1784
1784
|
try {
|
|
1785
|
-
const sharePath = `${
|
|
1786
|
-
if (!
|
|
1785
|
+
const sharePath = `${homedir()}/.titan/shares/${req.params.shareId}.json`;
|
|
1786
|
+
if (!fs.existsSync(sharePath)) {
|
|
1787
1787
|
res.status(404).json({ error: "Share not found" });
|
|
1788
1788
|
return;
|
|
1789
1789
|
}
|
|
1790
|
-
const data = JSON.parse(
|
|
1790
|
+
const data = JSON.parse(fs.readFileSync(sharePath, "utf-8"));
|
|
1791
1791
|
res.json(data);
|
|
1792
1792
|
} catch (e) {
|
|
1793
1793
|
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
@@ -1936,6 +1936,17 @@ ${msg.content}
|
|
|
1936
1936
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1937
1937
|
}
|
|
1938
1938
|
});
|
|
1939
|
+
app.get("/api/widget-gallery", async (_req, res) => {
|
|
1940
|
+
try {
|
|
1941
|
+
const { listTemplates, listCategories } = await import("../skills/builtin/widget_gallery.js");
|
|
1942
|
+
const templates = listTemplates();
|
|
1943
|
+
const categories = listCategories();
|
|
1944
|
+
res.json({ count: templates.length, categories, templates });
|
|
1945
|
+
} catch (e) {
|
|
1946
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
1947
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
1948
|
+
}
|
|
1949
|
+
});
|
|
1939
1950
|
app.get("/api/tools", (req, res) => {
|
|
1940
1951
|
const includeSchema = req.query.include === "schema";
|
|
1941
1952
|
const q = typeof req.query.q === "string" ? req.query.q.toLowerCase() : "";
|
|
@@ -2194,22 +2205,135 @@ ${msg.content}
|
|
|
2194
2205
|
res.status(501).json({ error: "Not implemented" });
|
|
2195
2206
|
});
|
|
2196
2207
|
app.get("/api/organism/alerts", async (_req, res) => {
|
|
2197
|
-
|
|
2208
|
+
try {
|
|
2209
|
+
const { getAlerts } = await import("../organism/alertsStore.js");
|
|
2210
|
+
res.json({ alerts: getAlerts() });
|
|
2211
|
+
} catch (e) {
|
|
2212
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2213
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
2214
|
+
}
|
|
2198
2215
|
});
|
|
2199
2216
|
app.get("/api/organism/alerts/stats", async (_req, res) => {
|
|
2200
|
-
|
|
2217
|
+
try {
|
|
2218
|
+
const { getAlertStats } = await import("../organism/alertsStore.js");
|
|
2219
|
+
res.json(getAlertStats());
|
|
2220
|
+
} catch (e) {
|
|
2221
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2222
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
2223
|
+
}
|
|
2201
2224
|
});
|
|
2202
2225
|
app.get("/api/organism/alerts/config", async (_req, res) => {
|
|
2203
|
-
|
|
2226
|
+
try {
|
|
2227
|
+
const { getAlertConfig } = await import("../organism/alertsStore.js");
|
|
2228
|
+
res.json(getAlertConfig());
|
|
2229
|
+
} catch (e) {
|
|
2230
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2231
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
2232
|
+
}
|
|
2204
2233
|
});
|
|
2205
2234
|
app.post("/api/organism/alerts/config", async (_req, res) => {
|
|
2206
|
-
|
|
2235
|
+
try {
|
|
2236
|
+
const { setAlertConfig } = await import("../organism/alertsStore.js");
|
|
2237
|
+
setAlertConfig(_req.body || {});
|
|
2238
|
+
res.json({ success: true });
|
|
2239
|
+
} catch (e) {
|
|
2240
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2241
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
2242
|
+
}
|
|
2207
2243
|
});
|
|
2208
|
-
app.post("/api/organism/alerts/:id/acknowledge", async (
|
|
2209
|
-
|
|
2244
|
+
app.post("/api/organism/alerts/:id/acknowledge", async (req, res) => {
|
|
2245
|
+
try {
|
|
2246
|
+
const { acknowledgeAlert } = await import("../organism/alertsStore.js");
|
|
2247
|
+
const ok = acknowledgeAlert(req.params.id);
|
|
2248
|
+
if (!ok) {
|
|
2249
|
+
res.status(404).json({ error: "Alert not found" });
|
|
2250
|
+
return;
|
|
2251
|
+
}
|
|
2252
|
+
res.json({ success: true });
|
|
2253
|
+
} catch (e) {
|
|
2254
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2255
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
2256
|
+
}
|
|
2210
2257
|
});
|
|
2211
2258
|
app.delete("/api/organism/alerts/old", async (_req, res) => {
|
|
2212
|
-
|
|
2259
|
+
try {
|
|
2260
|
+
const { deleteOldAlerts } = await import("../organism/alertsStore.js");
|
|
2261
|
+
const removed = deleteOldAlerts();
|
|
2262
|
+
res.json({ removed });
|
|
2263
|
+
} catch (e) {
|
|
2264
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2265
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
2266
|
+
}
|
|
2267
|
+
});
|
|
2268
|
+
app.post("/api/eval/run", async (req, res) => {
|
|
2269
|
+
try {
|
|
2270
|
+
const { suite } = req.body;
|
|
2271
|
+
const {
|
|
2272
|
+
runEvalSuite,
|
|
2273
|
+
WIDGET_CREATION_SUITE,
|
|
2274
|
+
SAFETY_SUITE,
|
|
2275
|
+
TOOL_ROUTING_SUITE,
|
|
2276
|
+
GATE_FORMAT_SUITE
|
|
2277
|
+
} = await import("../eval/harness.js");
|
|
2278
|
+
const systemWidgetShortcuts = [
|
|
2279
|
+
{ pattern: /\b(?:backups?|snapshots?|archives?)\b/i, source: "system:backup", name: "Backup Manager", w: 6, h: 6 },
|
|
2280
|
+
{ pattern: /\b(?:training|train|specialists?|models?)\b/i, source: "system:training", name: "Training Dashboard", w: 6, h: 6 },
|
|
2281
|
+
{ pattern: /\b(?:recipes?|playbooks?|workflows?|jarvis)\b/i, source: "system:recipes", name: "Recipe Kitchen", w: 6, h: 6 },
|
|
2282
|
+
{ pattern: /\b(?:vram|gpu|memory|nvidia)\b/i, source: "system:vram", name: "VRAM Monitor", w: 6, h: 6 },
|
|
2283
|
+
{ pattern: /\b(?:teams?|members?|roles?|permissions?|rbac)\b/i, source: "system:teams", name: "Team Hub", w: 6, h: 6 },
|
|
2284
|
+
{ pattern: /\b(?:cron|schedules?|jobs?|timers?)\b/i, source: "system:cron", name: "Cron Scheduler", w: 6, h: 6 },
|
|
2285
|
+
{ pattern: /\b(?:checkpoints?|restores?|save state)\b/i, source: "system:checkpoints", name: "Checkpoints", w: 6, h: 5 },
|
|
2286
|
+
{ pattern: /\b(?:organism|drives?|safety|alerts?|guardrails?)\b/i, source: "system:organism", name: "Organism Monitor", w: 6, h: 6 },
|
|
2287
|
+
{ pattern: /\b(?:fleet|nodes?|routes?|mesh)\b/i, source: "system:fleet", name: "Fleet Router", w: 6, h: 5 },
|
|
2288
|
+
{ pattern: /\b(?:captcha|browsers?|form fill|web automation)\b/i, source: "system:browser", name: "Browser Tools", w: 6, h: 5 },
|
|
2289
|
+
{ pattern: /\b(?:paperclip|sidecars?|helpers?)\b/i, source: "system:paperclip", name: "Paperclip", w: 6, h: 5 },
|
|
2290
|
+
{ pattern: /\b(?:tests?|flaky|failing|coverage|eval)\b/i, source: "system:eval", name: "Test Lab", w: 6, h: 6 }
|
|
2291
|
+
];
|
|
2292
|
+
const agentCall = async (input, testName) => {
|
|
2293
|
+
const shortcut = systemWidgetShortcuts.find((s) => s.pattern.test(input));
|
|
2294
|
+
if (shortcut) {
|
|
2295
|
+
return {
|
|
2296
|
+
content: `Added the **${shortcut.name}** widget to your canvas.
|
|
2297
|
+
|
|
2298
|
+
_____widget
|
|
2299
|
+
{ "name": "${shortcut.name}", "format": "system", "source": "${shortcut.source}", "w": ${shortcut.w}, "h": ${shortcut.h} }`,
|
|
2300
|
+
toolsUsed: []
|
|
2301
|
+
};
|
|
2302
|
+
}
|
|
2303
|
+
const userId = testName ? `eval-${testName.replace(/\s+/g, "-").toLowerCase()}` : "eval-harness";
|
|
2304
|
+
const result2 = await processMessage(input, "eval", userId, {});
|
|
2305
|
+
return {
|
|
2306
|
+
content: result2.content || "",
|
|
2307
|
+
toolsUsed: result2.toolsUsed ?? []
|
|
2308
|
+
};
|
|
2309
|
+
};
|
|
2310
|
+
let cases;
|
|
2311
|
+
switch (suite) {
|
|
2312
|
+
case "widget-creation":
|
|
2313
|
+
cases = WIDGET_CREATION_SUITE;
|
|
2314
|
+
break;
|
|
2315
|
+
case "safety":
|
|
2316
|
+
cases = SAFETY_SUITE;
|
|
2317
|
+
break;
|
|
2318
|
+
case "tool-routing":
|
|
2319
|
+
cases = TOOL_ROUTING_SUITE;
|
|
2320
|
+
break;
|
|
2321
|
+
case "gate-format":
|
|
2322
|
+
cases = GATE_FORMAT_SUITE;
|
|
2323
|
+
break;
|
|
2324
|
+
default:
|
|
2325
|
+
res.status(400).json({ error: `Unknown suite: ${suite}. Choose: widget-creation, safety, tool-routing, gate-format, continuation.` });
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
const result = await runEvalSuite(suite, cases, agentCall);
|
|
2329
|
+
res.json(result);
|
|
2330
|
+
} catch (e) {
|
|
2331
|
+
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2332
|
+
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
2333
|
+
}
|
|
2334
|
+
});
|
|
2335
|
+
app.get("/api/eval/suites", async (_req, res) => {
|
|
2336
|
+
res.json({ suites: ["widget-creation", "safety", "tool-routing", "gate-format"] });
|
|
2213
2337
|
});
|
|
2214
2338
|
app.get("/api/tests/health", async (_req, res) => {
|
|
2215
2339
|
try {
|
|
@@ -2329,9 +2453,16 @@ ${msg.content}
|
|
|
2329
2453
|
});
|
|
2330
2454
|
app.get("/api/test-health/summary", async (_req, res) => {
|
|
2331
2455
|
try {
|
|
2332
|
-
const { getTestHealthSummary } = await import("../testing/testHealthMonitor.js");
|
|
2333
|
-
const
|
|
2334
|
-
|
|
2456
|
+
const { getTestHealthSummary, getFlakyTests } = await import("../testing/testHealthMonitor.js");
|
|
2457
|
+
const raw = getTestHealthSummary();
|
|
2458
|
+
const flaky = getFlakyTests().length;
|
|
2459
|
+
res.json({
|
|
2460
|
+
total: raw.total,
|
|
2461
|
+
passing: raw.passing,
|
|
2462
|
+
failing: raw.failing,
|
|
2463
|
+
flaky,
|
|
2464
|
+
coverage: raw.coveragePct
|
|
2465
|
+
});
|
|
2335
2466
|
} catch (e) {
|
|
2336
2467
|
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
2337
2468
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
@@ -2341,7 +2472,8 @@ ${msg.content}
|
|
|
2341
2472
|
try {
|
|
2342
2473
|
const { getFailingTests } = await import("../testing/testHealthMonitor.js");
|
|
2343
2474
|
const limit = _req.query.limit ? parseInt(_req.query.limit, 10) : 10;
|
|
2344
|
-
const
|
|
2475
|
+
const names = getFailingTests().slice(0, limit);
|
|
2476
|
+
const tests = names.map((name) => ({ name, suite: "", error: "", lastFailed: "", attempts: 0 }));
|
|
2345
2477
|
res.json({ count: tests.length, tests });
|
|
2346
2478
|
} catch (e) {
|
|
2347
2479
|
res.status(500).json({ error: e.message, tests: [] });
|
|
@@ -2352,7 +2484,8 @@ ${msg.content}
|
|
|
2352
2484
|
const { getFlakyTests } = await import("../testing/testHealthMonitor.js");
|
|
2353
2485
|
const threshold = _req.query.threshold ? parseFloat(_req.query.threshold) : 0.4;
|
|
2354
2486
|
const limit = _req.query.limit ? parseInt(_req.query.limit, 10) : 10;
|
|
2355
|
-
const
|
|
2487
|
+
const names = getFlakyTests(threshold).slice(0, limit);
|
|
2488
|
+
const tests = names.map((name) => ({ name, suite: "", passRate: 0, runs: 0 }));
|
|
2356
2489
|
res.json({ count: tests.length, threshold, tests });
|
|
2357
2490
|
} catch (e) {
|
|
2358
2491
|
res.status(500).json({ error: e.message, tests: [] });
|
|
@@ -2784,6 +2917,47 @@ ${msg.content}
|
|
|
2784
2917
|
return;
|
|
2785
2918
|
}
|
|
2786
2919
|
const safeUserId = channel === "api" ? "api-user" : userId || "api-user";
|
|
2920
|
+
const systemWidgetShortcuts = [
|
|
2921
|
+
{ pattern: /\b(?:backups?|snapshots?|archives?)\b/i, source: "system:backup", name: "Backup Manager", w: 6, h: 6 },
|
|
2922
|
+
{ pattern: /\b(?:training|train|specialists?|models?)\b/i, source: "system:training", name: "Training Dashboard", w: 6, h: 6 },
|
|
2923
|
+
{ pattern: /\b(?:recipes?|playbooks?|workflows?|jarvis)\b/i, source: "system:recipes", name: "Recipe Kitchen", w: 6, h: 6 },
|
|
2924
|
+
{ pattern: /\b(?:vram|gpu|memory|nvidia)\b/i, source: "system:vram", name: "VRAM Monitor", w: 6, h: 6 },
|
|
2925
|
+
{ pattern: /\b(?:teams?|members?|roles?|permissions?|rbac)\b/i, source: "system:teams", name: "Team Hub", w: 6, h: 6 },
|
|
2926
|
+
{ pattern: /\b(?:cron|schedules?|jobs?|timers?)\b/i, source: "system:cron", name: "Cron Scheduler", w: 6, h: 6 },
|
|
2927
|
+
{ pattern: /\b(?:checkpoints?|restores?|save state)\b/i, source: "system:checkpoints", name: "Checkpoints", w: 6, h: 5 },
|
|
2928
|
+
{ pattern: /\b(?:organism|drives?|safety|alerts?|guardrails?)\b/i, source: "system:organism", name: "Organism Monitor", w: 6, h: 6 },
|
|
2929
|
+
{ pattern: /\b(?:fleet|nodes?|routes?|mesh)\b/i, source: "system:fleet", name: "Fleet Router", w: 6, h: 5 },
|
|
2930
|
+
{ pattern: /\b(?:captcha|browsers?|form fill|web automation)\b/i, source: "system:browser", name: "Browser Tools", w: 6, h: 5 },
|
|
2931
|
+
{ pattern: /\b(?:paperclip|sidecars?|helpers?)\b/i, source: "system:paperclip", name: "Paperclip", w: 6, h: 5 },
|
|
2932
|
+
{ pattern: /\b(?:tests?|flaky|failing|coverage|eval)\b/i, source: "system:eval", name: "Test Lab", w: 6, h: 6 }
|
|
2933
|
+
];
|
|
2934
|
+
const matchedShortcut = systemWidgetShortcuts.find((s) => s.pattern.test(content));
|
|
2935
|
+
if (matchedShortcut) {
|
|
2936
|
+
const gateText = `_____widget
|
|
2937
|
+
{ "name": "${matchedShortcut.name}", "format": "system", "source": "${matchedShortcut.source}", "w": ${matchedShortcut.w}, "h": ${matchedShortcut.h} }`;
|
|
2938
|
+
const responseText = `Added the **${matchedShortcut.name}** widget to your canvas.`;
|
|
2939
|
+
titanRequestsTotal.increment({ channel, status: "ok" });
|
|
2940
|
+
if (req.headers.accept === "text/event-stream") {
|
|
2941
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
2942
|
+
res.flushHeaders();
|
|
2943
|
+
res.write(`event: token
|
|
2944
|
+
data: ${JSON.stringify({ text: responseText })}
|
|
2945
|
+
|
|
2946
|
+
`);
|
|
2947
|
+
res.write(`event: token
|
|
2948
|
+
data: ${JSON.stringify({ text: "\n\n" + gateText })}
|
|
2949
|
+
|
|
2950
|
+
`);
|
|
2951
|
+
res.write(`event: done
|
|
2952
|
+
data: ${JSON.stringify({ content: responseText + "\n\n" + gateText, sessionId: requestedSessionId || null, durationMs: 0, toolsUsed: [] })}
|
|
2953
|
+
|
|
2954
|
+
`);
|
|
2955
|
+
res.end();
|
|
2956
|
+
} else {
|
|
2957
|
+
res.json({ content: responseText + "\n\n" + gateText, sessionId: requestedSessionId || null, toolsUsed: [], model: "system", durationMs: 0 });
|
|
2958
|
+
}
|
|
2959
|
+
return;
|
|
2960
|
+
}
|
|
2787
2961
|
const startTime = process.hrtime.bigint();
|
|
2788
2962
|
const wantsSSE = req.headers.accept === "text/event-stream";
|
|
2789
2963
|
if (requestedSessionId && !/^[a-zA-Z0-9_:-]{1,128}$/.test(requestedSessionId)) {
|
|
@@ -3436,6 +3610,119 @@ data: ${JSON.stringify(structured)}
|
|
|
3436
3610
|
if (org.tickIntervalMs !== void 0) draft.organism.tickIntervalMs = Number(org.tickIntervalMs);
|
|
3437
3611
|
changedFields.push("organism");
|
|
3438
3612
|
}
|
|
3613
|
+
const handleNestedBool = (section, key, target) => {
|
|
3614
|
+
const sec = body[section];
|
|
3615
|
+
if (sec && key in sec) {
|
|
3616
|
+
target[key] = Boolean(sec[key]);
|
|
3617
|
+
changedFields.push(`${section}.${key}`);
|
|
3618
|
+
}
|
|
3619
|
+
};
|
|
3620
|
+
if (body.autonomy !== void 0 && typeof body.autonomy === "object") {
|
|
3621
|
+
const a = body.autonomy;
|
|
3622
|
+
if (!draft.autonomy) draft.autonomy = {};
|
|
3623
|
+
const da = draft.autonomy;
|
|
3624
|
+
if (a.mode !== void 0) da.mode = a.mode;
|
|
3625
|
+
if (a.autoProposeGoals !== void 0) da.autoProposeGoals = Boolean(a.autoProposeGoals);
|
|
3626
|
+
if (a.proactiveInitiative !== void 0) da.proactiveInitiative = Boolean(a.proactiveInitiative);
|
|
3627
|
+
changedFields.push("autonomy");
|
|
3628
|
+
}
|
|
3629
|
+
if (body.selfMod !== void 0 && typeof body.selfMod === "object") {
|
|
3630
|
+
const s = body.selfMod;
|
|
3631
|
+
if (!draft.selfMod) draft.selfMod = {};
|
|
3632
|
+
if (s.enabled !== void 0) draft.selfMod.enabled = Boolean(s.enabled);
|
|
3633
|
+
if (s.autoPR !== void 0) draft.selfMod.autoPR = Boolean(s.autoPR);
|
|
3634
|
+
changedFields.push("selfMod");
|
|
3635
|
+
}
|
|
3636
|
+
if (body.commandPost !== void 0 && typeof body.commandPost === "object") {
|
|
3637
|
+
const cp = body.commandPost;
|
|
3638
|
+
if (!draft.commandPost) draft.commandPost = {};
|
|
3639
|
+
if (cp.enabled !== void 0) draft.commandPost.enabled = Boolean(cp.enabled);
|
|
3640
|
+
changedFields.push("commandPost");
|
|
3641
|
+
}
|
|
3642
|
+
if (body.mesh !== void 0 && typeof body.mesh === "object") {
|
|
3643
|
+
const m = body.mesh;
|
|
3644
|
+
if (!draft.mesh) draft.mesh = {};
|
|
3645
|
+
if (m.enabled !== void 0) draft.mesh.enabled = Boolean(m.enabled);
|
|
3646
|
+
changedFields.push("mesh");
|
|
3647
|
+
}
|
|
3648
|
+
if (body.autopilot !== void 0 && typeof body.autopilot === "object") {
|
|
3649
|
+
const ap = body.autopilot;
|
|
3650
|
+
if (!draft.autopilot) draft.autopilot = {};
|
|
3651
|
+
if (ap.enabled !== void 0) draft.autopilot.enabled = Boolean(ap.enabled);
|
|
3652
|
+
if (ap.goals !== void 0 && typeof ap.goals === "object") {
|
|
3653
|
+
const apg = ap.goals;
|
|
3654
|
+
const dag = draft.autopilot;
|
|
3655
|
+
if (!dag.goals) dag.goals = {};
|
|
3656
|
+
if (apg.selfInitiate !== void 0) dag.goals.selfInitiate = Boolean(apg.selfInitiate);
|
|
3657
|
+
}
|
|
3658
|
+
changedFields.push("autopilot");
|
|
3659
|
+
}
|
|
3660
|
+
if (body.brain !== void 0 && typeof body.brain === "object") {
|
|
3661
|
+
const b = body.brain;
|
|
3662
|
+
if (!draft.brain) draft.brain = {};
|
|
3663
|
+
if (b.enabled !== void 0) draft.brain.enabled = Boolean(b.enabled);
|
|
3664
|
+
changedFields.push("brain");
|
|
3665
|
+
}
|
|
3666
|
+
if (body.mcp !== void 0 && typeof body.mcp === "object") {
|
|
3667
|
+
const mcp = body.mcp;
|
|
3668
|
+
if (!draft.mcp) draft.mcp = { server: {} };
|
|
3669
|
+
if (mcp.server !== void 0 && typeof mcp.server === "object") {
|
|
3670
|
+
const srv = mcp.server;
|
|
3671
|
+
const dmcp = draft.mcp;
|
|
3672
|
+
if (!dmcp.server) dmcp.server = {};
|
|
3673
|
+
if (srv.enabled !== void 0) dmcp.server.enabled = Boolean(srv.enabled);
|
|
3674
|
+
}
|
|
3675
|
+
changedFields.push("mcp");
|
|
3676
|
+
}
|
|
3677
|
+
if (body.training !== void 0 && typeof body.training === "object") {
|
|
3678
|
+
const t = body.training;
|
|
3679
|
+
if (!draft.training) draft.training = {};
|
|
3680
|
+
if (t.enabled !== void 0) draft.training.enabled = Boolean(t.enabled);
|
|
3681
|
+
changedFields.push("training");
|
|
3682
|
+
}
|
|
3683
|
+
if (body.teams !== void 0 && typeof body.teams === "object") {
|
|
3684
|
+
const t = body.teams;
|
|
3685
|
+
if (!draft.teams) draft.teams = {};
|
|
3686
|
+
if (t.enabled !== void 0) draft.teams.enabled = Boolean(t.enabled);
|
|
3687
|
+
changedFields.push("teams");
|
|
3688
|
+
}
|
|
3689
|
+
if (body.tunnel !== void 0 && typeof body.tunnel === "object") {
|
|
3690
|
+
const t = body.tunnel;
|
|
3691
|
+
if (!draft.tunnel) draft.tunnel = {};
|
|
3692
|
+
if (t.enabled !== void 0) draft.tunnel.enabled = Boolean(t.enabled);
|
|
3693
|
+
changedFields.push("tunnel");
|
|
3694
|
+
}
|
|
3695
|
+
if (body.vault !== void 0 && typeof body.vault === "object") {
|
|
3696
|
+
const v = body.vault;
|
|
3697
|
+
const dsec = draft.security;
|
|
3698
|
+
if (!dsec.vault) dsec.vault = {};
|
|
3699
|
+
if (v.enabled !== void 0) dsec.vault.enabled = Boolean(v.enabled);
|
|
3700
|
+
changedFields.push("security.vault");
|
|
3701
|
+
}
|
|
3702
|
+
if (body.capsolver !== void 0 && typeof body.capsolver === "object") {
|
|
3703
|
+
const c = body.capsolver;
|
|
3704
|
+
if (!draft.capsolver) draft.capsolver = {};
|
|
3705
|
+
if (c.enabled !== void 0) draft.capsolver.enabled = Boolean(c.enabled);
|
|
3706
|
+
changedFields.push("capsolver");
|
|
3707
|
+
}
|
|
3708
|
+
if (body.deliberation !== void 0 && typeof body.deliberation === "object") {
|
|
3709
|
+
const d = body.deliberation;
|
|
3710
|
+
if (!draft.deliberation) draft.deliberation = {};
|
|
3711
|
+
if (d.autoDetect !== void 0) draft.deliberation.autoDetect = Boolean(d.autoDetect);
|
|
3712
|
+
changedFields.push("deliberation");
|
|
3713
|
+
}
|
|
3714
|
+
if (body.selfImprove !== void 0 && typeof body.selfImprove === "object") {
|
|
3715
|
+
const si = body.selfImprove;
|
|
3716
|
+
if (!draft.selfImprove) draft.selfImprove = {};
|
|
3717
|
+
if (si.autoApply !== void 0) draft.selfImprove.autoApply = Boolean(si.autoApply);
|
|
3718
|
+
changedFields.push("selfImprove");
|
|
3719
|
+
}
|
|
3720
|
+
if (body.memory !== void 0 && typeof body.memory === "object") {
|
|
3721
|
+
const mem = body.memory;
|
|
3722
|
+
if (!draft.memory) draft.memory = {};
|
|
3723
|
+
if (mem.vectorSearchEnabled !== void 0) draft.memory.vectorSearchEnabled = Boolean(mem.vectorSearchEnabled);
|
|
3724
|
+
changedFields.push("memory");
|
|
3725
|
+
}
|
|
3439
3726
|
if (changedFields.length === 0) {
|
|
3440
3727
|
const validFields = [
|
|
3441
3728
|
"model",
|
|
@@ -3471,7 +3758,22 @@ data: ${JSON.stringify(structured)}
|
|
|
3471
3758
|
"homeAssistantToken",
|
|
3472
3759
|
"voice",
|
|
3473
3760
|
"nvidia",
|
|
3474
|
-
"organism"
|
|
3761
|
+
"organism",
|
|
3762
|
+
"autonomy",
|
|
3763
|
+
"selfMod",
|
|
3764
|
+
"commandPost",
|
|
3765
|
+
"mesh",
|
|
3766
|
+
"autopilot",
|
|
3767
|
+
"brain",
|
|
3768
|
+
"mcp",
|
|
3769
|
+
"training",
|
|
3770
|
+
"teams",
|
|
3771
|
+
"tunnel",
|
|
3772
|
+
"vault",
|
|
3773
|
+
"capsolver",
|
|
3774
|
+
"deliberation",
|
|
3775
|
+
"selfImprove",
|
|
3776
|
+
"memory"
|
|
3475
3777
|
];
|
|
3476
3778
|
res.status(400).json({ error: "No recognized fields in request body", validFields });
|
|
3477
3779
|
return;
|
|
@@ -4233,7 +4535,7 @@ data: ${JSON.stringify(structured)}
|
|
|
4233
4535
|
app.get("/api/backup/list", async (_req, res) => {
|
|
4234
4536
|
try {
|
|
4235
4537
|
const { listBackups } = await import("../storage/backup.js");
|
|
4236
|
-
res.json(listBackups());
|
|
4538
|
+
res.json({ backups: listBackups() });
|
|
4237
4539
|
} catch (e) {
|
|
4238
4540
|
logger.error(COMPONENT, `Endpoint error: ${e.message}`);
|
|
4239
4541
|
res.status(500).json({ error: "Something went wrong on our end. Please try again in a moment." });
|
|
@@ -7001,8 +7303,8 @@ Retrying after failure: ${run.error || "unknown error"}`;
|
|
|
7001
7303
|
sessionAbortTimes.set(requestedSessionId, Date.now());
|
|
7002
7304
|
}
|
|
7003
7305
|
let effectiveTtsEngine = ttsEngine;
|
|
7004
|
-
|
|
7005
|
-
|
|
7306
|
+
const effectiveTtsUrl = ttsUrl;
|
|
7307
|
+
const effectiveTtsModel = "f5-tts-mlx";
|
|
7006
7308
|
try {
|
|
7007
7309
|
const probe = await fetch(`${effectiveTtsUrl}/health`, { signal: AbortSignal.timeout(5e3) });
|
|
7008
7310
|
if (!probe.ok) effectiveTtsEngine = "unavailable";
|
|
@@ -8341,32 +8643,6 @@ td{padding:10px 12px;font-size:14px;vertical-align:middle}
|
|
|
8341
8643
|
logger.info(COMPONENT, `Messenger webhook: /api/messenger/webhook + /messenger/webhook (verify token: ${messengerAdapter.getVerifyToken()})`);
|
|
8342
8644
|
}
|
|
8343
8645
|
{
|
|
8344
|
-
let getTwilioConfig2 = function() {
|
|
8345
|
-
const cfg = loadConfig();
|
|
8346
|
-
const c = cfg.channels?.twilio || {};
|
|
8347
|
-
return {
|
|
8348
|
-
authToken: c.authToken || process.env.TWILIO_AUTH_TOKEN || "",
|
|
8349
|
-
phoneNumber: c.phoneNumber || process.env.TWILIO_PHONE_NUMBER || "",
|
|
8350
|
-
voice: c.voice || "andrew",
|
|
8351
|
-
allowedCallers: c.allowedCallers || [],
|
|
8352
|
-
publicHost: c.publicHost || process.env.TWILIO_PUBLIC_HOST || ""
|
|
8353
|
-
};
|
|
8354
|
-
}, computeSignedUrl2 = function(req) {
|
|
8355
|
-
const cfg = getTwilioConfig2();
|
|
8356
|
-
const host2 = cfg.publicHost.replace(/\/$/, "") || `https://${req.headers.host}`;
|
|
8357
|
-
return host2 + req.originalUrl;
|
|
8358
|
-
}, checkTwilioAuth2 = function(req) {
|
|
8359
|
-
const { authToken } = getTwilioConfig2();
|
|
8360
|
-
if (!authToken) {
|
|
8361
|
-
logger.warn(COMPONENT, "Twilio authToken not configured \u2014 signature check SKIPPED");
|
|
8362
|
-
return true;
|
|
8363
|
-
}
|
|
8364
|
-
const signature = req.headers["x-twilio-signature"] || "";
|
|
8365
|
-
const url = computeSignedUrl2(req);
|
|
8366
|
-
const params = req.body || {};
|
|
8367
|
-
return validateTwilioSignature(authToken, signature, url, params);
|
|
8368
|
-
};
|
|
8369
|
-
var getTwilioConfig = getTwilioConfig2, computeSignedUrl = computeSignedUrl2, checkTwilioAuth = checkTwilioAuth2;
|
|
8370
8646
|
const {
|
|
8371
8647
|
twimlPlayAndGather,
|
|
8372
8648
|
twimlPauseAndRedirect,
|
|
@@ -8387,14 +8663,41 @@ td{padding:10px 12px;font-size:14px;vertical-align:middle}
|
|
|
8387
8663
|
} = await import("../channels/twilio-voice.js");
|
|
8388
8664
|
const twilioCfg = config.channels?.twilio;
|
|
8389
8665
|
const twilioEnabled = twilioCfg?.enabled !== false;
|
|
8666
|
+
const getTwilioConfig = () => {
|
|
8667
|
+
const cfg = loadConfig();
|
|
8668
|
+
const c = cfg.channels?.twilio || {};
|
|
8669
|
+
return {
|
|
8670
|
+
authToken: c.authToken || process.env.TWILIO_AUTH_TOKEN || "",
|
|
8671
|
+
phoneNumber: c.phoneNumber || process.env.TWILIO_PHONE_NUMBER || "",
|
|
8672
|
+
voice: c.voice || "andrew",
|
|
8673
|
+
allowedCallers: c.allowedCallers || [],
|
|
8674
|
+
publicHost: c.publicHost || process.env.TWILIO_PUBLIC_HOST || ""
|
|
8675
|
+
};
|
|
8676
|
+
};
|
|
8390
8677
|
const urlEncoded = express.urlencoded({ extended: false });
|
|
8678
|
+
const computeSignedUrl = (req) => {
|
|
8679
|
+
const cfg = getTwilioConfig();
|
|
8680
|
+
const host2 = cfg.publicHost.replace(/\/$/, "") || `https://${req.headers.host}`;
|
|
8681
|
+
return host2 + req.originalUrl;
|
|
8682
|
+
};
|
|
8683
|
+
const checkTwilioAuth = (req) => {
|
|
8684
|
+
const { authToken } = getTwilioConfig();
|
|
8685
|
+
if (!authToken) {
|
|
8686
|
+
logger.warn(COMPONENT, "Twilio authToken not configured \u2014 signature check SKIPPED");
|
|
8687
|
+
return true;
|
|
8688
|
+
}
|
|
8689
|
+
const signature = req.headers["x-twilio-signature"] || "";
|
|
8690
|
+
const url = computeSignedUrl(req);
|
|
8691
|
+
const params = req.body || {};
|
|
8692
|
+
return validateTwilioSignature(authToken, signature, url, params);
|
|
8693
|
+
};
|
|
8391
8694
|
app.post("/api/twilio/voice-webhook", urlEncoded, async (req, res) => {
|
|
8392
8695
|
try {
|
|
8393
8696
|
if (!twilioEnabled) {
|
|
8394
8697
|
res.type("text/xml").send(twimlReject());
|
|
8395
8698
|
return;
|
|
8396
8699
|
}
|
|
8397
|
-
if (!
|
|
8700
|
+
if (!checkTwilioAuth(req)) {
|
|
8398
8701
|
logger.warn(COMPONENT, "Twilio voice-webhook: signature invalid");
|
|
8399
8702
|
res.status(403).send("forbidden");
|
|
8400
8703
|
return;
|
|
@@ -8403,7 +8706,7 @@ td{padding:10px 12px;font-size:14px;vertical-align:middle}
|
|
|
8403
8706
|
const to = req.body?.To || "";
|
|
8404
8707
|
const direction = req.body?.Direction || "inbound";
|
|
8405
8708
|
const callSid = req.body?.CallSid || "";
|
|
8406
|
-
const { allowedCallers, voice, publicHost } =
|
|
8709
|
+
const { allowedCallers, voice, publicHost } = getTwilioConfig();
|
|
8407
8710
|
const isOutbound = direction.startsWith("outbound");
|
|
8408
8711
|
const humanNumber = isOutbound ? to : from;
|
|
8409
8712
|
if (allowedCallers.length > 0 && !isAllowedCaller(humanNumber, allowedCallers)) {
|
|
@@ -8433,7 +8736,7 @@ td{padding:10px 12px;font-size:14px;vertical-align:middle}
|
|
|
8433
8736
|
res.type("text/xml").send(twimlReject());
|
|
8434
8737
|
return;
|
|
8435
8738
|
}
|
|
8436
|
-
if (!
|
|
8739
|
+
if (!checkTwilioAuth(req)) {
|
|
8437
8740
|
res.status(403).send("forbidden");
|
|
8438
8741
|
return;
|
|
8439
8742
|
}
|
|
@@ -8442,7 +8745,7 @@ td{padding:10px 12px;font-size:14px;vertical-align:middle}
|
|
|
8442
8745
|
const to = req.body?.To || "";
|
|
8443
8746
|
const direction = req.body?.Direction || "inbound";
|
|
8444
8747
|
const speechResult = (req.body?.SpeechResult || "").trim();
|
|
8445
|
-
const { voice, publicHost, allowedCallers } =
|
|
8748
|
+
const { voice, publicHost, allowedCallers } = getTwilioConfig();
|
|
8446
8749
|
const isOutbound = direction.startsWith("outbound");
|
|
8447
8750
|
const humanNumber = isOutbound ? to : from;
|
|
8448
8751
|
if (allowedCallers.length > 0 && !isAllowedCaller(humanNumber, allowedCallers)) {
|
|
@@ -8528,7 +8831,7 @@ td{padding:10px 12px;font-size:14px;vertical-align:middle}
|
|
|
8528
8831
|
res.type("text/xml").send(twimlReject());
|
|
8529
8832
|
return;
|
|
8530
8833
|
}
|
|
8531
|
-
if (!
|
|
8834
|
+
if (!checkTwilioAuth(req)) {
|
|
8532
8835
|
logger.warn(COMPONENT, `voice-poll signature rejected (method=${req.method}, jobId=${req.query.jobId})`);
|
|
8533
8836
|
res.status(403).send("forbidden");
|
|
8534
8837
|
return;
|
|
@@ -8536,7 +8839,7 @@ td{padding:10px 12px;font-size:14px;vertical-align:middle}
|
|
|
8536
8839
|
const jobId = req.query.jobId || "";
|
|
8537
8840
|
const job = getVoiceJob(jobId);
|
|
8538
8841
|
logger.info(COMPONENT, `voice-poll method=${req.method} jobId=${jobId.slice(0, 8)} status=${job?.status || "missing"}`);
|
|
8539
|
-
const { voice, publicHost } =
|
|
8842
|
+
const { voice, publicHost } = getTwilioConfig();
|
|
8540
8843
|
const host2 = publicHost.replace(/\/$/, "") || `https://${req.headers.host}`;
|
|
8541
8844
|
const pollUrl = `${host2}/api/twilio/voice-poll?jobId=${jobId}`;
|
|
8542
8845
|
const gatherUrl = `${host2}/api/twilio/voice-gather`;
|
|
@@ -9077,7 +9380,7 @@ Your task: ${monitor.prompt}`;
|
|
|
9077
9380
|
logger.info(COMPONENT, "Health monitor started (60s interval)");
|
|
9078
9381
|
const SECRET_PATTERNS = [
|
|
9079
9382
|
// Bearer / Basic auth headers
|
|
9080
|
-
/\b[Bb]earer\s+[A-Za-z0-9_
|
|
9383
|
+
/\b[Bb]earer\s+[A-Za-z0-9_\-.]{20,}/g,
|
|
9081
9384
|
/\b[Bb]asic\s+[A-Za-z0-9+/=]{20,}/g,
|
|
9082
9385
|
// API key prefixes (OpenAI, Anthropic, Groq, etc.)
|
|
9083
9386
|
/\b(sk|pk)-[A-Za-z0-9]{20,}/g,
|
|
@@ -9184,12 +9487,9 @@ Channels: ${Array.from(channels.values()).map((c) => `${c.displayName} (${c.getS
|
|
|
9184
9487
|
logger.info(COMPONENT, `Skills: ${getSkills().length} loaded`);
|
|
9185
9488
|
logger.info(COMPONENT, `Tools: ${getRegisteredTools().length} registered`);
|
|
9186
9489
|
try {
|
|
9187
|
-
const
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
const markerPath = join2(homedir2(), ".titan", "install-marker.json");
|
|
9191
|
-
if (existsSync(markerPath)) {
|
|
9192
|
-
const marker = JSON.parse(readFileSync(markerPath, "utf-8"));
|
|
9490
|
+
const markerPath = join(homedir(), ".titan", "install-marker.json");
|
|
9491
|
+
if (fs.existsSync(markerPath)) {
|
|
9492
|
+
const marker = JSON.parse(fs.readFileSync(markerPath, "utf-8"));
|
|
9193
9493
|
if (marker.previousVersion && marker.previousVersion !== TITAN_VERSION) {
|
|
9194
9494
|
logger.info(COMPONENT, `
|
|
9195
9495
|
\u{1F680} Welcome to TITAN v${TITAN_VERSION}! Upgraded from v${marker.previousVersion}.`);
|