comisai 1.0.14 → 1.0.16

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.
Files changed (79) hide show
  1. package/node_modules/@comis/agent/dist/bootstrap/index.d.ts +1 -1
  2. package/node_modules/@comis/agent/dist/bootstrap/index.js +1 -1
  3. package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.d.ts +26 -0
  4. package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.js +86 -54
  5. package/node_modules/@comis/agent/dist/bootstrap/types.d.ts +7 -1
  6. package/node_modules/@comis/agent/dist/bootstrap/workspace-loader.d.ts +12 -0
  7. package/node_modules/@comis/agent/dist/bootstrap/workspace-loader.js +21 -0
  8. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +12 -11
  9. package/node_modules/@comis/agent/dist/context-engine/constants.d.ts +11 -0
  10. package/node_modules/@comis/agent/dist/context-engine/constants.js +11 -0
  11. package/node_modules/@comis/agent/dist/context-engine/index.d.ts +1 -1
  12. package/node_modules/@comis/agent/dist/context-engine/index.js +1 -1
  13. package/node_modules/@comis/agent/dist/context-engine/llm-compaction.js +32 -18
  14. package/node_modules/@comis/agent/dist/executor/cache-break-diff-writer.d.ts +2 -0
  15. package/node_modules/@comis/agent/dist/executor/cache-break-diff-writer.js +36 -0
  16. package/node_modules/@comis/agent/dist/executor/executor-post-execution.d.ts +12 -0
  17. package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +117 -27
  18. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.d.ts +1 -0
  19. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +16 -4
  20. package/node_modules/@comis/agent/dist/executor/executor-stream-setup.js +17 -1
  21. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +29 -1
  22. package/node_modules/@comis/agent/dist/executor/prompt-assembly.d.ts +8 -1
  23. package/node_modules/@comis/agent/dist/executor/prompt-assembly.js +22 -5
  24. package/node_modules/@comis/agent/dist/executor/session-snapshot-cleanup.js +3 -1
  25. package/node_modules/@comis/agent/dist/executor/stream-wrappers/index.d.ts +2 -0
  26. package/node_modules/@comis/agent/dist/executor/stream-wrappers/index.js +2 -0
  27. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.d.ts +9 -0
  28. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +65 -3
  29. package/node_modules/@comis/agent/dist/executor/stream-wrappers/stub-filter-injector.d.ts +28 -0
  30. package/node_modules/@comis/agent/dist/executor/stream-wrappers/stub-filter-injector.js +63 -0
  31. package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +18 -1
  32. package/node_modules/@comis/agent/dist/executor/tool-deferral.js +275 -133
  33. package/node_modules/@comis/agent/dist/executor/ttl-guard.d.ts +6 -0
  34. package/node_modules/@comis/agent/dist/executor/ttl-guard.js +8 -0
  35. package/node_modules/@comis/agent/dist/session/comis-session-manager.js +7 -2
  36. package/node_modules/@comis/agent/package.json +1 -1
  37. package/node_modules/@comis/channels/dist/shared/typing-controller.d.ts +7 -0
  38. package/node_modules/@comis/channels/dist/shared/typing-controller.js +33 -0
  39. package/node_modules/@comis/channels/package.json +1 -1
  40. package/node_modules/@comis/cli/dist/commands/daemon.js +116 -28
  41. package/node_modules/@comis/cli/dist/doctor/checks/channel-health.js +2 -2
  42. package/node_modules/@comis/cli/dist/wizard/index.d.ts +2 -3
  43. package/node_modules/@comis/cli/dist/wizard/index.js +2 -3
  44. package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +1 -1
  45. package/node_modules/@comis/cli/dist/wizard/types.d.ts +1 -2
  46. package/node_modules/@comis/cli/dist/wizard/types.js +1 -2
  47. package/node_modules/@comis/cli/package.json +1 -1
  48. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +64 -10
  49. package/node_modules/@comis/core/dist/config/schema-agent.js +19 -0
  50. package/node_modules/@comis/core/dist/config/schema-skills.d.ts +16 -2
  51. package/node_modules/@comis/core/dist/config/schema-skills.js +9 -2
  52. package/node_modules/@comis/core/dist/config/schema.d.ts +19 -11
  53. package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +8 -0
  54. package/node_modules/@comis/core/package.json +1 -1
  55. package/node_modules/@comis/daemon/dist/daemon.js +2 -1
  56. package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +19 -2
  57. package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.js +10 -0
  58. package/node_modules/@comis/daemon/dist/wiring/setup-memory.d.ts +2 -0
  59. package/node_modules/@comis/daemon/dist/wiring/setup-memory.js +15 -0
  60. package/node_modules/@comis/daemon/dist/wiring/setup-schedulers.js +1 -0
  61. package/node_modules/@comis/daemon/dist/wiring/setup-shutdown.d.ts +1 -0
  62. package/node_modules/@comis/daemon/dist/wiring/setup-shutdown.js +4 -0
  63. package/node_modules/@comis/daemon/package.json +1 -1
  64. package/node_modules/@comis/gateway/package.json +1 -1
  65. package/node_modules/@comis/infra/package.json +1 -1
  66. package/node_modules/@comis/memory/package.json +1 -1
  67. package/node_modules/@comis/scheduler/dist/cron/cron-types.d.ts +11 -0
  68. package/node_modules/@comis/scheduler/dist/cron/cron-types.js +11 -0
  69. package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.d.ts +26 -1
  70. package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +23 -2
  71. package/node_modules/@comis/scheduler/dist/heartbeat/heartbeat-config.d.ts +7 -0
  72. package/node_modules/@comis/scheduler/dist/heartbeat/heartbeat-config.js +2 -0
  73. package/node_modules/@comis/scheduler/package.json +1 -1
  74. package/node_modules/@comis/shared/package.json +1 -1
  75. package/node_modules/@comis/skills/dist/index.d.ts +1 -1
  76. package/node_modules/@comis/skills/dist/index.js +1 -1
  77. package/node_modules/@comis/skills/dist/policy/tool-policy.js +25 -0
  78. package/node_modules/@comis/skills/package.json +1 -1
  79. package/package.json +12 -12
@@ -33,6 +33,13 @@
33
33
  * text deltas from the model). Active generation keeps the indicator
34
34
  * alive beyond the initial TTL window.
35
35
  *
36
+ * 6. **Internal TTL refresh (liveness watchdog)**: While active and not
37
+ * sealed, an internal 30s interval calls resetTtl() unconditionally.
38
+ * This is a belt-and-braces mechanism for long silences (extended
39
+ * thinking, slow tools, inter-turn gaps). External refreshTtl() calls
40
+ * from content signals remain the primary mechanism; this timer is
41
+ * additive, not a replacement.
42
+ *
36
43
  * Typing failures are non-fatal: errors from `sendTyping` are caught
37
44
  * and logged but never propagated to the caller.
38
45
  *
@@ -34,6 +34,13 @@
34
34
  * text deltas from the model). Active generation keeps the indicator
35
35
  * alive beyond the initial TTL window.
36
36
  *
37
+ * 6. **Internal TTL refresh (liveness watchdog)**: While active and not
38
+ * sealed, an internal 30s interval calls resetTtl() unconditionally.
39
+ * This is a belt-and-braces mechanism for long silences (extended
40
+ * thinking, slow tools, inter-turn gaps). External refreshTtl() calls
41
+ * from content signals remain the primary mechanism; this timer is
42
+ * additive, not a replacement.
43
+ *
37
44
  * Typing failures are non-fatal: errors from `sendTyping` are caught
38
45
  * and logged but never propagated to the caller.
39
46
  *
@@ -42,6 +49,11 @@
42
49
  // ---------------------------------------------------------------------------
43
50
  // Factory
44
51
  // ---------------------------------------------------------------------------
52
+ /** Internal liveness refresh interval. MUST be strictly less than default
53
+ * ttlMs (60_000) so an active, non-sealed controller cannot have its TTL
54
+ * expire without an explicit stop() or circuit-breaker trip. Matches the
55
+ * tool-active refresh cadence in execution-execute.ts for consistency. */
56
+ const INTERNAL_TTL_REFRESH_MS = 30_000;
45
57
  /**
46
58
  * Create a typing controller that sends platform typing indicators at a
47
59
  * configurable refresh interval.
@@ -59,6 +71,7 @@ export function createTypingController(config, sendTyping, logger) {
59
71
  let consecutiveFailures = 0;
60
72
  let tickInFlight = false;
61
73
  let ttlTimer = null;
74
+ let ttlRefreshTimer = null;
62
75
  const threshold = config.circuitBreakerThreshold ?? 3;
63
76
  /** Fire-and-forget typing send with tick serialization and circuit breaker. */
64
77
  function doSendTyping(chatId) {
@@ -83,6 +96,10 @@ export function createTypingController(config, sendTyping, logger) {
83
96
  clearTimeout(ttlTimer);
84
97
  ttlTimer = null;
85
98
  }
99
+ if (ttlRefreshTimer !== null) {
100
+ clearInterval(ttlRefreshTimer);
101
+ ttlRefreshTimer = null;
102
+ }
86
103
  }
87
104
  else {
88
105
  logger?.warn({ err, chatId, hint: "Typing indicator delivery failed; non-blocking", errorKind: "platform" }, "Typing indicator send failed");
@@ -106,6 +123,10 @@ export function createTypingController(config, sendTyping, logger) {
106
123
  clearInterval(timer);
107
124
  timer = null;
108
125
  }
126
+ if (ttlRefreshTimer !== null) {
127
+ clearInterval(ttlRefreshTimer);
128
+ ttlRefreshTimer = null;
129
+ }
109
130
  }
110
131
  }, config.ttlMs ?? 60_000);
111
132
  }
@@ -125,6 +146,14 @@ export function createTypingController(config, sendTyping, logger) {
125
146
  }, config.refreshMs);
126
147
  // Arm the TTL timer.
127
148
  resetTtl();
149
+ // Belt-and-braces liveness watchdog: refresh the TTL on a fixed cadence so
150
+ // the indicator survives long silences (extended thinking, slow tools,
151
+ // inter-turn gaps) even when no external signal calls refreshTtl().
152
+ ttlRefreshTimer = setInterval(() => {
153
+ if (active && !sealed) {
154
+ resetTtl();
155
+ }
156
+ }, INTERNAL_TTL_REFRESH_MS);
128
157
  },
129
158
  stop() {
130
159
  active = false;
@@ -137,6 +166,10 @@ export function createTypingController(config, sendTyping, logger) {
137
166
  clearTimeout(ttlTimer);
138
167
  ttlTimer = null;
139
168
  }
169
+ if (ttlRefreshTimer !== null) {
170
+ clearInterval(ttlRefreshTimer);
171
+ ttlRefreshTimer = null;
172
+ }
140
173
  },
141
174
  refreshTtl() {
142
175
  if (!active || sealed)
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/channels",
3
3
  "private": true,
4
- "version": "1.0.14",
4
+ "version": "1.0.16",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "Chat platform adapters — Discord, Telegram, Slack, WhatsApp, Signal, iMessage, IRC, LINE",
@@ -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
- const child = spawn("journalctl", jArgs, { stdio: "inherit" });
543
- child.on("error", (err) => {
544
- error(`Failed to read logs: ${err.message}`);
545
- process.exit(1);
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
- // Try journalctl directly first (works when user is in systemd-journal group),
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
- if (stdout.trim()) {
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
- const child = spawn("pm2", args, { stdio: "inherit" });
581
- child.on("error", (err) => {
582
- error(`Failed to read logs: ${err.message}`);
583
- process.exit(1);
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
- const child = spawn("tail", args, { stdio: "inherit" });
598
- child.on("error", (err) => {
599
- error(`Failed to read logs: ${err.message}`);
600
- process.exit(1);
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
  }
@@ -8,12 +8,12 @@
8
8
  *
9
9
  * @module
10
10
  */
11
- import { CHANNEL_ENV_KEYS } from "../../wizard/flow-types.js";
11
+ import { CHANNEL_ENV_KEYS } from "../../wizard/index.js";
12
12
  const CATEGORY = "channels";
13
13
  /**
14
14
  * Map of channel types to their required credential environment variable names.
15
15
  *
16
- * Sourced from the shared CHANNEL_ENV_KEYS constant in flow-types.
16
+ * Sourced from the shared CHANNEL_ENV_KEYS constant in the wizard module.
17
17
  * These are format checks only -- we verify the credential appears to be
18
18
  * a non-empty string, not that it's a valid API key.
19
19
  */
@@ -6,9 +6,8 @@
6
6
  * init command, tests, future phases) imports from this single entry
7
7
  * point rather than reaching into individual wizard files.
8
8
  *
9
- * Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts)
10
- * are NOT re-exported here -- they remain for backward compatibility
11
- * but are not part of the new wizard architecture.
9
+ * Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts,
10
+ * config-writer.ts) were removed -- superseded by the step-based architecture.
12
11
  *
13
12
  * @module
14
13
  */
@@ -7,9 +7,8 @@
7
7
  * init command, tests, future phases) imports from this single entry
8
8
  * point rather than reaching into individual wizard files.
9
9
  *
10
- * Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts)
11
- * are NOT re-exported here -- they remain for backward compatibility
12
- * but are not part of the new wizard architecture.
10
+ * Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts,
11
+ * config-writer.ts) were removed -- superseded by the step-based architecture.
13
12
  *
14
13
  * @module
15
14
  */
@@ -17,7 +17,7 @@ import { updateState, heading, success as themeSuccess, PROVIDER_ENV_KEYS, CHANN
17
17
  /**
18
18
  * Get a sensible default model for a provider.
19
19
  *
20
- * Matches the defaults in the existing config-writer.ts.
20
+ * Matches the defaults used by the wizard.
21
21
  */
22
22
  function getDefaultModel(provider) {
23
23
  if (!provider)
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Foundational types and constants for the init wizard redesign.
3
3
  *
4
- * Replaces the role of flow-types.ts with a richer type system
5
- * that supports the full wizard architecture: immutable state
4
+ * Core type system for the wizard architecture: immutable state
6
5
  * accumulation, structured validation, and multi-flow support.
7
6
  *
8
7
  * @module
@@ -2,8 +2,7 @@
2
2
  /**
3
3
  * Foundational types and constants for the init wizard redesign.
4
4
  *
5
- * Replaces the role of flow-types.ts with a richer type system
6
- * that supports the full wizard architecture: immutable state
5
+ * Core type system for the wizard architecture: immutable state
7
6
  * accumulation, structured validation, and multi-flow support.
8
7
  *
9
8
  * @module
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/cli",
3
3
  "private": true,
4
- "version": "1.0.14",
4
+ "version": "1.0.16",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "Command-line interface for the Comis AI agent platform",
@@ -550,9 +550,9 @@ export declare const BootstrapConfigSchema: z.ZodObject<{
550
550
  maxChars: z.ZodDefault<z.ZodNumber>;
551
551
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
552
552
  promptMode: z.ZodDefault<z.ZodEnum<{
553
- minimal: "minimal";
554
- full: "full";
555
553
  none: "none";
554
+ full: "full";
555
+ minimal: "minimal";
556
556
  }>>;
557
557
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
558
558
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -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>;
@@ -822,9 +826,9 @@ export declare const AgentConfigSchema: z.ZodObject<{
822
826
  maxChars: z.ZodDefault<z.ZodNumber>;
823
827
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
824
828
  promptMode: z.ZodDefault<z.ZodEnum<{
825
- minimal: "minimal";
826
- full: "full";
827
829
  none: "none";
830
+ full: "full";
831
+ minimal: "minimal";
828
832
  }>>;
829
833
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
830
834
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -987,6 +991,17 @@ export declare const PerAgentHeartbeatConfigSchema: z.ZodObject<{
987
991
  alertCooldownMs: z.ZodOptional<z.ZodNumber>;
988
992
  /** Override stuck detection timeout in ms (per-agent) */
989
993
  staleMs: z.ZodOptional<z.ZodNumber>;
994
+ /** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
995
+ *
996
+ * Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
997
+ * Opt-in: omitting this field preserves the agent's interactive tool set for
998
+ * heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
999
+ * preset in `packages/skills/src/policy/tool-policy.ts`. */
1000
+ toolPolicy: z.ZodOptional<z.ZodObject<{
1001
+ profile: z.ZodDefault<z.ZodString>;
1002
+ allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
1003
+ deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
1004
+ }, z.core.$strip>>;
990
1005
  }, z.core.$strict>;
991
1006
  export type HeartbeatTarget = z.infer<typeof HeartbeatTargetSchema>;
992
1007
  export type PerAgentHeartbeatConfig = z.infer<typeof PerAgentHeartbeatConfigSchema>;
@@ -1046,6 +1061,17 @@ export declare const PerAgentSchedulerConfigSchema: z.ZodObject<{
1046
1061
  alertCooldownMs: z.ZodOptional<z.ZodNumber>;
1047
1062
  /** Override stuck detection timeout in ms (per-agent) */
1048
1063
  staleMs: z.ZodOptional<z.ZodNumber>;
1064
+ /** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
1065
+ *
1066
+ * Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
1067
+ * Opt-in: omitting this field preserves the agent's interactive tool set for
1068
+ * heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
1069
+ * preset in `packages/skills/src/policy/tool-policy.ts`. */
1070
+ toolPolicy: z.ZodOptional<z.ZodObject<{
1071
+ profile: z.ZodDefault<z.ZodString>;
1072
+ allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
1073
+ deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
1074
+ }, z.core.$strip>>;
1049
1075
  }, z.core.$strict>>;
1050
1076
  }, z.core.$strict>;
1051
1077
  /** Per-agent configuration: extends AgentConfigSchema with skills, scheduler, session, concurrency. */
@@ -1080,6 +1106,9 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
1080
1106
  "multi-zone": "multi-zone";
1081
1107
  single: "single";
1082
1108
  }>>;
1109
+ advancedCacheOptimization: z.ZodDefault<z.ZodObject<{
1110
+ enableRecentZonePromotion: z.ZodDefault<z.ZodBoolean>;
1111
+ }, z.core.$strip>>;
1083
1112
  geminiCache: z.ZodDefault<z.ZodObject<{
1084
1113
  enabled: z.ZodDefault<z.ZodBoolean>;
1085
1114
  maxActiveCaches: z.ZodDefault<z.ZodNumber>;
@@ -1150,9 +1179,9 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
1150
1179
  maxChars: z.ZodDefault<z.ZodNumber>;
1151
1180
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
1152
1181
  promptMode: z.ZodDefault<z.ZodEnum<{
1153
- minimal: "minimal";
1154
- full: "full";
1155
1182
  none: "none";
1183
+ full: "full";
1184
+ minimal: "minimal";
1156
1185
  }>>;
1157
1186
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
1158
1187
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -1259,11 +1288,11 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
1259
1288
  }, z.core.$strict>>;
1260
1289
  toolPolicy: z.ZodDefault<z.ZodObject<{
1261
1290
  profile: z.ZodDefault<z.ZodEnum<{
1291
+ full: "full";
1262
1292
  minimal: "minimal";
1263
1293
  coding: "coding";
1264
1294
  messaging: "messaging";
1265
1295
  supervisor: "supervisor";
1266
- full: "full";
1267
1296
  }>>;
1268
1297
  allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
1269
1298
  deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -1351,6 +1380,17 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
1351
1380
  alertCooldownMs: z.ZodOptional<z.ZodNumber>;
1352
1381
  /** Override stuck detection timeout in ms (per-agent) */
1353
1382
  staleMs: z.ZodOptional<z.ZodNumber>;
1383
+ /** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
1384
+ *
1385
+ * Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
1386
+ * Opt-in: omitting this field preserves the agent's interactive tool set for
1387
+ * heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
1388
+ * preset in `packages/skills/src/policy/tool-policy.ts`. */
1389
+ toolPolicy: z.ZodOptional<z.ZodObject<{
1390
+ profile: z.ZodDefault<z.ZodString>;
1391
+ allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
1392
+ deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
1393
+ }, z.core.$strip>>;
1354
1394
  }, z.core.$strict>>;
1355
1395
  }, z.core.$strict>>;
1356
1396
  session: z.ZodOptional<z.ZodObject<{
@@ -1740,6 +1780,9 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
1740
1780
  "multi-zone": "multi-zone";
1741
1781
  single: "single";
1742
1782
  }>>;
1783
+ advancedCacheOptimization: z.ZodDefault<z.ZodObject<{
1784
+ enableRecentZonePromotion: z.ZodDefault<z.ZodBoolean>;
1785
+ }, z.core.$strip>>;
1743
1786
  geminiCache: z.ZodDefault<z.ZodObject<{
1744
1787
  enabled: z.ZodDefault<z.ZodBoolean>;
1745
1788
  maxActiveCaches: z.ZodDefault<z.ZodNumber>;
@@ -1810,9 +1853,9 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
1810
1853
  maxChars: z.ZodDefault<z.ZodNumber>;
1811
1854
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
1812
1855
  promptMode: z.ZodDefault<z.ZodEnum<{
1813
- minimal: "minimal";
1814
- full: "full";
1815
1856
  none: "none";
1857
+ full: "full";
1858
+ minimal: "minimal";
1816
1859
  }>>;
1817
1860
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
1818
1861
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -1919,11 +1962,11 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
1919
1962
  }, z.core.$strict>>;
1920
1963
  toolPolicy: z.ZodDefault<z.ZodObject<{
1921
1964
  profile: z.ZodDefault<z.ZodEnum<{
1965
+ full: "full";
1922
1966
  minimal: "minimal";
1923
1967
  coding: "coding";
1924
1968
  messaging: "messaging";
1925
1969
  supervisor: "supervisor";
1926
- full: "full";
1927
1970
  }>>;
1928
1971
  allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
1929
1972
  deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -2011,6 +2054,17 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
2011
2054
  alertCooldownMs: z.ZodOptional<z.ZodNumber>;
2012
2055
  /** Override stuck detection timeout in ms (per-agent) */
2013
2056
  staleMs: z.ZodOptional<z.ZodNumber>;
2057
+ /** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
2058
+ *
2059
+ * Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
2060
+ * Opt-in: omitting this field preserves the agent's interactive tool set for
2061
+ * heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
2062
+ * preset in `packages/skills/src/policy/tool-policy.ts`. */
2063
+ toolPolicy: z.ZodOptional<z.ZodObject<{
2064
+ profile: z.ZodDefault<z.ZodString>;
2065
+ allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
2066
+ deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
2067
+ }, z.core.$strip>>;
2014
2068
  }, z.core.$strict>>;
2015
2069
  }, z.core.$strict>>;
2016
2070
  session: z.ZodOptional<z.ZodObject<{
@@ -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. */
@@ -674,6 +682,17 @@ export const PerAgentHeartbeatConfigSchema = z.strictObject({
674
682
  alertCooldownMs: z.number().int().positive().optional(),
675
683
  /** Override stuck detection timeout in ms (per-agent) */
676
684
  staleMs: z.number().int().positive().optional(),
685
+ /** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
686
+ *
687
+ * Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
688
+ * Opt-in: omitting this field preserves the agent's interactive tool set for
689
+ * heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
690
+ * preset in `packages/skills/src/policy/tool-policy.ts`. */
691
+ toolPolicy: z.object({
692
+ profile: z.string().default("full"),
693
+ allow: z.array(z.string()).default([]),
694
+ deny: z.array(z.string()).default([]),
695
+ }).optional(),
677
696
  });
678
697
  /** Per-agent scheduler configuration (wraps cron and heartbeat settings). */
679
698
  export const PerAgentSchedulerConfigSchema = z.strictObject({
@@ -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 to consider a match (BM25-only mode). Default 0.8. */
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 to consider a match (BM25-only mode). Default 0.8. */
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 to consider a match (BM25-only mode). Default 0.8. */
97
- minBm25Score: z.number().min(0).default(0.8),
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
  });