neuralos 3.3.9 → 3.4.1
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/bin/gybackend.cjs
CHANGED
|
@@ -258528,6 +258528,81 @@ var init_HistorySqliteStore = __esm({
|
|
|
258528
258528
|
});
|
|
258529
258529
|
})();
|
|
258530
258530
|
}
|
|
258531
|
+
/**
|
|
258532
|
+
* v3.4.1: append only the NEW messages for a session instead of rewriting
|
|
258533
|
+
* the whole session. saveUiSessions() deletes every row and re-inserts the
|
|
258534
|
+
* entire message list — on a long session that is a large synchronous
|
|
258535
|
+
* better-sqlite3 transaction on the main event loop, which is the
|
|
258536
|
+
* spinning-wheel freeze. This method appends from a given position in one
|
|
258537
|
+
* small transaction, so a debounced flush costs O(new messages), not
|
|
258538
|
+
* O(all messages).
|
|
258539
|
+
*
|
|
258540
|
+
* Returns the number of rows appended.
|
|
258541
|
+
*/
|
|
258542
|
+
appendUiSessionMessages(sessionId, messages, fromPosition, summary) {
|
|
258543
|
+
if (messages.length === 0 || fromPosition >= messages.length) {
|
|
258544
|
+
return 0;
|
|
258545
|
+
}
|
|
258546
|
+
const upsertSession = this.db.prepare(
|
|
258547
|
+
`INSERT INTO ui_sessions (
|
|
258548
|
+
id, title, updated_at, messages_count, last_message_preview
|
|
258549
|
+
) VALUES (
|
|
258550
|
+
@id, @title, @updatedAt, @messagesCount, @lastMessagePreview
|
|
258551
|
+
)
|
|
258552
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
258553
|
+
title = excluded.title,
|
|
258554
|
+
updated_at = excluded.updated_at,
|
|
258555
|
+
messages_count = excluded.messages_count,
|
|
258556
|
+
last_message_preview = excluded.last_message_preview`
|
|
258557
|
+
);
|
|
258558
|
+
const insertMessage = this.db.prepare(
|
|
258559
|
+
`INSERT INTO ui_session_messages (
|
|
258560
|
+
session_id, position, ui_message_id, backend_message_id, role, message_type, content, metadata_json, timestamp, streaming
|
|
258561
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
258562
|
+
);
|
|
258563
|
+
const slice = messages.slice(fromPosition);
|
|
258564
|
+
this.db.transaction(() => {
|
|
258565
|
+
if (summary) {
|
|
258566
|
+
upsertSession.run({
|
|
258567
|
+
id: sessionId,
|
|
258568
|
+
title: summary.title,
|
|
258569
|
+
updatedAt: summary.updatedAt,
|
|
258570
|
+
messagesCount: summary.messagesCount,
|
|
258571
|
+
lastMessagePreview: summary.lastMessagePreview
|
|
258572
|
+
});
|
|
258573
|
+
} else {
|
|
258574
|
+
const existing = this.db.prepare("SELECT title, updated_at FROM ui_sessions WHERE id = ?").get(sessionId);
|
|
258575
|
+
upsertSession.run({
|
|
258576
|
+
id: sessionId,
|
|
258577
|
+
title: existing?.title ?? "New Chat",
|
|
258578
|
+
updatedAt: Date.now(),
|
|
258579
|
+
messagesCount: (existing ? 0 : 0) + fromPosition + slice.length,
|
|
258580
|
+
lastMessagePreview: slice[slice.length - 1]?.content?.slice(0, 200) ?? ""
|
|
258581
|
+
});
|
|
258582
|
+
}
|
|
258583
|
+
for (let i = 0; i < slice.length; i++) {
|
|
258584
|
+
const message = slice[i];
|
|
258585
|
+
insertMessage.run(
|
|
258586
|
+
sessionId,
|
|
258587
|
+
fromPosition + i,
|
|
258588
|
+
message.id,
|
|
258589
|
+
message.backendMessageId ?? null,
|
|
258590
|
+
message.role,
|
|
258591
|
+
message.type,
|
|
258592
|
+
message.content,
|
|
258593
|
+
message.metadata ? JSON.stringify(message.metadata) : null,
|
|
258594
|
+
message.timestamp,
|
|
258595
|
+
message.streaming ? 1 : 0
|
|
258596
|
+
);
|
|
258597
|
+
}
|
|
258598
|
+
})();
|
|
258599
|
+
return slice.length;
|
|
258600
|
+
}
|
|
258601
|
+
/** v3.4.1: how many messages are already persisted for a session. */
|
|
258602
|
+
countUiSessionMessages(sessionId) {
|
|
258603
|
+
const row = this.db.prepare("SELECT COUNT(*) AS n FROM ui_session_messages WHERE session_id = ?").get(sessionId);
|
|
258604
|
+
return row?.n ?? 0;
|
|
258605
|
+
}
|
|
258531
258606
|
deleteUiSessions(sessionIds) {
|
|
258532
258607
|
const ids = Array.from(
|
|
258533
258608
|
new Set(sessionIds.filter((id) => id.trim().length > 0))
|
|
@@ -350712,12 +350787,12 @@ var BUILTIN_TOOL_INFO = [
|
|
|
350712
350787
|
{
|
|
350713
350788
|
name: "write_file",
|
|
350714
350789
|
description: WRITE_FILE_TOOL_DESCRIPTION,
|
|
350715
|
-
|
|
350790
|
+
shortDescription: "Write a full file (replace contents)"
|
|
350716
350791
|
},
|
|
350717
350792
|
{
|
|
350718
350793
|
name: "edit_file",
|
|
350719
350794
|
description: EDIT_FILE_TOOL_DESCRIPTION,
|
|
350720
|
-
|
|
350795
|
+
shortDescription: "Edit a file by replacing an exact string"
|
|
350721
350796
|
},
|
|
350722
350797
|
{
|
|
350723
350798
|
name: "skill",
|
|
@@ -354867,6 +354942,7 @@ var CORE_METHODS = [
|
|
|
354867
354942
|
m("tools:getMcp", "tools", "List MCP tools.", "1.0.0"),
|
|
354868
354943
|
m("tools:setMcpEnabled", "tools", "Enable/disable an MCP tool.", "1.0.0"),
|
|
354869
354944
|
m("tools:getBuiltIn", "tools", "List built-in agent tools with enabled state.", "1.0.0"),
|
|
354945
|
+
m("tools:getPlugins", "tools", "List plugin agent tools (name, plugin, description).", "3.4.0"),
|
|
354870
354946
|
m("tools:setBuiltInEnabled", "tools", "Enable/disable a built-in tool.", "1.0.0", { name: { type: "string" }, enabled: { type: "boolean" } })
|
|
354871
354947
|
];
|
|
354872
354948
|
var DESCRIBE_METHOD = m(
|
|
@@ -369458,6 +369534,7 @@ var AgentService_v2 = class {
|
|
|
369458
369534
|
pluginTools = /* @__PURE__ */ new Map();
|
|
369459
369535
|
/** Plugin tool schemas (for toolsForModel injection). */
|
|
369460
369536
|
pluginToolSchemas = [];
|
|
369537
|
+
pluginToolMeta = [];
|
|
369461
369538
|
passChatTempExportService = new PassChatTempExportService();
|
|
369462
369539
|
fallbackCompactionHistoryExportService = null;
|
|
369463
369540
|
activeAgentRunIdsBySession = /* @__PURE__ */ new Map();
|
|
@@ -369516,11 +369593,35 @@ var AgentService_v2 = class {
|
|
|
369516
369593
|
* pluginTools (so the dispatch switch's default case can call them). */
|
|
369517
369594
|
setPluginTools(tools2) {
|
|
369518
369595
|
this.pluginTools = new Map(tools2.map((t) => [t.name, t.handler]));
|
|
369519
|
-
this.
|
|
369596
|
+
this.pluginToolMeta = tools2.map((t) => ({
|
|
369520
369597
|
name: t.name,
|
|
369521
|
-
description: t.description,
|
|
369522
|
-
|
|
369598
|
+
description: t.description || t.name,
|
|
369599
|
+
plugin: t.plugin || "plugin"
|
|
369523
369600
|
}));
|
|
369601
|
+
this.pluginToolSchemas = tools2.map((t) => {
|
|
369602
|
+
const params = t.params && typeof t.params === "object" ? t.params : {};
|
|
369603
|
+
const looksJsonSchema = typeof params.type === "string";
|
|
369604
|
+
const parameters = looksJsonSchema ? params : {
|
|
369605
|
+
type: "object",
|
|
369606
|
+
properties: params,
|
|
369607
|
+
additionalProperties: true
|
|
369608
|
+
};
|
|
369609
|
+
return {
|
|
369610
|
+
type: "function",
|
|
369611
|
+
function: {
|
|
369612
|
+
name: t.name,
|
|
369613
|
+
description: t.description || t.name,
|
|
369614
|
+
parameters
|
|
369615
|
+
}
|
|
369616
|
+
};
|
|
369617
|
+
});
|
|
369618
|
+
}
|
|
369619
|
+
/** Plugin tools in OpenAI bindTools shape (empty until setPluginTools). */
|
|
369620
|
+
getPluginToolSchemas() {
|
|
369621
|
+
return this.pluginToolSchemas;
|
|
369622
|
+
}
|
|
369623
|
+
listPluginTools() {
|
|
369624
|
+
return this.pluginToolMeta.map((t) => ({ ...t, enabled: true }));
|
|
369524
369625
|
}
|
|
369525
369626
|
/** Wire a session-log handle so list_session_logs / read_session_log work. */
|
|
369526
369627
|
setSessionLogger(logger) {
|
|
@@ -370142,9 +370243,11 @@ var AgentService_v2 = class {
|
|
|
370142
370243
|
}
|
|
370143
370244
|
);
|
|
370144
370245
|
const baseModel = shouldUseThinkingModelOnThisPass ? sessionBinding.thinkingModel || sessionBinding.model : sessionBinding.model;
|
|
370246
|
+
const pluginOpenAiTools = this.pluginToolSchemas;
|
|
370145
370247
|
const modelWithTools = baseModel.bindTools([
|
|
370146
370248
|
...builtInTools,
|
|
370147
|
-
...mcpTools
|
|
370249
|
+
...mcpTools,
|
|
370250
|
+
...pluginOpenAiTools
|
|
370148
370251
|
]);
|
|
370149
370252
|
const messageId = v4_default();
|
|
370150
370253
|
let partialText = "";
|
|
@@ -370180,7 +370283,11 @@ var AgentService_v2 = class {
|
|
|
370180
370283
|
shouldUseThinkingModelOnThisPass ? 0.2 : 0.7,
|
|
370181
370284
|
null
|
|
370182
370285
|
);
|
|
370183
|
-
modelToUse = fallbackChat.bindTools([
|
|
370286
|
+
modelToUse = fallbackChat.bindTools([
|
|
370287
|
+
...builtInTools,
|
|
370288
|
+
...mcpTools,
|
|
370289
|
+
...pluginOpenAiTools
|
|
370290
|
+
]);
|
|
370184
370291
|
}
|
|
370185
370292
|
return await invokeWithRetryAndSanitizedInput({
|
|
370186
370293
|
helpers: this.helpers,
|
|
@@ -373372,16 +373479,84 @@ function buildUiSessionSummary(session) {
|
|
|
373372
373479
|
}
|
|
373373
373480
|
|
|
373374
373481
|
// ../../packages/backend/src/services/UIHistoryService.ts
|
|
373375
|
-
var UIHistoryService = class {
|
|
373482
|
+
var UIHistoryService = class _UIHistoryService {
|
|
373376
373483
|
store;
|
|
373377
373484
|
sessionsCache = {};
|
|
373378
373485
|
sessionSummaryCache = {};
|
|
373379
373486
|
dirtySessions = /* @__PURE__ */ new Set();
|
|
373487
|
+
/**
|
|
373488
|
+
* v3.4.1: debounced auto-flush. Previously recordEvent() marked a session
|
|
373489
|
+
* dirty but NEVER flushed — messages reached SQLite only on rename /
|
|
373490
|
+
* rollback / branch or a graceful app close. Kill the process mid-run
|
|
373491
|
+
* (freeze, crash, force-quit) and every message since the last flush was
|
|
373492
|
+
* lost. That is the "work done, no record" bug.
|
|
373493
|
+
*
|
|
373494
|
+
* Now: flush within FLUSH_DEBOUNCE_MS of the last event, plus a synchronous
|
|
373495
|
+
* flush on beforeExit / SIGINT / SIGTERM.
|
|
373496
|
+
*/
|
|
373497
|
+
flushTimer = null;
|
|
373498
|
+
shutdownHooksInstalled = false;
|
|
373499
|
+
/** v3.4.1: messages already written to SQLite per session, so flush()
|
|
373500
|
+
* appends only the new ones instead of rewriting the whole session. */
|
|
373501
|
+
persistedMessageCount = /* @__PURE__ */ new Map();
|
|
373502
|
+
/** Flush debounce window — short enough to survive a crash, long enough
|
|
373503
|
+
* to batch a streaming burst into one write. */
|
|
373504
|
+
static FLUSH_DEBOUNCE_MS = 1500;
|
|
373380
373505
|
constructor(options) {
|
|
373381
373506
|
this.store = options?.store || new HistorySqliteStore();
|
|
373382
373507
|
this.sessionSummaryCache = this.buildSessionSummaryCache(
|
|
373383
373508
|
this.store.listUiSessionSummaries()
|
|
373384
373509
|
);
|
|
373510
|
+
this.installShutdownHooks();
|
|
373511
|
+
}
|
|
373512
|
+
installShutdownHooks() {
|
|
373513
|
+
if (this.shutdownHooksInstalled) return;
|
|
373514
|
+
this.shutdownHooksInstalled = true;
|
|
373515
|
+
const flushNow = () => {
|
|
373516
|
+
try {
|
|
373517
|
+
this.flush();
|
|
373518
|
+
} catch {
|
|
373519
|
+
}
|
|
373520
|
+
};
|
|
373521
|
+
process.once("beforeExit", flushNow);
|
|
373522
|
+
for (const sig of ["SIGINT", "SIGTERM"]) {
|
|
373523
|
+
if (!_UIHistoryService.activeFlushOnSignal.has(sig)) {
|
|
373524
|
+
_UIHistoryService.activeFlushOnSignal.add(sig);
|
|
373525
|
+
const hadListeners = process.listenerCount(sig) > 0;
|
|
373526
|
+
process.once(sig, () => {
|
|
373527
|
+
for (const svc of _UIHistoryService.instances) {
|
|
373528
|
+
try {
|
|
373529
|
+
svc.flush();
|
|
373530
|
+
} catch {
|
|
373531
|
+
}
|
|
373532
|
+
}
|
|
373533
|
+
_UIHistoryService.activeFlushOnSignal.delete(sig);
|
|
373534
|
+
if (!hadListeners) {
|
|
373535
|
+
process.kill(process.pid, sig);
|
|
373536
|
+
}
|
|
373537
|
+
});
|
|
373538
|
+
}
|
|
373539
|
+
}
|
|
373540
|
+
_UIHistoryService.instances.add(this);
|
|
373541
|
+
}
|
|
373542
|
+
/** Live instances — the shared signal handler flushes all of them. */
|
|
373543
|
+
static instances = /* @__PURE__ */ new Set();
|
|
373544
|
+
static activeFlushOnSignal = /* @__PURE__ */ new Set();
|
|
373545
|
+
scheduleFlush() {
|
|
373546
|
+
if (this.flushTimer) {
|
|
373547
|
+
clearTimeout(this.flushTimer);
|
|
373548
|
+
}
|
|
373549
|
+
this.flushTimer = setTimeout(() => {
|
|
373550
|
+
this.flushTimer = null;
|
|
373551
|
+
try {
|
|
373552
|
+
this.flush();
|
|
373553
|
+
} catch (error40) {
|
|
373554
|
+
console.error("[UIHistory] auto-flush failed:", error40);
|
|
373555
|
+
}
|
|
373556
|
+
}, _UIHistoryService.FLUSH_DEBOUNCE_MS);
|
|
373557
|
+
if (typeof this.flushTimer.unref === "function") {
|
|
373558
|
+
this.flushTimer.unref();
|
|
373559
|
+
}
|
|
373385
373560
|
}
|
|
373386
373561
|
buildSessionSummaryCache(summaries) {
|
|
373387
373562
|
const cache2 = {};
|
|
@@ -373401,6 +373576,9 @@ var UIHistoryService = class {
|
|
|
373401
373576
|
}
|
|
373402
373577
|
const sanitized = sanitizeUiSession(loaded);
|
|
373403
373578
|
this.sessionsCache[sessionId] = sanitized;
|
|
373579
|
+
if (!this.persistedMessageCount.has(sessionId)) {
|
|
373580
|
+
this.persistedMessageCount.set(sessionId, sanitized.messages.length);
|
|
373581
|
+
}
|
|
373404
373582
|
this.syncSessionSummary(sessionId);
|
|
373405
373583
|
return sanitized;
|
|
373406
373584
|
}
|
|
@@ -373427,6 +373605,7 @@ var UIHistoryService = class {
|
|
|
373427
373605
|
const actions = this.processEvent(session, event, sessionId);
|
|
373428
373606
|
this.syncSessionSummary(sessionId);
|
|
373429
373607
|
this.dirtySessions.add(sessionId);
|
|
373608
|
+
this.scheduleFlush();
|
|
373430
373609
|
return actions;
|
|
373431
373610
|
}
|
|
373432
373611
|
flush(sessionId) {
|
|
@@ -373435,6 +373614,7 @@ var UIHistoryService = class {
|
|
|
373435
373614
|
return;
|
|
373436
373615
|
}
|
|
373437
373616
|
const entries = [];
|
|
373617
|
+
const appendFrom = {};
|
|
373438
373618
|
sessionIds.forEach((id) => {
|
|
373439
373619
|
const session = this.sessionsCache[id];
|
|
373440
373620
|
if (!session) {
|
|
@@ -373446,9 +373626,34 @@ var UIHistoryService = class {
|
|
|
373446
373626
|
const summary = buildUiSessionSummary(sanitized);
|
|
373447
373627
|
this.sessionSummaryCache[id] = summary;
|
|
373448
373628
|
entries.push({ session: sanitized, summary });
|
|
373629
|
+
const already = this.persistedMessageCount.get(id);
|
|
373630
|
+
appendFrom[id] = typeof already === "number" && already <= sanitized.messages.length ? already : 0;
|
|
373449
373631
|
});
|
|
373450
373632
|
if (entries.length > 0) {
|
|
373451
|
-
|
|
373633
|
+
let usedIncremental = false;
|
|
373634
|
+
try {
|
|
373635
|
+
let appended = 0;
|
|
373636
|
+
for (const { session, summary } of entries) {
|
|
373637
|
+
const from = appendFrom[session.id] ?? 0;
|
|
373638
|
+
const n2 = this.store.appendUiSessionMessages(
|
|
373639
|
+
session.id,
|
|
373640
|
+
session.messages,
|
|
373641
|
+
from,
|
|
373642
|
+
summary
|
|
373643
|
+
);
|
|
373644
|
+
appended += n2;
|
|
373645
|
+
this.persistedMessageCount.set(session.id, session.messages.length);
|
|
373646
|
+
}
|
|
373647
|
+
usedIncremental = true;
|
|
373648
|
+
} catch {
|
|
373649
|
+
usedIncremental = false;
|
|
373650
|
+
}
|
|
373651
|
+
if (!usedIncremental) {
|
|
373652
|
+
this.store.saveUiSessions(entries);
|
|
373653
|
+
entries.forEach(
|
|
373654
|
+
({ session }) => this.persistedMessageCount.set(session.id, session.messages.length)
|
|
373655
|
+
);
|
|
373656
|
+
}
|
|
373452
373657
|
}
|
|
373453
373658
|
sessionIds.forEach((id) => this.dirtySessions.delete(id));
|
|
373454
373659
|
}
|
|
@@ -373961,6 +374166,7 @@ Error: ${event.message}` : ""),
|
|
|
373961
374166
|
delete this.sessionsCache[id];
|
|
373962
374167
|
delete this.sessionSummaryCache[id];
|
|
373963
374168
|
this.dirtySessions.delete(id);
|
|
374169
|
+
this.persistedMessageCount.delete(id);
|
|
373964
374170
|
});
|
|
373965
374171
|
this.store.deleteUiSessions(ids);
|
|
373966
374172
|
}
|
|
@@ -373999,6 +374205,7 @@ Error: ${event.message}` : ""),
|
|
|
373999
374205
|
);
|
|
374000
374206
|
this.syncSessionSummary(sessionId);
|
|
374001
374207
|
this.dirtySessions.add(sessionId);
|
|
374208
|
+
this.persistedMessageCount.delete(sessionId);
|
|
374002
374209
|
this.flush(sessionId);
|
|
374003
374210
|
return removedCount;
|
|
374004
374211
|
}
|
|
@@ -376649,6 +376856,15 @@ var WebSocketGatewayAdapter = class {
|
|
|
376649
376856
|
}
|
|
376650
376857
|
return await this.options.toolsBridge.getBuiltIn();
|
|
376651
376858
|
}
|
|
376859
|
+
case "tools:getPlugins": {
|
|
376860
|
+
if (!this.options.toolsBridge?.getPlugins) {
|
|
376861
|
+
throw new WebSocketRpcError(
|
|
376862
|
+
"METHOD_NOT_FOUND",
|
|
376863
|
+
"tools:getPlugins is not available on this websocket gateway."
|
|
376864
|
+
);
|
|
376865
|
+
}
|
|
376866
|
+
return await this.options.toolsBridge.getPlugins();
|
|
376867
|
+
}
|
|
376652
376868
|
case "tools:setBuiltInEnabled": {
|
|
376653
376869
|
if (!this.options.toolsBridge?.setBuiltInEnabled) {
|
|
376654
376870
|
throw new WebSocketRpcError(
|
|
@@ -392577,6 +392793,23 @@ var PluginRegistry = class {
|
|
|
392577
392793
|
allTools() {
|
|
392578
392794
|
return this.list().filter((p) => p.enabled && !p.error).flatMap((p) => p.tools);
|
|
392579
392795
|
}
|
|
392796
|
+
/** Flatten enabled plugin tools for AgentService.setPluginTools. */
|
|
392797
|
+
collectAgentTools() {
|
|
392798
|
+
const out = [];
|
|
392799
|
+
for (const record2 of this.list()) {
|
|
392800
|
+
if (record2.error || !record2.enabled) continue;
|
|
392801
|
+
for (const tool2 of record2.tools) {
|
|
392802
|
+
out.push({
|
|
392803
|
+
name: tool2.name,
|
|
392804
|
+
description: tool2.description ?? "",
|
|
392805
|
+
params: tool2.params ?? {},
|
|
392806
|
+
handler: tool2.handler,
|
|
392807
|
+
plugin: record2.manifest.name
|
|
392808
|
+
});
|
|
392809
|
+
}
|
|
392810
|
+
}
|
|
392811
|
+
return out;
|
|
392812
|
+
}
|
|
392580
392813
|
/** All triggers from enabled plugins. */
|
|
392581
392814
|
allTriggers() {
|
|
392582
392815
|
return this.list().filter((p) => p.enabled && !p.error).flatMap((p) => p.triggers);
|
|
@@ -398016,25 +398249,15 @@ async function startGyBackend() {
|
|
|
398016
398249
|
Promise.race([
|
|
398017
398250
|
observability.pluginRegistry.reload(),
|
|
398018
398251
|
new Promise((_, reject) => setTimeout(() => reject(new Error("plugin reload timeout (10s)")), 1e4))
|
|
398019
|
-
]).then((
|
|
398020
|
-
const pluginTools =
|
|
398021
|
-
|
|
398022
|
-
|
|
398023
|
-
|
|
398024
|
-
|
|
398025
|
-
|
|
398026
|
-
description: tool2.description ?? "",
|
|
398027
|
-
params: tool2.params ?? {},
|
|
398028
|
-
handler: tool2.handler
|
|
398029
|
-
});
|
|
398030
|
-
}
|
|
398031
|
-
}
|
|
398032
|
-
if (pluginTools.length > 0) {
|
|
398033
|
-
agentService.setPluginTools(pluginTools);
|
|
398034
|
-
console.log(`[gybackend] Wired ${pluginTools.length} plugin tools from ${pluginRecords.filter((r) => !r.error && r.enabled).length} plugins into the agent.`);
|
|
398035
|
-
} else {
|
|
398036
|
-
console.log("[gybackend] No plugin tools found to wire.");
|
|
398252
|
+
]).then(() => {
|
|
398253
|
+
const pluginTools = observability.pluginRegistry.collectAgentTools();
|
|
398254
|
+
agentService.setPluginTools(pluginTools);
|
|
398255
|
+
const enabled = observability.pluginRegistry.list().filter((r) => !r.error && r.enabled).length;
|
|
398256
|
+
try {
|
|
398257
|
+
gatewayService.broadcastRaw("tools:pluginsUpdated", agentService.listPluginTools());
|
|
398258
|
+
} catch {
|
|
398037
398259
|
}
|
|
398260
|
+
console.log(`[gybackend] Wired ${pluginTools.length} plugin tools from ${enabled} plugins into the agent.`);
|
|
398038
398261
|
}).catch((e) => {
|
|
398039
398262
|
console.warn("[gybackend] Plugin tool wiring skipped:", e instanceof Error ? e.message : String(e));
|
|
398040
398263
|
});
|
|
@@ -398698,6 +398921,7 @@ async function startGyBackend() {
|
|
|
398698
398921
|
const settings = settingsService.getSettings();
|
|
398699
398922
|
return buildBuiltInToolStatusSummary(settings.tools?.builtIn);
|
|
398700
398923
|
},
|
|
398924
|
+
getPlugins: () => agentService.listPluginTools(),
|
|
398701
398925
|
setBuiltInEnabled: async (name, enabled) => {
|
|
398702
398926
|
const settings = settingsService.getSettings();
|
|
398703
398927
|
const nextBuiltIn = { ...settings.tools?.builtIn ?? {} };
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neuralos",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "AI-native terminal & agentic-AI operations platform for Forward Deployed Engineers & SREs: AIOps closed-loop remediation, AI SRE, self-healing infrastructure, runbook automation, ChatOps; executes over SSH/WinRM/serial under policy with tamper-evident audit.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"forward-deployed-engineer",
|