@tea-agent/loop-agent 0.44.0-next.1 → 0.44.0-next.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/CHANGELOG.md +178 -175
- package/dist/build-stamp.json +3 -3
- package/dist/executors/pi-sdk-executor.js +29 -1
- package/dist/shared/wizard-local-telemetry.js +50 -0
- package/dist/worker/console/chat/chat-event-store.js +3 -0
- package/dist/worker/console/chat/db-connections.js +790 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +1 -1
- package/dist/worker/console/chat/pi-runtime/custom-tools/sql-tools.js +627 -0
- package/dist/worker/console/chat/pi-runtime.js +66 -6
- package/dist/worker/console/chat/routes.js +154 -3
- package/dist/worker/console/chat/sdd-data-alignment.js +8 -31
- package/dist/worker/console/chat/timeline-message-order.js +22 -0
- package/dist/worker/console/chat/tools.js +34 -0
- package/dist/worker/console/chat/turn-process.js +43 -39
- package/dist/worker/console/dag-confirmation.js +3 -0
- package/dist/worker/console/dag-execution-receipt.js +3 -0
- package/dist/worker/console/operator-actions.js +32 -2
- package/dist/worker/console/server.js +5 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-8-j6y-sd.js → abnfDiagram-N423BO3Z-COQlLTI7.js} +1 -1
- package/dist/worker/console/static/assets/{arc-eoQiMvuk.js → arc-zN3QkNaV.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-C4A3uMcI.js → architectureDiagram-T3A2C74G-Pyoyj5f2.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-D4zD2F-Q.js → blockDiagram-VBNYF7ZC-BNppA5WW.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-j1RkJziL.js → c4Diagram-5PPSVZJV-lyxL8nTx.js} +1 -1
- package/dist/worker/console/static/assets/channel-CgLPkTw2.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-YBHmhik1.js → chunk-2GRJ4B5K-0hgjcdK4.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-COfWyo9P.js → chunk-2Q5K7J3B-D63N9d4i.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-I99OUkHY.js → chunk-5RXB4S5H-CUw2AyB5.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-XKxoJNJ4.js → chunk-5VM5RSS4-Q_kwZT30.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DLT_cYx1.js → chunk-6Q2QTUOP-C7vMiKcw.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CxcKZ9mV.js → chunk-GF5L2VYU-T9GbV5Hz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-V1EqXdjY.js → chunk-JWPE2WC7-D8nUSUJI.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DebTtdFp.js → chunk-KBJHAD2P-BCH2ewdp.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-B-ivNRDf.js → chunk-RYQCIY6F-BTdDuDBN.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-DC_Ds11b.js → chunk-XXDRQBXY-Cqm2RcKF.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-CuSD1Mhb.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-CuSD1Mhb.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-sWEqKwIb.js → cose-bilkent-JH36ORCC-pjwfpVu4.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BXa_dcu4.js → cynefin-VYW2F7L2-BvalptKA.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-C-Mle84F.js → cynefinDiagram-MW4NZA55-BU4qJ6d7.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CXPDBITe.js → dagre-VZM6K2ZE-DVTpq8J9.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CC-WJQfa.js → diagram-7IWD3JNH-B8s1W6Fc.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CDAV5Vs4.js → diagram-B4RE2ZJO-DPrFk9yH.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-CmFiAcNz.js → diagram-LBJQPF4R-CnQIQsHC.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DPBZHuyn.js → diagram-Q27KOJAE-op0DEpCv.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-jUlm_Ds3.js → diagram-UB23O5K3-DXQamm4T.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DWhQ3mfY.js → ebnfDiagram-BXEA7PRR-b1ad2C0r.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-Tr2gMqet.js → erDiagram-JOGREHBK-B4cD-ZFJ.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-DJjVQHPA.js → flowDiagram-UKHOOZJN-CrgGjlQ1.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-D74dQ4u0.js → ganttDiagram-PKOTCBZU-DovmXQNV.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DwW0tZ0X.js → gitGraphDiagram-DS77QQ5N-DpFyu2Jn.js} +1 -1
- package/dist/worker/console/static/assets/index-DHBWEwz_.css +1 -0
- package/dist/worker/console/static/assets/index-JRfTUgP7.js +478 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-ILCbxJyb.js → infoDiagram-6WML65LV-D3MoQZIl.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DeuWBQ89.js → ishikawaDiagram-WSZJBQD7-Ci6C1yjS.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-CF5ih8Fk.js → journeyDiagram-NVQOT4AX-BWMo2lIP.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-C7yOSuRO.js → kanban-definition-27J2QSJJ-BdthIAg3.js} +1 -1
- package/dist/worker/console/static/assets/{linear-BDZ9riWi.js → linear-DuFAlSOj.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-7pKqYtpZ.js → mermaid.core-Dqz3Slj9.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-LeJDybSU.js → mindmap-definition-FAOFIHXS-DNVTrD09.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BJvT3pMD.js → pegDiagram-VL7TDLO6-CgfZPfBh.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-_rGqpMan.js → pieDiagram-7S7Q4E2Y-ClM9P7yo.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DPcSv5aA.js → quadrantDiagram-CIZ2JOQS-DwnEak2J.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Drxx4hkJ.js → railroadDiagram-AXF67PYL-rK4hxt9P.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BCTUdU4z.js → requirementDiagram-LRYGKXZP-Cjqa6vo3.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B6wzbZmB.js → sankeyDiagram-W5VNT64P-D3Fa250Z.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BGt8d3QQ.js → sequenceDiagram-SI44F4Z6-2PdrNajj.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-7nlhJKo7.js → sizeCapture-X5ZJPWSS-BBcuGeZn.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Cv2stqMA.js → stateDiagram-OKZ733FA-CSJX9X6s.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cqskj0zt.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-qDAo4Yc1.js → swimlanes-SLNWSIFB-pOUU1bic.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CM0ZIhNP.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CKbDNKTr.js → timeline-definition-Z64GVDOM-CAeqfQn0.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DI-9EHic.js → vennDiagram-T6HMQDX7-DYPLOMVO.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-BrzzRDpX.js → wardleyDiagram-T6FBY63Y-Dy2V0Cha.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-BclH5hGh.js → xychartDiagram-ELKLHX3M-Dj9o7jrn.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +33 -1
- package/dist/worker/console/static-src/operator-chat/chat-stream-continuity.js +101 -0
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +18 -3
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +17 -3
- package/dist/worker/console/static-src/operator-chat/tools-catalog.js +16 -7
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +15 -7
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +47 -5
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +24 -2
- package/dist/worker/console/workspace-context.js +2 -0
- package/dist/worker/observe/static/console-theme.css +174 -0
- package/dist/worker/observe/static/console-theme.js +36 -0
- package/dist/worker/observe/static/operator-chrome.css +85 -0
- package/dist/worker/observe/static/operator-chrome.js +51 -0
- package/dist/worker/scheduler/scheduled-goal-evidence.js +60 -2
- package/dist/worker/scheduler/scheduled-goal-store.js +10 -0
- package/package.json +3 -1
- package/dist/worker/console/static/assets/channel-ChE7y-cx.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C01TCf2X.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C01TCf2X.js +0 -1
- package/dist/worker/console/static/assets/index-BWkIfcrK.css +0 -1
- package/dist/worker/console/static/assets/index-Cdkvw_H6.js +0 -469
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DC7V5vcq.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bwy4QUTO.js +0 -8
|
@@ -48,6 +48,8 @@ import { BrowserAutomationService } from "./browser-automation.js";
|
|
|
48
48
|
import { buildTodoContinuationContext, } from "./todos.js";
|
|
49
49
|
import { buildPersistentTerminalTools } from "./terminal-tools.js";
|
|
50
50
|
import { buildScmTools } from "./scm-tools.js";
|
|
51
|
+
import { DbConnectionRegistry } from "./db-connections.js";
|
|
52
|
+
import { buildSqlTools } from "./pi-runtime/custom-tools/sql-tools.js";
|
|
51
53
|
import { buildGoalContinuationContext, } from "./goals.js";
|
|
52
54
|
import { injectWizardLocalHeaders, } from "./sdd-data-alignment.js";
|
|
53
55
|
import { buildScheduledGoalTools } from "./pi-runtime/custom-tools/scheduled-goal-tools.js";
|
|
@@ -418,12 +420,14 @@ export class ConsolePiRuntime {
|
|
|
418
420
|
compactionControllers = new Map();
|
|
419
421
|
siftStates = new Map();
|
|
420
422
|
/** Session-less tool definition caches (no AgentSession state). */
|
|
421
|
-
|
|
423
|
+
operatorCustomToolsBySession = new Map();
|
|
422
424
|
exploreCustomToolsPromise;
|
|
423
425
|
exploreOrchestrator;
|
|
424
426
|
bindings;
|
|
425
427
|
browserAutomation;
|
|
426
428
|
ownsBrowserAutomation;
|
|
429
|
+
dbConnections;
|
|
430
|
+
ownsDbConnections;
|
|
427
431
|
constructor(options) {
|
|
428
432
|
this.options = options;
|
|
429
433
|
this.loader = createOperatorChatResourceLoader();
|
|
@@ -434,6 +438,12 @@ export class ConsolePiRuntime {
|
|
|
434
438
|
downloadsDir: path.join(this.options.sessionDir, "..", "browser-downloads"),
|
|
435
439
|
screenshotsDir: path.join(this.options.sessionDir, "..", "browser-screenshots"),
|
|
436
440
|
});
|
|
441
|
+
// Governed DB connections are Console-global, not repository-scoped.
|
|
442
|
+
// This keeps named connections available when the user switches folders.
|
|
443
|
+
this.ownsDbConnections = options.dbConnections === undefined;
|
|
444
|
+
this.dbConnections =
|
|
445
|
+
options.dbConnections ??
|
|
446
|
+
new DbConnectionRegistry(path.join(options.globalAppDataRoot ?? path.resolve(this.options.sessionDir, ".."), "db"), undefined, undefined, path.join(this.options.sessionDir, "..", "db"));
|
|
437
447
|
this.exploreOrchestrator = new ExploreOrchestrator({
|
|
438
448
|
cwd: this.options.cwd,
|
|
439
449
|
bindings: this.bindings,
|
|
@@ -1018,7 +1028,7 @@ export class ConsolePiRuntime {
|
|
|
1018
1028
|
const loadWorkflowTools = shouldLoadWorkflowBusinessTools(sessionMode);
|
|
1019
1029
|
const [operatorCustomTools, exploreCustomTools] = await Promise.all([
|
|
1020
1030
|
loadWorkflowTools
|
|
1021
|
-
? this.loadOperatorCustomTools(sessionMode)
|
|
1031
|
+
? this.loadOperatorCustomTools(sessionId, sessionMode)
|
|
1022
1032
|
: Promise.resolve([]),
|
|
1023
1033
|
this.loadExploreCustomTools(),
|
|
1024
1034
|
]);
|
|
@@ -1059,6 +1069,16 @@ export class ConsolePiRuntime {
|
|
|
1059
1069
|
return [];
|
|
1060
1070
|
})
|
|
1061
1071
|
: [];
|
|
1072
|
+
const sqlTools = await buildSqlTools({
|
|
1073
|
+
sessionId,
|
|
1074
|
+
registry: this.dbConnections,
|
|
1075
|
+
...(this.options.questionRegistry
|
|
1076
|
+
? { questionRegistry: this.options.questionRegistry }
|
|
1077
|
+
: {}),
|
|
1078
|
+
}).catch((error) => {
|
|
1079
|
+
process.stderr.write(`[console] chat sql-tools build failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1080
|
+
return [];
|
|
1081
|
+
});
|
|
1062
1082
|
const agentTool = await buildAgentCustomTool({
|
|
1063
1083
|
parentSessionId: sessionId,
|
|
1064
1084
|
orchestrator: this.exploreOrchestrator,
|
|
@@ -1092,25 +1112,28 @@ export class ConsolePiRuntime {
|
|
|
1092
1112
|
...terminalTools,
|
|
1093
1113
|
...scmTools,
|
|
1094
1114
|
...browserTools,
|
|
1115
|
+
...sqlTools,
|
|
1095
1116
|
...(agentTool ? [agentTool] : []),
|
|
1096
1117
|
];
|
|
1097
1118
|
}
|
|
1098
|
-
loadOperatorCustomTools(sessionMode) {
|
|
1119
|
+
loadOperatorCustomTools(sessionId, sessionMode) {
|
|
1099
1120
|
if (!this.options.actionContext)
|
|
1100
1121
|
return Promise.resolve([]);
|
|
1101
|
-
const
|
|
1122
|
+
const cacheKey = `${sessionId}:${sessionMode}`;
|
|
1123
|
+
const cached = this.operatorCustomToolsBySession.get(cacheKey);
|
|
1102
1124
|
if (cached)
|
|
1103
1125
|
return cached;
|
|
1104
1126
|
const promise = buildCustomOperatorTools({
|
|
1105
1127
|
actionContext: this.options.actionContext,
|
|
1128
|
+
sessionId,
|
|
1106
1129
|
sessionMode,
|
|
1107
1130
|
}).catch((error) => {
|
|
1108
1131
|
process.stderr.write(`[console] chat custom-tools build failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1109
1132
|
// Allow a later create/reopen to retry after a transient failure.
|
|
1110
|
-
this.
|
|
1133
|
+
this.operatorCustomToolsBySession.delete(cacheKey);
|
|
1111
1134
|
return [];
|
|
1112
1135
|
});
|
|
1113
|
-
this.
|
|
1136
|
+
this.operatorCustomToolsBySession.set(cacheKey, promise);
|
|
1114
1137
|
return promise;
|
|
1115
1138
|
}
|
|
1116
1139
|
loadExploreCustomTools() {
|
|
@@ -2232,6 +2255,36 @@ export class ConsolePiRuntime {
|
|
|
2232
2255
|
const result = await session.compact(customInstructions);
|
|
2233
2256
|
return projectCompactSnapshot(result ?? {});
|
|
2234
2257
|
}
|
|
2258
|
+
listDatabaseConnections() {
|
|
2259
|
+
return this.dbConnections.list();
|
|
2260
|
+
}
|
|
2261
|
+
addDatabaseConnection(input) {
|
|
2262
|
+
return this.dbConnections.add(input);
|
|
2263
|
+
}
|
|
2264
|
+
updateDatabaseConnection(currentName, input) {
|
|
2265
|
+
return this.dbConnections.update(currentName, input);
|
|
2266
|
+
}
|
|
2267
|
+
removeDatabaseConnection(name) {
|
|
2268
|
+
return this.dbConnections.remove(name);
|
|
2269
|
+
}
|
|
2270
|
+
exportDatabaseConnections() {
|
|
2271
|
+
return this.dbConnections.exportConfig();
|
|
2272
|
+
}
|
|
2273
|
+
importDatabaseConnections(input, conflict) {
|
|
2274
|
+
return this.dbConnections.importConfig(input, conflict);
|
|
2275
|
+
}
|
|
2276
|
+
testDatabaseConnection(name) {
|
|
2277
|
+
return this.dbConnections.test(name);
|
|
2278
|
+
}
|
|
2279
|
+
listDatabaseDatabases(name) {
|
|
2280
|
+
return this.dbConnections.listDatabases(name);
|
|
2281
|
+
}
|
|
2282
|
+
listDatabaseTables(name, database) {
|
|
2283
|
+
return this.dbConnections.listTables(name, database);
|
|
2284
|
+
}
|
|
2285
|
+
browseDatabaseTable(name, table, page, pageSize, database) {
|
|
2286
|
+
return this.dbConnections.browseTable(name, table, page, pageSize, database);
|
|
2287
|
+
}
|
|
2235
2288
|
dispose(sessionId) {
|
|
2236
2289
|
// Mark disposed first so a late materialization never registers ready.
|
|
2237
2290
|
this.disposedSessions.add(sessionId);
|
|
@@ -2239,6 +2292,11 @@ export class ConsolePiRuntime {
|
|
|
2239
2292
|
this.sessionInit.delete(sessionId);
|
|
2240
2293
|
this.compactionControllers.delete(sessionId);
|
|
2241
2294
|
this.siftStates.delete(sessionId);
|
|
2295
|
+
for (const key of this.operatorCustomToolsBySession.keys()) {
|
|
2296
|
+
if (key.startsWith(`${sessionId}:`)) {
|
|
2297
|
+
this.operatorCustomToolsBySession.delete(key);
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2242
2300
|
const session = this.sessions.get(sessionId);
|
|
2243
2301
|
if (session) {
|
|
2244
2302
|
try {
|
|
@@ -2269,6 +2327,8 @@ export class ConsolePiRuntime {
|
|
|
2269
2327
|
void this.exploreOrchestrator.abortAll();
|
|
2270
2328
|
if (this.ownsBrowserAutomation)
|
|
2271
2329
|
void this.browserAutomation.dispose();
|
|
2330
|
+
if (this.ownsDbConnections)
|
|
2331
|
+
this.dbConnections.dispose();
|
|
2272
2332
|
}
|
|
2273
2333
|
}
|
|
2274
2334
|
function mapAssistantMessageEvent(type, sessionId, message) {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import { randomUUID } from "node:crypto";
|
|
16
16
|
import { access } from "node:fs/promises";
|
|
17
17
|
import { parseAssistantContent } from "./assistant-content.js";
|
|
18
|
-
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, } from "./tools.js";
|
|
18
|
+
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, OPERATOR_CHAT_SQL_TOOL_CAPABILITIES, } from "./tools.js";
|
|
19
19
|
import { InvalidChatSessionModeError, SESSION_MODE_ACTION_DENIED_CODE, SESSION_MODE_ACTION_DENIED_MESSAGE, SESSION_MODE_IMMUTABLE_CODE, UnknownChatSessionModeError, isWorkflowSessionMode, parseCreateSessionMode, readStoredSessionMode, shouldAcceptOperatorSnapshot, } from "./session-mode.js";
|
|
20
20
|
import { buildModelCallableToolSchemas } from "./tool-adapter.js";
|
|
21
21
|
import { cleanChatTitle, acceptedOperationIdFromResult, isBlankChatSession } from "./session-store.js";
|
|
@@ -49,6 +49,7 @@ import { TerminalSessionRegistry } from "./terminal-sessions.js";
|
|
|
49
49
|
import { handleTerminalRequest } from "./terminal-routes.js";
|
|
50
50
|
import { handleScmRequest } from "./scm-routes.js";
|
|
51
51
|
import { handleBrowserRequest } from "./browser-routes.js";
|
|
52
|
+
import { DbConnectionError } from "./db-connections.js";
|
|
52
53
|
function projectBrowserChatSession(record) {
|
|
53
54
|
const { telemetrySessionId, ...projected } = record;
|
|
54
55
|
void telemetrySessionId;
|
|
@@ -606,6 +607,7 @@ export async function handleChatCapabilities(_req, res, deps) {
|
|
|
606
607
|
deniedTools: OPERATOR_CHAT_DENIED_TOOLS,
|
|
607
608
|
deniedOperatorActions: OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS,
|
|
608
609
|
tools: toolSchemas,
|
|
610
|
+
builtinCustomTools: OPERATOR_CHAT_SQL_TOOL_CAPABILITIES,
|
|
609
611
|
builtinSubagents: [
|
|
610
612
|
{
|
|
611
613
|
toolId: "Agent",
|
|
@@ -981,6 +983,9 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
|
|
|
981
983
|
const lastEvent = snapshot.at(-1);
|
|
982
984
|
const activeTurn = deps.events.getActiveTurn(sessionId);
|
|
983
985
|
const pendingQuestion = await deps.questionRegistry?.get(sessionId);
|
|
986
|
+
const sddSessionIdentity = deps.sddDataAlignment && (await deps.sddDataAlignment.isEligible())
|
|
987
|
+
? { telemetrySessionId: record.telemetrySessionId ?? null }
|
|
988
|
+
: undefined;
|
|
984
989
|
sendJson(res, 200, {
|
|
985
990
|
ok: true,
|
|
986
991
|
eventEpoch: deps.events.epoch(sessionId),
|
|
@@ -1006,6 +1011,9 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
|
|
|
1006
1011
|
sessionStats: telemetry.stats,
|
|
1007
1012
|
usage: telemetry.usage,
|
|
1008
1013
|
turnTelemetry: deriveChatTurnTelemetry(snapshot),
|
|
1014
|
+
...(sddSessionIdentity
|
|
1015
|
+
? { sddDataAlignment: sddSessionIdentity }
|
|
1016
|
+
: {}),
|
|
1009
1017
|
contextPressure: typeof deps.runtime.getContextPressureTelemetry === "function"
|
|
1010
1018
|
? deps.runtime.getContextPressureTelemetry(sessionId)
|
|
1011
1019
|
: undefined,
|
|
@@ -2669,6 +2677,7 @@ export async function handleChatEventsStream(req, res, deps, sessionId) {
|
|
|
2669
2677
|
kind: "stream_ready",
|
|
2670
2678
|
sessionId,
|
|
2671
2679
|
epoch: deps.events.epoch(sessionId),
|
|
2680
|
+
lastSeq: deps.events.latestSeq(sessionId),
|
|
2672
2681
|
latestEventId: retainedTail?.eventId ?? null,
|
|
2673
2682
|
});
|
|
2674
2683
|
let closed = false;
|
|
@@ -2973,7 +2982,20 @@ async function handleSddBingo(req, res, deps, sessionId) {
|
|
|
2973
2982
|
throw new SddDataAlignmentError("SDD_INVALID_SKILL_NAME", "请求体只允许 skillName 字段", 400);
|
|
2974
2983
|
}
|
|
2975
2984
|
const result = await deps.sddDataAlignment.report(sessionId, body.skillName);
|
|
2976
|
-
|
|
2985
|
+
deps.events.append(sessionId, deps.events.latestTurnId(sessionId) ?? `${sessionId}:operator-action`, {
|
|
2986
|
+
kind: "operator-action",
|
|
2987
|
+
data: {
|
|
2988
|
+
schemaVersion: 1,
|
|
2989
|
+
action: "sdd-bingo",
|
|
2990
|
+
skillName: result.skillName,
|
|
2991
|
+
telemetrySessionId: result.telemetrySessionId,
|
|
2992
|
+
},
|
|
2993
|
+
});
|
|
2994
|
+
sendJson(res, 200, {
|
|
2995
|
+
ok: true,
|
|
2996
|
+
skillName: result.skillName,
|
|
2997
|
+
telemetrySessionId: result.telemetrySessionId,
|
|
2998
|
+
});
|
|
2977
2999
|
}
|
|
2978
3000
|
catch (error) {
|
|
2979
3001
|
if (error instanceof SddDataAlignmentError) {
|
|
@@ -3901,7 +3923,7 @@ async function handleDagHumanGate(req, res, deps, sessionId, step) {
|
|
|
3901
3923
|
: step === "confirm"
|
|
3902
3924
|
? "confirmDagConfirmation"
|
|
3903
3925
|
: "runDag";
|
|
3904
|
-
const result = await dispatchOperatorAction(ctx, {
|
|
3926
|
+
const result = await dispatchOperatorAction({ ...ctx, chatSessionRef: sessionId }, {
|
|
3905
3927
|
action,
|
|
3906
3928
|
actionParams: body,
|
|
3907
3929
|
clientRequestId: typeof body.clientRequestId === "string"
|
|
@@ -4279,6 +4301,24 @@ export async function handleChatRequest(req, res, deps, pathname, workspaceScope
|
|
|
4279
4301
|
throw error;
|
|
4280
4302
|
}
|
|
4281
4303
|
}
|
|
4304
|
+
function databaseConnectionInput(body, engine) {
|
|
4305
|
+
return {
|
|
4306
|
+
name: typeof body.name === "string" ? body.name : "",
|
|
4307
|
+
engine,
|
|
4308
|
+
...(typeof body.path === "string" ? { path: body.path } : {}),
|
|
4309
|
+
...(body.mode === "parameters" || body.mode === "url-env" ? { mode: body.mode } : {}),
|
|
4310
|
+
...(typeof body.urlEnv === "string" ? { urlEnv: body.urlEnv } : {}),
|
|
4311
|
+
...(typeof body.host === "string" ? { host: body.host } : {}),
|
|
4312
|
+
...(typeof body.port === "number" ? { port: body.port } : {}),
|
|
4313
|
+
...(typeof body.database === "string" ? { database: body.database } : {}),
|
|
4314
|
+
...(typeof body.username === "string" ? { username: body.username } : {}),
|
|
4315
|
+
...(body.passwordMode === "runtime" || body.passwordMode === "environment" || body.passwordMode === "encrypted" ? { passwordMode: body.passwordMode } : {}),
|
|
4316
|
+
...(typeof body.passwordRef === "string" ? { passwordRef: body.passwordRef } : {}),
|
|
4317
|
+
...(typeof body.passwordEnv === "string" ? { passwordEnv: body.passwordEnv } : {}),
|
|
4318
|
+
...(typeof body.password === "string" ? { password: body.password } : {}),
|
|
4319
|
+
...(typeof body.ssl === "boolean" ? { ssl: body.ssl } : {}),
|
|
4320
|
+
};
|
|
4321
|
+
}
|
|
4282
4322
|
async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
|
|
4283
4323
|
// Terminal management API (model + Console UI shared PTY registry).
|
|
4284
4324
|
if (await handleTerminalRequest(req, res, {
|
|
@@ -4358,6 +4398,117 @@ async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
|
|
|
4358
4398
|
await handleChatCapabilities(req, res, deps);
|
|
4359
4399
|
return true;
|
|
4360
4400
|
}
|
|
4401
|
+
if (method === "GET" && pathname === "/api/operator/v1/chat/database-connections/export") {
|
|
4402
|
+
sendJson(res, 200, { ok: true, document: deps.runtime.exportDatabaseConnections() });
|
|
4403
|
+
return true;
|
|
4404
|
+
}
|
|
4405
|
+
if (method === "POST" && pathname === "/api/operator/v1/chat/database-connections/import") {
|
|
4406
|
+
const gate = gateMutation(req, deps);
|
|
4407
|
+
if (!gate.ok) {
|
|
4408
|
+
sendJson(res, gate.status, { ok: false, error: { code: gate.code, message: gate.message } });
|
|
4409
|
+
return true;
|
|
4410
|
+
}
|
|
4411
|
+
try {
|
|
4412
|
+
const body = await readJsonBody(req);
|
|
4413
|
+
const conflict = body.conflict === "overwrite" ? "overwrite" : "skip";
|
|
4414
|
+
const result = await deps.runtime.importDatabaseConnections(body.document, conflict);
|
|
4415
|
+
sendJson(res, 200, { ok: true, result });
|
|
4416
|
+
}
|
|
4417
|
+
catch (error) {
|
|
4418
|
+
const code = error instanceof DbConnectionError ? error.code : "DB_PERSISTENCE_ERROR";
|
|
4419
|
+
const status = code === "DB_PERSISTENCE_ERROR" ? 500 : 400;
|
|
4420
|
+
sendJson(res, status, { ok: false, error: { code, message: error instanceof Error ? error.message : String(error) } });
|
|
4421
|
+
}
|
|
4422
|
+
return true;
|
|
4423
|
+
}
|
|
4424
|
+
if (pathname === "/api/operator/v1/chat/database-connections" &&
|
|
4425
|
+
(method === "GET" || method === "POST")) {
|
|
4426
|
+
if (method === "GET") {
|
|
4427
|
+
sendJson(res, 200, { ok: true, connections: deps.runtime.listDatabaseConnections() });
|
|
4428
|
+
return true;
|
|
4429
|
+
}
|
|
4430
|
+
const gate = gateMutation(req, deps);
|
|
4431
|
+
if (!gate.ok) {
|
|
4432
|
+
sendJson(res, gate.status, { ok: false, error: { code: gate.code, message: gate.message } });
|
|
4433
|
+
return true;
|
|
4434
|
+
}
|
|
4435
|
+
try {
|
|
4436
|
+
const body = await readJsonBody(req);
|
|
4437
|
+
const engine = body.engine;
|
|
4438
|
+
if (engine !== "sqlite" && engine !== "postgres" && engine !== "mysql") {
|
|
4439
|
+
throw new DbConnectionError("DB_INVALID_CONFIG", "engine must be sqlite, postgres, or mysql");
|
|
4440
|
+
}
|
|
4441
|
+
const connection = await deps.runtime.addDatabaseConnection(databaseConnectionInput(body, engine));
|
|
4442
|
+
sendJson(res, 201, { ok: true, connection });
|
|
4443
|
+
}
|
|
4444
|
+
catch (error) {
|
|
4445
|
+
const code = error instanceof DbConnectionError ? error.code : "DB_PERSISTENCE_ERROR";
|
|
4446
|
+
const status = code === "DB_PERSISTENCE_ERROR" ? 500 : 400;
|
|
4447
|
+
sendJson(res, status, { ok: false, error: { code, message: error instanceof Error ? error.message : String(error) } });
|
|
4448
|
+
}
|
|
4449
|
+
return true;
|
|
4450
|
+
}
|
|
4451
|
+
const databaseBrowseRoute = pathname.match(/^\/api\/operator\/v1\/chat\/database-connections\/([^/]+)\/browse$/);
|
|
4452
|
+
if (databaseBrowseRoute && method === "GET") {
|
|
4453
|
+
const name = decodeURIComponent(databaseBrowseRoute[1]);
|
|
4454
|
+
try {
|
|
4455
|
+
const table = url.searchParams.get("table")?.trim();
|
|
4456
|
+
const database = url.searchParams.get("database")?.trim() || undefined;
|
|
4457
|
+
if (!table) {
|
|
4458
|
+
const databases = await deps.runtime.listDatabaseDatabases(name);
|
|
4459
|
+
const connection = deps.runtime.listDatabaseConnections().find((item) => item.name === name);
|
|
4460
|
+
const shouldLoadTables = connection?.engine === "sqlite" || Boolean(database || connection?.database);
|
|
4461
|
+
sendJson(res, 200, { ok: true, connection: name, database, databases, tables: shouldLoadTables ? await deps.runtime.listDatabaseTables(name, database) : [] });
|
|
4462
|
+
}
|
|
4463
|
+
else {
|
|
4464
|
+
const page = Number(url.searchParams.get("page") ?? "1");
|
|
4465
|
+
const pageSize = Number(url.searchParams.get("pageSize") ?? "50");
|
|
4466
|
+
sendJson(res, 200, { ok: true, result: await deps.runtime.browseDatabaseTable(name, table, page, pageSize, database) });
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
catch (error) {
|
|
4470
|
+
const code = error instanceof DbConnectionError ? error.code : "DB_ENGINE_ERROR";
|
|
4471
|
+
const status = code === "DB_CONNECTION_NOT_FOUND" ? 404 : 400;
|
|
4472
|
+
sendJson(res, status, { ok: false, error: { code, message: error instanceof Error ? error.message : String(error) } });
|
|
4473
|
+
}
|
|
4474
|
+
return true;
|
|
4475
|
+
}
|
|
4476
|
+
const databaseConnectionRoute = pathname.match(/^\/api\/operator\/v1\/chat\/database-connections\/([^/]+)(?:\/(test))?$/);
|
|
4477
|
+
if (databaseConnectionRoute && (method === "DELETE" || method === "POST" || method === "PATCH")) {
|
|
4478
|
+
const gate = gateMutation(req, deps);
|
|
4479
|
+
if (!gate.ok) {
|
|
4480
|
+
sendJson(res, gate.status, { ok: false, error: { code: gate.code, message: gate.message } });
|
|
4481
|
+
return true;
|
|
4482
|
+
}
|
|
4483
|
+
const name = decodeURIComponent(databaseConnectionRoute[1]);
|
|
4484
|
+
try {
|
|
4485
|
+
if (method === "POST" && databaseConnectionRoute[2] === "test") {
|
|
4486
|
+
sendJson(res, 200, { ok: true, result: await deps.runtime.testDatabaseConnection(name) });
|
|
4487
|
+
}
|
|
4488
|
+
else if (method === "PATCH" && !databaseConnectionRoute[2]) {
|
|
4489
|
+
const body = await readJsonBody(req);
|
|
4490
|
+
const engine = body.engine;
|
|
4491
|
+
if (engine !== "sqlite" && engine !== "postgres" && engine !== "mysql") {
|
|
4492
|
+
throw new DbConnectionError("DB_INVALID_CONFIG", "engine must be sqlite, postgres, or mysql");
|
|
4493
|
+
}
|
|
4494
|
+
const connection = await deps.runtime.updateDatabaseConnection(name, databaseConnectionInput(body, engine));
|
|
4495
|
+
sendJson(res, 200, { ok: true, connection });
|
|
4496
|
+
}
|
|
4497
|
+
else if (method === "DELETE" && !databaseConnectionRoute[2]) {
|
|
4498
|
+
await deps.runtime.removeDatabaseConnection(name);
|
|
4499
|
+
sendJson(res, 200, { ok: true });
|
|
4500
|
+
}
|
|
4501
|
+
else {
|
|
4502
|
+
sendJson(res, 405, { ok: false, error: { code: "METHOD_NOT_ALLOWED", message: "method not allowed" } });
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4505
|
+
catch (error) {
|
|
4506
|
+
const code = error instanceof DbConnectionError ? error.code : "DB_ENGINE_ERROR";
|
|
4507
|
+
const status = code === "DB_CONNECTION_NOT_FOUND" ? 404 : code === "DB_PERSISTENCE_ERROR" ? 500 : 400;
|
|
4508
|
+
sendJson(res, status, { ok: false, error: { code, message: error instanceof Error ? error.message : String(error) } });
|
|
4509
|
+
}
|
|
4510
|
+
return true;
|
|
4511
|
+
}
|
|
4361
4512
|
const htmlPreviewRoute = matchRepoHtmlPreviewRoute(pathname);
|
|
4362
4513
|
if (method === "GET" && htmlPreviewRoute) {
|
|
4363
4514
|
if (!htmlPreviewRoute.rawPath)
|
|
@@ -2,6 +2,8 @@ import { createDecipheriv, randomBytes } from "node:crypto";
|
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import { injectWizardLocalTelemetryHeaders, } from "../../../shared/wizard-local-telemetry.js";
|
|
6
|
+
export { WIZARD_LOCAL_DEFAULT_USER_AGENT, } from "../../../shared/wizard-local-telemetry.js";
|
|
5
7
|
export const SDD_SKILL_NAMES = [
|
|
6
8
|
"SDD-design-analysis",
|
|
7
9
|
"SDD-implementation-test-review",
|
|
@@ -14,7 +16,6 @@ export const SDD_TELEMETRY_URL = "https://wizard-ai.paic.com.cn/code_pilot/api/s
|
|
|
14
16
|
export const DEFAULT_AI_MA_PUB_SALT_KEY = "52aad0c09e6b46818a11ee702d6fe0ba";
|
|
15
17
|
export const SDD_TELEMETRY_SIGN = DEFAULT_AI_MA_PUB_SALT_KEY;
|
|
16
18
|
export const AIMAX_AUTH_TOKEN_ENV = "AIMAX_AUTH_TOKEN";
|
|
17
|
-
export const WIZARD_LOCAL_DEFAULT_USER_AGENT = "Builder/OpenCode ai-sdk/provider-utils/4.0.21 runtime/bun/1.3.11";
|
|
18
19
|
const SM4_V1_PREFIX = "sm4:v1:";
|
|
19
20
|
/** Decode a plaintext ticket or `sm4:v1:` ciphertext. Unknown prefixes and crypto errors fail closed. */
|
|
20
21
|
export function decodeAimaxAuthToken(raw, keyHex = DEFAULT_AI_MA_PUB_SALT_KEY) {
|
|
@@ -215,7 +216,7 @@ export class SddDataAlignmentService {
|
|
|
215
216
|
if (!response.ok || body?.ret !== 0 || body.succ !== true) {
|
|
216
217
|
throw new SddDataAlignmentError("SDD_UPSTREAM_FAILED", "SDD 数据对齐上报失败", 502);
|
|
217
218
|
}
|
|
218
|
-
return { skillName };
|
|
219
|
+
return { skillName, telemetrySessionId };
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
222
|
async function readBoundedTelemetryJson(response) {
|
|
@@ -251,39 +252,15 @@ async function readBoundedTelemetryJson(response) {
|
|
|
251
252
|
reader.releaseLock();
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
|
-
function deleteHeaderCaseInsensitive(headers, name) {
|
|
255
|
-
for (const key of Object.keys(headers))
|
|
256
|
-
if (key.toLowerCase() === name.toLowerCase())
|
|
257
|
-
delete headers[key];
|
|
258
|
-
}
|
|
259
|
-
function configuredHeader(headers, name) {
|
|
260
|
-
const key = Object.keys(headers ?? {}).find((entry) => entry.toLowerCase() === name.toLowerCase());
|
|
261
|
-
return key ? headers?.[key] : undefined;
|
|
262
|
-
}
|
|
263
|
-
function setStaticHeader(headers, configured, name, defaultValue) {
|
|
264
|
-
deleteHeaderCaseInsensitive(headers, name);
|
|
265
|
-
headers[name] = configuredHeader(configured, name) ?? defaultValue;
|
|
266
|
-
}
|
|
267
255
|
export async function injectWizardLocalHeaders(options) {
|
|
268
256
|
const model = options.context.model;
|
|
269
257
|
if (model?.provider !== "wizard-local" || !model.id)
|
|
270
258
|
return;
|
|
271
259
|
if (!(await options.service.isEligible()))
|
|
272
260
|
return;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
// SDK path fail closed and silently drop all custom headers.
|
|
279
|
-
const auth = await modelRegistry.getApiKeyAndHeaders(model);
|
|
280
|
-
if (!auth.ok || typeof auth.apiKey !== "string" || !auth.apiKey)
|
|
281
|
-
return;
|
|
282
|
-
setStaticHeader(options.headers, auth.headers, "client-code", "OpenCode");
|
|
283
|
-
setStaticHeader(options.headers, auth.headers, "User-Agent", WIZARD_LOCAL_DEFAULT_USER_AGENT);
|
|
284
|
-
for (const name of ["x-api-key", "X-Session-Id", "X-Model-Id"])
|
|
285
|
-
deleteHeaderCaseInsensitive(options.headers, name);
|
|
286
|
-
options.headers["x-api-key"] = auth.apiKey;
|
|
287
|
-
options.headers["X-Session-Id"] = await options.service.ensureTelemetrySessionId(options.sessionId);
|
|
288
|
-
options.headers["X-Model-Id"] = model.id;
|
|
261
|
+
await injectWizardLocalTelemetryHeaders({
|
|
262
|
+
headers: options.headers,
|
|
263
|
+
context: options.context,
|
|
264
|
+
telemetrySessionId: await options.service.ensureTelemetrySessionId(options.sessionId),
|
|
265
|
+
});
|
|
289
266
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Repair only a local submission pair after the ordinary stable sort.
|
|
2
|
+
* A pair-specific comparator would be non-transitive when a third row falls
|
|
3
|
+
* between the user and placeholder, so this bounded pass moves the user back
|
|
4
|
+
* to the placeholder's established timeline seat instead. */
|
|
5
|
+
export function ensureLinkedSubmissionOrder(messages) {
|
|
6
|
+
const next = [...messages];
|
|
7
|
+
for (let assistantIndex = 0; assistantIndex < next.length; assistantIndex += 1) {
|
|
8
|
+
const assistant = next[assistantIndex];
|
|
9
|
+
if (assistant?.role !== "assistant" || !assistant.clientRequestId)
|
|
10
|
+
continue;
|
|
11
|
+
const userIndex = next.findIndex((message, index) => index > assistantIndex &&
|
|
12
|
+
message.role === "user" &&
|
|
13
|
+
message.clientRequestId === assistant.clientRequestId);
|
|
14
|
+
if (userIndex < 0)
|
|
15
|
+
continue;
|
|
16
|
+
const [user] = next.splice(userIndex, 1);
|
|
17
|
+
if (user)
|
|
18
|
+
next.splice(assistantIndex, 0, user);
|
|
19
|
+
assistantIndex += 1;
|
|
20
|
+
}
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
@@ -20,6 +20,39 @@ import { OFFICIAL_DENIED_TOOL_IDS } from "../resource-loader.js";
|
|
|
20
20
|
import { EXECUTABLE_GATE_ONLY_ACTIONS } from "./tool-adapter.js";
|
|
21
21
|
import { OPERATOR_CHAT_AGENT_TOOL_NAME } from "./subagents/types.js";
|
|
22
22
|
const EXECUTABLE_GATE_ONLY = new Set(EXECUTABLE_GATE_ONLY_ACTIONS);
|
|
23
|
+
/** Server-owned metadata for SQL custom tools advertised to the Console UI. */
|
|
24
|
+
export const OPERATOR_CHAT_SQL_TOOL_CAPABILITIES = Object.freeze([
|
|
25
|
+
{
|
|
26
|
+
toolId: "sql_query",
|
|
27
|
+
description: "对命名数据库连接执行受限只读 SQL 查询。",
|
|
28
|
+
kind: "read",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
toolId: "sql_exec",
|
|
32
|
+
description: "已禁用:数据库连接强制只读,拒绝 DELETE、DROP 及所有写入或 DDL。",
|
|
33
|
+
kind: "read",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
toolId: "sql_schema",
|
|
37
|
+
description: "查看数据库表及字段结构。",
|
|
38
|
+
kind: "read",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
toolId: "sql_stats",
|
|
42
|
+
description: "查看数据库表行数和存储规模统计。",
|
|
43
|
+
kind: "read",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
toolId: "sql_health",
|
|
47
|
+
description: "检查数据库连接健康状态与安全配置。",
|
|
48
|
+
kind: "read",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
toolId: "sql_connections",
|
|
52
|
+
description: "列出、新增或移除受治理的命名数据库连接。",
|
|
53
|
+
kind: "mutation",
|
|
54
|
+
},
|
|
55
|
+
]);
|
|
23
56
|
/** Built-in Chat custom tools that are not operator registry actions. */
|
|
24
57
|
export const OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS = Object.freeze([
|
|
25
58
|
OPERATOR_CHAT_AGENT_TOOL_NAME,
|
|
@@ -35,6 +68,7 @@ export const OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS = Object.freeze([
|
|
|
35
68
|
"browser_dialog",
|
|
36
69
|
"browser_wait",
|
|
37
70
|
"browser_screenshot",
|
|
71
|
+
...OPERATOR_CHAT_SQL_TOOL_CAPABILITIES.map((tool) => tool.toolId),
|
|
38
72
|
]);
|
|
39
73
|
/**
|
|
40
74
|
* Actions the model MAY invoke. Derived from the registry but filtered by the
|