comisai 1.0.22 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@comis/agent/dist/executor/pi-executor.js +30 -3
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/daemon.js +11 -4
- package/node_modules/@comis/daemon/dist/wiring/setup-gateway.d.ts +22 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-gateway.js +34 -8
- package/node_modules/@comis/daemon/dist/wiring/setup-tools.js +14 -1
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/dist/logging/log-fields.d.ts +2 -2
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/builtin/sandbox/detect-provider.d.ts +1 -0
- package/node_modules/@comis/skills/dist/builtin/sandbox/detect-provider.js +78 -5
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/package.json +1 -1
- package/package.json +13 -13
|
@@ -449,6 +449,24 @@ export function createPiExecutor(config, deps) {
|
|
|
449
449
|
}
|
|
450
450
|
const resourceLoader = new DefaultResourceLoader(resourceLoaderOptions);
|
|
451
451
|
await resourceLoader.reload();
|
|
452
|
+
// The SDK's `tools` is an allowlist of tool *names* (not definitions).
|
|
453
|
+
// An empty array is treated as a non-empty allowlist that allows zero
|
|
454
|
+
// tools, including all customTools — which is why the agent ran
|
|
455
|
+
// tool-less from every entry point (chat API, SSE, Telegram, etc.):
|
|
456
|
+
// every Comis tool was filtered out of the SDK's tool registry, the
|
|
457
|
+
// Anthropic API request went out with `tools: []`, and the model
|
|
458
|
+
// emitted `<tool_call>...</tool_call>` markup as plaintext that
|
|
459
|
+
// Comis's loop never parsed back.
|
|
460
|
+
//
|
|
461
|
+
// Pass our customTool names as the explicit allowlist so:
|
|
462
|
+
// 1. All customTools land in the SDK's tool registry (their names
|
|
463
|
+
// pass `isAllowedTool`).
|
|
464
|
+
// 2. SDK built-ins like `bash` that conflict with Comis's policy
|
|
465
|
+
// controls are filtered out (Comis uses `exec` instead, with
|
|
466
|
+
// its own sandbox/audit hooks).
|
|
467
|
+
// 3. Where names overlap (read/edit/write), Comis's customTools
|
|
468
|
+
// override the SDK built-ins via Map.set() in the registry
|
|
469
|
+
// build (`agent-session.js:1810-1813` in pi-coding-agent@0.68.0).
|
|
452
470
|
const sessionOptions = {
|
|
453
471
|
cwd: deps.workspaceDir,
|
|
454
472
|
authStorage: deps.authStorage,
|
|
@@ -457,7 +475,7 @@ export function createPiExecutor(config, deps) {
|
|
|
457
475
|
sessionManager: sm,
|
|
458
476
|
settingsManager,
|
|
459
477
|
resourceLoader,
|
|
460
|
-
tools:
|
|
478
|
+
tools: mergedCustomTools.map((t) => t.name),
|
|
461
479
|
customTools: mergedCustomTools,
|
|
462
480
|
};
|
|
463
481
|
const { session, modelFallbackMessage } = await createAgentSession(sessionOptions);
|
|
@@ -654,11 +672,20 @@ export function createPiExecutor(config, deps) {
|
|
|
654
672
|
const postActiveNames = session.getActiveToolNames?.() ?? [];
|
|
655
673
|
if (postActiveNames.length < mergedToolNames.length) {
|
|
656
674
|
const rejected = mergedToolNames.filter(n => !postActiveNames.includes(n));
|
|
675
|
+
const allRejected = postActiveNames.length === 0 && rejected.length === mergedToolNames.length;
|
|
657
676
|
deps.logger.warn({
|
|
658
677
|
rejected,
|
|
659
|
-
|
|
678
|
+
rejectedCount: rejected.length,
|
|
679
|
+
registeredCount: mergedToolNames.length,
|
|
680
|
+
postActiveCount: postActiveNames.length,
|
|
681
|
+
allRejected,
|
|
682
|
+
hint: allRejected
|
|
683
|
+
? "SDK has 0 active tools after setActiveToolsByName -- not a name collision (empty active list, every Comis tool dropped). Indicates the SDK ResourceLoader / agent.tools handoff is broken; the LLM will receive no structured tool definitions and may emit `<tool_call>` markup as plaintext instead of using tool_use content blocks."
|
|
684
|
+
: "SDK filtered some Comis tools; likely name collisions with SDK built-ins (e.g. SDK reserves `bash`, `read_file`, etc.). Rename or omit the listed tools to avoid the conflict.",
|
|
660
685
|
errorKind: "validation",
|
|
661
|
-
},
|
|
686
|
+
}, allRejected
|
|
687
|
+
? "SDK rejected ALL tool registrations -- agent will run with no tools"
|
|
688
|
+
: "SDK rejected some tool registrations");
|
|
662
689
|
}
|
|
663
690
|
}
|
|
664
691
|
catch (toolMgmtError) {
|
|
@@ -182,13 +182,20 @@ export async function main(overrides = {}) {
|
|
|
182
182
|
// better-sqlite3 'bindings' module fails fast with a clear repair hint
|
|
183
183
|
// instead of cascading into a systemd restart loop.
|
|
184
184
|
await _preflightDoctor(exitFn);
|
|
185
|
-
// 0.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
//
|
|
185
|
+
// 0. Resolve data directory, then load secrets from <dataDir>/.env.
|
|
186
|
+
// The env file always lives alongside the data dir, so it follows
|
|
187
|
+
// COMIS_DATA_DIR — set to /data inside the Docker container (matches
|
|
188
|
+
// the compose mount of ${COMIS_ENV_FILE:-~/.comis/.env}:/data/.env:ro),
|
|
189
|
+
// unset on bare-metal so it falls back to ~/.comis/.env. This is what
|
|
190
|
+
// makes the legacy "credentials in a flat .env file" workflow the
|
|
191
|
+
// default for both deployment modes; secrets.db is opt-in via
|
|
192
|
+
// SECRETS_MASTER_KEY.
|
|
189
193
|
// eslint-disable-next-line no-restricted-syntax -- process.env access needed before SecretManager is initialized
|
|
190
194
|
const dataDir = process.env["COMIS_DATA_DIR"]
|
|
191
195
|
?? safePath(os.homedir(), ".comis");
|
|
196
|
+
const envPath = safePath(dataDir, ".env");
|
|
197
|
+
loadEnvFile(envPath);
|
|
198
|
+
// 0.5. Decrypt secrets, merge with env, scrub process.env
|
|
192
199
|
// Scan and correct permissions on known sensitive files
|
|
193
200
|
const permissionCorrections = hardenDataDirPermissions(dataDir);
|
|
194
201
|
const secretsBootResult = _setupSecrets({
|
|
@@ -14,6 +14,28 @@ import type { MemoryApi, SqliteMemoryAdapter, createEmbeddingQueue, createSessio
|
|
|
14
14
|
import type { RpcCall } from "@comis/skills";
|
|
15
15
|
import { createGatewayServer, WsConnectionManager, type GatewayServerHandle } from "@comis/gateway";
|
|
16
16
|
import type { RpcDispatchDeps } from "../rpc/rpc-dispatch.js";
|
|
17
|
+
/**
|
|
18
|
+
* Build the structured log fields for the gateway "Agent execution requested"
|
|
19
|
+
* INFO line. Replaces the previous behavior of logging the first 200 chars
|
|
20
|
+
* of the raw user message, which violated AGENTS.md §2.2 (no message bodies
|
|
21
|
+
* in logs at any level). Emits message length plus a short SHA-256 prefix
|
|
22
|
+
* for correlation, never the body itself.
|
|
23
|
+
*
|
|
24
|
+
* @param input.agentId Resolved agent ID (already trust-derived).
|
|
25
|
+
* @param input.message Raw user message (may be empty / undefined).
|
|
26
|
+
* @param input.connectionId Optional WebSocket connection ID.
|
|
27
|
+
* @returns Object suitable for `logger.info(obj, "Agent execution requested")`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildExecutionRequestedLogFields(input: {
|
|
30
|
+
agentId: string;
|
|
31
|
+
message: string | undefined;
|
|
32
|
+
connectionId: string | undefined;
|
|
33
|
+
}): {
|
|
34
|
+
agentId: string;
|
|
35
|
+
messageLen: number;
|
|
36
|
+
messageHash?: string;
|
|
37
|
+
connectionId?: string;
|
|
38
|
+
};
|
|
17
39
|
/** All services produced by the RPC bridge setup phase. */
|
|
18
40
|
export interface RpcBridgeResult {
|
|
19
41
|
/** The rpcCall function usable immediately (delegates to inner dispatch once wired). */
|
|
@@ -15,10 +15,39 @@ import { suppressError } from "@comis/shared";
|
|
|
15
15
|
import { readFileSync, existsSync } from "node:fs";
|
|
16
16
|
import { parseSlashCommand, createCommandHandler, createGreetingGenerator, } from "@comis/agent";
|
|
17
17
|
import { createDynamicMethodRouter, createRpcAdapters, createTokenStore, WsConnectionManager, } from "@comis/gateway";
|
|
18
|
-
import { randomUUID } from "node:crypto";
|
|
18
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
19
19
|
import { dirname, join, resolve } from "node:path";
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
21
|
import { createRpcDispatch, classifyRpcError } from "../rpc/rpc-dispatch.js";
|
|
22
|
+
// ===========================================================================
|
|
23
|
+
// Execution-request log redaction helper
|
|
24
|
+
// ===========================================================================
|
|
25
|
+
/**
|
|
26
|
+
* Build the structured log fields for the gateway "Agent execution requested"
|
|
27
|
+
* INFO line. Replaces the previous behavior of logging the first 200 chars
|
|
28
|
+
* of the raw user message, which violated AGENTS.md §2.2 (no message bodies
|
|
29
|
+
* in logs at any level). Emits message length plus a short SHA-256 prefix
|
|
30
|
+
* for correlation, never the body itself.
|
|
31
|
+
*
|
|
32
|
+
* @param input.agentId Resolved agent ID (already trust-derived).
|
|
33
|
+
* @param input.message Raw user message (may be empty / undefined).
|
|
34
|
+
* @param input.connectionId Optional WebSocket connection ID.
|
|
35
|
+
* @returns Object suitable for `logger.info(obj, "Agent execution requested")`.
|
|
36
|
+
*/
|
|
37
|
+
export function buildExecutionRequestedLogFields(input) {
|
|
38
|
+
const raw = input.message ?? "";
|
|
39
|
+
const fields = {
|
|
40
|
+
agentId: input.agentId,
|
|
41
|
+
messageLen: raw.length,
|
|
42
|
+
};
|
|
43
|
+
if (raw.length > 0) {
|
|
44
|
+
fields.messageHash = createHash("sha256").update(raw).digest("hex").slice(0, 12);
|
|
45
|
+
}
|
|
46
|
+
if (input.connectionId !== undefined) {
|
|
47
|
+
fields.connectionId = input.connectionId;
|
|
48
|
+
}
|
|
49
|
+
return fields;
|
|
50
|
+
}
|
|
22
51
|
/**
|
|
23
52
|
* Create the rpcCall wrapper and deferred dispatch mechanism.
|
|
24
53
|
* The returned rpcCall can be passed to setupTools immediately. After
|
|
@@ -296,14 +325,11 @@ export async function setupGateway(deps) {
|
|
|
296
325
|
// Admin scope or wildcard -> admin trust; otherwise -> user trust (fail-closed).
|
|
297
326
|
const trustLevel = deriveTrustLevel(params.scopes);
|
|
298
327
|
gatewayLogger.debug({ scopes: params.scopes, trustLevel, agentId: execAgentId }, "Trust level derived from token scopes");
|
|
299
|
-
|
|
300
|
-
const truncated = rawMsg.length > 200;
|
|
301
|
-
gatewayLogger.info({
|
|
328
|
+
gatewayLogger.info(buildExecutionRequestedLogFields({
|
|
302
329
|
agentId: execAgentId,
|
|
303
|
-
message:
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}, "Agent execution requested");
|
|
330
|
+
message: params.message,
|
|
331
|
+
connectionId,
|
|
332
|
+
}), "Agent execution requested");
|
|
307
333
|
// Link understanding preprocessing: enrich message text with fetched URL content
|
|
308
334
|
const enrichedText = await preprocessMessageText(params.message);
|
|
309
335
|
const msg = {
|
|
@@ -28,6 +28,11 @@ export function setupTools(deps) {
|
|
|
28
28
|
const { rpcCall, agents, defaultAgentId, workspaceDirs, defaultWorkspaceDir, dataDir, secretManager, platformSecretNames, eventBus, skillsLogger, linkRunner, approvalGate, subprocessEnv, credentialMappingStore, onSuspiciousContent, mcpClientManager, sandboxProvider, sessionTrackerRegistry, } = deps;
|
|
29
29
|
/** Per-agent ProcessRegistry instances for background process lifecycle management. */
|
|
30
30
|
const processRegistries = new Map();
|
|
31
|
+
/** Agents we've already logged the no-sandbox WARN for. Per-agent assembly
|
|
32
|
+
* runs on every session/heartbeat/cron tick; without this guard the WARN
|
|
33
|
+
* repeats on every LLM call even though the underlying state is fixed at
|
|
34
|
+
* daemon startup (detectSandboxProvider runs once). */
|
|
35
|
+
const warnedNoSandboxAgents = new Set();
|
|
31
36
|
function getOrCreateRegistry(agentId) {
|
|
32
37
|
let registry = processRegistries.get(agentId);
|
|
33
38
|
if (!registry) {
|
|
@@ -238,7 +243,15 @@ export function setupTools(deps) {
|
|
|
238
243
|
}
|
|
239
244
|
: undefined;
|
|
240
245
|
if (!sandboxCfg && skillsConfig.execSandbox.enabled === "always") {
|
|
241
|
-
|
|
246
|
+
if (warnedNoSandboxAgents.has(agentId)) {
|
|
247
|
+
// Already warned for this agent at WARN level — drop to DEBUG so
|
|
248
|
+
// every per-call assembly doesn't re-log the same fact.
|
|
249
|
+
skillsLogger.debug({ agentId }, "Exec tool running without OS sandbox (already warned at startup; per-call DEBUG)");
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
skillsLogger.warn({ agentId, hint: "Sandbox enabled in config but no provider available -- exec tool will run without OS sandbox", errorKind: "config" }, "Exec tool running without OS sandbox");
|
|
253
|
+
warnedNoSandboxAgents.add(agentId);
|
|
254
|
+
}
|
|
242
255
|
}
|
|
243
256
|
// Exec tool -- always instantiated; builtinTools ceiling applied after profile filtering
|
|
244
257
|
{
|
|
@@ -119,10 +119,10 @@ export interface LogFields {
|
|
|
119
119
|
closeReason: string;
|
|
120
120
|
/** Semantic categorization of the WebSocket close code (e.g., "normal", "abnormal", "no-status"). */
|
|
121
121
|
closeType: string;
|
|
122
|
-
/** Whether the logged message text was truncated from the original. */
|
|
123
|
-
messageTruncated: boolean;
|
|
124
122
|
/** Input message character length. */
|
|
125
123
|
messageLen: number;
|
|
124
|
+
/** First 12 hex chars of SHA-256 of input message; omitted when empty. Stable per content. */
|
|
125
|
+
messageHash: string;
|
|
126
126
|
/** Output response character length. */
|
|
127
127
|
responseLen: number;
|
|
128
128
|
/** Flat input token count for easy aggregation. */
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import type { SandboxProvider } from "./types.js";
|
|
11
11
|
/** Minimal logger interface for sandbox detection. */
|
|
12
12
|
export interface DetectLogger {
|
|
13
|
+
info(obj: Record<string, unknown>, msg: string): void;
|
|
13
14
|
warn(obj: Record<string, unknown>, msg: string): void;
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
@@ -8,8 +8,40 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
+
import { existsSync } from "node:fs";
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
11
13
|
import { BwrapProvider } from "./bwrap-provider.js";
|
|
12
14
|
import { SandboxExecProvider } from "./sandbox-exec-provider.js";
|
|
15
|
+
/**
|
|
16
|
+
* True when the daemon is running inside a Linux container. Docker writes
|
|
17
|
+
* `/.dockerenv` on container creation; Podman writes `/run/.containerenv`.
|
|
18
|
+
* One sync stat per daemon boot — runs once at sandbox detection.
|
|
19
|
+
*/
|
|
20
|
+
function isContainer() {
|
|
21
|
+
return existsSync("/.dockerenv") || existsSync("/run/.containerenv");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Smoke-test the bwrap binary against the isolation flags BwrapProvider
|
|
25
|
+
* actually uses (--unshare-pid + --proc /proc). On Docker Desktop's linuxkit
|
|
26
|
+
* kernel and similar restricted environments this combo EPERMs at the
|
|
27
|
+
* procfs mount step, even with apparmor/seccomp unconfined — every later
|
|
28
|
+
* exec call would silently fail. `available()` only checks if `bwrap` is on
|
|
29
|
+
* PATH, so without this probe the daemon would log "provider: bwrap" even
|
|
30
|
+
* when bwrap is non-functional. ~50ms one-shot at startup.
|
|
31
|
+
*/
|
|
32
|
+
function bwrapSmokeTest() {
|
|
33
|
+
const r = spawnSync("bwrap", [
|
|
34
|
+
"--unshare-user",
|
|
35
|
+
"--unshare-pid",
|
|
36
|
+
"--proc", "/proc",
|
|
37
|
+
"--ro-bind", "/usr", "/usr",
|
|
38
|
+
"--ro-bind", "/bin", "/bin",
|
|
39
|
+
"--ro-bind", "/lib", "/lib",
|
|
40
|
+
"--tmpfs", "/tmp",
|
|
41
|
+
"/bin/true",
|
|
42
|
+
], { encoding: "utf8", timeout: 5000 });
|
|
43
|
+
return r.status === 0;
|
|
44
|
+
}
|
|
13
45
|
/**
|
|
14
46
|
* Detect and return the best available sandbox provider for this platform.
|
|
15
47
|
* Returns undefined if no sandbox runtime is available -- caller decides
|
|
@@ -18,12 +50,53 @@ import { SandboxExecProvider } from "./sandbox-exec-provider.js";
|
|
|
18
50
|
export function detectSandboxProvider(logger) {
|
|
19
51
|
if (process.platform === "linux") {
|
|
20
52
|
const bwrap = new BwrapProvider();
|
|
21
|
-
if (bwrap.available())
|
|
53
|
+
if (bwrap.available()) {
|
|
54
|
+
if (!bwrapSmokeTest()) {
|
|
55
|
+
// bwrap is on PATH but the kernel rejects the isolation flags
|
|
56
|
+
// (typically Docker Desktop's linuxkit on macOS/Windows). Behaviour
|
|
57
|
+
// diverges by environment:
|
|
58
|
+
//
|
|
59
|
+
// - Inside a container: the project already declares macOS/Windows
|
|
60
|
+
// Docker Desktop as dev/testing only (CLAUDE.md, README, docs).
|
|
61
|
+
// Returning bwrap would just make every exec call fail and
|
|
62
|
+
// leave the agent useless for local testing. We disable the
|
|
63
|
+
// sandbox so exec runs unsandboxed inside the container,
|
|
64
|
+
// accepting the documented trust-boundary trade-off, and warn
|
|
65
|
+
// loudly. /data and /etc/comis are reachable from agent exec
|
|
66
|
+
// in this mode — never use it in production.
|
|
67
|
+
//
|
|
68
|
+
// - Bare metal: a non-functional bwrap is a real misconfiguration
|
|
69
|
+
// (rare on stock Linux). Surface it loudly and return the
|
|
70
|
+
// provider so exec fails via bwrap's stderr until the operator
|
|
71
|
+
// fixes the kernel/userns config — never silently degrade
|
|
72
|
+
// sandboxing on a bare-metal host.
|
|
73
|
+
if (isContainer()) {
|
|
74
|
+
logger?.warn({
|
|
75
|
+
hint: "Kernel rejected --unshare-pid + --proc /proc (typically Docker Desktop linuxkit on macOS/Windows). Sandbox auto-disabled so agent exec is functional for development. PRODUCTION DEPLOYMENTS MUST USE A REAL LINUX HOST — see docs/operations/docker.mdx → Platform Support.",
|
|
76
|
+
errorKind: "config",
|
|
77
|
+
}, "Exec sandbox DISABLED (kernel limitation; container host) -- shell commands will run UNSANDBOXED. Dev/testing only.");
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
logger?.warn({
|
|
81
|
+
hint: "Kernel rejected --unshare-pid + --proc /proc on a bare-metal host. Check `kernel.unprivileged_userns_clone` and AppArmor's `apparmor_restrict_unprivileged_userns`. Exec calls will fail until bwrap can run.",
|
|
82
|
+
errorKind: "config",
|
|
83
|
+
}, "bwrap installed but smoke test failed -- exec sandbox is non-functional on this kernel");
|
|
84
|
+
}
|
|
22
85
|
return bwrap;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
86
|
+
}
|
|
87
|
+
if (isContainer()) {
|
|
88
|
+
// Container deployments treat the container itself as the trust boundary;
|
|
89
|
+
// bwrap is intentionally absent. See docs/operations/docker.mdx → Trust boundary.
|
|
90
|
+
logger?.info({
|
|
91
|
+
hint: "Container runtime detected; intra-container exec sandboxing is opt-in. To enable, install bubblewrap and run with security_opt: apparmor=unconfined / seccomp=unconfined.",
|
|
92
|
+
}, "Exec OS sandbox not present (container runtime) -- relying on container isolation");
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
logger?.warn({
|
|
96
|
+
hint: "Install bubblewrap for OS-level exec sandboxing: apt install bubblewrap",
|
|
97
|
+
errorKind: "config",
|
|
98
|
+
}, "bwrap not found -- exec tool will run without OS sandbox");
|
|
99
|
+
}
|
|
27
100
|
return undefined;
|
|
28
101
|
}
|
|
29
102
|
if (process.platform === "darwin") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comisai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"author": "Moshe Anconina",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Security-first AI agent platform — connects AI agents to Discord, Telegram, Slack, WhatsApp, and more",
|
|
@@ -111,18 +111,18 @@
|
|
|
111
111
|
"@comis/web"
|
|
112
112
|
],
|
|
113
113
|
"dependencies": {
|
|
114
|
-
"@comis/shared": "1.0.
|
|
115
|
-
"@comis/core": "1.0.
|
|
116
|
-
"@comis/infra": "1.0.
|
|
117
|
-
"@comis/memory": "1.0.
|
|
118
|
-
"@comis/gateway": "1.0.
|
|
119
|
-
"@comis/skills": "1.0.
|
|
120
|
-
"@comis/scheduler": "1.0.
|
|
121
|
-
"@comis/agent": "1.0.
|
|
122
|
-
"@comis/channels": "1.0.
|
|
123
|
-
"@comis/cli": "1.0.
|
|
124
|
-
"@comis/daemon": "1.0.
|
|
125
|
-
"@comis/web": "1.0.
|
|
114
|
+
"@comis/shared": "1.0.23",
|
|
115
|
+
"@comis/core": "1.0.23",
|
|
116
|
+
"@comis/infra": "1.0.23",
|
|
117
|
+
"@comis/memory": "1.0.23",
|
|
118
|
+
"@comis/gateway": "1.0.23",
|
|
119
|
+
"@comis/skills": "1.0.23",
|
|
120
|
+
"@comis/scheduler": "1.0.23",
|
|
121
|
+
"@comis/agent": "1.0.23",
|
|
122
|
+
"@comis/channels": "1.0.23",
|
|
123
|
+
"@comis/cli": "1.0.23",
|
|
124
|
+
"@comis/daemon": "1.0.23",
|
|
125
|
+
"@comis/web": "1.0.23",
|
|
126
126
|
"@agentclientprotocol/sdk": "^0.19.0",
|
|
127
127
|
"@clack/core": "^1.1.0",
|
|
128
128
|
"@clack/prompts": "^1.1.0",
|