@geravant/sinain 1.18.2 → 1.19.0
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/cli.js +10 -0
- package/onboard.js +40 -10
- package/package.json +1 -1
- package/sinain-agent/agents.example.json +1 -1
- package/sinain-core/src/index.ts +10 -0
- package/sinain-core/src/server.ts +2 -2
package/cli.js
CHANGED
|
@@ -81,6 +81,13 @@ switch (cmd) {
|
|
|
81
81
|
await import("./install.js");
|
|
82
82
|
break;
|
|
83
83
|
|
|
84
|
+
case "mcp": {
|
|
85
|
+
const sub = process.argv[3]; // install | list | remove
|
|
86
|
+
const { runMcpCli } = await import("./mcp-register.js");
|
|
87
|
+
await runMcpCli(sub, process.argv.slice(4));
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
|
|
84
91
|
case "export-knowledge":
|
|
85
92
|
await exportKnowledge();
|
|
86
93
|
break;
|
|
@@ -396,6 +403,9 @@ Usage:
|
|
|
396
403
|
sinain export-knowledge Export knowledge for transfer to another machine
|
|
397
404
|
sinain import-knowledge <file> Import knowledge from export file
|
|
398
405
|
sinain install Install OpenClaw plugin (server-side)
|
|
406
|
+
sinain mcp install Register sinain MCP for your agents (Claude, Cursor, Codex, Goose, Junie)
|
|
407
|
+
sinain mcp list Show MCP registration status across agents
|
|
408
|
+
sinain mcp remove <agent> Unregister sinain MCP from one agent
|
|
399
409
|
|
|
400
410
|
Start options:
|
|
401
411
|
--no-sense Skip screen capture (sense_client)
|
package/onboard.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
stepApiKey, stepTranscription, stepGateway, stepPrivacy, stepModel,
|
|
13
13
|
HOME, SINAIN_DIR, ENV_PATH, PKG_DIR, IS_WINDOWS, IS_MAC,
|
|
14
14
|
} from "./config-shared.js";
|
|
15
|
+
import { stepMcpInstall, detectMcpAgents } from "./mcp-register.js";
|
|
15
16
|
|
|
16
17
|
// ── Header ──────────────────────────────────────────────────────────────────
|
|
17
18
|
|
|
@@ -138,7 +139,7 @@ export async function runOnboard(args = {}) {
|
|
|
138
139
|
initialValue: "quickstart",
|
|
139
140
|
}));
|
|
140
141
|
|
|
141
|
-
const totalSteps = flow === "quickstart" ? 2 :
|
|
142
|
+
const totalSteps = flow === "quickstart" ? 2 : 6;
|
|
142
143
|
|
|
143
144
|
// ── Collect vars ────────────────────────────────────────────────────────
|
|
144
145
|
|
|
@@ -180,7 +181,11 @@ export async function runOnboard(args = {}) {
|
|
|
180
181
|
|
|
181
182
|
agentsPatch = {
|
|
182
183
|
default: base.SINAIN_AGENT || "claude",
|
|
183
|
-
escalationMode
|
|
184
|
+
// No `escalationMode` written — lane (default agent) is the single
|
|
185
|
+
// source of truth for whether escalation runs. If the user picks a
|
|
186
|
+
// local agent (claude), the runtime's default mode ("rich" from
|
|
187
|
+
// config.ts) takes effect and registerBareAgent ensures lane and
|
|
188
|
+
// mode stay reconciled at boot.
|
|
184
189
|
};
|
|
185
190
|
|
|
186
191
|
if (enableGateway) {
|
|
@@ -207,9 +212,28 @@ export async function runOnboard(args = {}) {
|
|
|
207
212
|
].join("\n"),
|
|
208
213
|
"QuickStart defaults",
|
|
209
214
|
);
|
|
215
|
+
|
|
216
|
+
// QuickStart MCP install: a single confirm gated on at least one
|
|
217
|
+
// detected agent. Avoids interrupting users who don't have any
|
|
218
|
+
// MCP-aware agent installed. Re-runnable later via `sinain mcp install`.
|
|
219
|
+
try {
|
|
220
|
+
const detected = (await detectMcpAgents()).filter((a) => a.present);
|
|
221
|
+
if (detected.length > 0) {
|
|
222
|
+
const labels = detected.map((a) => a.label).join(", ");
|
|
223
|
+
const wantMcp = guard(await p.confirm({
|
|
224
|
+
message: `Detected ${labels} — register sinain MCP for them?`,
|
|
225
|
+
initialValue: true,
|
|
226
|
+
}));
|
|
227
|
+
if (wantMcp) {
|
|
228
|
+
await stepMcpInstall(base, "Connect MCP agents");
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
} catch (err) {
|
|
232
|
+
p.log.info(`Skipping MCP setup: ${err.message}`);
|
|
233
|
+
}
|
|
210
234
|
} else {
|
|
211
|
-
// Advanced flow: steps 2-
|
|
212
|
-
const transcription = await stepTranscription(base, "[2/
|
|
235
|
+
// Advanced flow: steps 2-6 (MCP install is step 6)
|
|
236
|
+
const transcription = await stepTranscription(base, "[2/6] Audio transcription");
|
|
213
237
|
vars.TRANSCRIPTION_BACKEND = transcription;
|
|
214
238
|
p.log.success(`Using ${transcription === "openrouter" ? "cloud" : "local"} transcription.`);
|
|
215
239
|
|
|
@@ -245,7 +269,7 @@ export async function runOnboard(args = {}) {
|
|
|
245
269
|
|
|
246
270
|
// stepGateway returns { envVars, agentsPatch }: tokens go to .env,
|
|
247
271
|
// URLs + session + escalation mode go to agents.json's openclaw profile.
|
|
248
|
-
const gatewayResult = await stepGateway(base, "[3/
|
|
272
|
+
const gatewayResult = await stepGateway(base, "[3/6] OpenClaw gateway");
|
|
249
273
|
Object.assign(vars, gatewayResult.envVars);
|
|
250
274
|
Object.assign(agentsPatch, gatewayResult.agentsPatch);
|
|
251
275
|
if (gatewayResult.agentsPatch.escalationMode === "off") {
|
|
@@ -254,17 +278,23 @@ export async function runOnboard(args = {}) {
|
|
|
254
278
|
p.log.success("Gateway configured.");
|
|
255
279
|
}
|
|
256
280
|
|
|
257
|
-
const privacy = await stepPrivacy(base, "[4/
|
|
281
|
+
const privacy = await stepPrivacy(base, "[4/6] Privacy mode");
|
|
258
282
|
vars.PRIVACY_MODE = privacy;
|
|
259
283
|
p.log.success(`Privacy: ${privacy}.`);
|
|
260
284
|
|
|
261
|
-
const model = await stepModel(base, "[5/
|
|
285
|
+
const model = await stepModel(base, "[5/6] AI model for HUD analysis");
|
|
262
286
|
vars.AGENT_MODEL = model;
|
|
263
287
|
p.log.success(`Model: ${model}.`);
|
|
264
288
|
|
|
265
289
|
// Default agent goes into agents.json `default` field (was SINAIN_AGENT
|
|
266
290
|
// env var). Overlay's chip selector lets the user switch at runtime.
|
|
267
291
|
agentsPatch.default = base.SINAIN_AGENT || "claude";
|
|
292
|
+
|
|
293
|
+
// Step 6: register sinain MCP with locally-installed MCP-aware agents
|
|
294
|
+
// (Claude Code, Cursor, Codex, Goose, Junie, Claude Desktop). Detection
|
|
295
|
+
// is non-destructive — if no agents are installed, the step prints a
|
|
296
|
+
// skip note and returns. Idempotent across re-runs.
|
|
297
|
+
await stepMcpInstall(base, "[6/6] Connect MCP agents");
|
|
268
298
|
}
|
|
269
299
|
|
|
270
300
|
// ── Common defaults ───────────────────────────────────────────────────
|
|
@@ -397,9 +427,9 @@ if (flags.nonInteractive) {
|
|
|
397
427
|
}
|
|
398
428
|
|
|
399
429
|
writeEnv(vars);
|
|
400
|
-
// Default agent +
|
|
401
|
-
//
|
|
402
|
-
writeAgentsConfig({ default: "claude",
|
|
430
|
+
// Default agent + openclaw explicitly disabled. No escalation mode written
|
|
431
|
+
// — lane is the source of truth, registerBareAgent reconciles at boot.
|
|
432
|
+
writeAgentsConfig({ default: "claude", openclawProfile: null });
|
|
403
433
|
console.log(c.green(` Config written to ${ENV_PATH} + ~/.sinain/agents.json`));
|
|
404
434
|
process.exit(0);
|
|
405
435
|
} else {
|
package/package.json
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
|
|
66
66
|
"escalation": {
|
|
67
|
-
"
|
|
67
|
+
"_comment": "Lane (the agent picked for escalation in agents.json `default` or via the overlay chip) is the source of truth for whether escalation runs. `mode` is intentionally omitted here — the runtime default (rich) applies, and registerBareAgent reconciles mode with lane at boot. Override `mode` only if you want to force selective/focus/off semantics.",
|
|
68
68
|
"cooldownMs": 30000,
|
|
69
69
|
"staleMs": 90000
|
|
70
70
|
},
|
package/sinain-core/src/index.ts
CHANGED
|
@@ -734,6 +734,16 @@ async function main() {
|
|
|
734
734
|
}
|
|
735
735
|
wsHandler.updateState({ agents: { ...bareAgentState } });
|
|
736
736
|
log(TAG, `bareagent register: available=[${clean.join(",")}] current=${current} → lanes esc=${bareAgentState.escalationAgent} spawn=${bareAgentState.spawnAgent}`);
|
|
737
|
+
|
|
738
|
+
// Lane is the source of truth for "is escalation active?". If a lane is
|
|
739
|
+
// set but mode is still "off" (e.g. an old wizard run wrote mode=off and
|
|
740
|
+
// the user has since picked an agent in the chip selector — or we just
|
|
741
|
+
// booted from agents.json with that combination), reconcile by promoting
|
|
742
|
+
// mode to match. Mirrors the existing set_agent → resumeEscalation flow,
|
|
743
|
+
// applied at register time so the boot-from-disk case isn't an exception.
|
|
744
|
+
if (bareAgentState.escalationAgent && config.escalationConfig.mode === "off") {
|
|
745
|
+
resumeEscalationInternal();
|
|
746
|
+
}
|
|
737
747
|
}
|
|
738
748
|
|
|
739
749
|
// ── Create HTTP + WS server ──
|
|
@@ -60,7 +60,7 @@ let allFacts = [];
|
|
|
60
60
|
async function loadFacts() {
|
|
61
61
|
document.getElementById('status').textContent = 'Loading...';
|
|
62
62
|
try {
|
|
63
|
-
const res = await fetch('/knowledge/entities?max=
|
|
63
|
+
const res = await fetch('/knowledge/entities?max=1000');
|
|
64
64
|
const data = await res.json();
|
|
65
65
|
allFacts = typeof data.entities === 'string' ? JSON.parse(data.entities) : data.entities;
|
|
66
66
|
const domains = [...new Set(allFacts.map(f => f.domain).filter(Boolean))].sort();
|
|
@@ -440,7 +440,7 @@ export function createAppServer(deps: ServerDeps) {
|
|
|
440
440
|
|
|
441
441
|
if (req.method === "GET" && url.pathname === "/knowledge/entities") {
|
|
442
442
|
// List all entities in the knowledge graph
|
|
443
|
-
const max = Math.min(parseInt(url.searchParams.get("max") || "50"),
|
|
443
|
+
const max = Math.min(parseInt(url.searchParams.get("max") || "50"), 1000);
|
|
444
444
|
if (deps.listKnowledgeEntities) {
|
|
445
445
|
try {
|
|
446
446
|
const entities = await deps.listKnowledgeEntities(max);
|