comisai 1.0.15 → 1.0.17
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/node_modules/@comis/agent/dist/bootstrap/types.d.ts +1 -1
- package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +12 -11
- package/node_modules/@comis/agent/dist/context-engine/constants.d.ts +11 -0
- package/node_modules/@comis/agent/dist/context-engine/constants.js +11 -0
- package/node_modules/@comis/agent/dist/context-engine/index.d.ts +1 -1
- package/node_modules/@comis/agent/dist/context-engine/index.js +1 -1
- package/node_modules/@comis/agent/dist/context-engine/llm-compaction.js +32 -18
- package/node_modules/@comis/agent/dist/executor/cache-break-diff-writer.d.ts +2 -0
- package/node_modules/@comis/agent/dist/executor/cache-break-diff-writer.js +36 -0
- package/node_modules/@comis/agent/dist/executor/executor-post-execution.d.ts +12 -0
- package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +117 -27
- package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.d.ts +1 -0
- package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +16 -4
- package/node_modules/@comis/agent/dist/executor/executor-stream-setup.js +17 -1
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +27 -1
- package/node_modules/@comis/agent/dist/executor/session-snapshot-cleanup.js +3 -1
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/index.d.ts +2 -0
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/index.js +2 -0
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.d.ts +9 -0
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +65 -3
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/stub-filter-injector.d.ts +28 -0
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/stub-filter-injector.js +63 -0
- package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +18 -1
- package/node_modules/@comis/agent/dist/executor/tool-deferral.js +275 -133
- package/node_modules/@comis/agent/dist/executor/ttl-guard.d.ts +6 -0
- package/node_modules/@comis/agent/dist/executor/ttl-guard.js +8 -0
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/dist/shared/typing-controller.d.ts +7 -0
- package/node_modules/@comis/channels/dist/shared/typing-controller.js +33 -0
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/dist/commands/daemon.js +116 -28
- package/node_modules/@comis/cli/dist/wizard/non-interactive.js +1 -0
- package/node_modules/@comis/cli/dist/wizard/steps/01-detect-existing.js +4 -0
- package/node_modules/@comis/cli/dist/wizard/steps/07-gateway.js +9 -0
- package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +2 -0
- package/node_modules/@comis/cli/dist/wizard/steps/12-finish.js +5 -2
- package/node_modules/@comis/cli/dist/wizard/types.d.ts +1 -0
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/config/schema-agent.d.ts +10 -0
- package/node_modules/@comis/core/dist/config/schema-agent.js +8 -0
- package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +17 -2
- package/node_modules/@comis/core/dist/config/schema-gateway.js +11 -0
- package/node_modules/@comis/core/dist/config/schema-skills.d.ts +16 -2
- package/node_modules/@comis/core/dist/config/schema-skills.js +9 -2
- package/node_modules/@comis/core/dist/config/schema.d.ts +66 -60
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-gateway.js +34 -6
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +1 -1
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/dist/android-chrome-192x192.png +0 -0
- package/node_modules/@comis/web/dist/android-chrome-512x512.png +0 -0
- package/node_modules/@comis/web/dist/apple-touch-icon.png +0 -0
- package/node_modules/@comis/web/dist/assets/agent-detail-BG9MGWWj.js +615 -0
- package/node_modules/@comis/web/dist/assets/agent-editor-C26Q_xCs.js +2173 -0
- package/node_modules/@comis/web/dist/assets/agent-list-LHCJ4rw2.js +504 -0
- package/node_modules/@comis/web/dist/assets/approvals-q9VH_IKr.js +54 -0
- package/node_modules/@comis/web/dist/assets/billing-view-CtYvBqTE.js +375 -0
- package/node_modules/@comis/web/dist/assets/channel-detail-CaInesJM.js +681 -0
- package/node_modules/@comis/web/dist/assets/channel-list-B8dj3O9a.js +323 -0
- package/node_modules/@comis/web/dist/assets/chat-console-CNmzl0JW.js +943 -0
- package/node_modules/@comis/web/dist/assets/config-editor-DX4ITw6y.js +1374 -0
- package/node_modules/@comis/web/dist/assets/context-dag-browser-BwiaF5tf.js +393 -0
- package/node_modules/@comis/web/dist/assets/context-engine-BZ5Am6hA.js +393 -0
- package/node_modules/@comis/web/dist/assets/delivery-view-OfBZof-m.js +392 -0
- package/node_modules/@comis/web/dist/assets/diagnostics-view-YFwCxgr2.js +231 -0
- package/node_modules/@comis/web/dist/assets/directive-DoeGSK_T.js +1 -0
- package/node_modules/@comis/web/dist/assets/extract-variables-BM5qyK-s.js +149 -0
- package/node_modules/@comis/web/dist/assets/ic-array-editor-B7m6x7-S.js +118 -0
- package/node_modules/@comis/web/dist/assets/ic-breadcrumb-CUMpp3BL.js +75 -0
- package/node_modules/@comis/web/dist/assets/ic-budget-segment-bar-BtJ6x5mN.js +64 -0
- package/node_modules/@comis/web/dist/assets/ic-chat-message-CFyDJd0z.js +352 -0
- package/node_modules/@comis/web/dist/assets/ic-confirm-dialog-CCDbB04e.js +110 -0
- package/node_modules/@comis/web/dist/assets/ic-connection-dot-CnT1b8xr.js +54 -0
- package/node_modules/@comis/web/dist/assets/ic-data-table-CKUNTxHw.js +277 -0
- package/node_modules/@comis/web/dist/assets/ic-delivery-row-GP5Fkygs.js +67 -0
- package/node_modules/@comis/web/dist/assets/ic-detail-panel-BF83r-if.js +116 -0
- package/node_modules/@comis/web/dist/assets/ic-empty-state-60l2ePhd.js +52 -0
- package/node_modules/@comis/web/dist/assets/ic-graph-canvas-C8FuSMe1.js +359 -0
- package/node_modules/@comis/web/dist/assets/ic-icon-xeGTVhVG.js +33 -0
- package/node_modules/@comis/web/dist/assets/ic-layer-waterfall-COvEYMg5.js +69 -0
- package/node_modules/@comis/web/dist/assets/ic-relative-time-3FqpjeAI.js +12 -0
- package/node_modules/@comis/web/dist/assets/ic-search-input-CSOxY9g7.js +92 -0
- package/node_modules/@comis/web/dist/assets/ic-select-Ce-Raudx.js +127 -0
- package/node_modules/@comis/web/dist/assets/ic-tabs-B7QtM_v8.js +95 -0
- package/node_modules/@comis/web/dist/assets/ic-tag-CPPUnDLF.js +33 -0
- package/node_modules/@comis/web/dist/assets/ic-time-range-picker-CypCT68y.js +93 -0
- package/node_modules/@comis/web/dist/assets/ic-tool-call-7MaXSsCW.js +146 -0
- package/node_modules/@comis/web/dist/assets/index-CEcM1R_C.js +2830 -0
- package/node_modules/@comis/web/dist/assets/index-CIJFuItj.css +1 -0
- package/node_modules/@comis/web/dist/assets/mcp-management-BNZPnpDn.js +582 -0
- package/node_modules/@comis/web/dist/assets/media-config-BBvTYxOX.js +314 -0
- package/node_modules/@comis/web/dist/assets/media-test-BkK3RCRK.js +496 -0
- package/node_modules/@comis/web/dist/assets/memory-inspector-1hDGCGat.js +1139 -0
- package/node_modules/@comis/web/dist/assets/message-center-CXefwsUu.js +785 -0
- package/node_modules/@comis/web/dist/assets/models-C1qcU_j3.js +894 -0
- package/node_modules/@comis/web/dist/assets/observability-types-D7jUtSde.js +1 -0
- package/node_modules/@comis/web/dist/assets/observe-view-C0VBhX4C.js +814 -0
- package/node_modules/@comis/web/dist/assets/pipeline-builder-DcUUIrm0.js +1496 -0
- package/node_modules/@comis/web/dist/assets/pipeline-history-DkfOQ6SW.js +317 -0
- package/node_modules/@comis/web/dist/assets/pipeline-history-detail-hyHgD0ai.js +287 -0
- package/node_modules/@comis/web/dist/assets/pipeline-list-BPW8hV-q.js +518 -0
- package/node_modules/@comis/web/dist/assets/pipeline-monitor-Bip16T7e.js +972 -0
- package/node_modules/@comis/web/dist/assets/scheduler-BGgwKd06.js +1182 -0
- package/node_modules/@comis/web/dist/assets/security-D15st4xx.js +1224 -0
- package/node_modules/@comis/web/dist/assets/session-detail-SGEYNJ0M.js +632 -0
- package/node_modules/@comis/web/dist/assets/session-key-parser-DPORMVyU.js +1 -0
- package/node_modules/@comis/web/dist/assets/session-list-6ybUTxbY.js +231 -0
- package/node_modules/@comis/web/dist/assets/setup-wizard-nT0tz9QP.js +853 -0
- package/node_modules/@comis/web/dist/assets/skills-D8yVfSUy.js +1051 -0
- package/node_modules/@comis/web/dist/assets/subagents-HHXMeHYo.js +193 -0
- package/node_modules/@comis/web/dist/assets/workspace-manager-BQlr10iH.js +785 -0
- package/node_modules/@comis/web/dist/comis-logo.png +0 -0
- package/node_modules/@comis/web/dist/favicon-16x16.png +0 -0
- package/node_modules/@comis/web/dist/favicon-32x32.png +0 -0
- package/node_modules/@comis/web/dist/favicon.ico +0 -0
- package/node_modules/@comis/web/dist/index.html +17 -0
- package/node_modules/@comis/web/package.json +29 -0
- package/package.json +15 -13
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
import { execFile, spawn } from "node:child_process";
|
|
13
13
|
import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync, openSync } from "node:fs";
|
|
14
14
|
import * as os from "node:os";
|
|
15
|
+
import { createInterface } from "node:readline";
|
|
15
16
|
import { promisify } from "node:util";
|
|
17
|
+
import chalk from "chalk";
|
|
16
18
|
import { safePath } from "@comis/core";
|
|
17
19
|
import { withClient } from "../client/rpc-client.js";
|
|
18
20
|
import { success, error, info, warn } from "../output/format.js";
|
|
@@ -23,6 +25,63 @@ const PID_FILE = safePath(COMIS_DIR, "daemon.pid");
|
|
|
23
25
|
const LOG_FILE = safePath(COMIS_DIR, "daemon.log");
|
|
24
26
|
/** Max time to wait for daemon gateway to become ready (ms). */
|
|
25
27
|
const READY_TIMEOUT_MS = 15_000;
|
|
28
|
+
// ---------- Log formatting ----------
|
|
29
|
+
const PINO_LEVELS = {
|
|
30
|
+
10: { label: "TRACE", color: chalk.gray },
|
|
31
|
+
20: { label: "DEBUG", color: chalk.gray },
|
|
32
|
+
30: { label: "INFO", color: chalk.cyan },
|
|
33
|
+
40: { label: "WARN", color: chalk.yellow },
|
|
34
|
+
50: { label: "ERROR", color: chalk.red },
|
|
35
|
+
60: { label: "FATAL", color: chalk.bgRed.white },
|
|
36
|
+
};
|
|
37
|
+
const PINO_META_KEYS = new Set([
|
|
38
|
+
"level", "time", "pid", "hostname", "name", "msg", "module",
|
|
39
|
+
"levelValue", "instanceId",
|
|
40
|
+
]);
|
|
41
|
+
function formatPinoLine(line) {
|
|
42
|
+
const trimmed = line.trim();
|
|
43
|
+
if (!trimmed.startsWith("{"))
|
|
44
|
+
return line;
|
|
45
|
+
let record;
|
|
46
|
+
try {
|
|
47
|
+
record = JSON.parse(trimmed);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return line;
|
|
51
|
+
}
|
|
52
|
+
if (typeof record["level"] !== "number" && typeof record["level"] !== "string")
|
|
53
|
+
return line;
|
|
54
|
+
const levelNum = typeof record["level"] === "number"
|
|
55
|
+
? record["level"]
|
|
56
|
+
: ({ trace: 10, debug: 20, info: 30, warn: 40, error: 50, fatal: 60 }[record["level"]] ?? 30);
|
|
57
|
+
const levelInfo = PINO_LEVELS[levelNum] ?? { label: String(record["level"]), color: chalk.white };
|
|
58
|
+
const time = record["time"]
|
|
59
|
+
? new Date(record["time"]).toLocaleTimeString()
|
|
60
|
+
: "";
|
|
61
|
+
const mod = record["module"] ? `[${record["module"]}]` : "";
|
|
62
|
+
const msg = record["msg"] ?? "";
|
|
63
|
+
const extra = {};
|
|
64
|
+
for (const [k, v] of Object.entries(record)) {
|
|
65
|
+
if (!PINO_META_KEYS.has(k))
|
|
66
|
+
extra[k] = v;
|
|
67
|
+
}
|
|
68
|
+
const extraStr = Object.keys(extra).length > 0
|
|
69
|
+
? chalk.gray(` ${JSON.stringify(extra)}`)
|
|
70
|
+
: "";
|
|
71
|
+
return `${chalk.dim(time)} ${levelInfo.color(levelInfo.label.padEnd(5))} ${chalk.blue(mod)} ${msg}${extraStr}`;
|
|
72
|
+
}
|
|
73
|
+
function formatLogOutput(raw) {
|
|
74
|
+
return raw
|
|
75
|
+
.split("\n")
|
|
76
|
+
.map((line) => (line.trim() ? formatPinoLine(line) : line))
|
|
77
|
+
.join("\n");
|
|
78
|
+
}
|
|
79
|
+
function pipeFormatted(child) {
|
|
80
|
+
if (!child.stdout)
|
|
81
|
+
return;
|
|
82
|
+
const rl = createInterface({ input: child.stdout });
|
|
83
|
+
rl.on("line", (line) => console.log(formatPinoLine(line)));
|
|
84
|
+
}
|
|
26
85
|
/** Interval between readiness polls (ms). */
|
|
27
86
|
const READY_POLL_MS = 500;
|
|
28
87
|
/**
|
|
@@ -533,40 +592,48 @@ async function handleDaemonLogs(options) {
|
|
|
533
592
|
}
|
|
534
593
|
}
|
|
535
594
|
async function streamSystemdLogs(scope, options) {
|
|
536
|
-
const jArgs = ["--unit=comis", "--no-pager", `-n${options.lines}
|
|
595
|
+
const jArgs = ["--unit=comis", "--no-pager", `-n${options.lines}`, "--output=cat"];
|
|
537
596
|
if (scope === "systemd-user")
|
|
538
597
|
jArgs.push("--user");
|
|
539
598
|
if (options.follow)
|
|
540
599
|
jArgs.push("--follow");
|
|
541
600
|
if (options.follow) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
error(
|
|
545
|
-
|
|
546
|
-
|
|
601
|
+
if (options.raw) {
|
|
602
|
+
const child = spawn("journalctl", jArgs, { stdio: "inherit" });
|
|
603
|
+
child.on("error", (err) => {
|
|
604
|
+
error(`Failed to read logs: ${err.message}`);
|
|
605
|
+
process.exit(1);
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
const child = spawn("journalctl", jArgs, { stdio: ["ignore", "pipe", "inherit"] });
|
|
610
|
+
child.on("error", (err) => {
|
|
611
|
+
error(`Failed to read logs: ${err.message}`);
|
|
612
|
+
process.exit(1);
|
|
613
|
+
});
|
|
614
|
+
pipeFormatted(child);
|
|
615
|
+
}
|
|
547
616
|
return;
|
|
548
617
|
}
|
|
549
|
-
|
|
550
|
-
// then fall back to sudo for system-scope journals.
|
|
551
|
-
try {
|
|
552
|
-
const { stdout } = await exec("journalctl", jArgs, { timeout: 10_000 });
|
|
618
|
+
const printOutput = (stdout) => {
|
|
553
619
|
if (stdout.trim()) {
|
|
554
|
-
console.log(stdout);
|
|
620
|
+
console.log(options.raw ? stdout : formatLogOutput(stdout));
|
|
555
621
|
}
|
|
556
622
|
else {
|
|
557
623
|
info("No logs found");
|
|
558
624
|
}
|
|
625
|
+
};
|
|
626
|
+
// Try journalctl directly first (works when user is in systemd-journal group),
|
|
627
|
+
// then fall back to sudo for system-scope journals.
|
|
628
|
+
try {
|
|
629
|
+
const { stdout } = await exec("journalctl", jArgs, { timeout: 10_000 });
|
|
630
|
+
printOutput(stdout);
|
|
559
631
|
}
|
|
560
632
|
catch {
|
|
561
633
|
// eslint-disable-next-line no-restricted-syntax -- CLI bootstrap before SecretManager
|
|
562
634
|
if (scope === "systemd" && process.getuid?.() !== 0) {
|
|
563
635
|
const { stdout } = await exec("sudo", ["journalctl", ...jArgs], { timeout: 10_000 });
|
|
564
|
-
|
|
565
|
-
console.log(stdout);
|
|
566
|
-
}
|
|
567
|
-
else {
|
|
568
|
-
info("No logs found");
|
|
569
|
-
}
|
|
636
|
+
printOutput(stdout);
|
|
570
637
|
}
|
|
571
638
|
else {
|
|
572
639
|
throw new Error("Failed to read journal logs");
|
|
@@ -577,11 +644,21 @@ function streamPm2Logs(options) {
|
|
|
577
644
|
const args = ["logs", "comis", "--lines", options.lines];
|
|
578
645
|
if (!options.follow)
|
|
579
646
|
args.push("--nostream");
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
error(
|
|
583
|
-
|
|
584
|
-
|
|
647
|
+
if (options.raw) {
|
|
648
|
+
const child = spawn("pm2", args, { stdio: "inherit" });
|
|
649
|
+
child.on("error", (err) => {
|
|
650
|
+
error(`Failed to read logs: ${err.message}`);
|
|
651
|
+
process.exit(1);
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
const child = spawn("pm2", args, { stdio: ["ignore", "pipe", "inherit"] });
|
|
656
|
+
child.on("error", (err) => {
|
|
657
|
+
error(`Failed to read logs: ${err.message}`);
|
|
658
|
+
process.exit(1);
|
|
659
|
+
});
|
|
660
|
+
pipeFormatted(child);
|
|
661
|
+
}
|
|
585
662
|
}
|
|
586
663
|
async function streamDirectLogs(options) {
|
|
587
664
|
// eslint-disable-next-line no-restricted-syntax -- CLI bootstrap before SecretManager
|
|
@@ -594,16 +671,26 @@ async function streamDirectLogs(options) {
|
|
|
594
671
|
const args = ["-n", options.lines, logPath];
|
|
595
672
|
if (options.follow) {
|
|
596
673
|
args.unshift("-f");
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
error(
|
|
600
|
-
|
|
601
|
-
|
|
674
|
+
if (options.raw) {
|
|
675
|
+
const child = spawn("tail", args, { stdio: "inherit" });
|
|
676
|
+
child.on("error", (err) => {
|
|
677
|
+
error(`Failed to read logs: ${err.message}`);
|
|
678
|
+
process.exit(1);
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
const child = spawn("tail", args, { stdio: ["ignore", "pipe", "inherit"] });
|
|
683
|
+
child.on("error", (err) => {
|
|
684
|
+
error(`Failed to read logs: ${err.message}`);
|
|
685
|
+
process.exit(1);
|
|
686
|
+
});
|
|
687
|
+
pipeFormatted(child);
|
|
688
|
+
}
|
|
602
689
|
return;
|
|
603
690
|
}
|
|
604
691
|
const { stdout } = await exec("tail", args, { timeout: 5_000 });
|
|
605
692
|
if (stdout.trim()) {
|
|
606
|
-
console.log(stdout);
|
|
693
|
+
console.log(options.raw ? stdout : formatLogOutput(stdout));
|
|
607
694
|
}
|
|
608
695
|
else {
|
|
609
696
|
info("No logs found");
|
|
@@ -634,5 +721,6 @@ export function registerDaemonCommand(program) {
|
|
|
634
721
|
.description("Show daemon logs")
|
|
635
722
|
.option("-f, --follow", "Follow log output")
|
|
636
723
|
.option("-n, --lines <n>", "Number of lines to show", "50")
|
|
724
|
+
.option("--raw", "Show raw JSON output without formatting")
|
|
637
725
|
.action(handleDaemonLogs);
|
|
638
726
|
}
|
|
@@ -230,6 +230,7 @@ export function buildNonInteractiveState(opts) {
|
|
|
230
230
|
authMethod: gatewayAuth,
|
|
231
231
|
...(gatewayToken !== undefined && { token: gatewayToken }),
|
|
232
232
|
...(gatewayPassword !== undefined && { password: gatewayPassword }),
|
|
233
|
+
webEnabled: true,
|
|
233
234
|
};
|
|
234
235
|
// Data directory
|
|
235
236
|
const dataDir = opts.dataDir ?? safePath(homedir(), ".comis", "data");
|
|
@@ -68,12 +68,16 @@ function extractStateFromConfig(raw, envRecord = {}) {
|
|
|
68
68
|
bindMode = "custom";
|
|
69
69
|
customIp = host;
|
|
70
70
|
}
|
|
71
|
+
// Recover gateway.web.enabled (default true) when reloading existing config
|
|
72
|
+
const webRaw = gatewayRaw["web"];
|
|
73
|
+
const webEnabled = webRaw && typeof webRaw["enabled"] === "boolean" ? webRaw["enabled"] : true;
|
|
71
74
|
if (port !== undefined) {
|
|
72
75
|
gateway = {
|
|
73
76
|
port,
|
|
74
77
|
bindMode,
|
|
75
78
|
...(customIp !== undefined && { customIp }),
|
|
76
79
|
authMethod: "token",
|
|
80
|
+
webEnabled,
|
|
77
81
|
};
|
|
78
82
|
}
|
|
79
83
|
}
|
|
@@ -91,6 +91,14 @@ export const gatewayStep = {
|
|
|
91
91
|
},
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
|
+
// 5b. Web dashboard prompt
|
|
95
|
+
const webEnabled = await prompter.confirm({
|
|
96
|
+
message: "Enable web dashboard? (served at /app/ on the gateway port)",
|
|
97
|
+
initialValue: state.gateway?.webEnabled ?? true,
|
|
98
|
+
});
|
|
99
|
+
if (webEnabled && bindMode === "loopback") {
|
|
100
|
+
prompter.log.info("Dashboard will bind to 127.0.0.1 only. For remote access, SSH-tunnel: `ssh -L 4766:localhost:4766 user@host`.");
|
|
101
|
+
}
|
|
94
102
|
// 6. Build config and update state
|
|
95
103
|
const config = {
|
|
96
104
|
port,
|
|
@@ -99,6 +107,7 @@ export const gatewayStep = {
|
|
|
99
107
|
authMethod: authMethod,
|
|
100
108
|
...(token !== undefined && { token }),
|
|
101
109
|
...(password !== undefined && { password }),
|
|
110
|
+
webEnabled,
|
|
102
111
|
};
|
|
103
112
|
return updateState(state, { gateway: config });
|
|
104
113
|
},
|
|
@@ -96,6 +96,8 @@ function buildConfigObject(state) {
|
|
|
96
96
|
else if (state.gateway.authMethod === "password") {
|
|
97
97
|
gatewayConfig.password = "${COMIS_GATEWAY_PASSWORD}";
|
|
98
98
|
}
|
|
99
|
+
// Web dashboard -- default true; wizard always sets this explicitly
|
|
100
|
+
gatewayConfig.web = { enabled: state.gateway.webEnabled };
|
|
99
101
|
config.gateway = gatewayConfig;
|
|
100
102
|
}
|
|
101
103
|
// Channels section
|
|
@@ -54,6 +54,9 @@ function buildGatewayInfo(state) {
|
|
|
54
54
|
host = "127.0.0.1";
|
|
55
55
|
}
|
|
56
56
|
const wsLine = ` WebSocket: ${brand(`ws://${host}:${state.gateway.port}/ws`)}`;
|
|
57
|
+
const dashboardLine = state.gateway.webEnabled
|
|
58
|
+
? ` Dashboard: ${brand(`http://${host}:${state.gateway.port}/app/`)}`
|
|
59
|
+
: undefined;
|
|
57
60
|
let authLine;
|
|
58
61
|
if (state.gateway.authMethod === "password") {
|
|
59
62
|
authLine = " Auth: Password auth (in ~/.comis/.env)";
|
|
@@ -64,8 +67,8 @@ function buildGatewayInfo(state) {
|
|
|
64
67
|
: "see file";
|
|
65
68
|
authLine = ` Token: ${tokenPreview} (in ~/.comis/.env)`;
|
|
66
69
|
}
|
|
67
|
-
const
|
|
68
|
-
return
|
|
70
|
+
const lines = [wsLine, dashboardLine, authLine].filter((l) => l !== undefined);
|
|
71
|
+
return lines.join("\n");
|
|
69
72
|
}
|
|
70
73
|
// ---------- Step Implementation ----------
|
|
71
74
|
export const finishStep = {
|
|
@@ -65,6 +65,7 @@ export type GatewayConfig = {
|
|
|
65
65
|
authMethod: "token" | "password";
|
|
66
66
|
token?: string;
|
|
67
67
|
password?: string;
|
|
68
|
+
webEnabled: boolean;
|
|
68
69
|
};
|
|
69
70
|
/** Auth method for providers that support both API keys and OAuth tokens. */
|
|
70
71
|
export type AuthMethod = "apikey" | "oauth";
|
|
@@ -737,6 +737,10 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
737
737
|
"multi-zone": "multi-zone";
|
|
738
738
|
single: "single";
|
|
739
739
|
}>>;
|
|
740
|
+
/** Advanced cache optimization options for interactive sessions. */
|
|
741
|
+
advancedCacheOptimization: z.ZodDefault<z.ZodObject<{
|
|
742
|
+
enableRecentZonePromotion: z.ZodDefault<z.ZodBoolean>;
|
|
743
|
+
}, z.core.$strip>>;
|
|
740
744
|
/** Gemini explicit cache configuration (CachedContent lifecycle). */
|
|
741
745
|
geminiCache: z.ZodDefault<z.ZodObject<{
|
|
742
746
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -1102,6 +1106,9 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
|
|
|
1102
1106
|
"multi-zone": "multi-zone";
|
|
1103
1107
|
single: "single";
|
|
1104
1108
|
}>>;
|
|
1109
|
+
advancedCacheOptimization: z.ZodDefault<z.ZodObject<{
|
|
1110
|
+
enableRecentZonePromotion: z.ZodDefault<z.ZodBoolean>;
|
|
1111
|
+
}, z.core.$strip>>;
|
|
1105
1112
|
geminiCache: z.ZodDefault<z.ZodObject<{
|
|
1106
1113
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1107
1114
|
maxActiveCaches: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1773,6 +1780,9 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
1773
1780
|
"multi-zone": "multi-zone";
|
|
1774
1781
|
single: "single";
|
|
1775
1782
|
}>>;
|
|
1783
|
+
advancedCacheOptimization: z.ZodDefault<z.ZodObject<{
|
|
1784
|
+
enableRecentZonePromotion: z.ZodDefault<z.ZodBoolean>;
|
|
1785
|
+
}, z.core.$strip>>;
|
|
1776
1786
|
geminiCache: z.ZodDefault<z.ZodObject<{
|
|
1777
1787
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1778
1788
|
maxActiveCaches: z.ZodDefault<z.ZodNumber>;
|
|
@@ -574,6 +574,14 @@ export const AgentConfigSchema = z.strictObject({
|
|
|
574
574
|
* 'auto' resolves to 'single' for direct Anthropic and 'multi-zone' for Bedrock/Vertex.
|
|
575
575
|
* 'multi-zone' places breakpoints across system, tools, and messages. */
|
|
576
576
|
cacheBreakpointStrategy: z.enum(["auto", "multi-zone", "single"]).default("single"),
|
|
577
|
+
/** Advanced cache optimization options for interactive sessions. */
|
|
578
|
+
advancedCacheOptimization: z.object({
|
|
579
|
+
/** When true, the recent-zone message breakpoint may be promoted from
|
|
580
|
+
* "short" (5m) to "long" (1h) TTL when observed inter-turn gaps
|
|
581
|
+
* consistently exceed 5 minutes. Prevents repeated cache rewrite costs
|
|
582
|
+
* in slow-cadence channels like Telegram. Default: true. */
|
|
583
|
+
enableRecentZonePromotion: z.boolean().default(true),
|
|
584
|
+
}).default(() => ({ enableRecentZonePromotion: true })),
|
|
577
585
|
/** Gemini explicit cache configuration (CachedContent lifecycle). */
|
|
578
586
|
geminiCache: GeminiCacheConfigSchema.default(() => GeminiCacheConfigSchema.parse({})),
|
|
579
587
|
/** When true, only content inside <final> blocks reaches users (streaming + non-streaming). Default: false. */
|
|
@@ -29,9 +29,9 @@ export declare const GatewayTokenSchema: z.ZodObject<{
|
|
|
29
29
|
/** The secret value (min 32 chars; resolved at runtime if omitted; string or SecretRef) */
|
|
30
30
|
secret: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
31
31
|
source: z.ZodEnum<{
|
|
32
|
+
env: "env";
|
|
32
33
|
file: "file";
|
|
33
34
|
exec: "exec";
|
|
34
|
-
env: "env";
|
|
35
35
|
}>;
|
|
36
36
|
provider: z.ZodString;
|
|
37
37
|
id: z.ZodString;
|
|
@@ -48,6 +48,15 @@ export declare const GatewayRateLimitSchema: z.ZodObject<{
|
|
|
48
48
|
/** Maximum requests per window (default: 100) */
|
|
49
49
|
maxRequests: z.ZodDefault<z.ZodNumber>;
|
|
50
50
|
}, z.core.$strict>;
|
|
51
|
+
/**
|
|
52
|
+
* Web dashboard configuration. Controls whether the @comis/web SPA is mounted
|
|
53
|
+
* at /app/* alongside the gateway, sharing the same host/port/auth. When
|
|
54
|
+
* disabled, the daemon skips /app/*, /api, SSE, and the `/` -> `/app/` redirect.
|
|
55
|
+
*/
|
|
56
|
+
export declare const GatewayWebConfigSchema: z.ZodObject<{
|
|
57
|
+
/** Enable the web dashboard SPA (default: true) */
|
|
58
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
59
|
+
}, z.core.$strict>;
|
|
51
60
|
/**
|
|
52
61
|
* Gateway server configuration schema.
|
|
53
62
|
*
|
|
@@ -79,9 +88,9 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
79
88
|
/** The secret value (min 32 chars; resolved at runtime if omitted; string or SecretRef) */
|
|
80
89
|
secret: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
81
90
|
source: z.ZodEnum<{
|
|
91
|
+
env: "env";
|
|
82
92
|
file: "file";
|
|
83
93
|
exec: "exec";
|
|
84
|
-
env: "env";
|
|
85
94
|
}>;
|
|
86
95
|
provider: z.ZodString;
|
|
87
96
|
id: z.ZodString;
|
|
@@ -96,6 +105,11 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
96
105
|
/** Maximum requests per window (default: 100) */
|
|
97
106
|
maxRequests: z.ZodDefault<z.ZodNumber>;
|
|
98
107
|
}, z.core.$strict>>;
|
|
108
|
+
/** Web dashboard (mounted at /app/*, shares gateway host/port/auth) */
|
|
109
|
+
web: z.ZodDefault<z.ZodObject<{
|
|
110
|
+
/** Enable the web dashboard SPA (default: true) */
|
|
111
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
112
|
+
}, z.core.$strict>>;
|
|
99
113
|
/** Maximum JSON-RPC batch size (default: 50) */
|
|
100
114
|
maxBatchSize: z.ZodDefault<z.ZodNumber>;
|
|
101
115
|
/** WebSocket heartbeat interval in milliseconds (default: 30000) */
|
|
@@ -122,3 +136,4 @@ export type GatewayConfig = z.infer<typeof GatewayConfigSchema>;
|
|
|
122
136
|
export type GatewayTlsConfig = z.infer<typeof GatewayTlsConfigSchema>;
|
|
123
137
|
export type GatewayToken = z.infer<typeof GatewayTokenSchema>;
|
|
124
138
|
export type GatewayRateLimit = z.infer<typeof GatewayRateLimitSchema>;
|
|
139
|
+
export type GatewayWebConfig = z.infer<typeof GatewayWebConfigSchema>;
|
|
@@ -42,6 +42,15 @@ export const GatewayRateLimitSchema = z.strictObject({
|
|
|
42
42
|
/** Maximum requests per window (default: 100) */
|
|
43
43
|
maxRequests: z.number().int().positive().default(100),
|
|
44
44
|
});
|
|
45
|
+
/**
|
|
46
|
+
* Web dashboard configuration. Controls whether the @comis/web SPA is mounted
|
|
47
|
+
* at /app/* alongside the gateway, sharing the same host/port/auth. When
|
|
48
|
+
* disabled, the daemon skips /app/*, /api, SSE, and the `/` -> `/app/` redirect.
|
|
49
|
+
*/
|
|
50
|
+
export const GatewayWebConfigSchema = z.strictObject({
|
|
51
|
+
/** Enable the web dashboard SPA (default: true) */
|
|
52
|
+
enabled: z.boolean().default(true),
|
|
53
|
+
});
|
|
45
54
|
/**
|
|
46
55
|
* Gateway server configuration schema.
|
|
47
56
|
*
|
|
@@ -61,6 +70,8 @@ export const GatewayConfigSchema = z.strictObject({
|
|
|
61
70
|
tokens: z.array(GatewayTokenSchema).default([]),
|
|
62
71
|
/** Rate limiting settings */
|
|
63
72
|
rateLimit: GatewayRateLimitSchema.default(() => GatewayRateLimitSchema.parse({})),
|
|
73
|
+
/** Web dashboard (mounted at /app/*, shares gateway host/port/auth) */
|
|
74
|
+
web: GatewayWebConfigSchema.default(() => GatewayWebConfigSchema.parse({})),
|
|
64
75
|
/** Maximum JSON-RPC batch size (default: 50) */
|
|
65
76
|
maxBatchSize: z.number().int().positive().default(50),
|
|
66
77
|
/** WebSocket heartbeat interval in milliseconds (default: 30000) */
|
|
@@ -23,7 +23,14 @@ export declare const PromptSkillsConfigSchema: z.ZodObject<{
|
|
|
23
23
|
* per-deployment without a rebuild.
|
|
24
24
|
*/
|
|
25
25
|
declare const ToolDiscoverySchema: z.ZodObject<{
|
|
26
|
-
/** Minimum BM25 score
|
|
26
|
+
/** Minimum BM25 score as FRACTION OF TOP MATCH (0..1). Default 0.8.
|
|
27
|
+
* As of 2026-04-23, BM25 scores are normalized to [0, 1] before this floor
|
|
28
|
+
* applies, matching the semantics of minHybridScore. A value of 0.8 means
|
|
29
|
+
* "return only tools scoring >= 80% of the top match". Values > 1.0 fail
|
|
30
|
+
* validation at config load (stale raw-score overrides would produce zero
|
|
31
|
+
* matches under the new normalized semantics; fail-fast surfaces the
|
|
32
|
+
* error immediately per AGENTS.md §3.4). See design §5.6:
|
|
33
|
+
* .planning/design/discover-tools-bm25-fallback-fix.md */
|
|
27
34
|
minBm25Score: z.ZodDefault<z.ZodNumber>;
|
|
28
35
|
/** Minimum combined score (0..1 normalized) for hybrid mode. Default 0.35. */
|
|
29
36
|
minHybridScore: z.ZodDefault<z.ZodNumber>;
|
|
@@ -115,7 +122,14 @@ export declare const SkillsConfigSchema: z.ZodObject<{
|
|
|
115
122
|
}, z.core.$strict>>;
|
|
116
123
|
/** discover_tools score-floor thresholds (BM25 + hybrid). */
|
|
117
124
|
toolDiscovery: z.ZodDefault<z.ZodObject<{
|
|
118
|
-
/** Minimum BM25 score
|
|
125
|
+
/** Minimum BM25 score as FRACTION OF TOP MATCH (0..1). Default 0.8.
|
|
126
|
+
* As of 2026-04-23, BM25 scores are normalized to [0, 1] before this floor
|
|
127
|
+
* applies, matching the semantics of minHybridScore. A value of 0.8 means
|
|
128
|
+
* "return only tools scoring >= 80% of the top match". Values > 1.0 fail
|
|
129
|
+
* validation at config load (stale raw-score overrides would produce zero
|
|
130
|
+
* matches under the new normalized semantics; fail-fast surfaces the
|
|
131
|
+
* error immediately per AGENTS.md §3.4). See design §5.6:
|
|
132
|
+
* .planning/design/discover-tools-bm25-fallback-fix.md */
|
|
119
133
|
minBm25Score: z.ZodDefault<z.ZodNumber>;
|
|
120
134
|
/** Minimum combined score (0..1 normalized) for hybrid mode. Default 0.35. */
|
|
121
135
|
minHybridScore: z.ZodDefault<z.ZodNumber>;
|
|
@@ -93,8 +93,15 @@ const ExecSandboxSchema = z.strictObject({
|
|
|
93
93
|
* per-deployment without a rebuild.
|
|
94
94
|
*/
|
|
95
95
|
const ToolDiscoverySchema = z.strictObject({
|
|
96
|
-
/** Minimum BM25 score
|
|
97
|
-
|
|
96
|
+
/** Minimum BM25 score as FRACTION OF TOP MATCH (0..1). Default 0.8.
|
|
97
|
+
* As of 2026-04-23, BM25 scores are normalized to [0, 1] before this floor
|
|
98
|
+
* applies, matching the semantics of minHybridScore. A value of 0.8 means
|
|
99
|
+
* "return only tools scoring >= 80% of the top match". Values > 1.0 fail
|
|
100
|
+
* validation at config load (stale raw-score overrides would produce zero
|
|
101
|
+
* matches under the new normalized semantics; fail-fast surfaces the
|
|
102
|
+
* error immediately per AGENTS.md §3.4). See design §5.6:
|
|
103
|
+
* .planning/design/discover-tools-bm25-fallback-fix.md */
|
|
104
|
+
minBm25Score: z.number().min(0).max(1).default(0.8),
|
|
98
105
|
/** Minimum combined score (0..1 normalized) for hybrid mode. Default 0.35. */
|
|
99
106
|
minHybridScore: z.number().min(0).max(1).default(0.35),
|
|
100
107
|
});
|