@cogitator-ai/channels 0.2.4 → 0.3.0
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/README.md +141 -39
- package/dist/assistant-config.d.ts +1 -0
- package/dist/assistant-config.d.ts.map +1 -1
- package/dist/assistant-config.js +1 -0
- package/dist/assistant-config.js.map +1 -1
- package/dist/channels/discord.d.ts +4 -0
- package/dist/channels/discord.d.ts.map +1 -1
- package/dist/channels/discord.js +123 -59
- package/dist/channels/discord.js.map +1 -1
- package/dist/channels/slack.d.ts +9 -0
- package/dist/channels/slack.d.ts.map +1 -1
- package/dist/channels/slack.js +153 -34
- package/dist/channels/slack.js.map +1 -1
- package/dist/channels/telegram.d.ts +13 -0
- package/dist/channels/telegram.d.ts.map +1 -1
- package/dist/channels/telegram.js +206 -111
- package/dist/channels/telegram.js.map +1 -1
- package/dist/channels/terminal.d.ts +10 -0
- package/dist/channels/terminal.d.ts.map +1 -1
- package/dist/channels/terminal.js +46 -10
- package/dist/channels/terminal.js.map +1 -1
- package/dist/channels/webchat.d.ts +7 -2
- package/dist/channels/webchat.d.ts.map +1 -1
- package/dist/channels/webchat.js +112 -50
- package/dist/channels/webchat.js.map +1 -1
- package/dist/channels/whatsapp.d.ts +19 -3
- package/dist/channels/whatsapp.d.ts.map +1 -1
- package/dist/channels/whatsapp.js +204 -66
- package/dist/channels/whatsapp.js.map +1 -1
- package/dist/cron.d.ts +2 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +9 -0
- package/dist/cron.js.map +1 -0
- package/dist/envelope.d.ts.map +1 -1
- package/dist/envelope.js +7 -6
- package/dist/envelope.js.map +1 -1
- package/dist/formatters/code-protect.d.ts +2 -0
- package/dist/formatters/code-protect.d.ts.map +1 -0
- package/dist/formatters/code-protect.js +12 -0
- package/dist/formatters/code-protect.js.map +1 -0
- package/dist/formatters/markdown.d.ts +1 -1
- package/dist/formatters/markdown.d.ts.map +1 -1
- package/dist/formatters/markdown.js +79 -21
- package/dist/formatters/markdown.js.map +1 -1
- package/dist/formatters/whatsapp-markdown.d.ts.map +1 -1
- package/dist/formatters/whatsapp-markdown.js +7 -21
- package/dist/formatters/whatsapp-markdown.js.map +1 -1
- package/dist/gateway.d.ts +32 -3
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +275 -174
- package/dist/gateway.js.map +1 -1
- package/dist/heartbeat.d.ts +9 -2
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +121 -84
- package/dist/heartbeat.js.map +1 -1
- package/dist/inbound-debounce.js +2 -2
- package/dist/inbound-debounce.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/media/audio-format.d.ts +3 -0
- package/dist/media/audio-format.d.ts.map +1 -0
- package/dist/media/audio-format.js +20 -0
- package/dist/media/audio-format.js.map +1 -0
- package/dist/media/deepgram-stt.d.ts +1 -1
- package/dist/media/deepgram-stt.d.ts.map +1 -1
- package/dist/media/deepgram-stt.js +4 -3
- package/dist/media/deepgram-stt.js.map +1 -1
- package/dist/media/media-processor.d.ts +12 -1
- package/dist/media/media-processor.d.ts.map +1 -1
- package/dist/media/media-processor.js +75 -18
- package/dist/media/media-processor.js.map +1 -1
- package/dist/media/whisper-api.d.ts.map +1 -1
- package/dist/media/whisper-api.js +20 -32
- package/dist/media/whisper-api.js.map +1 -1
- package/dist/media/whisper-local.d.ts +1 -0
- package/dist/media/whisper-local.d.ts.map +1 -1
- package/dist/media/whisper-local.js +100 -45
- package/dist/media/whisper-local.js.map +1 -1
- package/dist/message-queue.d.ts +1 -0
- package/dist/message-queue.d.ts.map +1 -1
- package/dist/message-queue.js +17 -10
- package/dist/message-queue.js.map +1 -1
- package/dist/middleware/auto-extract.d.ts +2 -0
- package/dist/middleware/auto-extract.d.ts.map +1 -1
- package/dist/middleware/auto-extract.js +94 -30
- package/dist/middleware/auto-extract.js.map +1 -1
- package/dist/middleware/dm-policy.d.ts +2 -1
- package/dist/middleware/dm-policy.d.ts.map +1 -1
- package/dist/middleware/dm-policy.js +26 -27
- package/dist/middleware/dm-policy.js.map +1 -1
- package/dist/middleware/owner-commands.d.ts +1 -1
- package/dist/middleware/owner-commands.d.ts.map +1 -1
- package/dist/middleware/owner-commands.js +8 -7
- package/dist/middleware/owner-commands.js.map +1 -1
- package/dist/middleware/pairing-codes.d.ts +12 -0
- package/dist/middleware/pairing-codes.d.ts.map +1 -0
- package/dist/middleware/pairing-codes.js +26 -0
- package/dist/middleware/pairing-codes.js.map +1 -0
- package/dist/middleware/pairing.d.ts +3 -3
- package/dist/middleware/pairing.d.ts.map +1 -1
- package/dist/middleware/pairing.js +18 -25
- package/dist/middleware/pairing.js.map +1 -1
- package/dist/middleware/rate-limit.d.ts +3 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +21 -6
- package/dist/middleware/rate-limit.js.map +1 -1
- package/dist/runtime-builder.d.ts +11 -0
- package/dist/runtime-builder.d.ts.map +1 -1
- package/dist/runtime-builder.js +212 -62
- package/dist/runtime-builder.js.map +1 -1
- package/dist/simple-timer-store.d.ts +6 -0
- package/dist/simple-timer-store.d.ts.map +1 -1
- package/dist/simple-timer-store.js +8 -1
- package/dist/simple-timer-store.js.map +1 -1
- package/dist/stream-buffer.d.ts +14 -7
- package/dist/stream-buffer.d.ts.map +1 -1
- package/dist/stream-buffer.js +129 -84
- package/dist/stream-buffer.js.map +1 -1
- package/dist/tools/path-guard.d.ts +4 -0
- package/dist/tools/path-guard.d.ts.map +1 -0
- package/dist/tools/path-guard.js +53 -0
- package/dist/tools/path-guard.js.map +1 -0
- package/dist/tools/self-config.d.ts +12 -2
- package/dist/tools/self-config.d.ts.map +1 -1
- package/dist/tools/self-config.js +53 -16
- package/dist/tools/self-config.js.map +1 -1
- package/package.json +19 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairing.js","sourceRoot":"","sources":["../../src/middleware/pairing.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"pairing.js","sourceRoot":"","sources":["../../src/middleware/pairing.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,11 @@ export interface RateLimitConfig {
|
|
|
6
6
|
export declare class RateLimitMiddleware implements GatewayMiddleware {
|
|
7
7
|
private readonly config;
|
|
8
8
|
readonly name = "rate-limit";
|
|
9
|
-
private buckets;
|
|
9
|
+
private readonly buckets;
|
|
10
|
+
private lastSweep;
|
|
10
11
|
constructor(config: RateLimitConfig);
|
|
11
12
|
handle(msg: ChannelMessage, ctx: MiddlewareContext, next: () => Promise<void>): Promise<void>;
|
|
13
|
+
private sweep;
|
|
12
14
|
}
|
|
13
15
|
export declare function rateLimit(config: RateLimitConfig): GatewayMiddleware;
|
|
14
16
|
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEhG,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEhG,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AASD,qBAAa,mBAAoB,YAAW,iBAAiB;IAK/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,SAAS,CAAK;gBAEO,MAAM,EAAE,eAAe;IAE9C,MAAM,CACV,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACxB,OAAO,CAAC,IAAI,CAAC;IA8BhB,OAAO,CAAC,KAAK;CASd;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,CAEpE"}
|
|
@@ -1,29 +1,44 @@
|
|
|
1
|
+
const WINDOW_MS = 60_000;
|
|
1
2
|
export class RateLimitMiddleware {
|
|
2
3
|
config;
|
|
3
4
|
name = 'rate-limit';
|
|
4
5
|
buckets = new Map();
|
|
6
|
+
lastSweep = 0;
|
|
5
7
|
constructor(config) {
|
|
6
8
|
this.config = config;
|
|
7
9
|
}
|
|
8
10
|
async handle(msg, ctx, next) {
|
|
9
11
|
const userKey = `${msg.channelType}:${msg.userId}`;
|
|
10
12
|
const now = Date.now();
|
|
11
|
-
|
|
13
|
+
this.sweep(now);
|
|
12
14
|
let bucket = this.buckets.get(userKey);
|
|
13
15
|
if (!bucket) {
|
|
14
|
-
bucket = { timestamps: [] };
|
|
16
|
+
bucket = { timestamps: [], notified: false };
|
|
15
17
|
this.buckets.set(userKey, bucket);
|
|
16
18
|
}
|
|
17
|
-
bucket.timestamps = bucket.timestamps.filter((t) => now - t <
|
|
19
|
+
bucket.timestamps = bucket.timestamps.filter((t) => now - t < WINDOW_MS);
|
|
18
20
|
if (bucket.timestamps.length >= this.config.maxPerMinute) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
if (!bucket.notified) {
|
|
22
|
+
bucket.notified = true;
|
|
23
|
+
await ctx.channel.sendText(msg.channelId, this.config.message ??
|
|
24
|
+
'Rate limit exceeded. Please wait a moment before sending another message.');
|
|
25
|
+
}
|
|
22
26
|
return;
|
|
23
27
|
}
|
|
28
|
+
bucket.notified = false;
|
|
24
29
|
bucket.timestamps.push(now);
|
|
25
30
|
await next();
|
|
26
31
|
}
|
|
32
|
+
sweep(now) {
|
|
33
|
+
if (now - this.lastSweep < WINDOW_MS)
|
|
34
|
+
return;
|
|
35
|
+
this.lastSweep = now;
|
|
36
|
+
for (const [key, bucket] of this.buckets) {
|
|
37
|
+
if (bucket.timestamps.every((t) => now - t >= WINDOW_MS)) {
|
|
38
|
+
this.buckets.delete(key);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
27
42
|
}
|
|
28
43
|
export function rateLimit(config) {
|
|
29
44
|
return new RateLimitMiddleware(config);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAYA,MAAM,SAAS,GAAG,MAAM,CAAC;AAEzB,MAAM,OAAO,mBAAmB;IAKD;IAJpB,IAAI,GAAG,YAAY,CAAC;IACZ,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IACjD,SAAS,GAAG,CAAC,CAAC;IAEtB,YAA6B,MAAuB;QAAvB,WAAM,GAAN,MAAM,CAAiB;IAAG,CAAC;IAExD,KAAK,CAAC,MAAM,CACV,GAAmB,EACnB,GAAsB,EACtB,IAAyB;QAEzB,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAEhB,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;QAEzE,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACrB,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACvB,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CACxB,GAAG,CAAC,SAAS,EACb,IAAI,CAAC,MAAM,CAAC,OAAO;oBACjB,2EAA2E,CAC9E,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,IAAI,EAAE,CAAC;IACf,CAAC;IAEO,KAAK,CAAC,GAAW;QACvB,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,SAAS;YAAE,OAAO;QAC7C,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;QACrB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACzC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC;gBACzD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,SAAS,CAAC,MAAuB;IAC/C,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -17,16 +17,27 @@ export interface RuntimeBuilderOpts {
|
|
|
17
17
|
stringifyYaml: (o: unknown) => string;
|
|
18
18
|
validateConfig: (o: unknown) => unknown;
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Invoked when the assistant needs to restart (config change, `/restart`).
|
|
22
|
+
* Defaults to exiting the process with code 78, which `cogitator up` treats as a restart request.
|
|
23
|
+
*/
|
|
24
|
+
onRestart?: () => void;
|
|
20
25
|
}
|
|
26
|
+
export declare const RESTART_EXIT_CODE = 78;
|
|
21
27
|
export declare class RuntimeBuilder {
|
|
22
28
|
private config;
|
|
23
29
|
private env;
|
|
24
30
|
private opts?;
|
|
25
31
|
constructor(config: AssistantConfig, env: Record<string, string | undefined>, opts?: RuntimeBuilderOpts | undefined);
|
|
26
32
|
build(): Promise<BuiltRuntime>;
|
|
33
|
+
private requestRestart;
|
|
34
|
+
private collectOwnerIds;
|
|
35
|
+
private resolveFileSystemRoots;
|
|
36
|
+
private buildMemoryBackends;
|
|
27
37
|
private createExtractorBackend;
|
|
28
38
|
private wireBrowser;
|
|
29
39
|
private ensurePlaywright;
|
|
40
|
+
private playwrightCacheDir;
|
|
30
41
|
private wireRAG;
|
|
31
42
|
private wireMCPServers;
|
|
32
43
|
private resolveEmbeddingConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-builder.d.ts","sourceRoot":"","sources":["../src/runtime-builder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime-builder.d.ts","sourceRoot":"","sources":["../src/runtime-builder.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,KAAK,EACL,SAAS,EAUV,MAAM,oBAAoB,CAAC;AAe5B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAkBjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAgBD,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE;QACd,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QAClC,aAAa,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;QACtC,cAAc,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;KACzC,CAAC;IACF;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,KAAK,CAAC;AA2BpC,qBAAa,cAAc;IAEvB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,IAAI,CAAC;gBAFL,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,IAAI,CAAC,EAAE,kBAAkB,YAAA;IAG7B,KAAK,IAAI,OAAO,CAAC,YAAY,CAAC;IA6SpC,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,sBAAsB;YAMhB,mBAAmB;IAoDjC,OAAO,CAAC,sBAAsB;YAqBhB,WAAW;YAiEX,gBAAgB;IAQ9B,OAAO,CAAC,kBAAkB;YAeZ,OAAO;YA4DP,cAAc;IAoC5B,OAAO,CAAC,sBAAsB;IAkC9B,OAAO,KAAK,WAAW,GAItB;IAED,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,iBAAiB;IA0FzB,OAAO,CAAC,gBAAgB;YAaV,kBAAkB;IAgBhC,OAAO,CAAC,eAAe;CAOxB"}
|
package/dist/runtime-builder.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
1
2
|
import { homedir } from 'node:os';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import { Agent, Cogitator, builtinTools, createMemoryTools, createSchedulerTools, createCapabilitiesTool, createDeviceTools, createSelfTools, loadCustomTools, parseModel, tool as createTool, } from '@cogitator-ai/core';
|
|
4
|
-
import { SQLiteAdapter, SQLiteGraphAdapter, CoreFactsStore, LLMEntityExtractor, createEmbeddingService, InMemoryEmbeddingAdapter, } from '@cogitator-ai/memory';
|
|
5
|
+
import { SQLiteAdapter, SQLiteGraphAdapter, PostgresAdapter, PostgresGraphAdapter, CoreFactsStore, LLMEntityExtractor, createEmbeddingService, InMemoryEmbeddingAdapter, } from '@cogitator-ai/memory';
|
|
5
6
|
import { createSelfConfigTools } from './tools/self-config.js';
|
|
7
|
+
import { restrictFileTools } from './tools/path-guard.js';
|
|
6
8
|
import { Gateway } from './gateway.js';
|
|
9
|
+
import { getNextCronMs } from './cron.js';
|
|
7
10
|
import { HeartbeatScheduler } from './heartbeat.js';
|
|
8
11
|
import { SimpleTimerStore } from './simple-timer-store.js';
|
|
9
12
|
import { telegramChannel } from './channels/telegram.js';
|
|
@@ -13,13 +16,37 @@ import { terminalChannel } from './channels/terminal.js';
|
|
|
13
16
|
import { ownerCommands } from './middleware/owner-commands.js';
|
|
14
17
|
import { rateLimit } from './middleware/rate-limit.js';
|
|
15
18
|
import { autoExtract } from './middleware/auto-extract.js';
|
|
16
|
-
import {
|
|
19
|
+
import { DmPolicyMiddleware } from './middleware/dm-policy.js';
|
|
17
20
|
import { generateCapabilitiesDoc } from './capabilities.js';
|
|
18
21
|
import { MediaProcessor } from './media/media-processor.js';
|
|
19
22
|
import { LocalWhisper } from './media/whisper-local.js';
|
|
20
23
|
import { createWhisperDownloadTool } from './media/whisper-tool.js';
|
|
21
24
|
import { GroqSttProvider, OpenAISttProvider } from './media/whisper-api.js';
|
|
22
25
|
import { DeepgramSttProvider } from './media/deepgram-stt.js';
|
|
26
|
+
export const RESTART_EXIT_CODE = 78;
|
|
27
|
+
const MODULE_NOT_FOUND_CODES = new Set(['ERR_MODULE_NOT_FOUND', 'MODULE_NOT_FOUND']);
|
|
28
|
+
function isModuleNotFound(err, specifier) {
|
|
29
|
+
if (!(err instanceof Error))
|
|
30
|
+
return false;
|
|
31
|
+
const code = err.code;
|
|
32
|
+
return !!code && MODULE_NOT_FOUND_CODES.has(code) && err.message.includes(specifier);
|
|
33
|
+
}
|
|
34
|
+
function expandHome(path) {
|
|
35
|
+
return path.startsWith('~') ? path.replace(/^~/, homedir()) : path;
|
|
36
|
+
}
|
|
37
|
+
function localIsoDate(date) {
|
|
38
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
39
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
40
|
+
}
|
|
41
|
+
function formatDuration(ms) {
|
|
42
|
+
const minutes = Math.floor(ms / 60_000);
|
|
43
|
+
if (minutes < 60)
|
|
44
|
+
return `${minutes}m`;
|
|
45
|
+
const hours = Math.floor(minutes / 60);
|
|
46
|
+
if (hours < 24)
|
|
47
|
+
return `${hours}h ${minutes % 60}m`;
|
|
48
|
+
return `${Math.floor(hours / 24)}d ${hours % 24}h`;
|
|
49
|
+
}
|
|
23
50
|
export class RuntimeBuilder {
|
|
24
51
|
config;
|
|
25
52
|
env;
|
|
@@ -32,17 +59,9 @@ export class RuntimeBuilder {
|
|
|
32
59
|
async build() {
|
|
33
60
|
const cogitator = this.buildCogitator();
|
|
34
61
|
const cleanupResources = { mcpClients: [] };
|
|
35
|
-
const
|
|
36
|
-
const resolvedPath = memoryPath.replace(/^~/, homedir());
|
|
37
|
-
const memoryAdapter = new SQLiteAdapter({ provider: 'sqlite', path: resolvedPath });
|
|
38
|
-
await memoryAdapter.connect();
|
|
62
|
+
const { memoryAdapter, graphAdapter, coreFactsPath } = await this.buildMemoryBackends(cleanupResources);
|
|
39
63
|
cogitator.memory = memoryAdapter;
|
|
40
|
-
|
|
41
|
-
if (this.config.memory.knowledgeGraph !== false) {
|
|
42
|
-
graphAdapter = new SQLiteGraphAdapter({ path: resolvedPath });
|
|
43
|
-
await graphAdapter.initialize();
|
|
44
|
-
}
|
|
45
|
-
const coreFacts = new CoreFactsStore({ path: resolvedPath });
|
|
64
|
+
const coreFacts = new CoreFactsStore({ path: coreFactsPath });
|
|
46
65
|
await coreFacts.initialize();
|
|
47
66
|
const tools = [];
|
|
48
67
|
if (this.config.capabilities.webSearch) {
|
|
@@ -53,8 +72,10 @@ export class RuntimeBuilder {
|
|
|
53
72
|
tools.push(found);
|
|
54
73
|
}
|
|
55
74
|
}
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
const fsCfg = this.config.capabilities.fileSystem;
|
|
76
|
+
if (fsCfg) {
|
|
77
|
+
const fileTools = builtinTools.filter((t) => t.name.startsWith('file_'));
|
|
78
|
+
tools.push(...restrictFileTools(fileTools, this.resolveFileSystemRoots()));
|
|
58
79
|
}
|
|
59
80
|
if (this.config.capabilities.github) {
|
|
60
81
|
const found = builtinTools.find((t) => t.name === 'github_api');
|
|
@@ -73,28 +94,29 @@ export class RuntimeBuilder {
|
|
|
73
94
|
if (this.config.capabilities.scheduler) {
|
|
74
95
|
timerStore = new SimpleTimerStore({
|
|
75
96
|
persistPath: join(homedir(), '.cogitator', 'timers.json'),
|
|
97
|
+
resolveCronFiresAt: (cron, timezone) => getNextCronMs(cron, Date.now(), timezone),
|
|
76
98
|
});
|
|
77
|
-
const
|
|
78
|
-
const firstChannel = channelEntries[0];
|
|
79
|
-
const firstOwnerId = firstChannel
|
|
80
|
-
? firstChannel[1]?.ownerIds?.[0]
|
|
81
|
-
: undefined;
|
|
99
|
+
const [firstChannelName, firstChannel] = Object.entries(this.config.channels).find(([, value]) => value !== undefined) ?? [undefined, undefined];
|
|
82
100
|
tools.push(...createSchedulerTools({
|
|
83
101
|
store: timerStore,
|
|
84
|
-
defaultChannel:
|
|
85
|
-
defaultUserId:
|
|
102
|
+
defaultChannel: firstChannelName ?? 'system',
|
|
103
|
+
defaultUserId: firstChannel?.ownerIds?.[0],
|
|
86
104
|
}));
|
|
87
105
|
}
|
|
88
106
|
if (this.config.capabilities.deviceTools) {
|
|
89
107
|
tools.push(...createDeviceTools());
|
|
90
108
|
}
|
|
109
|
+
const ownerIds = this.collectOwnerIds();
|
|
110
|
+
const isOwner = (caller) => caller.channelType === 'terminal' ||
|
|
111
|
+
(!!caller.channelType && !!caller.userId && ownerIds[caller.channelType] === caller.userId);
|
|
91
112
|
if (this.config.capabilities.selfConfig && this.opts?.configPath && this.opts.configHelpers) {
|
|
92
113
|
tools.push(...createSelfConfigTools({
|
|
93
114
|
configPath: this.opts.configPath,
|
|
94
115
|
...this.opts.configHelpers,
|
|
116
|
+
authorize: isOwner,
|
|
95
117
|
onConfigUpdated: () => {
|
|
96
118
|
console.log(`[${this.config.name}] Config updated, restarting...`);
|
|
97
|
-
|
|
119
|
+
this.requestRestart();
|
|
98
120
|
},
|
|
99
121
|
}));
|
|
100
122
|
}
|
|
@@ -117,47 +139,98 @@ export class RuntimeBuilder {
|
|
|
117
139
|
await this.wireBrowser(tools, cleanupResources);
|
|
118
140
|
await this.wireRAG(tools);
|
|
119
141
|
await this.wireMCPServers(tools, cleanupResources);
|
|
120
|
-
const coreFactsText = await coreFacts.formatForPrompt();
|
|
121
142
|
const channels = this.buildChannels();
|
|
122
143
|
const capDoc = generateCapabilitiesDoc({
|
|
123
144
|
tools: tools.map((t) => ({ name: t.name, description: t.description })),
|
|
124
145
|
channels: channels.map((c) => c.type),
|
|
125
146
|
});
|
|
126
147
|
tools.push(createCapabilitiesTool(capDoc));
|
|
127
|
-
const instructions = this.buildInstructions(coreFactsText);
|
|
128
148
|
const agent = new Agent({
|
|
129
149
|
name: this.config.name,
|
|
130
150
|
model: this.fullModelId,
|
|
131
|
-
instructions,
|
|
151
|
+
instructions: this.buildInstructions(await coreFacts.formatForPrompt(), new Date()),
|
|
132
152
|
tools,
|
|
133
153
|
maxIterations: 15,
|
|
134
154
|
});
|
|
155
|
+
const modelOverrides = new Map();
|
|
156
|
+
let globalModel = this.fullModelId;
|
|
157
|
+
const agentForUser = async (user) => {
|
|
158
|
+
const model = modelOverrides.get(`${user.channelType}:${user.id}`) ??
|
|
159
|
+
modelOverrides.get(user.id) ??
|
|
160
|
+
globalModel;
|
|
161
|
+
const instructions = this.buildInstructions(await coreFacts.formatForPrompt(), new Date());
|
|
162
|
+
return new Agent({ ...agent.config, id: agent.id, model, instructions });
|
|
163
|
+
};
|
|
135
164
|
const middleware = [];
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
ownerIds.telegram = this.config.channels.telegram.ownerIds[0];
|
|
139
|
-
}
|
|
140
|
-
if (this.config.channels.discord?.ownerIds?.[0]) {
|
|
141
|
-
ownerIds.discord = this.config.channels.discord.ownerIds[0];
|
|
142
|
-
}
|
|
143
|
-
if (this.config.channels.slack?.ownerIds?.[0]) {
|
|
144
|
-
ownerIds.slack = this.config.channels.slack.ownerIds[0];
|
|
145
|
-
}
|
|
165
|
+
let gatewayRef = null;
|
|
166
|
+
let dmPolicyMiddleware = null;
|
|
146
167
|
if (this.config.security) {
|
|
147
|
-
|
|
168
|
+
dmPolicyMiddleware = new DmPolicyMiddleware({
|
|
148
169
|
mode: this.config.security.dmPolicy,
|
|
149
170
|
allowlist: this.config.security.allowlist,
|
|
150
171
|
groupPolicy: this.config.security.groupPolicy,
|
|
151
172
|
groupAllowlist: this.config.security.groupAllowlist,
|
|
152
|
-
storePath: this.config.security.storePath
|
|
173
|
+
storePath: this.config.security.storePath
|
|
174
|
+
? expandHome(this.config.security.storePath)
|
|
175
|
+
: undefined,
|
|
153
176
|
ownerIds,
|
|
154
|
-
})
|
|
177
|
+
});
|
|
178
|
+
middleware.push(dmPolicyMiddleware);
|
|
155
179
|
}
|
|
156
180
|
if (Object.keys(ownerIds).length > 0) {
|
|
157
181
|
middleware.push(ownerCommands({
|
|
158
182
|
ownerIds,
|
|
159
183
|
authorizedUserIds: this.config.security?.commandAccess?.authorized,
|
|
160
184
|
publicCommands: this.config.security?.commandAccess?.publicCommands,
|
|
185
|
+
onStatus: () => {
|
|
186
|
+
if (!gatewayRef)
|
|
187
|
+
return 'Gateway is not running';
|
|
188
|
+
const stats = gatewayRef.stats;
|
|
189
|
+
return [
|
|
190
|
+
`Assistant: ${this.config.name}`,
|
|
191
|
+
`Model: ${globalModel}`,
|
|
192
|
+
`Uptime: ${formatDuration(stats.uptime)}`,
|
|
193
|
+
`Sessions: ${stats.activeSessions} active / ${stats.totalSessions} total`,
|
|
194
|
+
`Messages today: ${stats.messagesToday}`,
|
|
195
|
+
`Channels: ${stats.connectedChannels.join(', ')}`,
|
|
196
|
+
].join('\n');
|
|
197
|
+
},
|
|
198
|
+
onSessions: () => {
|
|
199
|
+
const sessions = gatewayRef?.getSessions() ?? [];
|
|
200
|
+
if (sessions.length === 0)
|
|
201
|
+
return 'No sessions yet';
|
|
202
|
+
return sessions
|
|
203
|
+
.slice(0, 20)
|
|
204
|
+
.map((s) => `${s.active ? '●' : '○'} ${s.threadId}${s.userName ? ` (${s.userName})` : ''} — ${s.messageCount} msg, ${formatDuration(Date.now() - s.lastActiveAt)} ago`)
|
|
205
|
+
.join('\n');
|
|
206
|
+
},
|
|
207
|
+
onUsers: () => {
|
|
208
|
+
const owners = Object.entries(ownerIds).map(([type, id]) => `${type}:${id} (owner)`);
|
|
209
|
+
const approved = dmPolicyMiddleware
|
|
210
|
+
? dmPolicyMiddleware
|
|
211
|
+
.getApprovedUsers()
|
|
212
|
+
.filter((key) => !owners.some((o) => o.startsWith(`${key} `)))
|
|
213
|
+
: [];
|
|
214
|
+
return [...owners, ...approved].join('\n') || 'No users';
|
|
215
|
+
},
|
|
216
|
+
onCompact: async (target, threadId) => {
|
|
217
|
+
if (!gatewayRef)
|
|
218
|
+
return 'Gateway is not running';
|
|
219
|
+
return gatewayRef.compactThread(target === 'current' ? threadId : target);
|
|
220
|
+
},
|
|
221
|
+
onModel: (model, forUser) => {
|
|
222
|
+
const fullModel = model.includes('/') ? model : `${this.config.llm.provider}/${model}`;
|
|
223
|
+
if (forUser) {
|
|
224
|
+
const key = forUser.replace(/^@/, '');
|
|
225
|
+
modelOverrides.set(key, fullModel);
|
|
226
|
+
return `Model for ${key} set to: ${fullModel}`;
|
|
227
|
+
}
|
|
228
|
+
globalModel = fullModel;
|
|
229
|
+
return `Model set to: ${fullModel}`;
|
|
230
|
+
},
|
|
231
|
+
onRestart: async () => {
|
|
232
|
+
setTimeout(() => this.requestRestart(), 500);
|
|
233
|
+
},
|
|
161
234
|
}));
|
|
162
235
|
}
|
|
163
236
|
if (this.config.rateLimit) {
|
|
@@ -192,14 +265,12 @@ export class RuntimeBuilder {
|
|
|
192
265
|
coreFacts,
|
|
193
266
|
}));
|
|
194
267
|
}
|
|
195
|
-
const streamConfig =
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
: { flushInterval: 600, minChunkSize: 30 };
|
|
268
|
+
const streamConfig = {
|
|
269
|
+
flushInterval: this.config.stream?.flushInterval ?? 600,
|
|
270
|
+
minChunkSize: this.config.stream?.minChunkSize ?? 30,
|
|
271
|
+
};
|
|
201
272
|
const gateway = new Gateway({
|
|
202
|
-
agent,
|
|
273
|
+
agent: agentForUser,
|
|
203
274
|
cogitator,
|
|
204
275
|
channels,
|
|
205
276
|
middleware,
|
|
@@ -219,6 +290,7 @@ export class RuntimeBuilder {
|
|
|
219
290
|
console.error(`[${this.config.name}] Error for ${msg.userId}:`, err.message);
|
|
220
291
|
},
|
|
221
292
|
});
|
|
293
|
+
gatewayRef = gateway;
|
|
222
294
|
const scheduler = this.buildScheduler(timerStore, gateway);
|
|
223
295
|
if (scheduler)
|
|
224
296
|
scheduler.start();
|
|
@@ -227,9 +299,11 @@ export class RuntimeBuilder {
|
|
|
227
299
|
scheduler.stop();
|
|
228
300
|
await gateway.stop();
|
|
229
301
|
await coreFacts.close();
|
|
230
|
-
if (graphAdapter)
|
|
302
|
+
if (graphAdapter?.close)
|
|
231
303
|
await graphAdapter.close();
|
|
232
304
|
await memoryAdapter.disconnect();
|
|
305
|
+
if (cleanupResources.pgPool)
|
|
306
|
+
await cleanupResources.pgPool.end().catch(() => { });
|
|
233
307
|
if (cleanupResources.browserSession) {
|
|
234
308
|
await cleanupResources.browserSession.close().catch(() => { });
|
|
235
309
|
}
|
|
@@ -240,6 +314,66 @@ export class RuntimeBuilder {
|
|
|
240
314
|
};
|
|
241
315
|
return { agent, cogitator, gateway, scheduler, cleanup };
|
|
242
316
|
}
|
|
317
|
+
requestRestart() {
|
|
318
|
+
if (this.opts?.onRestart) {
|
|
319
|
+
this.opts.onRestart();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
process.exit(RESTART_EXIT_CODE);
|
|
323
|
+
}
|
|
324
|
+
collectOwnerIds() {
|
|
325
|
+
const ownerIds = {};
|
|
326
|
+
for (const [channel, cfg] of Object.entries(this.config.channels)) {
|
|
327
|
+
const owner = cfg?.ownerIds?.[0];
|
|
328
|
+
if (owner)
|
|
329
|
+
ownerIds[channel] = owner;
|
|
330
|
+
}
|
|
331
|
+
return ownerIds;
|
|
332
|
+
}
|
|
333
|
+
resolveFileSystemRoots() {
|
|
334
|
+
const fsCfg = this.config.capabilities.fileSystem;
|
|
335
|
+
const paths = fsCfg?.paths.length ? fsCfg.paths : [homedir()];
|
|
336
|
+
return paths.map(expandHome);
|
|
337
|
+
}
|
|
338
|
+
async buildMemoryBackends(resources) {
|
|
339
|
+
const memory = this.config.memory;
|
|
340
|
+
const sqlitePath = expandHome(memory.path ?? '~/.cogitator/memory.db');
|
|
341
|
+
const useGraph = memory.knowledgeGraph !== false;
|
|
342
|
+
if (memory.adapter === 'postgres') {
|
|
343
|
+
const connectionString = memory.connectionString ?? this.env.DATABASE_URL ?? this.env.POSTGRES_URL;
|
|
344
|
+
if (!connectionString) {
|
|
345
|
+
throw new Error('memory.adapter "postgres" requires memory.connectionString or DATABASE_URL in env');
|
|
346
|
+
}
|
|
347
|
+
const memoryAdapter = new PostgresAdapter({ provider: 'postgres', connectionString });
|
|
348
|
+
const connected = await memoryAdapter.connect();
|
|
349
|
+
if (!connected.success) {
|
|
350
|
+
throw new Error(`Failed to connect to Postgres: ${connected.error}`);
|
|
351
|
+
}
|
|
352
|
+
let graphAdapter = null;
|
|
353
|
+
if (useGraph) {
|
|
354
|
+
const pg = (await import('pg'));
|
|
355
|
+
const Pool = pg.Pool ?? pg.default?.Pool;
|
|
356
|
+
if (!Pool)
|
|
357
|
+
throw new Error('The "pg" package does not export Pool');
|
|
358
|
+
const pool = new Pool({ connectionString });
|
|
359
|
+
resources.pgPool = pool;
|
|
360
|
+
graphAdapter = new PostgresGraphAdapter({ pool });
|
|
361
|
+
await graphAdapter.initialize();
|
|
362
|
+
}
|
|
363
|
+
return { memoryAdapter, graphAdapter, coreFactsPath: sqlitePath };
|
|
364
|
+
}
|
|
365
|
+
const memoryAdapter = new SQLiteAdapter({ provider: 'sqlite', path: sqlitePath });
|
|
366
|
+
const connected = await memoryAdapter.connect();
|
|
367
|
+
if (connected && !connected.success) {
|
|
368
|
+
throw new Error(`Failed to open SQLite memory at ${sqlitePath}: ${connected.error}`);
|
|
369
|
+
}
|
|
370
|
+
let graphAdapter = null;
|
|
371
|
+
if (useGraph) {
|
|
372
|
+
graphAdapter = new SQLiteGraphAdapter({ path: sqlitePath });
|
|
373
|
+
await graphAdapter.initialize();
|
|
374
|
+
}
|
|
375
|
+
return { memoryAdapter, graphAdapter, coreFactsPath: sqlitePath };
|
|
376
|
+
}
|
|
243
377
|
createExtractorBackend(cogitator) {
|
|
244
378
|
const llmBackend = cogitator.getLLMBackend(this.fullModelId);
|
|
245
379
|
const modelName = parseModel(this.fullModelId).model;
|
|
@@ -310,15 +444,24 @@ export class RuntimeBuilder {
|
|
|
310
444
|
}
|
|
311
445
|
}
|
|
312
446
|
async ensurePlaywright() {
|
|
313
|
-
|
|
314
|
-
const { join } = await import('node:path');
|
|
315
|
-
const cacheDir = process.env.PLAYWRIGHT_BROWSERS_PATH ?? join(homedir(), 'Library', 'Caches', 'ms-playwright');
|
|
316
|
-
if (existsSync(cacheDir))
|
|
447
|
+
if (existsSync(this.playwrightCacheDir()))
|
|
317
448
|
return;
|
|
318
449
|
console.log('[RuntimeBuilder] Installing Playwright chromium...');
|
|
319
450
|
const { execSync } = await import('node:child_process');
|
|
320
451
|
execSync('npx playwright install chromium', { stdio: 'inherit' });
|
|
321
452
|
}
|
|
453
|
+
playwrightCacheDir() {
|
|
454
|
+
if (process.env.PLAYWRIGHT_BROWSERS_PATH)
|
|
455
|
+
return process.env.PLAYWRIGHT_BROWSERS_PATH;
|
|
456
|
+
switch (process.platform) {
|
|
457
|
+
case 'darwin':
|
|
458
|
+
return join(homedir(), 'Library', 'Caches', 'ms-playwright');
|
|
459
|
+
case 'win32':
|
|
460
|
+
return join(process.env.LOCALAPPDATA ?? join(homedir(), 'AppData', 'Local'), 'ms-playwright');
|
|
461
|
+
default:
|
|
462
|
+
return join(process.env.XDG_CACHE_HOME ?? join(homedir(), '.cache'), 'ms-playwright');
|
|
463
|
+
}
|
|
464
|
+
}
|
|
322
465
|
async wireRAG(tools) {
|
|
323
466
|
if (!this.config.capabilities.rag)
|
|
324
467
|
return;
|
|
@@ -356,8 +499,12 @@ export class RuntimeBuilder {
|
|
|
356
499
|
execute: ingestTool.execute,
|
|
357
500
|
}));
|
|
358
501
|
}
|
|
359
|
-
catch {
|
|
360
|
-
|
|
502
|
+
catch (err) {
|
|
503
|
+
if (isModuleNotFound(err, '@cogitator-ai/rag')) {
|
|
504
|
+
console.warn('[RuntimeBuilder] RAG capability requires @cogitator-ai/rag package');
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
console.warn('[RuntimeBuilder] RAG capability failed:', err instanceof Error ? err.message : String(err));
|
|
361
508
|
}
|
|
362
509
|
}
|
|
363
510
|
async wireMCPServers(tools, resources) {
|
|
@@ -382,8 +529,12 @@ export class RuntimeBuilder {
|
|
|
382
529
|
}
|
|
383
530
|
}
|
|
384
531
|
}
|
|
385
|
-
catch {
|
|
386
|
-
|
|
532
|
+
catch (err) {
|
|
533
|
+
if (isModuleNotFound(err, '@cogitator-ai/mcp')) {
|
|
534
|
+
console.warn('[RuntimeBuilder] MCP servers require @cogitator-ai/mcp package');
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
console.warn('[RuntimeBuilder] MCP setup failed:', err instanceof Error ? err.message : String(err));
|
|
387
538
|
}
|
|
388
539
|
}
|
|
389
540
|
resolveEmbeddingConfig() {
|
|
@@ -488,11 +639,13 @@ export class RuntimeBuilder {
|
|
|
488
639
|
await gateway.injectMessage(msg);
|
|
489
640
|
},
|
|
490
641
|
pollInterval: 30_000,
|
|
642
|
+
onError: (err, entry) => {
|
|
643
|
+
console.error(`[${this.config.name}] Scheduler error${entry ? ` for ${entry.id}` : ''}:`, err.message);
|
|
644
|
+
},
|
|
491
645
|
});
|
|
492
646
|
}
|
|
493
|
-
buildInstructions(coreFactsText) {
|
|
647
|
+
buildInstructions(coreFactsText, now) {
|
|
494
648
|
let instructions = this.config.personality;
|
|
495
|
-
const now = new Date();
|
|
496
649
|
const dateStr = now.toLocaleDateString('en-US', {
|
|
497
650
|
weekday: 'long',
|
|
498
651
|
year: 'numeric',
|
|
@@ -505,11 +658,8 @@ export class RuntimeBuilder {
|
|
|
505
658
|
instructions += `\n\n## What I know about the user\n${coreFactsText}`;
|
|
506
659
|
}
|
|
507
660
|
instructions += `\n\nIMPORTANT: Use your tools when relevant. Don't guess answers when tools can provide accurate data.`;
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const paths = typeof fsCfg === 'object' && 'paths' in fsCfg
|
|
511
|
-
? fsCfg.paths.map((p) => p.replace(/^~/, homedir()))
|
|
512
|
-
: [homedir()];
|
|
661
|
+
if (this.config.capabilities.fileSystem) {
|
|
662
|
+
const paths = this.resolveFileSystemRoots();
|
|
513
663
|
instructions += `\nYou have filesystem access. Allowed paths: ${paths.join(', ')}. Use file_read, file_write, file_list tools. Always use absolute paths.`;
|
|
514
664
|
}
|
|
515
665
|
if (this.config.capabilities.browser) {
|
|
@@ -532,7 +682,7 @@ When to use — IMMEDIATELY call schedule_task when the user:
|
|
|
532
682
|
Examples:
|
|
533
683
|
- "Remind me to check Slack in 5 min" → schedule_task({description: "Check Slack", delay: "5m"})
|
|
534
684
|
- "Every morning at 9" → schedule_task({description: "Morning briefing", cron: "0 9 * * *"})
|
|
535
|
-
- "At 3pm today" → schedule_task({description: "...", at: "${
|
|
685
|
+
- "At 3pm today" → schedule_task({description: "...", at: "${localIsoDate(now)}T15:00:00"})
|
|
536
686
|
|
|
537
687
|
The channel and userId are filled automatically from the current conversation — do NOT pass them manually.
|
|
538
688
|
When the task fires, you will execute it — describe what to DO, not just what to say.
|