@kortix/sdk 0.9.98
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 +313 -0
- package/dist/files/client.d.ts +96 -0
- package/dist/files/client.d.ts.map +1 -0
- package/dist/files/client.js +346 -0
- package/dist/files/client.js.map +1 -0
- package/dist/files/types.d.ts +82 -0
- package/dist/files/types.d.ts.map +1 -0
- package/dist/files/types.js +6 -0
- package/dist/files/types.js.map +1 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/kortix.d.ts +897 -0
- package/dist/kortix.d.ts.map +1 -0
- package/dist/kortix.js +772 -0
- package/dist/kortix.js.map +1 -0
- package/dist/opencode/client.d.ts +89 -0
- package/dist/opencode/client.d.ts.map +1 -0
- package/dist/opencode/client.js +191 -0
- package/dist/opencode/client.js.map +1 -0
- package/dist/opencode/env.d.ts +13 -0
- package/dist/opencode/env.d.ts.map +1 -0
- package/dist/opencode/env.js +63 -0
- package/dist/opencode/env.js.map +1 -0
- package/dist/opencode/kortix-master.d.ts +487 -0
- package/dist/opencode/kortix-master.d.ts.map +1 -0
- package/dist/opencode/kortix-master.js +313 -0
- package/dist/opencode/kortix-master.js.map +1 -0
- package/dist/opencode/triggers.d.ts +6 -0
- package/dist/opencode/triggers.d.ts.map +1 -0
- package/dist/opencode/triggers.js +34 -0
- package/dist/opencode/triggers.js.map +1 -0
- package/dist/platform/api/errors.d.ts +106 -0
- package/dist/platform/api/errors.d.ts.map +1 -0
- package/dist/platform/api/errors.js +137 -0
- package/dist/platform/api/errors.js.map +1 -0
- package/dist/platform/api-client.d.ts +35 -0
- package/dist/platform/api-client.d.ts.map +1 -0
- package/dist/platform/api-client.js +279 -0
- package/dist/platform/api-client.js.map +1 -0
- package/dist/platform/auth-core.d.ts +60 -0
- package/dist/platform/auth-core.d.ts.map +1 -0
- package/dist/platform/auth-core.js +104 -0
- package/dist/platform/auth-core.js.map +1 -0
- package/dist/platform/auth.d.ts +88 -0
- package/dist/platform/auth.d.ts.map +1 -0
- package/dist/platform/auth.js +161 -0
- package/dist/platform/auth.js.map +1 -0
- package/dist/platform/config-node.d.ts +33 -0
- package/dist/platform/config-node.d.ts.map +1 -0
- package/dist/platform/config-node.js +63 -0
- package/dist/platform/config-node.js.map +1 -0
- package/dist/platform/config.d.ts +77 -0
- package/dist/platform/config.d.ts.map +1 -0
- package/dist/platform/config.js +62 -0
- package/dist/platform/config.js.map +1 -0
- package/dist/platform/feature-flags.d.ts +25 -0
- package/dist/platform/feature-flags.d.ts.map +1 -0
- package/dist/platform/feature-flags.js +114 -0
- package/dist/platform/feature-flags.js.map +1 -0
- package/dist/platform/fresh-sessions.d.ts +4 -0
- package/dist/platform/fresh-sessions.d.ts.map +1 -0
- package/dist/platform/fresh-sessions.js +22 -0
- package/dist/platform/fresh-sessions.js.map +1 -0
- package/dist/platform/instance-routes.d.ts +17 -0
- package/dist/platform/instance-routes.d.ts.map +1 -0
- package/dist/platform/instance-routes.js +105 -0
- package/dist/platform/instance-routes.js.map +1 -0
- package/dist/platform/logger.d.ts +20 -0
- package/dist/platform/logger.d.ts.map +1 -0
- package/dist/platform/logger.js +44 -0
- package/dist/platform/logger.js.map +1 -0
- package/dist/platform/opencode-errors.d.ts +20 -0
- package/dist/platform/opencode-errors.d.ts.map +1 -0
- package/dist/platform/opencode-errors.js +71 -0
- package/dist/platform/opencode-errors.js.map +1 -0
- package/dist/platform/platform-client/backups.d.ts +22 -0
- package/dist/platform/platform-client/backups.d.ts.map +1 -0
- package/dist/platform/platform-client/backups.js +16 -0
- package/dist/platform/platform-client/backups.js.map +1 -0
- package/dist/platform/platform-client/index.d.ts +21 -0
- package/dist/platform/platform-client/index.d.ts.map +1 -0
- package/dist/platform/platform-client/index.js +21 -0
- package/dist/platform/platform-client/index.js.map +1 -0
- package/dist/platform/platform-client/instance-admin.d.ts +67 -0
- package/dist/platform/platform-client/instance-admin.d.ts.map +1 -0
- package/dist/platform/platform-client/instance-admin.js +59 -0
- package/dist/platform/platform-client/instance-admin.js.map +1 -0
- package/dist/platform/platform-client/invites.d.ts +35 -0
- package/dist/platform/platform-client/invites.d.ts.map +1 -0
- package/dist/platform/platform-client/invites.js +25 -0
- package/dist/platform/platform-client/invites.js.map +1 -0
- package/dist/platform/platform-client/lifecycle.d.ts +78 -0
- package/dist/platform/platform-client/lifecycle.d.ts.map +1 -0
- package/dist/platform/platform-client/lifecycle.js +151 -0
- package/dist/platform/platform-client/lifecycle.js.map +1 -0
- package/dist/platform/platform-client/members.d.ts +81 -0
- package/dist/platform/platform-client/members.d.ts.map +1 -0
- package/dist/platform/platform-client/members.js +59 -0
- package/dist/platform/platform-client/members.js.map +1 -0
- package/dist/platform/platform-client/shared.d.ts +44 -0
- package/dist/platform/platform-client/shared.d.ts.map +1 -0
- package/dist/platform/platform-client/shared.js +177 -0
- package/dist/platform/platform-client/shared.js.map +1 -0
- package/dist/platform/platform-client/ssh.d.ts +29 -0
- package/dist/platform/platform-client/ssh.d.ts.map +1 -0
- package/dist/platform/platform-client/ssh.js +14 -0
- package/dist/platform/platform-client/ssh.js.map +1 -0
- package/dist/platform/platform-client/types.d.ts +56 -0
- package/dist/platform/platform-client/types.d.ts.map +1 -0
- package/dist/platform/platform-client/types.js +19 -0
- package/dist/platform/platform-client/types.js.map +1 -0
- package/dist/platform/platform-client/updates.d.ts +117 -0
- package/dist/platform/platform-client/updates.d.ts.map +1 -0
- package/dist/platform/platform-client/updates.js +97 -0
- package/dist/platform/platform-client/updates.js.map +1 -0
- package/dist/platform/platform-client/urls.d.ts +18 -0
- package/dist/platform/platform-client/urls.d.ts.map +1 -0
- package/dist/platform/platform-client/urls.js +31 -0
- package/dist/platform/platform-client/urls.js.map +1 -0
- package/dist/platform/projects-client/access.d.ts +273 -0
- package/dist/platform/projects-client/access.d.ts.map +1 -0
- package/dist/platform/projects-client/access.js +89 -0
- package/dist/platform/projects-client/access.js.map +1 -0
- package/dist/platform/projects-client/accounts.d.ts +184 -0
- package/dist/platform/projects-client/accounts.d.ts.map +1 -0
- package/dist/platform/projects-client/accounts.js +78 -0
- package/dist/platform/projects-client/accounts.js.map +1 -0
- package/dist/platform/projects-client/agent-config.d.ts +58 -0
- package/dist/platform/projects-client/agent-config.d.ts.map +1 -0
- package/dist/platform/projects-client/agent-config.js +9 -0
- package/dist/platform/projects-client/agent-config.js.map +1 -0
- package/dist/platform/projects-client/agent-scope.d.ts +12 -0
- package/dist/platform/projects-client/agent-scope.d.ts.map +1 -0
- package/dist/platform/projects-client/agent-scope.js +6 -0
- package/dist/platform/projects-client/agent-scope.js.map +1 -0
- package/dist/platform/projects-client/apps.d.ts +98 -0
- package/dist/platform/projects-client/apps.d.ts.map +1 -0
- package/dist/platform/projects-client/apps.js +29 -0
- package/dist/platform/projects-client/apps.js.map +1 -0
- package/dist/platform/projects-client/audit.d.ts +85 -0
- package/dist/platform/projects-client/audit.d.ts.map +1 -0
- package/dist/platform/projects-client/audit.js +51 -0
- package/dist/platform/projects-client/audit.js.map +1 -0
- package/dist/platform/projects-client/billing.d.ts +336 -0
- package/dist/platform/projects-client/billing.d.ts.map +1 -0
- package/dist/platform/projects-client/billing.js +260 -0
- package/dist/platform/projects-client/billing.js.map +1 -0
- package/dist/platform/projects-client/change-requests.d.ts +119 -0
- package/dist/platform/projects-client/change-requests.d.ts.map +1 -0
- package/dist/platform/projects-client/change-requests.js +56 -0
- package/dist/platform/projects-client/change-requests.js.map +1 -0
- package/dist/platform/projects-client/channels.d.ts +135 -0
- package/dist/platform/projects-client/channels.d.ts.map +1 -0
- package/dist/platform/projects-client/channels.js +103 -0
- package/dist/platform/projects-client/channels.js.map +1 -0
- package/dist/platform/projects-client/connectors.d.ts +148 -0
- package/dist/platform/projects-client/connectors.d.ts.map +1 -0
- package/dist/platform/projects-client/connectors.js +66 -0
- package/dist/platform/projects-client/connectors.js.map +1 -0
- package/dist/platform/projects-client/files.d.ts +37 -0
- package/dist/platform/projects-client/files.d.ts.map +1 -0
- package/dist/platform/projects-client/files.js +58 -0
- package/dist/platform/projects-client/files.js.map +1 -0
- package/dist/platform/projects-client/gateway.d.ts +177 -0
- package/dist/platform/projects-client/gateway.d.ts.map +1 -0
- package/dist/platform/projects-client/gateway.js +59 -0
- package/dist/platform/projects-client/gateway.js.map +1 -0
- package/dist/platform/projects-client/git-history.d.ts +74 -0
- package/dist/platform/projects-client/git-history.d.ts.map +1 -0
- package/dist/platform/projects-client/git-history.js +40 -0
- package/dist/platform/projects-client/git-history.js.map +1 -0
- package/dist/platform/projects-client/github.d.ts +62 -0
- package/dist/platform/projects-client/github.d.ts.map +1 -0
- package/dist/platform/projects-client/github.js +30 -0
- package/dist/platform/projects-client/github.js.map +1 -0
- package/dist/platform/projects-client/index.d.ts +32 -0
- package/dist/platform/projects-client/index.d.ts.map +1 -0
- package/dist/platform/projects-client/index.js +34 -0
- package/dist/platform/projects-client/index.js.map +1 -0
- package/dist/platform/projects-client/marketplace-catalog.d.ts +76 -0
- package/dist/platform/projects-client/marketplace-catalog.d.ts.map +1 -0
- package/dist/platform/projects-client/marketplace-catalog.js +48 -0
- package/dist/platform/projects-client/marketplace-catalog.js.map +1 -0
- package/dist/platform/projects-client/marketplace.d.ts +80 -0
- package/dist/platform/projects-client/marketplace.d.ts.map +1 -0
- package/dist/platform/projects-client/marketplace.js +52 -0
- package/dist/platform/projects-client/marketplace.js.map +1 -0
- package/dist/platform/projects-client/model-defaults.d.ts +36 -0
- package/dist/platform/projects-client/model-defaults.d.ts.map +1 -0
- package/dist/platform/projects-client/model-defaults.js +16 -0
- package/dist/platform/projects-client/model-defaults.js.map +1 -0
- package/dist/platform/projects-client/policies.d.ts +21 -0
- package/dist/platform/projects-client/policies.d.ts.map +1 -0
- package/dist/platform/projects-client/policies.js +10 -0
- package/dist/platform/projects-client/policies.js.map +1 -0
- package/dist/platform/projects-client/projects.d.ts +235 -0
- package/dist/platform/projects-client/projects.d.ts.map +1 -0
- package/dist/platform/projects-client/projects.js +161 -0
- package/dist/platform/projects-client/projects.js.map +1 -0
- package/dist/platform/projects-client/public-session-shares.d.ts +52 -0
- package/dist/platform/projects-client/public-session-shares.d.ts.map +1 -0
- package/dist/platform/projects-client/public-session-shares.js +54 -0
- package/dist/platform/projects-client/public-session-shares.js.map +1 -0
- package/dist/platform/projects-client/review.d.ts +57 -0
- package/dist/platform/projects-client/review.d.ts.map +1 -0
- package/dist/platform/projects-client/review.js +28 -0
- package/dist/platform/projects-client/review.js.map +1 -0
- package/dist/platform/projects-client/sandbox-shares.d.ts +25 -0
- package/dist/platform/projects-client/sandbox-shares.d.ts.map +1 -0
- package/dist/platform/projects-client/sandbox-shares.js +29 -0
- package/dist/platform/projects-client/sandbox-shares.js.map +1 -0
- package/dist/platform/projects-client/sandbox.d.ts +123 -0
- package/dist/platform/projects-client/sandbox.d.ts.map +1 -0
- package/dist/platform/projects-client/sandbox.js +45 -0
- package/dist/platform/projects-client/sandbox.js.map +1 -0
- package/dist/platform/projects-client/secrets.d.ts +122 -0
- package/dist/platform/projects-client/secrets.d.ts.map +1 -0
- package/dist/platform/projects-client/secrets.js +34 -0
- package/dist/platform/projects-client/secrets.js.map +1 -0
- package/dist/platform/projects-client/session-sandbox.d.ts +61 -0
- package/dist/platform/projects-client/session-sandbox.d.ts.map +1 -0
- package/dist/platform/projects-client/session-sandbox.js +82 -0
- package/dist/platform/projects-client/session-sandbox.js.map +1 -0
- package/dist/platform/projects-client/sessions.d.ts +216 -0
- package/dist/platform/projects-client/sessions.d.ts.map +1 -0
- package/dist/platform/projects-client/sessions.js +74 -0
- package/dist/platform/projects-client/sessions.js.map +1 -0
- package/dist/platform/projects-client/setup-links.d.ts +35 -0
- package/dist/platform/projects-client/setup-links.d.ts.map +1 -0
- package/dist/platform/projects-client/setup-links.js +24 -0
- package/dist/platform/projects-client/setup-links.js.map +1 -0
- package/dist/platform/projects-client/shared.d.ts +66 -0
- package/dist/platform/projects-client/shared.d.ts.map +1 -0
- package/dist/platform/projects-client/shared.js +44 -0
- package/dist/platform/projects-client/shared.js.map +1 -0
- package/dist/platform/projects-client/tokens.d.ts +77 -0
- package/dist/platform/projects-client/tokens.d.ts.map +1 -0
- package/dist/platform/projects-client/tokens.js +43 -0
- package/dist/platform/projects-client/tokens.js.map +1 -0
- package/dist/platform/projects-client/transcription.d.ts +5 -0
- package/dist/platform/projects-client/transcription.d.ts.map +1 -0
- package/dist/platform/projects-client/transcription.js +14 -0
- package/dist/platform/projects-client/transcription.js.map +1 -0
- package/dist/platform/projects-client/triggers.d.ts +102 -0
- package/dist/platform/projects-client/triggers.d.ts.map +1 -0
- package/dist/platform/projects-client/triggers.js +27 -0
- package/dist/platform/projects-client/triggers.js.map +1 -0
- package/dist/platform/session-id.d.ts +9 -0
- package/dist/platform/session-id.d.ts.map +1 -0
- package/dist/platform/session-id.js +23 -0
- package/dist/platform/session-id.js.map +1 -0
- package/dist/platform/storage/managed-storage.d.ts +97 -0
- package/dist/platform/storage/managed-storage.d.ts.map +1 -0
- package/dist/platform/storage/managed-storage.js +271 -0
- package/dist/platform/storage/managed-storage.js.map +1 -0
- package/dist/platform/strings.d.ts +12 -0
- package/dist/platform/strings.d.ts.map +1 -0
- package/dist/platform/strings.js +17 -0
- package/dist/platform/strings.js.map +1 -0
- package/dist/platform/ui.d.ts +11 -0
- package/dist/platform/ui.d.ts.map +1 -0
- package/dist/platform/ui.js +22 -0
- package/dist/platform/ui.js.map +1 -0
- package/dist/react/chat/index.d.ts +3 -0
- package/dist/react/chat/index.d.ts.map +1 -0
- package/dist/react/chat/index.js +7 -0
- package/dist/react/chat/index.js.map +1 -0
- package/dist/react/chat/render-parts.d.ts +39 -0
- package/dist/react/chat/render-parts.d.ts.map +1 -0
- package/dist/react/chat/render-parts.js +34 -0
- package/dist/react/chat/render-parts.js.map +1 -0
- package/dist/react/chat/use-chat-turns.d.ts +19 -0
- package/dist/react/chat/use-chat-turns.d.ts.map +1 -0
- package/dist/react/chat/use-chat-turns.js +27 -0
- package/dist/react/chat/use-chat-turns.js.map +1 -0
- package/dist/react/file-keys.d.ts +18 -0
- package/dist/react/file-keys.d.ts.map +1 -0
- package/dist/react/file-keys.js +18 -0
- package/dist/react/file-keys.js.map +1 -0
- package/dist/react/index.d.ts +12 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +49 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/model-flatten.d.ts +33 -0
- package/dist/react/model-flatten.d.ts.map +1 -0
- package/dist/react/model-flatten.js +59 -0
- package/dist/react/model-flatten.js.map +1 -0
- package/dist/react/opencode.d.ts +43 -0
- package/dist/react/opencode.d.ts.map +1 -0
- package/dist/react/opencode.js +100 -0
- package/dist/react/opencode.js.map +1 -0
- package/dist/react/prefetch-session-start.d.ts +10 -0
- package/dist/react/prefetch-session-start.d.ts.map +1 -0
- package/dist/react/prefetch-session-start.js +17 -0
- package/dist/react/prefetch-session-start.js.map +1 -0
- package/dist/react/provider-refresh.d.ts +7 -0
- package/dist/react/provider-refresh.d.ts.map +1 -0
- package/dist/react/provider-refresh.js +28 -0
- package/dist/react/provider-refresh.js.map +1 -0
- package/dist/react/provider-selection.d.ts +31 -0
- package/dist/react/provider-selection.d.ts.map +1 -0
- package/dist/react/provider-selection.js +135 -0
- package/dist/react/provider-selection.js.map +1 -0
- package/dist/react/route-project.d.ts +7 -0
- package/dist/react/route-project.d.ts.map +1 -0
- package/dist/react/route-project.js +19 -0
- package/dist/react/route-project.js.map +1 -0
- package/dist/react/session-start-stash.d.ts +56 -0
- package/dist/react/session-start-stash.d.ts.map +1 -0
- package/dist/react/session-start-stash.js +202 -0
- package/dist/react/session-start-stash.js.map +1 -0
- package/dist/react/use-canonical-opencode-session.d.ts +35 -0
- package/dist/react/use-canonical-opencode-session.d.ts.map +1 -0
- package/dist/react/use-canonical-opencode-session.js +52 -0
- package/dist/react/use-canonical-opencode-session.js.map +1 -0
- package/dist/react/use-change-requests.d.ts +321 -0
- package/dist/react/use-change-requests.d.ts.map +1 -0
- package/dist/react/use-change-requests.js +43 -0
- package/dist/react/use-change-requests.js.map +1 -0
- package/dist/react/use-current-runtime.d.ts +8 -0
- package/dist/react/use-current-runtime.d.ts.map +1 -0
- package/dist/react/use-current-runtime.js +12 -0
- package/dist/react/use-current-runtime.js.map +1 -0
- package/dist/react/use-gateway-catalog-sync.d.ts +2 -0
- package/dist/react/use-gateway-catalog-sync.d.ts.map +1 -0
- package/dist/react/use-gateway-catalog-sync.js +39 -0
- package/dist/react/use-gateway-catalog-sync.js.map +1 -0
- package/dist/react/use-kortix-master.d.ts +384 -0
- package/dist/react/use-kortix-master.d.ts.map +1 -0
- package/dist/react/use-kortix-master.js +958 -0
- package/dist/react/use-kortix-master.js.map +1 -0
- package/dist/react/use-model-store.d.ts +71 -0
- package/dist/react/use-model-store.d.ts.map +1 -0
- package/dist/react/use-model-store.js +411 -0
- package/dist/react/use-model-store.js.map +1 -0
- package/dist/react/use-opencode-config.d.ts +15 -0
- package/dist/react/use-opencode-config.d.ts.map +1 -0
- package/dist/react/use-opencode-config.js +79 -0
- package/dist/react/use-opencode-config.js.map +1 -0
- package/dist/react/use-opencode-events/diagnostics.d.ts +11 -0
- package/dist/react/use-opencode-events/diagnostics.d.ts.map +1 -0
- package/dist/react/use-opencode-events/diagnostics.js +58 -0
- package/dist/react/use-opencode-events/diagnostics.js.map +1 -0
- package/dist/react/use-opencode-events/handle-event.d.ts +20 -0
- package/dist/react/use-opencode-events/handle-event.d.ts.map +1 -0
- package/dist/react/use-opencode-events/handle-event.js +450 -0
- package/dist/react/use-opencode-events/handle-event.js.map +1 -0
- package/dist/react/use-opencode-events/helpers.d.ts +30 -0
- package/dist/react/use-opencode-events/helpers.d.ts.map +1 -0
- package/dist/react/use-opencode-events/helpers.js +93 -0
- package/dist/react/use-opencode-events/helpers.js.map +1 -0
- package/dist/react/use-opencode-events/index.d.ts +25 -0
- package/dist/react/use-opencode-events/index.d.ts.map +1 -0
- package/dist/react/use-opencode-events/index.js +242 -0
- package/dist/react/use-opencode-events/index.js.map +1 -0
- package/dist/react/use-opencode-events/types.d.ts +10 -0
- package/dist/react/use-opencode-events/types.d.ts.map +1 -0
- package/dist/react/use-opencode-events/types.js +2 -0
- package/dist/react/use-opencode-events/types.js.map +1 -0
- package/dist/react/use-opencode-events/use-event-stream-refs.d.ts +22 -0
- package/dist/react/use-opencode-events/use-event-stream-refs.d.ts.map +1 -0
- package/dist/react/use-opencode-events/use-event-stream-refs.js +158 -0
- package/dist/react/use-opencode-events/use-event-stream-refs.js.map +1 -0
- package/dist/react/use-opencode-local.d.ts +139 -0
- package/dist/react/use-opencode-local.d.ts.map +1 -0
- package/dist/react/use-opencode-local.js +484 -0
- package/dist/react/use-opencode-local.js.map +1 -0
- package/dist/react/use-opencode-mcp.d.ts +34 -0
- package/dist/react/use-opencode-mcp.d.ts.map +1 -0
- package/dist/react/use-opencode-mcp.js +190 -0
- package/dist/react/use-opencode-mcp.js.map +1 -0
- package/dist/react/use-opencode-pty.d.ts +30 -0
- package/dist/react/use-opencode-pty.d.ts.map +1 -0
- package/dist/react/use-opencode-pty.js +126 -0
- package/dist/react/use-opencode-pty.js.map +1 -0
- package/dist/react/use-opencode-sessions/agents.d.ts +14 -0
- package/dist/react/use-opencode-sessions/agents.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/agents.js +82 -0
- package/dist/react/use-opencode-sessions/agents.js.map +1 -0
- package/dist/react/use-opencode-sessions/commands.d.ts +8 -0
- package/dist/react/use-opencode-sessions/commands.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/commands.js +46 -0
- package/dist/react/use-opencode-sessions/commands.js.map +1 -0
- package/dist/react/use-opencode-sessions/files.d.ts +2 -0
- package/dist/react/use-opencode-sessions/files.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/files.js +181 -0
- package/dist/react/use-opencode-sessions/files.js.map +1 -0
- package/dist/react/use-opencode-sessions/index.d.ts +15 -0
- package/dist/react/use-opencode-sessions/index.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/index.js +21 -0
- package/dist/react/use-opencode-sessions/index.js.map +1 -0
- package/dist/react/use-opencode-sessions/keys.d.ts +94 -0
- package/dist/react/use-opencode-sessions/keys.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/keys.js +39 -0
- package/dist/react/use-opencode-sessions/keys.js.map +1 -0
- package/dist/react/use-opencode-sessions/mcp.d.ts +3 -0
- package/dist/react/use-opencode-sessions/mcp.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/mcp.js +23 -0
- package/dist/react/use-opencode-sessions/mcp.js.map +1 -0
- package/dist/react/use-opencode-sessions/messages.d.ts +75 -0
- package/dist/react/use-opencode-sessions/messages.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/messages.js +319 -0
- package/dist/react/use-opencode-sessions/messages.js.map +1 -0
- package/dist/react/use-opencode-sessions/parts.d.ts +23 -0
- package/dist/react/use-opencode-sessions/parts.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/parts.js +49 -0
- package/dist/react/use-opencode-sessions/parts.js.map +1 -0
- package/dist/react/use-opencode-sessions/permissions.d.ts +17 -0
- package/dist/react/use-opencode-sessions/permissions.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/permissions.js +66 -0
- package/dist/react/use-opencode-sessions/permissions.js.map +1 -0
- package/dist/react/use-opencode-sessions/projects.d.ts +5 -0
- package/dist/react/use-opencode-sessions/projects.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/projects.js +54 -0
- package/dist/react/use-opencode-sessions/projects.js.map +1 -0
- package/dist/react/use-opencode-sessions/providers.d.ts +10 -0
- package/dist/react/use-opencode-sessions/providers.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/providers.js +98 -0
- package/dist/react/use-opencode-sessions/providers.js.map +1 -0
- package/dist/react/use-opencode-sessions/sessions.d.ts +35 -0
- package/dist/react/use-opencode-sessions/sessions.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/sessions.js +380 -0
- package/dist/react/use-opencode-sessions/sessions.js.map +1 -0
- package/dist/react/use-opencode-sessions/shared.d.ts +43 -0
- package/dist/react/use-opencode-sessions/shared.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/shared.js +109 -0
- package/dist/react/use-opencode-sessions/shared.js.map +1 -0
- package/dist/react/use-opencode-sessions/sharing.d.ts +4 -0
- package/dist/react/use-opencode-sessions/sharing.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/sharing.js +57 -0
- package/dist/react/use-opencode-sessions/sharing.js.map +1 -0
- package/dist/react/use-opencode-sessions/tools.d.ts +5 -0
- package/dist/react/use-opencode-sessions/tools.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/tools.js +54 -0
- package/dist/react/use-opencode-sessions/tools.js.map +1 -0
- package/dist/react/use-permission-self-heal.d.ts +45 -0
- package/dist/react/use-permission-self-heal.d.ts.map +1 -0
- package/dist/react/use-permission-self-heal.js +144 -0
- package/dist/react/use-permission-self-heal.js.map +1 -0
- package/dist/react/use-project-config.d.ts +11 -0
- package/dist/react/use-project-config.d.ts.map +1 -0
- package/dist/react/use-project-config.js +22 -0
- package/dist/react/use-project-config.js.map +1 -0
- package/dist/react/use-project-models.d.ts +11 -0
- package/dist/react/use-project-models.d.ts.map +1 -0
- package/dist/react/use-project-models.js +25 -0
- package/dist/react/use-project-models.js.map +1 -0
- package/dist/react/use-project-secrets.d.ts +265 -0
- package/dist/react/use-project-secrets.d.ts.map +1 -0
- package/dist/react/use-project-secrets.js +41 -0
- package/dist/react/use-project-secrets.js.map +1 -0
- package/dist/react/use-project-triggers.d.ts +228 -0
- package/dist/react/use-project-triggers.d.ts.map +1 -0
- package/dist/react/use-project-triggers.js +42 -0
- package/dist/react/use-project-triggers.js.map +1 -0
- package/dist/react/use-question-self-heal.d.ts +36 -0
- package/dist/react/use-question-self-heal.d.ts.map +1 -0
- package/dist/react/use-question-self-heal.js +95 -0
- package/dist/react/use-question-self-heal.js.map +1 -0
- package/dist/react/use-runtime-phase.d.ts +9 -0
- package/dist/react/use-runtime-phase.d.ts.map +1 -0
- package/dist/react/use-runtime-phase.js +20 -0
- package/dist/react/use-runtime-phase.js.map +1 -0
- package/dist/react/use-runtime-reconnect.d.ts +90 -0
- package/dist/react/use-runtime-reconnect.d.ts.map +1 -0
- package/dist/react/use-runtime-reconnect.js +234 -0
- package/dist/react/use-runtime-reconnect.js.map +1 -0
- package/dist/react/use-session-picks.d.ts +17 -0
- package/dist/react/use-session-picks.d.ts.map +1 -0
- package/dist/react/use-session-picks.js +36 -0
- package/dist/react/use-session-picks.js.map +1 -0
- package/dist/react/use-session-prefetch.d.ts +18 -0
- package/dist/react/use-session-prefetch.d.ts.map +1 -0
- package/dist/react/use-session-prefetch.js +84 -0
- package/dist/react/use-session-prefetch.js.map +1 -0
- package/dist/react/use-session-send.d.ts +183 -0
- package/dist/react/use-session-send.d.ts.map +1 -0
- package/dist/react/use-session-send.js +287 -0
- package/dist/react/use-session-send.js.map +1 -0
- package/dist/react/use-session-sync.d.ts +24 -0
- package/dist/react/use-session-sync.d.ts.map +1 -0
- package/dist/react/use-session-sync.js +375 -0
- package/dist/react/use-session-sync.js.map +1 -0
- package/dist/react/use-session.d.ts +171 -0
- package/dist/react/use-session.d.ts.map +1 -0
- package/dist/react/use-session.js +396 -0
- package/dist/react/use-session.js.map +1 -0
- package/dist/react/use-visible-agents.d.ts +22 -0
- package/dist/react/use-visible-agents.d.ts.map +1 -0
- package/dist/react/use-visible-agents.js +45 -0
- package/dist/react/use-visible-agents.js.map +1 -0
- package/dist/server.d.ts +55 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +122 -0
- package/dist/server.js.map +1 -0
- package/dist/session/health.d.ts +49 -0
- package/dist/session/health.d.ts.map +1 -0
- package/dist/session/health.js +57 -0
- package/dist/session/health.js.map +1 -0
- package/dist/session/index.d.ts +19 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +19 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/preview.d.ts +24 -0
- package/dist/session/preview.d.ts.map +1 -0
- package/dist/session/preview.js +85 -0
- package/dist/session/preview.js.map +1 -0
- package/dist/session/url.d.ts +160 -0
- package/dist/session/url.d.ts.map +1 -0
- package/dist/session/url.js +522 -0
- package/dist/session/url.js.map +1 -0
- package/dist/state/chat-events.d.ts +141 -0
- package/dist/state/chat-events.d.ts.map +1 -0
- package/dist/state/chat-events.js +135 -0
- package/dist/state/chat-events.js.map +1 -0
- package/dist/state/current-runtime.d.ts +44 -0
- package/dist/state/current-runtime.d.ts.map +1 -0
- package/dist/state/current-runtime.js +44 -0
- package/dist/state/current-runtime.js.map +1 -0
- package/dist/state/diagnostics-store.d.ts +114 -0
- package/dist/state/diagnostics-store.d.ts.map +1 -0
- package/dist/state/diagnostics-store.js +319 -0
- package/dist/state/diagnostics-store.js.map +1 -0
- package/dist/state/event-stream.d.ts +134 -0
- package/dist/state/event-stream.d.ts.map +1 -0
- package/dist/state/event-stream.js +424 -0
- package/dist/state/event-stream.js.map +1 -0
- package/dist/state/idb-sync-cache.d.ts +18 -0
- package/dist/state/idb-sync-cache.d.ts.map +1 -0
- package/dist/state/idb-sync-cache.js +209 -0
- package/dist/state/idb-sync-cache.js.map +1 -0
- package/dist/state/opencode-compaction-store.d.ts +10 -0
- package/dist/state/opencode-compaction-store.d.ts.map +1 -0
- package/dist/state/opencode-compaction-store.js +32 -0
- package/dist/state/opencode-compaction-store.js.map +1 -0
- package/dist/state/opencode-pending-store.d.ts +19 -0
- package/dist/state/opencode-pending-store.d.ts.map +1 -0
- package/dist/state/opencode-pending-store.js +76 -0
- package/dist/state/opencode-pending-store.js.map +1 -0
- package/dist/state/sandbox-connection-store.d.ts +62 -0
- package/dist/state/sandbox-connection-store.d.ts.map +1 -0
- package/dist/state/sandbox-connection-store.js +290 -0
- package/dist/state/sandbox-connection-store.js.map +1 -0
- package/dist/state/server-store/active.d.ts +49 -0
- package/dist/state/server-store/active.d.ts.map +1 -0
- package/dist/state/server-store/active.js +76 -0
- package/dist/state/server-store/active.js.map +1 -0
- package/dist/state/server-store/types.d.ts +12 -0
- package/dist/state/server-store/types.d.ts.map +1 -0
- package/dist/state/server-store/types.js +2 -0
- package/dist/state/server-store/types.js.map +1 -0
- package/dist/state/server-store/url-helpers.d.ts +33 -0
- package/dist/state/server-store/url-helpers.d.ts.map +1 -0
- package/dist/state/server-store/url-helpers.js +55 -0
- package/dist/state/server-store/url-helpers.js.map +1 -0
- package/dist/state/server-store.d.ts +18 -0
- package/dist/state/server-store.d.ts.map +1 -0
- package/dist/state/server-store.js +23 -0
- package/dist/state/server-store.js.map +1 -0
- package/dist/state/session-runtime-registry.d.ts +49 -0
- package/dist/state/session-runtime-registry.d.ts.map +1 -0
- package/dist/state/session-runtime-registry.js +85 -0
- package/dist/state/session-runtime-registry.js.map +1 -0
- package/dist/state/sync-store/ascending-id.d.ts +2 -0
- package/dist/state/sync-store/ascending-id.d.ts.map +1 -0
- package/dist/state/sync-store/ascending-id.js +21 -0
- package/dist/state/sync-store/ascending-id.js.map +1 -0
- package/dist/state/sync-store/binary.d.ts +7 -0
- package/dist/state/sync-store/binary.d.ts.map +1 -0
- package/dist/state/sync-store/binary.js +21 -0
- package/dist/state/sync-store/binary.js.map +1 -0
- package/dist/state/sync-store/stream-cache.d.ts +2 -0
- package/dist/state/sync-store/stream-cache.d.ts.map +1 -0
- package/dist/state/sync-store/stream-cache.js +29 -0
- package/dist/state/sync-store/stream-cache.js.map +1 -0
- package/dist/state/sync-store/types.d.ts +29 -0
- package/dist/state/sync-store/types.d.ts.map +1 -0
- package/dist/state/sync-store/types.js +2 -0
- package/dist/state/sync-store/types.js.map +1 -0
- package/dist/state/sync-store.d.ts +39 -0
- package/dist/state/sync-store.d.ts.map +1 -0
- package/dist/state/sync-store.js +692 -0
- package/dist/state/sync-store.js.map +1 -0
- package/dist/state/tab-store.d.ts +91 -0
- package/dist/state/tab-store.d.ts.map +1 -0
- package/dist/state/tab-store.js +369 -0
- package/dist/state/tab-store.js.map +1 -0
- package/dist/transcript.d.ts +40 -0
- package/dist/transcript.d.ts.map +1 -0
- package/dist/transcript.js +126 -0
- package/dist/transcript.js.map +1 -0
- package/dist/turns/classify.d.ts +166 -0
- package/dist/turns/classify.d.ts.map +1 -0
- package/dist/turns/classify.js +259 -0
- package/dist/turns/classify.js.map +1 -0
- package/dist/turns/errors.d.ts +11 -0
- package/dist/turns/errors.d.ts.map +1 -0
- package/dist/turns/errors.js +85 -0
- package/dist/turns/errors.js.map +1 -0
- package/dist/turns/index.d.ts +264 -0
- package/dist/turns/index.d.ts.map +1 -0
- package/dist/turns/index.js +1243 -0
- package/dist/turns/index.js.map +1 -0
- package/dist/turns/tool-registry.d.ts +33 -0
- package/dist/turns/tool-registry.d.ts.map +1 -0
- package/dist/turns/tool-registry.js +108 -0
- package/dist/turns/tool-registry.js.map +1 -0
- package/dist/turns/types.d.ts +125 -0
- package/dist/turns/types.d.ts.map +1 -0
- package/dist/turns/types.js +12 -0
- package/dist/turns/types.js.map +1 -0
- package/dist/turns/view-model.d.ts +127 -0
- package/dist/turns/view-model.d.ts.map +1 -0
- package/dist/turns/view-model.js +401 -0
- package/dist/turns/view-model.js.map +1 -0
- package/package.json +155 -0
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { create } from "zustand";
|
|
3
|
+
import { ascendingId } from "./sync-store/ascending-id.js";
|
|
4
|
+
import { Binary } from "./sync-store/binary.js";
|
|
5
|
+
import { writeStreamCache } from "./sync-store/stream-cache.js";
|
|
6
|
+
// Re-export moved helpers/types so the public surface stays byte-identical:
|
|
7
|
+
// `Binary`, `ascendingId`, and the `MessageWithParts` type remain importable
|
|
8
|
+
// from this module exactly as before.
|
|
9
|
+
export { ascendingId, Binary };
|
|
10
|
+
function isTextLikePart(part) {
|
|
11
|
+
return part.type === "text" || part.type === "reasoning";
|
|
12
|
+
}
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Store Implementation
|
|
15
|
+
// Track optimistic message IDs so we can remove them when the server sends
|
|
16
|
+
// the real user message (which has a different, server-generated ID).
|
|
17
|
+
const optimisticIds = new Set();
|
|
18
|
+
// Track message IDs where optimistic parts were bridged to the real message.
|
|
19
|
+
// When the first real part arrives for a bridged message, the bridged parts
|
|
20
|
+
// are cleared so optimistic and real parts don't co-exist (which would
|
|
21
|
+
// double-render the user's text).
|
|
22
|
+
const bridgedPartIds = new Set();
|
|
23
|
+
// Track part IDs that have received at least one delta.
|
|
24
|
+
// Used by upsertPart to avoid overwriting delta-accumulated text with a
|
|
25
|
+
// stale message.part.updated snapshot that arrives in the same event batch.
|
|
26
|
+
// Entries are cleared when the streaming session goes idle.
|
|
27
|
+
const deltaActiveParts = new Set();
|
|
28
|
+
// ============================================================================
|
|
29
|
+
export const useSyncStore = create()((set, get) => ({
|
|
30
|
+
messages: {},
|
|
31
|
+
parts: {},
|
|
32
|
+
sessionStatus: {},
|
|
33
|
+
diffs: {},
|
|
34
|
+
todos: {},
|
|
35
|
+
// Compat alias
|
|
36
|
+
get statuses() {
|
|
37
|
+
return get().sessionStatus;
|
|
38
|
+
},
|
|
39
|
+
// ---- Core mutations ----
|
|
40
|
+
upsertMessage: (sessionID, message) => set((s) => {
|
|
41
|
+
const list = s.messages[sessionID] ?? [];
|
|
42
|
+
// First try binary search (fast path for sorted lists).
|
|
43
|
+
const result = Binary.search(list, message.id, (m) => m.id);
|
|
44
|
+
// Verify the binary search result — the list may be temporarily
|
|
45
|
+
// unsorted due to optimistic messages appended at the end.
|
|
46
|
+
const bsValid = result.found && list[result.index]?.id === message.id;
|
|
47
|
+
if (bsValid) {
|
|
48
|
+
const next = [...list];
|
|
49
|
+
next[result.index] = message;
|
|
50
|
+
return { messages: { ...s.messages, [sessionID]: next } };
|
|
51
|
+
}
|
|
52
|
+
// Fall back to linear scan to handle unsorted optimistic entries.
|
|
53
|
+
const linearIdx = list.findIndex((m) => m.id === message.id);
|
|
54
|
+
if (linearIdx !== -1) {
|
|
55
|
+
const next = [...list];
|
|
56
|
+
next[linearIdx] = message;
|
|
57
|
+
return { messages: { ...s.messages, [sessionID]: next } };
|
|
58
|
+
}
|
|
59
|
+
// New message — insert at sorted position via binary search.
|
|
60
|
+
const next = [...list];
|
|
61
|
+
next.splice(result.index, 0, message);
|
|
62
|
+
return { messages: { ...s.messages, [sessionID]: next } };
|
|
63
|
+
}),
|
|
64
|
+
removeMessage: (sessionID, messageID) => set((s) => {
|
|
65
|
+
const list = s.messages[sessionID];
|
|
66
|
+
if (!list)
|
|
67
|
+
return s;
|
|
68
|
+
// Try binary search first, fall back to linear for unsorted lists.
|
|
69
|
+
const result = Binary.search(list, messageID, (m) => m.id);
|
|
70
|
+
const idx = (result.found && list[result.index]?.id === messageID)
|
|
71
|
+
? result.index
|
|
72
|
+
: list.findIndex((m) => m.id === messageID);
|
|
73
|
+
if (idx === -1)
|
|
74
|
+
return s;
|
|
75
|
+
const next = [...list];
|
|
76
|
+
next.splice(idx, 1);
|
|
77
|
+
const { [messageID]: _, ...restParts } = s.parts;
|
|
78
|
+
return {
|
|
79
|
+
messages: { ...s.messages, [sessionID]: next },
|
|
80
|
+
parts: restParts,
|
|
81
|
+
};
|
|
82
|
+
}),
|
|
83
|
+
upsertPart: (messageID, part) => set((s) => {
|
|
84
|
+
// If this message had bridged (optimistic) parts, clear them now
|
|
85
|
+
// that a real part has arrived — prevents double-rendering.
|
|
86
|
+
let list;
|
|
87
|
+
let bridgeCleared = false;
|
|
88
|
+
if (bridgedPartIds.has(messageID)) {
|
|
89
|
+
// Only retire the optimistic/bridged user text once a REAL text
|
|
90
|
+
// part with actual content arrives. A stray non-text part — or an
|
|
91
|
+
// empty text snapshot — must NOT wipe the bridge, otherwise the
|
|
92
|
+
// user's message renders as an empty bubble.
|
|
93
|
+
const incoming = part;
|
|
94
|
+
const incomingIsRealText = incoming?.type === "text" &&
|
|
95
|
+
typeof incoming.text === "string" &&
|
|
96
|
+
incoming.text.length > 0;
|
|
97
|
+
if (incomingIsRealText) {
|
|
98
|
+
bridgedPartIds.delete(messageID);
|
|
99
|
+
list = [];
|
|
100
|
+
bridgeCleared = true;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
list = s.parts[messageID] ?? [];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
list = s.parts[messageID] ?? [];
|
|
108
|
+
}
|
|
109
|
+
const result = Binary.search(list, part.id, (p) => p.id);
|
|
110
|
+
if (result.found) {
|
|
111
|
+
const prev = list[result.index];
|
|
112
|
+
const prevIsTextLike = isTextLikePart(prev);
|
|
113
|
+
const incomingIsTextLike = isTextLikePart(part);
|
|
114
|
+
const tracksStreamingText = prevIsTextLike && incomingIsTextLike;
|
|
115
|
+
const prevText = prevIsTextLike ? prev.text : null;
|
|
116
|
+
const incomingText = incomingIsTextLike ? part.text : null;
|
|
117
|
+
// Guard against out-of-order/stale part snapshots that can cause
|
|
118
|
+
// the stream to jump or start from the middle.
|
|
119
|
+
// For existing text parts, only accept full-text replacements that
|
|
120
|
+
// are monotonic prefix growth (incoming starts with previous).
|
|
121
|
+
// Otherwise keep the existing part as-is — returning `s` avoids
|
|
122
|
+
// creating a new state reference which would cause infinite
|
|
123
|
+
// re-render loops in consuming components.
|
|
124
|
+
if (tracksStreamingText &&
|
|
125
|
+
prevText !== null &&
|
|
126
|
+
incomingText !== null &&
|
|
127
|
+
prevText.length > 0) {
|
|
128
|
+
const isPrefixGrowth = incomingText.startsWith(prevText);
|
|
129
|
+
if (!isPrefixGrowth) {
|
|
130
|
+
// Incoming text is not a prefix extension — reject the update
|
|
131
|
+
// entirely. Returning `s` preserves referential equality and
|
|
132
|
+
// prevents downstream selectors from re-firing.
|
|
133
|
+
if (!bridgeCleared)
|
|
134
|
+
return s;
|
|
135
|
+
// Bridge was cleared but we still need to keep the existing part.
|
|
136
|
+
const next = [...list];
|
|
137
|
+
next[result.index] = prev;
|
|
138
|
+
return { parts: { ...s.parts, [messageID]: next } };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const next = [...list];
|
|
143
|
+
if (result.found) {
|
|
144
|
+
next[result.index] = part;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// For NEW text/reasoning parts: if deltas have already been
|
|
148
|
+
// applied for this part ID, the part was created by the delta
|
|
149
|
+
// handler with correct accumulated text. A message.part.updated
|
|
150
|
+
// snapshot arriving later in the same batch could carry stale
|
|
151
|
+
// text (missing the beginning). Skip the insert — the delta-
|
|
152
|
+
// created version already exists in the parts list under the
|
|
153
|
+
// message entry created by the delta handler.
|
|
154
|
+
if (deltaActiveParts.has(part.id) && isTextLikePart(part)) {
|
|
155
|
+
// Delta-created part already exists — check all messageID
|
|
156
|
+
// buckets since the delta handler may have stored it under
|
|
157
|
+
// a different (stub) message entry.
|
|
158
|
+
const allParts = Object.values(s.parts);
|
|
159
|
+
for (const pl of allParts) {
|
|
160
|
+
if (pl && pl.some((p) => p.id === part.id)) {
|
|
161
|
+
return s;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
next.splice(result.index, 0, part);
|
|
166
|
+
}
|
|
167
|
+
return { parts: { ...s.parts, [messageID]: next } };
|
|
168
|
+
}),
|
|
169
|
+
removePart: (messageID, partID) => set((s) => {
|
|
170
|
+
const list = s.parts[messageID];
|
|
171
|
+
if (!list)
|
|
172
|
+
return s;
|
|
173
|
+
const result = Binary.search(list, partID, (p) => p.id);
|
|
174
|
+
if (!result.found)
|
|
175
|
+
return s;
|
|
176
|
+
const next = [...list];
|
|
177
|
+
next.splice(result.index, 1);
|
|
178
|
+
if (next.length === 0) {
|
|
179
|
+
const { [messageID]: _, ...restParts } = s.parts;
|
|
180
|
+
return { parts: restParts };
|
|
181
|
+
}
|
|
182
|
+
return { parts: { ...s.parts, [messageID]: next } };
|
|
183
|
+
}),
|
|
184
|
+
applyPartDelta: (messageID, partID, field, delta) => {
|
|
185
|
+
deltaActiveParts.add(partID);
|
|
186
|
+
set((s) => {
|
|
187
|
+
const list = s.parts[messageID];
|
|
188
|
+
if (!list)
|
|
189
|
+
return s;
|
|
190
|
+
const result = Binary.search(list, partID, (p) => p.id);
|
|
191
|
+
if (!result.found)
|
|
192
|
+
return s;
|
|
193
|
+
const next = [...list];
|
|
194
|
+
const part = { ...next[result.index] };
|
|
195
|
+
const existing = part[field];
|
|
196
|
+
part[field] = (existing ?? "") + delta;
|
|
197
|
+
next[result.index] = part;
|
|
198
|
+
return { parts: { ...s.parts, [messageID]: next } };
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
setStatus: (sessionID, status) => set((s) => ({
|
|
202
|
+
sessionStatus: { ...s.sessionStatus, [sessionID]: status },
|
|
203
|
+
})),
|
|
204
|
+
setDiff: (sessionID, diffs) => set((s) => ({
|
|
205
|
+
diffs: { ...s.diffs, [sessionID]: diffs },
|
|
206
|
+
})),
|
|
207
|
+
setTodo: (sessionID, todos) => set((s) => ({
|
|
208
|
+
todos: { ...s.todos, [sessionID]: todos },
|
|
209
|
+
})),
|
|
210
|
+
optimisticAdd: (sessionID, message, messageParts) => {
|
|
211
|
+
optimisticIds.add(message.id);
|
|
212
|
+
set((s) => {
|
|
213
|
+
const list = s.messages[sessionID] ?? [];
|
|
214
|
+
// Always append optimistic messages at the end of the list.
|
|
215
|
+
// Client-generated IDs can sort before server IDs due to clock skew
|
|
216
|
+
// (browser vs Docker). Appending ensures the user message appears
|
|
217
|
+
// at the bottom of the chat. The list may be temporarily unsorted,
|
|
218
|
+
// but upsertMessage and optimisticRemove handle this correctly.
|
|
219
|
+
const nextMsgs = [...list.filter((m) => m.id !== message.id), message];
|
|
220
|
+
const sorted = messageParts
|
|
221
|
+
.filter((p) => !!p?.id)
|
|
222
|
+
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
223
|
+
return {
|
|
224
|
+
messages: { ...s.messages, [sessionID]: nextMsgs },
|
|
225
|
+
parts: { ...s.parts, [message.id]: sorted },
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
optimisticRemove: (sessionID, messageID) => {
|
|
230
|
+
optimisticIds.delete(messageID);
|
|
231
|
+
set((s) => {
|
|
232
|
+
const list = s.messages[sessionID];
|
|
233
|
+
if (!list)
|
|
234
|
+
return s;
|
|
235
|
+
// Use linear search — optimistic messages may be appended out of
|
|
236
|
+
// sorted order, so Binary.search can miss them.
|
|
237
|
+
const idx = list.findIndex((m) => m.id === messageID);
|
|
238
|
+
if (idx === -1)
|
|
239
|
+
return s;
|
|
240
|
+
const nextMsgs = [...list];
|
|
241
|
+
nextMsgs.splice(idx, 1);
|
|
242
|
+
const { [messageID]: _, ...restParts } = s.parts;
|
|
243
|
+
return {
|
|
244
|
+
messages: { ...s.messages, [sessionID]: nextMsgs },
|
|
245
|
+
parts: restParts,
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
},
|
|
249
|
+
clearOptimisticMessages: (sessionID) => {
|
|
250
|
+
set((s) => {
|
|
251
|
+
const list = s.messages[sessionID];
|
|
252
|
+
if (!list)
|
|
253
|
+
return s;
|
|
254
|
+
const optIds = list
|
|
255
|
+
.filter((m) => optimisticIds.has(m.id))
|
|
256
|
+
.map((m) => m.id);
|
|
257
|
+
if (optIds.length === 0)
|
|
258
|
+
return s;
|
|
259
|
+
for (const id of optIds)
|
|
260
|
+
optimisticIds.delete(id);
|
|
261
|
+
const filtered = list.filter((m) => !optIds.includes(m.id));
|
|
262
|
+
const newParts = { ...s.parts };
|
|
263
|
+
for (const id of optIds)
|
|
264
|
+
delete newParts[id];
|
|
265
|
+
return {
|
|
266
|
+
messages: { ...s.messages, [sessionID]: filtered },
|
|
267
|
+
parts: newParts,
|
|
268
|
+
};
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
clearSession: (sessionID) => set((s) => {
|
|
272
|
+
const existingMessages = s.messages[sessionID] ?? [];
|
|
273
|
+
const nextParts = { ...s.parts };
|
|
274
|
+
for (const message of existingMessages)
|
|
275
|
+
delete nextParts[message.id];
|
|
276
|
+
return {
|
|
277
|
+
messages: { ...s.messages, [sessionID]: [] },
|
|
278
|
+
parts: nextParts,
|
|
279
|
+
sessionStatus: { ...s.sessionStatus, [sessionID]: { type: "idle" } },
|
|
280
|
+
diffs: { ...s.diffs, [sessionID]: [] },
|
|
281
|
+
todos: { ...s.todos, [sessionID]: [] },
|
|
282
|
+
};
|
|
283
|
+
}),
|
|
284
|
+
hydrate: (sessionID, msgs) => set((s) => {
|
|
285
|
+
const cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
286
|
+
const incoming = msgs
|
|
287
|
+
.filter((m) => !!m?.info?.id)
|
|
288
|
+
.map((m) => m.info)
|
|
289
|
+
.sort((a, b) => cmp(a.id, b.id));
|
|
290
|
+
// Merge incoming messages with existing ones — never delete messages
|
|
291
|
+
// that exist in the sync store but are missing from the fetch (they may
|
|
292
|
+
// be from a newer turn that the server hasn't persisted yet).
|
|
293
|
+
const existing = s.messages[sessionID] ?? [];
|
|
294
|
+
const merged = [];
|
|
295
|
+
const seen = new Set();
|
|
296
|
+
// Check if incoming messages contain real user messages. When the
|
|
297
|
+
// server already has the user message, any optimistic (client-
|
|
298
|
+
// generated) user messages are duplicates and must be removed.
|
|
299
|
+
// Without this, hydrate() + optimistic coexist → visual double bubble.
|
|
300
|
+
const incomingHasUserMessage = incoming.some((m) => m.role === "user" && !optimisticIds.has(m.id));
|
|
301
|
+
// Start with all incoming messages
|
|
302
|
+
for (const m of incoming) {
|
|
303
|
+
merged.push(m);
|
|
304
|
+
seen.add(m.id);
|
|
305
|
+
}
|
|
306
|
+
// Add any existing messages not in incoming (optimistic or from live SSE).
|
|
307
|
+
// Optimistic messages go at the end to avoid clock-skew sorting issues;
|
|
308
|
+
// non-optimistic ones are inserted at their sorted position.
|
|
309
|
+
const deferredOptimistic = [];
|
|
310
|
+
const supersededOptimistic = [];
|
|
311
|
+
for (const m of existing) {
|
|
312
|
+
if (!seen.has(m.id)) {
|
|
313
|
+
if (optimisticIds.has(m.id)) {
|
|
314
|
+
// If the server already has a real user message, this
|
|
315
|
+
// optimistic user message is a duplicate — drop it.
|
|
316
|
+
if (incomingHasUserMessage && m.role === "user") {
|
|
317
|
+
supersededOptimistic.push(m.id);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
deferredOptimistic.push(m);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
const r = Binary.search(merged, m.id, (x) => x.id);
|
|
325
|
+
merged.splice(r.index, 0, m);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
// Clean up superseded optimistic IDs
|
|
330
|
+
for (const id of supersededOptimistic) {
|
|
331
|
+
optimisticIds.delete(id);
|
|
332
|
+
}
|
|
333
|
+
// Append surviving optimistic messages at the end
|
|
334
|
+
for (const m of deferredOptimistic) {
|
|
335
|
+
merged.push(m);
|
|
336
|
+
}
|
|
337
|
+
// Merge parts: for each message, reconcile by part ID.
|
|
338
|
+
// If a message is optimistic (still in optimisticIds), keep existing
|
|
339
|
+
// parts entirely — they're from the client and shouldn't be overwritten.
|
|
340
|
+
// Otherwise, incoming parts win (server is authoritative), but keep
|
|
341
|
+
// any extra parts from SSE that aren't in the fetch response.
|
|
342
|
+
const newParts = { ...s.parts };
|
|
343
|
+
// When superseding an optimistic user message, bridge its parts to
|
|
344
|
+
// the real user message ID if the server hasn't sent parts yet.
|
|
345
|
+
// Mirrors the message.updated SSE handler (see above) — without
|
|
346
|
+
// this, a fetch/hydrate that races ahead of parts persistence
|
|
347
|
+
// would drop the user's text and render an empty bubble.
|
|
348
|
+
const realUserMsg = incoming.find((m) => m.role === "user" && !optimisticIds.has(m.id));
|
|
349
|
+
const realUserEntry = realUserMsg
|
|
350
|
+
? msgs.find((m) => m.info.id === realUserMsg.id)
|
|
351
|
+
: undefined;
|
|
352
|
+
const serverHasRealUserParts = (realUserEntry?.parts?.length ?? 0) > 0;
|
|
353
|
+
let bridge;
|
|
354
|
+
for (const id of supersededOptimistic) {
|
|
355
|
+
if (!bridge && newParts[id]?.length)
|
|
356
|
+
bridge = newParts[id];
|
|
357
|
+
delete newParts[id];
|
|
358
|
+
}
|
|
359
|
+
if (bridge &&
|
|
360
|
+
realUserMsg &&
|
|
361
|
+
!serverHasRealUserParts &&
|
|
362
|
+
!newParts[realUserMsg.id]?.length) {
|
|
363
|
+
newParts[realUserMsg.id] = bridge;
|
|
364
|
+
bridgedPartIds.add(realUserMsg.id);
|
|
365
|
+
}
|
|
366
|
+
for (const m of msgs) {
|
|
367
|
+
if (!m?.info?.id)
|
|
368
|
+
continue;
|
|
369
|
+
const mid = m.info.id;
|
|
370
|
+
if (optimisticIds.has(mid))
|
|
371
|
+
continue; // Don't touch optimistic parts
|
|
372
|
+
const inParts = m.parts
|
|
373
|
+
.filter((p) => !!p?.id)
|
|
374
|
+
.sort((a, b) => cmp(a.id, b.id));
|
|
375
|
+
// If this message still carries bridged optimistic parts, a hydrate
|
|
376
|
+
// snapshot with real parts should replace them immediately. Otherwise
|
|
377
|
+
// reconcile-by-extras can keep both copies and duplicate user text.
|
|
378
|
+
if (bridgedPartIds.has(mid) && inParts.length > 0) {
|
|
379
|
+
bridgedPartIds.delete(mid);
|
|
380
|
+
newParts[mid] = inParts;
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const exParts = newParts[mid];
|
|
384
|
+
if (!exParts || exParts.length === 0) {
|
|
385
|
+
newParts[mid] = inParts;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
// Reconcile by key: incoming parts are generally authoritative,
|
|
389
|
+
// but for text/reasoning parts during active streaming, SSE-accumulated
|
|
390
|
+
// parts may have MORE content than the server snapshot (the
|
|
391
|
+
// server may return empty/stale text for in-progress parts).
|
|
392
|
+
// In that case, prefer the existing (SSE) version.
|
|
393
|
+
const exById = new Map(exParts.map((p) => [p.id, p]));
|
|
394
|
+
const inIds = new Set(inParts.map((p) => p.id));
|
|
395
|
+
const extras = exParts.filter((p) => !inIds.has(p.id));
|
|
396
|
+
const reconciled = inParts.map((inP) => {
|
|
397
|
+
const exP = exById.get(inP.id);
|
|
398
|
+
if (!exP)
|
|
399
|
+
return inP;
|
|
400
|
+
// For text/reasoning parts: prefer whichever has more text content.
|
|
401
|
+
// This prevents hydrate from clobbering SSE-streamed content
|
|
402
|
+
// with an empty/stale server snapshot during active streaming.
|
|
403
|
+
if (isTextLikePart(inP) &&
|
|
404
|
+
isTextLikePart(exP) &&
|
|
405
|
+
exP.text.length > inP.text.length) {
|
|
406
|
+
return exP;
|
|
407
|
+
}
|
|
408
|
+
return inP;
|
|
409
|
+
});
|
|
410
|
+
for (const ep of extras) {
|
|
411
|
+
const r = Binary.search(reconciled, ep.id, (p) => p.id);
|
|
412
|
+
if (!r.found)
|
|
413
|
+
reconciled.splice(r.index, 0, ep);
|
|
414
|
+
}
|
|
415
|
+
newParts[mid] = reconciled;
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
messages: { ...s.messages, [sessionID]: merged },
|
|
419
|
+
parts: newParts,
|
|
420
|
+
};
|
|
421
|
+
}),
|
|
422
|
+
reset: () => {
|
|
423
|
+
optimisticIds.clear();
|
|
424
|
+
bridgedPartIds.clear();
|
|
425
|
+
set({
|
|
426
|
+
messages: {},
|
|
427
|
+
parts: {},
|
|
428
|
+
sessionStatus: {},
|
|
429
|
+
diffs: {},
|
|
430
|
+
todos: {},
|
|
431
|
+
});
|
|
432
|
+
},
|
|
433
|
+
// ---- Selector: join messages + parts into MessageWithParts[] ----
|
|
434
|
+
hasOptimisticMessages: (sessionID) => {
|
|
435
|
+
const list = get().messages[sessionID];
|
|
436
|
+
if (!list || list.length === 0)
|
|
437
|
+
return false;
|
|
438
|
+
return list.some((m) => optimisticIds.has(m.id));
|
|
439
|
+
},
|
|
440
|
+
getMessages: (sessionID) => {
|
|
441
|
+
const s = get();
|
|
442
|
+
const msgs = s.messages[sessionID];
|
|
443
|
+
if (!msgs)
|
|
444
|
+
return [];
|
|
445
|
+
return msgs.map((info) => ({
|
|
446
|
+
info,
|
|
447
|
+
parts: s.parts[info.id] ?? [],
|
|
448
|
+
}));
|
|
449
|
+
},
|
|
450
|
+
// ---- Event reducer (matches SolidJS event-reducer.ts 1:1) ----
|
|
451
|
+
applyEvent: (event) => {
|
|
452
|
+
const store = get();
|
|
453
|
+
switch (event.type) {
|
|
454
|
+
case "message.updated": {
|
|
455
|
+
const info = event.properties.info;
|
|
456
|
+
if (!info?.sessionID)
|
|
457
|
+
return;
|
|
458
|
+
// When a real user message arrives from the server, swap out the
|
|
459
|
+
// optimistic message(s) in a SINGLE atomic set() call.
|
|
460
|
+
// This prevents the intermediate render where the user bubble
|
|
461
|
+
// vanishes (optimistic removed) before the real one appears.
|
|
462
|
+
if (info.role === "user" && !optimisticIds.has(info.id)) {
|
|
463
|
+
const msgs = get().messages[info.sessionID];
|
|
464
|
+
if (msgs) {
|
|
465
|
+
const optIds = msgs
|
|
466
|
+
.filter((m) => m.role === "user" && optimisticIds.has(m.id))
|
|
467
|
+
.map((m) => m.id);
|
|
468
|
+
if (optIds.length > 0) {
|
|
469
|
+
// Clean up optimistic tracking
|
|
470
|
+
for (const id of optIds)
|
|
471
|
+
optimisticIds.delete(id);
|
|
472
|
+
// Atomic: remove optimistic + insert real in one set()
|
|
473
|
+
set((s) => {
|
|
474
|
+
const list = s.messages[info.sessionID] ?? [];
|
|
475
|
+
// Remove all optimistic user messages
|
|
476
|
+
const without = list.filter((m) => !optIds.includes(m.id));
|
|
477
|
+
// Insert the real message at sorted position
|
|
478
|
+
const r = Binary.search(without, info.id, (m) => m.id);
|
|
479
|
+
const next = [...without];
|
|
480
|
+
if (r.found) {
|
|
481
|
+
next[r.index] = info;
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
next.splice(r.index, 0, info);
|
|
485
|
+
}
|
|
486
|
+
// Bridge optimistic parts to the real message ID so
|
|
487
|
+
// the user bubble never flickers empty while waiting
|
|
488
|
+
// for real parts to arrive via message.part.updated.
|
|
489
|
+
const newParts = { ...s.parts };
|
|
490
|
+
let bridge;
|
|
491
|
+
for (const id of optIds) {
|
|
492
|
+
if (!bridge && newParts[id]?.length) {
|
|
493
|
+
bridge = newParts[id];
|
|
494
|
+
}
|
|
495
|
+
delete newParts[id];
|
|
496
|
+
}
|
|
497
|
+
if (bridge && !newParts[info.id]?.length) {
|
|
498
|
+
newParts[info.id] = bridge;
|
|
499
|
+
bridgedPartIds.add(info.id);
|
|
500
|
+
}
|
|
501
|
+
return {
|
|
502
|
+
messages: { ...s.messages, [info.sessionID]: next },
|
|
503
|
+
parts: newParts,
|
|
504
|
+
};
|
|
505
|
+
});
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
store.upsertMessage(info.sessionID, info);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
case "message.removed": {
|
|
514
|
+
const props = event.properties;
|
|
515
|
+
if (!props.sessionID || !props.messageID)
|
|
516
|
+
return;
|
|
517
|
+
store.removeMessage(props.sessionID, props.messageID);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
case "message.part.updated": {
|
|
521
|
+
const part = event.properties.part;
|
|
522
|
+
if (!part?.messageID)
|
|
523
|
+
return;
|
|
524
|
+
const eventSessionID = event.properties?.sessionID;
|
|
525
|
+
let resolvedSessionID = part.sessionID ?? eventSessionID;
|
|
526
|
+
if (!resolvedSessionID) {
|
|
527
|
+
const sessionsById = get().messages;
|
|
528
|
+
for (const [sid, msgs] of Object.entries(sessionsById)) {
|
|
529
|
+
if (msgs?.some((m) => m.id === part.messageID)) {
|
|
530
|
+
resolvedSessionID = sid;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
const existingMsgs = resolvedSessionID
|
|
536
|
+
? get().messages[resolvedSessionID]
|
|
537
|
+
: undefined;
|
|
538
|
+
const bsResult = existingMsgs && Binary.search(existingMsgs, part.messageID, (m) => m.id);
|
|
539
|
+
const exists = existingMsgs && ((bsResult && bsResult.found && existingMsgs[bsResult.index]?.id === part.messageID) ||
|
|
540
|
+
existingMsgs.some((m) => m.id === part.messageID));
|
|
541
|
+
if (!exists && resolvedSessionID) {
|
|
542
|
+
store.upsertMessage(resolvedSessionID, {
|
|
543
|
+
id: part.messageID,
|
|
544
|
+
sessionID: resolvedSessionID,
|
|
545
|
+
role: "assistant",
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
store.upsertPart(part.messageID, part);
|
|
549
|
+
if (isTextLikePart(part)) {
|
|
550
|
+
if (!resolvedSessionID)
|
|
551
|
+
return;
|
|
552
|
+
const msgInfo = get().messages[resolvedSessionID]?.find((m) => m.id === part.messageID);
|
|
553
|
+
writeStreamCache(resolvedSessionID, part.messageID, part.id, part.text, msgInfo?.role === "assistant" ? msgInfo.parentID : undefined);
|
|
554
|
+
}
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
case "message.part.removed": {
|
|
558
|
+
const props = event.properties;
|
|
559
|
+
if (!props.messageID || !props.partID)
|
|
560
|
+
return;
|
|
561
|
+
store.removePart(props.messageID, props.partID);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
case "message.part.delta": {
|
|
565
|
+
const props = event.properties;
|
|
566
|
+
if (!props.messageID || !props.partID || !props.field)
|
|
567
|
+
return;
|
|
568
|
+
// Ensure the part exists before applying the delta.
|
|
569
|
+
// message.part.delta can arrive before message.part.updated
|
|
570
|
+
// (which normally creates the message + part). Without a
|
|
571
|
+
// stub part, deltas are silently dropped by applyPartDelta,
|
|
572
|
+
// causing the streamed text to never appear.
|
|
573
|
+
const partList = get().parts[props.messageID];
|
|
574
|
+
const partExists = partList && partList.some((p) => p.id === props.partID);
|
|
575
|
+
if (!partExists) {
|
|
576
|
+
// Auto-create the assistant message so the part can
|
|
577
|
+
// render, BUT only if the session already has a user
|
|
578
|
+
// message. On page refresh, hydrate() may not have
|
|
579
|
+
// completed yet — creating a stub assistant message
|
|
580
|
+
// before the user message exists causes turn grouping
|
|
581
|
+
// to attach streaming text to the wrong bubble.
|
|
582
|
+
// In that case, the part is stored as an orphan and
|
|
583
|
+
// will be picked up once hydrate() or
|
|
584
|
+
// message.part.updated creates the real message.
|
|
585
|
+
if (props.sessionID) {
|
|
586
|
+
const existingMsgs = get().messages[props.sessionID];
|
|
587
|
+
const hasUserMsg = existingMsgs?.some((m) => m.role === "user");
|
|
588
|
+
const msgExists = existingMsgs?.some((m) => m.id === props.messageID);
|
|
589
|
+
if (!msgExists && hasUserMsg) {
|
|
590
|
+
store.upsertMessage(props.sessionID, {
|
|
591
|
+
id: props.messageID,
|
|
592
|
+
sessionID: props.sessionID,
|
|
593
|
+
role: "assistant",
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
store.upsertPart(props.messageID, {
|
|
598
|
+
id: props.partID,
|
|
599
|
+
messageID: props.messageID,
|
|
600
|
+
type: "text",
|
|
601
|
+
[props.field]: "",
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
store.applyPartDelta(props.messageID, props.partID, props.field, props.delta);
|
|
605
|
+
if (props.field === "text") {
|
|
606
|
+
const updated = get().parts[props.messageID]?.find((p) => p.id === props.partID);
|
|
607
|
+
if (updated && isTextLikePart(updated) && updated.text.length > 0) {
|
|
608
|
+
const msgInfo = get().messages[props.sessionID]?.find((m) => m.id === props.messageID);
|
|
609
|
+
writeStreamCache(props.sessionID, props.messageID, props.partID, updated.text, msgInfo?.role === "assistant" ? msgInfo.parentID : undefined);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
case "session.status": {
|
|
615
|
+
const props = event.properties;
|
|
616
|
+
if (props.sessionID && props.status)
|
|
617
|
+
store.setStatus(props.sessionID, props.status);
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
case "session.idle": {
|
|
621
|
+
const sessionID = event.properties.sessionID;
|
|
622
|
+
if (sessionID)
|
|
623
|
+
store.setStatus(sessionID, { type: "idle" });
|
|
624
|
+
// Streaming finished — clear delta tracking so future
|
|
625
|
+
// message.part.updated snapshots are accepted normally.
|
|
626
|
+
deltaActiveParts.clear();
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
case "session.error": {
|
|
630
|
+
const props = event.properties;
|
|
631
|
+
if (!props.sessionID || !props.error)
|
|
632
|
+
return;
|
|
633
|
+
const sid = props.sessionID;
|
|
634
|
+
const error = props.error;
|
|
635
|
+
// Mark session idle — errors terminate the response.
|
|
636
|
+
store.setStatus(sid, { type: "idle" });
|
|
637
|
+
deltaActiveParts.clear();
|
|
638
|
+
// Patch the error onto the last assistant message in the sync store.
|
|
639
|
+
// If no assistant message exists yet, create a temporary one so the
|
|
640
|
+
// error is visible immediately. The event handler in
|
|
641
|
+
// use-opencode-events.ts will also fetch real messages from the
|
|
642
|
+
// server which will bring in the authoritative data via hydrate().
|
|
643
|
+
set((s) => {
|
|
644
|
+
const msgs = s.messages[sid] ?? [];
|
|
645
|
+
// Find last assistant message and patch .error onto it
|
|
646
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
647
|
+
const msg = msgs[i];
|
|
648
|
+
if (msg.role === "assistant") {
|
|
649
|
+
if (msg.error)
|
|
650
|
+
return s; // already has error
|
|
651
|
+
const next = [...msgs];
|
|
652
|
+
// `error` may be the client-synthesized `SyntheticAbortError`
|
|
653
|
+
// (see `MessageError`), which the SDK's own `AssistantMessage.error`
|
|
654
|
+
// union doesn't declare — the assertion is the documented, narrow
|
|
655
|
+
// exception for that one extra shape.
|
|
656
|
+
next[i] = { ...msg, error };
|
|
657
|
+
return { messages: { ...s.messages, [sid]: next } };
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
// No assistant message yet — create a stub so the error shows.
|
|
661
|
+
// Mark it as a client-side stub so hydrate can replace it.
|
|
662
|
+
const stubId = ascendingId("msg");
|
|
663
|
+
const stubMsg = {
|
|
664
|
+
id: stubId,
|
|
665
|
+
sessionID: sid,
|
|
666
|
+
role: "assistant",
|
|
667
|
+
error,
|
|
668
|
+
};
|
|
669
|
+
return {
|
|
670
|
+
messages: { ...s.messages, [sid]: [...msgs, stubMsg] },
|
|
671
|
+
};
|
|
672
|
+
});
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
case "session.diff": {
|
|
676
|
+
const props = event.properties;
|
|
677
|
+
if (props.sessionID)
|
|
678
|
+
store.setDiff(props.sessionID, props.diff);
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
case "todo.updated": {
|
|
682
|
+
const props = event.properties;
|
|
683
|
+
if (props.sessionID)
|
|
684
|
+
store.setTodo(props.sessionID, props.todos);
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
default:
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
},
|
|
691
|
+
}));
|
|
692
|
+
//# sourceMappingURL=sync-store.js.map
|