@jcheesepkg/nanobot 0.9.0 → 0.9.2
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 +18 -18
- package/dist/agent/context.d.mts +4 -4
- package/dist/agent/context.d.mts.map +1 -1
- package/dist/agent/context.mjs +27 -28
- package/dist/agent/context.mjs.map +1 -1
- package/dist/agent/loop.d.mts +5 -3
- package/dist/agent/loop.d.mts.map +1 -1
- package/dist/agent/loop.mjs +64 -55
- package/dist/agent/loop.mjs.map +1 -1
- package/dist/agent/memory.d.mts.map +1 -1
- package/dist/agent/memory.mjs +3 -3
- package/dist/agent/memory.mjs.map +1 -1
- package/dist/agent/skills.d.mts.map +1 -1
- package/dist/agent/skills.mjs +4 -4
- package/dist/agent/skills.mjs.map +1 -1
- package/dist/agent/subagent.d.mts.map +1 -1
- package/dist/agent/subagent.mjs +22 -22
- package/dist/agent/subagent.mjs.map +1 -1
- package/dist/agent/tools/base.mjs +2 -2
- package/dist/agent/tools/base.mjs.map +1 -1
- package/dist/agent/tools/cron.d.mts +1 -1
- package/dist/agent/tools/cron.d.mts.map +1 -1
- package/dist/agent/tools/cron.mjs +11 -11
- package/dist/agent/tools/cron.mjs.map +1 -1
- package/dist/agent/tools/filesystem.d.mts +4 -4
- package/dist/agent/tools/filesystem.d.mts.map +1 -1
- package/dist/agent/tools/filesystem.mjs +20 -20
- package/dist/agent/tools/filesystem.mjs.map +1 -1
- package/dist/agent/tools/flex.d.mts +1 -1
- package/dist/agent/tools/flex.d.mts.map +1 -1
- package/dist/agent/tools/flex.mjs +112 -112
- package/dist/agent/tools/flex.mjs.map +1 -1
- package/dist/agent/tools/flex.test.mjs +60 -59
- package/dist/agent/tools/flex.test.mjs.map +1 -1
- package/dist/agent/tools/message.d.mts +1 -1
- package/dist/agent/tools/message.d.mts.map +1 -1
- package/dist/agent/tools/message.mjs +4 -4
- package/dist/agent/tools/message.mjs.map +1 -1
- package/dist/agent/tools/registry.d.mts.map +1 -1
- package/dist/agent/tools/registry.mjs +4 -4
- package/dist/agent/tools/registry.mjs.map +1 -1
- package/dist/agent/tools/shell.d.mts +1 -1
- package/dist/agent/tools/shell.mjs +4 -4
- package/dist/agent/tools/shell.mjs.map +1 -1
- package/dist/agent/tools/spawn.d.mts +1 -1
- package/dist/agent/tools/spawn.d.mts.map +1 -1
- package/dist/agent/tools/spawn.mjs +4 -4
- package/dist/agent/tools/spawn.mjs.map +1 -1
- package/dist/agent/tools/web.d.mts +2 -2
- package/dist/agent/tools/web.d.mts.map +1 -1
- package/dist/agent/tools/web.mjs +36 -36
- package/dist/agent/tools/web.mjs.map +1 -1
- package/dist/bus/events.mjs +1 -1
- package/dist/bus/events.mjs.map +1 -1
- package/dist/bus/queue.d.mts.map +1 -1
- package/dist/bus/queue.mjs.map +1 -1
- package/dist/channels/base.d.mts.map +1 -1
- package/dist/channels/base.mjs +2 -2
- package/dist/channels/base.mjs.map +1 -1
- package/dist/channels/line.d.mts +1 -0
- package/dist/channels/line.d.mts.map +1 -1
- package/dist/channels/line.mjs +65 -65
- package/dist/channels/line.mjs.map +1 -1
- package/dist/channels/line.test.mjs +26 -27
- package/dist/channels/line.test.mjs.map +1 -1
- package/dist/channels/manager.d.mts.map +1 -1
- package/dist/channels/manager.mjs +9 -9
- package/dist/channels/manager.mjs.map +1 -1
- package/dist/channels/telegram.mjs +34 -34
- package/dist/channels/telegram.mjs.map +1 -1
- package/dist/cli/index.mjs +36 -36
- package/dist/cli/index.mjs.map +1 -1
- package/dist/config/loader.d.mts.map +1 -1
- package/dist/config/loader.mjs +1 -1
- package/dist/config/loader.mjs.map +1 -1
- package/dist/config/schema.d.mts +381 -381
- package/dist/config/schema.d.mts.map +1 -1
- package/dist/config/schema.mjs +42 -42
- package/dist/config/schema.mjs.map +1 -1
- package/dist/gateway/server.d.mts.map +1 -1
- package/dist/gateway/server.mjs +48 -54
- package/dist/gateway/server.mjs.map +1 -1
- package/dist/heartbeat/service.d.mts.map +1 -1
- package/dist/heartbeat/service.mjs +8 -8
- package/dist/heartbeat/service.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/node_modules/{@jridgewell → .bun/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell}/sourcemap-codec/dist/sourcemap-codec.mjs +1 -1
- package/dist/node_modules/.bun/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_expect@2.1.9/node_modules/@vitest}/expect/dist/index.mjs +8 -8
- package/dist/node_modules/.bun/@vitest_expect@2.1.9/node_modules/@vitest/expect/dist/index.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_pretty-format@2.1.9/node_modules/@vitest}/pretty-format/dist/index.mjs +2 -2
- package/dist/node_modules/.bun/@vitest_pretty-format@2.1.9/node_modules/@vitest/pretty-format/dist/index.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_runner@2.1.9/node_modules/@vitest}/runner/dist/chunk-tasks.mjs +1 -1
- package/dist/node_modules/.bun/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/chunk-tasks.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_runner@2.1.9/node_modules/@vitest}/runner/dist/index.mjs +6 -6
- package/dist/node_modules/.bun/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/index.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_snapshot@2.1.9/node_modules/@vitest}/snapshot/dist/index.mjs +5 -5
- package/dist/node_modules/.bun/@vitest_snapshot@2.1.9/node_modules/@vitest/snapshot/dist/index.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_spy@2.1.9/node_modules/@vitest}/spy/dist/index.mjs +2 -2
- package/dist/node_modules/.bun/@vitest_spy@2.1.9/node_modules/@vitest/spy/dist/index.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/chunk-_commonjsHelpers.mjs +3 -3
- package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/diff.mjs +4 -4
- package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/diff.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/error.mjs +3 -3
- package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/error.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/helpers.mjs +1 -1
- package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/helpers.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/index.mjs +3 -3
- package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/index.mjs.map +1 -0
- package/dist/node_modules/{@vitest → .bun/@vitest_utils@2.1.9/node_modules/@vitest}/utils/dist/source-map.mjs +1 -1
- package/dist/node_modules/.bun/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/source-map.mjs.map +1 -0
- package/dist/node_modules/{chai → .bun/chai@5.3.3/node_modules/chai}/index.mjs +1 -1
- package/dist/node_modules/.bun/chai@5.3.3/node_modules/chai/index.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/arguments.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/arguments.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/array.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/array.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/bigint.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/bigint.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/class.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/class.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/date.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/date.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/error.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/error.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/function.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/function.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/helpers.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/helpers.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/html.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/html.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/index.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/index.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/map.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/map.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/number.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/number.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/object.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/object.mjs.map +1 -0
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/promise.mjs +6 -0
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/promise.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/regexp.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/regexp.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/set.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/set.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/string.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/string.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/symbol.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/symbol.mjs.map +1 -0
- package/dist/node_modules/{loupe → .bun/loupe@3.2.1/node_modules/loupe}/lib/typedarray.mjs +1 -1
- package/dist/node_modules/.bun/loupe@3.2.1/node_modules/loupe/lib/typedarray.mjs.map +1 -0
- package/dist/node_modules/{magic-string → .bun/magic-string@0.30.21/node_modules/magic-string}/dist/magic-string.es.mjs +2 -2
- package/dist/node_modules/.bun/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.mjs.map +1 -0
- package/dist/node_modules/{@vitest/snapshot → .bun/pathe@1.1.2}/node_modules/pathe/dist/shared/pathe.ff20891b.mjs +1 -1
- package/dist/node_modules/.bun/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.mjs.map +1 -0
- package/dist/node_modules/{tinyrainbow → .bun/tinyrainbow@1.2.0/node_modules/tinyrainbow}/dist/chunk-BVHSVHOK.mjs +1 -1
- package/dist/node_modules/.bun/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.mjs.map +1 -0
- package/dist/node_modules/{tinyrainbow → .bun/tinyrainbow@1.2.0/node_modules/tinyrainbow}/dist/node.mjs +1 -1
- package/dist/node_modules/.bun/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/node.mjs.map +1 -0
- package/dist/node_modules/{tinyspy → .bun/tinyspy@3.0.2/node_modules/tinyspy}/dist/index.mjs +1 -1
- package/dist/node_modules/.bun/tinyspy@3.0.2/node_modules/tinyspy/dist/index.mjs.map +1 -0
- package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/_commonjsHelpers.BFTU3MAI.mjs +1 -1
- package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.mjs.map +1 -0
- package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/date.W2xKR2qe.mjs +1 -1
- package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/date.W2xKR2qe.mjs.map +1 -0
- package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/utils.C8RiOc4B.mjs +2 -2
- package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/utils.C8RiOc4B.mjs.map +1 -0
- package/dist/node_modules/{vitest → .bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest}/dist/chunks/vi.DgezovHB.mjs +11 -11
- package/dist/node_modules/.bun/vitest@2.1.9_7700f9e9ace41f23/node_modules/vitest/dist/chunks/vi.DgezovHB.mjs.map +1 -0
- package/dist/providers/base.d.mts +2 -2
- package/dist/providers/base.d.mts.map +1 -1
- package/dist/providers/openai-provider.d.mts.map +1 -1
- package/dist/providers/openai-provider.mjs +10 -9
- package/dist/providers/openai-provider.mjs.map +1 -1
- package/dist/providers/registry.d.mts +1 -1
- package/dist/providers/registry.d.mts.map +1 -1
- package/dist/providers/registry.mjs +99 -99
- package/dist/providers/registry.mjs.map +1 -1
- package/dist/session/manager.d.mts +2 -2
- package/dist/session/manager.d.mts.map +1 -1
- package/dist/session/manager.mjs +18 -19
- package/dist/session/manager.mjs.map +1 -1
- package/dist/utils/helpers.d.mts.map +1 -1
- package/dist/utils/helpers.mjs.map +1 -1
- package/package.json +11 -11
- package/skills/cron/SKILL.md +12 -8
- package/skills/daily-summary/SKILL.md +5 -1
- package/skills/english/SKILL.md +72 -14
- package/skills/expense/SKILL.md +15 -11
- package/skills/fortune/SKILL.md +25 -21
- package/skills/habit/SKILL.md +7 -6
- package/skills/hydration/SKILL.md +8 -5
- package/skills/memory/SKILL.md +1 -0
- package/skills/mood/SKILL.md +13 -9
- package/skills/skill-creator/SKILL.md +22 -0
- package/skills/summarize/SKILL.md +1 -0
- package/skills/weather/SKILL.md +11 -9
- package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map +0 -1
- package/dist/node_modules/@vitest/expect/dist/index.mjs.map +0 -1
- package/dist/node_modules/@vitest/pretty-format/dist/index.mjs.map +0 -1
- package/dist/node_modules/@vitest/runner/dist/chunk-tasks.mjs.map +0 -1
- package/dist/node_modules/@vitest/runner/dist/index.mjs.map +0 -1
- package/dist/node_modules/@vitest/snapshot/dist/index.mjs.map +0 -1
- package/dist/node_modules/@vitest/snapshot/node_modules/pathe/dist/shared/pathe.ff20891b.mjs.map +0 -1
- package/dist/node_modules/@vitest/spy/dist/index.mjs.map +0 -1
- package/dist/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.mjs.map +0 -1
- package/dist/node_modules/@vitest/utils/dist/diff.mjs.map +0 -1
- package/dist/node_modules/@vitest/utils/dist/error.mjs.map +0 -1
- package/dist/node_modules/@vitest/utils/dist/helpers.mjs.map +0 -1
- package/dist/node_modules/@vitest/utils/dist/index.mjs.map +0 -1
- package/dist/node_modules/@vitest/utils/dist/source-map.mjs.map +0 -1
- package/dist/node_modules/chai/index.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/arguments.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/array.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/bigint.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/class.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/date.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/error.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/function.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/helpers.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/html.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/index.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/map.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/number.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/object.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/promise.mjs +0 -6
- package/dist/node_modules/loupe/lib/promise.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/regexp.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/set.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/string.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/symbol.mjs.map +0 -1
- package/dist/node_modules/loupe/lib/typedarray.mjs.map +0 -1
- package/dist/node_modules/magic-string/dist/magic-string.es.mjs.map +0 -1
- package/dist/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.mjs.map +0 -1
- package/dist/node_modules/tinyrainbow/dist/node.mjs.map +0 -1
- package/dist/node_modules/tinyspy/dist/index.mjs.map +0 -1
- package/dist/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.mjs.map +0 -1
- package/dist/node_modules/vitest/dist/chunks/date.W2xKR2qe.mjs.map +0 -1
- package/dist/node_modules/vitest/dist/chunks/utils.C8RiOc4B.mjs.map +0 -1
- package/dist/node_modules/vitest/dist/chunks/vi.DgezovHB.mjs.map +0 -1
- /package/dist/node_modules/{@vitest → .bun/@vitest_runner@2.1.9/node_modules/@vitest}/runner/dist/utils.mjs +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.mts","names":[],"sources":["../../src/config/schema.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"schema.d.mts","names":[],"sources":["../../src/config/schema.ts"],"mappings":"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"}
|
package/dist/config/schema.mjs
CHANGED
|
@@ -4,68 +4,68 @@ import { z } from "zod";
|
|
|
4
4
|
|
|
5
5
|
//#region src/config/schema.ts
|
|
6
6
|
const TelegramConfigSchema = z.object({
|
|
7
|
-
enabled: z.boolean().default(false),
|
|
8
|
-
token: z.string().default(""),
|
|
9
7
|
allowFrom: z.array(z.string()).default([]),
|
|
10
|
-
|
|
8
|
+
enabled: z.boolean().default(false),
|
|
9
|
+
proxy: z.string().nullish(),
|
|
10
|
+
token: z.string().default("")
|
|
11
11
|
});
|
|
12
12
|
const LineConfigSchema = z.object({
|
|
13
|
-
|
|
14
|
-
channelSecret: z.string().default(""),
|
|
13
|
+
allowFrom: z.array(z.string()).default([]),
|
|
15
14
|
channelAccessToken: z.string().default(""),
|
|
16
|
-
|
|
15
|
+
channelSecret: z.string().default(""),
|
|
16
|
+
enabled: z.boolean().default(false)
|
|
17
17
|
});
|
|
18
18
|
const ChannelsConfigSchema = z.object({
|
|
19
|
-
telegram: TelegramConfigSchema.default({
|
|
20
|
-
enabled: false,
|
|
21
|
-
token: "",
|
|
22
|
-
allowFrom: []
|
|
23
|
-
}),
|
|
24
19
|
line: LineConfigSchema.default({
|
|
25
20
|
enabled: false,
|
|
26
21
|
channelSecret: "",
|
|
27
22
|
channelAccessToken: "",
|
|
28
23
|
allowFrom: []
|
|
24
|
+
}),
|
|
25
|
+
telegram: TelegramConfigSchema.default({
|
|
26
|
+
enabled: false,
|
|
27
|
+
token: "",
|
|
28
|
+
allowFrom: []
|
|
29
29
|
})
|
|
30
30
|
});
|
|
31
31
|
const AgentDefaultsSchema = z.object({
|
|
32
|
-
workspace: z.string().default("~/.nanobot/workspace"),
|
|
33
|
-
model: z.string().default("anthropic/claude-sonnet-4-20250514"),
|
|
34
32
|
consolidationModel: z.string().optional(),
|
|
35
33
|
maxTokens: z.number().default(8192),
|
|
36
|
-
temperature: z.number().default(.7),
|
|
37
34
|
maxToolIterations: z.number().default(20),
|
|
38
|
-
memoryWindow: z.number().default(50)
|
|
35
|
+
memoryWindow: z.number().default(50),
|
|
36
|
+
model: z.string().default("anthropic/claude-sonnet-4-20250514"),
|
|
37
|
+
temperature: z.number().default(.7),
|
|
38
|
+
workspace: z.string().default("~/.nanobot/workspace")
|
|
39
39
|
});
|
|
40
40
|
function resolveConsolidationModel(defaults) {
|
|
41
41
|
return defaults.consolidationModel ?? defaults.model;
|
|
42
42
|
}
|
|
43
43
|
const AgentsConfigSchema = z.object({ defaults: AgentDefaultsSchema.default({
|
|
44
|
-
workspace: "~/.nanobot/workspace",
|
|
45
|
-
model: "anthropic/claude-sonnet-4-20250514",
|
|
46
44
|
maxTokens: 8192,
|
|
47
|
-
temperature: .7,
|
|
48
45
|
maxToolIterations: 20,
|
|
49
|
-
memoryWindow: 50
|
|
46
|
+
memoryWindow: 50,
|
|
47
|
+
model: "anthropic/claude-sonnet-4-20250514",
|
|
48
|
+
temperature: .7,
|
|
49
|
+
workspace: "~/.nanobot/workspace"
|
|
50
50
|
}) });
|
|
51
51
|
const ProviderConfigSchema = z.object({
|
|
52
|
-
apiKey: z.string().default(""),
|
|
53
52
|
apiBase: z.string().nullish(),
|
|
53
|
+
apiKey: z.string().default(""),
|
|
54
54
|
extraHeaders: z.record(z.string()).nullish()
|
|
55
55
|
});
|
|
56
56
|
const defaultProvider = { apiKey: "" };
|
|
57
57
|
const ProvidersConfigSchema = z.object({
|
|
58
|
+
aihubmix: ProviderConfigSchema.default(defaultProvider),
|
|
58
59
|
anthropic: ProviderConfigSchema.default(defaultProvider),
|
|
59
|
-
|
|
60
|
-
openrouter: ProviderConfigSchema.default(defaultProvider),
|
|
60
|
+
dashscope: ProviderConfigSchema.default(defaultProvider),
|
|
61
61
|
deepseek: ProviderConfigSchema.default(defaultProvider),
|
|
62
|
-
groq: ProviderConfigSchema.default(defaultProvider),
|
|
63
62
|
gemini: ProviderConfigSchema.default(defaultProvider),
|
|
64
|
-
|
|
65
|
-
dashscope: ProviderConfigSchema.default(defaultProvider),
|
|
63
|
+
groq: ProviderConfigSchema.default(defaultProvider),
|
|
66
64
|
moonshot: ProviderConfigSchema.default(defaultProvider),
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
openai: ProviderConfigSchema.default(defaultProvider),
|
|
66
|
+
openrouter: ProviderConfigSchema.default(defaultProvider),
|
|
67
|
+
vllm: ProviderConfigSchema.default(defaultProvider),
|
|
68
|
+
zhipu: ProviderConfigSchema.default(defaultProvider)
|
|
69
69
|
});
|
|
70
70
|
const GatewayConfigSchema = z.object({
|
|
71
71
|
host: z.string().default("127.0.0.1"),
|
|
@@ -81,20 +81,20 @@ const WebToolsConfigSchema = z.object({ search: WebSearchConfigSchema.default({
|
|
|
81
81
|
}) });
|
|
82
82
|
const ExecToolConfigSchema = z.object({ timeout: z.number().default(60) });
|
|
83
83
|
const CustomToolConfigSchema = z.object({
|
|
84
|
-
module: z.string(),
|
|
85
84
|
export: z.string().optional(),
|
|
85
|
+
module: z.string(),
|
|
86
86
|
options: z.record(z.unknown()).optional()
|
|
87
87
|
});
|
|
88
88
|
const ToolsConfigSchema = z.object({
|
|
89
|
+
custom: z.array(CustomToolConfigSchema).optional(),
|
|
90
|
+
disabled: z.array(z.string()).optional(),
|
|
91
|
+
enabled: z.array(z.string()).optional(),
|
|
92
|
+
exec: ExecToolConfigSchema.default({ timeout: 60 }),
|
|
93
|
+
restrictToWorkspace: z.boolean().default(false),
|
|
89
94
|
web: WebToolsConfigSchema.default({ search: {
|
|
90
95
|
apiKey: "",
|
|
91
96
|
maxResults: 5
|
|
92
|
-
} })
|
|
93
|
-
exec: ExecToolConfigSchema.default({ timeout: 60 }),
|
|
94
|
-
restrictToWorkspace: z.boolean().default(false),
|
|
95
|
-
enabled: z.array(z.string()).optional(),
|
|
96
|
-
disabled: z.array(z.string()).optional(),
|
|
97
|
-
custom: z.array(CustomToolConfigSchema).optional()
|
|
97
|
+
} })
|
|
98
98
|
});
|
|
99
99
|
const ConfigSchema = z.object({
|
|
100
100
|
agents: AgentsConfigSchema.default({ defaults: {
|
|
@@ -118,6 +118,10 @@ const ConfigSchema = z.object({
|
|
|
118
118
|
allowFrom: []
|
|
119
119
|
}
|
|
120
120
|
}),
|
|
121
|
+
gateway: GatewayConfigSchema.default({
|
|
122
|
+
host: "127.0.0.1",
|
|
123
|
+
port: 18790
|
|
124
|
+
}),
|
|
121
125
|
providers: ProvidersConfigSchema.default({
|
|
122
126
|
anthropic: defaultProvider,
|
|
123
127
|
openai: defaultProvider,
|
|
@@ -131,10 +135,6 @@ const ConfigSchema = z.object({
|
|
|
131
135
|
aihubmix: defaultProvider,
|
|
132
136
|
vllm: defaultProvider
|
|
133
137
|
}),
|
|
134
|
-
gateway: GatewayConfigSchema.default({
|
|
135
|
-
host: "127.0.0.1",
|
|
136
|
-
port: 18790
|
|
137
|
-
}),
|
|
138
138
|
tools: ToolsConfigSchema.default({
|
|
139
139
|
web: { search: {
|
|
140
140
|
apiKey: "",
|
|
@@ -164,16 +164,16 @@ function matchProvider(config, model) {
|
|
|
164
164
|
const p = config.providers[spec.name];
|
|
165
165
|
if (p && p.apiKey && spec.keywords.some((kw) => modelLower.includes(kw))) return {
|
|
166
166
|
provider: p,
|
|
167
|
-
|
|
168
|
-
spec
|
|
167
|
+
spec,
|
|
168
|
+
specName: spec.name
|
|
169
169
|
};
|
|
170
170
|
}
|
|
171
171
|
for (const spec of PROVIDERS) {
|
|
172
172
|
const p = config.providers[spec.name];
|
|
173
173
|
if (p && p.apiKey) return {
|
|
174
174
|
provider: p,
|
|
175
|
-
|
|
176
|
-
spec
|
|
175
|
+
spec,
|
|
176
|
+
specName: spec.name
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.mjs","names":[],"sources":["../../src/config/schema.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { homedir } from \"node:os\";\nimport { PROVIDERS, findByModel, findGateway, findByName } from \"../providers/registry.js\";\nimport type { ProviderSpec } from \"../providers/registry.js\";\n\nexport const TelegramConfigSchema = z.object({\n enabled: z.boolean().default(false),\n token: z.string().default(\"\"),\n allowFrom: z.array(z.string()).default([]),\n proxy: z.string().nullish(),\n});\nexport type TelegramConfig = z.infer<typeof TelegramConfigSchema>;\n\nexport const LineConfigSchema = z.object({\n enabled: z.boolean().default(false),\n channelSecret: z.string().default(\"\"),\n channelAccessToken: z.string().default(\"\"),\n allowFrom: z.array(z.string()).default([]),\n});\nexport type LineConfig = z.infer<typeof LineConfigSchema>;\n\nexport const ChannelsConfigSchema = z.object({\n telegram: TelegramConfigSchema.default({\n enabled: false,\n token: \"\",\n allowFrom: [],\n }),\n line: LineConfigSchema.default({\n enabled: false,\n channelSecret: \"\",\n channelAccessToken: \"\",\n allowFrom: [],\n }),\n});\nexport type ChannelsConfig = z.infer<typeof ChannelsConfigSchema>;\n\nexport const AgentDefaultsSchema = z.object({\n workspace: z.string().default(\"~/.nanobot/workspace\"),\n model: z.string().default(\"anthropic/claude-sonnet-4-20250514\"),\n consolidationModel: z.string().optional(),\n maxTokens: z.number().default(8192),\n temperature: z.number().default(0.7),\n maxToolIterations: z.number().default(20),\n memoryWindow: z.number().default(50),\n});\nexport type AgentDefaults = z.infer<typeof AgentDefaultsSchema>;\n\nexport function resolveConsolidationModel(defaults: AgentDefaults): string {\n return defaults.consolidationModel ?? defaults.model;\n}\n\nexport const AgentsConfigSchema = z.object({\n defaults: AgentDefaultsSchema.default({\n workspace: \"~/.nanobot/workspace\",\n model: \"anthropic/claude-sonnet-4-20250514\",\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n memoryWindow: 50,\n }),\n});\nexport type AgentsConfig = z.infer<typeof AgentsConfigSchema>;\n\nexport const ProviderConfigSchema = z.object({\n apiKey: z.string().default(\"\"),\n apiBase: z.string().nullish(),\n extraHeaders: z.record(z.string()).nullish(),\n});\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\n\nconst defaultProvider = { apiKey: \"\" } as const;\n\nexport const ProvidersConfigSchema = z.object({\n anthropic: ProviderConfigSchema.default(defaultProvider),\n openai: ProviderConfigSchema.default(defaultProvider),\n openrouter: ProviderConfigSchema.default(defaultProvider),\n deepseek: ProviderConfigSchema.default(defaultProvider),\n groq: ProviderConfigSchema.default(defaultProvider),\n gemini: ProviderConfigSchema.default(defaultProvider),\n zhipu: ProviderConfigSchema.default(defaultProvider),\n dashscope: ProviderConfigSchema.default(defaultProvider),\n moonshot: ProviderConfigSchema.default(defaultProvider),\n aihubmix: ProviderConfigSchema.default(defaultProvider),\n vllm: ProviderConfigSchema.default(defaultProvider),\n});\nexport type ProvidersConfig = z.infer<typeof ProvidersConfigSchema>;\n\nexport const GatewayConfigSchema = z.object({\n host: z.string().default(\"127.0.0.1\"),\n port: z.number().default(18790),\n});\nexport type GatewayConfig = z.infer<typeof GatewayConfigSchema>;\n\nexport const WebSearchConfigSchema = z.object({\n apiKey: z.string().default(\"\"),\n maxResults: z.number().default(5),\n});\n\nexport const WebToolsConfigSchema = z.object({\n search: WebSearchConfigSchema.default({ apiKey: \"\", maxResults: 5 }),\n});\n\nexport const ExecToolConfigSchema = z.object({\n timeout: z.number().default(60),\n});\nexport type ExecToolConfig = z.infer<typeof ExecToolConfigSchema>;\n\nexport const CustomToolConfigSchema = z.object({\n module: z.string(),\n export: z.string().optional(),\n options: z.record(z.unknown()).optional(),\n});\nexport type CustomToolConfig = z.infer<typeof CustomToolConfigSchema>;\n\nexport const ToolsConfigSchema = z.object({\n web: WebToolsConfigSchema.default({\n search: { apiKey: \"\", maxResults: 5 },\n }),\n exec: ExecToolConfigSchema.default({\n timeout: 60,\n }),\n restrictToWorkspace: z.boolean().default(false),\n enabled: z.array(z.string()).optional(),\n disabled: z.array(z.string()).optional(),\n custom: z.array(CustomToolConfigSchema).optional(),\n});\nexport type ToolsConfig = z.infer<typeof ToolsConfigSchema>;\n\nexport const ConfigSchema = z.object({\n agents: AgentsConfigSchema.default({\n defaults: {\n workspace: \"~/.nanobot/workspace\",\n model: \"anthropic/claude-sonnet-4-20250514\",\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n memoryWindow: 50,\n },\n }),\n channels: ChannelsConfigSchema.default({\n telegram: { enabled: false, token: \"\", allowFrom: [] },\n line: { enabled: false, channelSecret: \"\", channelAccessToken: \"\", allowFrom: [] },\n }),\n providers: ProvidersConfigSchema.default({\n anthropic: defaultProvider,\n openai: defaultProvider,\n openrouter: defaultProvider,\n deepseek: defaultProvider,\n groq: defaultProvider,\n gemini: defaultProvider,\n zhipu: defaultProvider,\n dashscope: defaultProvider,\n moonshot: defaultProvider,\n aihubmix: defaultProvider,\n vllm: defaultProvider,\n }),\n gateway: GatewayConfigSchema.default({ host: \"127.0.0.1\", port: 18790 }),\n tools: ToolsConfigSchema.default({\n web: { search: { apiKey: \"\", maxResults: 5 } },\n exec: { timeout: 60 },\n restrictToWorkspace: false,\n }),\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n/** Get expanded workspace path. */\nexport function getConfigWorkspacePath(config: Config): string {\n const ws = config.agents.defaults.workspace;\n if (ws.startsWith(\"~\")) {\n return ws.replace(/^~/, homedir());\n }\n return ws;\n}\n\n/**\n * Match provider config by model name or first available key.\n * Returns { providerConfig, specName, spec } or nulls.\n *\n * Priority:\n * 1. Keyword match on model name (follows PROVIDERS registry order)\n * 2. Fallback: first provider with a configured api_key (gateways first)\n */\nexport function matchProvider(\n config: Config,\n model?: string,\n): { provider: ProviderConfig; specName: string; spec: ProviderSpec } | null {\n const modelStr = model ?? config.agents.defaults.model;\n const modelLower = modelStr.toLowerCase();\n\n // 1. Keyword match\n for (const spec of PROVIDERS) {\n const p = (config.providers as Record<string, ProviderConfig>)[spec.name];\n if (p && p.apiKey && spec.keywords.some((kw) => modelLower.includes(kw))) {\n return { provider: p, specName: spec.name, spec };\n }\n }\n\n // 2. Fallback: first with a key (registry order → gateways first)\n for (const spec of PROVIDERS) {\n const p = (config.providers as Record<string, ProviderConfig>)[spec.name];\n if (p && p.apiKey) {\n return { provider: p, specName: spec.name, spec };\n }\n }\n\n return null;\n}\n\n/** Get API key for the given model. Falls back to first available key. */\nexport function getApiKey(config: Config, model?: string): string | null {\n return matchProvider(config, model)?.provider.apiKey ?? null;\n}\n\n/** Get API base URL for the given model. Applies default URLs for known providers. */\nexport function getApiBase(config: Config, model?: string): string | null {\n const match = matchProvider(config, model);\n if (!match) return null;\n\n // User-configured api_base wins\n if (match.provider.apiBase) return match.provider.apiBase;\n\n // Default api_base from the registry\n if (match.spec.defaultApiBase) return match.spec.defaultApiBase;\n\n return null;\n}\n\n/** Get extra headers for the matched provider. */\nexport function getExtraHeaders(\n config: Config,\n model?: string,\n): Record<string, string> | null {\n const match = matchProvider(config, model);\n return match?.provider.extraHeaders ?? null;\n}\n\n/** Get the provider name for the matched provider (e.g. \"deepseek\", \"openrouter\"). */\nexport function getProviderName(config: Config, model?: string): string | null {\n return matchProvider(config, model)?.specName ?? null;\n}\n"],"mappings":";;;;;AAKA,MAAa,uBAAuB,EAAE,OAAO;CAC3C,SAAS,EAAE,SAAS,CAAC,QAAQ,MAAM;CACnC,OAAO,EAAE,QAAQ,CAAC,QAAQ,GAAG;CAC7B,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;CAC1C,OAAO,EAAE,QAAQ,CAAC,SAAS;CAC5B,CAAC;AAGF,MAAa,mBAAmB,EAAE,OAAO;CACvC,SAAS,EAAE,SAAS,CAAC,QAAQ,MAAM;CACnC,eAAe,EAAE,QAAQ,CAAC,QAAQ,GAAG;CACrC,oBAAoB,EAAE,QAAQ,CAAC,QAAQ,GAAG;CAC1C,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;CAC3C,CAAC;AAGF,MAAa,uBAAuB,EAAE,OAAO;CAC3C,UAAU,qBAAqB,QAAQ;EACrC,SAAS;EACT,OAAO;EACP,WAAW,EAAE;EACd,CAAC;CACF,MAAM,iBAAiB,QAAQ;EAC7B,SAAS;EACT,eAAe;EACf,oBAAoB;EACpB,WAAW,EAAE;EACd,CAAC;CACH,CAAC;AAGF,MAAa,sBAAsB,EAAE,OAAO;CAC1C,WAAW,EAAE,QAAQ,CAAC,QAAQ,uBAAuB;CACrD,OAAO,EAAE,QAAQ,CAAC,QAAQ,qCAAqC;CAC/D,oBAAoB,EAAE,QAAQ,CAAC,UAAU;CACzC,WAAW,EAAE,QAAQ,CAAC,QAAQ,KAAK;CACnC,aAAa,EAAE,QAAQ,CAAC,QAAQ,GAAI;CACpC,mBAAmB,EAAE,QAAQ,CAAC,QAAQ,GAAG;CACzC,cAAc,EAAE,QAAQ,CAAC,QAAQ,GAAG;CACrC,CAAC;AAGF,SAAgB,0BAA0B,UAAiC;AACzE,QAAO,SAAS,sBAAsB,SAAS;;AAGjD,MAAa,qBAAqB,EAAE,OAAO,EACzC,UAAU,oBAAoB,QAAQ;CACpC,WAAW;CACX,OAAO;CACP,WAAW;CACX,aAAa;CACb,mBAAmB;CACnB,cAAc;CACf,CAAC,EACH,CAAC;AAGF,MAAa,uBAAuB,EAAE,OAAO;CAC3C,QAAQ,EAAE,QAAQ,CAAC,QAAQ,GAAG;CAC9B,SAAS,EAAE,QAAQ,CAAC,SAAS;CAC7B,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,SAAS;CAC7C,CAAC;AAGF,MAAM,kBAAkB,EAAE,QAAQ,IAAI;AAEtC,MAAa,wBAAwB,EAAE,OAAO;CAC5C,WAAW,qBAAqB,QAAQ,gBAAgB;CACxD,QAAQ,qBAAqB,QAAQ,gBAAgB;CACrD,YAAY,qBAAqB,QAAQ,gBAAgB;CACzD,UAAU,qBAAqB,QAAQ,gBAAgB;CACvD,MAAM,qBAAqB,QAAQ,gBAAgB;CACnD,QAAQ,qBAAqB,QAAQ,gBAAgB;CACrD,OAAO,qBAAqB,QAAQ,gBAAgB;CACpD,WAAW,qBAAqB,QAAQ,gBAAgB;CACxD,UAAU,qBAAqB,QAAQ,gBAAgB;CACvD,UAAU,qBAAqB,QAAQ,gBAAgB;CACvD,MAAM,qBAAqB,QAAQ,gBAAgB;CACpD,CAAC;AAGF,MAAa,sBAAsB,EAAE,OAAO;CAC1C,MAAM,EAAE,QAAQ,CAAC,QAAQ,YAAY;CACrC,MAAM,EAAE,QAAQ,CAAC,QAAQ,MAAM;CAChC,CAAC;AAGF,MAAa,wBAAwB,EAAE,OAAO;CAC5C,QAAQ,EAAE,QAAQ,CAAC,QAAQ,GAAG;CAC9B,YAAY,EAAE,QAAQ,CAAC,QAAQ,EAAE;CAClC,CAAC;AAEF,MAAa,uBAAuB,EAAE,OAAO,EAC3C,QAAQ,sBAAsB,QAAQ;CAAE,QAAQ;CAAI,YAAY;CAAG,CAAC,EACrE,CAAC;AAEF,MAAa,uBAAuB,EAAE,OAAO,EAC3C,SAAS,EAAE,QAAQ,CAAC,QAAQ,GAAG,EAChC,CAAC;AAGF,MAAa,yBAAyB,EAAE,OAAO;CAC7C,QAAQ,EAAE,QAAQ;CAClB,QAAQ,EAAE,QAAQ,CAAC,UAAU;CAC7B,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,UAAU;CAC1C,CAAC;AAGF,MAAa,oBAAoB,EAAE,OAAO;CACxC,KAAK,qBAAqB,QAAQ,EAChC,QAAQ;EAAE,QAAQ;EAAI,YAAY;EAAG,EACtC,CAAC;CACF,MAAM,qBAAqB,QAAQ,EACjC,SAAS,IACV,CAAC;CACF,qBAAqB,EAAE,SAAS,CAAC,QAAQ,MAAM;CAC/C,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU;CACvC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU;CACxC,QAAQ,EAAE,MAAM,uBAAuB,CAAC,UAAU;CACnD,CAAC;AAGF,MAAa,eAAe,EAAE,OAAO;CACnC,QAAQ,mBAAmB,QAAQ,EACjC,UAAU;EACR,WAAW;EACX,OAAO;EACP,WAAW;EACX,aAAa;EACb,mBAAmB;EACnB,cAAc;EACf,EACF,CAAC;CACF,UAAU,qBAAqB,QAAQ;EACrC,UAAU;GAAE,SAAS;GAAO,OAAO;GAAI,WAAW,EAAE;GAAE;EACtD,MAAM;GAAE,SAAS;GAAO,eAAe;GAAI,oBAAoB;GAAI,WAAW,EAAE;GAAE;EACnF,CAAC;CACF,WAAW,sBAAsB,QAAQ;EACvC,WAAW;EACX,QAAQ;EACR,YAAY;EACZ,UAAU;EACV,MAAM;EACN,QAAQ;EACR,OAAO;EACP,WAAW;EACX,UAAU;EACV,UAAU;EACV,MAAM;EACP,CAAC;CACF,SAAS,oBAAoB,QAAQ;EAAE,MAAM;EAAa,MAAM;EAAO,CAAC;CACxE,OAAO,kBAAkB,QAAQ;EAC/B,KAAK,EAAE,QAAQ;GAAE,QAAQ;GAAI,YAAY;GAAG,EAAE;EAC9C,MAAM,EAAE,SAAS,IAAI;EACrB,qBAAqB;EACtB,CAAC;CACH,CAAC;;AAIF,SAAgB,uBAAuB,QAAwB;CAC7D,MAAM,KAAK,OAAO,OAAO,SAAS;AAClC,KAAI,GAAG,WAAW,IAAI,CACpB,QAAO,GAAG,QAAQ,MAAM,SAAS,CAAC;AAEpC,QAAO;;;;;;;;;;AAWT,SAAgB,cACd,QACA,OAC2E;CAE3E,MAAM,cADW,SAAS,OAAO,OAAO,SAAS,OACrB,aAAa;AAGzC,MAAK,MAAM,QAAQ,WAAW;EAC5B,MAAM,IAAK,OAAO,UAA6C,KAAK;AACpE,MAAI,KAAK,EAAE,UAAU,KAAK,SAAS,MAAM,OAAO,WAAW,SAAS,GAAG,CAAC,CACtE,QAAO;GAAE,UAAU;GAAG,UAAU,KAAK;GAAM;GAAM;;AAKrD,MAAK,MAAM,QAAQ,WAAW;EAC5B,MAAM,IAAK,OAAO,UAA6C,KAAK;AACpE,MAAI,KAAK,EAAE,OACT,QAAO;GAAE,UAAU;GAAG,UAAU,KAAK;GAAM;GAAM;;AAIrD,QAAO;;;AAIT,SAAgB,UAAU,QAAgB,OAA+B;AACvE,QAAO,cAAc,QAAQ,MAAM,EAAE,SAAS,UAAU;;;AAI1D,SAAgB,WAAW,QAAgB,OAA+B;CACxE,MAAM,QAAQ,cAAc,QAAQ,MAAM;AAC1C,KAAI,CAAC,MAAO,QAAO;AAGnB,KAAI,MAAM,SAAS,QAAS,QAAO,MAAM,SAAS;AAGlD,KAAI,MAAM,KAAK,eAAgB,QAAO,MAAM,KAAK;AAEjD,QAAO;;;AAIT,SAAgB,gBACd,QACA,OAC+B;AAE/B,QADc,cAAc,QAAQ,MAAM,EAC5B,SAAS,gBAAgB;;;AAIzC,SAAgB,gBAAgB,QAAgB,OAA+B;AAC7E,QAAO,cAAc,QAAQ,MAAM,EAAE,YAAY"}
|
|
1
|
+
{"version":3,"file":"schema.mjs","names":[],"sources":["../../src/config/schema.ts"],"sourcesContent":["import { homedir } from \"node:os\";\nimport { z } from \"zod\";\n\nimport type { ProviderSpec } from \"../providers/registry.js\";\n\nimport {\n PROVIDERS,\n findByModel,\n findGateway,\n findByName,\n} from \"../providers/registry.js\";\n\nexport const TelegramConfigSchema = z.object({\n allowFrom: z.array(z.string()).default([]),\n enabled: z.boolean().default(false),\n proxy: z.string().nullish(),\n token: z.string().default(\"\"),\n});\nexport type TelegramConfig = z.infer<typeof TelegramConfigSchema>;\n\nexport const LineConfigSchema = z.object({\n allowFrom: z.array(z.string()).default([]),\n channelAccessToken: z.string().default(\"\"),\n channelSecret: z.string().default(\"\"),\n enabled: z.boolean().default(false),\n});\nexport type LineConfig = z.infer<typeof LineConfigSchema>;\n\nexport const ChannelsConfigSchema = z.object({\n line: LineConfigSchema.default({\n enabled: false,\n channelSecret: \"\",\n channelAccessToken: \"\",\n allowFrom: [],\n }),\n telegram: TelegramConfigSchema.default({\n enabled: false,\n token: \"\",\n allowFrom: [],\n }),\n});\nexport type ChannelsConfig = z.infer<typeof ChannelsConfigSchema>;\n\nexport const AgentDefaultsSchema = z.object({\n consolidationModel: z.string().optional(),\n maxTokens: z.number().default(8192),\n maxToolIterations: z.number().default(20),\n memoryWindow: z.number().default(50),\n model: z.string().default(\"anthropic/claude-sonnet-4-20250514\"),\n temperature: z.number().default(0.7),\n workspace: z.string().default(\"~/.nanobot/workspace\"),\n});\nexport type AgentDefaults = z.infer<typeof AgentDefaultsSchema>;\n\nexport function resolveConsolidationModel(defaults: AgentDefaults): string {\n return defaults.consolidationModel ?? defaults.model;\n}\n\nexport const AgentsConfigSchema = z.object({\n defaults: AgentDefaultsSchema.default({\n maxTokens: 8192,\n maxToolIterations: 20,\n memoryWindow: 50,\n model: \"anthropic/claude-sonnet-4-20250514\",\n temperature: 0.7,\n workspace: \"~/.nanobot/workspace\",\n }),\n});\nexport type AgentsConfig = z.infer<typeof AgentsConfigSchema>;\n\nexport const ProviderConfigSchema = z.object({\n apiBase: z.string().nullish(),\n apiKey: z.string().default(\"\"),\n extraHeaders: z.record(z.string()).nullish(),\n});\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\n\nconst defaultProvider = { apiKey: \"\" } as const;\n\nexport const ProvidersConfigSchema = z.object({\n aihubmix: ProviderConfigSchema.default(defaultProvider),\n anthropic: ProviderConfigSchema.default(defaultProvider),\n dashscope: ProviderConfigSchema.default(defaultProvider),\n deepseek: ProviderConfigSchema.default(defaultProvider),\n gemini: ProviderConfigSchema.default(defaultProvider),\n groq: ProviderConfigSchema.default(defaultProvider),\n moonshot: ProviderConfigSchema.default(defaultProvider),\n openai: ProviderConfigSchema.default(defaultProvider),\n openrouter: ProviderConfigSchema.default(defaultProvider),\n vllm: ProviderConfigSchema.default(defaultProvider),\n zhipu: ProviderConfigSchema.default(defaultProvider),\n});\nexport type ProvidersConfig = z.infer<typeof ProvidersConfigSchema>;\n\nexport const GatewayConfigSchema = z.object({\n host: z.string().default(\"127.0.0.1\"),\n port: z.number().default(18_790),\n});\nexport type GatewayConfig = z.infer<typeof GatewayConfigSchema>;\n\nexport const WebSearchConfigSchema = z.object({\n apiKey: z.string().default(\"\"),\n maxResults: z.number().default(5),\n});\n\nexport const WebToolsConfigSchema = z.object({\n search: WebSearchConfigSchema.default({ apiKey: \"\", maxResults: 5 }),\n});\n\nexport const ExecToolConfigSchema = z.object({\n timeout: z.number().default(60),\n});\nexport type ExecToolConfig = z.infer<typeof ExecToolConfigSchema>;\n\nexport const CustomToolConfigSchema = z.object({\n export: z.string().optional(),\n module: z.string(),\n options: z.record(z.unknown()).optional(),\n});\nexport type CustomToolConfig = z.infer<typeof CustomToolConfigSchema>;\n\nexport const ToolsConfigSchema = z.object({\n custom: z.array(CustomToolConfigSchema).optional(),\n disabled: z.array(z.string()).optional(),\n enabled: z.array(z.string()).optional(),\n exec: ExecToolConfigSchema.default({\n timeout: 60,\n }),\n restrictToWorkspace: z.boolean().default(false),\n web: WebToolsConfigSchema.default({\n search: { apiKey: \"\", maxResults: 5 },\n }),\n});\nexport type ToolsConfig = z.infer<typeof ToolsConfigSchema>;\n\nexport const ConfigSchema = z.object({\n agents: AgentsConfigSchema.default({\n defaults: {\n workspace: \"~/.nanobot/workspace\",\n model: \"anthropic/claude-sonnet-4-20250514\",\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n memoryWindow: 50,\n },\n }),\n channels: ChannelsConfigSchema.default({\n telegram: { enabled: false, token: \"\", allowFrom: [] },\n line: {\n enabled: false,\n channelSecret: \"\",\n channelAccessToken: \"\",\n allowFrom: [],\n },\n }),\n gateway: GatewayConfigSchema.default({ host: \"127.0.0.1\", port: 18_790 }),\n providers: ProvidersConfigSchema.default({\n anthropic: defaultProvider,\n openai: defaultProvider,\n openrouter: defaultProvider,\n deepseek: defaultProvider,\n groq: defaultProvider,\n gemini: defaultProvider,\n zhipu: defaultProvider,\n dashscope: defaultProvider,\n moonshot: defaultProvider,\n aihubmix: defaultProvider,\n vllm: defaultProvider,\n }),\n tools: ToolsConfigSchema.default({\n web: { search: { apiKey: \"\", maxResults: 5 } },\n exec: { timeout: 60 },\n restrictToWorkspace: false,\n }),\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n/** Get expanded workspace path. */\nexport function getConfigWorkspacePath(config: Config): string {\n const ws = config.agents.defaults.workspace;\n if (ws.startsWith(\"~\")) {\n return ws.replace(/^~/, homedir());\n }\n return ws;\n}\n\n/**\n * Match provider config by model name or first available key.\n * Returns { providerConfig, specName, spec } or nulls.\n *\n * Priority:\n * 1. Keyword match on model name (follows PROVIDERS registry order)\n * 2. Fallback: first provider with a configured api_key (gateways first)\n */\nexport function matchProvider(\n config: Config,\n model?: string\n): { provider: ProviderConfig; specName: string; spec: ProviderSpec } | null {\n const modelStr = model ?? config.agents.defaults.model;\n const modelLower = modelStr.toLowerCase();\n\n // 1. Keyword match\n for (const spec of PROVIDERS) {\n const p = (config.providers as Record<string, ProviderConfig>)[spec.name];\n if (p && p.apiKey && spec.keywords.some((kw) => modelLower.includes(kw))) {\n return { provider: p, spec, specName: spec.name };\n }\n }\n\n // 2. Fallback: first with a key (registry order → gateways first)\n for (const spec of PROVIDERS) {\n const p = (config.providers as Record<string, ProviderConfig>)[spec.name];\n if (p && p.apiKey) {\n return { provider: p, spec, specName: spec.name };\n }\n }\n\n return null;\n}\n\n/** Get API key for the given model. Falls back to first available key. */\nexport function getApiKey(config: Config, model?: string): string | null {\n return matchProvider(config, model)?.provider.apiKey ?? null;\n}\n\n/** Get API base URL for the given model. Applies default URLs for known providers. */\nexport function getApiBase(config: Config, model?: string): string | null {\n const match = matchProvider(config, model);\n if (!match) {\n return null;\n }\n\n // User-configured api_base wins\n if (match.provider.apiBase) {\n return match.provider.apiBase;\n }\n\n // Default api_base from the registry\n if (match.spec.defaultApiBase) {\n return match.spec.defaultApiBase;\n }\n\n return null;\n}\n\n/** Get extra headers for the matched provider. */\nexport function getExtraHeaders(\n config: Config,\n model?: string\n): Record<string, string> | null {\n const match = matchProvider(config, model);\n return match?.provider.extraHeaders ?? null;\n}\n\n/** Get the provider name for the matched provider (e.g. \"deepseek\", \"openrouter\"). */\nexport function getProviderName(config: Config, model?: string): string | null {\n return matchProvider(config, model)?.specName ?? null;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.mts","names":[],"sources":["../../src/gateway/server.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"server.d.mts","names":[],"sources":["../../src/gateway/server.ts"],"mappings":";;;;;;UAaiB,oBAAA;EACf,KAAA,EAAO,SAAA;EACP,GAAA,EAAK,UAAA;EACL,IAAA;EACA,QAAA,GAAW,cAAA;EACX,SAAA,GAAY,gBAAA;AAAA;AAAA,UAGG,aAAA;EAHH;EAKZ,MAAA,CAAO,IAAA,UAAc,OAAA,UAAiB,MAAA;EALV;EAO5B,cAAA,CAAe,IAAA,UAAc,IAAA;EAXtB;EAaP,gBAAA,CAAiB,IAAA,UAAc,MAAA;AAAA;AAAA,iBAGjB,mBAAA,CAAoB,IAAA,EAAM,oBAAA,GAAuB,aAAA"}
|
package/dist/gateway/server.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createOutboundMessage } from "../bus/events.mjs";
|
|
2
2
|
import { VERSION } from "../index.mjs";
|
|
3
3
|
import { getControlHtml } from "./ui.mjs";
|
|
4
|
-
import { Hono } from "hono";
|
|
5
4
|
import { serve } from "@hono/node-server";
|
|
5
|
+
import { Hono } from "hono";
|
|
6
6
|
import { streamSSE } from "hono/streaming";
|
|
7
7
|
|
|
8
8
|
//#region src/gateway/server.ts
|
|
@@ -17,29 +17,27 @@ function createGatewayServer(opts) {
|
|
|
17
17
|
}
|
|
18
18
|
function notify(role, content, chatId = "default") {
|
|
19
19
|
broadcast(JSON.stringify({
|
|
20
|
-
|
|
21
|
-
role,
|
|
20
|
+
chatId,
|
|
22
21
|
content,
|
|
23
|
-
|
|
22
|
+
role,
|
|
23
|
+
type: "message"
|
|
24
24
|
}));
|
|
25
25
|
}
|
|
26
26
|
function notifyToolCall(name, args) {
|
|
27
27
|
broadcast(JSON.stringify({
|
|
28
|
-
|
|
28
|
+
arguments: args,
|
|
29
29
|
name,
|
|
30
|
-
|
|
30
|
+
type: "tool_call"
|
|
31
31
|
}));
|
|
32
32
|
}
|
|
33
33
|
function notifyToolResult(name, output) {
|
|
34
34
|
broadcast(JSON.stringify({
|
|
35
|
-
type: "tool_result",
|
|
36
35
|
name,
|
|
37
|
-
output
|
|
36
|
+
output,
|
|
37
|
+
type: "tool_result"
|
|
38
38
|
}));
|
|
39
39
|
}
|
|
40
|
-
app.get("/", (c) =>
|
|
41
|
-
return c.html(getControlHtml());
|
|
42
|
-
});
|
|
40
|
+
app.get("/", (c) => c.html(getControlHtml()));
|
|
43
41
|
app.post("/api/chat", async (c) => {
|
|
44
42
|
const body = await c.req.json();
|
|
45
43
|
const message = body.message?.trim();
|
|
@@ -52,8 +50,8 @@ function createGatewayServer(opts) {
|
|
|
52
50
|
if (kind === "direct") {
|
|
53
51
|
const session = agent.sessions.getOrCreate(sessionKey);
|
|
54
52
|
session.addTurnMessages([{
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
content: message,
|
|
54
|
+
role: "assistant"
|
|
57
55
|
}]);
|
|
58
56
|
agent.sessions.save(session);
|
|
59
57
|
await bus.publishOutbound(createOutboundMessage({
|
|
@@ -70,8 +68,8 @@ function createGatewayServer(opts) {
|
|
|
70
68
|
content: response
|
|
71
69
|
}));
|
|
72
70
|
return c.json({ response });
|
|
73
|
-
} catch (
|
|
74
|
-
const errMsg =
|
|
71
|
+
} catch (error) {
|
|
72
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
75
73
|
console.error("Chat error:", errMsg);
|
|
76
74
|
return c.json({ error: errMsg }, 500);
|
|
77
75
|
}
|
|
@@ -83,57 +81,55 @@ function createGatewayServer(opts) {
|
|
|
83
81
|
for (const msg of history) if (msg.role === "user" || msg.role === "assistant") {
|
|
84
82
|
const content = typeof msg.content === "string" ? msg.content : msg.content ? msg.content.filter((p) => p.type === "text").map((p) => p.text).join("") : "";
|
|
85
83
|
const entry = {
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
content,
|
|
85
|
+
role: msg.role
|
|
88
86
|
};
|
|
89
87
|
if (msg.role === "assistant" && msg.tool_calls && msg.tool_calls.length > 0) entry.tool_calls = msg.tool_calls.map((tc) => ({
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
arguments: tc.function.arguments,
|
|
89
|
+
name: tc.function.name
|
|
92
90
|
}));
|
|
93
91
|
if (msg.role === "assistant" && !content && !entry.tool_calls) continue;
|
|
94
92
|
messages.push(entry);
|
|
95
93
|
} else if (msg.role === "tool") {
|
|
96
94
|
const content = typeof msg.content === "string" ? msg.content : "";
|
|
97
95
|
messages.push({
|
|
98
|
-
role: "tool",
|
|
99
96
|
content,
|
|
97
|
+
role: "tool",
|
|
100
98
|
tool_name: msg.name
|
|
101
99
|
});
|
|
102
100
|
}
|
|
103
101
|
return c.json({ messages });
|
|
104
102
|
});
|
|
105
|
-
app.get("/api/events", (c) => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
stream.writeSSE({ data: JSON.stringify({ type: "ping" }) }).catch(() => {
|
|
114
|
-
clearInterval(pingInterval);
|
|
115
|
-
});
|
|
116
|
-
}, 3e4);
|
|
117
|
-
try {
|
|
118
|
-
await new Promise((resolve) => {
|
|
119
|
-
stream.onAbort(() => resolve());
|
|
120
|
-
});
|
|
121
|
-
} finally {
|
|
103
|
+
app.get("/api/events", (c) => streamSSE(c, async (stream) => {
|
|
104
|
+
const send = (data) => {
|
|
105
|
+
stream.writeSSE({ data }).catch(() => {});
|
|
106
|
+
};
|
|
107
|
+
sseClients.add(send);
|
|
108
|
+
await stream.writeSSE({ data: JSON.stringify({ type: "connected" }) });
|
|
109
|
+
const pingInterval = setInterval(() => {
|
|
110
|
+
stream.writeSSE({ data: JSON.stringify({ type: "ping" }) }).catch(() => {
|
|
122
111
|
clearInterval(pingInterval);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
112
|
+
});
|
|
113
|
+
}, 3e4);
|
|
114
|
+
try {
|
|
115
|
+
await new Promise((resolve) => {
|
|
116
|
+
stream.onAbort(() => resolve());
|
|
117
|
+
});
|
|
118
|
+
} finally {
|
|
119
|
+
clearInterval(pingInterval);
|
|
120
|
+
sseClients.delete(send);
|
|
121
|
+
}
|
|
122
|
+
}));
|
|
127
123
|
app.post("/api/heartbeat", async (c) => {
|
|
128
124
|
if (!heartbeat) return c.json({ error: "Heartbeat not configured" }, 503);
|
|
129
125
|
try {
|
|
130
126
|
const response = await heartbeat.triggerNow();
|
|
131
127
|
return c.json({
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
response,
|
|
129
|
+
status: "ok"
|
|
134
130
|
});
|
|
135
|
-
} catch (
|
|
136
|
-
const errMsg =
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
137
133
|
console.error("Heartbeat error:", errMsg);
|
|
138
134
|
return c.json({ error: errMsg }, 500);
|
|
139
135
|
}
|
|
@@ -147,18 +143,16 @@ function createGatewayServer(opts) {
|
|
|
147
143
|
const signature = c.req.header("x-line-signature") ?? "";
|
|
148
144
|
if (!lineChannel.verifySignature(rawBody, signature)) return c.json({ error: "Invalid signature" }, 401);
|
|
149
145
|
const body = JSON.parse(rawBody);
|
|
150
|
-
lineChannel.handleWebhook(body).catch((
|
|
151
|
-
console.error("LINE webhook processing error:",
|
|
146
|
+
lineChannel.handleWebhook(body).catch((error) => {
|
|
147
|
+
console.error("LINE webhook processing error:", error);
|
|
152
148
|
});
|
|
153
149
|
return c.json({ status: "ok" });
|
|
154
150
|
});
|
|
155
|
-
app.get("/api/status", (c) => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
});
|
|
161
|
-
});
|
|
151
|
+
app.get("/api/status", (c) => c.json({
|
|
152
|
+
status: "ok",
|
|
153
|
+
version: VERSION,
|
|
154
|
+
uptime: process.uptime()
|
|
155
|
+
}));
|
|
162
156
|
serve({
|
|
163
157
|
fetch: app.fetch,
|
|
164
158
|
port
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.mjs","names":[],"sources":["../../src/gateway/server.ts"],"sourcesContent":["import { Hono } from \"hono\";\nimport { serve } from \"@hono/node-server\";\nimport { streamSSE } from \"hono/streaming\";\nimport { getControlHtml } from \"./ui.js\";\nimport type { AgentLoop } from \"../agent/loop.js\";\nimport type { ChannelManager } from \"../channels/manager.js\";\nimport { createOutboundMessage } from \"../bus/events.js\";\nimport type { MessageBus } from \"../bus/queue.js\";\nimport type { HeartbeatService } from \"../heartbeat/service.js\";\nimport { VERSION } from \"../index.js\";\n\nexport interface GatewayServerOptions {\n agent: AgentLoop;\n bus: MessageBus;\n port: number;\n channels?: ChannelManager;\n heartbeat?: HeartbeatService;\n}\n\nexport interface GatewayServer {\n /** Push a message to all connected SSE clients. */\n notify(role: string, content: string, chatId?: string): void;\n /** Push a tool call event to all connected SSE clients. */\n notifyToolCall(name: string, args: string): void;\n /** Push a tool result event to all connected SSE clients. */\n notifyToolResult(name: string, output: string): void;\n}\n\nexport function createGatewayServer(opts: GatewayServerOptions): GatewayServer {\n const { agent, bus, port, channels, heartbeat } = opts;\n const app = new Hono();\n\n // Track SSE clients for real-time push\n const sseClients = new Set<(data: string) => void>();\n\n function broadcast(payload: string): void {\n for (const send of sseClients) {\n try {\n send(payload);\n } catch {\n // client disconnected, will be cleaned up\n }\n }\n }\n\n function notify(role: string, content: string, chatId = \"default\"): void {\n broadcast(JSON.stringify({ type: \"message\", role, content, chatId }));\n }\n\n function notifyToolCall(name: string, args: string): void {\n broadcast(JSON.stringify({ type: \"tool_call\", name, arguments: args }));\n }\n\n function notifyToolResult(name: string, output: string): void {\n broadcast(JSON.stringify({ type: \"tool_result\", name, output }));\n }\n\n // Serve the control UI\n app.get(\"/\", (c) => {\n return c.html(getControlHtml());\n });\n\n // Chat endpoint — sends a message to the agent and returns the response\n // kind: \"direct\" = deliver message verbatim (no LLM), \"task\" = run through agent\n app.post(\"/api/chat\", async (c) => {\n const body = await c.req.json<{\n message?: string;\n kind?: \"direct\" | \"task\";\n session?: string;\n chatId?: string;\n deliver?: boolean;\n }>();\n const message = body.message?.trim();\n\n if (!message) {\n return c.json({ error: \"message is required\" }, 400);\n }\n\n const chatId = body.chatId ?? \"default\";\n const sessionKey = body.session ?? `line:${chatId}`;\n const kind = body.kind ?? \"task\";\n const deliver = body.deliver ?? false;\n\n try {\n if (kind === \"direct\") {\n // Deliver message verbatim — no LLM call, but record in session for context\n const session = agent.sessions.getOrCreate(sessionKey);\n session.addTurnMessages([{ role: \"assistant\", content: message }]);\n agent.sessions.save(session);\n\n await bus.publishOutbound(\n createOutboundMessage({\n channel: \"line\",\n chatId,\n content: message,\n }),\n );\n\n return c.json({ response: message });\n }\n\n // kind === \"task\" — run through the agent\n const response = await agent.processDirect(\n message,\n sessionKey,\n \"line\",\n chatId,\n );\n\n // Deliver response to LINE if requested (e.g. cron-triggered)\n if (deliver && response) {\n await bus.publishOutbound(\n createOutboundMessage({\n channel: \"line\",\n chatId,\n content: response,\n }),\n );\n }\n\n return c.json({ response });\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n console.error(\"Chat error:\", errMsg);\n return c.json({ error: errMsg }, 500);\n }\n });\n\n // History endpoint — returns conversation history for the UI\n app.get(\"/api/history\", (c) => {\n const sessionKey = c.req.query(\"session\") ?? \"web:default\";\n const session = agent.sessions.getOrCreate(sessionKey);\n const history = session.getHistory();\n\n // Return user, assistant, and tool messages for the UI\n const messages: Array<{\n role: string;\n content: string;\n tool_calls?: Array<{ name: string; arguments: string }>;\n tool_name?: string;\n }> = [];\n\n for (const msg of history) {\n if (msg.role === \"user\" || msg.role === \"assistant\") {\n const content =\n typeof msg.content === \"string\"\n ? msg.content\n : msg.content\n ? msg.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\")\n : \"\";\n\n const entry: (typeof messages)[number] = { role: msg.role, content };\n\n // Include tool calls if present on assistant messages\n if (msg.role === \"assistant\" && msg.tool_calls && msg.tool_calls.length > 0) {\n entry.tool_calls = msg.tool_calls.map((tc) => ({\n name: tc.function.name,\n arguments: tc.function.arguments,\n }));\n }\n\n // Skip empty assistant messages that only have tool_calls (no text)\n if (msg.role === \"assistant\" && !content && !entry.tool_calls) continue;\n\n messages.push(entry);\n } else if (msg.role === \"tool\") {\n const content =\n typeof msg.content === \"string\"\n ? msg.content\n : \"\";\n messages.push({\n role: \"tool\",\n content,\n tool_name: msg.name,\n });\n }\n }\n\n return c.json({ messages });\n });\n\n // SSE endpoint — real-time push for cron results and other async messages\n app.get(\"/api/events\", (c) => {\n return streamSSE(c, async (stream) => {\n const send = (data: string) => {\n stream.writeSSE({ data }).catch(() => {});\n };\n\n sseClients.add(send);\n\n // Send a ping so the client knows the connection is alive\n await stream.writeSSE({ data: JSON.stringify({ type: \"connected\" }) });\n\n // Keep alive with periodic pings\n const pingInterval = setInterval(() => {\n stream.writeSSE({ data: JSON.stringify({ type: \"ping\" }) }).catch(() => {\n clearInterval(pingInterval);\n });\n }, 30_000);\n\n // Wait until the client disconnects\n try {\n await new Promise<void>((resolve) => {\n stream.onAbort(() => resolve());\n });\n } finally {\n clearInterval(pingInterval);\n sseClients.delete(send);\n }\n });\n });\n\n // Heartbeat endpoint — triggered by DO scheduler via manager\n app.post(\"/api/heartbeat\", async (c) => {\n if (!heartbeat) {\n return c.json({ error: \"Heartbeat not configured\" }, 503);\n }\n\n try {\n const response = await heartbeat.triggerNow();\n return c.json({ status: \"ok\", response });\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n console.error(\"Heartbeat error:\", errMsg);\n return c.json({ error: errMsg }, 500);\n }\n });\n\n // LINE webhook endpoint\n app.post(\"/webhook/line\", async (c) => {\n if (!channels) {\n return c.json({ error: \"Channels not configured\" }, 503);\n }\n\n const { LineChannel } = await import(\"../channels/line.js\");\n const lineChannel = channels.getChannel(\"line\");\n if (!lineChannel || !(lineChannel instanceof LineChannel)) {\n return c.json({ error: \"LINE channel not enabled\" }, 404);\n }\n\n // Read raw body for signature verification\n const rawBody = await c.req.text();\n const signature = c.req.header(\"x-line-signature\") ?? \"\";\n\n if (!lineChannel.verifySignature(rawBody, signature)) {\n return c.json({ error: \"Invalid signature\" }, 401);\n }\n\n const body = JSON.parse(rawBody);\n\n // Process webhook events (non-blocking — return 200 immediately)\n lineChannel.handleWebhook(body).catch((err) => {\n console.error(\"LINE webhook processing error:\", err);\n });\n\n return c.json({ status: \"ok\" });\n });\n\n // Status / health check\n app.get(\"/api/status\", (c) => {\n return c.json({\n status: \"ok\",\n version: VERSION,\n uptime: process.uptime(),\n });\n });\n\n // Start the server\n serve({ fetch: app.fetch, port }, (info) => {\n console.log(`Gateway HTTP server listening on http://localhost:${info.port}`);\n });\n\n return { notify, notifyToolCall, notifyToolResult };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.mjs","names":[],"sources":["../../src/gateway/server.ts"],"sourcesContent":["import { serve } from \"@hono/node-server\";\nimport { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\n\nimport type { AgentLoop } from \"../agent/loop.js\";\nimport type { MessageBus } from \"../bus/queue.js\";\nimport type { ChannelManager } from \"../channels/manager.js\";\nimport type { HeartbeatService } from \"../heartbeat/service.js\";\n\nimport { createOutboundMessage } from \"../bus/events.js\";\nimport { VERSION } from \"../index.js\";\nimport { getControlHtml } from \"./ui.js\";\n\nexport interface GatewayServerOptions {\n agent: AgentLoop;\n bus: MessageBus;\n port: number;\n channels?: ChannelManager;\n heartbeat?: HeartbeatService;\n}\n\nexport interface GatewayServer {\n /** Push a message to all connected SSE clients. */\n notify(role: string, content: string, chatId?: string): void;\n /** Push a tool call event to all connected SSE clients. */\n notifyToolCall(name: string, args: string): void;\n /** Push a tool result event to all connected SSE clients. */\n notifyToolResult(name: string, output: string): void;\n}\n\nexport function createGatewayServer(opts: GatewayServerOptions): GatewayServer {\n const { agent, bus, port, channels, heartbeat } = opts;\n const app = new Hono();\n\n // Track SSE clients for real-time push\n const sseClients = new Set<(data: string) => void>();\n\n function broadcast(payload: string): void {\n for (const send of sseClients) {\n try {\n send(payload);\n } catch {\n // client disconnected, will be cleaned up\n }\n }\n }\n\n function notify(role: string, content: string, chatId = \"default\"): void {\n broadcast(JSON.stringify({ chatId, content, role, type: \"message\" }));\n }\n\n function notifyToolCall(name: string, args: string): void {\n broadcast(JSON.stringify({ arguments: args, name, type: \"tool_call\" }));\n }\n\n function notifyToolResult(name: string, output: string): void {\n broadcast(JSON.stringify({ name, output, type: \"tool_result\" }));\n }\n\n // Serve the control UI\n app.get(\"/\", (c) => c.html(getControlHtml()));\n\n // Chat endpoint — sends a message to the agent and returns the response\n // kind: \"direct\" = deliver message verbatim (no LLM), \"task\" = run through agent\n app.post(\"/api/chat\", async (c) => {\n const body = await c.req.json<{\n message?: string;\n kind?: \"direct\" | \"task\";\n session?: string;\n chatId?: string;\n deliver?: boolean;\n }>();\n const message = body.message?.trim();\n\n if (!message) {\n return c.json({ error: \"message is required\" }, 400);\n }\n\n const chatId = body.chatId ?? \"default\";\n const sessionKey = body.session ?? `line:${chatId}`;\n const kind = body.kind ?? \"task\";\n const deliver = body.deliver ?? false;\n\n try {\n if (kind === \"direct\") {\n // Deliver message verbatim — no LLM call, but record in session for context\n const session = agent.sessions.getOrCreate(sessionKey);\n session.addTurnMessages([{ content: message, role: \"assistant\" }]);\n agent.sessions.save(session);\n\n await bus.publishOutbound(\n createOutboundMessage({\n channel: \"line\",\n chatId,\n content: message,\n })\n );\n\n return c.json({ response: message });\n }\n\n // kind === \"task\" — run through the agent\n const response = await agent.processDirect(\n message,\n sessionKey,\n \"line\",\n chatId\n );\n\n // Deliver response to LINE if requested (e.g. cron-triggered)\n if (deliver && response) {\n await bus.publishOutbound(\n createOutboundMessage({\n channel: \"line\",\n chatId,\n content: response,\n })\n );\n }\n\n return c.json({ response });\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error);\n console.error(\"Chat error:\", errMsg);\n return c.json({ error: errMsg }, 500);\n }\n });\n\n // History endpoint — returns conversation history for the UI\n app.get(\"/api/history\", (c) => {\n const sessionKey = c.req.query(\"session\") ?? \"web:default\";\n const session = agent.sessions.getOrCreate(sessionKey);\n const history = session.getHistory();\n\n // Return user, assistant, and tool messages for the UI\n const messages: {\n role: string;\n content: string;\n tool_calls?: { name: string; arguments: string }[];\n tool_name?: string;\n }[] = [];\n\n for (const msg of history) {\n if (msg.role === \"user\" || msg.role === \"assistant\") {\n const content =\n typeof msg.content === \"string\"\n ? msg.content\n : msg.content\n ? msg.content\n .filter(\n (p): p is { type: \"text\"; text: string } =>\n p.type === \"text\"\n )\n .map((p) => p.text)\n .join(\"\")\n : \"\";\n\n const entry: (typeof messages)[number] = { content, role: msg.role };\n\n // Include tool calls if present on assistant messages\n if (\n msg.role === \"assistant\" &&\n msg.tool_calls &&\n msg.tool_calls.length > 0\n ) {\n entry.tool_calls = msg.tool_calls.map((tc) => ({\n arguments: tc.function.arguments,\n name: tc.function.name,\n }));\n }\n\n // Skip empty assistant messages that only have tool_calls (no text)\n if (msg.role === \"assistant\" && !content && !entry.tool_calls) {\n continue;\n }\n\n messages.push(entry);\n } else if (msg.role === \"tool\") {\n const content = typeof msg.content === \"string\" ? msg.content : \"\";\n messages.push({\n content,\n role: \"tool\",\n tool_name: msg.name,\n });\n }\n }\n\n return c.json({ messages });\n });\n\n // SSE endpoint — real-time push for cron results and other async messages\n app.get(\"/api/events\", (c) =>\n streamSSE(c, async (stream) => {\n const send = (data: string) => {\n stream.writeSSE({ data }).catch(() => {});\n };\n\n sseClients.add(send);\n\n // Send a ping so the client knows the connection is alive\n await stream.writeSSE({ data: JSON.stringify({ type: \"connected\" }) });\n\n // Keep alive with periodic pings\n const pingInterval = setInterval(() => {\n stream\n .writeSSE({ data: JSON.stringify({ type: \"ping\" }) })\n .catch(() => {\n clearInterval(pingInterval);\n });\n }, 30_000);\n\n // Wait until the client disconnects\n try {\n await new Promise<void>((resolve) => {\n stream.onAbort(() => resolve());\n });\n } finally {\n clearInterval(pingInterval);\n sseClients.delete(send);\n }\n })\n );\n\n // Heartbeat endpoint — triggered by DO scheduler via manager\n app.post(\"/api/heartbeat\", async (c) => {\n if (!heartbeat) {\n return c.json({ error: \"Heartbeat not configured\" }, 503);\n }\n\n try {\n const response = await heartbeat.triggerNow();\n return c.json({ response, status: \"ok\" });\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error);\n console.error(\"Heartbeat error:\", errMsg);\n return c.json({ error: errMsg }, 500);\n }\n });\n\n // LINE webhook endpoint\n app.post(\"/webhook/line\", async (c) => {\n if (!channels) {\n return c.json({ error: \"Channels not configured\" }, 503);\n }\n\n const { LineChannel } = await import(\"../channels/line.js\");\n const lineChannel = channels.getChannel(\"line\");\n if (!lineChannel || !(lineChannel instanceof LineChannel)) {\n return c.json({ error: \"LINE channel not enabled\" }, 404);\n }\n\n // Read raw body for signature verification\n const rawBody = await c.req.text();\n const signature = c.req.header(\"x-line-signature\") ?? \"\";\n\n if (!lineChannel.verifySignature(rawBody, signature)) {\n return c.json({ error: \"Invalid signature\" }, 401);\n }\n\n const body = JSON.parse(rawBody);\n\n // Process webhook events (non-blocking — return 200 immediately)\n lineChannel.handleWebhook(body).catch((error) => {\n console.error(\"LINE webhook processing error:\", error);\n });\n\n return c.json({ status: \"ok\" });\n });\n\n // Status / health check\n app.get(\"/api/status\", (c) =>\n c.json({\n status: \"ok\",\n version: VERSION,\n uptime: process.uptime(),\n })\n );\n\n // Start the server\n serve({ fetch: app.fetch, port }, (info) => {\n console.log(\n `Gateway HTTP server listening on http://localhost:${info.port}`\n );\n });\n\n return { notify, notifyToolCall, notifyToolResult };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.mts","names":[],"sources":["../../src/heartbeat/service.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"service.d.mts","names":[],"sources":["../../src/heartbeat/service.ts"],"mappings":";KAgCK,iBAAA,IAAqB,MAAA,aAAmB,OAAA;;;;;;cAOhC,gBAAA;EAAA,QACH,SAAA;EAAA,QACA,WAAA;cAEI,MAAA;IAAU,SAAA;IAAmB,WAAA,GAAc,iBAAA;EAAA;EAAA,YAK3C,aAAA,CAAA;EAAA,QAIJ,QAAA;EAT+C;EAAA,QAqB/C,qBAAA;EAhBI;;;;;;EAiEN,UAAA,CAAA,GAAc,OAAA;AAAA"}
|
|
@@ -40,7 +40,7 @@ var HeartbeatService = class {
|
|
|
40
40
|
readFile(path) {
|
|
41
41
|
if (!existsSync(path)) return null;
|
|
42
42
|
try {
|
|
43
|
-
return readFileSync(path, "
|
|
43
|
+
return readFileSync(path, "utf8");
|
|
44
44
|
} catch {
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
@@ -50,9 +50,9 @@ var HeartbeatService = class {
|
|
|
50
50
|
const results = [];
|
|
51
51
|
const rootContent = this.readFile(this.heartbeatFile);
|
|
52
52
|
if (rootContent && !isHeartbeatEmpty(rootContent)) results.push({
|
|
53
|
-
|
|
53
|
+
content: rootContent,
|
|
54
54
|
label: "workspace",
|
|
55
|
-
|
|
55
|
+
path: this.heartbeatFile
|
|
56
56
|
});
|
|
57
57
|
const skillsDir = join(this.workspace, "skills");
|
|
58
58
|
if (existsSync(skillsDir)) try {
|
|
@@ -61,9 +61,9 @@ var HeartbeatService = class {
|
|
|
61
61
|
const skillHeartbeat = join(skillsDir, entry.name, "HEARTBEAT.md");
|
|
62
62
|
const content = this.readFile(skillHeartbeat);
|
|
63
63
|
if (content && !isHeartbeatEmpty(content)) results.push({
|
|
64
|
-
|
|
64
|
+
content,
|
|
65
65
|
label: `skills/${entry.name}`,
|
|
66
|
-
|
|
66
|
+
path: skillHeartbeat
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
} catch {}
|
|
@@ -89,11 +89,11 @@ var HeartbeatService = class {
|
|
|
89
89
|
else prompt = `Check the following HEARTBEAT.md files in your workspace for tasks:\n${heartbeats.map((h) => `- ${h.label}/HEARTBEAT.md`).join("\n")}\nFollow any instructions or tasks listed there.\nIf nothing needs attention, reply with just: HEARTBEAT_OK`;
|
|
90
90
|
try {
|
|
91
91
|
const response = await this.onHeartbeat(prompt);
|
|
92
|
-
if (response.toUpperCase().
|
|
92
|
+
if (response.toUpperCase().replaceAll("_", "").includes(HEARTBEAT_OK_TOKEN.replaceAll("_", ""))) console.log("Heartbeat: OK (no action needed)");
|
|
93
93
|
else console.log("Heartbeat: completed task");
|
|
94
94
|
return response;
|
|
95
|
-
} catch (
|
|
96
|
-
console.error("Heartbeat execution failed:",
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error("Heartbeat execution failed:", error);
|
|
97
97
|
return null;
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":[],"sources":["../../src/heartbeat/service.ts"],"sourcesContent":["import { readFileSync, existsSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst HEARTBEAT_PROMPT = `Read HEARTBEAT.md in your workspace (if it exists).\nFollow any instructions or tasks listed there.\nIf nothing needs attention, reply with just: HEARTBEAT_OK`;\n\nconst HEARTBEAT_OK_TOKEN = \"HEARTBEAT_OK\";\n\n/** Check if HEARTBEAT.md has no actionable content. */\nfunction isHeartbeatEmpty(content: string | null): boolean {\n if (!content) return true;\n\n const skipPatterns = new Set([\"- [ ]\", \"* [ ]\", \"- [x]\", \"* [x]\"]);\n\n for (const rawLine of content.split(\"\\n\")) {\n const line = rawLine.trim();\n if (\n !line ||\n line.startsWith(\"#\") ||\n line.startsWith(\"<!--\") ||\n skipPatterns.has(line)\n ) {\n continue;\n }\n return false; // Found actionable content\n }\n return true;\n}\n\ntype HeartbeatCallback = (prompt: string) => Promise<string>;\n\n/**\n * Heartbeat service that checks workspace HEARTBEAT.md files for tasks.\n * Scheduling is handled externally by the DO — this service only provides\n * the smart file-reading logic and `triggerNow()` to invoke on demand.\n */\nexport class HeartbeatService {\n private workspace: string;\n private onHeartbeat: HeartbeatCallback | null;\n\n constructor(params: {
|
|
1
|
+
{"version":3,"file":"service.mjs","names":[],"sources":["../../src/heartbeat/service.ts"],"sourcesContent":["import { readFileSync, existsSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst HEARTBEAT_PROMPT = `Read HEARTBEAT.md in your workspace (if it exists).\nFollow any instructions or tasks listed there.\nIf nothing needs attention, reply with just: HEARTBEAT_OK`;\n\nconst HEARTBEAT_OK_TOKEN = \"HEARTBEAT_OK\";\n\n/** Check if HEARTBEAT.md has no actionable content. */\nfunction isHeartbeatEmpty(content: string | null): boolean {\n if (!content) {\n return true;\n }\n\n const skipPatterns = new Set([\"- [ ]\", \"* [ ]\", \"- [x]\", \"* [x]\"]);\n\n for (const rawLine of content.split(\"\\n\")) {\n const line = rawLine.trim();\n if (\n !line ||\n line.startsWith(\"#\") ||\n line.startsWith(\"<!--\") ||\n skipPatterns.has(line)\n ) {\n continue;\n }\n return false; // Found actionable content\n }\n return true;\n}\n\ntype HeartbeatCallback = (prompt: string) => Promise<string>;\n\n/**\n * Heartbeat service that checks workspace HEARTBEAT.md files for tasks.\n * Scheduling is handled externally by the DO — this service only provides\n * the smart file-reading logic and `triggerNow()` to invoke on demand.\n */\nexport class HeartbeatService {\n private workspace: string;\n private onHeartbeat: HeartbeatCallback | null;\n\n constructor(params: { workspace: string; onHeartbeat?: HeartbeatCallback }) {\n this.workspace = params.workspace;\n this.onHeartbeat = params.onHeartbeat ?? null;\n }\n\n private get heartbeatFile(): string {\n return join(this.workspace, \"HEARTBEAT.md\");\n }\n\n private readFile(path: string): string | null {\n if (!existsSync(path)) {\n return null;\n }\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return null;\n }\n }\n\n /** Read all HEARTBEAT.md files: root + skills/{name}/HEARTBEAT.md */\n private readAllHeartbeatFiles(): {\n path: string;\n label: string;\n content: string;\n }[] {\n const results: { path: string; label: string; content: string }[] = [];\n\n // Root heartbeat\n const rootContent = this.readFile(this.heartbeatFile);\n if (rootContent && !isHeartbeatEmpty(rootContent)) {\n results.push({\n content: rootContent,\n label: \"workspace\",\n path: this.heartbeatFile,\n });\n }\n\n // Skills heartbeats\n const skillsDir = join(this.workspace, \"skills\");\n if (existsSync(skillsDir)) {\n try {\n for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) {\n continue;\n }\n const skillHeartbeat = join(skillsDir, entry.name, \"HEARTBEAT.md\");\n const content = this.readFile(skillHeartbeat);\n if (content && !isHeartbeatEmpty(content)) {\n results.push({\n content,\n label: `skills/${entry.name}`,\n path: skillHeartbeat,\n });\n }\n }\n } catch {\n // skills dir not readable, ignore\n }\n }\n\n return results;\n }\n\n /**\n * Trigger a heartbeat check now.\n * Reads all HEARTBEAT.md files, skips if none have actionable content,\n * otherwise invokes the callback with a prompt for the agent.\n * Returns the agent response, or null if nothing to do.\n */\n async triggerNow(): Promise<string | null> {\n if (!this.onHeartbeat) {\n return null;\n }\n\n const heartbeats = this.readAllHeartbeatFiles();\n\n if (heartbeats.length === 0) {\n console.log(\"Heartbeat: no actionable content, skipping LLM call\");\n return null;\n }\n\n const locations = heartbeats.map((h) => h.label).join(\", \");\n console.log(`Heartbeat: checking for tasks in ${locations}...`);\n\n // Build a prompt that tells the agent which files to check\n let prompt: string;\n if (heartbeats.length === 1 && heartbeats[0].label === \"workspace\") {\n prompt = HEARTBEAT_PROMPT;\n } else {\n const fileList = heartbeats\n .map((h) => `- ${h.label}/HEARTBEAT.md`)\n .join(\"\\n\");\n prompt = `Check the following HEARTBEAT.md files in your workspace for tasks:\\n${fileList}\\nFollow any instructions or tasks listed there.\\nIf nothing needs attention, reply with just: HEARTBEAT_OK`;\n }\n\n try {\n const response = await this.onHeartbeat(prompt);\n const normalized = response.toUpperCase().replaceAll(\"_\", \"\");\n if (normalized.includes(HEARTBEAT_OK_TOKEN.replaceAll(\"_\", \"\"))) {\n console.log(\"Heartbeat: OK (no action needed)\");\n } else {\n console.log(\"Heartbeat: completed task\");\n }\n return response;\n } catch (error) {\n console.error(\"Heartbeat execution failed:\", error);\n return null;\n }\n }\n}\n"],"mappings":";;;;AAGA,MAAM,mBAAmB;;;AAIzB,MAAM,qBAAqB;;AAG3B,SAAS,iBAAiB,SAAiC;AACzD,KAAI,CAAC,QACH,QAAO;CAGT,MAAM,eAAe,IAAI,IAAI;EAAC;EAAS;EAAS;EAAS;EAAQ,CAAC;AAElE,MAAK,MAAM,WAAW,QAAQ,MAAM,KAAK,EAAE;EACzC,MAAM,OAAO,QAAQ,MAAM;AAC3B,MACE,CAAC,QACD,KAAK,WAAW,IAAI,IACpB,KAAK,WAAW,OAAO,IACvB,aAAa,IAAI,KAAK,CAEtB;AAEF,SAAO;;AAET,QAAO;;;;;;;AAUT,IAAa,mBAAb,MAA8B;CAC5B,AAAQ;CACR,AAAQ;CAER,YAAY,QAAgE;AAC1E,OAAK,YAAY,OAAO;AACxB,OAAK,cAAc,OAAO,eAAe;;CAG3C,IAAY,gBAAwB;AAClC,SAAO,KAAK,KAAK,WAAW,eAAe;;CAG7C,AAAQ,SAAS,MAA6B;AAC5C,MAAI,CAAC,WAAW,KAAK,CACnB,QAAO;AAET,MAAI;AACF,UAAO,aAAa,MAAM,OAAO;UAC3B;AACN,UAAO;;;;CAKX,AAAQ,wBAIJ;EACF,MAAM,UAA8D,EAAE;EAGtE,MAAM,cAAc,KAAK,SAAS,KAAK,cAAc;AACrD,MAAI,eAAe,CAAC,iBAAiB,YAAY,CAC/C,SAAQ,KAAK;GACX,SAAS;GACT,OAAO;GACP,MAAM,KAAK;GACZ,CAAC;EAIJ,MAAM,YAAY,KAAK,KAAK,WAAW,SAAS;AAChD,MAAI,WAAW,UAAU,CACvB,KAAI;AACF,QAAK,MAAM,SAAS,YAAY,WAAW,EAAE,eAAe,MAAM,CAAC,EAAE;AACnE,QAAI,CAAC,MAAM,aAAa,CACtB;IAEF,MAAM,iBAAiB,KAAK,WAAW,MAAM,MAAM,eAAe;IAClE,MAAM,UAAU,KAAK,SAAS,eAAe;AAC7C,QAAI,WAAW,CAAC,iBAAiB,QAAQ,CACvC,SAAQ,KAAK;KACX;KACA,OAAO,UAAU,MAAM;KACvB,MAAM;KACP,CAAC;;UAGA;AAKV,SAAO;;;;;;;;CAST,MAAM,aAAqC;AACzC,MAAI,CAAC,KAAK,YACR,QAAO;EAGT,MAAM,aAAa,KAAK,uBAAuB;AAE/C,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAQ,IAAI,sDAAsD;AAClE,UAAO;;EAGT,MAAM,YAAY,WAAW,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK;AAC3D,UAAQ,IAAI,oCAAoC,UAAU,KAAK;EAG/D,IAAI;AACJ,MAAI,WAAW,WAAW,KAAK,WAAW,GAAG,UAAU,YACrD,UAAS;MAKT,UAAS,wEAHQ,WACd,KAAK,MAAM,KAAK,EAAE,MAAM,eAAe,CACvC,KAAK,KAAK,CAC6E;AAG5F,MAAI;GACF,MAAM,WAAW,MAAM,KAAK,YAAY,OAAO;AAE/C,OADmB,SAAS,aAAa,CAAC,WAAW,KAAK,GAAG,CAC9C,SAAS,mBAAmB,WAAW,KAAK,GAAG,CAAC,CAC7D,SAAQ,IAAI,mCAAmC;OAE/C,SAAQ,IAAI,4BAA4B;AAE1C,UAAO;WACA,OAAO;AACd,WAAQ,MAAM,+BAA+B,MAAM;AACnD,UAAO"}
|
package/dist/index.d.mts
CHANGED
|
@@ -6,8 +6,8 @@ import { InboundMessage, OutboundMessage } from "./bus/events.mjs";
|
|
|
6
6
|
import { MessageBus } from "./bus/queue.mjs";
|
|
7
7
|
import { PROVIDERS, ProviderSpec, findByModel, findByName, findGateway, getModelOverrides, resolveModel } from "./providers/registry.mjs";
|
|
8
8
|
import { Config } from "./config/schema.mjs";
|
|
9
|
-
import { SubagentManager } from "./agent/subagent.mjs";
|
|
10
9
|
import { SessionManager } from "./session/manager.mjs";
|
|
10
|
+
import { SubagentManager } from "./agent/subagent.mjs";
|
|
11
11
|
import { AgentLoop } from "./agent/loop.mjs";
|
|
12
12
|
import { LineChannel } from "./channels/line.mjs";
|
|
13
13
|
import { ChannelManager } from "./channels/manager.mjs";
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;cAyBa,OAAA;AAAA,cACA,IAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { SessionManager } from "./session/manager.mjs";
|
|
1
2
|
import { MemoryStore } from "./agent/memory.mjs";
|
|
2
3
|
import { SkillsLoader } from "./agent/skills.mjs";
|
|
3
4
|
import { ContextBuilder } from "./agent/context.mjs";
|
|
4
5
|
import { SubagentManager } from "./agent/subagent.mjs";
|
|
5
|
-
import { SessionManager } from "./session/manager.mjs";
|
|
6
6
|
import { AgentLoop } from "./agent/loop.mjs";
|
|
7
7
|
import { MessageBus } from "./bus/queue.mjs";
|
|
8
8
|
import { PROVIDERS, findByModel, findByName, findGateway, getModelOverrides, resolveModel } from "./providers/registry.mjs";
|
|
@@ -21,7 +21,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
21
21
|
function readVersion() {
|
|
22
22
|
try {
|
|
23
23
|
for (const rel of ["../package.json", "../../package.json"]) try {
|
|
24
|
-
const pkg = JSON.parse(readFileSync(join(__dirname, rel), "
|
|
24
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, rel), "utf8"));
|
|
25
25
|
if (pkg.version) return pkg.version;
|
|
26
26
|
} catch {}
|
|
27
27
|
} catch {}
|