@xopcai/xopcbot 0.1.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 +132 -0
- package/README.zh-CN.md +130 -0
- package/dist/__tests__/core.test.d.ts +1 -0
- package/dist/__tests__/core.test.js +72 -0
- package/dist/__tests__/core.test.js.map +1 -0
- package/dist/agent/fallback/__tests__/index.test.d.ts +1 -0
- package/dist/agent/fallback/__tests__/index.test.js +111 -0
- package/dist/agent/fallback/__tests__/index.test.js.map +1 -0
- package/dist/agent/fallback/candidates.d.ts +23 -0
- package/dist/agent/fallback/candidates.js +62 -0
- package/dist/agent/fallback/candidates.js.map +1 -0
- package/dist/agent/fallback/error.d.ts +22 -0
- package/dist/agent/fallback/error.js +27 -0
- package/dist/agent/fallback/error.js.map +1 -0
- package/dist/agent/fallback/index.d.ts +6 -0
- package/dist/agent/fallback/index.js +5 -0
- package/dist/agent/fallback/index.js.map +1 -0
- package/dist/agent/fallback/reason.d.ts +7 -0
- package/dist/agent/fallback/reason.js +78 -0
- package/dist/agent/fallback/reason.js.map +1 -0
- package/dist/agent/fallback/runner.d.ts +22 -0
- package/dist/agent/fallback/runner.js +34 -0
- package/dist/agent/fallback/runner.js.map +1 -0
- package/dist/agent/helpers.d.ts +38 -0
- package/dist/agent/helpers.js +122 -0
- package/dist/agent/helpers.js.map +1 -0
- package/dist/agent/index.d.ts +7 -0
- package/dist/agent/index.js +7 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/memory/compaction.d.ts +63 -0
- package/dist/agent/memory/compaction.js +233 -0
- package/dist/agent/memory/compaction.js.map +1 -0
- package/dist/agent/memory/window.d.ts +29 -0
- package/dist/agent/memory/window.js +64 -0
- package/dist/agent/memory/window.js.map +1 -0
- package/dist/agent/model-manager.d.ts +80 -0
- package/dist/agent/model-manager.js +213 -0
- package/dist/agent/model-manager.js.map +1 -0
- package/dist/agent/prompt/heartbeat.d.ts +97 -0
- package/dist/agent/prompt/heartbeat.js +313 -0
- package/dist/agent/prompt/heartbeat.js.map +1 -0
- package/dist/agent/prompt/index.d.ts +65 -0
- package/dist/agent/prompt/index.js +215 -0
- package/dist/agent/prompt/index.js.map +1 -0
- package/dist/agent/prompt/memory/index.d.ts +37 -0
- package/dist/agent/prompt/memory/index.js +241 -0
- package/dist/agent/prompt/memory/index.js.map +1 -0
- package/dist/agent/prompt/modes.d.ts +44 -0
- package/dist/agent/prompt/modes.js +167 -0
- package/dist/agent/prompt/modes.js.map +1 -0
- package/dist/agent/prompt/safety.d.ts +88 -0
- package/dist/agent/prompt/safety.js +290 -0
- package/dist/agent/prompt/safety.js.map +1 -0
- package/dist/agent/service.d.ts +91 -0
- package/dist/agent/service.js +641 -0
- package/dist/agent/service.js.map +1 -0
- package/dist/agent/session-tracker.d.ts +73 -0
- package/dist/agent/session-tracker.js +137 -0
- package/dist/agent/session-tracker.js.map +1 -0
- package/dist/agent/skills/__tests__/test-framework.test.d.ts +4 -0
- package/dist/agent/skills/__tests__/test-framework.test.js +343 -0
- package/dist/agent/skills/__tests__/test-framework.test.js.map +1 -0
- package/dist/agent/skills/config.d.ts +58 -0
- package/dist/agent/skills/config.js +212 -0
- package/dist/agent/skills/config.js.map +1 -0
- package/dist/agent/skills/index.d.ts +25 -0
- package/dist/agent/skills/index.js +349 -0
- package/dist/agent/skills/index.js.map +1 -0
- package/dist/agent/skills/installer.d.ts +38 -0
- package/dist/agent/skills/installer.js +352 -0
- package/dist/agent/skills/installer.js.map +1 -0
- package/dist/agent/skills/scanner.d.ts +32 -0
- package/dist/agent/skills/scanner.js +265 -0
- package/dist/agent/skills/scanner.js.map +1 -0
- package/dist/agent/skills/test-framework.d.ts +107 -0
- package/dist/agent/skills/test-framework.js +607 -0
- package/dist/agent/skills/test-framework.js.map +1 -0
- package/dist/agent/skills/types.d.ts +181 -0
- package/dist/agent/skills/types.js +7 -0
- package/dist/agent/skills/types.js.map +1 -0
- package/dist/agent/skills/watcher.d.ts +37 -0
- package/dist/agent/skills/watcher.js +124 -0
- package/dist/agent/skills/watcher.js.map +1 -0
- package/dist/agent/tools/communication.d.ts +18 -0
- package/dist/agent/tools/communication.js +56 -0
- package/dist/agent/tools/communication.js.map +1 -0
- package/dist/agent/tools/edit-diff.d.ts +21 -0
- package/dist/agent/tools/edit-diff.js +69 -0
- package/dist/agent/tools/edit-diff.js.map +1 -0
- package/dist/agent/tools/edit.d.ts +13 -0
- package/dist/agent/tools/edit.js +65 -0
- package/dist/agent/tools/edit.js.map +1 -0
- package/dist/agent/tools/find.d.ts +24 -0
- package/dist/agent/tools/find.js +99 -0
- package/dist/agent/tools/find.js.map +1 -0
- package/dist/agent/tools/grep.d.ts +33 -0
- package/dist/agent/tools/grep.js +183 -0
- package/dist/agent/tools/grep.js.map +1 -0
- package/dist/agent/tools/index.d.ts +13 -0
- package/dist/agent/tools/index.js +18 -0
- package/dist/agent/tools/index.js.map +1 -0
- package/dist/agent/tools/list-dir.d.ts +6 -0
- package/dist/agent/tools/list-dir.js +37 -0
- package/dist/agent/tools/list-dir.js.map +1 -0
- package/dist/agent/tools/memory-tool.d.ts +14 -0
- package/dist/agent/tools/memory-tool.js +81 -0
- package/dist/agent/tools/memory-tool.js.map +1 -0
- package/dist/agent/tools/path-utils.d.ts +4 -0
- package/dist/agent/tools/path-utils.js +13 -0
- package/dist/agent/tools/path-utils.js.map +1 -0
- package/dist/agent/tools/read.d.ts +7 -0
- package/dist/agent/tools/read.js +47 -0
- package/dist/agent/tools/read.js.map +1 -0
- package/dist/agent/tools/send-media.d.ts +18 -0
- package/dist/agent/tools/send-media.js +104 -0
- package/dist/agent/tools/send-media.js.map +1 -0
- package/dist/agent/tools/shell.d.ts +13 -0
- package/dist/agent/tools/shell.js +114 -0
- package/dist/agent/tools/shell.js.map +1 -0
- package/dist/agent/tools/truncate.d.ts +36 -0
- package/dist/agent/tools/truncate.js +98 -0
- package/dist/agent/tools/truncate.js.map +1 -0
- package/dist/agent/tools/web.d.ts +14 -0
- package/dist/agent/tools/web.js +109 -0
- package/dist/agent/tools/web.js.map +1 -0
- package/dist/agent/tools/write.d.ts +7 -0
- package/dist/agent/tools/write.js +35 -0
- package/dist/agent/tools/write.js.map +1 -0
- package/dist/agent/types.d.ts +8 -0
- package/dist/agent/types.js +2 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/agent/typing.d.ts +9 -0
- package/dist/agent/typing.js +32 -0
- package/dist/agent/typing.js.map +1 -0
- package/dist/auth/index.d.ts +12 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/oauth/anthropic.d.ts +7 -0
- package/dist/auth/oauth/anthropic.js +89 -0
- package/dist/auth/oauth/anthropic.js.map +1 -0
- package/dist/auth/oauth/github-copilot.d.ts +8 -0
- package/dist/auth/oauth/github-copilot.js +35 -0
- package/dist/auth/oauth/github-copilot.js.map +1 -0
- package/dist/auth/oauth/google-antigravity.d.ts +7 -0
- package/dist/auth/oauth/google-antigravity.js +27 -0
- package/dist/auth/oauth/google-antigravity.js.map +1 -0
- package/dist/auth/oauth/google-gemini-cli.d.ts +7 -0
- package/dist/auth/oauth/google-gemini-cli.js +28 -0
- package/dist/auth/oauth/google-gemini-cli.js.map +1 -0
- package/dist/auth/oauth/index.d.ts +14 -0
- package/dist/auth/oauth/index.js +15 -0
- package/dist/auth/oauth/index.js.map +1 -0
- package/dist/auth/oauth/kimi.d.ts +8 -0
- package/dist/auth/oauth/kimi.js +104 -0
- package/dist/auth/oauth/kimi.js.map +1 -0
- package/dist/auth/oauth/minimax.d.ts +8 -0
- package/dist/auth/oauth/minimax.js +109 -0
- package/dist/auth/oauth/minimax.js.map +1 -0
- package/dist/auth/oauth/openai-codex.d.ts +7 -0
- package/dist/auth/oauth/openai-codex.js +33 -0
- package/dist/auth/oauth/openai-codex.js.map +1 -0
- package/dist/auth/oauth/pkce.d.ts +8 -0
- package/dist/auth/oauth/pkce.js +22 -0
- package/dist/auth/oauth/pkce.js.map +1 -0
- package/dist/auth/oauth/qwen.d.ts +7 -0
- package/dist/auth/oauth/qwen.js +114 -0
- package/dist/auth/oauth/qwen.js.map +1 -0
- package/dist/auth/oauth/types.d.ts +46 -0
- package/dist/auth/oauth/types.js +7 -0
- package/dist/auth/oauth/types.js.map +1 -0
- package/dist/auth/profiles/index.d.ts +16 -0
- package/dist/auth/profiles/index.js +17 -0
- package/dist/auth/profiles/index.js.map +1 -0
- package/dist/auth/profiles/oauth.d.ts +12 -0
- package/dist/auth/profiles/oauth.js +106 -0
- package/dist/auth/profiles/oauth.js.map +1 -0
- package/dist/auth/profiles/order.d.ts +19 -0
- package/dist/auth/profiles/order.js +63 -0
- package/dist/auth/profiles/order.js.map +1 -0
- package/dist/auth/profiles/profiles.d.ts +27 -0
- package/dist/auth/profiles/profiles.js +110 -0
- package/dist/auth/profiles/profiles.js.map +1 -0
- package/dist/auth/profiles/store.d.ts +17 -0
- package/dist/auth/profiles/store.js +234 -0
- package/dist/auth/profiles/store.js.map +1 -0
- package/dist/auth/profiles/types.d.ts +64 -0
- package/dist/auth/profiles/types.js +7 -0
- package/dist/auth/profiles/types.js.map +1 -0
- package/dist/auth/profiles/usage.d.ts +24 -0
- package/dist/auth/profiles/usage.js +99 -0
- package/dist/auth/profiles/usage.js.map +1 -0
- package/dist/auth/storage.d.ts +99 -0
- package/dist/auth/storage.js +315 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/bus/index.d.ts +3 -0
- package/dist/bus/index.js +2 -0
- package/dist/bus/index.js.map +1 -0
- package/dist/bus/queue.d.ts +20 -0
- package/dist/bus/queue.js +57 -0
- package/dist/bus/queue.js.map +1 -0
- package/dist/channels/__tests__/access-control.test.d.ts +4 -0
- package/dist/channels/__tests__/access-control.test.js +310 -0
- package/dist/channels/__tests__/access-control.test.js.map +1 -0
- package/dist/channels/__tests__/draft-stream.test.d.ts +4 -0
- package/dist/channels/__tests__/draft-stream.test.js +243 -0
- package/dist/channels/__tests__/draft-stream.test.js.map +1 -0
- package/dist/channels/__tests__/format.test.d.ts +4 -0
- package/dist/channels/__tests__/format.test.js +146 -0
- package/dist/channels/__tests__/format.test.js.map +1 -0
- package/dist/channels/__tests__/manager.test.d.ts +6 -0
- package/dist/channels/__tests__/manager.test.js +34 -0
- package/dist/channels/__tests__/manager.test.js.map +1 -0
- package/dist/channels/__tests__/typing-controller.test.d.ts +4 -0
- package/dist/channels/__tests__/typing-controller.test.js +109 -0
- package/dist/channels/__tests__/typing-controller.test.js.map +1 -0
- package/dist/channels/__tests__/update-offset-store.test.d.ts +7 -0
- package/dist/channels/__tests__/update-offset-store.test.js +35 -0
- package/dist/channels/__tests__/update-offset-store.test.js.map +1 -0
- package/dist/channels/access-control.d.ts +93 -0
- package/dist/channels/access-control.js +201 -0
- package/dist/channels/access-control.js.map +1 -0
- package/dist/channels/draft-stream.d.ts +55 -0
- package/dist/channels/draft-stream.js +211 -0
- package/dist/channels/draft-stream.js.map +1 -0
- package/dist/channels/format.d.ts +38 -0
- package/dist/channels/format.js +187 -0
- package/dist/channels/format.js.map +1 -0
- package/dist/channels/index.d.ts +22 -0
- package/dist/channels/index.js +23 -0
- package/dist/channels/index.js.map +1 -0
- package/dist/channels/manager.d.ts +30 -0
- package/dist/channels/manager.js +125 -0
- package/dist/channels/manager.js.map +1 -0
- package/dist/channels/telegram/__tests__/index.test.d.ts +4 -0
- package/dist/channels/telegram/__tests__/index.test.js +153 -0
- package/dist/channels/telegram/__tests__/index.test.js.map +1 -0
- package/dist/channels/telegram/__tests__/inline-keyboards.test.d.ts +4 -0
- package/dist/channels/telegram/__tests__/inline-keyboards.test.js +99 -0
- package/dist/channels/telegram/__tests__/inline-keyboards.test.js.map +1 -0
- package/dist/channels/telegram/client.d.ts +48 -0
- package/dist/channels/telegram/client.js +177 -0
- package/dist/channels/telegram/client.js.map +1 -0
- package/dist/channels/telegram/command-handler.d.ts +28 -0
- package/dist/channels/telegram/command-handler.js +209 -0
- package/dist/channels/telegram/command-handler.js.map +1 -0
- package/dist/channels/telegram/index.d.ts +8 -0
- package/dist/channels/telegram/index.js +9 -0
- package/dist/channels/telegram/index.js.map +1 -0
- package/dist/channels/telegram/inline-keyboards.d.ts +20 -0
- package/dist/channels/telegram/inline-keyboards.js +38 -0
- package/dist/channels/telegram/inline-keyboards.js.map +1 -0
- package/dist/channels/telegram/plugin.d.ts +33 -0
- package/dist/channels/telegram/plugin.js +640 -0
- package/dist/channels/telegram/plugin.js.map +1 -0
- package/dist/channels/telegram/webhook.d.ts +31 -0
- package/dist/channels/telegram/webhook.js +129 -0
- package/dist/channels/telegram/webhook.js.map +1 -0
- package/dist/channels/types.d.ts +186 -0
- package/dist/channels/types.js +7 -0
- package/dist/channels/types.js.map +1 -0
- package/dist/channels/typing-controller.d.ts +47 -0
- package/dist/channels/typing-controller.js +117 -0
- package/dist/channels/typing-controller.js.map +1 -0
- package/dist/channels/update-offset-store.d.ts +37 -0
- package/dist/channels/update-offset-store.js +165 -0
- package/dist/channels/update-offset-store.js.map +1 -0
- package/dist/channels/whatsapp/index.d.ts +4 -0
- package/dist/channels/whatsapp/index.js +5 -0
- package/dist/channels/whatsapp/index.js.map +1 -0
- package/dist/channels/whatsapp/plugin.d.ts +27 -0
- package/dist/channels/whatsapp/plugin.js +66 -0
- package/dist/channels/whatsapp/plugin.js.map +1 -0
- package/dist/cli/__tests__/registry.test.d.ts +1 -0
- package/dist/cli/__tests__/registry.test.js +366 -0
- package/dist/cli/__tests__/registry.test.js.map +1 -0
- package/dist/cli/commands/agent.d.ts +1 -0
- package/dist/cli/commands/agent.js +216 -0
- package/dist/cli/commands/agent.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +6 -0
- package/dist/cli/commands/auth.js +440 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/config.d.ts +1 -0
- package/dist/cli/commands/config.js +135 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/configure.d.ts +1 -0
- package/dist/cli/commands/configure.js +173 -0
- package/dist/cli/commands/configure.js.map +1 -0
- package/dist/cli/commands/cron.d.ts +1 -0
- package/dist/cli/commands/cron.js +81 -0
- package/dist/cli/commands/cron.js.map +1 -0
- package/dist/cli/commands/gateway.d.ts +1 -0
- package/dist/cli/commands/gateway.js +91 -0
- package/dist/cli/commands/gateway.js.map +1 -0
- package/dist/cli/commands/index.d.ts +0 -0
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/models.d.ts +1 -0
- package/dist/cli/commands/models.js +79 -0
- package/dist/cli/commands/models.js.map +1 -0
- package/dist/cli/commands/onboard.d.ts +1 -0
- package/dist/cli/commands/onboard.js +621 -0
- package/dist/cli/commands/onboard.js.map +1 -0
- package/dist/cli/commands/plugin.d.ts +1 -0
- package/dist/cli/commands/plugin.js +341 -0
- package/dist/cli/commands/plugin.js.map +1 -0
- package/dist/cli/commands/session.d.ts +1 -0
- package/dist/cli/commands/session.js +450 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/skills-test.d.ts +9 -0
- package/dist/cli/commands/skills-test.js +195 -0
- package/dist/cli/commands/skills-test.js.map +1 -0
- package/dist/cli/commands/skills.d.ts +9 -0
- package/dist/cli/commands/skills.js +385 -0
- package/dist/cli/commands/skills.js.map +1 -0
- package/dist/cli/index.d.ts +19 -0
- package/dist/cli/index.js +40 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/registry.d.ts +43 -0
- package/dist/cli/registry.js +82 -0
- package/dist/cli/registry.js.map +1 -0
- package/dist/cli/templates.d.ts +19 -0
- package/dist/cli/templates.js +191 -0
- package/dist/cli/templates.js.map +1 -0
- package/dist/cli/utils/colors.d.ts +13 -0
- package/dist/cli/utils/colors.js +16 -0
- package/dist/cli/utils/colors.js.map +1 -0
- package/dist/config/__tests__/diff.test.d.ts +1 -0
- package/dist/config/__tests__/diff.test.js +192 -0
- package/dist/config/__tests__/diff.test.js.map +1 -0
- package/dist/config/__tests__/loader.test.d.ts +1 -0
- package/dist/config/__tests__/loader.test.js +356 -0
- package/dist/config/__tests__/loader.test.js.map +1 -0
- package/dist/config/__tests__/paths.test.d.ts +1 -0
- package/dist/config/__tests__/paths.test.js +192 -0
- package/dist/config/__tests__/paths.test.js.map +1 -0
- package/dist/config/__tests__/reload.test.d.ts +1 -0
- package/dist/config/__tests__/reload.test.js +374 -0
- package/dist/config/__tests__/reload.test.js.map +1 -0
- package/dist/config/__tests__/rules.test.d.ts +1 -0
- package/dist/config/__tests__/rules.test.js +204 -0
- package/dist/config/__tests__/rules.test.js.map +1 -0
- package/dist/config/__tests__/schema.test.d.ts +1 -0
- package/dist/config/__tests__/schema.test.js +672 -0
- package/dist/config/__tests__/schema.test.js.map +1 -0
- package/dist/config/diff.d.ts +7 -0
- package/dist/config/diff.js +46 -0
- package/dist/config/diff.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.js +7 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +5 -0
- package/dist/config/loader.js +81 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/paths.d.ts +35 -0
- package/dist/config/paths.js +79 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/reload.d.ts +78 -0
- package/dist/config/reload.js +190 -0
- package/dist/config/reload.js.map +1 -0
- package/dist/config/rules.d.ts +42 -0
- package/dist/config/rules.js +114 -0
- package/dist/config/rules.js.map +1 -0
- package/dist/config/schema.d.ts +1340 -0
- package/dist/config/schema.js +611 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/cron/executor.d.ts +54 -0
- package/dist/cron/executor.js +364 -0
- package/dist/cron/executor.js.map +1 -0
- package/dist/cron/index.d.ts +5 -0
- package/dist/cron/index.js +6 -0
- package/dist/cron/index.js.map +1 -0
- package/dist/cron/persistence.d.ts +61 -0
- package/dist/cron/persistence.js +188 -0
- package/dist/cron/persistence.js.map +1 -0
- package/dist/cron/service.d.ts +94 -0
- package/dist/cron/service.js +382 -0
- package/dist/cron/service.js.map +1 -0
- package/dist/cron/types.d.ts +119 -0
- package/dist/cron/types.js +3 -0
- package/dist/cron/types.js.map +1 -0
- package/dist/cron/validation.d.ts +144 -0
- package/dist/cron/validation.js +113 -0
- package/dist/cron/validation.js.map +1 -0
- package/dist/errors/__tests__/index.test.d.ts +1 -0
- package/dist/errors/__tests__/index.test.js +301 -0
- package/dist/errors/__tests__/index.test.js.map +1 -0
- package/dist/errors/index.d.ts +114 -0
- package/dist/errors/index.js +278 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/gateway/hono/app.d.ts +7 -0
- package/dist/gateway/hono/app.js +668 -0
- package/dist/gateway/hono/app.js.map +1 -0
- package/dist/gateway/hono/index.d.ts +2 -0
- package/dist/gateway/hono/index.js +3 -0
- package/dist/gateway/hono/index.js.map +1 -0
- package/dist/gateway/hono/middleware/auth.d.ts +18 -0
- package/dist/gateway/hono/middleware/auth.js +79 -0
- package/dist/gateway/hono/middleware/auth.js.map +1 -0
- package/dist/gateway/hono/middleware/logger.d.ts +1 -0
- package/dist/gateway/hono/middleware/logger.js +17 -0
- package/dist/gateway/hono/middleware/logger.js.map +1 -0
- package/dist/gateway/hono/sse.d.ts +55 -0
- package/dist/gateway/hono/sse.js +224 -0
- package/dist/gateway/hono/sse.js.map +1 -0
- package/dist/gateway/index.d.ts +4 -0
- package/dist/gateway/index.js +5 -0
- package/dist/gateway/index.js.map +1 -0
- package/dist/gateway/protocol.d.ts +28 -0
- package/dist/gateway/protocol.js +14 -0
- package/dist/gateway/protocol.js.map +1 -0
- package/dist/gateway/server.d.ts +19 -0
- package/dist/gateway/server.js +64 -0
- package/dist/gateway/server.js.map +1 -0
- package/dist/gateway/service.d.ts +265 -0
- package/dist/gateway/service.js +621 -0
- package/dist/gateway/service.js.map +1 -0
- package/dist/gateway/static/root/assets/main-CfIxL-cL.js +2105 -0
- package/dist/gateway/static/root/assets/main-CfIxL-cL.js.map +1 -0
- package/dist/gateway/static/root/assets/main-DndcTCgX.css +1 -0
- package/dist/gateway/static/root/index.html +116 -0
- package/dist/heartbeat/index.d.ts +1 -0
- package/dist/heartbeat/index.js +2 -0
- package/dist/heartbeat/index.js.map +1 -0
- package/dist/heartbeat/service.d.ts +19 -0
- package/dist/heartbeat/service.js +61 -0
- package/dist/heartbeat/service.js.map +1 -0
- package/dist/plugin-sdk/index.d.ts +21 -0
- package/dist/plugin-sdk/index.js +12 -0
- package/dist/plugin-sdk/index.js.map +1 -0
- package/dist/plugins/__tests__/api.test.d.ts +1 -0
- package/dist/plugins/__tests__/api.test.js +164 -0
- package/dist/plugins/__tests__/api.test.js.map +1 -0
- package/dist/plugins/__tests__/hooks.test.d.ts +1 -0
- package/dist/plugins/__tests__/hooks.test.js +159 -0
- package/dist/plugins/__tests__/hooks.test.js.map +1 -0
- package/dist/plugins/__tests__/loader.test.d.ts +1 -0
- package/dist/plugins/__tests__/loader.test.js +120 -0
- package/dist/plugins/__tests__/loader.test.js.map +1 -0
- package/dist/plugins/api.d.ts +41 -0
- package/dist/plugins/api.js +131 -0
- package/dist/plugins/api.js.map +1 -0
- package/dist/plugins/hooks.d.ts +153 -0
- package/dist/plugins/hooks.js +172 -0
- package/dist/plugins/hooks.js.map +1 -0
- package/dist/plugins/index.d.ts +11 -0
- package/dist/plugins/index.js +16 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/install.d.ts +59 -0
- package/dist/plugins/install.js +324 -0
- package/dist/plugins/install.js.map +1 -0
- package/dist/plugins/loader.d.ts +84 -0
- package/dist/plugins/loader.js +545 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/types.d.ts +190 -0
- package/dist/plugins/types.js +7 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/providers/__tests__/registry.test.d.ts +1 -0
- package/dist/providers/__tests__/registry.test.js +110 -0
- package/dist/providers/__tests__/registry.test.js.map +1 -0
- package/dist/providers/api-strategies.d.ts +15 -0
- package/dist/providers/api-strategies.js +96 -0
- package/dist/providers/api-strategies.js.map +1 -0
- package/dist/providers/auto-discovery.d.ts +84 -0
- package/dist/providers/auto-discovery.js +236 -0
- package/dist/providers/auto-discovery.js.map +1 -0
- package/dist/providers/config.d.ts +25 -0
- package/dist/providers/config.js +42 -0
- package/dist/providers/config.js.map +1 -0
- package/dist/providers/index.d.ts +25 -0
- package/dist/providers/index.js +55 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/model-catalog.d.ts +205 -0
- package/dist/providers/model-catalog.js +1071 -0
- package/dist/providers/model-catalog.js.map +1 -0
- package/dist/providers/models-dev-data.d.ts +11 -0
- package/dist/providers/models-dev-data.js +1035 -0
- package/dist/providers/models-dev-data.js.map +1 -0
- package/dist/providers/models-dev.d.ts +30 -0
- package/dist/providers/models-dev.js +42 -0
- package/dist/providers/models-dev.js.map +1 -0
- package/dist/providers/pi-ai.d.ts +62 -0
- package/dist/providers/pi-ai.js +221 -0
- package/dist/providers/pi-ai.js.map +1 -0
- package/dist/providers/provider-catalog.d.ts +173 -0
- package/dist/providers/provider-catalog.js +834 -0
- package/dist/providers/provider-catalog.js.map +1 -0
- package/dist/providers/registry.d.ts +155 -0
- package/dist/providers/registry.js +524 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/types.d.ts +95 -0
- package/dist/providers/types.js +7 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/chat-manager.d.ts +49 -0
- package/dist/session/chat-manager.js +167 -0
- package/dist/session/chat-manager.js.map +1 -0
- package/dist/session/chat-types.d.ts +53 -0
- package/dist/session/chat-types.js +63 -0
- package/dist/session/chat-types.js.map +1 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.js +5 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +103 -0
- package/dist/session/manager.js +200 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/store.d.ts +114 -0
- package/dist/session/store.js +687 -0
- package/dist/session/store.js.map +1 -0
- package/dist/session/types.d.ts +88 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/types/index.d.ts +177 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/providers.d.ts +67 -0
- package/dist/types/providers.js +7 -0
- package/dist/types/providers.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +17 -0
- package/dist/utils/frontmatter.js +104 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/helpers.d.ts +5 -0
- package/dist/utils/helpers.js +36 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/log-store.d.ts +78 -0
- package/dist/utils/log-store.js +432 -0
- package/dist/utils/log-store.js.map +1 -0
- package/dist/utils/logger.d.ts +127 -0
- package/dist/utils/logger.js +481 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/logger.types.d.ts +152 -0
- package/dist/utils/logger.types.js +30 -0
- package/dist/utils/logger.types.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
// Session store - manages session persistence, indexing, compaction, and sliding window
|
|
2
|
+
import { readFile, writeFile, mkdir, unlink, readdir, stat } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
import { createLogger } from '../utils/logger.js';
|
|
6
|
+
import { SessionStatus } from './types.js';
|
|
7
|
+
import { SessionCompactor } from '../agent/memory/compaction.js';
|
|
8
|
+
import { SlidingWindow } from '../agent/memory/window.js';
|
|
9
|
+
const log = createLogger('SessionStore');
|
|
10
|
+
const INDEX_VERSION = '1.0';
|
|
11
|
+
const DEFAULT_LIMIT = 50;
|
|
12
|
+
export class SessionStore {
|
|
13
|
+
baseDir;
|
|
14
|
+
sessionsDir;
|
|
15
|
+
archiveDir;
|
|
16
|
+
indexFile;
|
|
17
|
+
indexCache = null;
|
|
18
|
+
indexCacheTime = 0;
|
|
19
|
+
indexDirty = false;
|
|
20
|
+
window;
|
|
21
|
+
compactor;
|
|
22
|
+
constructor(workspace, windowConfig, compactionConfig) {
|
|
23
|
+
this.baseDir = workspace;
|
|
24
|
+
this.sessionsDir = join(workspace, '.sessions');
|
|
25
|
+
this.archiveDir = join(workspace, '.sessions', 'archive');
|
|
26
|
+
this.indexFile = join(workspace, '.sessions', 'index.json');
|
|
27
|
+
this.window = new SlidingWindow(windowConfig);
|
|
28
|
+
this.compactor = new SessionCompactor(compactionConfig);
|
|
29
|
+
}
|
|
30
|
+
// ========== Initialization ==========
|
|
31
|
+
async initialize() {
|
|
32
|
+
await mkdir(this.sessionsDir, { recursive: true });
|
|
33
|
+
await mkdir(this.archiveDir, { recursive: true });
|
|
34
|
+
if (!existsSync(this.indexFile)) {
|
|
35
|
+
await this.rebuildIndex();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
await this.loadIndex();
|
|
39
|
+
}
|
|
40
|
+
log.info('Session store initialized');
|
|
41
|
+
}
|
|
42
|
+
// ========== Index Management ==========
|
|
43
|
+
async loadIndex() {
|
|
44
|
+
try {
|
|
45
|
+
// Check if index file has been modified
|
|
46
|
+
const stats = await stat(this.indexFile);
|
|
47
|
+
const mtime = stats.mtime.getTime();
|
|
48
|
+
// If cache is valid and file hasn't changed, use cache
|
|
49
|
+
if (this.indexCache && mtime <= this.indexCacheTime) {
|
|
50
|
+
return this.indexCache;
|
|
51
|
+
}
|
|
52
|
+
// File has changed or cache is empty, reload
|
|
53
|
+
const data = await readFile(this.indexFile, 'utf-8');
|
|
54
|
+
this.indexCache = JSON.parse(data);
|
|
55
|
+
this.indexCacheTime = mtime;
|
|
56
|
+
return this.indexCache;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Index corrupted or missing, rebuild
|
|
60
|
+
return this.rebuildIndex();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Force refresh the index cache from disk
|
|
65
|
+
*/
|
|
66
|
+
async refreshIndex() {
|
|
67
|
+
this.indexCache = null;
|
|
68
|
+
this.indexCacheTime = 0;
|
|
69
|
+
await this.loadIndex();
|
|
70
|
+
}
|
|
71
|
+
async saveIndex() {
|
|
72
|
+
if (!this.indexCache)
|
|
73
|
+
return;
|
|
74
|
+
this.indexCache.lastUpdated = new Date().toISOString();
|
|
75
|
+
await writeFile(this.indexFile, JSON.stringify(this.indexCache, null, 2));
|
|
76
|
+
this.indexDirty = false;
|
|
77
|
+
// Update cache time after saving
|
|
78
|
+
try {
|
|
79
|
+
const stats = await stat(this.indexFile);
|
|
80
|
+
this.indexCacheTime = stats.mtime.getTime();
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
this.indexCacheTime = Date.now();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async rebuildIndex() {
|
|
87
|
+
log.info('Rebuilding session index...');
|
|
88
|
+
const sessions = [];
|
|
89
|
+
// Scan sessions directory
|
|
90
|
+
const files = await this.scanSessionFiles();
|
|
91
|
+
for (const file of files) {
|
|
92
|
+
if (file.endsWith('.json') && !file.endsWith('.meta.json')) {
|
|
93
|
+
const key = this.fileNameToKey(file.replace('.json', ''));
|
|
94
|
+
try {
|
|
95
|
+
const metadata = await this.scanSessionFile(key);
|
|
96
|
+
if (metadata) {
|
|
97
|
+
sessions.push(metadata);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
log.warn({ key, err }, 'Failed to scan session file');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
this.indexCache = {
|
|
106
|
+
version: INDEX_VERSION,
|
|
107
|
+
lastUpdated: new Date().toISOString(),
|
|
108
|
+
sessions,
|
|
109
|
+
};
|
|
110
|
+
await this.saveIndex();
|
|
111
|
+
// Update cache time after saving
|
|
112
|
+
try {
|
|
113
|
+
const stats = await stat(this.indexFile);
|
|
114
|
+
this.indexCacheTime = stats.mtime.getTime();
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
this.indexCacheTime = Date.now();
|
|
118
|
+
}
|
|
119
|
+
log.info({ count: sessions.length }, 'Session index rebuilt');
|
|
120
|
+
return this.indexCache;
|
|
121
|
+
}
|
|
122
|
+
async scanSessionFiles() {
|
|
123
|
+
try {
|
|
124
|
+
const files = await readdir(this.sessionsDir);
|
|
125
|
+
return files.filter((f) => f.endsWith('.json') && f !== 'index.json');
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async scanSessionFile(key) {
|
|
132
|
+
const messages = await this.loadMessages(key);
|
|
133
|
+
if (messages.length === 0)
|
|
134
|
+
return null;
|
|
135
|
+
const safeKey = this.sanitizeKey(key);
|
|
136
|
+
const filePath = join(this.sessionsDir, `${safeKey}.json`);
|
|
137
|
+
const stats = await stat(filePath);
|
|
138
|
+
const { channel, chatId } = this.parseSessionKey(key);
|
|
139
|
+
return {
|
|
140
|
+
key,
|
|
141
|
+
status: SessionStatus.ACTIVE,
|
|
142
|
+
tags: [],
|
|
143
|
+
createdAt: stats.birthtime.toISOString(),
|
|
144
|
+
updatedAt: stats.mtime.toISOString(),
|
|
145
|
+
lastAccessedAt: stats.mtime.toISOString(),
|
|
146
|
+
messageCount: messages.length,
|
|
147
|
+
estimatedTokens: this.estimateTokens(messages),
|
|
148
|
+
compactedCount: 0,
|
|
149
|
+
sourceChannel: channel,
|
|
150
|
+
sourceChatId: chatId,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// ========== CRUD Operations ==========
|
|
154
|
+
async list(query = {}) {
|
|
155
|
+
const index = await this.loadIndex();
|
|
156
|
+
let sessions = [...index.sessions];
|
|
157
|
+
// Apply filters
|
|
158
|
+
if (query.status) {
|
|
159
|
+
const statuses = Array.isArray(query.status) ? query.status : [query.status];
|
|
160
|
+
sessions = sessions.filter((s) => statuses.includes(s.status));
|
|
161
|
+
}
|
|
162
|
+
if (query.channel) {
|
|
163
|
+
sessions = sessions.filter((s) => s.sourceChannel === query.channel);
|
|
164
|
+
}
|
|
165
|
+
if (query.tags && query.tags.length > 0) {
|
|
166
|
+
sessions = sessions.filter((s) => query.tags.some((tag) => s.tags.includes(tag)));
|
|
167
|
+
}
|
|
168
|
+
if (query.search) {
|
|
169
|
+
const searchLower = query.search.toLowerCase();
|
|
170
|
+
sessions = sessions.filter((s) => s.key.toLowerCase().includes(searchLower) ||
|
|
171
|
+
s.name?.toLowerCase().includes(searchLower) ||
|
|
172
|
+
s.tags.some((t) => t.toLowerCase().includes(searchLower)));
|
|
173
|
+
}
|
|
174
|
+
// Apply sorting
|
|
175
|
+
const sortBy = query.sortBy || 'updatedAt';
|
|
176
|
+
const sortOrder = query.sortOrder || 'desc';
|
|
177
|
+
sessions.sort((a, b) => {
|
|
178
|
+
const aVal = a[sortBy];
|
|
179
|
+
const bVal = b[sortBy];
|
|
180
|
+
const comparison = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
181
|
+
return sortOrder === 'asc' ? comparison : -comparison;
|
|
182
|
+
});
|
|
183
|
+
// Apply pagination
|
|
184
|
+
const total = sessions.length;
|
|
185
|
+
const limit = query.limit || DEFAULT_LIMIT;
|
|
186
|
+
const offset = query.offset || 0;
|
|
187
|
+
const items = sessions.slice(offset, offset + limit);
|
|
188
|
+
return {
|
|
189
|
+
items,
|
|
190
|
+
total,
|
|
191
|
+
limit,
|
|
192
|
+
offset,
|
|
193
|
+
hasMore: offset + limit < total,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
async get(key) {
|
|
197
|
+
const metadata = await this.getMetadata(key);
|
|
198
|
+
if (!metadata)
|
|
199
|
+
return null;
|
|
200
|
+
const messages = await this.loadMessages(key);
|
|
201
|
+
return {
|
|
202
|
+
...metadata,
|
|
203
|
+
messages: this.convertMessages(messages),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async getMetadata(key) {
|
|
207
|
+
const index = await this.loadIndex();
|
|
208
|
+
const metadata = index.sessions.find((s) => s.key === key);
|
|
209
|
+
if (!metadata) {
|
|
210
|
+
// Try to load from file directly (orphaned session)
|
|
211
|
+
const scanned = await this.scanSessionFile(key);
|
|
212
|
+
if (scanned) {
|
|
213
|
+
index.sessions.push(scanned);
|
|
214
|
+
this.indexDirty = true;
|
|
215
|
+
return scanned;
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
return metadata;
|
|
220
|
+
}
|
|
221
|
+
async updateMetadata(key, updates) {
|
|
222
|
+
const index = await this.loadIndex();
|
|
223
|
+
const idx = index.sessions.findIndex((s) => s.key === key);
|
|
224
|
+
if (idx === -1) {
|
|
225
|
+
throw new Error(`Session not found: ${key}`);
|
|
226
|
+
}
|
|
227
|
+
index.sessions[idx] = {
|
|
228
|
+
...index.sessions[idx],
|
|
229
|
+
...updates,
|
|
230
|
+
updatedAt: new Date().toISOString(),
|
|
231
|
+
};
|
|
232
|
+
this.indexDirty = true;
|
|
233
|
+
await this.saveIndex();
|
|
234
|
+
log.debug({ key, updates }, 'Session metadata updated');
|
|
235
|
+
}
|
|
236
|
+
async delete(key) {
|
|
237
|
+
const index = await this.loadIndex();
|
|
238
|
+
const idx = index.sessions.findIndex((s) => s.key === key);
|
|
239
|
+
// Delete files
|
|
240
|
+
const safeKey = this.sanitizeKey(key);
|
|
241
|
+
const sessionPath = join(this.sessionsDir, `${safeKey}.json`);
|
|
242
|
+
const metaPath = join(this.sessionsDir, `${safeKey}.meta.json`);
|
|
243
|
+
try {
|
|
244
|
+
await unlink(sessionPath);
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
if (err.code !== 'ENOENT')
|
|
248
|
+
throw err;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
await unlink(metaPath);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
if (err.code !== 'ENOENT')
|
|
255
|
+
throw err;
|
|
256
|
+
}
|
|
257
|
+
// Remove from index
|
|
258
|
+
if (idx !== -1) {
|
|
259
|
+
index.sessions.splice(idx, 1);
|
|
260
|
+
this.indexDirty = true;
|
|
261
|
+
await this.saveIndex();
|
|
262
|
+
}
|
|
263
|
+
log.info({ key }, 'Session deleted');
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
async deleteMany(keys) {
|
|
267
|
+
const success = [];
|
|
268
|
+
const failed = [];
|
|
269
|
+
for (const key of keys) {
|
|
270
|
+
try {
|
|
271
|
+
await this.delete(key);
|
|
272
|
+
success.push(key);
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
failed.push(key);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return { success, failed };
|
|
279
|
+
}
|
|
280
|
+
// ========== Status Operations ==========
|
|
281
|
+
async setStatus(key, status) {
|
|
282
|
+
await this.updateMetadata(key, { status });
|
|
283
|
+
if (status === SessionStatus.ARCHIVED) {
|
|
284
|
+
await this.moveToArchive(key);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
await this.moveFromArchive(key);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async archive(key) {
|
|
291
|
+
await this.setStatus(key, SessionStatus.ARCHIVED);
|
|
292
|
+
}
|
|
293
|
+
async unarchive(key) {
|
|
294
|
+
await this.setStatus(key, SessionStatus.ACTIVE);
|
|
295
|
+
}
|
|
296
|
+
async pin(key) {
|
|
297
|
+
await this.setStatus(key, SessionStatus.PINNED);
|
|
298
|
+
}
|
|
299
|
+
async unpin(key) {
|
|
300
|
+
await this.setStatus(key, SessionStatus.ACTIVE);
|
|
301
|
+
}
|
|
302
|
+
// ========== Message Operations ==========
|
|
303
|
+
async loadMessages(key) {
|
|
304
|
+
const safeKey = this.sanitizeKey(key);
|
|
305
|
+
const path = join(this.sessionsDir, `${safeKey}.json`);
|
|
306
|
+
try {
|
|
307
|
+
const data = await readFile(path, 'utf-8');
|
|
308
|
+
return JSON.parse(data);
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
// Check archive - find the most recent archived file
|
|
312
|
+
const archivedFile = await this.findMostRecentArchive(safeKey);
|
|
313
|
+
if (!archivedFile) {
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
const data = await readFile(archivedFile, 'utf-8');
|
|
318
|
+
return JSON.parse(data);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return [];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Find the most recent archived session file for a given key.
|
|
327
|
+
* Archived files have format: {safeKey}.{timestamp}.json
|
|
328
|
+
*/
|
|
329
|
+
async findMostRecentArchive(safeKey) {
|
|
330
|
+
try {
|
|
331
|
+
const files = await readdir(this.archiveDir);
|
|
332
|
+
const matchingFiles = files
|
|
333
|
+
.filter((f) => f.startsWith(`${safeKey}.`) && f.endsWith('.json') && !f.endsWith('.meta.json'))
|
|
334
|
+
.sort()
|
|
335
|
+
.reverse();
|
|
336
|
+
if (matchingFiles.length === 0) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
return join(this.archiveDir, matchingFiles[0]);
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
async saveMessages(key, messages) {
|
|
346
|
+
const safeKey = this.sanitizeKey(key);
|
|
347
|
+
const path = join(this.sessionsDir, `${safeKey}.json`);
|
|
348
|
+
await mkdir(this.sessionsDir, { recursive: true });
|
|
349
|
+
await writeFile(path, JSON.stringify(messages, null, 2));
|
|
350
|
+
// Update or create metadata
|
|
351
|
+
const index = await this.loadIndex();
|
|
352
|
+
const existingIdx = index.sessions.findIndex((s) => s.key === key);
|
|
353
|
+
const now = new Date().toISOString();
|
|
354
|
+
const { channel, chatId } = this.parseSessionKey(key);
|
|
355
|
+
if (existingIdx !== -1) {
|
|
356
|
+
index.sessions[existingIdx] = {
|
|
357
|
+
...index.sessions[existingIdx],
|
|
358
|
+
messageCount: messages.length,
|
|
359
|
+
estimatedTokens: this.estimateTokens(messages),
|
|
360
|
+
updatedAt: now,
|
|
361
|
+
lastAccessedAt: now,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
index.sessions.push({
|
|
366
|
+
key,
|
|
367
|
+
status: SessionStatus.ACTIVE,
|
|
368
|
+
tags: [],
|
|
369
|
+
createdAt: now,
|
|
370
|
+
updatedAt: now,
|
|
371
|
+
lastAccessedAt: now,
|
|
372
|
+
messageCount: messages.length,
|
|
373
|
+
estimatedTokens: this.estimateTokens(messages),
|
|
374
|
+
compactedCount: 0,
|
|
375
|
+
sourceChannel: channel,
|
|
376
|
+
sourceChatId: chatId,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
this.indexDirty = true;
|
|
380
|
+
await this.saveIndex();
|
|
381
|
+
}
|
|
382
|
+
// ========== Sliding Window & Compaction ==========
|
|
383
|
+
/**
|
|
384
|
+
* Get window stats for messages
|
|
385
|
+
*/
|
|
386
|
+
getWindowStats(messages) {
|
|
387
|
+
return this.window.getStats(messages);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Check if session needs compaction
|
|
391
|
+
*/
|
|
392
|
+
needsCompaction(key, messages, contextWindow) {
|
|
393
|
+
return this.compactor.needsCompaction(messages, contextWindow);
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Prepare compaction (check if needed)
|
|
397
|
+
*/
|
|
398
|
+
prepareCompaction(key, messages, contextWindow) {
|
|
399
|
+
const result = this.compactor.needsCompaction(messages, contextWindow);
|
|
400
|
+
return {
|
|
401
|
+
needsCompaction: result.needed,
|
|
402
|
+
messages,
|
|
403
|
+
stats: result,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Apply compaction result to messages
|
|
408
|
+
*/
|
|
409
|
+
async applyCompaction(key, messages, result) {
|
|
410
|
+
const compacted = this.compactor.applyCompaction(messages, result);
|
|
411
|
+
const metadata = await this.getMetadata(key);
|
|
412
|
+
if (metadata) {
|
|
413
|
+
await this.updateMetadata(key, {
|
|
414
|
+
compactedCount: metadata.compactedCount + 1,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
log.info({
|
|
418
|
+
key,
|
|
419
|
+
tokensBefore: result.tokensBefore,
|
|
420
|
+
tokensAfter: result.tokensAfter,
|
|
421
|
+
keptMessages: compacted.length,
|
|
422
|
+
}, 'Session compacted');
|
|
423
|
+
return compacted;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Compact session with LLM summary
|
|
427
|
+
*/
|
|
428
|
+
async compact(key, messages, contextWindow, instructions) {
|
|
429
|
+
const result = await this.compactor.compact(messages, instructions);
|
|
430
|
+
if (result.compacted) {
|
|
431
|
+
await this.applyCompaction(key, messages, result);
|
|
432
|
+
}
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Get compaction stats for a session
|
|
437
|
+
*/
|
|
438
|
+
async getCompactionStats(key) {
|
|
439
|
+
const metadata = await this.getMetadata(key);
|
|
440
|
+
if (!metadata)
|
|
441
|
+
return undefined;
|
|
442
|
+
return {
|
|
443
|
+
compactionCount: metadata.compactedCount,
|
|
444
|
+
totalTokensBefore: 0,
|
|
445
|
+
totalTokensAfter: 0,
|
|
446
|
+
lastCompactionAt: undefined,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
// ========== MemoryStore API Aliases ==========
|
|
450
|
+
/** Alias for delete */
|
|
451
|
+
async deleteSession(key) {
|
|
452
|
+
return this.delete(key);
|
|
453
|
+
}
|
|
454
|
+
/** Alias for loadMessages */
|
|
455
|
+
async load(key) {
|
|
456
|
+
return this.loadMessages(key);
|
|
457
|
+
}
|
|
458
|
+
/** Alias for saveMessages */
|
|
459
|
+
async save(key, messages) {
|
|
460
|
+
return this.saveMessages(key, messages);
|
|
461
|
+
}
|
|
462
|
+
/** Alias for estimateTokens */
|
|
463
|
+
async estimateTokenUsage(key, messages) {
|
|
464
|
+
return this.estimateTokens(messages);
|
|
465
|
+
}
|
|
466
|
+
// ========== Search ==========
|
|
467
|
+
async searchInSession(key, keyword) {
|
|
468
|
+
const messages = await this.loadMessages(key);
|
|
469
|
+
const keywordLower = keyword.toLowerCase();
|
|
470
|
+
return this.convertMessages(messages.filter((m) => {
|
|
471
|
+
const content = this.extractTextContent(m.content);
|
|
472
|
+
return content.toLowerCase().includes(keywordLower);
|
|
473
|
+
}));
|
|
474
|
+
}
|
|
475
|
+
// ========== Export/Import ==========
|
|
476
|
+
async exportSession(key, format) {
|
|
477
|
+
const detail = await this.get(key);
|
|
478
|
+
if (!detail) {
|
|
479
|
+
throw new Error(`Session not found: ${key}`);
|
|
480
|
+
}
|
|
481
|
+
if (format === 'json') {
|
|
482
|
+
const exportData = {
|
|
483
|
+
version: INDEX_VERSION,
|
|
484
|
+
exportedAt: new Date().toISOString(),
|
|
485
|
+
metadata: detail,
|
|
486
|
+
messages: detail.messages,
|
|
487
|
+
};
|
|
488
|
+
return JSON.stringify(exportData, null, 2);
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
// Markdown format
|
|
492
|
+
const lines = [
|
|
493
|
+
`# ${detail.name || detail.key}`,
|
|
494
|
+
'',
|
|
495
|
+
`- **Channel:** ${detail.sourceChannel}`,
|
|
496
|
+
`- **Created:** ${detail.createdAt}`,
|
|
497
|
+
`- **Messages:** ${detail.messageCount}`,
|
|
498
|
+
`- **Tags:** ${detail.tags.join(', ') || 'none'}`,
|
|
499
|
+
'',
|
|
500
|
+
'---',
|
|
501
|
+
'',
|
|
502
|
+
];
|
|
503
|
+
for (const msg of detail.messages) {
|
|
504
|
+
const role = msg.role === 'assistant' ? 'Assistant' : msg.role === 'user' ? 'User' : msg.role;
|
|
505
|
+
lines.push(`## ${role}`);
|
|
506
|
+
lines.push('');
|
|
507
|
+
lines.push(msg.content);
|
|
508
|
+
lines.push('');
|
|
509
|
+
lines.push('---');
|
|
510
|
+
lines.push('');
|
|
511
|
+
}
|
|
512
|
+
return lines.join('\n');
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
// ========== Statistics ==========
|
|
516
|
+
async getStats() {
|
|
517
|
+
const index = await this.loadIndex();
|
|
518
|
+
const sessions = index.sessions;
|
|
519
|
+
const byChannel = {};
|
|
520
|
+
for (const s of sessions) {
|
|
521
|
+
byChannel[s.sourceChannel] = (byChannel[s.sourceChannel] || 0) + 1;
|
|
522
|
+
}
|
|
523
|
+
let oldestSession;
|
|
524
|
+
let newestSession;
|
|
525
|
+
if (sessions.length > 0) {
|
|
526
|
+
const sorted = [...sessions].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
527
|
+
oldestSession = sorted[0].createdAt;
|
|
528
|
+
newestSession = sorted[sorted.length - 1].createdAt;
|
|
529
|
+
}
|
|
530
|
+
return {
|
|
531
|
+
totalSessions: sessions.length,
|
|
532
|
+
activeSessions: sessions.filter((s) => s.status === SessionStatus.ACTIVE || s.status === SessionStatus.IDLE).length,
|
|
533
|
+
archivedSessions: sessions.filter((s) => s.status === SessionStatus.ARCHIVED).length,
|
|
534
|
+
pinnedSessions: sessions.filter((s) => s.status === SessionStatus.PINNED).length,
|
|
535
|
+
totalMessages: sessions.reduce((sum, s) => sum + s.messageCount, 0),
|
|
536
|
+
totalTokens: sessions.reduce((sum, s) => sum + s.estimatedTokens, 0),
|
|
537
|
+
oldestSession,
|
|
538
|
+
newestSession,
|
|
539
|
+
byChannel,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
// ========== Cleanup ==========
|
|
543
|
+
async archiveOld(olderThanDays) {
|
|
544
|
+
const cutoff = new Date();
|
|
545
|
+
cutoff.setDate(cutoff.getDate() - olderThanDays);
|
|
546
|
+
const index = await this.loadIndex();
|
|
547
|
+
let archived = 0;
|
|
548
|
+
for (const session of index.sessions) {
|
|
549
|
+
if (session.status !== SessionStatus.ARCHIVED && session.status !== SessionStatus.PINNED) {
|
|
550
|
+
const lastAccess = new Date(session.lastAccessedAt);
|
|
551
|
+
if (lastAccess < cutoff) {
|
|
552
|
+
await this.archive(session.key);
|
|
553
|
+
archived++;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return archived;
|
|
558
|
+
}
|
|
559
|
+
// ========== Helper Methods ==========
|
|
560
|
+
sanitizeKey(key) {
|
|
561
|
+
return key.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
562
|
+
}
|
|
563
|
+
fileNameToKey(fileName) {
|
|
564
|
+
// Reverse of sanitizeKey - try to restore original format
|
|
565
|
+
// telegram_123456 -> telegram:123456
|
|
566
|
+
return fileName.replace(/^([^_]+)_(.+)$/, '$1:$2');
|
|
567
|
+
}
|
|
568
|
+
parseSessionKey(key) {
|
|
569
|
+
const parts = key.split(':');
|
|
570
|
+
if (parts.length >= 2) {
|
|
571
|
+
return { channel: parts[0], chatId: parts.slice(1).join(':') };
|
|
572
|
+
}
|
|
573
|
+
return { channel: 'unknown', chatId: key };
|
|
574
|
+
}
|
|
575
|
+
estimateTokens(messages) {
|
|
576
|
+
// Rough estimate: 1 token ≈ 4 characters
|
|
577
|
+
let total = 0;
|
|
578
|
+
for (const msg of messages) {
|
|
579
|
+
const text = this.extractTextContent(msg.content);
|
|
580
|
+
total += Math.ceil(text.length / 4);
|
|
581
|
+
}
|
|
582
|
+
return total;
|
|
583
|
+
}
|
|
584
|
+
extractTextContent(content) {
|
|
585
|
+
if (typeof content === 'string')
|
|
586
|
+
return content;
|
|
587
|
+
if (Array.isArray(content)) {
|
|
588
|
+
return content
|
|
589
|
+
.filter((c) => typeof c === 'object' && c !== null && 'type' in c && c.type === 'text')
|
|
590
|
+
.map((c) => c.text || '')
|
|
591
|
+
.join('');
|
|
592
|
+
}
|
|
593
|
+
return '';
|
|
594
|
+
}
|
|
595
|
+
convertMessages(messages) {
|
|
596
|
+
return messages.map((m) => ({
|
|
597
|
+
role: m.role,
|
|
598
|
+
content: typeof m.content === 'string' ? m.content : this.extractTextContent(m.content),
|
|
599
|
+
timestamp: m.timestamp ? new Date(m.timestamp).toISOString() : undefined,
|
|
600
|
+
tool_call_id: m.tool_call_id || m.toolCallId,
|
|
601
|
+
tool_calls: m.tool_calls,
|
|
602
|
+
name: m.name,
|
|
603
|
+
}));
|
|
604
|
+
}
|
|
605
|
+
async moveToArchive(key) {
|
|
606
|
+
const safeKey = this.sanitizeKey(key);
|
|
607
|
+
const sourcePath = join(this.sessionsDir, `${safeKey}.json`);
|
|
608
|
+
// Use timestamped filename to avoid overwriting previous archives
|
|
609
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
610
|
+
const targetPath = join(this.archiveDir, `${safeKey}.${timestamp}.json`);
|
|
611
|
+
try {
|
|
612
|
+
const data = await readFile(sourcePath, 'utf-8');
|
|
613
|
+
await writeFile(targetPath, data);
|
|
614
|
+
await unlink(sourcePath);
|
|
615
|
+
// Move meta file if exists
|
|
616
|
+
const metaSource = join(this.sessionsDir, `${safeKey}.meta.json`);
|
|
617
|
+
const metaTarget = join(this.archiveDir, `${safeKey}.${timestamp}.meta.json`);
|
|
618
|
+
try {
|
|
619
|
+
const metaData = await readFile(metaSource, 'utf-8');
|
|
620
|
+
await writeFile(metaTarget, metaData);
|
|
621
|
+
await unlink(metaSource);
|
|
622
|
+
}
|
|
623
|
+
catch {
|
|
624
|
+
// Meta file might not exist
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
catch (err) {
|
|
628
|
+
if (err.code !== 'ENOENT')
|
|
629
|
+
throw err;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
async moveFromArchive(key) {
|
|
633
|
+
const safeKey = this.sanitizeKey(key);
|
|
634
|
+
const sourcePath = await this.findMostRecentArchive(safeKey);
|
|
635
|
+
if (!sourcePath) {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
const targetPath = join(this.sessionsDir, `${safeKey}.json`);
|
|
639
|
+
try {
|
|
640
|
+
const data = await readFile(sourcePath, 'utf-8');
|
|
641
|
+
await writeFile(targetPath, data);
|
|
642
|
+
await unlink(sourcePath);
|
|
643
|
+
// Move meta file if exists (find the corresponding meta file)
|
|
644
|
+
const metaSource = sourcePath.replace('.json', '.meta.json');
|
|
645
|
+
const metaTarget = join(this.sessionsDir, `${safeKey}.meta.json`);
|
|
646
|
+
try {
|
|
647
|
+
const metaData = await readFile(metaSource, 'utf-8');
|
|
648
|
+
await writeFile(metaTarget, metaData);
|
|
649
|
+
await unlink(metaSource);
|
|
650
|
+
}
|
|
651
|
+
catch {
|
|
652
|
+
// Meta file might not exist
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
catch (err) {
|
|
656
|
+
if (err.code !== 'ENOENT')
|
|
657
|
+
throw err;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
// ========== Legacy Compatibility ==========
|
|
661
|
+
async migrateFromLegacy() {
|
|
662
|
+
// Migrate old .sessions/*.json files without index
|
|
663
|
+
const files = await this.scanSessionFiles();
|
|
664
|
+
let migrated = 0;
|
|
665
|
+
for (const file of files) {
|
|
666
|
+
if (file.endsWith('.json') && !file.endsWith('.meta.json')) {
|
|
667
|
+
const key = this.fileNameToKey(file.replace('.json', ''));
|
|
668
|
+
const metadata = await this.getMetadata(key);
|
|
669
|
+
if (!metadata) {
|
|
670
|
+
const scanned = await this.scanSessionFile(key);
|
|
671
|
+
if (scanned) {
|
|
672
|
+
const index = await this.loadIndex();
|
|
673
|
+
index.sessions.push(scanned);
|
|
674
|
+
migrated++;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (migrated > 0) {
|
|
680
|
+
this.indexDirty = true;
|
|
681
|
+
await this.saveIndex();
|
|
682
|
+
}
|
|
683
|
+
log.info({ migrated }, 'Migrated legacy sessions');
|
|
684
|
+
return migrated;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
//# sourceMappingURL=store.js.map
|