@xopcai/xopc 0.0.30 → 0.0.31
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/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/agents-3u63Fw2Y.js +216 -0
- package/dist/gateway/static/root/assets/agents-3u63Fw2Y.js.map +1 -0
- package/dist/gateway/static/root/assets/{apps-page-CTChHQAu.js → apps-page-CWegY6Kp.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-CTChHQAu.js.map → apps-page-CWegY6Kp.js.map} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CiyeXcTK.js +9 -0
- package/dist/gateway/static/root/assets/channels-settings-CiyeXcTK.js.map +1 -0
- package/dist/gateway/static/root/assets/cron-api-_j_79Zf5.js +3 -0
- package/dist/gateway/static/root/assets/cron-api-_j_79Zf5.js.map +1 -0
- package/dist/gateway/static/root/assets/cron-page-S86YNTtI.js +2 -0
- package/dist/gateway/static/root/assets/cron-page-S86YNTtI.js.map +1 -0
- package/dist/gateway/static/root/assets/dist-D0jxbvuz.js +2 -0
- package/dist/gateway/static/root/assets/{dist-UWGUW3x8.js.map → dist-D0jxbvuz.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BwB4a4cK.js → extension-debug-page-DB630cW8.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-BwB4a4cK.js.map → extension-debug-page-DB630cW8.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CSWu2PHZ.js → extension-page-CnoPUBul.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-CSWu2PHZ.js.map → extension-page-CnoPUBul.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-B12K2a13.js → extension-settings-page-BsiOkvBe.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-B12K2a13.js.map → extension-settings-page-BsiOkvBe.js.map} +1 -1
- package/dist/gateway/static/root/assets/{index-D0pFZ0OE.js → index-DHLmAIQl.js} +81 -81
- package/dist/gateway/static/root/assets/{index-D0pFZ0OE.js.map → index-DHLmAIQl.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-DoPwy4aU.css +1 -0
- package/dist/gateway/static/root/assets/logs-page-Bndhenn2.js +2 -0
- package/dist/gateway/static/root/assets/logs-page-Bndhenn2.js.map +1 -0
- package/dist/gateway/static/root/assets/sessions-page-Q201-_lP.js +2 -0
- package/dist/gateway/static/root/assets/{sessions-page-DJkuWpOT.js.map → sessions-page-Q201-_lP.js.map} +1 -1
- package/dist/gateway/static/root/assets/settings-page-Cw75fpc6.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-Cw75fpc6.js.map +1 -0
- package/dist/gateway/static/root/assets/skills-page-CVwEzD_J.js +3 -0
- package/dist/gateway/static/root/assets/skills-page-CVwEzD_J.js.map +1 -0
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +12 -1
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +4 -0
- package/dist/src/agent/service.js +7 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/skills/marketplace/resolve-adapter.js +1 -1
- package/dist/src/agent/skills/marketplace/resolve-adapter.js.map +1 -1
- package/dist/src/config/schema.js +1 -0
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/cron/validation.js +1 -1
- package/dist/src/cron/validation.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +124 -2
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/sse.js +9 -2
- package/dist/src/gateway/hono/sse.js.map +1 -1
- package/dist/src/gateway/service/run-gateway-agent.d.ts +1 -0
- package/dist/src/gateway/service/run-gateway-agent.js +18 -10
- package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
- package/dist/src/gateway/service.d.ts +23 -1
- package/dist/src/gateway/service.js +47 -3
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/session/abort-cutoff.d.ts +6 -0
- package/dist/src/session/abort-cutoff.js +10 -0
- package/dist/src/session/abort-cutoff.js.map +1 -0
- package/dist/src/session/compaction-checkpoints.d.ts +8 -0
- package/dist/src/session/compaction-checkpoints.js +21 -0
- package/dist/src/session/compaction-checkpoints.js.map +1 -0
- package/dist/src/session/index.d.ts +8 -1
- package/dist/src/session/index.js +7 -1
- package/dist/src/session/manager.d.ts +26 -1
- package/dist/src/session/manager.js +39 -2
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/patch-metadata.d.ts +12 -0
- package/dist/src/session/patch-metadata.js +23 -0
- package/dist/src/session/patch-metadata.js.map +1 -0
- package/dist/src/session/search-index.d.ts +2 -0
- package/dist/src/session/search-index.js +30 -2
- package/dist/src/session/search-index.js.map +1 -1
- package/dist/src/session/session-context-for-llm.d.ts +32 -0
- package/dist/src/session/session-context-for-llm.js +60 -0
- package/dist/src/session/session-context-for-llm.js.map +1 -0
- package/dist/src/session/store.d.ts +36 -2
- package/dist/src/session/store.js +200 -28
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/strip-webchat-early-save.d.ts +5 -0
- package/dist/src/session/strip-webchat-early-save.js +17 -0
- package/dist/src/session/strip-webchat-early-save.js.map +1 -0
- package/dist/src/session/transcript-format.d.ts +46 -0
- package/dist/src/session/transcript-format.js +88 -0
- package/dist/src/session/transcript-format.js.map +1 -0
- package/dist/src/session/types.d.ts +37 -0
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/utils/logger/log-store.js +4 -3
- package/dist/src/utils/logger/log-store.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-BfwtJOPK.js +0 -216
- package/dist/gateway/static/root/assets/agents-BfwtJOPK.js.map +0 -1
- package/dist/gateway/static/root/assets/channels-settings-BpwVOvvf.js +0 -9
- package/dist/gateway/static/root/assets/channels-settings-BpwVOvvf.js.map +0 -1
- package/dist/gateway/static/root/assets/cron-page-C_6AbVRf.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-C_6AbVRf.js.map +0 -1
- package/dist/gateway/static/root/assets/cron-utils-DZ7pabh5.js +0 -3
- package/dist/gateway/static/root/assets/cron-utils-DZ7pabh5.js.map +0 -1
- package/dist/gateway/static/root/assets/dist-UWGUW3x8.js +0 -2
- package/dist/gateway/static/root/assets/index-C6itMrqR.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-BXqha2gI.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-BXqha2gI.js.map +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DJkuWpOT.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-CleZrGHy.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-CleZrGHy.js.map +0 -1
- package/dist/gateway/static/root/assets/skills-page-D7NiIOzA.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-D7NiIOzA.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":[],"sources":["../../../src/config/schema.ts"],"sourcesContent":["import { z } from 'zod';\n\nimport { getDefaultWorkspacePath } from '../agent/agent-scope.js';\n\n// ============================================\n// Agent Configs\n// ============================================\n\nexport const AgentModelRefSchema = z.union([\n z.string(),\n z\n .object({\n primary: z.string().optional(),\n fallbacks: z.array(z.string()).optional(),\n })\n .strict(),\n]);\n\nexport type AgentModelConfig = z.infer<typeof AgentModelRefSchema>;\n\nexport const AgentDefaultsSchema = z.object({\n /** Parent directory: each agent’s Markdown root is `<expanded>/<agentId>/` (e.g. `.../workspace/main`). */\n workspace: z.string().default('~/.xopc/workspace'),\n model: z.union([\n z.string(),\n z.object({\n primary: z.string().optional(),\n fallbacks: z.array(z.string()).optional(),\n }).strict(),\n ]).default(''), // Empty default - will be resolved dynamically at runtime\n /** Vision / image understanding model (provider/model). Falls back to heuristics when unset. */\n imageModel: AgentModelRefSchema.optional(),\n /** Image generation model (provider/model), e.g. openai/gpt-image-1. Thin REST wrapper; OpenAI supported. */\n imageGenerationModel: AgentModelRefSchema.optional(),\n /** Max image size for image tool loads (MB). */\n mediaMaxMb: z.number().positive().optional(),\n maxTokens: z.number().default(8192),\n temperature: z.number().default(0.7),\n maxToolIterations: z.number().default(20),\n // Wall-clock limit for one user turn (LLM + tools). Default 30m if unset; cap 4h.\n maxTaskDurationMs: z.number().min(60000).max(14_400_000).optional(),\n // Reliability settings\n maxRequestsPerTurn: z.number().min(10).max(200).default(50),\n maxToolFailuresPerTurn: z.number().min(1).max(20).default(3),\n // Thinking ability settings\n thinkingDefault: z.enum(['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'adaptive']).optional(),\n reasoningDefault: z.enum(['off', 'on', 'stream']).optional(),\n verboseDefault: z.enum(['off', 'on', 'full']).optional(),\n compaction: z.object({\n enabled: z.boolean().default(true),\n mode: z.enum(['default', 'safeguard']).default('default'),\n reserveTokens: z.number().default(8000),\n triggerThreshold: z.number().min(0.5).max(0.95).default(0.8),\n minMessagesBeforeCompact: z.number().default(10),\n keepRecentMessages: z.number().default(5),\n // Dual-strategy compaction\n evictionWindow: z.number().min(0.1).max(0.5).default(0.2),\n retentionWindow: z.number().min(3).max(20).default(6),\n }).optional(),\n pruning: z.object({\n enabled: z.boolean().default(true),\n maxToolResultChars: z.number().default(10000),\n headKeepRatio: z.number().default(0.3),\n tailKeepRatio: z.number().default(0.3),\n }).optional(),\n /**\n * Curated memory (`agents/<id>/memories/`) + pluggable external provider.\n * Only one external provider at a time.\n */\n memory: z\n .object({\n /** Master switch: curated snapshot, `curated_memory`, prefetch, and external provider. Default true. */\n enabled: z.boolean().optional(),\n /** When false, use workspace bootstrap only (no curated snapshot / tool). Default true. */\n useEnhancedSystem: z.boolean().optional(),\n /** Include USER.md in snapshot. Default true. */\n userProfileEnabled: z.boolean().optional(),\n memoryCharLimit: z.number().positive().optional(),\n userCharLimit: z.number().positive().optional(),\n provider: z.enum(['none', 'stub']).optional(),\n /** How often prefetched external memory is injected into the user message. */\n injectionFrequency: z.enum(['every-turn', 'first-turn']).optional(),\n /** Inject prefetch on turns 1, 1+N, 1+2N, … (only when injectionFrequency is every-turn). Min 1. */\n contextCadence: z.number().int().min(1).optional(),\n /** Reserved for future external “dialectic” sync cadence (not wired yet). */\n dialecticCadence: z.number().int().min(1).optional(),\n /**\n * Background memory consolidation (\"dreaming\"): three-phase sleep model that\n * promotes short-term recall signals into long-term memory (`MEMORY.md`).\n *\n * Phases:\n * - **light** — fast, frequent sweep (default every 6 h): dedup + signal collection.\n * - **deep** — daily deep promotion (default 3 AM): score-gated write to MEMORY.md.\n * - **rem** — weekly pattern discovery (default Sun 5 AM): cross-session insight mining.\n */\n dreaming: z\n .object({\n enabled: z.boolean().optional(),\n /** Default deep-phase cron when `phases.deep.cron` is omitted. */\n frequency: z.string().optional(),\n timezone: z.string().optional(),\n phases: z\n .object({\n light: z\n .object({\n enabled: z.boolean().optional(),\n cron: z.string().optional(),\n lookbackDays: z.number().int().min(1).optional(),\n limit: z.number().int().min(0).optional(),\n dedupeSimilarity: z.number().min(0).max(1).optional(),\n })\n .optional(),\n deep: z\n .object({\n enabled: z.boolean().optional(),\n cron: z.string().optional(),\n minScore: z.number().min(0).max(1).optional(),\n minRecallCount: z.number().int().min(1).optional(),\n minUniqueQueries: z.number().int().min(1).optional(),\n limit: z.number().int().min(0).optional(),\n recencyHalfLifeDays: z.number().min(1).optional(),\n maxAgeDays: z.number().int().min(1).optional(),\n })\n .optional(),\n rem: z\n .object({\n enabled: z.boolean().optional(),\n cron: z.string().optional(),\n lookbackDays: z.number().int().min(1).optional(),\n limit: z.number().int().min(0).optional(),\n minPatternStrength: z.number().min(0).max(1).optional(),\n })\n .optional(),\n })\n .optional(),\n })\n .optional(),\n })\n .optional(),\n /** Cross-session transcript search (`session_search` tool). */\n sessionSearch: z\n .object({\n /** Model ref for per-session summaries (e.g. openai/gpt-4o-mini). */\n summaryModel: z.string().optional(),\n })\n .optional(),\n /**\n * Post-turn background review (Hermes-style): optional quiet follow-up that may call\n * `curated_memory` / `skill_manage` so durable facts and reusable workflows persist\n * without bloating the main user-visible turn.\n */\n backgroundReview: z\n .object({\n /** When true, nudges may run after successful turns. Default false (opt-in). */\n enabled: z.boolean().optional(),\n /** User-turn cadence for memory review. 0 disables the memory channel. Default 10. */\n memoryNudgeInterval: z.number().int().min(0).optional(),\n /** LLM rounds without `skill_manage` before a skill review. 0 disables the skill channel. Default 10. */\n skillNudgeInterval: z.number().int().min(0).optional(),\n /** Max tool executions for the review agent. Default 8. */\n maxToolRounds: z.number().int().min(1).max(32).optional(),\n /** Max prior messages passed into the review context (tail). Default 80. */\n maxHistoryMessages: z.number().int().min(10).max(200).optional(),\n /** Wall-clock cap for the review run (ms). Default 120000. */\n maxDurationMs: z.number().int().min(30_000).max(600_000).optional(),\n })\n .optional(),\n /** LLM pass for `web_extract` (markdown-focused extraction). */\n webExtract: z\n .object({\n model: z.string().optional(),\n maxLength: z.number().positive().optional(),\n })\n .optional(),\n /**\n * Headless Playwright tools (`browser_*`). Opt-in. Install browsers once: `npx playwright install chromium`.\n */\n browser: z\n .object({\n enabled: z.boolean().optional(),\n /** Default true when browser tools are enabled. */\n headless: z.boolean().optional(),\n })\n .optional(),\n /** Sub-agent delegation (`delegate_task`). Opt-in. */\n delegate: z\n .object({\n enabled: z.boolean().optional(),\n })\n .optional(),\n /** Sandboxed `execute_code` (programmatic tool calls). Opt-in. */\n executeCode: z\n .object({\n enabled: z.boolean().optional(),\n })\n .optional(),\n /** Optional full system prompt replacement (merged with per-agent entry; entry wins). */\n systemPromptOverride: z.string().optional(),\n /** Optional allowlist of skill names for `<available_skills>`; when set, replaces unfiltered list. */\n skills: z.array(z.string()).optional(),\n /** Disable built-in tools by name (e.g. `shell`, `web_search`). */\n tools: z\n .object({\n disable: z.array(z.string()).optional(),\n })\n .optional(),\n /** Opaque per-process params (reserved for extensions / future use). */\n params: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const AgentConfigSchema = z.object({\n id: z.string(),\n /** When true, this entry is the default routing agent. */\n default: z.boolean().optional(),\n name: z.string().optional(),\n /** Short human-readable summary for UIs (gateway console, pickers). */\n description: z.string().max(4000).optional(),\n enabled: z.boolean().default(true),\n /** Per-agent workspace root (`~` expanded at runtime). */\n workspace: z.string().optional(),\n /**\n * Internal agent state directory (`…/credentials`, `agent.json`, pid, inbox).\n * Default: `<stateDir>/agents/<id>/agent`.\n */\n agentDir: z.string().optional(),\n model: AgentModelRefSchema.optional(),\n thinkingDefault: z.enum(['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'adaptive']).optional(),\n reasoningDefault: z.enum(['off', 'on', 'stream']).optional(),\n verboseDefault: z.enum(['off', 'on', 'full']).optional(),\n systemPromptOverride: z.string().optional(),\n skills: z.array(z.string()).optional(),\n tools: z\n .object({\n disable: z.array(z.string()).optional(),\n })\n .optional(),\n params: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const AgentsConfigSchema = z.object({\n /** Default agent id when not specified (routing / session creation). */\n default: z.string().optional(),\n defaults: AgentDefaultsSchema.optional(),\n list: z.array(AgentConfigSchema).optional(),\n}).default({\n defaults: {\n workspace: '~/.xopc/workspace',\n model: '', // Empty default - will be resolved dynamically at runtime\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n thinkingDefault: 'medium',\n reasoningDefault: 'stream',\n verboseDefault: 'full',\n compaction: {\n enabled: true,\n mode: 'default',\n reserveTokens: 8000,\n triggerThreshold: 0.8,\n minMessagesBeforeCompact: 10,\n keepRecentMessages: 5,\n evictionWindow: 0.2,\n retentionWindow: 6,\n },\n pruning: {\n enabled: true,\n maxToolResultChars: 10000,\n headKeepRatio: 0.3,\n tailKeepRatio: 0.3,\n },\n },\n} as any);\n\n// ============================================\n// Channel Configs (per-channel Zod lives in bundled extensions; root schema is open)\n// ============================================\n\nexport {\n TelegramTopicConfigSchema,\n TelegramGroupConfigSchema,\n TelegramAccountConfigSchema,\n TelegramConfigSchema,\n} from '../../extensions/telegram/src/config-schema.js';\nexport type { TelegramConfig } from '../../extensions/telegram/src/config-schema.js';\nexport { WeixinAccountConfigSchema, WeixinConfigSchema } from '../../extensions/weixin/src/config-schema.js';\nexport type { WeixinConfig } from '../../extensions/weixin/src/config-schema.js';\n\n// ============================================\n// Session Routing Configuration\n// ============================================\n\nexport const BindingMatchSchema = z.object({\n channel: z.string(),\n accountId: z.string().optional(),\n peerKind: z.string().optional(),\n peerId: z.string().optional(),\n guildId: z.string().optional(),\n teamId: z.string().optional(),\n memberRoleIds: z.array(z.string()).optional(),\n});\n\nexport const BindingRuleSchema = z.object({\n id: z.string().optional(),\n agentId: z.string(),\n priority: z.number().default(100),\n match: BindingMatchSchema,\n enabled: z.boolean().default(true),\n});\n\nexport const BindingsConfigSchema = z.array(BindingRuleSchema).default([]);\n\nexport const SessionDmScopeSchema = z.enum([\n 'main',\n 'per-peer',\n 'per-channel-peer',\n 'per-account-channel-peer',\n]);\n\nexport const SessionStorageConfigSchema = z.object({\n pruneAfterMs: z.number().optional(),\n maxEntries: z.number().optional(),\n});\n\nexport const SessionConfigSchema = z.object({\n dmScope: SessionDmScopeSchema.default('main'),\n identityLinks: z.record(z.string(), z.array(z.string())).optional(),\n storage: SessionStorageConfigSchema.optional(),\n}).default({\n dmScope: 'main',\n});\n\n/** Channel buckets — shapes validated post-parse by registered channel plugins. */\nexport const ChannelsConfigSchema = z.record(z.string(), z.unknown()).default({\n telegram: {\n enabled: false,\n allowFrom: [],\n groupAllowFrom: [],\n debug: false,\n accounts: {\n default: {\n accountId: 'default',\n enabled: true,\n botToken: '',\n allowFrom: [],\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n streamMode: 'partial' as const,\n },\n },\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n },\n});\n\nexport const SearchProviderEntrySchema = z.object({\n type: z.enum(['brave', 'tavily', 'bing', 'searxng']),\n apiKey: z.string().optional(),\n /** SearXNG instance base URL (e.g. http://localhost:8080) */\n url: z.string().optional(),\n disabled: z.boolean().optional(),\n});\n\nexport type SearchProviderEntry = z.infer<typeof SearchProviderEntrySchema>;\n\nexport const WebSearchConfigSchema = z.object({\n maxResults: z.number().default(5),\n /** Ordered API providers; empty → HTML fallback only */\n providers: z.array(SearchProviderEntrySchema).default([]),\n});\n\nexport type WebSearchConfig = z.infer<typeof WebSearchConfigSchema>;\n\nexport const WebToolsConfigSchema = z.object({\n /** Search result HTML fallback: cn → Bing, otherwise DuckDuckGo */\n region: z.enum(['cn', 'global']).optional(),\n search: WebSearchConfigSchema.optional(),\n});\n\nexport type WebToolsConfig = z.infer<typeof WebToolsConfigSchema>;\n\nexport const ToolsConfigSchema = z.object({\n web: WebToolsConfigSchema.optional(),\n}).default({\n web: {\n search: {\n maxResults: 5,\n providers: [],\n },\n },\n});\n\n// ============================================\n// Gateway Configuration\n// ============================================\n\nexport const GatewayAuthRateLimitSchema = z\n .object({\n enabled: z.boolean().default(true),\n maxAttempts: z.number().int().min(1).default(5),\n windowMs: z.number().default(900_000),\n blockDurationMs: z.number().default(300_000),\n })\n .optional();\n\nexport const GatewayAuthSchema = z\n .object({\n mode: z.enum(['none', 'token', 'password']).default('token'),\n token: z.string().optional(),\n password: z.string().optional(),\n rateLimit: GatewayAuthRateLimitSchema,\n })\n .default({\n mode: 'token',\n });\n\nexport const HeartbeatConfigSchema = z\n .object({\n enabled: z.boolean(),\n intervalMs: z.number(),\n /** When false, heartbeat instructions are only sent during heartbeat polling turns (not in every chat system prompt). */\n includeSystemPromptSection: z.boolean().optional().default(false),\n target: z.string().optional(),\n targetChatId: z.string().optional(),\n prompt: z.string().optional(),\n ackMaxChars: z.number().optional(),\n isolatedSession: z.boolean().optional(),\n activeHours: z\n .object({\n start: z.string(),\n end: z.string(),\n timezone: z.string().optional(),\n })\n .optional(),\n })\n .default({\n enabled: true,\n intervalMs: 1_800_000,\n includeSystemPromptSection: false,\n });\n\nexport const GatewayConfigSchema = z.object({\n host: z.string().optional(),\n port: z.number().optional(),\n auth: GatewayAuthSchema.optional(),\n heartbeat: HeartbeatConfigSchema.optional(),\n maxSseConnections: z.number().optional(),\n corsOrigins: z.array(z.string()).optional(),\n /** Skills marketplace provider: `store` (store.xopc.ai) or `skillhub` (skillhub.cn). */\n skillsMarketplaceProvider: z.enum(['store', 'skillhub']).optional(),\n /** Base URL for the xopc skills marketplace (public REST API). */\n skillsStoreBaseUrl: z.string().url().optional(),\n}).default({\n host: '127.0.0.1',\n port: 18790,\n auth: {\n mode: 'token',\n },\n heartbeat: {\n enabled: true,\n intervalMs: 1_800_000,\n includeSystemPromptSection: false,\n },\n maxSseConnections: 100,\n corsOrigins: [],\n skillsMarketplaceProvider: 'skillhub',\n skillsStoreBaseUrl: 'https://store.xopc.ai',\n});\n\nexport const CronConfigSchema = z.object({\n enabled: z.boolean().optional(),\n maxConcurrentJobs: z.number().optional(),\n defaultTimezone: z.string().optional(),\n historyRetentionDays: z.number().optional(),\n enableMetrics: z.boolean().optional(),\n}).default({\n enabled: true,\n maxConcurrentJobs: 5,\n defaultTimezone: 'UTC',\n historyRetentionDays: 7,\n enableMetrics: true,\n});\n\nexport const ModelsDevConfigSchema = z.object({\n enabled: z.boolean().default(true),\n}).default({\n enabled: true,\n});\n\n// ============================================\n// STT (Speech-to-Text) Config\n// ============================================\n\nexport const STTProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n model: z.string().optional(),\n});\n\nexport const STTFallbackConfigSchema = z.object({\n enabled: z.boolean().default(true),\n order: z.array(z.enum(['alibaba', 'openai'])).default(['alibaba', 'openai']),\n});\n\nexport const STTConfigSchema = z.object({\n enabled: z.boolean().default(false),\n provider: z.enum(['alibaba', 'openai']).default('alibaba'),\n alibaba: STTProviderConfigSchema.optional(),\n openai: STTProviderConfigSchema.optional(),\n fallback: STTFallbackConfigSchema.optional(),\n});\n\n// ============================================\n// TTS (Text-to-Speech) Config\n// ============================================\n\nexport const TTSProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n model: z.string().optional(),\n voice: z.string().optional(),\n});\n\nexport const TTSFallbackConfigSchema = z.object({\n enabled: z.boolean().default(true),\n order: z\n .array(z.enum(['openai', 'alibaba', 'edge', 'minimax']))\n .default(['openai', 'alibaba', 'minimax', 'edge']),\n});\n\nexport const TTSModelOverridesConfigSchema = z.object({\n enabled: z.boolean().default(true),\n allowText: z.boolean().default(true),\n allowProvider: z.boolean().default(false),\n allowVoice: z.boolean().default(true),\n allowModelId: z.boolean().default(true),\n allowVoiceSettings: z.boolean().default(false),\n allowNormalization: z.boolean().default(false),\n allowSeed: z.boolean().default(false),\n});\n\nexport const TTSEdgeConfigSchema = z.object({\n enabled: z.boolean().default(true),\n voice: z.string().optional(),\n lang: z.string().optional(),\n outputFormat: z.string().optional(),\n pitch: z.string().optional(),\n rate: z.string().optional(),\n volume: z.string().optional(),\n proxy: z.string().optional(),\n timeoutMs: z.number().int().min(1000).max(120000).optional(),\n});\n\nexport const TTSSummarizationConfigSchema = z.object({\n enabled: z.boolean().optional(),\n targetLength: z.number().int().min(1).optional(),\n threshold: z.number().int().min(1).optional(),\n model: z.string().optional(),\n});\n\nexport const TTSConfigSchema = z.object({\n enabled: z.boolean().default(false),\n provider: z.enum(['openai', 'alibaba', 'edge', 'minimax']).default('openai'),\n trigger: z.enum(['off', 'always', 'inbound', 'tagged']).default('always'),\n fallback: TTSFallbackConfigSchema.optional(),\n maxTextLength: z.number().int().min(1).default(512), // Conservative default to accommodate all providers (Alibaba limit is 512)\n timeoutMs: z.number().int().min(1000).max(180000).default(60000),\n summarization: TTSSummarizationConfigSchema.optional(),\n modelOverrides: TTSModelOverridesConfigSchema.optional(),\n alibaba: TTSProviderConfigSchema.optional(),\n openai: TTSProviderConfigSchema.optional(),\n edge: TTSEdgeConfigSchema.optional(),\n minimax: TTSProviderConfigSchema.optional(),\n});\n\n// ============================================\n// Extension Configs \n// ============================================\n\n// Security config for extensions \nexport const ExtensionSecurityConfigSchema = z.object({\n checkPermissions: z.boolean().default(true),\n allowUntrusted: z.boolean().default(false),\n allow: z.array(z.string()).default([]),\n trackProvenance: z.boolean().default(true),\n allowPromptInjection: z.boolean().default(false),\n});\n\n// Slot config for extensions \nexport const ExtensionSlotsConfigSchema = z.object({\n memory: z.string().optional(),\n tts: z.string().optional(),\n imageGeneration: z.string().optional(),\n webSearch: z.string().optional(),\n});\n\n// Complete extensions config\n// Extension config allows both known fields AND arbitrary extension-specific config\n// Known fields: enabled (array), allow (array), security (object), slots (object)\n// Arbitrary: any other key is extension-specific config (e.g., extensions.hello.greeting)\nexport const ExtensionsConfigSchema: z.ZodType<Record<string, unknown>> = z.record(z.string(), z.unknown());\n\n// ============================================\n// Update Config\n// ============================================\n\nexport const UpdateAutoConfigSchema = z\n .object({\n /** Enable automatic update installation. Default false. */\n enabled: z.boolean().default(false),\n /** Hours to wait before applying a stable update after first detection. */\n stableDelayHours: z.number().min(0).default(6),\n /** Additional random jitter hours for stable rollout (avoids thundering herd). */\n stableJitterHours: z.number().min(0).default(12),\n /** How often to re-check for beta updates (hours). Min 0.25. */\n betaCheckIntervalHours: z.number().min(0.25).default(1),\n })\n .strict()\n .optional();\n\nexport const UpdateConfigSchema = z\n .object({\n /** Check for updates on gateway startup. Default true. */\n checkOnStart: z.boolean().default(true),\n /** Update channel: stable (default), beta, or dev. */\n channel: z.enum(['stable', 'beta', 'dev']).default('stable'),\n /** Automatic update policy. */\n auto: UpdateAutoConfigSchema,\n })\n .strict()\n .optional();\n\nexport type UpdateConfig = z.infer<typeof UpdateConfigSchema>;\n\n// ============================================\n// Root Config\n// ============================================\n\nexport const ConfigSchema = z.object({\n agents: AgentsConfigSchema,\n bindings: BindingsConfigSchema,\n session: SessionConfigSchema,\n channels: ChannelsConfigSchema,\n gateway: GatewayConfigSchema,\n tools: ToolsConfigSchema,\n cron: CronConfigSchema,\n extensions: ExtensionsConfigSchema.default({}),\n modelsDev: ModelsDevConfigSchema,\n stt: STTConfigSchema.optional(),\n tts: TTSConfigSchema.optional(),\n update: UpdateConfigSchema,\n}).default({\n agents: {\n defaults: {\n workspace: '~/.xopc/workspace',\n model: '', // Empty default - will be resolved dynamically at runtime\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n thinkingDefault: 'medium',\n reasoningDefault: 'stream',\n verboseDefault: 'full',\n compaction: {\n enabled: true,\n mode: 'default',\n reserveTokens: 8000,\n triggerThreshold: 0.8,\n minMessagesBeforeCompact: 10,\n keepRecentMessages: 5,\n evictionWindow: 0.2,\n retentionWindow: 6,\n },\n pruning: {\n enabled: true,\n maxToolResultChars: 10000,\n headKeepRatio: 0.3,\n tailKeepRatio: 0.3,\n },\n },\n },\n bindings: [],\n session: {\n dmScope: 'main' as const,\n },\n channels: {\n telegram: {\n enabled: false,\n allowFrom: [],\n groupAllowFrom: [],\n debug: false,\n accounts: {\n default: {\n accountId: 'default',\n enabled: true,\n botToken: '',\n allowFrom: [],\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n streamMode: 'partial' as const,\n },\n },\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n },\n },\n gateway: {\n host: '127.0.0.1',\n port: 18790,\n auth: {\n mode: 'token',\n },\n heartbeat: {\n enabled: true,\n intervalMs: 1_800_000,\n includeSystemPromptSection: false,\n },\n maxSseConnections: 100,\n corsOrigins: [],\n skillsStoreBaseUrl: 'https://store.xopc.ai',\n },\n tools: {\n web: {\n search: {\n maxResults: 5,\n providers: [],\n },\n },\n },\n cron: {\n enabled: true,\n maxConcurrentJobs: 5,\n defaultTimezone: 'UTC',\n historyRetentionDays: 7,\n enableMetrics: true,\n },\n extensions: {\n allow: [],\n security: {\n checkPermissions: true,\n allowUntrusted: false,\n allow: [],\n trackProvenance: true,\n allowPromptInjection: false,\n },\n slots: {},\n },\n modelsDev: {\n enabled: true,\n },\n stt: {\n enabled: false,\n provider: 'alibaba',\n alibaba: {\n model: 'paraformer-v2',\n },\n openai: {\n model: 'whisper-1',\n },\n fallback: {\n enabled: true,\n order: ['alibaba', 'openai'],\n },\n },\n tts: {\n enabled: false,\n provider: 'openai',\n trigger: 'always',\n fallback: {\n enabled: true,\n order: ['openai', 'alibaba', 'minimax', 'edge'],\n },\n maxTextLength: 4096,\n timeoutMs: 30000,\n modelOverrides: {\n enabled: true,\n allowText: true,\n allowProvider: false,\n allowVoice: true,\n allowModelId: true,\n allowVoiceSettings: false,\n allowNormalization: false,\n allowSeed: false,\n },\n alibaba: {\n model: 'qwen-tts',\n voice: 'Cherry',\n },\n openai: {\n model: 'tts-1',\n voice: 'alloy',\n },\n edge: {\n enabled: true,\n voice: 'en-US-MichelleNeural',\n lang: 'en-US',\n outputFormat: 'audio-24khz-48kbitrate-mono-mp3',\n },\n minimax: {\n model: 'speech-2.8-hd',\n voice: 'male-qn-qingse',\n },\n },\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\nexport type AgentDefaults = z.infer<typeof AgentDefaultsSchema>;\nexport type GatewayAuthConfig = z.infer<typeof GatewayAuthSchema>;\nexport type GatewayAuthRateLimitConfig = z.infer<typeof GatewayAuthRateLimitSchema>;\nexport type STTConfig = z.infer<typeof STTConfigSchema>;\nexport type TTSConfig = z.infer<typeof TTSConfigSchema>;\n\n// ============================================\n// Helper Functions\n// ============================================\n\n/**\n * Parse a model reference string.\n */\nexport interface ParsedModelRef {\n provider: string;\n model: string;\n}\n\n/**\n * Default agent’s resolved Markdown workspace root (`resolveAgentWorkspaceDir` for the default agent id).\n */\nexport function getWorkspacePath(config: Config): string {\n return getDefaultWorkspacePath(config);\n}\n\n/**\n * Primary model ref from `agents.defaults.model` (string or `{ primary }`).\n * Returns undefined when unset or empty.\n */\nexport function getAgentDefaultModelRef(config: Config): string | undefined {\n const raw = config.agents?.defaults?.model;\n if (raw === undefined || raw === null) return undefined;\n const ref = typeof raw === 'string' ? raw : raw.primary;\n if (ref === undefined || ref === null) return undefined;\n const s = String(ref).trim();\n return s ? s : undefined;\n}\n\n/** `provider/model` or null when invalid. */\nexport function parseModelRef(ref: string): ParsedModelRef | null {\n const trimmed = ref.trim();\n const idx = trimmed.indexOf('/');\n if (idx <= 0 || idx === trimmed.length - 1) {\n return null;\n }\n return { provider: trimmed.slice(0, idx).trim(), model: trimmed.slice(idx + 1).trim() };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","names":[],"sources":["../../../src/config/schema.ts"],"sourcesContent":["import { z } from 'zod';\n\nimport { getDefaultWorkspacePath } from '../agent/agent-scope.js';\n\n// ============================================\n// Agent Configs\n// ============================================\n\nexport const AgentModelRefSchema = z.union([\n z.string(),\n z\n .object({\n primary: z.string().optional(),\n fallbacks: z.array(z.string()).optional(),\n })\n .strict(),\n]);\n\nexport type AgentModelConfig = z.infer<typeof AgentModelRefSchema>;\n\nexport const AgentDefaultsSchema = z.object({\n /** Parent directory: each agent’s Markdown root is `<expanded>/<agentId>/` (e.g. `.../workspace/main`). */\n workspace: z.string().default('~/.xopc/workspace'),\n model: z.union([\n z.string(),\n z.object({\n primary: z.string().optional(),\n fallbacks: z.array(z.string()).optional(),\n }).strict(),\n ]).default(''), // Empty default - will be resolved dynamically at runtime\n /** Vision / image understanding model (provider/model). Falls back to heuristics when unset. */\n imageModel: AgentModelRefSchema.optional(),\n /** Image generation model (provider/model), e.g. openai/gpt-image-1. Thin REST wrapper; OpenAI supported. */\n imageGenerationModel: AgentModelRefSchema.optional(),\n /** Max image size for image tool loads (MB). */\n mediaMaxMb: z.number().positive().optional(),\n maxTokens: z.number().default(8192),\n temperature: z.number().default(0.7),\n maxToolIterations: z.number().default(20),\n // Wall-clock limit for one user turn (LLM + tools). Default 30m if unset; cap 4h.\n maxTaskDurationMs: z.number().min(60000).max(14_400_000).optional(),\n // Reliability settings\n maxRequestsPerTurn: z.number().min(10).max(200).default(50),\n maxToolFailuresPerTurn: z.number().min(1).max(20).default(3),\n // Thinking ability settings\n thinkingDefault: z.enum(['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'adaptive']).optional(),\n reasoningDefault: z.enum(['off', 'on', 'stream']).optional(),\n verboseDefault: z.enum(['off', 'on', 'full']).optional(),\n compaction: z.object({\n enabled: z.boolean().default(true),\n mode: z.enum(['default', 'safeguard']).default('default'),\n reserveTokens: z.number().default(8000),\n triggerThreshold: z.number().min(0.5).max(0.95).default(0.8),\n minMessagesBeforeCompact: z.number().default(10),\n keepRecentMessages: z.number().default(5),\n // Dual-strategy compaction\n evictionWindow: z.number().min(0.1).max(0.5).default(0.2),\n retentionWindow: z.number().min(3).max(20).default(6),\n }).optional(),\n pruning: z.object({\n enabled: z.boolean().default(true),\n maxToolResultChars: z.number().default(10000),\n headKeepRatio: z.number().default(0.3),\n tailKeepRatio: z.number().default(0.3),\n }).optional(),\n /**\n * Curated memory (`agents/<id>/memories/`) + pluggable external provider.\n * Only one external provider at a time.\n */\n memory: z\n .object({\n /** Master switch: curated snapshot, `curated_memory`, prefetch, and external provider. Default true. */\n enabled: z.boolean().optional(),\n /** When false, use workspace bootstrap only (no curated snapshot / tool). Default true. */\n useEnhancedSystem: z.boolean().optional(),\n /** Include USER.md in snapshot. Default true. */\n userProfileEnabled: z.boolean().optional(),\n memoryCharLimit: z.number().positive().optional(),\n userCharLimit: z.number().positive().optional(),\n provider: z.enum(['none', 'stub']).optional(),\n /** How often prefetched external memory is injected into the user message. */\n injectionFrequency: z.enum(['every-turn', 'first-turn']).optional(),\n /** Inject prefetch on turns 1, 1+N, 1+2N, … (only when injectionFrequency is every-turn). Min 1. */\n contextCadence: z.number().int().min(1).optional(),\n /** Reserved for future external “dialectic” sync cadence (not wired yet). */\n dialecticCadence: z.number().int().min(1).optional(),\n /**\n * Background memory consolidation (\"dreaming\"): three-phase sleep model that\n * promotes short-term recall signals into long-term memory (`MEMORY.md`).\n *\n * Phases:\n * - **light** — fast, frequent sweep (default every 6 h): dedup + signal collection.\n * - **deep** — daily deep promotion (default 3 AM): score-gated write to MEMORY.md.\n * - **rem** — weekly pattern discovery (default Sun 5 AM): cross-session insight mining.\n */\n dreaming: z\n .object({\n enabled: z.boolean().optional(),\n /** Default deep-phase cron when `phases.deep.cron` is omitted. */\n frequency: z.string().optional(),\n timezone: z.string().optional(),\n phases: z\n .object({\n light: z\n .object({\n enabled: z.boolean().optional(),\n cron: z.string().optional(),\n lookbackDays: z.number().int().min(1).optional(),\n limit: z.number().int().min(0).optional(),\n dedupeSimilarity: z.number().min(0).max(1).optional(),\n })\n .optional(),\n deep: z\n .object({\n enabled: z.boolean().optional(),\n cron: z.string().optional(),\n minScore: z.number().min(0).max(1).optional(),\n minRecallCount: z.number().int().min(1).optional(),\n minUniqueQueries: z.number().int().min(1).optional(),\n limit: z.number().int().min(0).optional(),\n recencyHalfLifeDays: z.number().min(1).optional(),\n maxAgeDays: z.number().int().min(1).optional(),\n })\n .optional(),\n rem: z\n .object({\n enabled: z.boolean().optional(),\n cron: z.string().optional(),\n lookbackDays: z.number().int().min(1).optional(),\n limit: z.number().int().min(0).optional(),\n minPatternStrength: z.number().min(0).max(1).optional(),\n })\n .optional(),\n })\n .optional(),\n })\n .optional(),\n })\n .optional(),\n /** Cross-session transcript search (`session_search` tool). */\n sessionSearch: z\n .object({\n /** Model ref for per-session summaries (e.g. openai/gpt-4o-mini). */\n summaryModel: z.string().optional(),\n })\n .optional(),\n /**\n * Post-turn background review (Hermes-style): optional quiet follow-up that may call\n * `curated_memory` / `skill_manage` so durable facts and reusable workflows persist\n * without bloating the main user-visible turn.\n */\n backgroundReview: z\n .object({\n /** When true, nudges may run after successful turns. Default false (opt-in). */\n enabled: z.boolean().optional(),\n /** User-turn cadence for memory review. 0 disables the memory channel. Default 10. */\n memoryNudgeInterval: z.number().int().min(0).optional(),\n /** LLM rounds without `skill_manage` before a skill review. 0 disables the skill channel. Default 10. */\n skillNudgeInterval: z.number().int().min(0).optional(),\n /** Max tool executions for the review agent. Default 8. */\n maxToolRounds: z.number().int().min(1).max(32).optional(),\n /** Max prior messages passed into the review context (tail). Default 80. */\n maxHistoryMessages: z.number().int().min(10).max(200).optional(),\n /** Wall-clock cap for the review run (ms). Default 120000. */\n maxDurationMs: z.number().int().min(30_000).max(600_000).optional(),\n })\n .optional(),\n /** LLM pass for `web_extract` (markdown-focused extraction). */\n webExtract: z\n .object({\n model: z.string().optional(),\n maxLength: z.number().positive().optional(),\n })\n .optional(),\n /**\n * Headless Playwright tools (`browser_*`). Opt-in. Install browsers once: `npx playwright install chromium`.\n */\n browser: z\n .object({\n enabled: z.boolean().optional(),\n /** Default true when browser tools are enabled. */\n headless: z.boolean().optional(),\n })\n .optional(),\n /** Sub-agent delegation (`delegate_task`). Opt-in. */\n delegate: z\n .object({\n enabled: z.boolean().optional(),\n })\n .optional(),\n /** Sandboxed `execute_code` (programmatic tool calls). Opt-in. */\n executeCode: z\n .object({\n enabled: z.boolean().optional(),\n })\n .optional(),\n /** Optional full system prompt replacement (merged with per-agent entry; entry wins). */\n systemPromptOverride: z.string().optional(),\n /** Optional allowlist of skill names for `<available_skills>`; when set, replaces unfiltered list. */\n skills: z.array(z.string()).optional(),\n /** Disable built-in tools by name (e.g. `shell`, `web_search`). */\n tools: z\n .object({\n disable: z.array(z.string()).optional(),\n })\n .optional(),\n /** Opaque per-process params (reserved for extensions / future use). */\n params: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const AgentConfigSchema = z.object({\n id: z.string(),\n /** When true, this entry is the default routing agent. */\n default: z.boolean().optional(),\n name: z.string().optional(),\n /** Short human-readable summary for UIs (gateway console, pickers). */\n description: z.string().max(4000).optional(),\n enabled: z.boolean().default(true),\n /** Per-agent workspace root (`~` expanded at runtime). */\n workspace: z.string().optional(),\n /**\n * Internal agent state directory (`…/credentials`, `agent.json`, pid, inbox).\n * Default: `<stateDir>/agents/<id>/agent`.\n */\n agentDir: z.string().optional(),\n model: AgentModelRefSchema.optional(),\n thinkingDefault: z.enum(['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'adaptive']).optional(),\n reasoningDefault: z.enum(['off', 'on', 'stream']).optional(),\n verboseDefault: z.enum(['off', 'on', 'full']).optional(),\n systemPromptOverride: z.string().optional(),\n skills: z.array(z.string()).optional(),\n tools: z\n .object({\n disable: z.array(z.string()).optional(),\n })\n .optional(),\n params: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const AgentsConfigSchema = z.object({\n /** Default agent id when not specified (routing / session creation). */\n default: z.string().optional(),\n defaults: AgentDefaultsSchema.optional(),\n list: z.array(AgentConfigSchema).optional(),\n}).default({\n defaults: {\n workspace: '~/.xopc/workspace',\n model: '', // Empty default - will be resolved dynamically at runtime\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n thinkingDefault: 'medium',\n reasoningDefault: 'stream',\n verboseDefault: 'full',\n compaction: {\n enabled: true,\n mode: 'default',\n reserveTokens: 8000,\n triggerThreshold: 0.8,\n minMessagesBeforeCompact: 10,\n keepRecentMessages: 5,\n evictionWindow: 0.2,\n retentionWindow: 6,\n },\n pruning: {\n enabled: true,\n maxToolResultChars: 10000,\n headKeepRatio: 0.3,\n tailKeepRatio: 0.3,\n },\n },\n} as any);\n\n// ============================================\n// Channel Configs (per-channel Zod lives in bundled extensions; root schema is open)\n// ============================================\n\nexport {\n TelegramTopicConfigSchema,\n TelegramGroupConfigSchema,\n TelegramAccountConfigSchema,\n TelegramConfigSchema,\n} from '../../extensions/telegram/src/config-schema.js';\nexport type { TelegramConfig } from '../../extensions/telegram/src/config-schema.js';\nexport { WeixinAccountConfigSchema, WeixinConfigSchema } from '../../extensions/weixin/src/config-schema.js';\nexport type { WeixinConfig } from '../../extensions/weixin/src/config-schema.js';\n\n// ============================================\n// Session Routing Configuration\n// ============================================\n\nexport const BindingMatchSchema = z.object({\n channel: z.string(),\n accountId: z.string().optional(),\n peerKind: z.string().optional(),\n peerId: z.string().optional(),\n guildId: z.string().optional(),\n teamId: z.string().optional(),\n memberRoleIds: z.array(z.string()).optional(),\n});\n\nexport const BindingRuleSchema = z.object({\n id: z.string().optional(),\n agentId: z.string(),\n priority: z.number().default(100),\n match: BindingMatchSchema,\n enabled: z.boolean().default(true),\n});\n\nexport const BindingsConfigSchema = z.array(BindingRuleSchema).default([]);\n\nexport const SessionDmScopeSchema = z.enum([\n 'main',\n 'per-peer',\n 'per-channel-peer',\n 'per-account-channel-peer',\n]);\n\nexport const SessionStorageConfigSchema = z.object({\n pruneAfterMs: z.number().optional(),\n maxEntries: z.number().optional(),\n});\n\nexport const SessionConfigSchema = z.object({\n dmScope: SessionDmScopeSchema.default('main'),\n identityLinks: z.record(z.string(), z.array(z.string())).optional(),\n storage: SessionStorageConfigSchema.optional(),\n}).default({\n dmScope: 'main',\n});\n\n/** Channel buckets — shapes validated post-parse by registered channel plugins. */\nexport const ChannelsConfigSchema = z.record(z.string(), z.unknown()).default({\n telegram: {\n enabled: false,\n allowFrom: [],\n groupAllowFrom: [],\n debug: false,\n accounts: {\n default: {\n accountId: 'default',\n enabled: true,\n botToken: '',\n allowFrom: [],\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n streamMode: 'partial' as const,\n },\n },\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n },\n});\n\nexport const SearchProviderEntrySchema = z.object({\n type: z.enum(['brave', 'tavily', 'bing', 'searxng']),\n apiKey: z.string().optional(),\n /** SearXNG instance base URL (e.g. http://localhost:8080) */\n url: z.string().optional(),\n disabled: z.boolean().optional(),\n});\n\nexport type SearchProviderEntry = z.infer<typeof SearchProviderEntrySchema>;\n\nexport const WebSearchConfigSchema = z.object({\n maxResults: z.number().default(5),\n /** Ordered API providers; empty → HTML fallback only */\n providers: z.array(SearchProviderEntrySchema).default([]),\n});\n\nexport type WebSearchConfig = z.infer<typeof WebSearchConfigSchema>;\n\nexport const WebToolsConfigSchema = z.object({\n /** Search result HTML fallback: cn → Bing, otherwise DuckDuckGo */\n region: z.enum(['cn', 'global']).optional(),\n search: WebSearchConfigSchema.optional(),\n});\n\nexport type WebToolsConfig = z.infer<typeof WebToolsConfigSchema>;\n\nexport const ToolsConfigSchema = z.object({\n web: WebToolsConfigSchema.optional(),\n}).default({\n web: {\n search: {\n maxResults: 5,\n providers: [],\n },\n },\n});\n\n// ============================================\n// Gateway Configuration\n// ============================================\n\nexport const GatewayAuthRateLimitSchema = z\n .object({\n enabled: z.boolean().default(true),\n maxAttempts: z.number().int().min(1).default(5),\n windowMs: z.number().default(900_000),\n blockDurationMs: z.number().default(300_000),\n })\n .optional();\n\nexport const GatewayAuthSchema = z\n .object({\n mode: z.enum(['none', 'token', 'password']).default('token'),\n token: z.string().optional(),\n password: z.string().optional(),\n rateLimit: GatewayAuthRateLimitSchema,\n })\n .default({\n mode: 'token',\n });\n\nexport const HeartbeatConfigSchema = z\n .object({\n enabled: z.boolean(),\n intervalMs: z.number(),\n /** When false, heartbeat instructions are only sent during heartbeat polling turns (not in every chat system prompt). */\n includeSystemPromptSection: z.boolean().optional().default(false),\n target: z.string().optional(),\n targetChatId: z.string().optional(),\n prompt: z.string().optional(),\n ackMaxChars: z.number().optional(),\n isolatedSession: z.boolean().optional(),\n activeHours: z\n .object({\n start: z.string(),\n end: z.string(),\n timezone: z.string().optional(),\n })\n .optional(),\n })\n .default({\n enabled: true,\n intervalMs: 1_800_000,\n includeSystemPromptSection: false,\n });\n\nexport const GatewayConfigSchema = z.object({\n host: z.string().optional(),\n port: z.number().optional(),\n auth: GatewayAuthSchema.optional(),\n heartbeat: HeartbeatConfigSchema.optional(),\n maxSseConnections: z.number().optional(),\n corsOrigins: z.array(z.string()).optional(),\n /** Skills marketplace provider: `store` (store.xopc.ai) or `skillhub` (skillhub.cn). */\n skillsMarketplaceProvider: z.enum(['store', 'skillhub']).optional(),\n /** Base URL for the xopc skills marketplace (public REST API). */\n skillsStoreBaseUrl: z.string().url().optional(),\n}).default({\n host: '127.0.0.1',\n port: 18790,\n auth: {\n mode: 'token',\n },\n heartbeat: {\n enabled: true,\n intervalMs: 1_800_000,\n includeSystemPromptSection: false,\n },\n maxSseConnections: 100,\n corsOrigins: [],\n skillsMarketplaceProvider: 'skillhub',\n skillsStoreBaseUrl: 'https://store.xopc.ai',\n});\n\nexport const CronConfigSchema = z.object({\n enabled: z.boolean().optional(),\n maxConcurrentJobs: z.number().optional(),\n defaultTimezone: z.string().optional(),\n historyRetentionDays: z.number().optional(),\n enableMetrics: z.boolean().optional(),\n}).default({\n enabled: true,\n maxConcurrentJobs: 5,\n defaultTimezone: 'UTC',\n historyRetentionDays: 7,\n enableMetrics: true,\n});\n\nexport const ModelsDevConfigSchema = z.object({\n enabled: z.boolean().default(true),\n}).default({\n enabled: true,\n});\n\n// ============================================\n// STT (Speech-to-Text) Config\n// ============================================\n\nexport const STTProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n model: z.string().optional(),\n});\n\nexport const STTFallbackConfigSchema = z.object({\n enabled: z.boolean().default(true),\n order: z.array(z.enum(['alibaba', 'openai'])).default(['alibaba', 'openai']),\n});\n\nexport const STTConfigSchema = z.object({\n enabled: z.boolean().default(false),\n provider: z.enum(['alibaba', 'openai']).default('alibaba'),\n alibaba: STTProviderConfigSchema.optional(),\n openai: STTProviderConfigSchema.optional(),\n fallback: STTFallbackConfigSchema.optional(),\n});\n\n// ============================================\n// TTS (Text-to-Speech) Config\n// ============================================\n\nexport const TTSProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n model: z.string().optional(),\n voice: z.string().optional(),\n});\n\nexport const TTSFallbackConfigSchema = z.object({\n enabled: z.boolean().default(true),\n order: z\n .array(z.enum(['openai', 'alibaba', 'edge', 'minimax']))\n .default(['openai', 'alibaba', 'minimax', 'edge']),\n});\n\nexport const TTSModelOverridesConfigSchema = z.object({\n enabled: z.boolean().default(true),\n allowText: z.boolean().default(true),\n allowProvider: z.boolean().default(false),\n allowVoice: z.boolean().default(true),\n allowModelId: z.boolean().default(true),\n allowVoiceSettings: z.boolean().default(false),\n allowNormalization: z.boolean().default(false),\n allowSeed: z.boolean().default(false),\n});\n\nexport const TTSEdgeConfigSchema = z.object({\n enabled: z.boolean().default(true),\n voice: z.string().optional(),\n lang: z.string().optional(),\n outputFormat: z.string().optional(),\n pitch: z.string().optional(),\n rate: z.string().optional(),\n volume: z.string().optional(),\n proxy: z.string().optional(),\n timeoutMs: z.number().int().min(1000).max(120000).optional(),\n});\n\nexport const TTSSummarizationConfigSchema = z.object({\n enabled: z.boolean().optional(),\n targetLength: z.number().int().min(1).optional(),\n threshold: z.number().int().min(1).optional(),\n model: z.string().optional(),\n});\n\nexport const TTSConfigSchema = z.object({\n enabled: z.boolean().default(false),\n provider: z.enum(['openai', 'alibaba', 'edge', 'minimax']).default('openai'),\n trigger: z.enum(['off', 'always', 'inbound', 'tagged']).default('always'),\n fallback: TTSFallbackConfigSchema.optional(),\n maxTextLength: z.number().int().min(1).default(512), // Conservative default to accommodate all providers (Alibaba limit is 512)\n timeoutMs: z.number().int().min(1000).max(180000).default(60000),\n summarization: TTSSummarizationConfigSchema.optional(),\n modelOverrides: TTSModelOverridesConfigSchema.optional(),\n alibaba: TTSProviderConfigSchema.optional(),\n openai: TTSProviderConfigSchema.optional(),\n edge: TTSEdgeConfigSchema.optional(),\n minimax: TTSProviderConfigSchema.optional(),\n});\n\n// ============================================\n// Extension Configs \n// ============================================\n\n// Security config for extensions \nexport const ExtensionSecurityConfigSchema = z.object({\n checkPermissions: z.boolean().default(true),\n allowUntrusted: z.boolean().default(false),\n allow: z.array(z.string()).default([]),\n trackProvenance: z.boolean().default(true),\n allowPromptInjection: z.boolean().default(false),\n});\n\n// Slot config for extensions \nexport const ExtensionSlotsConfigSchema = z.object({\n memory: z.string().optional(),\n tts: z.string().optional(),\n imageGeneration: z.string().optional(),\n webSearch: z.string().optional(),\n});\n\n// Complete extensions config\n// Extension config allows both known fields AND arbitrary extension-specific config\n// Known fields: enabled (array), allow (array), security (object), slots (object)\n// Arbitrary: any other key is extension-specific config (e.g., extensions.hello.greeting)\nexport const ExtensionsConfigSchema: z.ZodType<Record<string, unknown>> = z.record(z.string(), z.unknown());\n\n// ============================================\n// Update Config\n// ============================================\n\nexport const UpdateAutoConfigSchema = z\n .object({\n /** Enable automatic update installation. Default false. */\n enabled: z.boolean().default(false),\n /** Hours to wait before applying a stable update after first detection. */\n stableDelayHours: z.number().min(0).default(6),\n /** Additional random jitter hours for stable rollout (avoids thundering herd). */\n stableJitterHours: z.number().min(0).default(12),\n /** How often to re-check for beta updates (hours). Min 0.25. */\n betaCheckIntervalHours: z.number().min(0.25).default(1),\n })\n .strict()\n .optional();\n\nexport const UpdateConfigSchema = z\n .object({\n /** Check for updates on gateway startup. Default true. */\n checkOnStart: z.boolean().default(true),\n /** Update channel: stable (default), beta, or dev. */\n channel: z.enum(['stable', 'beta', 'dev']).default('stable'),\n /** Automatic update policy. */\n auto: UpdateAutoConfigSchema,\n })\n .strict()\n .optional();\n\nexport type UpdateConfig = z.infer<typeof UpdateConfigSchema>;\n\n// ============================================\n// Root Config\n// ============================================\n\nexport const ConfigSchema = z.object({\n agents: AgentsConfigSchema,\n bindings: BindingsConfigSchema,\n session: SessionConfigSchema,\n channels: ChannelsConfigSchema,\n gateway: GatewayConfigSchema,\n tools: ToolsConfigSchema,\n cron: CronConfigSchema,\n extensions: ExtensionsConfigSchema.default({}),\n modelsDev: ModelsDevConfigSchema,\n stt: STTConfigSchema.optional(),\n tts: TTSConfigSchema.optional(),\n update: UpdateConfigSchema,\n}).default({\n agents: {\n defaults: {\n workspace: '~/.xopc/workspace',\n model: '', // Empty default - will be resolved dynamically at runtime\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n thinkingDefault: 'medium',\n reasoningDefault: 'stream',\n verboseDefault: 'full',\n compaction: {\n enabled: true,\n mode: 'default',\n reserveTokens: 8000,\n triggerThreshold: 0.8,\n minMessagesBeforeCompact: 10,\n keepRecentMessages: 5,\n evictionWindow: 0.2,\n retentionWindow: 6,\n },\n pruning: {\n enabled: true,\n maxToolResultChars: 10000,\n headKeepRatio: 0.3,\n tailKeepRatio: 0.3,\n },\n },\n },\n bindings: [],\n session: {\n dmScope: 'main' as const,\n },\n channels: {\n telegram: {\n enabled: false,\n allowFrom: [],\n groupAllowFrom: [],\n debug: false,\n accounts: {\n default: {\n accountId: 'default',\n enabled: true,\n botToken: '',\n allowFrom: [],\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n streamMode: 'partial' as const,\n },\n },\n dmPolicy: 'pairing' as const,\n groupPolicy: 'open' as const,\n replyToMode: 'off' as const,\n historyLimit: 50,\n textChunkLimit: 4000,\n },\n },\n gateway: {\n host: '127.0.0.1',\n port: 18790,\n auth: {\n mode: 'token',\n },\n heartbeat: {\n enabled: true,\n intervalMs: 1_800_000,\n includeSystemPromptSection: false,\n },\n maxSseConnections: 100,\n corsOrigins: [],\n skillsMarketplaceProvider: 'skillhub' as const,\n skillsStoreBaseUrl: 'https://store.xopc.ai',\n },\n tools: {\n web: {\n search: {\n maxResults: 5,\n providers: [],\n },\n },\n },\n cron: {\n enabled: true,\n maxConcurrentJobs: 5,\n defaultTimezone: 'UTC',\n historyRetentionDays: 7,\n enableMetrics: true,\n },\n extensions: {\n allow: [],\n security: {\n checkPermissions: true,\n allowUntrusted: false,\n allow: [],\n trackProvenance: true,\n allowPromptInjection: false,\n },\n slots: {},\n },\n modelsDev: {\n enabled: true,\n },\n stt: {\n enabled: false,\n provider: 'alibaba',\n alibaba: {\n model: 'paraformer-v2',\n },\n openai: {\n model: 'whisper-1',\n },\n fallback: {\n enabled: true,\n order: ['alibaba', 'openai'],\n },\n },\n tts: {\n enabled: false,\n provider: 'openai',\n trigger: 'always',\n fallback: {\n enabled: true,\n order: ['openai', 'alibaba', 'minimax', 'edge'],\n },\n maxTextLength: 4096,\n timeoutMs: 30000,\n modelOverrides: {\n enabled: true,\n allowText: true,\n allowProvider: false,\n allowVoice: true,\n allowModelId: true,\n allowVoiceSettings: false,\n allowNormalization: false,\n allowSeed: false,\n },\n alibaba: {\n model: 'qwen-tts',\n voice: 'Cherry',\n },\n openai: {\n model: 'tts-1',\n voice: 'alloy',\n },\n edge: {\n enabled: true,\n voice: 'en-US-MichelleNeural',\n lang: 'en-US',\n outputFormat: 'audio-24khz-48kbitrate-mono-mp3',\n },\n minimax: {\n model: 'speech-2.8-hd',\n voice: 'male-qn-qingse',\n },\n },\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\nexport type AgentDefaults = z.infer<typeof AgentDefaultsSchema>;\nexport type GatewayAuthConfig = z.infer<typeof GatewayAuthSchema>;\nexport type GatewayAuthRateLimitConfig = z.infer<typeof GatewayAuthRateLimitSchema>;\nexport type STTConfig = z.infer<typeof STTConfigSchema>;\nexport type TTSConfig = z.infer<typeof TTSConfigSchema>;\n\n// ============================================\n// Helper Functions\n// ============================================\n\n/**\n * Parse a model reference string.\n */\nexport interface ParsedModelRef {\n provider: string;\n model: string;\n}\n\n/**\n * Default agent’s resolved Markdown workspace root (`resolveAgentWorkspaceDir` for the default agent id).\n */\nexport function getWorkspacePath(config: Config): string {\n return getDefaultWorkspacePath(config);\n}\n\n/**\n * Primary model ref from `agents.defaults.model` (string or `{ primary }`).\n * Returns undefined when unset or empty.\n */\nexport function getAgentDefaultModelRef(config: Config): string | undefined {\n const raw = config.agents?.defaults?.model;\n if (raw === undefined || raw === null) return undefined;\n const ref = typeof raw === 'string' ? raw : raw.primary;\n if (ref === undefined || ref === null) return undefined;\n const s = String(ref).trim();\n return s ? s : undefined;\n}\n\n/** `provider/model` or null when invalid. */\nexport function parseModelRef(ref: string): ParsedModelRef | null {\n const trimmed = ref.trim();\n const idx = trimmed.indexOf('/');\n if (idx <= 0 || idx === trimmed.length - 1) {\n return null;\n }\n return { provider: trimmed.slice(0, idx).trim(), model: trimmed.slice(idx + 1).trim() };\n}\n"],"mappings":"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"}
|
|
@@ -95,7 +95,7 @@ const JobDataSchema = z.object({
|
|
|
95
95
|
});
|
|
96
96
|
}).optional(),
|
|
97
97
|
maxRetries: z.number().int().min(0).max(10).default(3),
|
|
98
|
-
timeout: z.number().int().min(1e3).max(3e5).default(
|
|
98
|
+
timeout: z.number().int().min(1e3).max(3e5).default(18e4),
|
|
99
99
|
created_at: z.string().datetime(),
|
|
100
100
|
updated_at: z.string().datetime(),
|
|
101
101
|
sessionTarget: z.enum(["main", "isolated"]).optional(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","names":[],"sources":["../../../src/cron/validation.ts"],"sourcesContent":["// Cron input validation using Zod\nimport { z } from 'zod';\nimport nodeCron from 'node-cron';\n\n// Custom cron validation\nconst cronExpression = z.string().superRefine((val, ctx) => {\n if (!nodeCron.validate(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid cron expression: ${val}`,\n });\n }\n});\n\n// Valid timezones (subset of IANA timezones)\nconst validTimezones = [\n 'UTC',\n 'America/New_York',\n 'America/Chicago',\n 'America/Denver',\n 'America/Los_Angeles',\n 'America/Toronto',\n 'Europe/London',\n 'Europe/Paris',\n 'Europe/Berlin',\n 'Europe/Moscow',\n 'Asia/Tokyo',\n 'Asia/Shanghai',\n 'Asia/Hong_Kong',\n 'Asia/Singapore',\n 'Asia/Seoul',\n 'Asia/Dubai',\n 'Asia/Mumbai',\n 'Australia/Sydney',\n 'Pacific/Auckland',\n];\n\nconst CronDeliveryMode = z.enum(['none', 'announce', 'direct']);\n\n/** Treat `''` / `null` / whitespace-only as absent so optional fields do not fail `.min(1)` */\nfunction optionalTrimmedString(max: number, min = 1) {\n return z.preprocess((v) => {\n if (v === null || v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? undefined : t;\n }, z.string().min(min).max(max).optional());\n}\n\n/** Optional agent id on create; empty string → undefined. */\nconst optionalJobAgentId = optionalTrimmedString(64, 1);\n\n/** Optional absolute workspace path on create; empty string → undefined. */\nconst optionalJobWorkingDirectory = optionalTrimmedString(4096, 1);\n\n/**\n * PATCH: set string, or `null` / empty to clear `workingDirectory` on the job.\n */\nconst patchJobWorkingDirectory = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(4096), z.null()]).optional());\n\n/**\n * PATCH: set string, or `null` / empty to clear `agentId` on the job.\n */\nconst patchJobAgentId = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(64), z.null()]).optional());\n\n// CronPayload validation\nconst CronSystemEventPayloadSchema = z.object({\n kind: z.literal('systemEvent'),\n text: z.string().min(1).max(50000),\n});\n\nconst CronAgentTurnPayloadSchema = z.object({\n kind: z.literal('agentTurn'),\n message: z.string().min(1).max(50000),\n model: optionalTrimmedString(100, 1),\n timeoutSeconds: z.number().int().min(10).max(3600).optional(),\n});\n\nconst CronPayloadSchema = z.union([\n CronSystemEventPayloadSchema,\n CronAgentTurnPayloadSchema,\n]);\n\n// CronDelivery validation — channel must match gateway UI / message bus ids (telegram, weixin, cli, local, …)\nconst CronDeliverySchema = z.object({\n mode: CronDeliveryMode.default('none'),\n channel: optionalTrimmedString(32, 1),\n to: z.preprocess(\n (v) => (v === '' || v === null || v === undefined ? undefined : v),\n z.string().max(100).optional(),\n ),\n bestEffort: z.boolean().optional(),\n});\n\nexport const JobDataSchema = z\n .object({\n id: z.string().min(1).max(32),\n name: z.string().max(100).optional(),\n schedule: cronExpression,\n enabled: z.boolean(),\n timezone: z.string().superRefine((val, ctx) => {\n if (val && !validTimezones.includes(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid timezone: ${val}. Use IANA timezone names.`,\n });\n }\n }).optional(),\n maxRetries: z.number().int().min(0).max(10).default(3),\n timeout: z.number().int().min(1000).max(300000).default(
|
|
1
|
+
{"version":3,"file":"validation.js","names":[],"sources":["../../../src/cron/validation.ts"],"sourcesContent":["// Cron input validation using Zod\nimport { z } from 'zod';\nimport nodeCron from 'node-cron';\n\n// Custom cron validation\nconst cronExpression = z.string().superRefine((val, ctx) => {\n if (!nodeCron.validate(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid cron expression: ${val}`,\n });\n }\n});\n\n// Valid timezones (subset of IANA timezones)\nconst validTimezones = [\n 'UTC',\n 'America/New_York',\n 'America/Chicago',\n 'America/Denver',\n 'America/Los_Angeles',\n 'America/Toronto',\n 'Europe/London',\n 'Europe/Paris',\n 'Europe/Berlin',\n 'Europe/Moscow',\n 'Asia/Tokyo',\n 'Asia/Shanghai',\n 'Asia/Hong_Kong',\n 'Asia/Singapore',\n 'Asia/Seoul',\n 'Asia/Dubai',\n 'Asia/Mumbai',\n 'Australia/Sydney',\n 'Pacific/Auckland',\n];\n\nconst CronDeliveryMode = z.enum(['none', 'announce', 'direct']);\n\n/** Treat `''` / `null` / whitespace-only as absent so optional fields do not fail `.min(1)` */\nfunction optionalTrimmedString(max: number, min = 1) {\n return z.preprocess((v) => {\n if (v === null || v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? undefined : t;\n }, z.string().min(min).max(max).optional());\n}\n\n/** Optional agent id on create; empty string → undefined. */\nconst optionalJobAgentId = optionalTrimmedString(64, 1);\n\n/** Optional absolute workspace path on create; empty string → undefined. */\nconst optionalJobWorkingDirectory = optionalTrimmedString(4096, 1);\n\n/**\n * PATCH: set string, or `null` / empty to clear `workingDirectory` on the job.\n */\nconst patchJobWorkingDirectory = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(4096), z.null()]).optional());\n\n/**\n * PATCH: set string, or `null` / empty to clear `agentId` on the job.\n */\nconst patchJobAgentId = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(64), z.null()]).optional());\n\n// CronPayload validation\nconst CronSystemEventPayloadSchema = z.object({\n kind: z.literal('systemEvent'),\n text: z.string().min(1).max(50000),\n});\n\nconst CronAgentTurnPayloadSchema = z.object({\n kind: z.literal('agentTurn'),\n message: z.string().min(1).max(50000),\n model: optionalTrimmedString(100, 1),\n timeoutSeconds: z.number().int().min(10).max(3600).optional(),\n});\n\nconst CronPayloadSchema = z.union([\n CronSystemEventPayloadSchema,\n CronAgentTurnPayloadSchema,\n]);\n\n// CronDelivery validation — channel must match gateway UI / message bus ids (telegram, weixin, cli, local, …)\nconst CronDeliverySchema = z.object({\n mode: CronDeliveryMode.default('none'),\n channel: optionalTrimmedString(32, 1),\n to: z.preprocess(\n (v) => (v === '' || v === null || v === undefined ? undefined : v),\n z.string().max(100).optional(),\n ),\n bestEffort: z.boolean().optional(),\n});\n\nexport const JobDataSchema = z\n .object({\n id: z.string().min(1).max(32),\n name: z.string().max(100).optional(),\n schedule: cronExpression,\n enabled: z.boolean(),\n timezone: z.string().superRefine((val, ctx) => {\n if (val && !validTimezones.includes(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid timezone: ${val}. Use IANA timezone names.`,\n });\n }\n }).optional(),\n maxRetries: z.number().int().min(0).max(10).default(3),\n timeout: z.number().int().min(1000).max(300000).default(180000),\n created_at: z.string().datetime(),\n updated_at: z.string().datetime(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: optionalTrimmedString(64, 1),\n workingDirectory: optionalJobWorkingDirectory,\n payload: CronPayloadSchema,\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n state: z.any().optional(),\n })\n .strict();\n\nexport const AddJobRequestSchema = z.object({\n schedule: cronExpression,\n name: z.string().max(100).optional(),\n timezone: z.string().optional(),\n maxRetries: z.number().int().min(0).max(10).optional(),\n timeout: z.number().int().min(1000).max(300000).optional(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: optionalJobAgentId,\n workingDirectory: optionalJobWorkingDirectory,\n payload: CronPayloadSchema,\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n});\n\nexport const UpdateJobRequestSchema = z.object({\n name: z.string().max(100).optional(),\n schedule: cronExpression.optional(),\n timezone: z.string().optional(),\n maxRetries: z.number().int().min(0).max(10).optional(),\n timeout: z.number().int().min(1000).max(300000).optional(),\n enabled: z.boolean().optional(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: patchJobAgentId,\n workingDirectory: patchJobWorkingDirectory,\n payload: CronPayloadSchema.optional(),\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n}).refine(\n (data) => Object.keys(data).length > 0,\n { message: 'At least one field must be provided for update' }\n);\n\nexport type ValidatedJobData = z.infer<typeof JobDataSchema>;\nexport type ValidatedAddJobRequest = z.infer<typeof AddJobRequestSchema>;\nexport type ValidatedUpdateJobRequest = z.infer<typeof UpdateJobRequestSchema>;\nexport type ValidatedCronPayload = z.infer<typeof CronPayloadSchema>;\nexport type ValidatedCronDelivery = z.infer<typeof CronDeliverySchema>;\n\n// Re-export common validation helpers\nexport { cronExpression };\n"],"mappings":"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"}
|
|
@@ -109,12 +109,129 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
109
109
|
payload: { messages }
|
|
110
110
|
});
|
|
111
111
|
});
|
|
112
|
-
authenticated.
|
|
112
|
+
authenticated.post("/api/sessions/:key/transcript/context", async (c) => {
|
|
113
|
+
const key = c.req.param("key");
|
|
114
|
+
if (!await service.sessionManagerInstance.getSessionMetadata(key)) return c.json({
|
|
115
|
+
ok: false,
|
|
116
|
+
error: "Session not found"
|
|
117
|
+
}, 404);
|
|
118
|
+
const body = await c.req.json().catch(() => ({}));
|
|
119
|
+
const id = typeof body.id === "string" && body.id.trim() ? body.id.trim() : void 0;
|
|
120
|
+
const text = typeof body.text === "string" ? body.text : void 0;
|
|
121
|
+
const data = body.data !== void 0 && typeof body.data === "object" && body.data !== null && !Array.isArray(body.data) ? body.data : void 0;
|
|
122
|
+
await service.sessionManagerInstance.appendTranscriptContextEntry(key, {
|
|
123
|
+
id,
|
|
124
|
+
text,
|
|
125
|
+
data
|
|
126
|
+
});
|
|
127
|
+
return c.json({ ok: true });
|
|
128
|
+
});
|
|
129
|
+
authenticated.get("/api/sessions/:key/compaction/checkpoints", async (c) => {
|
|
113
130
|
const key = c.req.param("key");
|
|
131
|
+
if (!await service.sessionManagerInstance.getSessionMetadata(key)) return c.json({
|
|
132
|
+
ok: false,
|
|
133
|
+
error: "Session not found"
|
|
134
|
+
}, 404);
|
|
135
|
+
const checkpoints = await service.listSessionCompactionCheckpoints(key);
|
|
136
|
+
return c.json({
|
|
137
|
+
ok: true,
|
|
138
|
+
payload: { checkpoints }
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
authenticated.get("/api/sessions/:key/compaction/checkpoints/:checkpointId", async (c) => {
|
|
142
|
+
const key = c.req.param("key");
|
|
143
|
+
const checkpointId = c.req.param("checkpointId");
|
|
144
|
+
const checkpoint = await service.getSessionCompactionCheckpoint(key, checkpointId);
|
|
145
|
+
if (!checkpoint) return c.json({
|
|
146
|
+
ok: false,
|
|
147
|
+
error: "Checkpoint not found"
|
|
148
|
+
}, 404);
|
|
149
|
+
return c.json({
|
|
150
|
+
ok: true,
|
|
151
|
+
payload: { checkpoint }
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
authenticated.post("/api/sessions/:key/compaction/restore", async (c) => {
|
|
155
|
+
const key = c.req.param("key");
|
|
156
|
+
const body = await c.req.json().catch(() => ({}));
|
|
157
|
+
const checkpointId = typeof body.checkpointId === "string" ? body.checkpointId.trim() : "";
|
|
158
|
+
if (!checkpointId) return c.json({
|
|
159
|
+
ok: false,
|
|
160
|
+
error: "checkpointId required"
|
|
161
|
+
}, 400);
|
|
162
|
+
try {
|
|
163
|
+
await service.restoreSessionCompactionCheckpoint(key, checkpointId);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
166
|
+
if (msg.includes("not found") || msg.includes("Invalid")) return c.json({
|
|
167
|
+
ok: false,
|
|
168
|
+
error: msg
|
|
169
|
+
}, 404);
|
|
170
|
+
return c.json({
|
|
171
|
+
ok: false,
|
|
172
|
+
error: msg
|
|
173
|
+
}, 500);
|
|
174
|
+
}
|
|
114
175
|
const session = await service.getSession(key);
|
|
176
|
+
if (!session) return c.json({
|
|
177
|
+
ok: false,
|
|
178
|
+
error: "Session not found"
|
|
179
|
+
}, 404);
|
|
180
|
+
return c.json({
|
|
181
|
+
ok: true,
|
|
182
|
+
session
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
authenticated.post("/api/sessions/:key/compaction/run", async (c) => {
|
|
186
|
+
const key = c.req.param("key");
|
|
187
|
+
if (!await service.getSession(key)) return c.json({
|
|
188
|
+
ok: false,
|
|
189
|
+
error: "Session not found"
|
|
190
|
+
}, 404);
|
|
191
|
+
const body = await c.req.json().catch(() => ({}));
|
|
192
|
+
const instructions = typeof body.instructions === "string" ? body.instructions : void 0;
|
|
193
|
+
const force = typeof body.force === "boolean" ? body.force : true;
|
|
194
|
+
const result = await service.runSessionCompaction(key, {
|
|
195
|
+
instructions,
|
|
196
|
+
force
|
|
197
|
+
});
|
|
198
|
+
return c.json({
|
|
199
|
+
ok: true,
|
|
200
|
+
payload: { result }
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
authenticated.get("/api/sessions/:key", async (c) => {
|
|
204
|
+
const key = c.req.param("key");
|
|
205
|
+
const includeRaw = c.req.query("include") ?? "";
|
|
206
|
+
const includeSet = new Set(includeRaw.split(",").map((s) => s.trim()).filter(Boolean));
|
|
207
|
+
const includeTranscript = includeSet.has("transcript");
|
|
208
|
+
const includeTranscriptRows = includeSet.has("transcriptRows");
|
|
209
|
+
const session = await service.getSession(key, {
|
|
210
|
+
includeTranscriptSummary: includeTranscript,
|
|
211
|
+
includeTranscriptRows
|
|
212
|
+
});
|
|
115
213
|
if (!session) return c.json({ error: "Session not found" }, 404);
|
|
116
214
|
return c.json({ session });
|
|
117
215
|
});
|
|
216
|
+
authenticated.patch("/api/sessions/:key", async (c) => {
|
|
217
|
+
const key = c.req.param("key");
|
|
218
|
+
const body = await c.req.json().catch(() => ({}));
|
|
219
|
+
const patch = {};
|
|
220
|
+
if (typeof body.name === "string") patch.name = body.name;
|
|
221
|
+
if (Array.isArray(body.tags)) patch.tags = body.tags;
|
|
222
|
+
if (typeof body.replaceTags === "boolean") patch.replaceTags = body.replaceTags;
|
|
223
|
+
if (body.customData !== void 0 && typeof body.customData === "object" && body.customData !== null) patch.customData = body.customData;
|
|
224
|
+
const result = await service.patchSession(key, patch);
|
|
225
|
+
if (result.ok === false) return c.json({
|
|
226
|
+
ok: false,
|
|
227
|
+
error: result.error
|
|
228
|
+
}, 404);
|
|
229
|
+
const session = await service.getSession(key);
|
|
230
|
+
return c.json({
|
|
231
|
+
ok: true,
|
|
232
|
+
session
|
|
233
|
+
});
|
|
234
|
+
});
|
|
118
235
|
authenticated.get("/api/sessions/:key/export", async (c) => {
|
|
119
236
|
const key = c.req.param("key");
|
|
120
237
|
const format = c.req.query("format") || "json";
|
|
@@ -179,7 +296,12 @@ function registerSessionsRoutes(authenticated, deps) {
|
|
|
179
296
|
authenticated.get("/api/subagents/:key", async (c) => {
|
|
180
297
|
const key = c.req.param("key");
|
|
181
298
|
if (!key.startsWith("subagent:")) return c.json({ error: "Not a subagent session" }, 400);
|
|
182
|
-
const
|
|
299
|
+
const includeRaw = c.req.query("include") ?? "";
|
|
300
|
+
const includeSet = new Set(includeRaw.split(",").map((s) => s.trim()).filter(Boolean));
|
|
301
|
+
const session = await service.getSession(key, {
|
|
302
|
+
includeTranscriptSummary: includeSet.has("transcript"),
|
|
303
|
+
includeTranscriptRows: includeSet.has("transcriptRows")
|
|
304
|
+
});
|
|
183
305
|
if (!session) return c.json({ error: "Subagent session not found" }, 404);
|
|
184
306
|
return c.json({ session });
|
|
185
307
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","names":[],"sources":["../../../../../src/gateway/hono/routes/sessions.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { buildSessionKey, parseSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport { messagesToClientHistory } from '../../../session/client-history.js';\n\nexport function registerSessionsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Session REST API (/api/sessions) ==========\n\n // POST /api/sessions - Create new session (reuses empty sessions)\n authenticated.post('/api/sessions', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel || 'webchat';\n const routingCfg = service.currentConfig;\n let agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim().toLowerCase()\n : getDefaultAgentId(routingCfg);\n if (!agentExists(agentId, routingCfg)) {\n agentId = getDefaultAgentId(routingCfg);\n }\n\n // If a specific chat_id is provided, use it (for advanced use cases)\n // Otherwise, try to find and reuse an existing empty session\n if (body.chat_id) {\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: body.chat_id,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n }\n \n // Look for existing empty sessions to reuse\n const existingSessions = await service.listSessions({\n channel,\n limit: 50,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n });\n \n // Reuse an empty session only when it matches the requested agent (session key embeds agent id).\n const emptySession = existingSessions.items.find((s) => {\n if (s.messageCount !== 0) return false;\n const parsed = parseSessionKey(s.key);\n return parsed?.agentId === agentId;\n });\n \n if (emptySession) {\n // Return existing empty session instead of creating a new one\n const session = await service.getSession(emptySession.key);\n return c.json({ session, reused: true }, 200);\n }\n \n // No empty session found, create a new one\n const chatId = `chat_${Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n });\n\n // GET /api/sessions - List sessions\n authenticated.get('/api/sessions', async (c) => {\n const query = c.req.query();\n const result = await service.listSessions({\n status: query.status as any,\n search: query.search,\n channel: query.channel,\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/sessions/stats - Get session stats (must be before /:key)\n authenticated.get('/api/sessions/stats', async (c) => {\n const result = await service.getSessionStats();\n return c.json(result);\n });\n\n // GET /api/sessions/chat-ids - Get unique chat IDs from sessions (must be before /:key)\n authenticated.get('/api/sessions/chat-ids', async (c) => {\n const channel = c.req.query('channel');\n const chatIds = await service.getSessionChatIds(channel || undefined);\n return c.json({ ok: true, payload: { chatIds } });\n });\n\n // GET /api/sessions/:key/agent-config — resolved session agent settings (thinking, etc.)\n authenticated.get('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const payload = await service.getSessionAgentConfig(key);\n return c.json({ ok: true, payload });\n });\n\n authenticated.patch('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const result = await service.patchSessionAgentConfig(key, body);\n if (!result.ok) {\n return c.json({ ok: false, error: result.error }, 400);\n }\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/messages — flattened transcript for TUI / clients\n authenticated.get('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const limitRaw = c.req.query('limit');\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : undefined;\n const limit =\n parsedLimit !== undefined && Number.isFinite(parsedLimit)\n ? Math.min(500, Math.max(1, parsedLimit))\n : undefined;\n\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n\n const messages = messagesToClientHistory(session.messages, { limit });\n return c.json({ ok: true, payload: { messages } });\n });\n\n // GET /api/sessions/:key - Get single session (must be after /stats and /chat-ids)\n authenticated.get('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n });\n\n // GET /api/sessions/:key/export - Export session (must be before /:key)\n authenticated.get('/api/sessions/:key/export', async (c) => {\n const key = c.req.param('key');\n const format = c.req.query('format') as any || 'json';\n const result = await service.exportSession(key, format);\n return c.json(result);\n });\n\n // DELETE /api/sessions/:key/messages — delete a range of messages by index (before whole-session DELETE)\n authenticated.delete('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const startIndex = typeof body.startIndex === 'number' ? body.startIndex : -1;\n const count = typeof body.count === 'number' ? body.count : 0;\n if (startIndex < 0 || count <= 0) {\n return c.json({ error: 'Invalid startIndex or count' }, 400);\n }\n const loaded = await service.sessionManagerInstance.loadMessages(key);\n if (!loaded || startIndex >= loaded.length) {\n return c.json({ error: 'Index out of range' }, 400);\n }\n const deleteCount = Math.min(count, loaded.length - startIndex);\n const next = loaded.slice(0, startIndex).concat(loaded.slice(startIndex + deleteCount));\n await service.sessionManagerInstance.saveMessages(key, next);\n return c.json({ ok: true, deleted: deleteCount });\n });\n\n // DELETE /api/sessions/:key - Delete session\n authenticated.delete('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const result = await service.deleteSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/archive - Archive session\n authenticated.post('/api/sessions/:key/archive', async (c) => {\n const key = c.req.param('key');\n const result = await service.archiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unarchive - Unarchive session\n authenticated.post('/api/sessions/:key/unarchive', async (c) => {\n const key = c.req.param('key');\n const result = await service.unarchiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/pin - Pin session\n authenticated.post('/api/sessions/:key/pin', async (c) => {\n const key = c.req.param('key');\n const result = await service.pinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unpin - Unpin session\n authenticated.post('/api/sessions/:key/unpin', async (c) => {\n const key = c.req.param('key');\n const result = await service.unpinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/rename - Rename session\n authenticated.post('/api/sessions/:key/rename', async (c) => {\n const key = c.req.param('key');\n\n const body = await c.req.json();\n const { name } = body;\n const result = await service.renameSession(key, name);\n return c.json(result);\n });\n\n // ========== Subagent REST API (/api/subagents) ==========\n\n // GET /api/subagents - List subagent sessions\n authenticated.get('/api/subagents', async (c) => {\n const query = c.req.query();\n const result = await service.listSubagents({\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/subagents/:key - Get subagent session detail\n authenticated.get('/api/subagents/:key', async (c) => {\n const key = c.req.param('key');\n // Verify it's a subagent session\n if (!key.startsWith('subagent:')) {\n return c.json({ error: 'Not a subagent session' }, 400);\n }\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ error: 'Subagent session not found' }, 404);\n }\n return c.json({ session });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sessions.js","names":[],"sources":["../../../../../src/gateway/hono/routes/sessions.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { buildSessionKey, parseSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport { messagesToClientHistory } from '../../../session/client-history.js';\n\nexport function registerSessionsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Session REST API (/api/sessions) ==========\n\n // POST /api/sessions - Create new session (reuses empty sessions)\n authenticated.post('/api/sessions', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel || 'webchat';\n const routingCfg = service.currentConfig;\n let agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim().toLowerCase()\n : getDefaultAgentId(routingCfg);\n if (!agentExists(agentId, routingCfg)) {\n agentId = getDefaultAgentId(routingCfg);\n }\n\n // If a specific chat_id is provided, use it (for advanced use cases)\n // Otherwise, try to find and reuse an existing empty session\n if (body.chat_id) {\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: body.chat_id,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n }\n \n // Look for existing empty sessions to reuse\n const existingSessions = await service.listSessions({\n channel,\n limit: 50,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n });\n \n // Reuse an empty session only when it matches the requested agent (session key embeds agent id).\n const emptySession = existingSessions.items.find((s) => {\n if (s.messageCount !== 0) return false;\n const parsed = parseSessionKey(s.key);\n return parsed?.agentId === agentId;\n });\n \n if (emptySession) {\n // Return existing empty session instead of creating a new one\n const session = await service.getSession(emptySession.key);\n return c.json({ session, reused: true }, 200);\n }\n \n // No empty session found, create a new one\n const chatId = `chat_${Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n });\n\n // GET /api/sessions - List sessions\n authenticated.get('/api/sessions', async (c) => {\n const query = c.req.query();\n const result = await service.listSessions({\n status: query.status as any,\n search: query.search,\n channel: query.channel,\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/sessions/stats - Get session stats (must be before /:key)\n authenticated.get('/api/sessions/stats', async (c) => {\n const result = await service.getSessionStats();\n return c.json(result);\n });\n\n // GET /api/sessions/chat-ids - Get unique chat IDs from sessions (must be before /:key)\n authenticated.get('/api/sessions/chat-ids', async (c) => {\n const channel = c.req.query('channel');\n const chatIds = await service.getSessionChatIds(channel || undefined);\n return c.json({ ok: true, payload: { chatIds } });\n });\n\n // GET /api/sessions/:key/agent-config — resolved session agent settings (thinking, etc.)\n authenticated.get('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const payload = await service.getSessionAgentConfig(key);\n return c.json({ ok: true, payload });\n });\n\n authenticated.patch('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const result = await service.patchSessionAgentConfig(key, body);\n if (!result.ok) {\n return c.json({ ok: false, error: result.error }, 400);\n }\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/messages — flattened transcript for TUI / clients\n authenticated.get('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const limitRaw = c.req.query('limit');\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : undefined;\n const limit =\n parsedLimit !== undefined && Number.isFinite(parsedLimit)\n ? Math.min(500, Math.max(1, parsedLimit))\n : undefined;\n\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n\n const messages = messagesToClientHistory(session.messages, { limit });\n return c.json({ ok: true, payload: { messages } });\n });\n\n // POST /api/sessions/:key/transcript/context — append persisted-only `kind: 'context'` row (not in LLM context)\n authenticated.post('/api/sessions/:key/transcript/context', async (c) => {\n const key = c.req.param('key');\n const meta = await service.sessionManagerInstance.getSessionMetadata(key);\n if (!meta) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const body = await c.req.json().catch(() => ({}));\n const id = typeof body.id === 'string' && body.id.trim() ? body.id.trim() : undefined;\n const text = typeof body.text === 'string' ? body.text : undefined;\n const data =\n body.data !== undefined && typeof body.data === 'object' && body.data !== null && !Array.isArray(body.data)\n ? (body.data as Record<string, unknown>)\n : undefined;\n await service.sessionManagerInstance.appendTranscriptContextEntry(key, { id, text, data });\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/compaction/checkpoints — list pre-compaction snapshots (OpenClaw-style)\n authenticated.get('/api/sessions/:key/compaction/checkpoints', async (c) => {\n const key = c.req.param('key');\n const meta = await service.sessionManagerInstance.getSessionMetadata(key);\n if (!meta) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const checkpoints = await service.listSessionCompactionCheckpoints(key);\n return c.json({ ok: true, payload: { checkpoints } });\n });\n\n authenticated.get('/api/sessions/:key/compaction/checkpoints/:checkpointId', async (c) => {\n const key = c.req.param('key');\n const checkpointId = c.req.param('checkpointId');\n const checkpoint = await service.getSessionCompactionCheckpoint(key, checkpointId);\n if (!checkpoint) {\n return c.json({ ok: false, error: 'Checkpoint not found' }, 404);\n }\n return c.json({ ok: true, payload: { checkpoint } });\n });\n\n authenticated.post('/api/sessions/:key/compaction/restore', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const checkpointId = typeof body.checkpointId === 'string' ? body.checkpointId.trim() : '';\n if (!checkpointId) {\n return c.json({ ok: false, error: 'checkpointId required' }, 400);\n }\n try {\n await service.restoreSessionCompactionCheckpoint(key, checkpointId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('not found') || msg.includes('Invalid')) {\n return c.json({ ok: false, error: msg }, 404);\n }\n return c.json({ ok: false, error: msg }, 500);\n }\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n return c.json({ ok: true, session });\n });\n\n authenticated.post('/api/sessions/:key/compaction/run', async (c) => {\n const key = c.req.param('key');\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n const body = await c.req.json().catch(() => ({}));\n const instructions = typeof body.instructions === 'string' ? body.instructions : undefined;\n const force = typeof body.force === 'boolean' ? body.force : true;\n const result = await service.runSessionCompaction(key, { instructions, force });\n return c.json({ ok: true, payload: { result } });\n });\n\n // GET /api/sessions/:key - Get single session (must be after /stats and /chat-ids)\n authenticated.get('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const includeRaw = c.req.query('include') ?? '';\n const includeSet = new Set(\n includeRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const includeTranscript = includeSet.has('transcript');\n const includeTranscriptRows = includeSet.has('transcriptRows');\n const session = await service.getSession(key, {\n includeTranscriptSummary: includeTranscript,\n includeTranscriptRows,\n });\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n });\n\n // PATCH /api/sessions/:key - Partial metadata (name, tags, customData); OpenClaw-style patch subset\n authenticated.patch('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const patch: {\n name?: string;\n tags?: string[];\n replaceTags?: boolean;\n customData?: Record<string, unknown>;\n } = {};\n if (typeof body.name === 'string') {\n patch.name = body.name;\n }\n if (Array.isArray(body.tags)) {\n patch.tags = body.tags;\n }\n if (typeof body.replaceTags === 'boolean') {\n patch.replaceTags = body.replaceTags;\n }\n if (body.customData !== undefined && typeof body.customData === 'object' && body.customData !== null) {\n patch.customData = body.customData as Record<string, unknown>;\n }\n const result = await service.patchSession(key, patch);\n if (result.ok === false) {\n return c.json({ ok: false, error: result.error }, 404);\n }\n const session = await service.getSession(key);\n return c.json({ ok: true, session });\n });\n\n // GET /api/sessions/:key/export - Export session (must be before /:key)\n authenticated.get('/api/sessions/:key/export', async (c) => {\n const key = c.req.param('key');\n const format = c.req.query('format') as any || 'json';\n const result = await service.exportSession(key, format);\n return c.json(result);\n });\n\n // DELETE /api/sessions/:key/messages — delete a range by **LLM message indices** (same order as\n // `loadMessages` / session `messages`), not raw on-disk row indices when `kind: 'context'` rows exist.\n authenticated.delete('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const startIndex = typeof body.startIndex === 'number' ? body.startIndex : -1;\n const count = typeof body.count === 'number' ? body.count : 0;\n if (startIndex < 0 || count <= 0) {\n return c.json({ error: 'Invalid startIndex or count' }, 400);\n }\n const loaded = await service.sessionManagerInstance.loadMessages(key);\n if (!loaded || startIndex >= loaded.length) {\n return c.json({ error: 'Index out of range' }, 400);\n }\n const deleteCount = Math.min(count, loaded.length - startIndex);\n const next = loaded.slice(0, startIndex).concat(loaded.slice(startIndex + deleteCount));\n await service.sessionManagerInstance.saveMessages(key, next);\n return c.json({ ok: true, deleted: deleteCount });\n });\n\n // DELETE /api/sessions/:key - Delete session\n authenticated.delete('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const result = await service.deleteSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/archive - Archive session\n authenticated.post('/api/sessions/:key/archive', async (c) => {\n const key = c.req.param('key');\n const result = await service.archiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unarchive - Unarchive session\n authenticated.post('/api/sessions/:key/unarchive', async (c) => {\n const key = c.req.param('key');\n const result = await service.unarchiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/pin - Pin session\n authenticated.post('/api/sessions/:key/pin', async (c) => {\n const key = c.req.param('key');\n const result = await service.pinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unpin - Unpin session\n authenticated.post('/api/sessions/:key/unpin', async (c) => {\n const key = c.req.param('key');\n const result = await service.unpinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/rename - Rename session\n authenticated.post('/api/sessions/:key/rename', async (c) => {\n const key = c.req.param('key');\n\n const body = await c.req.json();\n const { name } = body;\n const result = await service.renameSession(key, name);\n return c.json(result);\n });\n\n // ========== Subagent REST API (/api/subagents) ==========\n\n // GET /api/subagents - List subagent sessions\n authenticated.get('/api/subagents', async (c) => {\n const query = c.req.query();\n const result = await service.listSubagents({\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/subagents/:key - Get subagent session detail\n authenticated.get('/api/subagents/:key', async (c) => {\n const key = c.req.param('key');\n // Verify it's a subagent session\n if (!key.startsWith('subagent:')) {\n return c.json({ error: 'Not a subagent session' }, 400);\n }\n const includeRaw = c.req.query('include') ?? '';\n const includeSet = new Set(\n includeRaw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const session = await service.getSession(key, {\n includeTranscriptSummary: includeSet.has('transcript'),\n includeTranscriptRows: includeSet.has('transcriptRows'),\n });\n if (!session) {\n return c.json({ error: 'Subagent session not found' }, 404);\n }\n return c.json({ session });\n });\n}\n"],"mappings":"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"}
|
|
@@ -49,6 +49,7 @@ function createAgentSSEHandler(config) {
|
|
|
49
49
|
}
|
|
50
50
|
}, 400);
|
|
51
51
|
const { message, channel = "webchat", attachments, thinking } = body;
|
|
52
|
+
const clientCreatedAtMs = typeof body.clientCreatedAtMs === "number" && Number.isFinite(body.clientCreatedAtMs) ? body.clientCreatedAtMs : void 0;
|
|
52
53
|
const newSession = Boolean(body.newSession);
|
|
53
54
|
let chatId = "default";
|
|
54
55
|
if (newSession && channel === "webchat") chatId = `chat_${randomUUID()}`;
|
|
@@ -89,7 +90,10 @@ function createAgentSSEHandler(config) {
|
|
|
89
90
|
peerId: chatId
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
|
-
const generator = service.runAgent(message, channel, chatId, attachments, thinking, {
|
|
93
|
+
const generator = service.runAgent(message, channel, chatId, attachments, thinking, {
|
|
94
|
+
signal: clientAbort.signal,
|
|
95
|
+
...clientCreatedAtMs !== void 0 ? { clientCreatedAtMs } : {}
|
|
96
|
+
});
|
|
93
97
|
try {
|
|
94
98
|
let finalResult;
|
|
95
99
|
const tokens = [];
|
|
@@ -129,7 +133,10 @@ function createAgentSSEHandler(config) {
|
|
|
129
133
|
if (channel !== "webchat") stream.onAbort(() => {
|
|
130
134
|
clientAbort.abort();
|
|
131
135
|
});
|
|
132
|
-
const generator = service.runAgent(message, channel, chatId, attachments, thinking, {
|
|
136
|
+
const generator = service.runAgent(message, channel, chatId, attachments, thinking, {
|
|
137
|
+
signal: clientAbort.signal,
|
|
138
|
+
...clientCreatedAtMs !== void 0 ? { clientCreatedAtMs } : {}
|
|
139
|
+
});
|
|
133
140
|
let eventId = 0;
|
|
134
141
|
try {
|
|
135
142
|
while (true) {
|