comisai 1.0.18 → 1.0.22

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 (149) hide show
  1. package/dist/cli-entry.js +0 -0
  2. package/node_modules/@comis/agent/dist/context-engine/context-engine.js +43 -2
  3. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +51 -0
  4. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +110 -0
  5. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.d.ts +54 -0
  6. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.js +145 -0
  7. package/node_modules/@comis/agent/dist/context-engine/types-core.d.ts +17 -0
  8. package/node_modules/@comis/agent/dist/executor/error-classifier.d.ts +11 -1
  9. package/node_modules/@comis/agent/dist/executor/error-classifier.js +13 -0
  10. package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.d.ts +1 -0
  11. package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.js +55 -0
  12. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +106 -5
  13. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +1 -0
  14. package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +1 -4
  15. package/node_modules/@comis/agent/dist/executor/replay-drift-detector.d.ts +85 -0
  16. package/node_modules/@comis/agent/dist/executor/replay-drift-detector.js +92 -0
  17. package/node_modules/@comis/agent/dist/executor/signature-block-scrubber.d.ts +34 -0
  18. package/node_modules/@comis/agent/dist/executor/signature-block-scrubber.js +69 -0
  19. package/node_modules/@comis/agent/dist/executor/signed-replay-detector.d.ts +39 -0
  20. package/node_modules/@comis/agent/dist/executor/signed-replay-detector.js +72 -0
  21. package/node_modules/@comis/agent/package.json +1 -1
  22. package/node_modules/@comis/channels/package.json +1 -1
  23. package/node_modules/@comis/cli/dist/cli.js +0 -0
  24. package/node_modules/@comis/cli/dist/wizard/steps/12-finish.d.ts +4 -5
  25. package/node_modules/@comis/cli/dist/wizard/steps/12-finish.js +99 -40
  26. package/node_modules/@comis/cli/package.json +1 -1
  27. package/node_modules/@comis/core/dist/config/git-manager.js +10 -4
  28. package/node_modules/@comis/core/dist/config/index.d.ts +1 -0
  29. package/node_modules/@comis/core/dist/config/index.js +2 -0
  30. package/node_modules/@comis/core/dist/config/managed-sections.d.ts +67 -0
  31. package/node_modules/@comis/core/dist/config/managed-sections.js +124 -0
  32. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +28 -10
  33. package/node_modules/@comis/core/dist/config/schema-agent.js +6 -0
  34. package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +2 -2
  35. package/node_modules/@comis/core/dist/config/schema.d.ts +65 -64
  36. package/node_modules/@comis/core/dist/event-bus/events-messaging.d.ts +16 -0
  37. package/node_modules/@comis/core/dist/exports/config.d.ts +1 -1
  38. package/node_modules/@comis/core/dist/exports/config.js +1 -1
  39. package/node_modules/@comis/core/package.json +1 -1
  40. package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/init-skill.py +0 -0
  41. package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/validate-skill.py +0 -0
  42. package/node_modules/@comis/daemon/dist/daemon.js +0 -0
  43. package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +20 -7
  44. package/node_modules/@comis/daemon/dist/rpc/session-handlers.js +27 -1
  45. package/node_modules/@comis/daemon/package.json +1 -1
  46. package/node_modules/@comis/gateway/package.json +1 -1
  47. package/node_modules/@comis/infra/package.json +1 -1
  48. package/node_modules/@comis/memory/package.json +1 -1
  49. package/node_modules/@comis/scheduler/package.json +1 -1
  50. package/node_modules/@comis/shared/package.json +1 -1
  51. package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +23 -8
  52. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +1 -1
  53. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +18 -14
  54. package/node_modules/@comis/skills/dist/builtin/platform/unified-session-tool.js +1 -1
  55. package/node_modules/@comis/skills/package.json +1 -1
  56. package/node_modules/@comis/web/package.json +1 -1
  57. package/package.json +24 -26
  58. package/node_modules/@comis/agent/dist/provider/response/strip-minimax-xml.d.ts +0 -9
  59. package/node_modules/@comis/agent/dist/provider/response/strip-minimax-xml.js +0 -17
  60. package/node_modules/@comis/agent/dist/provider/response/strip-model-tokens.d.ts +0 -13
  61. package/node_modules/@comis/agent/dist/provider/response/strip-model-tokens.js +0 -19
  62. package/node_modules/@comis/agent/dist/provider/response/strip-tool-text.d.ts +0 -11
  63. package/node_modules/@comis/agent/dist/provider/response/strip-tool-text.js +0 -32
  64. package/node_modules/@comis/agent/dist/safety/follow-through-detector.d.ts +0 -46
  65. package/node_modules/@comis/agent/dist/safety/follow-through-detector.js +0 -76
  66. package/node_modules/@comis/agent/dist/safety/post-compaction-safety.d.ts +0 -30
  67. package/node_modules/@comis/agent/dist/safety/post-compaction-safety.js +0 -51
  68. package/node_modules/@comis/agent/dist/safety/schema-normalizer.d.ts +0 -37
  69. package/node_modules/@comis/agent/dist/safety/schema-normalizer.js +0 -137
  70. package/node_modules/@comis/agent/dist/safety/schema-pruning.d.ts +0 -50
  71. package/node_modules/@comis/agent/dist/safety/schema-pruning.js +0 -112
  72. package/node_modules/@comis/agent/dist/safety/tool-image-sanitizer.d.ts +0 -43
  73. package/node_modules/@comis/agent/dist/safety/tool-image-sanitizer.js +0 -96
  74. package/node_modules/@comis/agent/dist/safety/tool-sanitizer.d.ts +0 -44
  75. package/node_modules/@comis/agent/dist/safety/tool-sanitizer.js +0 -94
  76. package/node_modules/@comis/channels/dist/shared/thinking-tag-filter.d.ts +0 -28
  77. package/node_modules/@comis/channels/dist/shared/thinking-tag-filter.js +0 -206
  78. package/node_modules/@comis/cli/dist/wizard/config-writer.d.ts +0 -25
  79. package/node_modules/@comis/cli/dist/wizard/config-writer.js +0 -144
  80. package/node_modules/@comis/cli/dist/wizard/flow-types.d.ts +0 -48
  81. package/node_modules/@comis/cli/dist/wizard/flow-types.js +0 -70
  82. package/node_modules/@comis/cli/dist/wizard/manual-flow.d.ts +0 -21
  83. package/node_modules/@comis/cli/dist/wizard/manual-flow.js +0 -345
  84. package/node_modules/@comis/cli/dist/wizard/quickstart-flow.d.ts +0 -21
  85. package/node_modules/@comis/cli/dist/wizard/quickstart-flow.js +0 -116
  86. package/node_modules/@comis/core/dist/config/schema-agent-model.d.ts +0 -135
  87. package/node_modules/@comis/core/dist/config/schema-agent-model.js +0 -114
  88. package/node_modules/@comis/core/dist/config/schema-agent-session.d.ts +0 -177
  89. package/node_modules/@comis/core/dist/config/schema-agent-session.js +0 -116
  90. package/node_modules/@comis/core/dist/config/schema-context-engine.d.ts +0 -92
  91. package/node_modules/@comis/core/dist/config/schema-context-engine.js +0 -92
  92. package/node_modules/@comis/core/dist/config/schema-context-guard.d.ts +0 -34
  93. package/node_modules/@comis/core/dist/config/schema-context-guard.js +0 -32
  94. package/node_modules/@comis/core/dist/config/schema-delivery-mirror.d.ts +0 -27
  95. package/node_modules/@comis/core/dist/config/schema-delivery-mirror.js +0 -26
  96. package/node_modules/@comis/core/dist/config/schema-delivery-queue.d.ts +0 -31
  97. package/node_modules/@comis/core/dist/config/schema-delivery-queue.js +0 -30
  98. package/node_modules/@comis/core/dist/config/schema-delivery-timing.d.ts +0 -41
  99. package/node_modules/@comis/core/dist/config/schema-delivery-timing.js +0 -31
  100. package/node_modules/@comis/core/dist/config/schema-monitoring.d.ts +0 -105
  101. package/node_modules/@comis/core/dist/config/schema-monitoring.js +0 -67
  102. package/node_modules/@comis/core/dist/ports/media-ports.d.ts +0 -278
  103. package/node_modules/@comis/core/dist/ports/media-ports.js +0 -1
  104. package/node_modules/@comis/core/dist/security/input-guard.d.ts +0 -46
  105. package/node_modules/@comis/core/dist/security/input-guard.js +0 -166
  106. package/node_modules/@comis/core/dist/security/scoped-secret-manager.d.ts +0 -38
  107. package/node_modules/@comis/core/dist/security/scoped-secret-manager.js +0 -94
  108. package/node_modules/@comis/daemon/dist/observability/delivery-context.d.ts +0 -37
  109. package/node_modules/@comis/daemon/dist/observability/delivery-context.js +0 -1
  110. package/node_modules/@comis/daemon/dist/observability/log-level-manager.d.ts +0 -23
  111. package/node_modules/@comis/daemon/dist/observability/log-level-manager.js +0 -34
  112. package/node_modules/@comis/daemon/dist/observability/log-transport.d.ts +0 -44
  113. package/node_modules/@comis/daemon/dist/observability/log-transport.js +0 -74
  114. package/node_modules/@comis/daemon/dist/observability/obs-write-buffer.d.ts +0 -53
  115. package/node_modules/@comis/daemon/dist/observability/obs-write-buffer.js +0 -68
  116. package/node_modules/@comis/daemon/dist/observability/types.d.ts +0 -6
  117. package/node_modules/@comis/daemon/dist/observability/types.js +0 -1
  118. package/node_modules/@comis/daemon/dist/wiring/seed-bundled-skills.d.ts +0 -41
  119. package/node_modules/@comis/daemon/dist/wiring/seed-bundled-skills.js +0 -84
  120. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-mirror.d.ts +0 -24
  121. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-mirror.js +0 -88
  122. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-queue.d.ts +0 -31
  123. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-queue.js +0 -132
  124. package/node_modules/@comis/daemon/dist/wiring/setup-monitoring.d.ts +0 -38
  125. package/node_modules/@comis/daemon/dist/wiring/setup-monitoring.js +0 -100
  126. package/node_modules/@comis/daemon/dist/wiring/setup-rpc-bridge.d.ts +0 -34
  127. package/node_modules/@comis/daemon/dist/wiring/setup-rpc-bridge.js +0 -52
  128. package/node_modules/@comis/daemon/dist/wiring/setup-task-extraction.d.ts +0 -41
  129. package/node_modules/@comis/daemon/dist/wiring/setup-task-extraction.js +0 -86
  130. package/node_modules/@comis/memory/dist/embedding-cache.d.ts +0 -36
  131. package/node_modules/@comis/memory/dist/embedding-cache.js +0 -94
  132. package/node_modules/@comis/skills/dist/bridge/tool-output-schemas.d.ts +0 -17
  133. package/node_modules/@comis/skills/dist/bridge/tool-output-schemas.js +0 -125
  134. package/node_modules/@comis/skills/dist/bridge/tool-parallelism-metadata.d.ts +0 -14
  135. package/node_modules/@comis/skills/dist/bridge/tool-parallelism-metadata.js +0 -92
  136. package/node_modules/@comis/skills/dist/bridge/tool-result-caps.d.ts +0 -14
  137. package/node_modules/@comis/skills/dist/bridge/tool-result-caps.js +0 -36
  138. package/node_modules/@comis/skills/dist/bridge/tool-search-hints.d.ts +0 -15
  139. package/node_modules/@comis/skills/dist/bridge/tool-search-hints.js +0 -68
  140. package/node_modules/@comis/skills/dist/bridge/tool-validators.d.ts +0 -11
  141. package/node_modules/@comis/skills/dist/bridge/tool-validators.js +0 -105
  142. package/node_modules/@comis/skills/dist/builtin/file/find-sort-wrapper.d.ts +0 -22
  143. package/node_modules/@comis/skills/dist/builtin/file/find-sort-wrapper.js +0 -95
  144. package/node_modules/@comis/skills/dist/builtin/file/grep-output-mode-wrapper.d.ts +0 -24
  145. package/node_modules/@comis/skills/dist/builtin/file/grep-output-mode-wrapper.js +0 -167
  146. package/node_modules/@comis/skills/dist/builtin/task-plan-tool.d.ts +0 -25
  147. package/node_modules/@comis/skills/dist/builtin/task-plan-tool.js +0 -67
  148. package/node_modules/@comis/skills/dist/integrations/mcp-tool-bridge.d.ts +0 -75
  149. package/node_modules/@comis/skills/dist/integrations/mcp-tool-bridge.js +0 -235
@@ -3,15 +3,14 @@
3
3
  * Finish step -- step 12 of the init wizard.
4
4
  *
5
5
  * Displays a quick-reference card with essential CLI commands,
6
- * gateway access info with WebSocket URL and token location,
7
- * offers shell completion setup, and ends with a branded outro.
8
- *
9
- * This is the user's last impression of the wizard -- clear, concise,
10
- * and immediately actionable.
6
+ * gateway access info (URLs), the full access token with a secure-storage
7
+ * warning, and -- when the gateway binds loopback-only -- a copy-paste SSH
8
+ * tunnel recipe so non-technical users can open the dashboard from another
9
+ * computer. Ends with a shell-completion offer and a branded outro.
11
10
  *
12
11
  * @module
13
12
  */
14
- import { updateState, sectionSeparator, brand } from "../index.js";
13
+ import { brand, info, sectionSeparator, updateState, warning } from "../index.js";
15
14
  // ---------- Helpers ----------
16
15
  /**
17
16
  * Build the quick-reference card lines.
@@ -31,44 +30,94 @@ function buildReferenceCard() {
31
30
  const lines = commands.map(([label, cmd]) => ` ${label.padEnd(18)}${brand(cmd)}`);
32
31
  return lines.join("\n");
33
32
  }
33
+ function resolveHost(gateway) {
34
+ switch (gateway.bindMode) {
35
+ case "loopback":
36
+ return "127.0.0.1";
37
+ case "lan":
38
+ return "0.0.0.0";
39
+ case "custom":
40
+ return gateway.customIp ?? "127.0.0.1";
41
+ }
42
+ }
34
43
  /**
35
- * Build the gateway access info block from wizard state.
36
- *
37
- * Returns undefined if no gateway config exists.
44
+ * URLs block dashboard + websocket only. No auth hints here;
45
+ * the token/password lives in its own block so the user sees it
46
+ * as the thing to copy.
38
47
  */
39
48
  function buildGatewayInfo(state) {
40
49
  if (!state.gateway)
41
50
  return undefined;
42
- let host;
43
- switch (state.gateway.bindMode) {
44
- case "loopback":
45
- host = "127.0.0.1";
46
- break;
47
- case "lan":
48
- host = "0.0.0.0";
49
- break;
50
- case "custom":
51
- host = state.gateway.customIp ?? "127.0.0.1";
52
- break;
53
- default:
54
- host = "127.0.0.1";
51
+ const host = resolveHost(state.gateway);
52
+ const { port } = state.gateway;
53
+ const lines = [];
54
+ if (state.gateway.webEnabled) {
55
+ lines.push(` Dashboard: ${brand(`http://${host}:${port}/app/`)}`);
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;
60
- let authLine;
57
+ lines.push(` WebSocket: ${brand(`ws://${host}:${port}/ws`)}`);
58
+ return lines.join("\n");
59
+ }
60
+ /**
61
+ * Access token block — prints the full token on its own line so
62
+ * copy-paste works cleanly, plus a prominent "keep secret" warning
63
+ * and storage guidance. For password auth, points the user at the
64
+ * password they already chose.
65
+ */
66
+ function buildAccessTokenBlock(state) {
67
+ if (!state.gateway)
68
+ return undefined;
61
69
  if (state.gateway.authMethod === "password") {
62
- authLine = " Auth: Password auth (in ~/.comis/.env)";
63
- }
64
- else {
65
- const tokenPreview = state.gateway.token
66
- ? `${state.gateway.token.slice(0, 8)}...`
67
- : "see file";
68
- authLine = ` Token: ${tokenPreview} (in ~/.comis/.env)`;
70
+ return [
71
+ "You chose a password for gateway access.",
72
+ "",
73
+ info("Use the password you set earlier when the dashboard asks for it."),
74
+ info("It is also stored in ~/.comis/.env — keep that file private."),
75
+ ].join("\n");
69
76
  }
70
- const lines = [wsLine, dashboardLine, authLine].filter((l) => l !== undefined);
71
- return lines.join("\n");
77
+ if (!state.gateway.token)
78
+ return undefined;
79
+ return [
80
+ "Copy this token now — you will need it to sign in to the dashboard:",
81
+ "",
82
+ ` ${brand(state.gateway.token)}`,
83
+ "",
84
+ warning("Keep it secret. Anyone with this token can control your agents."),
85
+ info("Save it in a password manager (1Password, Bitwarden, Apple Passwords)."),
86
+ info("It is also stored at ~/.comis/.env — keep that file private."),
87
+ ].join("\n");
88
+ }
89
+ /**
90
+ * SSH tunnel recipe — shown only when the gateway is loopback-only
91
+ * and the dashboard is enabled. Walks the user through ssh -N -L
92
+ * with a clear YOUR-SERVER placeholder and the localhost URL to
93
+ * open on their laptop.
94
+ */
95
+ function buildTunnelInstructions(state) {
96
+ if (!state.gateway || !state.gateway.webEnabled)
97
+ return undefined;
98
+ if (state.gateway.bindMode !== "loopback")
99
+ return undefined;
100
+ const { port } = state.gateway;
101
+ return [
102
+ "Your dashboard is only reachable from this computer right now.",
103
+ "To open it from your laptop, follow these steps one time:",
104
+ "",
105
+ ` ${brand("1.")} On your laptop, open a Terminal window and run:`,
106
+ "",
107
+ ` ${brand(`ssh -N -L ${port}:127.0.0.1:${port} root@YOUR-SERVER`)}`,
108
+ "",
109
+ ` Replace ${brand("YOUR-SERVER")} with this server's IP address or`,
110
+ " hostname (ask your hosting provider if you are not sure).",
111
+ " Leave that Terminal window open.",
112
+ "",
113
+ ` ${brand("2.")} In your laptop's web browser, open:`,
114
+ "",
115
+ ` ${brand(`http://localhost:${port}/app/`)}`,
116
+ "",
117
+ ` ${brand("3.")} Paste your access token when asked.`,
118
+ "",
119
+ info("When you are done, close the Terminal window to disconnect."),
120
+ ].join("\n");
72
121
  }
73
122
  // ---------- Step Implementation ----------
74
123
  export const finishStep = {
@@ -77,12 +126,22 @@ export const finishStep = {
77
126
  async execute(state, prompter) {
78
127
  // 1. Quick-reference card
79
128
  prompter.note(buildReferenceCard(), sectionSeparator("Quick Reference"));
80
- // 2. Gateway access info
129
+ // 2. Gateway URLs
81
130
  const gatewayInfo = buildGatewayInfo(state);
82
131
  if (gatewayInfo) {
83
132
  prompter.note(gatewayInfo, sectionSeparator("Gateway Access"));
84
133
  }
85
- // 3. Shell completion offer
134
+ // 3. Access token (or password pointer) — its own highlighted block
135
+ const tokenBlock = buildAccessTokenBlock(state);
136
+ if (tokenBlock) {
137
+ prompter.note(tokenBlock, sectionSeparator("Your Access Token"));
138
+ }
139
+ // 4. Copy-paste SSH tunnel recipe (loopback only)
140
+ const tunnelBlock = buildTunnelInstructions(state);
141
+ if (tunnelBlock) {
142
+ prompter.note(tunnelBlock, sectionSeparator("Open the Dashboard from Another Computer"));
143
+ }
144
+ // 5. Shell completion offer
86
145
  const wantCompletions = await prompter.confirm({
87
146
  message: "Enable shell completions for comis?",
88
147
  initialValue: true,
@@ -90,9 +149,9 @@ export const finishStep = {
90
149
  if (wantCompletions) {
91
150
  prompter.log.info("Run 'comis --help' to see available commands including shell completion setup");
92
151
  }
93
- // 4. Branded outro
152
+ // 6. Branded outro
94
153
  prompter.outro("Happy building! Run 'comis status' to see your system.");
95
- // 5. Return state unchanged -- wizard complete
154
+ // 7. Return state unchanged -- wizard complete
96
155
  return updateState(state, {});
97
156
  },
98
157
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/cli",
3
3
  "private": true,
4
- "version": "1.0.18",
4
+ "version": "1.0.22",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "Command-line interface for the Comis AI agent platform",
@@ -11,6 +11,7 @@
11
11
  *
12
12
  * @module
13
13
  */
14
+ import { resolve as resolvePath } from "node:path";
14
15
  import { ok, err } from "@comis/shared";
15
16
  // ---------------------------------------------------------------------------
16
17
  // Constants
@@ -179,10 +180,15 @@ export function createConfigGitManager(deps) {
179
180
  if (initialized) {
180
181
  return ok(undefined);
181
182
  }
182
- // Check if .git already exists by running git status
183
- const statusResult = await execGit(["status", "--porcelain"], configDir);
184
- if (statusResult.ok) {
185
- // Repo already exists and is functional
183
+ // Probe for an existing git repo whose toplevel IS configDir.
184
+ // `git status` succeeds whenever any ancestor has a .git directory,
185
+ // which would silently treat a parent project's repo as ours and
186
+ // commit config changes onto whatever branch is checked out there.
187
+ // Use rev-parse --show-toplevel and require an exact path match;
188
+ // otherwise fall through and `git init` our own nested repo.
189
+ const toplevelResult = await execGit(["rev-parse", "--show-toplevel"], configDir);
190
+ if (toplevelResult.ok &&
191
+ resolvePath(toplevelResult.value.trim()) === resolvePath(configDir)) {
186
192
  initialized = true;
187
193
  return ok(undefined);
188
194
  }
@@ -65,6 +65,7 @@ export { substituteEnvVars, warnSuspiciousEnvValues, extractReferencedSecretName
65
65
  export { migrateConfig } from "./migrate.js";
66
66
  export { deepMerge, mergeLayered, loadLayered } from "./layered.js";
67
67
  export { IMMUTABLE_CONFIG_PREFIXES, MUTABLE_CONFIG_OVERRIDES, isImmutableConfigPath, matchesOverridePattern, getMutableOverridesForSection } from "./immutable-keys.js";
68
+ export { MANAGED_SECTIONS, getManagedSectionRedirect, formatRedirectHint, type ManagedSectionRedirect, } from "./managed-sections.js";
68
69
  export { getConfigSchema, getConfigSections } from "./schema-serializer.js";
69
70
  export { createTimestampedBackup } from "./backup.js";
70
71
  export type { BackupDeps, BackupOptions } from "./backup.js";
@@ -58,6 +58,8 @@ export { migrateConfig } from "./migrate.js";
58
58
  export { deepMerge, mergeLayered, loadLayered } from "./layered.js";
59
59
  // Immutable key guard (runtime config mutation protection)
60
60
  export { IMMUTABLE_CONFIG_PREFIXES, MUTABLE_CONFIG_OVERRIDES, isImmutableConfigPath, matchesOverridePattern, getMutableOverridesForSection } from "./immutable-keys.js";
61
+ // Managed-section redirects (LLM-readable hints for immutable rejections)
62
+ export { MANAGED_SECTIONS, getManagedSectionRedirect, formatRedirectHint, } from "./managed-sections.js";
61
63
  // Schema serializer (Zod to JSON Schema conversion)
62
64
  export { getConfigSchema, getConfigSections } from "./schema-serializer.js";
63
65
  // Config backup (timestamped backup creation with rotation)
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Single source of truth: which immutable config sections delegate to which
3
+ * dedicated management tool, and what an LLM-readable redirect looks like.
4
+ *
5
+ * gateway/apply, gateway/patch, and config.* RPC immutability guards all
6
+ * consume this module so their hints stay in sync. Adding a new managed
7
+ * section is a one-line entry here -- no code changes anywhere else.
8
+ *
9
+ * Designed to be model-agnostic: the hint includes the tool name, the
10
+ * discover_tools call to load it, and a parameter-correct example call body
11
+ * (verified against each tool's TypeBox schema). Every capable LLM --
12
+ * Opus/Sonnet/Haiku, GPT-5, Gemini 2.5/3 Flash/Pro, Mistral -- can imitate
13
+ * the JSON example verbatim without further prompting.
14
+ *
15
+ * @module
16
+ */
17
+ /** A single redirect entry: which tool, and a parameter-correct example. */
18
+ export interface ManagedSectionRedirect {
19
+ /** Path prefix that triggers this redirect (e.g., "agents", "integrations.mcp.servers"). */
20
+ pathPrefix: string;
21
+ /** Tool name (matches the registered AgentTool name). */
22
+ tool: string;
23
+ /** One-line description that includes the tool's full action list. */
24
+ description: string;
25
+ /**
26
+ * Concrete example arguments for the most common create-equivalent action.
27
+ * Shape MUST match the tool's TypeBox parameter schema exactly -- verified
28
+ * against the tool source as of this commit. Omit when the tool has no
29
+ * "create" semantics (e.g., channels_manage cannot add new platform types).
30
+ */
31
+ exampleArgs?: Record<string, unknown>;
32
+ /**
33
+ * True when the tool fully replaces gateway-patch for this section
34
+ * (create + update + delete). False when it can only operate on entries
35
+ * already present in config.
36
+ */
37
+ fullyManaged: boolean;
38
+ }
39
+ /**
40
+ * Registered managed sections.
41
+ *
42
+ * Order matters: longest pathPrefix first, so getManagedSectionRedirect picks
43
+ * the most specific match (e.g., "integrations.mcp.servers" wins over a
44
+ * hypothetical "integrations" entry).
45
+ */
46
+ export declare const MANAGED_SECTIONS: readonly ManagedSectionRedirect[];
47
+ /**
48
+ * Resolve the management redirect for a given section/key path.
49
+ *
50
+ * Picks the longest matching pathPrefix. Matches when fullPath equals or is a
51
+ * child of a redirect's pathPrefix. Returns undefined when no dedicated tool
52
+ * covers this path -- callers fall back to the generic immutable message.
53
+ */
54
+ export declare function getManagedSectionRedirect(section: string | undefined, key?: string): ManagedSectionRedirect | undefined;
55
+ /**
56
+ * Format an LLM-readable hint for an immutability rejection.
57
+ *
58
+ * The output uses an explicit two-step "Recovery:" framing because smaller
59
+ * models (Haiku 4.5, Gemini Flash, GPT-OSS-20b) parse numbered steps more
60
+ * reliably than prose. The example call is JSON-stringified compactly so it
61
+ * can be copy-pasted into the next tool invocation.
62
+ *
63
+ * @param redirect - The matched managed-section entry
64
+ * @param mutablePaths - Optional override paths for in-place patching of
65
+ * EXISTING entries (from getMutableOverridesForSection)
66
+ */
67
+ export declare function formatRedirectHint(redirect: ManagedSectionRedirect, mutablePaths?: readonly string[]): string;
@@ -0,0 +1,124 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Single source of truth: which immutable config sections delegate to which
4
+ * dedicated management tool, and what an LLM-readable redirect looks like.
5
+ *
6
+ * gateway/apply, gateway/patch, and config.* RPC immutability guards all
7
+ * consume this module so their hints stay in sync. Adding a new managed
8
+ * section is a one-line entry here -- no code changes anywhere else.
9
+ *
10
+ * Designed to be model-agnostic: the hint includes the tool name, the
11
+ * discover_tools call to load it, and a parameter-correct example call body
12
+ * (verified against each tool's TypeBox schema). Every capable LLM --
13
+ * Opus/Sonnet/Haiku, GPT-5, Gemini 2.5/3 Flash/Pro, Mistral -- can imitate
14
+ * the JSON example verbatim without further prompting.
15
+ *
16
+ * @module
17
+ */
18
+ /**
19
+ * Registered managed sections.
20
+ *
21
+ * Order matters: longest pathPrefix first, so getManagedSectionRedirect picks
22
+ * the most specific match (e.g., "integrations.mcp.servers" wins over a
23
+ * hypothetical "integrations" entry).
24
+ */
25
+ export const MANAGED_SECTIONS = [
26
+ {
27
+ pathPrefix: "integrations.mcp.servers",
28
+ tool: "mcp_manage",
29
+ description: "Manage MCP server connections (list, status, connect, disconnect, reconnect).",
30
+ // Flat parameter shape -- verified against mcp-manage-tool.ts McpManageToolParams.
31
+ exampleArgs: {
32
+ action: "connect",
33
+ name: "<server-name>",
34
+ transport: "stdio",
35
+ command: "<command>",
36
+ args: [],
37
+ },
38
+ fullyManaged: true,
39
+ },
40
+ {
41
+ pathPrefix: "gateway.tokens",
42
+ tool: "tokens_manage",
43
+ description: "Manage gateway tokens (list, create, revoke, rotate).",
44
+ // Verified against tokens-manage-tool.ts TokensManageToolParams.
45
+ exampleArgs: { action: "create", token_id: "<token-id>", scopes: ["rpc", "ws"] },
46
+ fullyManaged: true,
47
+ },
48
+ {
49
+ pathPrefix: "channels",
50
+ tool: "channels_manage",
51
+ description: "Manage channel adapters (list, get, enable, disable, restart, configure).",
52
+ // No exampleArgs -- no create-equivalent action; channels are configured
53
+ // via operator config + media-setting toggles only.
54
+ fullyManaged: false,
55
+ },
56
+ {
57
+ pathPrefix: "agents",
58
+ tool: "agents_manage",
59
+ description: "Manage agent fleet (create, get, update, delete, suspend, resume).",
60
+ // Verified against agents-manage-tool.ts AgentsManageToolParams.
61
+ exampleArgs: {
62
+ action: "create",
63
+ agent_id: "<new-agent-id>",
64
+ config: {
65
+ name: "<display-name>",
66
+ model: "<model-id>",
67
+ provider: "<provider>",
68
+ maxSteps: 100,
69
+ },
70
+ },
71
+ fullyManaged: true,
72
+ },
73
+ ];
74
+ /**
75
+ * Resolve the management redirect for a given section/key path.
76
+ *
77
+ * Picks the longest matching pathPrefix. Matches when fullPath equals or is a
78
+ * child of a redirect's pathPrefix. Returns undefined when no dedicated tool
79
+ * covers this path -- callers fall back to the generic immutable message.
80
+ */
81
+ export function getManagedSectionRedirect(section, key) {
82
+ if (!section)
83
+ return undefined;
84
+ const fullPath = key ? `${section}.${key}` : section;
85
+ let best;
86
+ for (const candidate of MANAGED_SECTIONS) {
87
+ const matches = fullPath === candidate.pathPrefix ||
88
+ fullPath.startsWith(candidate.pathPrefix + ".");
89
+ if (matches && (!best || candidate.pathPrefix.length > best.pathPrefix.length)) {
90
+ best = candidate;
91
+ }
92
+ }
93
+ return best;
94
+ }
95
+ /**
96
+ * Format an LLM-readable hint for an immutability rejection.
97
+ *
98
+ * The output uses an explicit two-step "Recovery:" framing because smaller
99
+ * models (Haiku 4.5, Gemini Flash, GPT-OSS-20b) parse numbered steps more
100
+ * reliably than prose. The example call is JSON-stringified compactly so it
101
+ * can be copy-pasted into the next tool invocation.
102
+ *
103
+ * @param redirect - The matched managed-section entry
104
+ * @param mutablePaths - Optional override paths for in-place patching of
105
+ * EXISTING entries (from getMutableOverridesForSection)
106
+ */
107
+ export function formatRedirectHint(redirect, mutablePaths) {
108
+ const parts = [];
109
+ parts.push(`Use the "${redirect.tool}" tool: ${redirect.description}`);
110
+ if (redirect.exampleArgs) {
111
+ const example = JSON.stringify(redirect.exampleArgs);
112
+ parts.push(`Recovery: (1) call discover_tools("${redirect.tool}") to load the schema, then (2) call ${redirect.tool}(${example}).`);
113
+ }
114
+ else {
115
+ parts.push(`Load it via discover_tools("${redirect.tool}") if not yet available.`);
116
+ }
117
+ if (mutablePaths && mutablePaths.length > 0) {
118
+ parts.push(`For in-place updates of an entry that ALREADY exists, gateway/patch also accepts these specific paths: ${mutablePaths.join(", ")}.`);
119
+ }
120
+ if (!redirect.fullyManaged) {
121
+ parts.push(`Note: this tool operates on entries already present in config; adding brand-new platform types still requires operator config edits.`);
122
+ }
123
+ return parts.join(" ");
124
+ }
@@ -391,6 +391,12 @@ export declare const ContextEngineConfigSchema: z.ZodObject<{
391
391
  }>>;
392
392
  /** Number of recent assistant turns that retain thinking blocks (older turns get stripped). */
393
393
  thinkingKeepTurns: z.ZodDefault<z.ZodNumber>;
394
+ /** Idle gap (ms) above which signed thinking state is treated as drifted and
395
+ * scrubbed pre-send to avoid provider replay-rejection. Default 30 min —
396
+ * below long-TTL caches and below the 74-min production incident gap. Also
397
+ * triggers on model id / provider / api change (those checks are
398
+ * unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
399
+ replayDriftIdleMs: z.ZodDefault<z.ZodNumber>;
394
400
  /** Model for LLM compaction in "provider:modelId" format. Defaults to Haiku for cost efficiency. Empty string falls through to session model. */
395
401
  compactionModel: z.ZodDefault<z.ZodString>;
396
402
  /** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
@@ -550,9 +556,9 @@ export declare const BootstrapConfigSchema: z.ZodObject<{
550
556
  maxChars: z.ZodDefault<z.ZodNumber>;
551
557
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
552
558
  promptMode: z.ZodDefault<z.ZodEnum<{
553
- none: "none";
554
- full: "full";
555
559
  minimal: "minimal";
560
+ full: "full";
561
+ none: "none";
556
562
  }>>;
557
563
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
558
564
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -826,9 +832,9 @@ export declare const AgentConfigSchema: z.ZodObject<{
826
832
  maxChars: z.ZodDefault<z.ZodNumber>;
827
833
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
828
834
  promptMode: z.ZodDefault<z.ZodEnum<{
829
- none: "none";
830
- full: "full";
831
835
  minimal: "minimal";
836
+ full: "full";
837
+ none: "none";
832
838
  }>>;
833
839
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
834
840
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -1179,9 +1185,9 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
1179
1185
  maxChars: z.ZodDefault<z.ZodNumber>;
1180
1186
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
1181
1187
  promptMode: z.ZodDefault<z.ZodEnum<{
1182
- none: "none";
1183
- full: "full";
1184
1188
  minimal: "minimal";
1189
+ full: "full";
1190
+ none: "none";
1185
1191
  }>>;
1186
1192
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
1187
1193
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -1288,11 +1294,11 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
1288
1294
  }, z.core.$strict>>;
1289
1295
  toolPolicy: z.ZodDefault<z.ZodObject<{
1290
1296
  profile: z.ZodDefault<z.ZodEnum<{
1291
- full: "full";
1292
1297
  minimal: "minimal";
1293
1298
  coding: "coding";
1294
1299
  messaging: "messaging";
1295
1300
  supervisor: "supervisor";
1301
+ full: "full";
1296
1302
  }>>;
1297
1303
  allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
1298
1304
  deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -1591,6 +1597,12 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
1591
1597
  }>>;
1592
1598
  /** Number of recent assistant turns that retain thinking blocks (older turns get stripped). */
1593
1599
  thinkingKeepTurns: z.ZodDefault<z.ZodNumber>;
1600
+ /** Idle gap (ms) above which signed thinking state is treated as drifted and
1601
+ * scrubbed pre-send to avoid provider replay-rejection. Default 30 min —
1602
+ * below long-TTL caches and below the 74-min production incident gap. Also
1603
+ * triggers on model id / provider / api change (those checks are
1604
+ * unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
1605
+ replayDriftIdleMs: z.ZodDefault<z.ZodNumber>;
1594
1606
  /** Model for LLM compaction in "provider:modelId" format. Defaults to Haiku for cost efficiency. Empty string falls through to session model. */
1595
1607
  compactionModel: z.ZodDefault<z.ZodString>;
1596
1608
  /** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
@@ -1853,9 +1865,9 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
1853
1865
  maxChars: z.ZodDefault<z.ZodNumber>;
1854
1866
  /** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
1855
1867
  promptMode: z.ZodDefault<z.ZodEnum<{
1856
- none: "none";
1857
- full: "full";
1858
1868
  minimal: "minimal";
1869
+ full: "full";
1870
+ none: "none";
1859
1871
  }>>;
1860
1872
  /** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
1861
1873
  groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
@@ -1962,11 +1974,11 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
1962
1974
  }, z.core.$strict>>;
1963
1975
  toolPolicy: z.ZodDefault<z.ZodObject<{
1964
1976
  profile: z.ZodDefault<z.ZodEnum<{
1965
- full: "full";
1966
1977
  minimal: "minimal";
1967
1978
  coding: "coding";
1968
1979
  messaging: "messaging";
1969
1980
  supervisor: "supervisor";
1981
+ full: "full";
1970
1982
  }>>;
1971
1983
  allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
1972
1984
  deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -2265,6 +2277,12 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
2265
2277
  }>>;
2266
2278
  /** Number of recent assistant turns that retain thinking blocks (older turns get stripped). */
2267
2279
  thinkingKeepTurns: z.ZodDefault<z.ZodNumber>;
2280
+ /** Idle gap (ms) above which signed thinking state is treated as drifted and
2281
+ * scrubbed pre-send to avoid provider replay-rejection. Default 30 min —
2282
+ * below long-TTL caches and below the 74-min production incident gap. Also
2283
+ * triggers on model id / provider / api change (those checks are
2284
+ * unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
2285
+ replayDriftIdleMs: z.ZodDefault<z.ZodNumber>;
2268
2286
  /** Model for LLM compaction in "provider:modelId" format. Defaults to Haiku for cost efficiency. Empty string falls through to session model. */
2269
2287
  compactionModel: z.ZodDefault<z.ZodString>;
2270
2288
  /** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
@@ -288,6 +288,12 @@ export const ContextEngineConfigSchema = z.strictObject({
288
288
  // --- Shared (both modes) ---
289
289
  /** Number of recent assistant turns that retain thinking blocks (older turns get stripped). */
290
290
  thinkingKeepTurns: z.number().int().min(1).max(50).default(10),
291
+ /** Idle gap (ms) above which signed thinking state is treated as drifted and
292
+ * scrubbed pre-send to avoid provider replay-rejection. Default 30 min —
293
+ * below long-TTL caches and below the 74-min production incident gap. Also
294
+ * triggers on model id / provider / api change (those checks are
295
+ * unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
296
+ replayDriftIdleMs: z.number().int().min(60_000).max(24 * 60 * 60_000).default(30 * 60_000),
291
297
  /** Model for LLM compaction in "provider:modelId" format. Defaults to Haiku for cost efficiency. Empty string falls through to session model. */
292
298
  compactionModel: z.string().default("anthropic:claude-haiku-4-5-20250929"),
293
299
  /** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
@@ -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";
33
32
  file: "file";
34
33
  exec: "exec";
34
+ env: "env";
35
35
  }>;
36
36
  provider: z.ZodString;
37
37
  id: z.ZodString;
@@ -88,9 +88,9 @@ export declare const GatewayConfigSchema: z.ZodObject<{
88
88
  /** The secret value (min 32 chars; resolved at runtime if omitted; string or SecretRef) */
89
89
  secret: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
90
90
  source: z.ZodEnum<{
91
- env: "env";
92
91
  file: "file";
93
92
  exec: "exec";
93
+ env: "env";
94
94
  }>;
95
95
  provider: z.ZodString;
96
96
  id: z.ZodString;