comisai 1.0.14 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@comis/agent/dist/bootstrap/index.d.ts +1 -1
- package/node_modules/@comis/agent/dist/bootstrap/index.js +1 -1
- package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.d.ts +26 -0
- package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.js +86 -54
- package/node_modules/@comis/agent/dist/bootstrap/types.d.ts +8 -2
- package/node_modules/@comis/agent/dist/bootstrap/workspace-loader.d.ts +12 -0
- package/node_modules/@comis/agent/dist/bootstrap/workspace-loader.js +21 -0
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +2 -0
- package/node_modules/@comis/agent/dist/executor/prompt-assembly.d.ts +8 -1
- package/node_modules/@comis/agent/dist/executor/prompt-assembly.js +22 -5
- package/node_modules/@comis/agent/dist/session/comis-session-manager.js +7 -2
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/dist/doctor/checks/channel-health.js +2 -2
- package/node_modules/@comis/cli/dist/wizard/index.d.ts +2 -3
- package/node_modules/@comis/cli/dist/wizard/index.js +2 -3
- package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +1 -1
- package/node_modules/@comis/cli/dist/wizard/types.d.ts +1 -2
- package/node_modules/@comis/cli/dist/wizard/types.js +1 -2
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/config/schema-agent.d.ts +54 -10
- package/node_modules/@comis/core/dist/config/schema-agent.js +11 -0
- package/node_modules/@comis/core/dist/config/schema.d.ts +19 -14
- package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +8 -0
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/daemon.js +2 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +19 -2
- package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.js +10 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-memory.d.ts +2 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-memory.js +15 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-schedulers.js +1 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-shutdown.d.ts +1 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-shutdown.js +4 -0
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/dist/cron/cron-types.d.ts +11 -0
- package/node_modules/@comis/scheduler/dist/cron/cron-types.js +11 -0
- package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.d.ts +26 -1
- package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +23 -2
- package/node_modules/@comis/scheduler/dist/heartbeat/heartbeat-config.d.ts +7 -0
- package/node_modules/@comis/scheduler/dist/heartbeat/heartbeat-config.js +2 -0
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +1 -1
- package/node_modules/@comis/skills/dist/index.d.ts +1 -1
- package/node_modules/@comis/skills/dist/index.js +1 -1
- package/node_modules/@comis/skills/dist/policy/tool-policy.js +25 -0
- package/node_modules/@comis/skills/package.json +1 -1
- package/package.json +12 -12
|
@@ -550,9 +550,9 @@ export declare const BootstrapConfigSchema: z.ZodObject<{
|
|
|
550
550
|
maxChars: z.ZodDefault<z.ZodNumber>;
|
|
551
551
|
/** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
|
|
552
552
|
promptMode: z.ZodDefault<z.ZodEnum<{
|
|
553
|
-
minimal: "minimal";
|
|
554
|
-
full: "full";
|
|
555
553
|
none: "none";
|
|
554
|
+
full: "full";
|
|
555
|
+
minimal: "minimal";
|
|
556
556
|
}>>;
|
|
557
557
|
/** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
|
|
558
558
|
groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -822,9 +822,9 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
822
822
|
maxChars: z.ZodDefault<z.ZodNumber>;
|
|
823
823
|
/** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
|
|
824
824
|
promptMode: z.ZodDefault<z.ZodEnum<{
|
|
825
|
-
minimal: "minimal";
|
|
826
|
-
full: "full";
|
|
827
825
|
none: "none";
|
|
826
|
+
full: "full";
|
|
827
|
+
minimal: "minimal";
|
|
828
828
|
}>>;
|
|
829
829
|
/** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
|
|
830
830
|
groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -987,6 +987,17 @@ export declare const PerAgentHeartbeatConfigSchema: z.ZodObject<{
|
|
|
987
987
|
alertCooldownMs: z.ZodOptional<z.ZodNumber>;
|
|
988
988
|
/** Override stuck detection timeout in ms (per-agent) */
|
|
989
989
|
staleMs: z.ZodOptional<z.ZodNumber>;
|
|
990
|
+
/** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
|
|
991
|
+
*
|
|
992
|
+
* Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
|
|
993
|
+
* Opt-in: omitting this field preserves the agent's interactive tool set for
|
|
994
|
+
* heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
|
|
995
|
+
* preset in `packages/skills/src/policy/tool-policy.ts`. */
|
|
996
|
+
toolPolicy: z.ZodOptional<z.ZodObject<{
|
|
997
|
+
profile: z.ZodDefault<z.ZodString>;
|
|
998
|
+
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
999
|
+
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1000
|
+
}, z.core.$strip>>;
|
|
990
1001
|
}, z.core.$strict>;
|
|
991
1002
|
export type HeartbeatTarget = z.infer<typeof HeartbeatTargetSchema>;
|
|
992
1003
|
export type PerAgentHeartbeatConfig = z.infer<typeof PerAgentHeartbeatConfigSchema>;
|
|
@@ -1046,6 +1057,17 @@ export declare const PerAgentSchedulerConfigSchema: z.ZodObject<{
|
|
|
1046
1057
|
alertCooldownMs: z.ZodOptional<z.ZodNumber>;
|
|
1047
1058
|
/** Override stuck detection timeout in ms (per-agent) */
|
|
1048
1059
|
staleMs: z.ZodOptional<z.ZodNumber>;
|
|
1060
|
+
/** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
|
|
1061
|
+
*
|
|
1062
|
+
* Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
|
|
1063
|
+
* Opt-in: omitting this field preserves the agent's interactive tool set for
|
|
1064
|
+
* heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
|
|
1065
|
+
* preset in `packages/skills/src/policy/tool-policy.ts`. */
|
|
1066
|
+
toolPolicy: z.ZodOptional<z.ZodObject<{
|
|
1067
|
+
profile: z.ZodDefault<z.ZodString>;
|
|
1068
|
+
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1069
|
+
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1070
|
+
}, z.core.$strip>>;
|
|
1049
1071
|
}, z.core.$strict>>;
|
|
1050
1072
|
}, z.core.$strict>;
|
|
1051
1073
|
/** Per-agent configuration: extends AgentConfigSchema with skills, scheduler, session, concurrency. */
|
|
@@ -1150,9 +1172,9 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
|
|
|
1150
1172
|
maxChars: z.ZodDefault<z.ZodNumber>;
|
|
1151
1173
|
/** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
|
|
1152
1174
|
promptMode: z.ZodDefault<z.ZodEnum<{
|
|
1153
|
-
minimal: "minimal";
|
|
1154
|
-
full: "full";
|
|
1155
1175
|
none: "none";
|
|
1176
|
+
full: "full";
|
|
1177
|
+
minimal: "minimal";
|
|
1156
1178
|
}>>;
|
|
1157
1179
|
/** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
|
|
1158
1180
|
groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -1259,11 +1281,11 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
|
|
|
1259
1281
|
}, z.core.$strict>>;
|
|
1260
1282
|
toolPolicy: z.ZodDefault<z.ZodObject<{
|
|
1261
1283
|
profile: z.ZodDefault<z.ZodEnum<{
|
|
1284
|
+
full: "full";
|
|
1262
1285
|
minimal: "minimal";
|
|
1263
1286
|
coding: "coding";
|
|
1264
1287
|
messaging: "messaging";
|
|
1265
1288
|
supervisor: "supervisor";
|
|
1266
|
-
full: "full";
|
|
1267
1289
|
}>>;
|
|
1268
1290
|
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1269
1291
|
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
@@ -1351,6 +1373,17 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
|
|
|
1351
1373
|
alertCooldownMs: z.ZodOptional<z.ZodNumber>;
|
|
1352
1374
|
/** Override stuck detection timeout in ms (per-agent) */
|
|
1353
1375
|
staleMs: z.ZodOptional<z.ZodNumber>;
|
|
1376
|
+
/** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
|
|
1377
|
+
*
|
|
1378
|
+
* Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
|
|
1379
|
+
* Opt-in: omitting this field preserves the agent's interactive tool set for
|
|
1380
|
+
* heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
|
|
1381
|
+
* preset in `packages/skills/src/policy/tool-policy.ts`. */
|
|
1382
|
+
toolPolicy: z.ZodOptional<z.ZodObject<{
|
|
1383
|
+
profile: z.ZodDefault<z.ZodString>;
|
|
1384
|
+
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1385
|
+
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1386
|
+
}, z.core.$strip>>;
|
|
1354
1387
|
}, z.core.$strict>>;
|
|
1355
1388
|
}, z.core.$strict>>;
|
|
1356
1389
|
session: z.ZodOptional<z.ZodObject<{
|
|
@@ -1810,9 +1843,9 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
1810
1843
|
maxChars: z.ZodDefault<z.ZodNumber>;
|
|
1811
1844
|
/** System prompt verbosity mode: full (all sections), minimal (sub-agents), none (identity only) */
|
|
1812
1845
|
promptMode: z.ZodDefault<z.ZodEnum<{
|
|
1813
|
-
minimal: "minimal";
|
|
1814
|
-
full: "full";
|
|
1815
1846
|
none: "none";
|
|
1847
|
+
full: "full";
|
|
1848
|
+
minimal: "minimal";
|
|
1816
1849
|
}>>;
|
|
1817
1850
|
/** When true, USER.md is excluded from bootstrap context in group chat sessions (privacy). Default: true. */
|
|
1818
1851
|
groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -1919,11 +1952,11 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
1919
1952
|
}, z.core.$strict>>;
|
|
1920
1953
|
toolPolicy: z.ZodDefault<z.ZodObject<{
|
|
1921
1954
|
profile: z.ZodDefault<z.ZodEnum<{
|
|
1955
|
+
full: "full";
|
|
1922
1956
|
minimal: "minimal";
|
|
1923
1957
|
coding: "coding";
|
|
1924
1958
|
messaging: "messaging";
|
|
1925
1959
|
supervisor: "supervisor";
|
|
1926
|
-
full: "full";
|
|
1927
1960
|
}>>;
|
|
1928
1961
|
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1929
1962
|
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
@@ -2011,6 +2044,17 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
2011
2044
|
alertCooldownMs: z.ZodOptional<z.ZodNumber>;
|
|
2012
2045
|
/** Override stuck detection timeout in ms (per-agent) */
|
|
2013
2046
|
staleMs: z.ZodOptional<z.ZodNumber>;
|
|
2047
|
+
/** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
|
|
2048
|
+
*
|
|
2049
|
+
* Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
|
|
2050
|
+
* Opt-in: omitting this field preserves the agent's interactive tool set for
|
|
2051
|
+
* heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
|
|
2052
|
+
* preset in `packages/skills/src/policy/tool-policy.ts`. */
|
|
2053
|
+
toolPolicy: z.ZodOptional<z.ZodObject<{
|
|
2054
|
+
profile: z.ZodDefault<z.ZodString>;
|
|
2055
|
+
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
2056
|
+
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
2057
|
+
}, z.core.$strip>>;
|
|
2014
2058
|
}, z.core.$strict>>;
|
|
2015
2059
|
}, z.core.$strict>>;
|
|
2016
2060
|
session: z.ZodOptional<z.ZodObject<{
|
|
@@ -674,6 +674,17 @@ export const PerAgentHeartbeatConfigSchema = z.strictObject({
|
|
|
674
674
|
alertCooldownMs: z.number().int().positive().optional(),
|
|
675
675
|
/** Override stuck detection timeout in ms (per-agent) */
|
|
676
676
|
staleMs: z.number().int().positive().optional(),
|
|
677
|
+
/** Per-agent heartbeat tool policy override -- matches AgentConfig.toolPolicy shape.
|
|
678
|
+
*
|
|
679
|
+
* Resolution order: heartbeat.toolPolicy > agentConfig.toolPolicy > passthrough.
|
|
680
|
+
* Opt-in: omitting this field preserves the agent's interactive tool set for
|
|
681
|
+
* heartbeat ticks. Use `{ profile: "heartbeat-minimal" }` for the conservative
|
|
682
|
+
* preset in `packages/skills/src/policy/tool-policy.ts`. */
|
|
683
|
+
toolPolicy: z.object({
|
|
684
|
+
profile: z.string().default("full"),
|
|
685
|
+
allow: z.array(z.string()).default([]),
|
|
686
|
+
deny: z.array(z.string()).default([]),
|
|
687
|
+
}).optional(),
|
|
677
688
|
});
|
|
678
689
|
/** Per-agent scheduler configuration (wraps cron and heartbeat settings). */
|
|
679
690
|
export const PerAgentSchedulerConfigSchema = z.strictObject({
|
|
@@ -105,9 +105,9 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
105
105
|
bootstrap: z.ZodDefault<z.ZodObject<{
|
|
106
106
|
maxChars: z.ZodDefault<z.ZodNumber>;
|
|
107
107
|
promptMode: z.ZodDefault<z.ZodEnum<{
|
|
108
|
-
minimal: "minimal";
|
|
109
|
-
full: "full";
|
|
110
108
|
none: "none";
|
|
109
|
+
full: "full";
|
|
110
|
+
minimal: "minimal";
|
|
111
111
|
}>>;
|
|
112
112
|
groupChatFiltering: z.ZodDefault<z.ZodBoolean>;
|
|
113
113
|
}, z.core.$strict>>;
|
|
@@ -184,11 +184,11 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
184
184
|
}, z.core.$strict>>;
|
|
185
185
|
toolPolicy: z.ZodDefault<z.ZodObject<{
|
|
186
186
|
profile: z.ZodDefault<z.ZodEnum<{
|
|
187
|
+
full: "full";
|
|
187
188
|
minimal: "minimal";
|
|
188
189
|
coding: "coding";
|
|
189
190
|
messaging: "messaging";
|
|
190
191
|
supervisor: "supervisor";
|
|
191
|
-
full: "full";
|
|
192
192
|
}>>;
|
|
193
193
|
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
194
194
|
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
@@ -250,6 +250,11 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
250
250
|
alertThreshold: z.ZodOptional<z.ZodNumber>;
|
|
251
251
|
alertCooldownMs: z.ZodOptional<z.ZodNumber>;
|
|
252
252
|
staleMs: z.ZodOptional<z.ZodNumber>;
|
|
253
|
+
toolPolicy: z.ZodOptional<z.ZodObject<{
|
|
254
|
+
profile: z.ZodDefault<z.ZodString>;
|
|
255
|
+
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
256
|
+
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
257
|
+
}, z.core.$strip>>;
|
|
253
258
|
}, z.core.$strict>>;
|
|
254
259
|
}, z.core.$strict>>;
|
|
255
260
|
session: z.ZodOptional<z.ZodObject<{
|
|
@@ -1105,11 +1110,11 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
1105
1110
|
waitTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
1106
1111
|
subAgentMaxSteps: z.ZodDefault<z.ZodNumber>;
|
|
1107
1112
|
subAgentToolGroups: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
1113
|
+
full: "full";
|
|
1108
1114
|
minimal: "minimal";
|
|
1109
1115
|
coding: "coding";
|
|
1110
1116
|
messaging: "messaging";
|
|
1111
1117
|
supervisor: "supervisor";
|
|
1112
|
-
full: "full";
|
|
1113
1118
|
}>>>;
|
|
1114
1119
|
subAgentMcpTools: z.ZodDefault<z.ZodEnum<{
|
|
1115
1120
|
none: "none";
|
|
@@ -1572,10 +1577,10 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
1572
1577
|
streaming: z.ZodDefault<z.ZodObject<{
|
|
1573
1578
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1574
1579
|
defaultChunkMode: z.ZodDefault<z.ZodEnum<{
|
|
1575
|
-
length: "length";
|
|
1576
1580
|
paragraph: "paragraph";
|
|
1577
1581
|
newline: "newline";
|
|
1578
1582
|
sentence: "sentence";
|
|
1583
|
+
length: "length";
|
|
1579
1584
|
}>>;
|
|
1580
1585
|
defaultDeliveryTiming: z.ZodDefault<z.ZodObject<{
|
|
1581
1586
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
@@ -1614,16 +1619,16 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
1614
1619
|
defaultUseMarkdownIR: z.ZodDefault<z.ZodBoolean>;
|
|
1615
1620
|
defaultReplyMode: z.ZodDefault<z.ZodEnum<{
|
|
1616
1621
|
off: "off";
|
|
1617
|
-
first: "first";
|
|
1618
1622
|
all: "all";
|
|
1623
|
+
first: "first";
|
|
1619
1624
|
}>>;
|
|
1620
1625
|
perChannel: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1621
1626
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1622
1627
|
chunkMode: z.ZodDefault<z.ZodEnum<{
|
|
1623
|
-
length: "length";
|
|
1624
1628
|
paragraph: "paragraph";
|
|
1625
1629
|
newline: "newline";
|
|
1626
1630
|
sentence: "sentence";
|
|
1631
|
+
length: "length";
|
|
1627
1632
|
}>>;
|
|
1628
1633
|
chunkMaxChars: z.ZodOptional<z.ZodNumber>;
|
|
1629
1634
|
chunkMinChars: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1666,19 +1671,19 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
1666
1671
|
}>>;
|
|
1667
1672
|
replyMode: z.ZodDefault<z.ZodEnum<{
|
|
1668
1673
|
off: "off";
|
|
1669
|
-
first: "first";
|
|
1670
1674
|
all: "all";
|
|
1675
|
+
first: "first";
|
|
1671
1676
|
}>>;
|
|
1672
1677
|
replyModeByChatType: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
1673
|
-
channel: "channel";
|
|
1674
1678
|
dm: "dm";
|
|
1675
1679
|
group: "group";
|
|
1676
1680
|
thread: "thread";
|
|
1681
|
+
channel: "channel";
|
|
1677
1682
|
forum: "forum";
|
|
1678
1683
|
}>, z.ZodEnum<{
|
|
1679
1684
|
off: "off";
|
|
1680
|
-
first: "first";
|
|
1681
1685
|
all: "all";
|
|
1686
|
+
first: "first";
|
|
1682
1687
|
}>>>;
|
|
1683
1688
|
}, z.core.$strict>>>;
|
|
1684
1689
|
}, z.core.$strict>>;
|
|
@@ -1718,8 +1723,8 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
1718
1723
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1719
1724
|
provider: z.ZodDefault<z.ZodEnum<{
|
|
1720
1725
|
auto: "auto";
|
|
1721
|
-
local: "local";
|
|
1722
1726
|
openai: "openai";
|
|
1727
|
+
local: "local";
|
|
1723
1728
|
}>>;
|
|
1724
1729
|
local: z.ZodDefault<z.ZodObject<{
|
|
1725
1730
|
modelUri: z.ZodDefault<z.ZodString>;
|
|
@@ -1867,15 +1872,15 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
1867
1872
|
approvals: z.ZodDefault<z.ZodObject<{
|
|
1868
1873
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1869
1874
|
defaultMode: z.ZodDefault<z.ZodEnum<{
|
|
1870
|
-
deny: "deny";
|
|
1871
1875
|
auto: "auto";
|
|
1876
|
+
deny: "deny";
|
|
1872
1877
|
require: "require";
|
|
1873
1878
|
}>>;
|
|
1874
1879
|
rules: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1875
1880
|
actionPattern: z.ZodString;
|
|
1876
1881
|
mode: z.ZodDefault<z.ZodEnum<{
|
|
1877
|
-
deny: "deny";
|
|
1878
1882
|
auto: "auto";
|
|
1883
|
+
deny: "deny";
|
|
1879
1884
|
require: "require";
|
|
1880
1885
|
}>>;
|
|
1881
1886
|
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
@@ -2009,8 +2014,8 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
2009
2014
|
senderTrustDisplay: z.ZodDefault<z.ZodObject<{
|
|
2010
2015
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
2011
2016
|
displayMode: z.ZodDefault<z.ZodEnum<{
|
|
2012
|
-
raw: "raw";
|
|
2013
2017
|
alias: "alias";
|
|
2018
|
+
raw: "raw";
|
|
2014
2019
|
hash: "hash";
|
|
2015
2020
|
}>>;
|
|
2016
2021
|
hashPrefix: z.ZodDefault<z.ZodNumber>;
|
|
@@ -189,6 +189,14 @@ export interface InfraEvents {
|
|
|
189
189
|
cronJobModel?: string;
|
|
190
190
|
/** Per-cron-job cache retention override from CronJob config. */
|
|
191
191
|
cacheRetention?: "none" | "short" | "long";
|
|
192
|
+
/** Per-cron-job tool policy override (opt-in). Resolution in the handler:
|
|
193
|
+
* job.toolPolicy > agentConfig.toolPolicy > passthrough `{ profile: "full" }`.
|
|
194
|
+
* Opt-in by design; omitting preserves pre-existing tool set. */
|
|
195
|
+
toolPolicy?: {
|
|
196
|
+
profile: string;
|
|
197
|
+
allow: string[];
|
|
198
|
+
deny: string[];
|
|
199
|
+
};
|
|
192
200
|
/** Callback for agent_turn jobs to report execution result back to the scheduler.
|
|
193
201
|
* Called by the event handler after agent execution completes. */
|
|
194
202
|
onComplete?: (result: {
|
|
@@ -295,7 +295,7 @@ export async function main(overrides = {}) {
|
|
|
295
295
|
container, logger, daemonLogger, _createProcessMonitor, _startWatchdog,
|
|
296
296
|
});
|
|
297
297
|
// 6.5. Memory + embedding
|
|
298
|
-
const { disposeEmbedding, cachedPort, memoryAdapter, db, sessionStore, memoryApi, embeddingQueue, backgroundIndexingPromise, embeddingCacheStats, embeddingCircuitBreakerState, } = await setupMemory({ container, memoryLogger });
|
|
298
|
+
const { disposeEmbedding, cachedPort, memoryAdapter, db, sessionStore, memoryApi, embeddingQueue, backgroundIndexingPromise, embeddingCacheStats, embeddingCircuitBreakerState, maintenanceTick, } = await setupMemory({ container, memoryLogger });
|
|
299
299
|
// Observability persistence (dual-write to SQLite)
|
|
300
300
|
const obsConfig = container.config.observability;
|
|
301
301
|
let obsStore;
|
|
@@ -1179,6 +1179,7 @@ export async function main(overrides = {}) {
|
|
|
1179
1179
|
}
|
|
1180
1180
|
}
|
|
1181
1181
|
catch { /* stat failure must not crash health check */ }
|
|
1182
|
+
maintenanceTick();
|
|
1182
1183
|
// Compute sub-agent health metrics (threshold-aware split)
|
|
1183
1184
|
const stuckKillThresholdMs = container.config.security.agentToAgent.subagentContext?.stuckKillThresholdMs ?? 180_000;
|
|
1184
1185
|
const graphStuckKillThresholdMs = container.config.security.agentToAgent.subagentContext?.graphStuckKillThresholdMs ?? 600_000;
|
|
@@ -16,7 +16,7 @@ import { formatSessionKey, runWithContext, createDeliveryOrigin, safePath } from
|
|
|
16
16
|
import { createMessageRouter, createCommandQueue, createCommandHandler, parseSlashCommand, sanitizeAssistantResponse, resolveOperationModel, resolveProviderFamily, runMemoryReview } from "@comis/agent";
|
|
17
17
|
import { createChannelManager, createRetryEngine, createApprovalNotifier, deliverToChannel, filterResponse, } from "@comis/channels";
|
|
18
18
|
import { RetryConfigSchema } from "@comis/core";
|
|
19
|
-
import { shouldAutoTts, resolveOutputFormat, parseOutboundMedia, } from "@comis/skills";
|
|
19
|
+
import { shouldAutoTts, resolveOutputFormat, parseOutboundMedia, applyToolPolicy, } from "@comis/skills";
|
|
20
20
|
import { bootstrapAdapters } from "./setup-channels-adapters.js";
|
|
21
21
|
import { buildMediaPipeline } from "./setup-channels-media.js";
|
|
22
22
|
import { createLifecycleReactor, reactWithFallback, initTelegramFileGuardConfig } from "@comis/channels";
|
|
@@ -193,9 +193,26 @@ export async function setupChannels(deps) {
|
|
|
193
193
|
};
|
|
194
194
|
const execStartTs = Date.now();
|
|
195
195
|
try {
|
|
196
|
-
const
|
|
196
|
+
const allTools = deps.assembleToolsForAgent
|
|
197
197
|
? await deps.assembleToolsForAgent(payload.agentId)
|
|
198
198
|
: [];
|
|
199
|
+
// Resolve effective tool policy: job > agent > passthrough `{ profile: "full" }`.
|
|
200
|
+
// Opt-in per job — omitting payload.toolPolicy preserves the agent's interactive
|
|
201
|
+
// tool set. The explicit "full" fallback makes the no-silent-default contract
|
|
202
|
+
// readable in the call site (see design-doc §"no silent default").
|
|
203
|
+
const effectivePolicy = payload.toolPolicy ??
|
|
204
|
+
agentConfig?.skills?.toolPolicy ??
|
|
205
|
+
{ profile: "full", allow: [], deny: [] };
|
|
206
|
+
const { tools, filtered: policyFiltered } = applyToolPolicy(allTools, effectivePolicy);
|
|
207
|
+
if (policyFiltered.length > 0) {
|
|
208
|
+
logger.debug({
|
|
209
|
+
jobName,
|
|
210
|
+
agentId: payload.agentId,
|
|
211
|
+
profile: effectivePolicy.profile,
|
|
212
|
+
filteredCount: policyFiltered.length,
|
|
213
|
+
filtered: policyFiltered.map((f) => ({ tool: f.toolName, reason: f.reason.kind })),
|
|
214
|
+
}, "Cron tool policy applied");
|
|
215
|
+
}
|
|
199
216
|
logger.info({ jobName, agentId: payload.agentId, channelType: deliveryTarget.channelType, toolCount: Array.isArray(tools) ? tools.length : 0 }, "Executing cron agentTurn");
|
|
200
217
|
const execResult = await runWithContext({
|
|
201
218
|
traceId: randomUUID(),
|
|
@@ -11,6 +11,7 @@ import { readFile } from "node:fs/promises";
|
|
|
11
11
|
import { safePath } from "@comis/core";
|
|
12
12
|
import { isHeartbeatContentEffectivelyEmpty } from "@comis/agent";
|
|
13
13
|
import { resolveEffectiveHeartbeatConfig, createAgentHeartbeatSource, createPerAgentHeartbeatRunner, createDuplicateDetector, } from "@comis/scheduler";
|
|
14
|
+
import { applyToolPolicy } from "@comis/skills";
|
|
14
15
|
// ---------------------------------------------------------------------------
|
|
15
16
|
// Setup function
|
|
16
17
|
// ---------------------------------------------------------------------------
|
|
@@ -85,6 +86,7 @@ export function setupHeartbeat(deps) {
|
|
|
85
86
|
getAgentConfig: (agentId) => ({
|
|
86
87
|
model: agents[agentId].model,
|
|
87
88
|
tenantId: container.config.tenantId,
|
|
89
|
+
toolPolicy: agents[agentId].skills?.toolPolicy,
|
|
88
90
|
}),
|
|
89
91
|
checkFileGate,
|
|
90
92
|
systemEventQueue,
|
|
@@ -96,6 +98,14 @@ export function setupHeartbeat(deps) {
|
|
|
96
98
|
},
|
|
97
99
|
activeRunRegistry,
|
|
98
100
|
getMemoryStats,
|
|
101
|
+
// Inject applyToolPolicy so scheduler can filter without taking a direct
|
|
102
|
+
// dependency on @comis/skills. Type-erased `unknown[]` at the boundary is
|
|
103
|
+
// safe: the filter reads only the `.name` field from each tool, and
|
|
104
|
+
// scheduler never inspects tool contents beyond passing them through.
|
|
105
|
+
applyToolPolicyFilter: (allTools, policy) => {
|
|
106
|
+
const { tools, filtered } = applyToolPolicy(allTools, policy);
|
|
107
|
+
return { tools, filtered };
|
|
108
|
+
},
|
|
99
109
|
logger: schedulerLogger,
|
|
100
110
|
});
|
|
101
111
|
// 5. Create and start the per-agent runner
|
|
@@ -32,6 +32,8 @@ export interface MemoryResult {
|
|
|
32
32
|
embeddingCacheStats?: () => import("@comis/memory").EmbeddingCacheStats;
|
|
33
33
|
/** Embedding circuit breaker state accessor for memory persistence operations. */
|
|
34
34
|
embeddingCircuitBreakerState?: () => import("@comis/agent").CircuitState;
|
|
35
|
+
/** Throttled WAL checkpoint — call every health tick, runs checkpoint every 10th call. */
|
|
36
|
+
maintenanceTick: () => void;
|
|
35
37
|
}
|
|
36
38
|
/**
|
|
37
39
|
* Wraps an EmbeddingPort with a circuit breaker that blocks calls when the
|
|
@@ -199,6 +199,20 @@ export async function setupMemory(deps) {
|
|
|
199
199
|
const disposeEmbedding = cachedPort?.dispose
|
|
200
200
|
? async () => { await cachedPort.dispose(); }
|
|
201
201
|
: undefined;
|
|
202
|
+
// Throttled WAL checkpoint: runs PASSIVE checkpoint every 10th call (~5 min at 30s health interval)
|
|
203
|
+
let maintenanceTickCount = 0;
|
|
204
|
+
const maintenanceTick = () => {
|
|
205
|
+
maintenanceTickCount++;
|
|
206
|
+
if (maintenanceTickCount % 10 !== 0)
|
|
207
|
+
return;
|
|
208
|
+
try {
|
|
209
|
+
const pages = memoryAdapter.checkpoint();
|
|
210
|
+
if (pages > 0) {
|
|
211
|
+
memoryLogger.debug({ pages }, "WAL checkpoint moved pages");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch { /* checkpoint failure must not crash health tick */ }
|
|
215
|
+
};
|
|
202
216
|
return {
|
|
203
217
|
disposeEmbedding,
|
|
204
218
|
cachedPort,
|
|
@@ -210,5 +224,6 @@ export async function setupMemory(deps) {
|
|
|
210
224
|
backgroundIndexingPromise,
|
|
211
225
|
embeddingCacheStats,
|
|
212
226
|
embeddingCircuitBreakerState: embeddingCbRef ? () => embeddingCbRef.getState() : undefined,
|
|
227
|
+
maintenanceTick,
|
|
213
228
|
};
|
|
214
229
|
}
|
|
@@ -110,6 +110,7 @@ export async function setupSchedulers(deps) {
|
|
|
110
110
|
maxHistoryTurns: job.maxHistoryTurns,
|
|
111
111
|
cronJobModel: job.payload.kind === "agent_turn" ? job.payload.model : undefined,
|
|
112
112
|
cacheRetention: job.cacheRetention,
|
|
113
|
+
toolPolicy: job.toolPolicy,
|
|
113
114
|
onComplete: deferredResolve,
|
|
114
115
|
});
|
|
115
116
|
// Forward isolated results to main session if requested
|
|
@@ -79,6 +79,7 @@ export interface ShutdownDeps {
|
|
|
79
79
|
/** Raw database handle for close. */
|
|
80
80
|
db: {
|
|
81
81
|
close: () => void;
|
|
82
|
+
pragma: (source: string) => unknown;
|
|
82
83
|
};
|
|
83
84
|
/** Coordinated embedding dispose callback: L1 -> L2 flush -> provider dispose */
|
|
84
85
|
disposeEmbedding?: () => Promise<void>;
|
|
@@ -284,6 +284,10 @@ export function setupShutdown(deps) {
|
|
|
284
284
|
// DB close is ALWAYS last -- no withStepTimeout (must complete or the outer 30s hard timeout handles it)
|
|
285
285
|
{
|
|
286
286
|
const stopMs = Date.now();
|
|
287
|
+
try {
|
|
288
|
+
db.pragma("wal_checkpoint(TRUNCATE)");
|
|
289
|
+
}
|
|
290
|
+
catch { /* best-effort flush before close */ }
|
|
287
291
|
db.close();
|
|
288
292
|
daemonLogger.info({ component: "memory-database", durationMs: Date.now() - stopMs, shutdownOrder: shutdownOrder + 1 }, "Component stopped");
|
|
289
293
|
}
|
|
@@ -144,6 +144,17 @@ export declare const CronJobSchema: z.ZodObject<{
|
|
|
144
144
|
short: "short";
|
|
145
145
|
long: "long";
|
|
146
146
|
}>>;
|
|
147
|
+
/** Per-job tool policy override -- matches AgentConfig.toolPolicy shape.
|
|
148
|
+
*
|
|
149
|
+
* Resolution order: job.toolPolicy > agentConfig.toolPolicy > passthrough
|
|
150
|
+
* (no filtering). Opt-in: omitting this field preserves existing tool set
|
|
151
|
+
* for the job. No silent defaults -- operators explicitly request
|
|
152
|
+
* conservative presets like `{ profile: "cron-minimal" }`. */
|
|
153
|
+
toolPolicy: z.ZodOptional<z.ZodObject<{
|
|
154
|
+
profile: z.ZodDefault<z.ZodString>;
|
|
155
|
+
allow: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
156
|
+
deny: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
157
|
+
}, z.core.$strip>>;
|
|
147
158
|
/** Delivery target for routing results to originating channel */
|
|
148
159
|
deliveryTarget: z.ZodOptional<z.ZodObject<{
|
|
149
160
|
channelId: z.ZodString;
|
|
@@ -98,6 +98,17 @@ export const CronJobSchema = z.strictObject({
|
|
|
98
98
|
maxHistoryTurns: z.number().int().positive().default(3).optional(),
|
|
99
99
|
/** Per-job cache retention override. Default inherits OPERATION_CACHE_DEFAULTS["cron"] = "short". */
|
|
100
100
|
cacheRetention: z.enum(["none", "short", "long"]).optional(),
|
|
101
|
+
/** Per-job tool policy override -- matches AgentConfig.toolPolicy shape.
|
|
102
|
+
*
|
|
103
|
+
* Resolution order: job.toolPolicy > agentConfig.toolPolicy > passthrough
|
|
104
|
+
* (no filtering). Opt-in: omitting this field preserves existing tool set
|
|
105
|
+
* for the job. No silent defaults -- operators explicitly request
|
|
106
|
+
* conservative presets like `{ profile: "cron-minimal" }`. */
|
|
107
|
+
toolPolicy: z.object({
|
|
108
|
+
profile: z.string().default("full"),
|
|
109
|
+
allow: z.array(z.string()).default([]),
|
|
110
|
+
deny: z.array(z.string()).default([]),
|
|
111
|
+
}).optional(),
|
|
101
112
|
/** Delivery target for routing results to originating channel */
|
|
102
113
|
deliveryTarget: CronDeliveryTargetSchema.optional(),
|
|
103
114
|
/** Whether this job is currently enabled */
|
|
@@ -41,6 +41,23 @@ interface HeartbeatExecutor {
|
|
|
41
41
|
interface HeartbeatActiveRunRegistry {
|
|
42
42
|
has(sessionKey: string): boolean;
|
|
43
43
|
}
|
|
44
|
+
/** Tool policy filter function signature -- matches applyToolPolicy from @comis/skills.
|
|
45
|
+
* Injected as a dep so scheduler doesn't take a hard dependency on skills. */
|
|
46
|
+
export interface HeartbeatToolPolicyFilter {
|
|
47
|
+
(tools: unknown[], policy: {
|
|
48
|
+
profile: string;
|
|
49
|
+
allow: string[];
|
|
50
|
+
deny: string[];
|
|
51
|
+
}): {
|
|
52
|
+
tools: unknown[];
|
|
53
|
+
filtered: Array<{
|
|
54
|
+
toolName: string;
|
|
55
|
+
reason: {
|
|
56
|
+
kind: string;
|
|
57
|
+
};
|
|
58
|
+
}>;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
44
61
|
/** Injected session side-effects for heartbeat response processing. */
|
|
45
62
|
export interface HeartbeatSessionOps {
|
|
46
63
|
/** Remove the last user+assistant turn from session transcript. */
|
|
@@ -63,10 +80,15 @@ export interface AgentHeartbeatSourceDeps {
|
|
|
63
80
|
assembleToolsForAgent: (agentId: string) => Promise<unknown[]>;
|
|
64
81
|
/** Get the resolved heartbeat config for an agent. */
|
|
65
82
|
getEffectiveConfig: (agentId: string) => EffectiveHeartbeatConfig;
|
|
66
|
-
/** Get agent-level config (model, tenantId). */
|
|
83
|
+
/** Get agent-level config (model, tenantId, optional toolPolicy). */
|
|
67
84
|
getAgentConfig: (agentId: string) => {
|
|
68
85
|
model: string;
|
|
69
86
|
tenantId: string;
|
|
87
|
+
toolPolicy?: {
|
|
88
|
+
profile: string;
|
|
89
|
+
allow: string[];
|
|
90
|
+
deny: string[];
|
|
91
|
+
};
|
|
70
92
|
};
|
|
71
93
|
/** Returns true if HEARTBEAT.md is effectively empty (should skip LLM). */
|
|
72
94
|
checkFileGate: (agentId: string) => Promise<boolean>;
|
|
@@ -80,6 +102,9 @@ export interface AgentHeartbeatSourceDeps {
|
|
|
80
102
|
sessionOps?: HeartbeatSessionOps;
|
|
81
103
|
/** Optional: fetch memory stats for an agent (for heartbeat prompt injection). */
|
|
82
104
|
getMemoryStats?: (agentId: string, tenantId: string) => HeartbeatMemoryStats | undefined;
|
|
105
|
+
/** Optional: apply a tool policy filter (wired to `applyToolPolicy` from @comis/skills).
|
|
106
|
+
* When absent, no policy is applied and tools pass through unchanged. */
|
|
107
|
+
applyToolPolicyFilter?: HeartbeatToolPolicyFilter;
|
|
83
108
|
/** Logger instance. */
|
|
84
109
|
logger: SchedulerLogger;
|
|
85
110
|
}
|
|
@@ -104,8 +104,29 @@ export function createAgentHeartbeatSource(deps) {
|
|
|
104
104
|
logger.debug({ agentId, formattedKey }, "Heartbeat skipped: session queue busy");
|
|
105
105
|
return;
|
|
106
106
|
}
|
|
107
|
-
// 6. Assemble tools
|
|
108
|
-
|
|
107
|
+
// 6. Assemble tools, then apply opt-in tool policy.
|
|
108
|
+
// Resolution order: config.toolPolicy (heartbeat) > agentConfig.toolPolicy > passthrough.
|
|
109
|
+
// Policy is opt-in per agent -- a missing toolPolicy preserves the agent's
|
|
110
|
+
// interactive tool set for heartbeat ticks. No silent defaults: the explicit
|
|
111
|
+
// "full" fallback documents the contract at the call site.
|
|
112
|
+
const allTools = await deps.assembleToolsForAgent(agentId);
|
|
113
|
+
const effectivePolicy = config.toolPolicy ??
|
|
114
|
+
agentConfig.toolPolicy ??
|
|
115
|
+
{ profile: "full", allow: [], deny: [] };
|
|
116
|
+
let tools = allTools;
|
|
117
|
+
if (deps.applyToolPolicyFilter) {
|
|
118
|
+
const { tools: filteredTools, filtered } = deps.applyToolPolicyFilter(allTools, effectivePolicy);
|
|
119
|
+
tools = filteredTools;
|
|
120
|
+
if (filtered.length > 0) {
|
|
121
|
+
logger.debug({
|
|
122
|
+
agentId,
|
|
123
|
+
trigger,
|
|
124
|
+
profile: effectivePolicy.profile,
|
|
125
|
+
filteredCount: filtered.length,
|
|
126
|
+
filtered: filtered.map((f) => ({ tool: f.toolName, reason: f.reason.kind })),
|
|
127
|
+
}, "Heartbeat tool policy applied");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
109
130
|
// 6.5 Fetch memory stats for conditional prompt injection
|
|
110
131
|
let memoryStats;
|
|
111
132
|
if (deps.getMemoryStats) {
|