@circuitwall/jarela 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +5 -5
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +14 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/access/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +27 -33
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +9 -2
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js +19 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/events/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/health/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/packages/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +27 -12
- package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/profile/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +585 -58
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/state/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +12 -6
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +125 -26
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +1 -2
- package/.next/standalone/.next/server/app/api/v1/threads/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/tools/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/watchers/route.js +1 -1
- package/.next/standalone/.next/server/app/page.js +27323 -27034
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup/page.js +8 -0
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +5 -5
- package/.next/standalone/.next/server/chunks/1388.js +106 -36
- package/.next/standalone/.next/server/chunks/2068.js +47 -10
- package/.next/standalone/.next/server/chunks/210.js +6 -6
- package/.next/standalone/.next/server/chunks/2447.js +10 -5
- package/.next/standalone/.next/server/chunks/2653.js +80 -1
- package/.next/standalone/.next/server/chunks/3042.js +10 -8
- package/.next/standalone/.next/server/chunks/{4540.js → 309.js} +104 -38
- package/.next/standalone/.next/server/chunks/{2350.js → 3272.js} +104 -37
- package/.next/standalone/.next/server/chunks/3524.js +150 -67
- package/.next/standalone/.next/server/chunks/3566.js +1 -1
- package/.next/standalone/.next/server/chunks/4189.js +1 -1
- package/.next/standalone/.next/server/chunks/4596.js +28 -4
- package/.next/standalone/.next/server/chunks/46.js +91 -31
- package/.next/standalone/.next/server/chunks/466.js +53 -7
- package/.next/standalone/.next/server/chunks/4955.js +30 -3
- package/.next/standalone/.next/server/chunks/5585.js +28 -4
- package/.next/standalone/.next/server/chunks/5908.js +63 -42
- package/.next/standalone/.next/server/chunks/6142.js +10 -2
- package/.next/standalone/.next/server/chunks/8461.js +10 -8
- package/.next/standalone/.next/server/chunks/9032.js +5 -5
- package/.next/standalone/.next/server/chunks/9164.js +487 -177
- package/.next/standalone/.next/server/chunks/9304.js +51 -12
- package/.next/standalone/.next/server/chunks/{423.js → 9590.js} +84 -24
- package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
- package/.next/standalone/.next/server/middleware.js +89 -21
- package/.next/standalone/.next/server/pages/404.html +14 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{1395-e4a99912b8f83044.js → 1395-bfe1f3ef760c0f50.js} +54 -8
- package/.next/standalone/.next/static/chunks/app/{layout-9bc0b10127cb7d42.js → layout-7b24ad13faa3944b.js} +69 -2
- package/.next/standalone/.next/static/chunks/app/{page-213a623b37226452.js → page-2ef8d75d40eb4311.js} +10643 -10295
- package/.next/standalone/.next/static/css/c160ea862133acd2.css +5 -0
- package/.next/standalone/docs/adoption/changesets.json +2805 -0
- package/.next/standalone/package.json +1 -1
- package/CHANGELOG.md +52 -0
- package/api/client.models.test.ts +10 -0
- package/api/client.startup.test.ts +129 -0
- package/api/client.ts +51 -9
- package/api/thread-metadata.test.ts +72 -0
- package/api/types.ts +6 -3
- package/app/api/v1/providers/[provider]/models/route.test.ts +216 -6
- package/app/api/v1/providers/[provider]/models/route.ts +259 -40
- package/app/api/v1/threads/[thread_id]/route.ts +26 -23
- package/app/api/v1/threads/[thread_id]/run/route.ts +0 -1
- package/app/globals.css +119 -29
- package/app/layout.tsx +12 -0
- package/components/agents/AgentsPanel.tsx +5 -13
- package/components/chat/ChatView.tsx +9 -18
- package/components/chat/InputBar.tsx +1 -1
- package/components/chat/MessageBubble.tsx +13 -1
- package/components/chat/MessageList.test.tsx +45 -4
- package/components/chat/MessageList.tsx +123 -89
- package/components/chat/ToolList.tsx +88 -84
- package/components/chat/useThreadActivity.test.tsx +2 -2
- package/components/chat/useThreadActivity.ts +2 -2
- package/components/chat/useThreadData.ts +1 -30
- package/components/chat/useThreadMetadataPolling.test.tsx +128 -0
- package/components/chat/useThreadMetadataPolling.ts +50 -0
- package/components/chat/useUserProfileAndAgent.test.tsx +31 -0
- package/components/chat/useUserProfileAndAgent.ts +13 -2
- package/components/dashboard/DashboardPanel.tsx +1 -1
- package/components/dashboard/Series.tsx +34 -21
- package/components/dashboard/SummaryCards.tsx +1 -1
- package/components/integrations/NetworkSection.tsx +2 -2
- package/components/layout/AppShell.tsx +22 -7
- package/components/layout/MenuPanel.tsx +14 -24
- package/components/profile/ProfilePanel.tsx +2 -2
- package/components/settings/AppearancePanel.tsx +70 -3
- package/components/settings/SettingsPanel.tsx +2 -2
- package/components/tools/ToolsPanel.tsx +2 -7
- package/components/ui/AppearancePreferences.test.tsx +68 -0
- package/components/ui/BootScreen.test.tsx +44 -0
- package/components/ui/BootScreen.tsx +24 -11
- package/components/ui/NotificationStatus.test.tsx +2 -2
- package/components/ui/NotificationStatus.tsx +5 -5
- package/components/ui/SubTabBar.tsx +2 -3
- package/contexts/ThemeContext.tsx +84 -1
- package/hooks/useAgentSession.test.ts +12 -1
- package/hooks/useAgentSession.ts +6 -4
- package/hooks/useUrlSync.test.ts +13 -0
- package/hooks/useUrlSync.ts +0 -4
- package/lib/agents/citation-checker.test.ts +40 -2
- package/lib/agents/citation-checker.ts +56 -11
- package/lib/agents/context-boundary.ts +5 -6
- package/lib/agents/instruction-edits.test.ts +120 -0
- package/lib/agents/instruction-edits.ts +65 -42
- package/lib/agents/prepare/request.ts +0 -2
- package/lib/agents/prepare/system-prompt.test.ts +10 -0
- package/lib/agents/prepare/system-prompt.ts +8 -2
- package/lib/agents/proposals.test.ts +76 -0
- package/lib/agents/proposals.ts +13 -5
- package/lib/agents/run-thread.auto-boundary.test.ts +125 -5
- package/lib/agents/run-thread.ts +24 -9
- package/lib/agents/sqlite-checkpoint-saver.test.ts +91 -0
- package/lib/agents/warm-summary-background.ts +22 -2
- package/lib/agents/warm-topics.test.ts +155 -1
- package/lib/agents/warm-topics.ts +27 -7
- package/lib/bridges/dispatcher.ts +1 -0
- package/lib/bridges/message-role.test.ts +81 -0
- package/lib/bridges/message-role.ts +23 -10
- package/lib/bridges/types.ts +6 -0
- package/lib/bridges/whatsapp-link.test.ts +32 -0
- package/lib/bridges/whatsapp-link.ts +21 -0
- package/lib/bridges/whatsapp.inbound.test.ts +239 -0
- package/lib/bridges/whatsapp.sender.test.ts +80 -1
- package/lib/bridges/whatsapp.ts +76 -38
- package/lib/db/migrations.test.ts +61 -0
- package/lib/db/migrations.ts +13 -0
- package/lib/embeddings/performance.test.ts +114 -0
- package/lib/pricing/snapshot.test.ts +70 -0
- package/lib/pricing/snapshot.ts +10 -2
- package/lib/proxy/dispatcher.test.ts +119 -1
- package/lib/proxy/dispatcher.ts +22 -9
- package/lib/stores/agent-configs.ts +10 -5
- package/lib/stores/bridges.test.ts +81 -0
- package/lib/stores/bridges.ts +9 -8
- package/lib/stores/dashboard-metrics-cache.test.ts +99 -0
- package/lib/stores/dashboard-metrics.ts +30 -4
- package/lib/stores/message-embedding-jobs.test.ts +27 -0
- package/lib/stores/message-embedding-jobs.ts +5 -3
- package/lib/stores/message-usage.test.ts +21 -1
- package/lib/stores/pricing-cache.test.ts +31 -0
- package/lib/stores/pricing.ts +3 -0
- package/lib/stores/proxy-config.test.ts +120 -0
- package/lib/stores/proxy-config.ts +22 -4
- package/lib/stores/threads.ts +12 -8
- package/lib/tools/communications/calendar.test.ts +43 -2
- package/lib/tools/communications/calendar.ts +2 -0
- package/lib/tools/communications/gmail.test.ts +51 -1
- package/lib/tools/communications/gmail.ts +44 -2
- package/lib/tools/communications/outlook-calendar.ts +2 -0
- package/lib/tools/communications/outlook.test.ts +33 -2
- package/lib/tools/communications/outlook.ts +2 -0
- package/lib/tools/filesystem/edit-match.test.ts +133 -0
- package/lib/tools/filesystem/edit-match.ts +7 -2
- package/lib/tools/packages/default-packages.test.ts +21 -0
- package/lib/tools/packages/optional-package.test.ts +72 -0
- package/lib/tools/packages/optional-package.ts +33 -4
- package/lib/tools/support/result-refs.test.ts +131 -0
- package/lib/tools/support/result-refs.ts +41 -9
- package/lib/ui/navigate.test.ts +13 -0
- package/lib/ui/navigate.ts +10 -2
- package/lib/utils/source-link.test.ts +51 -0
- package/lib/utils/source-link.ts +45 -0
- package/package.json +1 -1
- package/.next/standalone/.next/static/css/312542a5725ba0d5.css +0 -5
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_ssgManifest.js +0 -0
|
@@ -64,6 +64,9 @@ function runMigrations(db) {
|
|
|
64
64
|
-- (getMessages, getRecentMessagesWindow, getMessagesPage, clear).
|
|
65
65
|
-- Without this every read full-scans the messages table.
|
|
66
66
|
CREATE INDEX IF NOT EXISTS idx_messages_thread_id ON messages(thread_id, created_at);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_messages_thread_seq ON messages(thread_id);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_threads_updated ON threads(updated_at DESC);
|
|
67
70
|
CREATE TABLE IF NOT EXISTS runtime_operations (
|
|
68
71
|
id TEXT PRIMARY KEY,
|
|
69
72
|
kind TEXT NOT NULL,
|
|
@@ -87,6 +90,9 @@ function runMigrations(db) {
|
|
|
87
90
|
created_at INTEGER NOT NULL,
|
|
88
91
|
UNIQUE(kind,operation_id,agent_id,thread_id)
|
|
89
92
|
);
|
|
93
|
+
CREATE INDEX IF NOT EXISTS idx_runtime_operations_thread_state ON runtime_operations(thread_id,state);
|
|
94
|
+
CREATE INDEX IF NOT EXISTS idx_signal_events_thread ON signal_events(thread_id);
|
|
95
|
+
CREATE INDEX IF NOT EXISTS idx_signal_events_operation ON signal_events(operation_id);
|
|
90
96
|
CREATE TABLE IF NOT EXISTS signal_deliveries (
|
|
91
97
|
event_id TEXT PRIMARY KEY REFERENCES signal_events(id) ON DELETE CASCADE,
|
|
92
98
|
wake_eligible INTEGER NOT NULL DEFAULT 0,
|
|
@@ -101,6 +107,7 @@ function runMigrations(db) {
|
|
|
101
107
|
);
|
|
102
108
|
CREATE INDEX IF NOT EXISTS idx_signal_events_target ON signal_events(agent_id,thread_id,seq);
|
|
103
109
|
CREATE INDEX IF NOT EXISTS idx_signal_deliveries_due ON signal_deliveries(state,available_at);
|
|
110
|
+
CREATE INDEX IF NOT EXISTS idx_signal_deliveries_lease ON signal_deliveries(state,lease_until);
|
|
104
111
|
CREATE TABLE IF NOT EXISTS background_tool_results (
|
|
105
112
|
key TEXT PRIMARY KEY REFERENCES runtime_operations(id) ON DELETE CASCADE,
|
|
106
113
|
thread_id TEXT NOT NULL REFERENCES threads(thread_id) ON DELETE CASCADE,
|
|
@@ -112,6 +119,7 @@ function runMigrations(db) {
|
|
|
112
119
|
expires_at INTEGER NOT NULL
|
|
113
120
|
);
|
|
114
121
|
CREATE INDEX IF NOT EXISTS idx_background_results_owner ON background_tool_results(thread_id,expires_at);
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_background_results_expiry ON background_tool_results(expires_at);
|
|
115
123
|
CREATE TABLE IF NOT EXISTS memory_store (
|
|
116
124
|
namespace TEXT NOT NULL,
|
|
117
125
|
key TEXT NOT NULL,
|
|
@@ -120,6 +128,8 @@ function runMigrations(db) {
|
|
|
120
128
|
updated_at TEXT NOT NULL,
|
|
121
129
|
PRIMARY KEY (namespace, key)
|
|
122
130
|
);
|
|
131
|
+
CREATE INDEX IF NOT EXISTS idx_memory_namespace_updated ON memory_store(namespace,updated_at DESC);
|
|
132
|
+
CREATE INDEX IF NOT EXISTS idx_memory_updated ON memory_store(updated_at DESC);
|
|
123
133
|
CREATE TABLE IF NOT EXISTS model_configs (
|
|
124
134
|
name TEXT PRIMARY KEY,
|
|
125
135
|
provider TEXT NOT NULL,
|
|
@@ -693,6 +703,7 @@ function ensureMessageUsageTable(db) {
|
|
|
693
703
|
);
|
|
694
704
|
CREATE INDEX IF NOT EXISTS idx_message_usage_created_at ON message_usage(created_at);
|
|
695
705
|
CREATE INDEX IF NOT EXISTS idx_message_usage_agent_id ON message_usage(agent_id);
|
|
706
|
+
CREATE INDEX IF NOT EXISTS idx_message_usage_thread_created ON message_usage(thread_id,created_at DESC);
|
|
696
707
|
`);
|
|
697
708
|
}
|
|
698
709
|
function ensureEmbeddingColumns(db) {
|
|
@@ -732,6 +743,8 @@ function ensureMessageEmbeddingJobsTable(db) {
|
|
|
732
743
|
);
|
|
733
744
|
CREATE INDEX IF NOT EXISTS idx_message_embedding_jobs_due
|
|
734
745
|
ON message_embedding_jobs(state, available_at_ms, lease_until_ms);
|
|
746
|
+
CREATE INDEX IF NOT EXISTS idx_message_embedding_jobs_lease
|
|
747
|
+
ON message_embedding_jobs(state, lease_until_ms);
|
|
735
748
|
INSERT OR IGNORE INTO message_embedding_jobs (message_id, created_at, updated_at)
|
|
736
749
|
SELECT msg_id, created_at, created_at FROM messages WHERE embedding IS NULL;
|
|
737
750
|
`);
|
|
@@ -6155,9 +6168,11 @@ function claimMessageEmbeddingJobs(limit = 16, leaseMs = 5 * 60000, nowMs = Date
|
|
|
6155
6168
|
});
|
|
6156
6169
|
}
|
|
6157
6170
|
function nextMessageEmbeddingDelayMs(nowMs = Date.now()) {
|
|
6158
|
-
const row = (0,_lib_db__WEBPACK_IMPORTED_MODULE_2__/* .getDb */ .Lf)().prepare(`SELECT MIN(
|
|
6159
|
-
|
|
6160
|
-
|
|
6171
|
+
const row = (0,_lib_db__WEBPACK_IMPORTED_MODULE_2__/* .getDb */ .Lf)().prepare(`SELECT MIN(next_at_ms) AS next_at_ms FROM (
|
|
6172
|
+
SELECT MIN(available_at_ms) AS next_at_ms FROM message_embedding_jobs WHERE state='pending'
|
|
6173
|
+
UNION ALL
|
|
6174
|
+
SELECT MIN(lease_until_ms) AS next_at_ms FROM message_embedding_jobs WHERE state='processing'
|
|
6175
|
+
)`).get();
|
|
6161
6176
|
return typeof row?.next_at_ms === "number" ? Math.max(0, row.next_at_ms - nowMs) : null;
|
|
6162
6177
|
}
|
|
6163
6178
|
function completeMessageEmbeddingJob(job, embedding, modelSignature) {
|
|
@@ -8680,7 +8695,25 @@ async function applyProxyConfigFromDb() {
|
|
|
8680
8695
|
// ---------------------------------------------------------------------
|
|
8681
8696
|
function buildProxyUrl(scheme, host, port, username, password) {
|
|
8682
8697
|
const auth = username ? `${encodeURIComponent(username)}${password ? `:${encodeURIComponent(password)}` : ""}@` : "";
|
|
8683
|
-
|
|
8698
|
+
const urlHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
8699
|
+
return `${scheme}://${auth}${urlHost}:${port}`;
|
|
8700
|
+
}
|
|
8701
|
+
// undici's EnvHttpProxyAgent has no implicit loopback exemption, so without
|
|
8702
|
+
// these a configured proxy would also receive local traffic (Ollama, the
|
|
8703
|
+
// WhatsApp bridge sidecar, the app's own loopback API).
|
|
8704
|
+
const LOOPBACK_NO_PROXY = [
|
|
8705
|
+
"localhost",
|
|
8706
|
+
"127.0.0.1",
|
|
8707
|
+
"::1"
|
|
8708
|
+
];
|
|
8709
|
+
function mergeNoProxy(noProxy) {
|
|
8710
|
+
const entries = (noProxy ?? "").split(/[,\s]+/).map((entry)=>entry.trim()).filter(Boolean);
|
|
8711
|
+
return [
|
|
8712
|
+
...new Set([
|
|
8713
|
+
...entries,
|
|
8714
|
+
...LOOPBACK_NO_PROXY
|
|
8715
|
+
])
|
|
8716
|
+
].join(",");
|
|
8684
8717
|
}
|
|
8685
8718
|
function installProxy(url, noProxy, caBundle) {
|
|
8686
8719
|
// Set process.env so EnvHttpProxyAgent honors NO_PROXY semantics
|
|
@@ -8688,27 +8721,31 @@ function installProxy(url, noProxy, caBundle) {
|
|
|
8688
8721
|
// We still treat the boot-time env snapshot as authoritative for the
|
|
8689
8722
|
// "env beats DB" rule — this mutation only happens after we've
|
|
8690
8723
|
// confirmed the user did NOT set HTTP_PROXY at launch.
|
|
8724
|
+
const merged = mergeNoProxy(noProxy);
|
|
8691
8725
|
process.env.HTTP_PROXY = url;
|
|
8692
8726
|
process.env.HTTPS_PROXY = url;
|
|
8693
|
-
|
|
8694
|
-
process.env.NO_PROXY = noProxy.trim();
|
|
8695
|
-
} else {
|
|
8696
|
-
delete process.env.NO_PROXY;
|
|
8697
|
-
}
|
|
8727
|
+
process.env.NO_PROXY = merged;
|
|
8698
8728
|
// ADR-0012: when the user pasted a corporate root CA, inject it on
|
|
8699
8729
|
// both TLS legs — the proxy hop (proxyTls) for https-scheme proxies
|
|
8700
8730
|
// signed by the corporate root, and the upstream tunnel (requestTls)
|
|
8701
8731
|
// for proxies that MITM outbound HTTPS with the same internal CA.
|
|
8702
8732
|
// Same blob is correct: the corporate trust chain typically signs
|
|
8703
8733
|
// both ends.
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8734
|
+
// Pass the values explicitly too: undici prefers lowercase http_proxy /
|
|
8735
|
+
// no_proxy from the environment over the uppercase ones set above.
|
|
8736
|
+
const opts = {
|
|
8737
|
+
httpProxy: url,
|
|
8738
|
+
httpsProxy: url,
|
|
8739
|
+
noProxy: merged,
|
|
8740
|
+
...caBundle ? {
|
|
8741
|
+
requestTls: {
|
|
8742
|
+
ca: caBundle
|
|
8743
|
+
},
|
|
8744
|
+
proxyTls: {
|
|
8745
|
+
ca: caBundle
|
|
8746
|
+
}
|
|
8747
|
+
} : {}
|
|
8748
|
+
};
|
|
8712
8749
|
(0,external_undici_.setGlobalDispatcher)(new external_undici_.EnvHttpProxyAgent(opts));
|
|
8713
8750
|
}
|
|
8714
8751
|
function resetToBaseline() {
|
|
@@ -10776,9 +10813,11 @@ function getIntegrationMeta(name) {
|
|
|
10776
10813
|
/* harmony export */ qt: () => (/* binding */ saveProxyConfig),
|
|
10777
10814
|
/* harmony export */ xl: () => (/* binding */ getProxyConfigRaw)
|
|
10778
10815
|
/* harmony export */ });
|
|
10779
|
-
/* harmony import */ var
|
|
10780
|
-
/* harmony import */ var
|
|
10781
|
-
/* harmony import */ var
|
|
10816
|
+
/* harmony import */ var node_net__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(77030);
|
|
10817
|
+
/* harmony import */ var node_net__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_net__WEBPACK_IMPORTED_MODULE_0__);
|
|
10818
|
+
/* harmony import */ var _lib_db__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46);
|
|
10819
|
+
/* harmony import */ var _lib_crypto_envelope__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10938);
|
|
10820
|
+
/* harmony import */ var _lib_stores_integrations__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(78228);
|
|
10782
10821
|
// Proxy configuration store (ADR-0009, extended ADR-0012).
|
|
10783
10822
|
//
|
|
10784
10823
|
// Single-row table proxy_config. Non-secret columns are plaintext for
|
|
@@ -10798,6 +10837,7 @@ function getIntegrationMeta(name) {
|
|
|
10798
10837
|
|
|
10799
10838
|
|
|
10800
10839
|
|
|
10840
|
+
|
|
10801
10841
|
const DEFAULT_STATUS = {
|
|
10802
10842
|
mode: "off",
|
|
10803
10843
|
scheme: "http",
|
|
@@ -10818,7 +10858,7 @@ function getProxyConfigStatus() {
|
|
|
10818
10858
|
host: row.host,
|
|
10819
10859
|
port: row.port,
|
|
10820
10860
|
username: row.username,
|
|
10821
|
-
password: row.password ?
|
|
10861
|
+
password: row.password ? _lib_stores_integrations__WEBPACK_IMPORTED_MODULE_3__/* .SECRET_MASK */ .Q6 : null,
|
|
10822
10862
|
no_proxy: row.no_proxy,
|
|
10823
10863
|
ca_bundle: row.ca_bundle,
|
|
10824
10864
|
updated_at: row.updated_at
|
|
@@ -10836,7 +10876,7 @@ function getProxyConfigRaw() {
|
|
|
10836
10876
|
host: row.host,
|
|
10837
10877
|
port: row.port,
|
|
10838
10878
|
username: row.username,
|
|
10839
|
-
password: row.password ? (0,
|
|
10879
|
+
password: row.password ? (0,_lib_crypto_envelope__WEBPACK_IMPORTED_MODULE_2__/* .decryptIfNeeded */ .qU)(row.password) : null,
|
|
10840
10880
|
no_proxy: row.no_proxy,
|
|
10841
10881
|
ca_bundle: row.ca_bundle,
|
|
10842
10882
|
updated_at: row.updated_at
|
|
@@ -10848,15 +10888,26 @@ function saveProxyConfig(input) {
|
|
|
10848
10888
|
};
|
|
10849
10889
|
const scheme = input.scheme === "https" ? "https" : "http";
|
|
10850
10890
|
// Manual mode requires host + port. system / off don't.
|
|
10891
|
+
let host = nullable(input.host);
|
|
10851
10892
|
if (input.mode === "manual") {
|
|
10852
|
-
if (!
|
|
10893
|
+
if (!host) return {
|
|
10853
10894
|
error: "host is required in manual mode"
|
|
10854
10895
|
};
|
|
10855
|
-
|
|
10896
|
+
const normalisedHost = normaliseProxyHost(host);
|
|
10897
|
+
if (!normalisedHost) {
|
|
10856
10898
|
return {
|
|
10857
|
-
error: "
|
|
10899
|
+
error: "host must be a hostname or IP address, without scheme, port, path or credentials"
|
|
10858
10900
|
};
|
|
10859
10901
|
}
|
|
10902
|
+
host = normalisedHost;
|
|
10903
|
+
if (input.port == null) return {
|
|
10904
|
+
error: "port must be between 1 and 65535"
|
|
10905
|
+
};
|
|
10906
|
+
}
|
|
10907
|
+
if (input.port != null && (!Number.isInteger(input.port) || input.port <= 0 || input.port > 65535)) {
|
|
10908
|
+
return {
|
|
10909
|
+
error: "port must be between 1 and 65535"
|
|
10910
|
+
};
|
|
10860
10911
|
}
|
|
10861
10912
|
// CA bundle: empty/null clears; non-empty must look like PEM.
|
|
10862
10913
|
let storedCaBundle = null;
|
|
@@ -10871,15 +10922,15 @@ function saveProxyConfig(input) {
|
|
|
10871
10922
|
// Preserve existing password when the UI echoes back the masked sentinel.
|
|
10872
10923
|
const existing = readRow();
|
|
10873
10924
|
let storedPassword = null;
|
|
10874
|
-
if (input.password ===
|
|
10925
|
+
if (input.password === _lib_stores_integrations__WEBPACK_IMPORTED_MODULE_3__/* .SECRET_MASK */ .Q6) {
|
|
10875
10926
|
storedPassword = existing?.password ?? null;
|
|
10876
10927
|
} else if (input.password && input.password.length > 0) {
|
|
10877
|
-
storedPassword = (0,
|
|
10928
|
+
storedPassword = (0,_lib_crypto_envelope__WEBPACK_IMPORTED_MODULE_2__/* .encrypt */ .w)(input.password);
|
|
10878
10929
|
} else {
|
|
10879
10930
|
storedPassword = null;
|
|
10880
10931
|
}
|
|
10881
10932
|
const now = new Date().toISOString();
|
|
10882
|
-
const db = (0,
|
|
10933
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
10883
10934
|
db.prepare(`INSERT INTO proxy_config (id, mode, scheme, host, port, username, password, no_proxy, ca_bundle, updated_at)
|
|
10884
10935
|
VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
10885
10936
|
ON CONFLICT(id) DO UPDATE SET
|
|
@@ -10891,16 +10942,16 @@ function saveProxyConfig(input) {
|
|
|
10891
10942
|
password = excluded.password,
|
|
10892
10943
|
no_proxy = excluded.no_proxy,
|
|
10893
10944
|
ca_bundle = excluded.ca_bundle,
|
|
10894
|
-
updated_at = excluded.updated_at`).run(input.mode, scheme,
|
|
10945
|
+
updated_at = excluded.updated_at`).run(input.mode, scheme, host, input.port ?? null, nullable(input.username), storedPassword, nullable(input.no_proxy), storedCaBundle, now);
|
|
10895
10946
|
return getProxyConfigStatus();
|
|
10896
10947
|
}
|
|
10897
10948
|
function deleteProxyConfig() {
|
|
10898
|
-
const db = (0,
|
|
10949
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
10899
10950
|
const r = db.prepare("DELETE FROM proxy_config WHERE id = 1").run();
|
|
10900
10951
|
return r.changes > 0;
|
|
10901
10952
|
}
|
|
10902
10953
|
function readRow() {
|
|
10903
|
-
const db = (0,
|
|
10954
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
10904
10955
|
const r = db.prepare("SELECT mode, scheme, host, port, username, password, no_proxy, ca_bundle, updated_at FROM proxy_config WHERE id = 1").get();
|
|
10905
10956
|
return r ?? null;
|
|
10906
10957
|
}
|
|
@@ -10913,6 +10964,15 @@ function normaliseMode(m) {
|
|
|
10913
10964
|
function normaliseScheme(s) {
|
|
10914
10965
|
return s === "https" ? "https" : "http";
|
|
10915
10966
|
}
|
|
10967
|
+
// The dispatcher builds `${scheme}://${auth}${host}:${port}`, so a pasted URL
|
|
10968
|
+
// or host:port would produce an unusable proxy URL. IPv6 is stored unbracketed;
|
|
10969
|
+
// the dispatcher adds the brackets.
|
|
10970
|
+
function normaliseProxyHost(host) {
|
|
10971
|
+
const unbracketed = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
10972
|
+
if (/^[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?$/.test(unbracketed)) return unbracketed;
|
|
10973
|
+
if ((0,node_net__WEBPACK_IMPORTED_MODULE_0__.isIPv6)(unbracketed)) return unbracketed;
|
|
10974
|
+
return null;
|
|
10975
|
+
}
|
|
10916
10976
|
function nullable(v) {
|
|
10917
10977
|
if (v == null) return null;
|
|
10918
10978
|
const trimmed = v.trim();
|
|
@@ -734,11 +734,44 @@ async function parseJsonResponse(res) {
|
|
|
734
734
|
const stream = source.pipeThrough(new DecompressionStream("gzip"));
|
|
735
735
|
return JSON.parse(await new Response(stream).text());
|
|
736
736
|
}
|
|
737
|
+
const STARTUP_TTL_MS = 5000;
|
|
738
|
+
const startupReads = new Map();
|
|
739
|
+
function startupRead(path) {
|
|
740
|
+
const now = Date.now();
|
|
741
|
+
for (const [key, entry] of startupReads){
|
|
742
|
+
if (entry.settledAt !== null && (now < entry.settledAt || now - entry.settledAt >= STARTUP_TTL_MS)) {
|
|
743
|
+
startupReads.delete(key);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
const cached = startupReads.get(path);
|
|
747
|
+
if (cached) return cached.promise.then((value)=>structuredClone(value));
|
|
748
|
+
// Bound retained startup data when agents are switched rapidly.
|
|
749
|
+
const oldestKey = startupReads.keys().next().value;
|
|
750
|
+
if (startupReads.size >= 16 && oldestKey !== undefined) startupReads.delete(oldestKey);
|
|
751
|
+
const entry = {
|
|
752
|
+
promise: Promise.resolve(undefined),
|
|
753
|
+
settledAt: null
|
|
754
|
+
};
|
|
755
|
+
entry.promise = request(path, {
|
|
756
|
+
startup: true
|
|
757
|
+
}).then((value)=>{
|
|
758
|
+
entry.settledAt = Date.now();
|
|
759
|
+
return value;
|
|
760
|
+
}).catch((error)=>{
|
|
761
|
+
if (startupReads.get(path) === entry) startupReads.delete(path);
|
|
762
|
+
throw error;
|
|
763
|
+
});
|
|
764
|
+
startupReads.set(path, entry);
|
|
765
|
+
return entry.promise.then((value)=>structuredClone(value));
|
|
766
|
+
}
|
|
737
767
|
async function request(path, init) {
|
|
768
|
+
const mutation = !!init?.method && init.method !== "GET";
|
|
769
|
+
if (mutation) startupReads.clear();
|
|
770
|
+
else if (!init?.startup) startupReads.delete(path);
|
|
738
771
|
const cfg = (0,_runtime_config__WEBPACK_IMPORTED_MODULE_0__/* .runtimeConfig */ .Z)();
|
|
739
772
|
const maxAttempts = Math.max(1, cfg.httpMaxAttempts);
|
|
740
773
|
const timeoutMs = init?.timeoutMs ?? cfg.httpRequestTimeoutMs;
|
|
741
|
-
const { timeoutMs: _ignoreTimeoutMs, ...fetchInit } = init ?? {};
|
|
774
|
+
const { timeoutMs: _ignoreTimeoutMs, startup: _ignoreStartup, ...fetchInit } = init ?? {};
|
|
742
775
|
const callerSignal = fetchInit.signal ?? null;
|
|
743
776
|
let lastErr = null;
|
|
744
777
|
for(let attempt = 1; attempt <= maxAttempts; attempt++){
|
|
@@ -792,6 +825,7 @@ async function request(path, init) {
|
|
|
792
825
|
if (attempt < maxAttempts && isRetryable(err)) continue;
|
|
793
826
|
throw err;
|
|
794
827
|
} finally{
|
|
828
|
+
if (mutation) startupReads.clear();
|
|
795
829
|
clearTimeout(timer);
|
|
796
830
|
callerSignal?.removeEventListener("abort", onCallerAbort);
|
|
797
831
|
}
|
|
@@ -802,7 +836,10 @@ async function request(path, init) {
|
|
|
802
836
|
const api = {
|
|
803
837
|
agents: {
|
|
804
838
|
list: (opts)=>cachedList(agentListCache, ()=>request("/agents"), setAgentListCache, opts?.force === true),
|
|
805
|
-
get: (id)=>
|
|
839
|
+
get: (id, opts)=>{
|
|
840
|
+
const path = `/agents/${encodeURIComponent(id)}`;
|
|
841
|
+
return opts?.startup ? startupRead(path) : request(path);
|
|
842
|
+
},
|
|
806
843
|
create: async (data)=>{
|
|
807
844
|
const created = await request("/agents", {
|
|
808
845
|
method: "POST",
|
|
@@ -834,7 +871,10 @@ const api = {
|
|
|
834
871
|
}
|
|
835
872
|
return res;
|
|
836
873
|
},
|
|
837
|
-
getThread: (id)=>
|
|
874
|
+
getThread: (id, opts)=>{
|
|
875
|
+
const path = `/agents/${encodeURIComponent(id)}/thread`;
|
|
876
|
+
return opts?.startup ? startupRead(path) : request(path);
|
|
877
|
+
},
|
|
838
878
|
compact: (id, options)=>request(`/agents/${encodeURIComponent(id)}/compact`, // Conversation summarization can take longer than normal API calls,
|
|
839
879
|
// so avoid tripping the default HTTP timeout for large threads.
|
|
840
880
|
{
|
|
@@ -1053,8 +1093,12 @@ const api = {
|
|
|
1053
1093
|
// user+assistant pair instead of re-pulling the whole most-recent page.
|
|
1054
1094
|
if (opts?.after !== undefined) p.set("after", String(opts.after));
|
|
1055
1095
|
const qs = p.toString() ? `?${p}` : "";
|
|
1056
|
-
|
|
1096
|
+
const path = `/threads/${thread_id}${qs}`;
|
|
1097
|
+
return opts?.startup ? startupRead(path) : request(path);
|
|
1057
1098
|
},
|
|
1099
|
+
metadata: (thread_id, signal)=>request(`/threads/${thread_id}?view=metadata`, {
|
|
1100
|
+
signal
|
|
1101
|
+
}),
|
|
1058
1102
|
delete: (thread_id)=>request(`/threads/${thread_id}`, {
|
|
1059
1103
|
method: "DELETE"
|
|
1060
1104
|
}),
|
|
@@ -1253,7 +1297,7 @@ const api = {
|
|
|
1253
1297
|
}
|
|
1254
1298
|
},
|
|
1255
1299
|
profile: {
|
|
1256
|
-
get: ()=>request("/profile"),
|
|
1300
|
+
get: (opts)=>opts?.startup ? startupRead("/profile") : request("/profile"),
|
|
1257
1301
|
update: (data)=>request("/profile", {
|
|
1258
1302
|
method: "PUT",
|
|
1259
1303
|
body: JSON.stringify(data)
|
|
@@ -1737,6 +1781,7 @@ const api = {
|
|
|
1737
1781
|
* caller is expected to follow up with `subscribeRun()` to receive the
|
|
1738
1782
|
* chunk stream. Idempotent in the sense that two simultaneous submissions
|
|
1739
1783
|
* for the same thread will see one 202 and one 409 (`run_in_flight`). */ async function submitRun(thread_id, message, signal, stream_options, attachments, channels, hot_since_seq) {
|
|
1784
|
+
startupReads.clear();
|
|
1740
1785
|
const payload = {
|
|
1741
1786
|
message,
|
|
1742
1787
|
stream_options,
|
|
@@ -1752,7 +1797,7 @@ const api = {
|
|
|
1752
1797
|
},
|
|
1753
1798
|
body: JSON.stringify(runPayload),
|
|
1754
1799
|
signal
|
|
1755
|
-
});
|
|
1800
|
+
}).finally(()=>startupReads.clear());
|
|
1756
1801
|
// 2xx = accepted (currently always 202); 409 = already running. We treat
|
|
1757
1802
|
// every other status as a hard error so the consumer's catch fires.
|
|
1758
1803
|
if (res.status === 202) {
|
|
@@ -9841,6 +9886,7 @@ const Select = /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_1___default().forwar
|
|
|
9841
9886
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
9842
9887
|
|
|
9843
9888
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
9889
|
+
/* harmony export */ Dg: () => (/* binding */ getAppAccentColor),
|
|
9844
9890
|
/* harmony export */ E2: () => (/* binding */ UPSTREAM_URL),
|
|
9845
9891
|
/* harmony export */ SN: () => (/* binding */ getAppIssueUrl),
|
|
9846
9892
|
/* harmony export */ YC: () => (/* binding */ UPSTREAM_NAME),
|
|
@@ -9849,7 +9895,7 @@ const Select = /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_1___default().forwar
|
|
|
9849
9895
|
/* harmony export */ lE: () => (/* binding */ getAppLogoDark),
|
|
9850
9896
|
/* harmony export */ qc: () => (/* binding */ getAppIcons)
|
|
9851
9897
|
/* harmony export */ });
|
|
9852
|
-
/* unused harmony exports getAppShortName, getAppDescription,
|
|
9898
|
+
/* unused harmony exports getAppShortName, getAppDescription, getAppAccentHoverColor */
|
|
9853
9899
|
// Branding knobs sourced from NEXT_PUBLIC_* env vars so forks can rebrand
|
|
9854
9900
|
// the app without patching source. NEXT_PUBLIC_* is the right
|
|
9855
9901
|
// channel here because Next.js inlines these at build time, which lets
|
|
@@ -18,6 +18,8 @@ exports.modules = {
|
|
|
18
18
|
|
|
19
19
|
const CHARS_PER_TOKEN = 4;
|
|
20
20
|
const DEFAULT_WINDOW_DAYS = 30;
|
|
21
|
+
const METRICS_CACHE_MS = 5000;
|
|
22
|
+
let metricsCache = null;
|
|
21
23
|
function recalculateSnapshotCost(input, tables) {
|
|
22
24
|
const rates = (0,_pricing__WEBPACK_IMPORTED_MODULE_2__/* .modelRatesFor */ .En)(tables, input.provider, input.modelId);
|
|
23
25
|
if (rates.inputPer1M == null && rates.outputPer1M == null) return input.recordedCostUsd;
|
|
@@ -30,7 +32,17 @@ async function getDashboardMetrics(days = DEFAULT_WINDOW_DAYS) {
|
|
|
30
32
|
const now = new Date();
|
|
31
33
|
const boundedDays = Number.isFinite(days) ? Math.min(120, Math.max(7, Math.floor(days))) : DEFAULT_WINDOW_DAYS;
|
|
32
34
|
const since = new Date(now.getTime() - boundedDays * 24 * 60 * 60 * 1000).toISOString();
|
|
33
|
-
const
|
|
35
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_0__/* .getDb */ .Lf)();
|
|
36
|
+
const tables = (0,_pricing__WEBPACK_IMPORTED_MODULE_2__/* .getPricingTables */ .iH)();
|
|
37
|
+
// total_changes covers this connection; data_version covers other writers.
|
|
38
|
+
const { changes } = db.prepare("SELECT total_changes() AS changes").get();
|
|
39
|
+
const { data_version: dataVersion } = db.prepare("PRAGMA data_version").get();
|
|
40
|
+
if (metricsCache?.db === db && metricsCache.changes === changes && metricsCache.dataVersion === dataVersion && metricsCache.tables === tables && metricsCache.metrics.days === boundedDays && metricsCache.metrics.generated_at.slice(0, 10) === now.toISOString().slice(0, 10) && now.getTime() - metricsCache.createdAt >= 0 && now.getTime() - metricsCache.createdAt < METRICS_CACHE_MS) {
|
|
41
|
+
return metricsCache.metrics;
|
|
42
|
+
}
|
|
43
|
+
const usageRows = db.prepare(`SELECT m.created_at, m.role,
|
|
44
|
+
CASE WHEN mu.input_tokens IS NULL THEN m.content ELSE '' END AS content,
|
|
45
|
+
m.tool_events, m.thread_id, t.agent_id,
|
|
34
46
|
a.name AS agent_name, mc.provider AS provider,
|
|
35
47
|
mc.model_id AS model_id,
|
|
36
48
|
COALESCE(ta.model_config_name, a.model_config_name, dmc.name) AS model_config_name,
|
|
@@ -80,7 +92,6 @@ async function getDashboardMetrics(days = DEFAULT_WINDOW_DAYS) {
|
|
|
80
92
|
snapshotThreadIds.add(r.thread_id);
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
|
-
const tables = (0,_pricing__WEBPACK_IMPORTED_MODULE_2__/* .getPricingTables */ .iH)();
|
|
84
95
|
const { byProvider, generatedAt } = tables;
|
|
85
96
|
const dayMap = seedDayBuckets(now, boundedDays);
|
|
86
97
|
const agentMap = new Map();
|
|
@@ -396,7 +407,7 @@ async function getDashboardMetrics(days = DEFAULT_WINDOW_DAYS) {
|
|
|
396
407
|
by_model: dayModels
|
|
397
408
|
};
|
|
398
409
|
}
|
|
399
|
-
|
|
410
|
+
const metrics = {
|
|
400
411
|
generated_at: now.toISOString(),
|
|
401
412
|
days: boundedDays,
|
|
402
413
|
summary: {
|
|
@@ -452,6 +463,15 @@ async function getDashboardMetrics(days = DEFAULT_WINDOW_DAYS) {
|
|
|
452
463
|
notes: "Dashboard cost is recalculated from captured provider token usage and the latest matching rates. The original per-turn cost snapshots remain unchanged; legacy rows use content-length token estimates."
|
|
453
464
|
}
|
|
454
465
|
};
|
|
466
|
+
metricsCache = {
|
|
467
|
+
db,
|
|
468
|
+
changes,
|
|
469
|
+
dataVersion,
|
|
470
|
+
tables,
|
|
471
|
+
createdAt: now.getTime(),
|
|
472
|
+
metrics
|
|
473
|
+
};
|
|
474
|
+
return metrics;
|
|
455
475
|
}
|
|
456
476
|
function seedDayBuckets(now, days) {
|
|
457
477
|
const out = new Map();
|
|
@@ -882,6 +902,13 @@ function readSnapshotSync() {
|
|
|
882
902
|
try {
|
|
883
903
|
const p = snapshotPath();
|
|
884
904
|
const stat = (0,external_node_fs_.statSync)(p);
|
|
905
|
+
if (cached?.path === p && cached.mtimeMs === stat.mtimeMs) {
|
|
906
|
+
return {
|
|
907
|
+
path: p,
|
|
908
|
+
snapshot: null,
|
|
909
|
+
mtimeMs: stat.mtimeMs
|
|
910
|
+
};
|
|
911
|
+
}
|
|
885
912
|
const raw = (0,external_node_fs_.readFileSync)(p, "utf8");
|
|
886
913
|
return {
|
|
887
914
|
path: p,
|
|
@@ -335,12 +335,35 @@ function createRuntimeRequire(anchor) {
|
|
|
335
335
|
function managedPackagePath(packageName) {
|
|
336
336
|
return (0,node_path__WEBPACK_IMPORTED_MODULE_0__.join)((0,_langchain_packages__WEBPACK_IMPORTED_MODULE_1__/* .getPackagesDir */ .V_)(), "node_modules", packageName);
|
|
337
337
|
}
|
|
338
|
+
function resolveOptionalPackage(packageName) {
|
|
339
|
+
const managedReq = createRuntimeRequire((0,node_path__WEBPACK_IMPORTED_MODULE_0__.join)((0,_langchain_packages__WEBPACK_IMPORTED_MODULE_1__/* .getPackagesDir */ .V_)(), "_anchor"));
|
|
340
|
+
try {
|
|
341
|
+
return {
|
|
342
|
+
req: managedReq,
|
|
343
|
+
path: managedReq.resolve(managedPackagePath(packageName))
|
|
344
|
+
};
|
|
345
|
+
} catch {
|
|
346
|
+
// Workspace builds expose bundled @circuitwall packages from the app root.
|
|
347
|
+
}
|
|
348
|
+
if (process.env.JARELA_PACKAGES_DIR?.trim()) return null;
|
|
349
|
+
if (!packageName.startsWith("@circuitwall/")) return null;
|
|
350
|
+
const appReq = createRuntimeRequire((0,node_path__WEBPACK_IMPORTED_MODULE_0__.join)(process.cwd(), "package.json"));
|
|
351
|
+
try {
|
|
352
|
+
return {
|
|
353
|
+
req: appReq,
|
|
354
|
+
path: appReq.resolve(packageName)
|
|
355
|
+
};
|
|
356
|
+
} catch {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
338
360
|
function loadOptionalPackage(packageName) {
|
|
339
361
|
const override = testOverrides.get(packageName);
|
|
340
362
|
if (override) return override;
|
|
363
|
+
const resolved = resolveOptionalPackage(packageName);
|
|
364
|
+
if (!resolved) return null;
|
|
341
365
|
try {
|
|
342
|
-
|
|
343
|
-
return req(managedPackagePath(packageName));
|
|
366
|
+
return resolved.req(resolved.path);
|
|
344
367
|
} catch (err) {
|
|
345
368
|
// Keep the optional boundary non-fatal, but leave the actual load failure
|
|
346
369
|
// visible so missing peer dependencies are diagnosable from server logs.
|
|
@@ -372,9 +395,10 @@ function optionalFunction(packageName, exportName, fallback) {
|
|
|
372
395
|
};
|
|
373
396
|
}
|
|
374
397
|
function isOptionalPackageInstalled(packageName) {
|
|
398
|
+
const resolved = resolveOptionalPackage(packageName);
|
|
399
|
+
if (!resolved) return false;
|
|
375
400
|
try {
|
|
376
|
-
|
|
377
|
-
req(managedPackagePath(packageName));
|
|
401
|
+
resolved.req(resolved.path);
|
|
378
402
|
return true;
|
|
379
403
|
} catch (err) {
|
|
380
404
|
console.error(`[optional-package] failed to load ${packageName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -202,58 +202,79 @@ function containsText(source, needle, ignoreCase) {
|
|
|
202
202
|
if (!ignoreCase) return source.includes(needle);
|
|
203
203
|
return source.toLowerCase().includes(needle.toLowerCase());
|
|
204
204
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
...
|
|
205
|
+
const FENCE_RE = /^\s{0,3}(`{3,}|~{3,})/;
|
|
206
|
+
const HORIZONTAL_RULE_RE = /^\s{0,3}([-*_])(?:\s*\1){2,}\s*$/;
|
|
207
|
+
/**
|
|
208
|
+
* Drop duplicate segments from `parts`, which alternates content (even
|
|
209
|
+
* indexes) and the original separator that follows it (odd indexes).
|
|
210
|
+
* Separators are preserved verbatim, so only removed segments change the
|
|
211
|
+
* text. `keyOf` returns null for a segment that must always be kept.
|
|
212
|
+
*/ function dedupeSegments(parts, keyOf, keep) {
|
|
213
|
+
const contentIdx = parts.map((_, i)=>i).filter((i)=>i % 2 === 0);
|
|
214
|
+
const visit = keep === "first" ? contentIdx : [
|
|
215
|
+
...contentIdx
|
|
216
216
|
].reverse();
|
|
217
217
|
const seen = new Set();
|
|
218
|
+
const dropped = new Set();
|
|
218
219
|
for (const idx of visit){
|
|
219
|
-
const key =
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
220
|
+
const key = keyOf(idx);
|
|
221
|
+
if (key === null) continue;
|
|
222
|
+
if (seen.has(key)) dropped.add(idx);
|
|
223
|
+
else seen.add(key);
|
|
224
|
+
}
|
|
225
|
+
if (dropped.size === 0) return {
|
|
226
|
+
text: parts.join(""),
|
|
227
|
+
removed: 0
|
|
228
|
+
};
|
|
229
|
+
let text = "";
|
|
230
|
+
let emitted = false;
|
|
231
|
+
for (const idx of contentIdx){
|
|
232
|
+
if (dropped.has(idx)) continue;
|
|
233
|
+
if (emitted && idx > 0) text += parts[idx - 1];
|
|
234
|
+
text += parts[idx];
|
|
235
|
+
emitted = true;
|
|
227
236
|
}
|
|
228
|
-
const next = lines.filter((_, idx)=>keep.has(idx));
|
|
229
237
|
return {
|
|
230
|
-
text
|
|
231
|
-
removed:
|
|
238
|
+
text,
|
|
239
|
+
removed: dropped.size
|
|
232
240
|
};
|
|
233
241
|
}
|
|
242
|
+
function dedupeLines(source, opts) {
|
|
243
|
+
const parts = source.split(/(\r?\n)/);
|
|
244
|
+
// Fence markers, fenced code and horizontal rules repeat by design; a
|
|
245
|
+
// closing ``` is always a "duplicate" of the opening one.
|
|
246
|
+
const protectedIdx = new Set();
|
|
247
|
+
let fence = null;
|
|
248
|
+
for(let i = 0; i < parts.length; i += 2){
|
|
249
|
+
const marker = FENCE_RE.exec(parts[i])?.[1];
|
|
250
|
+
if (fence !== null) {
|
|
251
|
+
protectedIdx.add(i);
|
|
252
|
+
if (marker && marker[0] === fence[0] && marker.length >= fence.length && /^\s*[`~]+\s*$/.test(parts[i])) fence = null;
|
|
253
|
+
} else if (marker) {
|
|
254
|
+
protectedIdx.add(i);
|
|
255
|
+
fence = marker;
|
|
256
|
+
} else if (HORIZONTAL_RULE_RE.test(parts[i])) {
|
|
257
|
+
protectedIdx.add(i);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return dedupeSegments(parts, (i)=>{
|
|
261
|
+
if (protectedIdx.has(i)) return null;
|
|
262
|
+
const normalized = opts.trim ? parts[i].trim() : parts[i];
|
|
263
|
+
if (opts.skipBlank && normalized.length === 0) return null;
|
|
264
|
+
return opts.ignoreCase ? normalized.toLowerCase() : normalized;
|
|
265
|
+
}, opts.keep);
|
|
266
|
+
}
|
|
234
267
|
function dedupeParagraphs(source, opts) {
|
|
235
|
-
const
|
|
236
|
-
const
|
|
237
|
-
|
|
268
|
+
const tail = /\s*$/.exec(source)?.[0] ?? "";
|
|
269
|
+
const parts = source.slice(0, source.length - tail.length).split(/(\r?\n(?:[ \t]*\r?\n)+)/);
|
|
270
|
+
const out = dedupeSegments(parts, (i)=>{
|
|
271
|
+
if (parts[i].trim().length === 0) return null;
|
|
272
|
+
const base = opts.trim ? parts[i].trim() : parts[i];
|
|
238
273
|
return opts.ignoreCase ? base.toLowerCase() : base;
|
|
239
|
-
});
|
|
240
|
-
const keep = new Set();
|
|
241
|
-
const visit = opts.keep === "first" ? [
|
|
242
|
-
...keys.keys()
|
|
243
|
-
] : [
|
|
244
|
-
...keys.keys()
|
|
245
|
-
].reverse();
|
|
246
|
-
const seen = new Set();
|
|
247
|
-
for (const idx of visit){
|
|
248
|
-
const key = keys[idx];
|
|
249
|
-
if (seen.has(key)) continue;
|
|
250
|
-
seen.add(key);
|
|
251
|
-
keep.add(idx);
|
|
252
|
-
}
|
|
253
|
-
const next = paragraphs.filter((_, idx)=>keep.has(idx));
|
|
274
|
+
}, opts.keep);
|
|
254
275
|
return {
|
|
255
|
-
text:
|
|
256
|
-
removed:
|
|
276
|
+
text: out.text + tail,
|
|
277
|
+
removed: out.removed
|
|
257
278
|
};
|
|
258
279
|
}
|
|
259
280
|
|