comisai 1.0.19 → 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 (147) 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/package.json +1 -1
  25. package/node_modules/@comis/core/dist/config/git-manager.js +10 -4
  26. package/node_modules/@comis/core/dist/config/index.d.ts +1 -0
  27. package/node_modules/@comis/core/dist/config/index.js +2 -0
  28. package/node_modules/@comis/core/dist/config/managed-sections.d.ts +67 -0
  29. package/node_modules/@comis/core/dist/config/managed-sections.js +124 -0
  30. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +28 -10
  31. package/node_modules/@comis/core/dist/config/schema-agent.js +6 -0
  32. package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +2 -2
  33. package/node_modules/@comis/core/dist/config/schema.d.ts +65 -64
  34. package/node_modules/@comis/core/dist/event-bus/events-messaging.d.ts +16 -0
  35. package/node_modules/@comis/core/dist/exports/config.d.ts +1 -1
  36. package/node_modules/@comis/core/dist/exports/config.js +1 -1
  37. package/node_modules/@comis/core/package.json +1 -1
  38. package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/init-skill.py +0 -0
  39. package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/validate-skill.py +0 -0
  40. package/node_modules/@comis/daemon/dist/daemon.js +0 -0
  41. package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +20 -7
  42. package/node_modules/@comis/daemon/dist/rpc/session-handlers.js +27 -1
  43. package/node_modules/@comis/daemon/package.json +1 -1
  44. package/node_modules/@comis/gateway/package.json +1 -1
  45. package/node_modules/@comis/infra/package.json +1 -1
  46. package/node_modules/@comis/memory/package.json +1 -1
  47. package/node_modules/@comis/scheduler/package.json +1 -1
  48. package/node_modules/@comis/shared/package.json +1 -1
  49. package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +23 -8
  50. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +1 -1
  51. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +18 -14
  52. package/node_modules/@comis/skills/dist/builtin/platform/unified-session-tool.js +1 -1
  53. package/node_modules/@comis/skills/package.json +1 -1
  54. package/node_modules/@comis/web/package.json +1 -1
  55. package/package.json +24 -26
  56. package/node_modules/@comis/agent/dist/provider/response/strip-minimax-xml.d.ts +0 -9
  57. package/node_modules/@comis/agent/dist/provider/response/strip-minimax-xml.js +0 -17
  58. package/node_modules/@comis/agent/dist/provider/response/strip-model-tokens.d.ts +0 -13
  59. package/node_modules/@comis/agent/dist/provider/response/strip-model-tokens.js +0 -19
  60. package/node_modules/@comis/agent/dist/provider/response/strip-tool-text.d.ts +0 -11
  61. package/node_modules/@comis/agent/dist/provider/response/strip-tool-text.js +0 -32
  62. package/node_modules/@comis/agent/dist/safety/follow-through-detector.d.ts +0 -46
  63. package/node_modules/@comis/agent/dist/safety/follow-through-detector.js +0 -76
  64. package/node_modules/@comis/agent/dist/safety/post-compaction-safety.d.ts +0 -30
  65. package/node_modules/@comis/agent/dist/safety/post-compaction-safety.js +0 -51
  66. package/node_modules/@comis/agent/dist/safety/schema-normalizer.d.ts +0 -37
  67. package/node_modules/@comis/agent/dist/safety/schema-normalizer.js +0 -137
  68. package/node_modules/@comis/agent/dist/safety/schema-pruning.d.ts +0 -50
  69. package/node_modules/@comis/agent/dist/safety/schema-pruning.js +0 -112
  70. package/node_modules/@comis/agent/dist/safety/tool-image-sanitizer.d.ts +0 -43
  71. package/node_modules/@comis/agent/dist/safety/tool-image-sanitizer.js +0 -96
  72. package/node_modules/@comis/agent/dist/safety/tool-sanitizer.d.ts +0 -44
  73. package/node_modules/@comis/agent/dist/safety/tool-sanitizer.js +0 -94
  74. package/node_modules/@comis/channels/dist/shared/thinking-tag-filter.d.ts +0 -28
  75. package/node_modules/@comis/channels/dist/shared/thinking-tag-filter.js +0 -206
  76. package/node_modules/@comis/cli/dist/wizard/config-writer.d.ts +0 -25
  77. package/node_modules/@comis/cli/dist/wizard/config-writer.js +0 -144
  78. package/node_modules/@comis/cli/dist/wizard/flow-types.d.ts +0 -48
  79. package/node_modules/@comis/cli/dist/wizard/flow-types.js +0 -70
  80. package/node_modules/@comis/cli/dist/wizard/manual-flow.d.ts +0 -21
  81. package/node_modules/@comis/cli/dist/wizard/manual-flow.js +0 -345
  82. package/node_modules/@comis/cli/dist/wizard/quickstart-flow.d.ts +0 -21
  83. package/node_modules/@comis/cli/dist/wizard/quickstart-flow.js +0 -116
  84. package/node_modules/@comis/core/dist/config/schema-agent-model.d.ts +0 -135
  85. package/node_modules/@comis/core/dist/config/schema-agent-model.js +0 -114
  86. package/node_modules/@comis/core/dist/config/schema-agent-session.d.ts +0 -177
  87. package/node_modules/@comis/core/dist/config/schema-agent-session.js +0 -116
  88. package/node_modules/@comis/core/dist/config/schema-context-engine.d.ts +0 -92
  89. package/node_modules/@comis/core/dist/config/schema-context-engine.js +0 -92
  90. package/node_modules/@comis/core/dist/config/schema-context-guard.d.ts +0 -34
  91. package/node_modules/@comis/core/dist/config/schema-context-guard.js +0 -32
  92. package/node_modules/@comis/core/dist/config/schema-delivery-mirror.d.ts +0 -27
  93. package/node_modules/@comis/core/dist/config/schema-delivery-mirror.js +0 -26
  94. package/node_modules/@comis/core/dist/config/schema-delivery-queue.d.ts +0 -31
  95. package/node_modules/@comis/core/dist/config/schema-delivery-queue.js +0 -30
  96. package/node_modules/@comis/core/dist/config/schema-delivery-timing.d.ts +0 -41
  97. package/node_modules/@comis/core/dist/config/schema-delivery-timing.js +0 -31
  98. package/node_modules/@comis/core/dist/config/schema-monitoring.d.ts +0 -105
  99. package/node_modules/@comis/core/dist/config/schema-monitoring.js +0 -67
  100. package/node_modules/@comis/core/dist/ports/media-ports.d.ts +0 -278
  101. package/node_modules/@comis/core/dist/ports/media-ports.js +0 -1
  102. package/node_modules/@comis/core/dist/security/input-guard.d.ts +0 -46
  103. package/node_modules/@comis/core/dist/security/input-guard.js +0 -166
  104. package/node_modules/@comis/core/dist/security/scoped-secret-manager.d.ts +0 -38
  105. package/node_modules/@comis/core/dist/security/scoped-secret-manager.js +0 -94
  106. package/node_modules/@comis/daemon/dist/observability/delivery-context.d.ts +0 -37
  107. package/node_modules/@comis/daemon/dist/observability/delivery-context.js +0 -1
  108. package/node_modules/@comis/daemon/dist/observability/log-level-manager.d.ts +0 -23
  109. package/node_modules/@comis/daemon/dist/observability/log-level-manager.js +0 -34
  110. package/node_modules/@comis/daemon/dist/observability/log-transport.d.ts +0 -44
  111. package/node_modules/@comis/daemon/dist/observability/log-transport.js +0 -74
  112. package/node_modules/@comis/daemon/dist/observability/obs-write-buffer.d.ts +0 -53
  113. package/node_modules/@comis/daemon/dist/observability/obs-write-buffer.js +0 -68
  114. package/node_modules/@comis/daemon/dist/observability/types.d.ts +0 -6
  115. package/node_modules/@comis/daemon/dist/observability/types.js +0 -1
  116. package/node_modules/@comis/daemon/dist/wiring/seed-bundled-skills.d.ts +0 -41
  117. package/node_modules/@comis/daemon/dist/wiring/seed-bundled-skills.js +0 -84
  118. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-mirror.d.ts +0 -24
  119. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-mirror.js +0 -88
  120. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-queue.d.ts +0 -31
  121. package/node_modules/@comis/daemon/dist/wiring/setup-delivery-queue.js +0 -132
  122. package/node_modules/@comis/daemon/dist/wiring/setup-monitoring.d.ts +0 -38
  123. package/node_modules/@comis/daemon/dist/wiring/setup-monitoring.js +0 -100
  124. package/node_modules/@comis/daemon/dist/wiring/setup-rpc-bridge.d.ts +0 -34
  125. package/node_modules/@comis/daemon/dist/wiring/setup-rpc-bridge.js +0 -52
  126. package/node_modules/@comis/daemon/dist/wiring/setup-task-extraction.d.ts +0 -41
  127. package/node_modules/@comis/daemon/dist/wiring/setup-task-extraction.js +0 -86
  128. package/node_modules/@comis/memory/dist/embedding-cache.d.ts +0 -36
  129. package/node_modules/@comis/memory/dist/embedding-cache.js +0 -94
  130. package/node_modules/@comis/skills/dist/bridge/tool-output-schemas.d.ts +0 -17
  131. package/node_modules/@comis/skills/dist/bridge/tool-output-schemas.js +0 -125
  132. package/node_modules/@comis/skills/dist/bridge/tool-parallelism-metadata.d.ts +0 -14
  133. package/node_modules/@comis/skills/dist/bridge/tool-parallelism-metadata.js +0 -92
  134. package/node_modules/@comis/skills/dist/bridge/tool-result-caps.d.ts +0 -14
  135. package/node_modules/@comis/skills/dist/bridge/tool-result-caps.js +0 -36
  136. package/node_modules/@comis/skills/dist/bridge/tool-search-hints.d.ts +0 -15
  137. package/node_modules/@comis/skills/dist/bridge/tool-search-hints.js +0 -68
  138. package/node_modules/@comis/skills/dist/bridge/tool-validators.d.ts +0 -11
  139. package/node_modules/@comis/skills/dist/bridge/tool-validators.js +0 -105
  140. package/node_modules/@comis/skills/dist/builtin/file/find-sort-wrapper.d.ts +0 -22
  141. package/node_modules/@comis/skills/dist/builtin/file/find-sort-wrapper.js +0 -95
  142. package/node_modules/@comis/skills/dist/builtin/file/grep-output-mode-wrapper.d.ts +0 -24
  143. package/node_modules/@comis/skills/dist/builtin/file/grep-output-mode-wrapper.js +0 -167
  144. package/node_modules/@comis/skills/dist/builtin/task-plan-tool.d.ts +0 -25
  145. package/node_modules/@comis/skills/dist/builtin/task-plan-tool.js +0 -67
  146. package/node_modules/@comis/skills/dist/integrations/mcp-tool-bridge.d.ts +0 -75
  147. package/node_modules/@comis/skills/dist/integrations/mcp-tool-bridge.js +0 -235
@@ -1,23 +0,0 @@
1
- import { type ComisLogger } from "@comis/infra";
2
- /**
3
- * Log level manager: per-module child loggers with runtime level control.
4
- *
5
- * Modules obtain their logger via getLogger(module), which returns a cached
6
- * Pino child logger. Levels can be changed at runtime per-module or globally
7
- * via the daemon.setLogLevel RPC (OBS-04).
8
- */
9
- export interface LogLevelManager {
10
- /** Get or create a child logger for a named module. Cached on first call. */
11
- getLogger(module: string): ComisLogger;
12
- /** Change the log level for a specific module's logger. */
13
- setLevel(module: string, level: string): void;
14
- /** Change the root logger's level (affects all modules that haven't been individually overridden). */
15
- setGlobalLevel(level: string): void;
16
- }
17
- /**
18
- * Create a log level manager that maintains a registry of per-module child loggers.
19
- *
20
- * @param rootLogger - The root Pino logger from which child loggers are derived
21
- * @returns A LogLevelManager instance
22
- */
23
- export declare function createLogLevelManager(rootLogger: ComisLogger): LogLevelManager;
@@ -1,34 +0,0 @@
1
- import { isValidLogLevel } from "@comis/infra";
2
- /**
3
- * Create a log level manager that maintains a registry of per-module child loggers.
4
- *
5
- * @param rootLogger - The root Pino logger from which child loggers are derived
6
- * @returns A LogLevelManager instance
7
- */
8
- export function createLogLevelManager(rootLogger) {
9
- const loggers = new Map();
10
- const manager = {
11
- getLogger(module) {
12
- let logger = loggers.get(module);
13
- if (!logger) {
14
- logger = rootLogger.child({ module });
15
- loggers.set(module, logger);
16
- }
17
- return logger;
18
- },
19
- setLevel(module, level) {
20
- if (!isValidLogLevel(level))
21
- return; // CRED-05: silently reject invalid levels
22
- const logger = loggers.get(module);
23
- if (logger) {
24
- logger.level = level;
25
- }
26
- },
27
- setGlobalLevel(level) {
28
- if (!isValidLogLevel(level))
29
- return; // CRED-05: silently reject invalid levels
30
- rootLogger.level = level;
31
- },
32
- };
33
- return manager;
34
- }
@@ -1,44 +0,0 @@
1
- /**
2
- * Log transport factory: constructs pino multi-target transport config
3
- * for simultaneous file rotation (pino-roll) and stdout output.
4
- *
5
- * INFRA-02: File rotation transport.
6
- * INFRA-03: Dual file + stdout output.
7
- * INFRA-04: removeOtherLogFiles cleanup.
8
- *
9
- * @module
10
- */
11
- import type { LoggingConfig } from "@comis/core";
12
- import type pino from "pino";
13
- /**
14
- * Expand leading tilde to os.homedir().
15
- * pino-roll does NOT expand tildes, so this must be called before
16
- * passing filePath to the transport.
17
- */
18
- export declare function expandTilde(filePath: string): string;
19
- /**
20
- * Detect whether the process is running under pm2.
21
- *
22
- * pm2 sets the `PM2_HOME` environment variable for all managed processes.
23
- * When running under pm2, stdout is already captured to pm2's own log files
24
- * (`~/.pm2/logs/`), so the pino-roll file transport would be a byte-for-byte
25
- * duplicate.
26
- */
27
- export declare function isPm2Managed(): boolean;
28
- /**
29
- * Create a pino multi-target transport config from LoggingConfig.
30
- *
31
- * LI-1: PM2-aware transport selection.
32
- * - File transport (pino-roll): always active -- canonical log location.
33
- * - Stdout: skipped under pm2 (PM2_HOME set) to avoid byte-for-byte
34
- * duplication with pm2's own log capture in ~/.pm2/logs/.
35
- *
36
- * Note: node-llama-cpp native module warnings write directly to stderr and
37
- * cannot be captured by Pino transports. This is a known limitation.
38
- *
39
- * @param config - Logging config from DaemonConfigSchema.logging
40
- * @param level - Log level to apply to each target (Pino multi-transport
41
- * targets default to "info" unless explicitly set)
42
- * @returns Transport config to pass as LoggerOptions.transport
43
- */
44
- export declare function createFileTransport(config: LoggingConfig, level?: string): pino.TransportMultiOptions;
@@ -1,74 +0,0 @@
1
- /**
2
- * Log transport factory: constructs pino multi-target transport config
3
- * for simultaneous file rotation (pino-roll) and stdout output.
4
- *
5
- * INFRA-02: File rotation transport.
6
- * INFRA-03: Dual file + stdout output.
7
- * INFRA-04: removeOtherLogFiles cleanup.
8
- *
9
- * @module
10
- */
11
- import os from "node:os";
12
- /**
13
- * Expand leading tilde to os.homedir().
14
- * pino-roll does NOT expand tildes, so this must be called before
15
- * passing filePath to the transport.
16
- */
17
- export function expandTilde(filePath) {
18
- return filePath.replace(/^~(?=\/|$)/, os.homedir());
19
- }
20
- /**
21
- * Detect whether the process is running under pm2.
22
- *
23
- * pm2 sets the `PM2_HOME` environment variable for all managed processes.
24
- * When running under pm2, stdout is already captured to pm2's own log files
25
- * (`~/.pm2/logs/`), so the pino-roll file transport would be a byte-for-byte
26
- * duplicate.
27
- */
28
- export function isPm2Managed() {
29
- return typeof process.env.PM2_HOME === "string" && process.env.PM2_HOME.length > 0;
30
- }
31
- /**
32
- * Create a pino multi-target transport config from LoggingConfig.
33
- *
34
- * LI-1: PM2-aware transport selection.
35
- * - File transport (pino-roll): always active -- canonical log location.
36
- * - Stdout: skipped under pm2 (PM2_HOME set) to avoid byte-for-byte
37
- * duplication with pm2's own log capture in ~/.pm2/logs/.
38
- *
39
- * Note: node-llama-cpp native module warnings write directly to stderr and
40
- * cannot be captured by Pino transports. This is a known limitation.
41
- *
42
- * @param config - Logging config from DaemonConfigSchema.logging
43
- * @param level - Log level to apply to each target (Pino multi-transport
44
- * targets default to "info" unless explicitly set)
45
- * @returns Transport config to pass as LoggerOptions.transport
46
- */
47
- export function createFileTransport(config, level) {
48
- const expandedPath = expandTilde(config.filePath);
49
- const pm2Detected = isPm2Managed();
50
- const targets = [];
51
- // File transport: always active -- ~/.comis/logs/ is the canonical log location
52
- targets.push({
53
- target: "pino-roll",
54
- options: {
55
- file: expandedPath,
56
- size: config.maxSize,
57
- mkdir: true,
58
- limit: {
59
- count: config.maxFiles,
60
- removeOtherLogFiles: true,
61
- },
62
- },
63
- ...(level ? { level } : {}),
64
- });
65
- // Stdout: skip under pm2 (pm2 captures stdout to ~/.pm2/logs/, so it would be a duplicate)
66
- if (!pm2Detected) {
67
- targets.push({
68
- target: "pino/file",
69
- options: { destination: 1 }, // stdout
70
- ...(level ? { level } : {}),
71
- });
72
- }
73
- return { targets };
74
- }
@@ -1,53 +0,0 @@
1
- /**
2
- * Generic batched write buffer for observability persistence.
3
- *
4
- * Sits between event bus listeners and ObservabilityStore: listeners push items
5
- * into the buffer; the buffer flushes batches to SQLite periodically or when
6
- * the buffer reaches its size threshold.
7
- *
8
- * Design:
9
- * - Plain array (not ring buffer) per research recommendation
10
- * - Dual trigger: size threshold (default 50) OR timer interval (default 500ms)
11
- * - Timer uses unref() so it does not prevent Node.js process exit
12
- * - drain() provides synchronous final flush for clean shutdown
13
- * - flushFn is synchronous (better-sqlite3 db.transaction() is sync)
14
- *
15
- * @module obs-write-buffer
16
- */
17
- /** Public interface for the write buffer. */
18
- export interface ObsWriteBuffer<T> {
19
- /** Add an item to the buffer. Triggers flush if buffer hits maxSize. */
20
- push(item: T): void;
21
- /** Flush current buffer contents to the flush callback. No-op if empty. */
22
- flush(): void;
23
- /** Synchronous final flush for shutdown: flushes remaining items and clears the interval timer. */
24
- drain(): void;
25
- /** Number of items currently buffered. */
26
- readonly pending: number;
27
- }
28
- /** Options for creating a write buffer. */
29
- export interface ObsWriteBufferOptions<T> {
30
- /** Callback invoked with a batch of items when flushing. Must be synchronous (better-sqlite3 is sync). */
31
- flushFn: (items: T[]) => void;
32
- /** Maximum buffer size before triggering a flush. Default: 50. */
33
- maxSize?: number;
34
- /** Interval in ms between automatic flushes. Default: 500. */
35
- intervalMs?: number;
36
- }
37
- /**
38
- * Create a generic batched write buffer.
39
- *
40
- * Usage:
41
- * ```ts
42
- * const buf = createObsWriteBuffer<TokenUsageRow>({
43
- * flushFn: (items) => store.insertTokenUsageBatch(items),
44
- * maxSize: 50,
45
- * intervalMs: 500,
46
- * });
47
- *
48
- * eventBus.on("token:usage", (entry) => buf.push(toRow(entry)));
49
- * // On shutdown:
50
- * buf.drain();
51
- * ```
52
- */
53
- export declare function createObsWriteBuffer<T>(opts: ObsWriteBufferOptions<T>): ObsWriteBuffer<T>;
@@ -1,68 +0,0 @@
1
- /**
2
- * Generic batched write buffer for observability persistence.
3
- *
4
- * Sits between event bus listeners and ObservabilityStore: listeners push items
5
- * into the buffer; the buffer flushes batches to SQLite periodically or when
6
- * the buffer reaches its size threshold.
7
- *
8
- * Design:
9
- * - Plain array (not ring buffer) per research recommendation
10
- * - Dual trigger: size threshold (default 50) OR timer interval (default 500ms)
11
- * - Timer uses unref() so it does not prevent Node.js process exit
12
- * - drain() provides synchronous final flush for clean shutdown
13
- * - flushFn is synchronous (better-sqlite3 db.transaction() is sync)
14
- *
15
- * @module obs-write-buffer
16
- */
17
- /**
18
- * Create a generic batched write buffer.
19
- *
20
- * Usage:
21
- * ```ts
22
- * const buf = createObsWriteBuffer<TokenUsageRow>({
23
- * flushFn: (items) => store.insertTokenUsageBatch(items),
24
- * maxSize: 50,
25
- * intervalMs: 500,
26
- * });
27
- *
28
- * eventBus.on("token:usage", (entry) => buf.push(toRow(entry)));
29
- * // On shutdown:
30
- * buf.drain();
31
- * ```
32
- */
33
- export function createObsWriteBuffer(opts) {
34
- const { flushFn, maxSize = 50, intervalMs = 500 } = opts;
35
- let buffer = [];
36
- // Start periodic flush timer. unref() ensures it does not keep the process alive.
37
- const timer = setInterval(() => {
38
- flush();
39
- }, intervalMs);
40
- timer.unref();
41
- function flush() {
42
- if (buffer.length === 0)
43
- return;
44
- // Swap-before-call: if flushFn throws, the batch is in the local variable,
45
- // not lost back in the buffer. The caller of flushFn can decide recovery.
46
- const batch = buffer;
47
- buffer = [];
48
- flushFn(batch);
49
- }
50
- function push(item) {
51
- buffer.push(item);
52
- if (buffer.length >= maxSize) {
53
- flush();
54
- }
55
- }
56
- function drain() {
57
- clearInterval(timer);
58
- flush();
59
- }
60
- return {
61
- push,
62
- flush,
63
- drain,
64
- get pending() {
65
- return buffer.length;
66
- },
67
- };
68
- }
@@ -1,6 +0,0 @@
1
- import type { EventMap, EventHandler } from "@comis/core";
2
- /** Reference to a registered EventBus handler for cleanup. */
3
- export interface HandlerRef {
4
- event: keyof EventMap;
5
- handler: EventHandler<keyof EventMap>;
6
- }
@@ -1,41 +0,0 @@
1
- /**
2
- * Idempotent seeding of bundled skills from the repo's skills/ directory
3
- * into the user data directory (~/.comis/skills/).
4
- *
5
- * On first startup, copies each skill directory that does not already exist
6
- * in the target. Existing user skills are never overwritten.
7
- *
8
- * @module
9
- */
10
- /** Minimal Pino-compatible logger for seeding diagnostics. */
11
- interface SeedLogger {
12
- info(obj: Record<string, unknown>, msg: string): void;
13
- debug(obj: Record<string, unknown>, msg: string): void;
14
- }
15
- /** Result of a seeding operation. */
16
- export interface SeedResult {
17
- /** Skill directory names that were newly copied into targetDir. */
18
- seeded: string[];
19
- /** Skill directory names that already existed in targetDir and were skipped. */
20
- skipped: string[];
21
- }
22
- /**
23
- * Seed bundled skills from sourceDir into targetDir (idempotent).
24
- *
25
- * For each subdirectory in sourceDir, checks whether a same-named directory
26
- * already exists in targetDir. If not, copies the entire directory tree
27
- * recursively. Existing skill directories are never overwritten.
28
- *
29
- * @param opts.sourceDir - Absolute path to the repo's skills/ directory.
30
- * If omitted, resolves from __dirname (../../../../skills).
31
- * @param opts.targetDir - Absolute path to the user data skills directory
32
- * (e.g., ~/.comis/skills/).
33
- * @param opts.logger - Optional structured logger for diagnostics.
34
- * @returns SeedResult with seeded and skipped skill names.
35
- */
36
- export declare function seedBundledSkills(opts: {
37
- sourceDir?: string;
38
- targetDir: string;
39
- logger?: SeedLogger;
40
- }): SeedResult;
41
- export {};
@@ -1,84 +0,0 @@
1
- /**
2
- * Idempotent seeding of bundled skills from the repo's skills/ directory
3
- * into the user data directory (~/.comis/skills/).
4
- *
5
- * On first startup, copies each skill directory that does not already exist
6
- * in the target. Existing user skills are never overwritten.
7
- *
8
- * @module
9
- */
10
- import { existsSync, mkdirSync, readdirSync, cpSync, statSync } from "node:fs";
11
- import { resolve } from "node:path";
12
- import { fileURLToPath } from "node:url";
13
- /**
14
- * Seed bundled skills from sourceDir into targetDir (idempotent).
15
- *
16
- * For each subdirectory in sourceDir, checks whether a same-named directory
17
- * already exists in targetDir. If not, copies the entire directory tree
18
- * recursively. Existing skill directories are never overwritten.
19
- *
20
- * @param opts.sourceDir - Absolute path to the repo's skills/ directory.
21
- * If omitted, resolves from __dirname (../../../../skills).
22
- * @param opts.targetDir - Absolute path to the user data skills directory
23
- * (e.g., ~/.comis/skills/).
24
- * @param opts.logger - Optional structured logger for diagnostics.
25
- * @returns SeedResult with seeded and skipped skill names.
26
- */
27
- export function seedBundledSkills(opts) {
28
- const seeded = [];
29
- const skipped = [];
30
- // Resolve source directory: either provided or derived from module location
31
- const sourceDir = opts.sourceDir ?? resolveDefaultSourceDir();
32
- // Handle missing source directory gracefully
33
- if (!existsSync(sourceDir)) {
34
- opts.logger?.debug({ sourceDir }, "Bundled skills source directory not found, skipping seed");
35
- return { seeded, skipped };
36
- }
37
- // Ensure target directory exists
38
- mkdirSync(opts.targetDir, { recursive: true });
39
- // Enumerate skill directories in source
40
- let entries;
41
- try {
42
- entries = readdirSync(sourceDir);
43
- }
44
- catch {
45
- return { seeded, skipped };
46
- }
47
- for (const entry of entries) {
48
- const srcPath = resolve(sourceDir, entry);
49
- // Only process directories (skip files like README.md)
50
- try {
51
- if (!statSync(srcPath).isDirectory())
52
- continue;
53
- }
54
- catch {
55
- continue;
56
- }
57
- const destPath = resolve(opts.targetDir, entry);
58
- if (existsSync(destPath)) {
59
- skipped.push(entry);
60
- opts.logger?.debug({ skill: entry }, "Bundled skill already exists in target, skipping");
61
- }
62
- else {
63
- cpSync(srcPath, destPath, { recursive: true });
64
- seeded.push(entry);
65
- opts.logger?.debug({ skill: entry }, "Bundled skill seeded into target");
66
- }
67
- }
68
- if (seeded.length > 0 || skipped.length > 0) {
69
- opts.logger?.info({ seeded: seeded.length, skipped: skipped.length }, "Bundled skills seeded");
70
- }
71
- return { seeded, skipped };
72
- }
73
- // ---------------------------------------------------------------------------
74
- // Internal helpers
75
- // ---------------------------------------------------------------------------
76
- /**
77
- * Resolve the default bundled skills source directory relative to this module.
78
- * From packages/daemon/dist/wiring/ -> repo root skills/
79
- */
80
- function resolveDefaultSourceDir() {
81
- const __filename = fileURLToPath(import.meta.url);
82
- const __dirname = resolve(__filename, "..");
83
- return resolve(__dirname, "../../../../skills");
84
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * Delivery mirror wiring: adapter creation, hook-based recording, periodic prune.
3
- *
4
- * Phase 502: Session Mirroring.
5
- * @module
6
- */
7
- import type { AppConfig, DeliveryMirrorPort } from "@comis/core";
8
- import type { ComisLogger } from "@comis/infra";
9
- import type { PluginRegistry } from "@comis/core";
10
- export interface DeliveryMirrorResult {
11
- /** The delivery mirror adapter (real or no-op), available immediately. */
12
- deliveryMirror: DeliveryMirrorPort;
13
- /** Starts the periodic prune timer. Call AFTER setupChannels. */
14
- startPrune: () => void;
15
- /** Clears the prune interval timer (call on shutdown). */
16
- shutdown: () => void;
17
- }
18
- export declare function setupDeliveryMirror(deps: {
19
- /** Raw better-sqlite3 database handle (typed as unknown to avoid cross-package type dep). */
20
- db: unknown;
21
- config: AppConfig;
22
- pluginRegistry: PluginRegistry;
23
- logger: ComisLogger;
24
- }): Promise<DeliveryMirrorResult>;
@@ -1,88 +0,0 @@
1
- /**
2
- * Delivery mirror wiring: adapter creation, hook-based recording, periodic prune.
3
- *
4
- * Phase 502: Session Mirroring.
5
- * @module
6
- */
7
- import { createNoOpDeliveryMirror } from "@comis/core";
8
- import { createSqliteDeliveryMirror } from "@comis/memory";
9
- import { ok } from "@comis/shared";
10
- import { createHash } from "node:crypto";
11
- // ---------------------------------------------------------------------------
12
- // Idempotency key computation
13
- // ---------------------------------------------------------------------------
14
- /**
15
- * Compute an idempotency key for a mirror entry.
16
- * Uses session key + text hash + 1-second time bucket to deduplicate
17
- * repeated deliveries of the same text within the same second.
18
- */
19
- function computeIdempotencyKey(sessionKey, text, timestamp) {
20
- const textHash = createHash("sha256").update(text).digest("hex").slice(0, 16);
21
- const bucket = Math.floor(timestamp / 1000);
22
- return `${sessionKey}:${textHash}:${bucket}`;
23
- }
24
- // ---------------------------------------------------------------------------
25
- // Setup function
26
- // ---------------------------------------------------------------------------
27
- export async function setupDeliveryMirror(deps) {
28
- const { db, config, pluginRegistry, logger } = deps;
29
- const mirrorConfig = config.deliveryMirror;
30
- // 1. No-op when disabled
31
- if (!mirrorConfig?.enabled) {
32
- logger.debug("Delivery mirror disabled by config");
33
- return {
34
- deliveryMirror: createNoOpDeliveryMirror(),
35
- startPrune: () => { },
36
- shutdown: () => { },
37
- };
38
- }
39
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- db is better-sqlite3 Database; typed as unknown to avoid cross-package type dependency
40
- const deliveryMirror = createSqliteDeliveryMirror(db);
41
- logger.info({ retentionMs: mirrorConfig.retentionMs, maxEntriesPerInjection: mirrorConfig.maxEntriesPerInjection, maxCharsPerInjection: mirrorConfig.maxCharsPerInjection }, "Delivery mirror enabled");
42
- // 2. Hook registration: record delivered text via after_delivery hook
43
- pluginRegistry.register({
44
- id: "comis:delivery-mirror",
45
- name: "Delivery Mirror",
46
- version: "1.0.0",
47
- register(api) {
48
- api.registerHook("after_delivery", async (event, ctx) => {
49
- if (!ctx.sessionKey)
50
- return; // No session context -- skip (Pitfall 1)
51
- const now = Date.now();
52
- const idempotencyKey = computeIdempotencyKey(ctx.sessionKey, event.text, now);
53
- const result = await deliveryMirror.record({
54
- sessionKey: ctx.sessionKey,
55
- text: event.text,
56
- mediaUrls: [], // Phase 502 baseline -- HookAfterDeliveryEvent has no mediaUrls field; media URL mirroring deferred
57
- channelType: event.channelType,
58
- channelId: event.channelId,
59
- origin: event.origin,
60
- idempotencyKey,
61
- });
62
- if (result.ok) {
63
- logger.debug({ sessionKey: ctx.sessionKey, channelType: event.channelType, idempotencyKey }, "Mirror entry recorded");
64
- }
65
- // Recording failures are silently tolerated (fire-and-forget hook)
66
- });
67
- return ok(undefined);
68
- },
69
- });
70
- // 3. Prune timer
71
- let pruneInterval;
72
- const startPrune = () => {
73
- pruneInterval = setInterval(async () => {
74
- const result = await deliveryMirror.pruneOld(mirrorConfig.retentionMs);
75
- if (result.ok && result.value > 0) {
76
- logger.debug({ pruned: result.value }, "Delivery mirror pruned");
77
- }
78
- }, mirrorConfig.pruneIntervalMs);
79
- pruneInterval.unref();
80
- };
81
- const shutdown = () => {
82
- if (pruneInterval) {
83
- clearInterval(pruneInterval);
84
- pruneInterval = undefined;
85
- }
86
- };
87
- return { deliveryMirror, startPrune, shutdown };
88
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * Delivery queue wiring: adapter creation, startup drain, periodic prune.
3
- *
4
- * Two-phase lifecycle resolves the circular dependency between the queue and
5
- * channel adapters:
6
- * 1. setupDeliveryQueue() creates the adapter immediately (before setupChannels).
7
- * 2. drainAndStartPrune() runs drain + starts prune timer AFTER setupChannels
8
- * populates channelAdapters.
9
- *
10
- * Phase 499: Crash-Safe Delivery Queue.
11
- * @module
12
- */
13
- import type { AppConfig, TypedEventBus, DeliveryQueuePort } from "@comis/core";
14
- import { type DeliveryAdapter } from "@comis/channels";
15
- import type { ComisLogger } from "@comis/infra";
16
- export interface DeliveryQueueResult {
17
- /** The delivery queue adapter (real or no-op), available immediately. */
18
- deliveryQueue: DeliveryQueuePort;
19
- /** Runs startup drain then starts periodic prune timer. Call AFTER setupChannels. */
20
- drainAndStartPrune: () => Promise<void>;
21
- /** Clears the prune interval timer (call on shutdown). */
22
- shutdown: () => void;
23
- }
24
- export declare function setupDeliveryQueue(deps: {
25
- /** Raw better-sqlite3 database handle (typed as unknown to avoid cross-package type dep). */
26
- db: unknown;
27
- config: AppConfig;
28
- eventBus: TypedEventBus;
29
- logger: ComisLogger;
30
- channelAdapters: Map<string, DeliveryAdapter>;
31
- }): Promise<DeliveryQueueResult>;