clay-server 5.2.0-beta.1 → 5.2.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/lib/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +19 -16
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +1 -239
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +88 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +52 -0
- package/lib/clay-product-control.js +250 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +84 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +104 -0
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-vendor-usage.js +44 -0
- package/lib/clay-workspace-controls.js +84 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +78 -276
- package/lib/default-ai-runtime.js +4 -8
- package/lib/dm-digest-cursor.js +120 -0
- package/lib/email-mcp-server.js +1 -1
- package/lib/github-star-count.js +147 -0
- package/lib/issues-service.js +29 -15
- package/lib/kiro-defaults.js +1 -22
- package/lib/knowledge-db-import-validation.js +46 -0
- package/lib/knowledge-db-import.js +99 -0
- package/lib/knowledge-db-service.js +24 -33
- package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
- package/lib/knowledge-db-storage-nedb.js +66 -0
- package/lib/knowledge-db-storage.js +72 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-file-store.js +7 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-mate-bound.js +53 -0
- package/lib/mate-knowledge-mcp-server.js +55 -8
- package/lib/mate-knowledge-service.js +16 -34
- package/lib/mate-knowledge-text-tools.js +106 -0
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +18 -6
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +1 -0
- package/lib/mcp-source-context.js +1 -0
- package/lib/mcp-source-discovery.js +1 -0
- package/lib/mcp-source-plugins.js +1 -0
- package/lib/mcp-source-restrictions.js +1 -0
- package/lib/mcp-tool-policy.js +9 -0
- package/lib/notes-checklist.js +92 -0
- package/lib/notes.js +51 -4
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +24 -70
- package/lib/pane-pending-interactions.js +20 -0
- package/lib/pane-session-activation.js +114 -0
- package/lib/pane-session-transport.js +26 -0
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +8 -4
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-debate.js +1 -0
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +15 -85
- package/lib/project-full-access.js +23 -2
- package/lib/project-http.js +7 -4
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-mate-interaction.js +40 -62
- package/lib/project-mcp.js +54 -16
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +76 -17
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +4 -1
- package/lib/project-product-control.js +89 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +67 -68
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-document.js +27 -7
- package/lib/project-session-github.js +63 -19
- package/lib/project-session-history-actions.js +167 -0
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +40 -11
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +64 -0
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +55 -0
- package/lib/project-sessions.js +160 -290
- package/lib/project-shared-browser.js +78 -17
- package/lib/project-start-protocol.js +29 -0
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +67 -1
- package/lib/project-vendor-login.js +8 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +19 -2
- package/lib/project.js +181 -45
- package/lib/public/app.js +71 -17
- package/lib/public/appearance-bootstrap.js +16 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/command-palette.css +12 -33
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/filebrowser.css +1 -1
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/input.css +6 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/mate-loading-scene.css +21 -0
- package/lib/public/css/messages.css +6 -2
- package/lib/public/css/overlays.css +68 -258
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/project-mate-creation.css +5 -6
- package/lib/public/css/project-start.css +108 -0
- package/lib/public/css/projects-hub.css +53 -14
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/settings-shell.css +103 -0
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sidebar.css +7 -0
- package/lib/public/css/sticky-notes.css +87 -1
- package/lib/public/css/title-bar.css +79 -0
- package/lib/public/index.html +61 -68
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/admin-settings-invitations.js +2 -2
- package/lib/public/modules/admin-settings-projects.js +8 -4
- package/lib/public/modules/admin-settings-ui.js +20 -4
- package/lib/public/modules/admin-settings-users.js +4 -4
- package/lib/public/modules/app-connection.js +11 -1
- package/lib/public/modules/app-favicon.js +18 -9
- package/lib/public/modules/app-header.js +7 -4
- package/lib/public/modules/app-home-hub.js +2 -1
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +22 -1
- package/lib/public/modules/app-messages.js +125 -19
- package/lib/public/modules/app-misc.js +3 -1
- package/lib/public/modules/app-notifications.js +11 -5
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +14 -407
- package/lib/public/modules/app-rate-limit.js +19 -28
- package/lib/public/modules/app-rendering.js +4 -3
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +20 -0
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-log-links.js +23 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +33 -0
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +146 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +343 -0
- package/lib/public/modules/command-palette.js +162 -40
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +169 -0
- package/lib/public/modules/contextual-clay.js +252 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +117 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/elicitation-form.js +5 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/github-star.js +66 -0
- package/lib/public/modules/history-replay-batch.js +13 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +88 -10
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +6 -34
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mate-loading-scene.js +17 -0
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/message-delivery.js +20 -2
- package/lib/public/modules/model-picker.js +2 -0
- package/lib/public/modules/pane-activation.js +214 -0
- package/lib/public/modules/pane-binding.js +82 -0
- package/lib/public/modules/pane-bridge.js +7 -4
- package/lib/public/modules/pane-browser-bridge.js +22 -0
- package/lib/public/modules/pane-file-bridge.js +4 -0
- package/lib/public/modules/pane-issue-bridge.js +4 -1
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/profile.js +12 -241
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +3 -0
- package/lib/public/modules/project-mate-creation-workspace.js +13 -4
- package/lib/public/modules/project-mate-navigation.js +144 -22
- package/lib/public/modules/project-session-visibility-settings.js +19 -16
- package/lib/public/modules/project-settings.js +119 -129
- package/lib/public/modules/project-start-dialog.js +130 -0
- package/lib/public/modules/project-start-folder-state.js +78 -0
- package/lib/public/modules/project-start-folder-view.js +190 -0
- package/lib/public/modules/project-start-forms.js +66 -0
- package/lib/public/modules/project-start-path.js +60 -0
- package/lib/public/modules/project-start-state.js +54 -0
- package/lib/public/modules/project-start-submit.js +67 -0
- package/lib/public/modules/projects-hub-view.js +33 -14
- package/lib/public/modules/projects-hub.js +10 -6
- package/lib/public/modules/rewind.js +5 -0
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -440
- package/lib/public/modules/server-settings.js +36 -91
- package/lib/public/modules/session-actions.js +5 -2
- package/lib/public/modules/session-context-menu.js +5 -0
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +85 -14
- package/lib/public/modules/session-rich-drafts.js +21 -0
- package/lib/public/modules/session-switch-defer.js +67 -0
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/settings-project-target.js +56 -0
- package/lib/public/modules/settings-select.js +1 -1
- package/lib/public/modules/settings-shell-registry.js +88 -0
- package/lib/public/modules/settings-shell-view.js +104 -0
- package/lib/public/modules/settings-shell.js +342 -0
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +29 -6
- package/lib/public/modules/sidebar-mobile.js +12 -33
- package/lib/public/modules/sidebar-projects.js +3 -1
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-group-restore.js +68 -0
- package/lib/public/modules/split-pair-ui.js +1 -0
- package/lib/public/modules/split-pane-reconciler.js +15 -0
- package/lib/public/modules/split-pane-renderer.js +87 -6
- package/lib/public/modules/split-session-boundary.js +1 -1
- package/lib/public/modules/split-view.js +60 -68
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +116 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/stt-controller.js +4 -1
- package/lib/public/modules/stt-recording.js +1 -1
- package/lib/public/modules/stt.js +7 -2
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/theme.js +18 -3
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +60 -11
- package/lib/public/modules/tui-grab.js +1 -2
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +14 -30
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +13 -3
- package/lib/public/modules/user-settings.js +18 -84
- package/lib/public/modules/vendor-login-browser.js +5 -3
- package/lib/public/modules/vendor-login.js +2 -2
- package/lib/public/modules/vendor-priority.js +15 -1
- package/lib/public/modules/vendor-usage-format.js +93 -0
- package/lib/public/modules/vendor-usage-list.js +45 -0
- package/lib/public/modules/vendor-usage-model.js +215 -0
- package/lib/public/modules/vendor-usage-overview.js +312 -0
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +14 -6
- package/lib/public/sw.js +3 -1
- package/lib/public/welcome-art/conversation-desk.png +0 -0
- package/lib/public/welcome-art/mate-clay.png +0 -0
- package/lib/public/welcome-art/project-clay.png +0 -0
- package/lib/safe-bash-commands.js +3 -45
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +348 -402
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +61 -18
- package/lib/sdk-quota-snapshot.js +21 -3
- package/lib/sdk-response-recovery.js +1 -0
- package/lib/sdk-worker.js +2 -677
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-dm.js +2 -1
- package/lib/server-github-stars.js +39 -0
- package/lib/server-global-ws.js +26 -32
- package/lib/server-home-chat-events.js +18 -4
- package/lib/server-home-chat.js +22 -20
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +29 -9
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +25 -62
- package/lib/server-owner-ui.js +118 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server-settings.js +6 -1
- package/lib/server.js +167 -43
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-fork-history.js +21 -0
- package/lib/session-github.js +9 -2
- package/lib/session-hygiene.js +3 -35
- package/lib/session-notes-mcp-server.js +26 -4
- package/lib/session-notes-writes.js +88 -0
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +25 -10
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +66 -99
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/terminal-manager.js +65 -6
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +7 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/vendor-usage-acp-readers.js +97 -0
- package/lib/vendor-usage-capabilities.js +88 -0
- package/lib/vendor-usage-http-readers.js +214 -0
- package/lib/vendor-usage-metrics.js +47 -0
- package/lib/vendor-usage-native-readers.js +106 -0
- package/lib/vendor-usage-overview.js +406 -0
- package/lib/vendor-usage-service.js +281 -0
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/workspace-query-service.js +13 -2
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +22 -4
- package/lib/yoke/acp-agent-profiles.js +7 -5
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +66 -50
- package/lib/yoke/adapters/codex-query-contract.js +25 -0
- package/lib/yoke/adapters/codex.js +98 -123
- package/lib/yoke/adapters/kiro.js +3 -1
- package/lib/yoke/adapters/muse-query-contract.js +7 -0
- package/lib/yoke/adapters/muse.js +122 -0
- package/lib/yoke/auth-events.js +17 -0
- package/lib/yoke/claude-hook-installer.js +272 -0
- package/lib/yoke/claude-jsonl-watcher.js +204 -0
- package/lib/yoke/claude-maintenance.js +55 -0
- package/lib/yoke/claude-permission-patterns.js +53 -0
- package/lib/yoke/claude-response-recovery.js +155 -0
- package/lib/yoke/claude-transcript-hygiene.js +34 -0
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/clay-skill-install.js +33 -0
- package/lib/yoke/cli-sessions.js +300 -0
- package/lib/yoke/codex-app-server.js +7 -12
- package/lib/yoke/codex-dynamic-tool-names.js +80 -0
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-model-catalog.js +37 -3
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/configuration.js +13 -0
- package/lib/yoke/discovery.js +70 -0
- package/lib/yoke/errors.js +8 -0
- package/lib/yoke/host-environment.js +7 -0
- package/lib/yoke/index.js +9 -51
- package/lib/yoke/interface.js +116 -0
- package/lib/yoke/kiro-acp-server.js +5 -5
- package/lib/yoke/legacy-sessions.js +89 -0
- package/lib/yoke/login-protocol.js +25 -0
- package/lib/yoke/maintenance.js +12 -0
- package/lib/yoke/mcp-proxy.js +32 -0
- package/lib/yoke/mcp-source-adapters.js +91 -0
- package/lib/yoke/mcp-source-context.js +42 -0
- package/lib/yoke/mcp-source-discovery.js +169 -0
- package/lib/yoke/mcp-source-plugins.js +68 -0
- package/lib/yoke/mcp-source-restrictions.js +47 -0
- package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
- package/lib/yoke/model-preferences.js +6 -0
- package/lib/yoke/muse-artifacts.js +36 -0
- package/lib/yoke/muse-controls.js +50 -0
- package/lib/yoke/muse-input.js +64 -0
- package/lib/yoke/muse-items.js +157 -0
- package/lib/yoke/muse-policy.js +52 -0
- package/lib/yoke/muse-query.js +428 -0
- package/lib/yoke/muse-runtime.js +211 -0
- package/lib/yoke/muse-services.js +92 -0
- package/lib/yoke/muse-skills.js +79 -0
- package/lib/yoke/muse-turns.js +71 -0
- package/lib/yoke/options/acp.js +2 -0
- package/lib/yoke/options/antigravity.js +2 -0
- package/lib/yoke/options/claude.js +21 -0
- package/lib/yoke/options/codex-defaults.js +29 -0
- package/lib/yoke/options/codex-settings.js +21 -0
- package/lib/yoke/options/codex.js +6 -0
- package/lib/yoke/options/kiro-defaults.js +22 -0
- package/lib/yoke/options/kiro.js +5 -0
- package/lib/yoke/options/muse.js +5 -0
- package/lib/yoke/provider-contract.js +5 -0
- package/lib/yoke/providers/antigravity-executable.js +8 -0
- package/lib/yoke/providers/claude-executable.js +40 -0
- package/lib/yoke/providers/claude-model-descriptions.js +34 -0
- package/lib/yoke/providers/claude-process.js +97 -0
- package/lib/yoke/providers/claude-provision.js +75 -0
- package/lib/yoke/providers/codex-errors.js +8 -0
- package/lib/yoke/providers/muse-executable.js +17 -0
- package/lib/yoke/provisioning.js +6 -0
- package/lib/yoke/query-options.js +10 -0
- package/lib/yoke/response-recovery.js +41 -0
- package/lib/yoke/sdk-mcp-descriptors.js +37 -0
- package/lib/yoke/sdk-server-factory.js +7 -0
- package/lib/yoke/session-history.js +8 -0
- package/lib/yoke/session-tool-transport.js +34 -13
- package/lib/yoke/settings.js +23 -0
- package/lib/yoke/source-locations.js +4 -0
- package/lib/yoke/title-query.js +18 -7
- package/lib/yoke/tui-transcript-index.js +132 -0
- package/lib/yoke/usage.js +48 -0
- package/lib/yoke/user-input.js +13 -0
- package/lib/yoke/vendor-registry.js +87 -3
- package/package.json +11 -4
- package/lib/public/modules/server-settings-navigation.js +0 -39
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Kiro account usage through Kiro's own ACP server.
|
|
2
|
+
//
|
|
3
|
+
// Source (verified against the installed kiro-cli 2.32.0, not a web snippet):
|
|
4
|
+
// `kiro-cli acp` advertises `/usage` ("Show billing and usage information") in
|
|
5
|
+
// its available commands, and `_kiro.dev/commands/execute` with command "usage"
|
|
6
|
+
// answers with { success, message, data: { planName, billingCycleReset,
|
|
7
|
+
// overagesEnabled, usageBreakdowns: [{ resourceType, displayName, used, limit,
|
|
8
|
+
// percentage, hasLimit, currency, overageCharges, ... }] } }. The probe made no
|
|
9
|
+
// model turn. It does create an empty local Kiro session record (session/new is
|
|
10
|
+
// required before a command can run), under a neutral temp directory.
|
|
11
|
+
//
|
|
12
|
+
// A short-lived process is started per read, as the server user, with a hard
|
|
13
|
+
// timeout and kill; nothing is retained. Because the credential belongs to the
|
|
14
|
+
// server user, the capability table restricts it to single-user mode.
|
|
15
|
+
|
|
16
|
+
var m = require("./vendor-usage-metrics");
|
|
17
|
+
var failure = require("./vendor-usage-native-readers").failure;
|
|
18
|
+
|
|
19
|
+
function rpc(child, onFrame) {
|
|
20
|
+
var next = 0;
|
|
21
|
+
var pending = Object.create(null);
|
|
22
|
+
var buffer = "";
|
|
23
|
+
child.stdout.on("data", function (chunk) {
|
|
24
|
+
buffer += chunk;
|
|
25
|
+
if (buffer.length > 4 * 1024 * 1024) { buffer = ""; return; }
|
|
26
|
+
var lines = buffer.split("\n");
|
|
27
|
+
buffer = lines.pop();
|
|
28
|
+
lines.forEach(function (line) {
|
|
29
|
+
var frame;
|
|
30
|
+
try { frame = JSON.parse(line); } catch (e) { return; }
|
|
31
|
+
if (frame && frame.id !== undefined && pending[frame.id]) {
|
|
32
|
+
var entry = pending[frame.id];
|
|
33
|
+
delete pending[frame.id];
|
|
34
|
+
if (frame.error) entry.reject(failure("server", "Kiro rejected the usage request."));
|
|
35
|
+
else entry.resolve(frame.result);
|
|
36
|
+
} else if (onFrame) onFrame(frame);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
request: function (method, params) {
|
|
41
|
+
var id = ++next;
|
|
42
|
+
return new Promise(function (resolve, reject) {
|
|
43
|
+
pending[id] = { resolve: resolve, reject: reject };
|
|
44
|
+
child.stdin.write(JSON.stringify({ jsonrpc: "2.0", id: id, method: method, params: params }) + "\n");
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
failAll: function (error) { Object.keys(pending).forEach(function (id) { pending[id].reject(error); delete pending[id]; }); },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function mapUsage(data) {
|
|
52
|
+
var metrics = [];
|
|
53
|
+
var reset = typeof data.billingCycleReset === "string" ? Date.parse(data.billingCycleReset) : NaN;
|
|
54
|
+
var resetsAtMs = Number.isFinite(reset) ? reset : null;
|
|
55
|
+
(Array.isArray(data.usageBreakdowns) ? data.usageBreakdowns : []).forEach(function (item, index) {
|
|
56
|
+
if (!item || item.hasLimit !== true) return;
|
|
57
|
+
var used = m.num(item.used);
|
|
58
|
+
var limit = m.num(item.limit);
|
|
59
|
+
if (used === null || limit === null || limit <= 0) return;
|
|
60
|
+
var label = typeof item.displayName === "string" && item.displayName ? item.displayName : "Credits";
|
|
61
|
+
metrics.push(m.metric("credits", "kiro:" + (item.resourceType || index), label, { used: used, limit: limit, balance: null, unlimited: false, resetsAtMs: resetsAtMs }));
|
|
62
|
+
var charges = m.num(item.overageCharges);
|
|
63
|
+
if (data.overagesEnabled === true && charges !== null && typeof item.currency === "string" && item.currency) {
|
|
64
|
+
metrics.push(m.metric("currency", "kiro:overage:" + (item.resourceType || index), "Overage charges", { used: charges, limit: null, balance: null, currencyCode: item.currency, resetsAtMs: resetsAtMs }));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return { metrics: metrics, planType: typeof data.planName === "string" ? data.planName : null };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// deps: { binary(): path|null, spawn(command, args, options), tmpdir(), signal }
|
|
71
|
+
async function kiro(context, deps) {
|
|
72
|
+
var binary = deps.binary();
|
|
73
|
+
if (!binary) throw failure("unavailable", "The Kiro CLI was not found.");
|
|
74
|
+
var child = deps.spawn(binary, ["acp"], { stdio: ["pipe", "pipe", "ignore"], cwd: deps.tmpdir(), env: deps.env });
|
|
75
|
+
var link = rpc(child);
|
|
76
|
+
var died = new Promise(function (resolve, reject) {
|
|
77
|
+
child.on("error", function () { reject(failure("unavailable", "The Kiro CLI could not be started.")); });
|
|
78
|
+
child.on("exit", function () { reject(failure("unavailable", "The Kiro CLI exited before answering.")); });
|
|
79
|
+
});
|
|
80
|
+
died.catch(function () {});
|
|
81
|
+
var abort = context && context.signal;
|
|
82
|
+
var stop = function () { try { child.kill("SIGKILL"); } catch (e) {} link.failAll(failure("timeout", "The usage read was cancelled.")); };
|
|
83
|
+
if (abort) { if (abort.aborted) stop(); else abort.addEventListener("abort", stop, { once: true }); }
|
|
84
|
+
try {
|
|
85
|
+
await Promise.race([link.request("initialize", { protocolVersion: 1, clientCapabilities: {} }), died]);
|
|
86
|
+
var session = await Promise.race([link.request("session/new", { cwd: deps.tmpdir(), mcpServers: [] }), died]);
|
|
87
|
+
if (!session || typeof session.sessionId !== "string") throw failure("parse", "Kiro returned no session.");
|
|
88
|
+
var reply = await Promise.race([link.request("_kiro.dev/commands/execute", { sessionId: session.sessionId, command: { command: "usage", args: {} } }), died]);
|
|
89
|
+
if (!reply || reply.success !== true || !reply.data || typeof reply.data !== "object") throw failure("unavailable", "Kiro did not report usage for this account.");
|
|
90
|
+
return mapUsage(reply.data);
|
|
91
|
+
} finally {
|
|
92
|
+
if (abort) abort.removeEventListener("abort", stop);
|
|
93
|
+
try { child.kill("SIGKILL"); } catch (e) {}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = { kiro: kiro, mapUsage: mapUsage };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Per-vendor usage capability for all eleven Clay vendors.
|
|
2
|
+
//
|
|
3
|
+
// mode:
|
|
4
|
+
// query Clay asks the vendor's own native source for account figures
|
|
5
|
+
// (a reader exists in lib/vendor-usage-*-readers.js).
|
|
6
|
+
// event The vendor pushes quota into a session; only the latest
|
|
7
|
+
// observed snapshot of the owner's own sessions is shown.
|
|
8
|
+
// unintegrated A source may exist, but it is not verified safe or not
|
|
9
|
+
// reachable from Clay's integration, so Clay does not read it.
|
|
10
|
+
// This is "not integrated", never "the provider has none".
|
|
11
|
+
//
|
|
12
|
+
// `observed` is true when session-observed quota can also be displayed (the
|
|
13
|
+
// existing rate-limit snapshot path). `units` lists the metric kinds the reader
|
|
14
|
+
// returns; they are never converted to each other. `identity` states what a
|
|
15
|
+
// direct account read needs: "owner-os-user" (the runtime runs as the owner's
|
|
16
|
+
// mapped OS user), "owner-session" (answered by one of the owner's own live
|
|
17
|
+
// sessions), "single-user" (the credential is the server user's; refused in
|
|
18
|
+
// account mode because no owner can be proven), or null.
|
|
19
|
+
//
|
|
20
|
+
// Evidence kinds in `source`/`reason`: "installed" = observed on the installed
|
|
21
|
+
// CLI/SDK in this repository's environment; "primary doc" = the vendor's own
|
|
22
|
+
// documentation; "Orca" = Orca@17a2bced code only (not independently run here).
|
|
23
|
+
|
|
24
|
+
var CAPABILITIES = {
|
|
25
|
+
claude: {
|
|
26
|
+
mode: "query", observed: true, units: ["percent", "credits", "currency"], identity: "owner-session",
|
|
27
|
+
source: "Claude SDK account usage call on one of your live sessions (installed SDK 0.3.x; the SDK marks it experimental, so it is capability-guarded and shape-checked); session rate_limit_event otherwise",
|
|
28
|
+
},
|
|
29
|
+
codex: {
|
|
30
|
+
mode: "query", observed: true, units: ["percent", "credits"], identity: "owner-os-user",
|
|
31
|
+
source: "codex app-server account/rateLimits/read (installed protocol schema) and account/rateLimits/updated events",
|
|
32
|
+
},
|
|
33
|
+
muse: {
|
|
34
|
+
mode: "query", observed: true, units: ["percent"], identity: "single-user",
|
|
35
|
+
source: "Muse Code usage/read (installed adapter) and usage/changed events",
|
|
36
|
+
},
|
|
37
|
+
antigravity: {
|
|
38
|
+
mode: "unintegrated", observed: false, units: [], identity: null,
|
|
39
|
+
reason: "Not integrated: the only known read is print-mode `agy -p /usage` (Orca), which Orca documents as spending a model turn on versions that answer it as a prompt. Stays disabled until a non-billable path is proven.",
|
|
40
|
+
},
|
|
41
|
+
opencode: {
|
|
42
|
+
mode: "unintegrated", observed: false, units: [], identity: null,
|
|
43
|
+
reason: "Not integrated: OpenCode Go quota exists (Orca reads it with an OpenCode Go key) but OpenCode hosts many backends and Clay cannot tell which one a session uses; ACP exposes context tokens only.",
|
|
44
|
+
},
|
|
45
|
+
kimi: {
|
|
46
|
+
mode: "query", observed: false, units: ["count"], identity: "single-user",
|
|
47
|
+
source: "Kimi Code GET /usages with the CLI's saved token (Orca; Kimi CLI not installed here). Counts only: the response does not name a period or unit.",
|
|
48
|
+
},
|
|
49
|
+
grok: {
|
|
50
|
+
mode: "query", observed: false, units: ["percent", "amount"], identity: "single-user",
|
|
51
|
+
source: "Grok CLI chat proxy GET /billing with the CLI's saved token (Orca; Grok CLI not installed here). Money fields carry no currency, so they stay unit-less amounts.",
|
|
52
|
+
},
|
|
53
|
+
copilot: {
|
|
54
|
+
mode: "unintegrated", observed: false, units: [], identity: null,
|
|
55
|
+
reason: "Not integrated: GitHub's Copilot SDK documents account.getQuota (entitlement, used requests, remaining %, reset date), but Clay talks to the Copilot CLI over ACP and ships no SDK client; ACP exposure of it is unverified.",
|
|
56
|
+
},
|
|
57
|
+
qwen: {
|
|
58
|
+
mode: "unintegrated", observed: false, units: [], identity: null,
|
|
59
|
+
reason: "Not integrated: Qwen Code's documented /stats and /context report session token and call metrics; no account quota read is documented (primary doc, checked this task).",
|
|
60
|
+
},
|
|
61
|
+
junie: {
|
|
62
|
+
mode: "unintegrated", observed: false, units: [], identity: null,
|
|
63
|
+
reason: "Not integrated: Junie CLI documents a /usage slash command (session cost and remaining balance), but running it through ACP could be treated as a prompt; side effects are unverified.",
|
|
64
|
+
},
|
|
65
|
+
kiro: {
|
|
66
|
+
mode: "query", observed: false, units: ["credits", "currency"], identity: "single-user",
|
|
67
|
+
source: "Kiro ACP `_kiro.dev/commands/execute` command usage (installed kiro-cli 2.32.0: structured credits used/limit and billing-cycle reset; no model turn observed). Creates an empty local session record.",
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
var VENDORS = Object.keys(CAPABILITIES);
|
|
72
|
+
|
|
73
|
+
function capabilityFor(vendor) {
|
|
74
|
+
var entry = CAPABILITIES[vendor];
|
|
75
|
+
if (!entry) return { mode: "unintegrated", observed: false, units: [], identity: null, reason: "Not integrated: no usage source has been reviewed for this vendor." };
|
|
76
|
+
return entry;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Serializable form for the client; never includes functions.
|
|
80
|
+
function publicCapability(vendor) {
|
|
81
|
+
var entry = capabilityFor(vendor);
|
|
82
|
+
var result = { mode: entry.mode, observed: entry.observed === true, units: entry.units.slice() };
|
|
83
|
+
if (entry.source) result.source = entry.source;
|
|
84
|
+
if (entry.reason) result.reason = entry.reason;
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { VENDORS: VENDORS, capabilityFor: capabilityFor, publicCapability: publicCapability };
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Readers for vendors whose only native usage source is an authenticated HTTP
|
|
2
|
+
// endpoint using the vendor CLI's own stored token.
|
|
3
|
+
//
|
|
4
|
+
// These read exactly one documented credential file and send the token only to
|
|
5
|
+
// the vendor's own HTTPS host: an endpoint override is accepted only when it is
|
|
6
|
+
// https on that exact host (no credentials, no port); anything else is refused
|
|
7
|
+
// BEFORE the credential file is read, so a token is never sent to an unverified
|
|
8
|
+
// origin. Redirects are refused. They never refresh or rewrite the file (the CLI
|
|
9
|
+
// owns the token lifecycle), never log or return the token, and are used only
|
|
10
|
+
// where the credential provably belongs to the requester (see
|
|
11
|
+
// vendor-usage-service.js identity rules). `identity` is a short one-way
|
|
12
|
+
// fingerprint of the credential used, so the service can notice a sign-in
|
|
13
|
+
// change; it cannot be reversed to the token.
|
|
14
|
+
// Request shapes follow Orca@17a2bced src/main/rate-limits/{kimi,grok}-fetcher.ts.
|
|
15
|
+
|
|
16
|
+
var path = require("path");
|
|
17
|
+
var crypto = require("crypto");
|
|
18
|
+
var m = require("./vendor-usage-metrics");
|
|
19
|
+
var failure = require("./vendor-usage-native-readers").failure;
|
|
20
|
+
|
|
21
|
+
var TOKEN_SKEW_SECONDS = 5;
|
|
22
|
+
var TOKEN_SKEW_MS = 5 * 60 * 1000;
|
|
23
|
+
|
|
24
|
+
function parseJson(text, what) {
|
|
25
|
+
try { return JSON.parse(text); } catch (e) { throw failure("parse", what + " could not be read."); }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function fingerprint(parts) {
|
|
29
|
+
return crypto.createHash("sha256").update(parts.join("\u0000")).digest("hex").slice(0, 16);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Returns the base URL to use, or throws before any credential is read.
|
|
33
|
+
function trustedBase(override, fallback, host, what) {
|
|
34
|
+
var value = typeof override === "string" ? override.trim() : "";
|
|
35
|
+
if (!value) return fallback;
|
|
36
|
+
var url;
|
|
37
|
+
try { url = new URL(value); } catch (e) { url = null; }
|
|
38
|
+
if (!url || url.protocol !== "https:" || url.hostname !== host || url.username || url.password || url.port) {
|
|
39
|
+
throw failure("untrusted_origin", "The " + what + " endpoint override is not the vendor's own HTTPS host, so the saved sign-in was not used or sent.");
|
|
40
|
+
}
|
|
41
|
+
return (url.origin + url.pathname).replace(/\/$/, "");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// A missing file means "not signed in", any other failure is a read error.
|
|
45
|
+
async function readCredentialFile(deps, file, what) {
|
|
46
|
+
var text;
|
|
47
|
+
try { text = await deps.readText(file); } catch (error) {
|
|
48
|
+
if (error && error.code === "ENOENT") throw failure("no_auth", "Not signed in to " + what + ".");
|
|
49
|
+
throw failure("unavailable", "The " + what + " sign-in file could not be read.");
|
|
50
|
+
}
|
|
51
|
+
return parseJson(text, "The " + what + " sign-in file");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function getJson(deps, url, headers, what) {
|
|
55
|
+
var response;
|
|
56
|
+
try { response = await deps.fetchJson(url, headers); } catch (error) {
|
|
57
|
+
throw failure(error && error.name === "TimeoutError" ? "timeout" : "network", what + " usage could not be reached.");
|
|
58
|
+
}
|
|
59
|
+
if (response.status === 401 || response.status === 403) throw failure("unauthorized", what + " rejected the saved sign-in (HTTP " + response.status + ").");
|
|
60
|
+
if (response.status === 429) throw failure("rate_limited", what + " is rate-limiting usage reads.");
|
|
61
|
+
if (response.status < 200 || response.status >= 300) throw failure("server", what + " usage request failed (HTTP " + response.status + ").");
|
|
62
|
+
return response.body && typeof response.body === "object" ? response.body : {};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---- Kimi Code ------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
function kimiHome(deps) {
|
|
68
|
+
var override = deps.env.KIMI_CODE_HOME && deps.env.KIMI_CODE_HOME.trim();
|
|
69
|
+
return override || path.join(deps.homedir(), ".kimi-code");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function windowMins(window) {
|
|
73
|
+
var duration = m.num(window && window.duration);
|
|
74
|
+
if (duration === null) return null;
|
|
75
|
+
var unit = String((window && window.timeUnit) || "").toUpperCase();
|
|
76
|
+
if (unit.indexOf("MINUTE") !== -1) return duration;
|
|
77
|
+
if (unit.indexOf("HOUR") !== -1) return duration * 60;
|
|
78
|
+
if (unit.indexOf("DAY") !== -1) return duration * 1440;
|
|
79
|
+
if (unit.indexOf("SECOND") !== -1) return Math.round(duration / 60);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Counts stay counts: used/limit/remaining are the vendor's own figures.
|
|
84
|
+
function kimiCount(id, label, detail, mins) {
|
|
85
|
+
if (!detail) return null;
|
|
86
|
+
var limit = m.num(detail.limit);
|
|
87
|
+
var used = m.num(detail.used);
|
|
88
|
+
var remaining = m.num(detail.remaining);
|
|
89
|
+
if (limit === null || limit <= 0) return null;
|
|
90
|
+
if (used === null && remaining !== null) used = limit - remaining;
|
|
91
|
+
if (remaining === null && used !== null) remaining = limit - used;
|
|
92
|
+
if (used === null) return null;
|
|
93
|
+
return m.metric("count", id, label, { used: used, limit: limit, remaining: remaining, windowMins: mins, resetsAtMs: m.isoMs(detail.resetTime || detail.resetAt) });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function kimiToken(creds) {
|
|
97
|
+
return creds && typeof creds.access_token === "string" ? creds.access_token : "";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function kimi(deps) {
|
|
101
|
+
var base = trustedBase(deps.env.KIMI_CODE_BASE_URL, "https://api.kimi.com/coding/v1", "api.kimi.com", "Kimi Code");
|
|
102
|
+
var creds = await readCredentialFile(deps, path.join(kimiHome(deps), "credentials", "kimi-code.json"), "Kimi Code");
|
|
103
|
+
var token = kimiToken(creds);
|
|
104
|
+
if (!token) throw failure("no_auth", "Not signed in to Kimi Code.");
|
|
105
|
+
var expiresAt = m.num(creds.expires_at);
|
|
106
|
+
if (expiresAt === null || expiresAt - Math.floor(deps.now() / 1000) <= TOKEN_SKEW_SECONDS) {
|
|
107
|
+
throw failure("expired_auth", "The Kimi Code sign-in has expired; run kimi once to refresh it.");
|
|
108
|
+
}
|
|
109
|
+
var body = await getJson(deps, base + "/usages", { Authorization: "Bearer " + token, Accept: "application/json" }, "Kimi Code");
|
|
110
|
+
var metrics = [];
|
|
111
|
+
// The response does not name the period or unit of the top-level block.
|
|
112
|
+
var weekly = kimiCount("kimi:usage", "Usage", body.usage, null);
|
|
113
|
+
if (weekly) metrics.push(weekly);
|
|
114
|
+
(Array.isArray(body.limits) ? body.limits : []).forEach(function (limit, index) {
|
|
115
|
+
var mins = windowMins(limit && limit.window);
|
|
116
|
+
var item = kimiCount("kimi:limit:" + index, mins ? "Rolling window" : "Limit", limit && limit.detail, mins);
|
|
117
|
+
if (item) metrics.push(item);
|
|
118
|
+
});
|
|
119
|
+
return { metrics: metrics, identity: fingerprint(["kimi", token]) };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Fingerprint of the saved sign-in, read synchronously; null when absent,
|
|
123
|
+
// unreadable, or when the endpoint override is untrusted (the credential is not
|
|
124
|
+
// read at all in that case, same as the reader).
|
|
125
|
+
function kimiIdentity(deps) {
|
|
126
|
+
try {
|
|
127
|
+
trustedBase(deps.env.KIMI_CODE_BASE_URL, "https://api.kimi.com/coding/v1", "api.kimi.com", "Kimi Code");
|
|
128
|
+
var token = kimiToken(JSON.parse(deps.readTextSync(path.join(kimiHome(deps), "credentials", "kimi-code.json"))));
|
|
129
|
+
return token ? fingerprint(["kimi", token]) : null;
|
|
130
|
+
} catch (e) { return null; }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ---- Grok Build -----------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
var GROK_ISSUER = "https://auth.x.ai";
|
|
136
|
+
|
|
137
|
+
function grokHome(deps) {
|
|
138
|
+
var override = deps.env.GROK_HOME && deps.env.GROK_HOME.trim();
|
|
139
|
+
return override && path.isAbsolute(override) ? override : path.join(deps.homedir(), ".grok");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Only the default xAI issuer's session is used: a credential from any other
|
|
143
|
+
// issuer is not bound to the billing host, so it is never sent there.
|
|
144
|
+
function pickGrokSession(parsed, now) {
|
|
145
|
+
var expired = null;
|
|
146
|
+
var keys = Object.keys(parsed || {});
|
|
147
|
+
for (var i = 0; i < keys.length; i++) {
|
|
148
|
+
var entry = parsed[keys[i]];
|
|
149
|
+
var preferred = keys[i] === GROK_ISSUER || keys[i].indexOf(GROK_ISSUER + "::") === 0;
|
|
150
|
+
if (!preferred || !entry || typeof entry.key !== "string" || !entry.key) continue;
|
|
151
|
+
var expiresMs = m.isoMs(entry.expires_at);
|
|
152
|
+
var fresh = expiresMs === null || expiresMs - now > TOKEN_SKEW_MS;
|
|
153
|
+
var session = { token: entry.key, userId: typeof entry.user_id === "string" ? entry.user_id : null, fresh: fresh };
|
|
154
|
+
if (fresh) return session;
|
|
155
|
+
expired = expired || session;
|
|
156
|
+
}
|
|
157
|
+
return expired;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function grokMoney(value) {
|
|
161
|
+
return m.num(value && value.val);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function grokMetrics(config) {
|
|
165
|
+
var out = [];
|
|
166
|
+
var end = m.isoMs(config.currentPeriod && config.currentPeriod.end || config.billingPeriodEnd);
|
|
167
|
+
var start = m.isoMs(config.currentPeriod && config.currentPeriod.start || config.billingPeriodStart);
|
|
168
|
+
// The period length comes from the response's own start and end, never assumed.
|
|
169
|
+
var mins = start !== null && end !== null && end > start ? Math.round((end - start) / 60000) : null;
|
|
170
|
+
// Only a reported percent is shown: an absent field is unknown, not 0%.
|
|
171
|
+
if (m.num(config.creditUsagePercent) !== null) {
|
|
172
|
+
out.push(m.metric("percent", "grok:credits", "Credits", { usedPercent: Math.min(100, Math.max(0, config.creditUsagePercent)), windowMins: mins, resetsAtMs: end }));
|
|
173
|
+
}
|
|
174
|
+
var limit = grokMoney(config.monthlyLimit);
|
|
175
|
+
var used = grokMoney(config.used);
|
|
176
|
+
// The response does not name a currency, so these stay unitless amounts.
|
|
177
|
+
if (limit !== null && limit > 0 && used !== null) {
|
|
178
|
+
out.push(m.metric("amount", "grok:budget", "Included budget", { used: used, limit: limit, windowMins: mins, resetsAtMs: end }));
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function grokBase(deps) {
|
|
184
|
+
return trustedBase(deps.env.GROK_CLI_CHAT_PROXY_BASE_URL, "https://cli-chat-proxy.grok.com/v1", "cli-chat-proxy.grok.com", "Grok");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function grok(deps) {
|
|
188
|
+
var base = grokBase(deps);
|
|
189
|
+
var parsed = await readCredentialFile(deps, path.join(grokHome(deps), "auth.json"), "Grok");
|
|
190
|
+
var session = pickGrokSession(parsed, deps.now());
|
|
191
|
+
if (!session) throw failure("no_auth", "Not signed in to Grok.");
|
|
192
|
+
if (!session.fresh) throw failure("expired_auth", "The Grok sign-in has expired; run grok once to refresh it.");
|
|
193
|
+
var headers = { Authorization: "Bearer " + session.token, "X-XAI-Token-Auth": "xai-grok-cli", Accept: "application/json" };
|
|
194
|
+
if (session.userId) headers["x-userid"] = session.userId;
|
|
195
|
+
var body = await getJson(deps, base + "/billing?format=credits", headers, "Grok");
|
|
196
|
+
var config = body.config || body;
|
|
197
|
+
var metrics = grokMetrics(config);
|
|
198
|
+
if (metrics.length === 0) {
|
|
199
|
+
// The default view can carry a monthly budget the credits view omits.
|
|
200
|
+
var other = await getJson(deps, base + "/billing", headers, "Grok");
|
|
201
|
+
metrics = grokMetrics(other.config || other);
|
|
202
|
+
}
|
|
203
|
+
return { metrics: metrics, planType: typeof config.subscriptionTier === "string" ? config.subscriptionTier : null, identity: fingerprint(["grok", session.token, session.userId || ""]) };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function grokIdentity(deps) {
|
|
207
|
+
try {
|
|
208
|
+
grokBase(deps);
|
|
209
|
+
var session = pickGrokSession(JSON.parse(deps.readTextSync(path.join(grokHome(deps), "auth.json"))), deps.now());
|
|
210
|
+
return session ? fingerprint(["grok", session.token, session.userId || ""]) : null;
|
|
211
|
+
} catch (e) { return null; }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = { kimi: kimi, grok: grok, identities: { kimi: kimiIdentity, grok: grokIdentity } };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Provider-neutral usage metric shapes. A metric keeps the unit its vendor
|
|
2
|
+
// reported; nothing is converted to a percentage here or anywhere downstream.
|
|
3
|
+
//
|
|
4
|
+
// percent { usedPercent } native percent used
|
|
5
|
+
// count { used, limit, remaining } requests/messages/tokens
|
|
6
|
+
// credits { balance, used, limit, unlimited } unitless credits (balance and/or used of limit)
|
|
7
|
+
// currency { used, limit, balance, currencyCode } money in a named currency
|
|
8
|
+
// amount { used, limit } numbers whose unit the vendor did not name
|
|
9
|
+
//
|
|
10
|
+
// Every metric may carry windowMins and resetsAtMs (milliseconds). A field the
|
|
11
|
+
// vendor did not report is null, never 0.
|
|
12
|
+
|
|
13
|
+
var UNITS = ["percent", "count", "credits", "currency", "amount"];
|
|
14
|
+
|
|
15
|
+
function num(value) {
|
|
16
|
+
if (typeof value === "string" && value.trim() !== "") value = Number(value);
|
|
17
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function resetMs(value) {
|
|
21
|
+
var n = num(value);
|
|
22
|
+
return n !== null && n > 0 ? n : null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isoMs(value) {
|
|
26
|
+
if (typeof value !== "string" || !value) return null;
|
|
27
|
+
var ms = Date.parse(value);
|
|
28
|
+
return Number.isFinite(ms) ? ms : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function metric(unit, id, label, fields) {
|
|
32
|
+
var m = { unit: unit, id: String(id), label: String(label), windowMins: null, resetsAtMs: null };
|
|
33
|
+
Object.keys(fields || {}).forEach(function (key) { m[key] = fields[key]; });
|
|
34
|
+
return m;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Validates a metric from any reader before it can reach a client.
|
|
38
|
+
function valid(m) {
|
|
39
|
+
if (!m || UNITS.indexOf(m.unit) === -1 || typeof m.id !== "string") return false;
|
|
40
|
+
if (m.unit === "percent") return num(m.usedPercent) !== null && m.usedPercent >= 0;
|
|
41
|
+
if (m.unit === "count" || m.unit === "amount") return num(m.used) !== null || num(m.remaining) !== null;
|
|
42
|
+
if (m.unit === "credits") return m.unlimited === true || num(m.balance) !== null || num(m.used) !== null;
|
|
43
|
+
if (m.unit === "currency") return typeof m.currencyCode === "string" && m.currencyCode !== "" && (num(m.used) !== null || num(m.balance) !== null);
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = { UNITS: UNITS, num: num, resetMs: resetMs, isoMs: isoMs, metric: metric, valid: valid };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Readers that ask a vendor runtime Clay already manages (no credential reads).
|
|
2
|
+
// Each takes a request context { adapter, linuxUser } and returns
|
|
3
|
+
// { metrics: [...], accountId?, planType?, observedAtMs? }
|
|
4
|
+
// or throws an Error carrying `failureKind`.
|
|
5
|
+
|
|
6
|
+
var m = require("./vendor-usage-metrics");
|
|
7
|
+
|
|
8
|
+
function failure(kind, message) {
|
|
9
|
+
var error = new Error(message);
|
|
10
|
+
error.failureKind = kind;
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function codexSnapshotMetrics(limitId, snapshot) {
|
|
15
|
+
var out = [];
|
|
16
|
+
var prefix = limitId || "codex";
|
|
17
|
+
var named = snapshot.limitName && limitId && limitId !== "codex" ? String(snapshot.limitName) : "";
|
|
18
|
+
[["primary", "Primary"], ["secondary", "Secondary"]].forEach(function (pair) {
|
|
19
|
+
var window = snapshot[pair[0]];
|
|
20
|
+
if (!window || window.windowDurationMins === 0) return;
|
|
21
|
+
var used = m.num(window.usedPercent);
|
|
22
|
+
if (used === null || used < 0) return;
|
|
23
|
+
out.push(m.metric("percent", prefix + ":" + pair[0], named || pair[1], {
|
|
24
|
+
usedPercent: used,
|
|
25
|
+
windowMins: m.num(window.windowDurationMins) > 0 ? window.windowDurationMins : null,
|
|
26
|
+
resetsAtMs: m.resetMs(window.resetsAt) !== null ? window.resetsAt * 1000 : null,
|
|
27
|
+
}));
|
|
28
|
+
});
|
|
29
|
+
var credits = snapshot.credits;
|
|
30
|
+
if (credits && (credits.unlimited === true || (credits.hasCredits === true && m.num(credits.balance) !== null))) {
|
|
31
|
+
out.push(m.metric("credits", prefix + ":credits", "Credits", { balance: credits.unlimited === true ? null : m.num(credits.balance), unlimited: credits.unlimited === true }));
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Source: codex app-server `account/rateLimits/read` (GetAccountRateLimitsResponse).
|
|
37
|
+
function codex(context) {
|
|
38
|
+
var adapter = context.adapter;
|
|
39
|
+
if (!adapter || typeof adapter.readAccountRateLimits !== "function") return Promise.reject(failure("unavailable", "The Codex runtime cannot report account usage."));
|
|
40
|
+
return adapter.readAccountRateLimits({ linuxUser: context.linuxUser || undefined }).then(function (reply) {
|
|
41
|
+
if (!reply || typeof reply !== "object") throw failure("parse", "Codex returned no usage.");
|
|
42
|
+
var metrics = [];
|
|
43
|
+
var byId = reply.rateLimitsByLimitId && typeof reply.rateLimitsByLimitId === "object" ? reply.rateLimitsByLimitId : null;
|
|
44
|
+
if (byId) Object.keys(byId).forEach(function (id) { if (byId[id]) metrics = metrics.concat(codexSnapshotMetrics(id, byId[id])); });
|
|
45
|
+
else if (reply.rateLimits) metrics = codexSnapshotMetrics(reply.rateLimits.limitId || "codex", reply.rateLimits);
|
|
46
|
+
var plan = reply.rateLimits && typeof reply.rateLimits.planType === "string" ? reply.rateLimits.planType : null;
|
|
47
|
+
return { metrics: metrics, accountId: typeof reply.accountId === "string" ? reply.accountId : null, planType: plan };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Source: Muse Code `usage/read`; windows carry native used percent and reset ms.
|
|
52
|
+
function muse(context) {
|
|
53
|
+
var adapter = context.adapter;
|
|
54
|
+
if (!adapter || typeof adapter.readUsage !== "function") return Promise.reject(failure("unavailable", "The Muse runtime cannot report usage."));
|
|
55
|
+
return adapter.readUsage({ signal: context.signal }).then(function (usage) {
|
|
56
|
+
if (!usage) throw failure("unavailable", "Muse reported no usage.");
|
|
57
|
+
var metrics = [];
|
|
58
|
+
[["window", "Window"], ["weekly", "Weekly"]].forEach(function (pair) {
|
|
59
|
+
var value = usage[pair[0]];
|
|
60
|
+
if (!value || m.num(value.usedPercent) === null || value.usedPercent < 0) return;
|
|
61
|
+
metrics.push(m.metric("percent", "muse:" + pair[0], pair[1], {
|
|
62
|
+
usedPercent: value.usedPercent,
|
|
63
|
+
windowMins: pair[0] === "weekly" ? 10080 : (m.num(value.windowDurationMins) > 0 ? value.windowDurationMins : null),
|
|
64
|
+
resetsAtMs: m.resetMs(value.resetsAtMs),
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
return { metrics: metrics, observedAtMs: m.num(usage.observedAtMs) };
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var CLAUDE_WINDOWS = [["five_hour", "5-hour", 300], ["seven_day", "7-day", 10080], ["seven_day_opus", "7-day Opus", 10080], ["seven_day_sonnet", "7-day Sonnet", 10080], ["seven_day_oauth_apps", "7-day OAuth apps", 10080]];
|
|
72
|
+
|
|
73
|
+
// Source: the Claude SDK's account usage call (marked experimental by the SDK),
|
|
74
|
+
// answered by one of the requester's own live sessions, so the account is the
|
|
75
|
+
// one that session authenticates as. Every field is shape-checked; a changed or
|
|
76
|
+
// missing response is "unavailable", never a guess.
|
|
77
|
+
function claude(context) {
|
|
78
|
+
var session = context.session;
|
|
79
|
+
var query = session && session.queryInstance;
|
|
80
|
+
if (!query || typeof query.getAccountUsage !== "function") return Promise.reject(failure("unavailable", "Account usage needs one of your live Claude sessions."));
|
|
81
|
+
return Promise.resolve(query.getAccountUsage({ skipBehaviors: true })).then(function (reply) {
|
|
82
|
+
if (!reply || typeof reply !== "object") throw failure("unavailable", "This Claude runtime cannot report account usage.");
|
|
83
|
+
if (reply.rate_limits_available === false || !reply.rate_limits) throw failure("unavailable", "Plan limits do not apply to this Claude account (for example an API key or a third-party provider).");
|
|
84
|
+
var limits = reply.rate_limits;
|
|
85
|
+
var metrics = [];
|
|
86
|
+
CLAUDE_WINDOWS.forEach(function (spec) {
|
|
87
|
+
var w = limits[spec[0]];
|
|
88
|
+
if (!w || m.num(w.utilization) === null || w.utilization < 0) return;
|
|
89
|
+
metrics.push(m.metric("percent", "claude:" + spec[0], spec[1], { usedPercent: w.utilization, windowMins: spec[2], resetsAtMs: m.isoMs(w.resets_at) }));
|
|
90
|
+
});
|
|
91
|
+
(Array.isArray(limits.model_scoped) ? limits.model_scoped : []).forEach(function (w, index) {
|
|
92
|
+
if (!w || m.num(w.utilization) === null || w.utilization < 0) return;
|
|
93
|
+
metrics.push(m.metric("percent", "claude:model:" + index, typeof w.display_name === "string" && w.display_name ? w.display_name : "Model", { usedPercent: w.utilization, resetsAtMs: m.isoMs(w.resets_at) }));
|
|
94
|
+
});
|
|
95
|
+
var extra = limits.extra_usage;
|
|
96
|
+
if (extra && extra.is_enabled === true && m.num(extra.used_credits) !== null) {
|
|
97
|
+
var shared = { used: extra.used_credits, limit: m.num(extra.monthly_limit), balance: null };
|
|
98
|
+
metrics.push(typeof extra.currency === "string" && extra.currency
|
|
99
|
+
? m.metric("currency", "claude:extra", "Extra usage", Object.assign({ currencyCode: extra.currency }, shared))
|
|
100
|
+
: m.metric("credits", "claude:extra", "Extra usage", Object.assign({ unlimited: false }, shared)));
|
|
101
|
+
}
|
|
102
|
+
return { metrics: metrics, planType: typeof reply.subscription_type === "string" ? reply.subscription_type : null, sourceSessionId: session.localId };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { codex: codex, muse: muse, claude: claude, failure: failure };
|