@beeuni/sdk 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -92
- package/dist/beeuni.esm.min.js +36 -34
- package/dist/beeuni.global.js +36 -34
- package/dist/browser/cache/idb-sync-cache.js +15 -5
- package/dist/browser/session-sync/server-transcript-mirror.d.ts +7 -1
- package/dist/browser/session-sync/server-transcript-mirror.js +30 -24
- package/dist/browser/session-sync/session-sync-registry.d.ts +3 -1
- package/dist/browser/session-sync/session-sync-registry.js +48 -3
- package/dist/browser/stores/sync-store/keep-unchanged.d.ts +4 -0
- package/dist/browser/stores/sync-store/keep-unchanged.js +34 -0
- package/dist/browser/stores/sync-store.d.ts +7 -0
- package/dist/browser/stores/sync-store.js +122 -35
- package/dist/core/attachments/prompt-attachments.d.ts +4 -0
- package/dist/core/attachments/prompt-attachments.js +34 -0
- package/dist/core/capture/rules.d.ts +17 -0
- package/dist/core/capture/rules.js +27 -0
- package/dist/core/client/beeuni.d.ts +99 -34
- package/dist/core/client/beeuni.js +5 -11
- package/dist/core/client/capture.d.ts +105 -0
- package/dist/core/client/capture.js +48 -0
- package/dist/core/client/facade-catalog.d.ts +0 -4
- package/dist/core/client/facade-catalog.js +1 -5
- package/dist/core/client/facade-identity.d.ts +1 -0
- package/dist/core/client/facade-identity.js +1 -0
- package/dist/core/client/project-access-resources.d.ts +3 -1
- package/dist/core/client/project-access-resources.js +1 -1
- package/dist/core/client/project-connections.d.ts +2 -2
- package/dist/core/client/project-connections.js +2 -2
- package/dist/core/client/project-operations-admin.d.ts +4 -4
- package/dist/core/client/project-operations-review.d.ts +2 -3
- package/dist/core/client/project-operations-review.js +1 -0
- package/dist/core/client/project-operations-workspace.d.ts +4 -4
- package/dist/core/client/project-operations-workspace.js +1 -1
- package/dist/core/client/project-operations.d.ts +9 -19
- package/dist/core/client/project-operations.js +2 -6
- package/dist/core/client/project-platform-security.d.ts +1 -1
- package/dist/core/client/project-platform-settings.d.ts +1 -1
- package/dist/core/client/session-context.d.ts +2 -0
- package/dist/core/client/session-handle.d.ts +13 -0
- package/dist/core/client/session-lifecycle-resources.d.ts +11 -0
- package/dist/core/client/session-lifecycle-resources.js +4 -0
- package/dist/core/client/session-lifecycle-security.d.ts +2 -0
- package/dist/core/client/session-lifecycle-security.js +1 -0
- package/dist/core/client/session-readiness.d.ts +2 -0
- package/dist/core/client/session-readiness.js +20 -1
- package/dist/core/http/api-client.d.ts +1 -7
- package/dist/core/http/api-client.js +2 -37
- package/dist/core/http/auth.d.ts +2 -4
- package/dist/core/http/auth.js +2 -8
- package/dist/core/http/config.d.ts +2 -0
- package/dist/core/http/response-error.js +26 -11
- package/dist/core/http/transport.js +6 -1
- package/dist/core/models/composer-model.d.ts +14 -0
- package/dist/core/models/composer-model.js +21 -1
- package/dist/core/rest/platform-client/capture.d.ts +363 -0
- package/dist/core/rest/platform-client/capture.js +116 -0
- package/dist/core/rest/platform-client/client-policy.d.ts +8 -0
- package/dist/core/rest/platform-client/client-policy.js +30 -0
- package/dist/core/rest/platform-client/index.d.ts +4 -4
- package/dist/core/rest/platform-client/index.js +4 -4
- package/dist/core/rest/platform-client/lifecycle.js +18 -12
- package/dist/core/rest/platform-client/shared.d.ts +5 -0
- package/dist/core/rest/platform-client/shared.js +18 -0
- package/dist/core/rest/platform-client/types.d.ts +1 -1
- package/dist/core/rest/projects-client/account-secret-resources.d.ts +2 -1
- package/dist/core/rest/projects-client/accounts.d.ts +34 -0
- package/dist/core/rest/projects-client/accounts.js +10 -0
- package/dist/core/rest/projects-client/admin-providers.d.ts +0 -61
- package/dist/core/rest/projects-client/admin-providers.js +0 -6
- package/dist/core/rest/projects-client/agent-config.d.ts +3 -0
- package/dist/core/rest/projects-client/apps-fleet.d.ts +5 -1
- package/dist/core/rest/projects-client/apps-fleet.js +2 -2
- package/dist/core/rest/projects-client/apps.d.ts +11 -1
- package/dist/core/rest/projects-client/change-requests.d.ts +2 -0
- package/dist/core/rest/projects-client/change-requests.js +2 -0
- package/dist/core/rest/projects-client/connectors.d.ts +13 -55
- package/dist/core/rest/projects-client/connectors.js +5 -29
- package/dist/core/rest/projects-client/files.d.ts +3 -0
- package/dist/core/rest/projects-client/files.js +4 -0
- package/dist/core/rest/projects-client/gateway.d.ts +5 -0
- package/dist/core/rest/projects-client/git-backend.d.ts +1 -10
- package/dist/core/rest/projects-client/git-backend.js +0 -10
- package/dist/core/rest/projects-client/iam-actions.d.ts +76 -0
- package/dist/core/rest/projects-client/iam-actions.js +101 -0
- package/dist/core/rest/projects-client/iam-sso.d.ts +0 -10
- package/dist/core/rest/projects-client/iam-sso.js +0 -3
- package/dist/core/rest/projects-client/iam.d.ts +1 -0
- package/dist/core/rest/projects-client/iam.js +1 -0
- package/dist/core/rest/projects-client/index.d.ts +1 -4
- package/dist/core/rest/projects-client/index.js +1 -4
- package/dist/core/rest/projects-client/notifications.d.ts +1 -1
- package/dist/core/rest/projects-client/notifications.js +4 -0
- package/dist/core/rest/projects-client/projects.d.ts +4 -2
- package/dist/core/rest/projects-client/projects.js +4 -2
- package/dist/core/rest/projects-client/review-items.d.ts +2 -0
- package/dist/core/rest/projects-client/review-items.js +4 -0
- package/dist/core/rest/projects-client/review.d.ts +17 -3
- package/dist/core/rest/projects-client/review.js +11 -0
- package/dist/core/rest/projects-client/sandbox.d.ts +8 -9
- package/dist/core/rest/projects-client/secrets.d.ts +3 -0
- package/dist/core/rest/projects-client/session-attachments.js +14 -1
- package/dist/core/rest/projects-client/session-sandbox.d.ts +1 -1
- package/dist/core/rest/projects-client/sessions.d.ts +31 -4
- package/dist/core/rest/projects-client/sessions.js +34 -4
- package/dist/core/runtime/runtime-rest-client.js +1 -1
- package/dist/core/runtime/runtime-types.d.ts +1 -0
- package/dist/core/session/control-stream.d.ts +1 -0
- package/dist/core/session/control-stream.js +18 -1
- package/dist/core/session/open-bundle.d.ts +4 -4
- package/dist/core/session/open-bundle.js +29 -46
- package/dist/core/session/turn-end-watch.d.ts +47 -0
- package/dist/core/session/turn-end-watch.js +141 -0
- package/dist/core/session-log/guard.d.ts +6 -0
- package/dist/core/session-log/guard.js +109 -0
- package/dist/core/session-log/index.d.ts +7 -0
- package/dist/core/session-log/index.js +5 -0
- package/dist/core/session-log/saved-log.d.ts +10 -0
- package/dist/core/session-log/saved-log.js +25 -0
- package/dist/core/session-log/source.d.ts +25 -0
- package/dist/core/session-log/source.js +30 -0
- package/dist/core/session-log/store.d.ts +21 -0
- package/dist/core/session-log/store.js +126 -0
- package/dist/core/session-log/tool-call.d.ts +11 -0
- package/dist/core/session-log/tool-call.js +65 -0
- package/dist/core/session-log/turns/blocks.d.ts +60 -0
- package/dist/core/session-log/turns/blocks.js +124 -0
- package/dist/core/session-log/turns/history.d.ts +32 -0
- package/dist/core/session-log/turns/history.js +99 -0
- package/dist/core/session-log/turns/index.d.ts +4 -0
- package/dist/core/session-log/turns/index.js +4 -0
- package/dist/core/session-log/turns/metrics.d.ts +21 -0
- package/dist/core/session-log/turns/metrics.js +29 -0
- package/dist/core/session-log/turns/turn.d.ts +55 -0
- package/dist/core/session-log/turns/turn.js +279 -0
- package/dist/core/session-log/turns/v1-parts.d.ts +8 -0
- package/dist/core/session-log/turns/v1-parts.js +43 -0
- package/dist/core/session-log/types.d.ts +264 -0
- package/dist/core/session-log/types.js +6 -0
- package/dist/core/session-log/v1-view.d.ts +13 -0
- package/dist/core/session-log/v1-view.js +215 -0
- package/dist/core/session-log/v1.d.ts +31 -0
- package/dist/core/session-log/v1.js +473 -0
- package/dist/core/session-sync/copy-store-types.d.ts +19 -0
- package/dist/core/session-sync/copy-store-types.js +1 -0
- package/dist/core/session-sync/saved-copy-store.js +25 -4
- package/dist/core/session-sync/saved-transcript.d.ts +15 -1
- package/dist/core/session-sync/saved-transcript.js +55 -0
- package/dist/core/session-sync/session-sync-controller.js +3 -0
- package/dist/core/stream/event-stream.js +2 -2
- package/dist/core/turns/classify.d.ts +2 -1
- package/dist/core/turns/classify.js +7 -3
- package/dist/core/turns/edit-blocks.d.ts +1 -0
- package/dist/core/turns/edit-blocks.js +15 -0
- package/dist/core/turns/parts.d.ts +3 -2
- package/dist/core/turns/parts.js +4 -2
- package/dist/core/turns/segments/burst-summary.d.ts +1 -0
- package/dist/core/turns/segments/burst-summary.js +24 -0
- package/dist/core/turns/segments/group-steps.d.ts +4 -3
- package/dist/core/turns/segments/group-steps.js +9 -6
- package/dist/core/turns/segments/index.d.ts +1 -0
- package/dist/core/turns/segments/index.js +1 -0
- package/dist/core/turns/segments/narration.d.ts +5 -4
- package/dist/core/turns/segments/narration.js +12 -3
- package/dist/core/turns/segments/session-activity-groups.d.ts +2 -1
- package/dist/core/turns/segments/session-activity-groups.js +3 -1
- package/dist/core/turns/segments/step-label.d.ts +2 -1
- package/dist/core/turns/segments/step-label.js +3 -1
- package/dist/core/turns/segments/work-split.d.ts +10 -0
- package/dist/core/turns/segments/work-split.js +40 -0
- package/dist/core/turns/segments/working-turn.d.ts +4 -2
- package/dist/core/turns/segments/working-turn.js +9 -8
- package/dist/core/turns/state.d.ts +2 -7
- package/dist/core/turns/state.js +28 -134
- package/dist/core/turns/tool-kind.d.ts +1 -1
- package/dist/core/turns/tool-kind.js +3 -2
- package/dist/core/turns/tool-registry.js +1 -0
- package/dist/core/turns/tools/tool-meta.d.ts +3 -2
- package/dist/core/turns/tools/tool-meta.js +5 -2
- package/dist/core/turns/tools/tool-outcome.d.ts +2 -1
- package/dist/core/turns/tools/tool-outcome.js +3 -1
- package/dist/core/turns/types.d.ts +1 -1
- package/dist/core/turns/view-model.js +1 -13
- package/dist/core/warm-session-pool.d.ts +29 -0
- package/dist/core/warm-session-pool.js +127 -0
- package/dist/genui/catalog.d.ts +28 -0
- package/dist/genui/catalog.js +396 -0
- package/dist/genui/expansion.d.ts +3 -0
- package/dist/genui/expansion.js +295 -0
- package/dist/genui/fence-entry.d.ts +2 -0
- package/dist/genui/fence-entry.js +1 -0
- package/dist/genui/fence.d.ts +21 -0
- package/dist/genui/fence.js +138 -0
- package/dist/genui/index.d.ts +6 -0
- package/dist/genui/index.js +6 -0
- package/dist/genui/markdown.d.ts +12 -0
- package/dist/genui/markdown.js +104 -0
- package/dist/genui/parse.d.ts +6 -0
- package/dist/genui/parse.js +75 -0
- package/dist/genui/prompt.d.ts +2 -0
- package/dist/genui/prompt.js +206 -0
- package/dist/genui/react/default-components.d.ts +2 -0
- package/dist/genui/react/default-components.js +72 -0
- package/dist/genui/react/default-components.test.d.ts +1 -0
- package/dist/genui/react/default-components.test.js +94 -0
- package/dist/genui/react/genui-block-disabled.test.d.ts +1 -0
- package/dist/genui/react/genui-block-disabled.test.js +50 -0
- package/dist/genui/react/genui-block.d.ts +28 -0
- package/dist/genui/react/genui-block.js +91 -0
- package/dist/genui/react/genui-block.test.d.ts +1 -0
- package/dist/genui/react/genui-block.test.js +205 -0
- package/dist/genui/react/index.d.ts +2 -0
- package/dist/genui/react/index.js +2 -0
- package/dist/genui/share.d.ts +5 -0
- package/dist/genui/share.js +30 -0
- package/dist/genui/test-fixtures.d.ts +2 -0
- package/dist/genui/test-fixtures.js +16 -0
- package/dist/genui/types.d.ts +29 -0
- package/dist/genui/types.js +1 -0
- package/dist/genui/urls.d.ts +1 -0
- package/dist/genui/urls.js +18 -0
- package/dist/genui/validate.d.ts +9 -0
- package/dist/genui/validate.js +116 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/internal/connector-catalog.d.ts +48 -0
- package/dist/internal/connector-catalog.js +27 -0
- package/dist/internal/host-configuration.d.ts +22 -0
- package/dist/internal/host-configuration.js +28 -0
- package/dist/internal/platform-admin-react.d.ts +12 -0
- package/dist/internal/platform-admin-react.js +13 -0
- package/dist/internal/platform-admin.d.ts +9 -0
- package/dist/internal/platform-admin.js +9 -0
- package/dist/platform/ui.d.ts +8 -2
- package/dist/platform/ui.js +19 -4
- package/dist/react/chat/use-chat-turns.d.ts +1 -1
- package/dist/react/human-presence.d.ts +9 -0
- package/dist/react/human-presence.js +12 -0
- package/dist/react/index.d.ts +4 -13
- package/dist/react/index.js +4 -13
- package/dist/react/opencode.d.ts +1 -0
- package/dist/react/opencode.js +1 -0
- package/dist/react/query-contracts.d.ts +6 -0
- package/dist/react/query-contracts.js +6 -0
- package/dist/react/query-keys.d.ts +17 -2
- package/dist/react/query-keys.js +24 -2
- package/dist/react/reset-identity-state.js +2 -0
- package/dist/react/session-cache-write.d.ts +1 -0
- package/dist/react/session-cache-write.js +20 -0
- package/dist/react/session-transcript-subscription.js +3 -1
- package/dist/react/sign-in-with-beeuni.d.ts +6 -6
- package/dist/react/turn-end-handoff.d.ts +13 -0
- package/dist/react/turn-end-handoff.js +101 -0
- package/dist/react/use-admin-providers.d.ts +3 -6
- package/dist/react/use-admin-providers.js +1 -11
- package/dist/react/use-capture.d.ts +47 -0
- package/dist/react/use-capture.js +173 -0
- package/dist/react/use-feature-flag.js +1 -0
- package/dist/react/use-opencode-events/handle-event.d.ts +1 -0
- package/dist/react/use-opencode-events/handle-event.js +5 -0
- package/dist/react/use-opencode-events/handle-interaction-event.js +8 -3
- package/dist/react/use-opencode-events/handle-session-event.js +13 -8
- package/dist/react/use-opencode-events/handler-context.d.ts +1 -0
- package/dist/react/use-opencode-events/helpers.d.ts +1 -0
- package/dist/react/use-opencode-events/helpers.js +11 -1
- package/dist/react/use-opencode-events/index.js +1 -0
- package/dist/react/use-opencode-local.d.ts +5 -1
- package/dist/react/use-opencode-local.js +15 -2
- package/dist/react/use-opencode-sessions/commands.d.ts +11 -1
- package/dist/react/use-opencode-sessions/commands.js +21 -1
- package/dist/react/use-opencode-sessions/permissions.js +28 -1
- package/dist/react/use-project-sessions.d.ts +1 -1
- package/dist/react/use-project-sessions.js +6 -5
- package/dist/react/use-prompt-attachments.js +1 -0
- package/dist/react/use-review-summary.d.ts +13 -0
- package/dist/react/use-review-summary.js +32 -0
- package/dist/react/use-runtime-reconnect.js +1 -1
- package/dist/react/use-session-list-state.d.ts +6 -0
- package/dist/react/use-session-list-state.js +33 -0
- package/dist/react/use-session-log.d.ts +16 -0
- package/dist/react/use-session-log.js +143 -0
- package/dist/react/use-session-messages.d.ts +2 -1
- package/dist/react/use-session-messages.js +15 -14
- package/dist/react/use-session-stream.js +12 -1
- package/dist/react/use-session-sync.d.ts +2 -2
- package/dist/react/use-session-sync.js +10 -8
- package/dist/react/use-session-transcript-history.js +2 -12
- package/dist/react/use-session-working.d.ts +2 -0
- package/dist/react/use-session-working.js +10 -0
- package/dist/react/use-session.d.ts +6 -0
- package/dist/react/use-session.js +88 -6
- package/package.json +62 -8
|
@@ -20,4 +20,5 @@ export declare function createEventHandler(deps: {
|
|
|
20
20
|
reconcileSessionTail?: (sessionID: string, reason: SessionSyncReason) => Promise<void>;
|
|
21
21
|
userPartsGraceMs?: number;
|
|
22
22
|
projectId?: string | null;
|
|
23
|
+
sessionId?: string | null;
|
|
23
24
|
}): (event: RuntimeEvent) => void;
|
|
@@ -44,6 +44,11 @@ export function createEventHandler(deps) {
|
|
|
44
44
|
const statusBeforeEvent = sessionID
|
|
45
45
|
? useSyncStore.getState().sessionStatus[sessionID]
|
|
46
46
|
: undefined;
|
|
47
|
+
if (event.type.startsWith('log.')) {
|
|
48
|
+
if (deps.sessionId)
|
|
49
|
+
useSyncStore.getState().applySessionLogEvent(deps.sessionId, event);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
47
52
|
deps.applySyncEvent(event);
|
|
48
53
|
if (event.type.startsWith('message.'))
|
|
49
54
|
handleMessageEvent(event, ctx);
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { notifyPermissionRequest, notifyQuestion } from '../../platform/ui.js';
|
|
2
|
-
import {
|
|
2
|
+
import { qk } from '../query-keys.js';
|
|
3
|
+
import { asStringOrUndefined, notificationSessionId } from './helpers.js';
|
|
3
4
|
export function handleInteractionEvent(event, ctx) {
|
|
4
5
|
const { addPermission, removePermission, addQuestion, removeQuestion, getSessionTitle } = ctx;
|
|
6
|
+
const notifiedId = (runtimeId) => notificationSessionId(ctx.queryClient, ctx.projectId, ctx.sessionId, runtimeId, true) ?? runtimeId;
|
|
7
|
+
if (event.type.startsWith('question.') && ctx.projectId) {
|
|
8
|
+
ctx.queryClient.invalidateQueries({ queryKey: qk.project.needsInput(ctx.projectId) });
|
|
9
|
+
}
|
|
5
10
|
switch (event.type) {
|
|
6
11
|
case 'permission.asked': {
|
|
7
12
|
const props = event.properties;
|
|
@@ -9,7 +14,7 @@ export function handleInteractionEvent(event, ctx) {
|
|
|
9
14
|
addPermission(props);
|
|
10
15
|
const rawProps = props;
|
|
11
16
|
const toolName = asStringOrUndefined(rawProps.tool) ?? asStringOrUndefined(rawProps.type) ?? 'a tool';
|
|
12
|
-
notifyPermissionRequest(props.sessionID, toolName, getSessionTitle(props.sessionID));
|
|
17
|
+
notifyPermissionRequest(notifiedId(props.sessionID), toolName, getSessionTitle(props.sessionID));
|
|
13
18
|
}
|
|
14
19
|
break;
|
|
15
20
|
}
|
|
@@ -24,7 +29,7 @@ export function handleInteractionEvent(event, ctx) {
|
|
|
24
29
|
if (props.id && props.sessionID) {
|
|
25
30
|
addQuestion(props);
|
|
26
31
|
const questionText = props.questions[0]?.question || props.questions[0]?.header || 'Beeuni needs your input';
|
|
27
|
-
notifyQuestion(props.sessionID, questionText, getSessionTitle(props.sessionID));
|
|
32
|
+
notifyQuestion(notifiedId(props.sessionID), questionText, getSessionTitle(props.sessionID));
|
|
28
33
|
}
|
|
29
34
|
break;
|
|
30
35
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useSyncStore } from '../../browser/stores/sync-store.js';
|
|
2
2
|
import { isAbortError } from '../../core/http/abort-error.js';
|
|
3
3
|
import { getClient } from '../../core/runtime/client.js';
|
|
4
|
+
import { extractGatewayErrorDetails, unwrapError } from '../../core/turns/errors.js';
|
|
4
5
|
import { notifySessionError, notifyTaskComplete } from '../../platform/ui.js';
|
|
5
6
|
import { runtimeKeys } from '../use-opencode-sessions/index.js';
|
|
6
|
-
import { patchBeeuniSessionTitleMirrors, readSessionInfo, realRuntimeTitle, refetchBeeuniSessionMirrors, } from './helpers.js';
|
|
7
|
+
import { notificationSessionId, patchBeeuniSessionTitleMirrors, readSessionInfo, realRuntimeTitle, refetchBeeuniSessionMirrors, } from './helpers.js';
|
|
7
8
|
export function handleSessionEvent(event, ctx, statusBeforeEvent) {
|
|
8
9
|
if (event.type === 'session.created' || event.type === 'session.updated')
|
|
9
10
|
handleSessionLifecycle(event, ctx);
|
|
@@ -146,6 +147,11 @@ function handleSessionCompaction(event, ctx) {
|
|
|
146
147
|
break;
|
|
147
148
|
}
|
|
148
149
|
}
|
|
150
|
+
function notifyTurnEnd(ctx, runtimeId, notify) {
|
|
151
|
+
const id = notificationSessionId(ctx.queryClient, ctx.projectId, ctx.sessionId, runtimeId);
|
|
152
|
+
if (id)
|
|
153
|
+
notify(id);
|
|
154
|
+
}
|
|
149
155
|
function handleSessionCompletion(event, ctx, statusBeforeEvent) {
|
|
150
156
|
const { reconcileTail, getSessionTitle, invalidateWorkspaceFilesAfterTurn } = ctx;
|
|
151
157
|
switch (event.type) {
|
|
@@ -164,7 +170,7 @@ function handleSessionCompletion(event, ctx, statusBeforeEvent) {
|
|
|
164
170
|
void reconcileTail(sessionID, 'turn-end');
|
|
165
171
|
const prevStatus = statusBeforeEvent;
|
|
166
172
|
if (status.type === 'idle' && prevStatus && prevStatus.type !== 'idle') {
|
|
167
|
-
|
|
173
|
+
notifyTurnEnd(ctx, sessionID, (id) => notifyTaskComplete(id, getSessionTitle(sessionID)));
|
|
168
174
|
invalidateWorkspaceFilesAfterTurn();
|
|
169
175
|
}
|
|
170
176
|
}
|
|
@@ -176,7 +182,7 @@ function handleSessionCompletion(event, ctx, statusBeforeEvent) {
|
|
|
176
182
|
void reconcileTail(sessionID, 'turn-end');
|
|
177
183
|
const prevStatus = statusBeforeEvent;
|
|
178
184
|
if (prevStatus && prevStatus.type !== 'idle') {
|
|
179
|
-
|
|
185
|
+
notifyTurnEnd(ctx, sessionID, (id) => notifyTaskComplete(id, getSessionTitle(sessionID)));
|
|
180
186
|
invalidateWorkspaceFilesAfterTurn();
|
|
181
187
|
}
|
|
182
188
|
}
|
|
@@ -195,11 +201,10 @@ function handleSessionFailure(event, ctx) {
|
|
|
195
201
|
const sessionID = props.sessionID;
|
|
196
202
|
const error = props.error;
|
|
197
203
|
stopCompaction(sessionID);
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
(
|
|
201
|
-
|
|
202
|
-
notifySessionError(sessionID, errorTitle, getSessionTitle(sessionID));
|
|
204
|
+
const errorTitle = extractGatewayErrorDetails(error)?.message || unwrapError(error);
|
|
205
|
+
if (!isAbortError(error)) {
|
|
206
|
+
notifyTurnEnd(ctx, sessionID, (id) => notifySessionError(id, errorTitle, getSessionTitle(sessionID)));
|
|
207
|
+
}
|
|
203
208
|
const key = runtimeKeys.runtimeMessages(sessionID);
|
|
204
209
|
queryClient.cancelQueries({ queryKey: key });
|
|
205
210
|
queryClient.setQueryData(key, (old) => {
|
|
@@ -19,6 +19,7 @@ export type HandlerContext = {
|
|
|
19
19
|
reconcileSessionTail?: (sessionID: string, reason: SessionSyncReason) => Promise<void>;
|
|
20
20
|
userPartsGraceMs?: number;
|
|
21
21
|
projectId?: string | null;
|
|
22
|
+
sessionId?: string | null;
|
|
22
23
|
} & {
|
|
23
24
|
reconcileTail: (sessionID: string, reason: import('../../core/session-sync/session-sync-controller.js').SessionSyncReason) => Promise<void>;
|
|
24
25
|
getSessionTitle: (sessionID: string) => string | undefined;
|
|
@@ -25,3 +25,4 @@ export declare function scheduleProjectMetadataRefetch(queryClient: QueryClient)
|
|
|
25
25
|
export declare function refetchBeeuniSessionMirrors(queryClient: QueryClient, projectId: string | null): void;
|
|
26
26
|
export declare function realRuntimeTitle(value: unknown): string | null;
|
|
27
27
|
export declare function patchBeeuniSessionTitleMirrors(queryClient: QueryClient, projectId: string | null, nativeSessionId: string, title: string | null): void;
|
|
28
|
+
export declare function notificationSessionId(queryClient: QueryClient, projectId: string | null | undefined, streamSessionId: string | null | undefined, runtimeId: string, subAgentAsStream?: boolean): string | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { STREAM_OBSERVATION_MAX_MS } from '../../core/session/working.js';
|
|
2
2
|
import { runtimeKeys } from '../use-opencode-sessions/index.js';
|
|
3
3
|
import { qk } from '../query-keys.js';
|
|
4
|
-
import { updateCachedProjectSessions } from '../session-cache-write.js';
|
|
4
|
+
import { findCachedProjectSession, updateCachedProjectSessions } from '../session-cache-write.js';
|
|
5
5
|
export const WIRE_STATUS_FILL_FRESHNESS_MS = STREAM_OBSERVATION_MAX_MS;
|
|
6
6
|
export function shouldSkipStatusFill(input) {
|
|
7
7
|
if (!input.hasSlot)
|
|
@@ -124,3 +124,13 @@ export function patchBeeuniSessionTitleMirrors(queryClient, projectId, nativeSes
|
|
|
124
124
|
return changed ? next : rows;
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
|
+
export function notificationSessionId(queryClient, projectId, streamSessionId, runtimeId, subAgentAsStream = false) {
|
|
128
|
+
if (!streamSessionId)
|
|
129
|
+
return runtimeId;
|
|
130
|
+
const row = projectId
|
|
131
|
+
? findCachedProjectSession(queryClient, projectId, (session) => (session.runtime_session_id ?? session.opencode_session_id) === runtimeId)
|
|
132
|
+
: undefined;
|
|
133
|
+
if (row)
|
|
134
|
+
return row.session_id;
|
|
135
|
+
return subAgentAsStream ? streamSessionId : null;
|
|
136
|
+
}
|
|
@@ -101,6 +101,7 @@ export function useRuntimeEventStream(options = {}) {
|
|
|
101
101
|
fetchLspDiagnosticsDebounced,
|
|
102
102
|
reconcileSessionTail: reconcileSessionTailFromRegistry,
|
|
103
103
|
projectId,
|
|
104
|
+
sessionId: options.projectId && options.sessionId ? options.sessionId : null,
|
|
104
105
|
});
|
|
105
106
|
const hydrate = (options) => hydrateCore({
|
|
106
107
|
client,
|
|
@@ -11,6 +11,10 @@ export interface UseRuntimeLocalOptions {
|
|
|
11
11
|
defaultAgentName?: string | null;
|
|
12
12
|
freeTier?: boolean;
|
|
13
13
|
resolveServerDefault?: (agentName: string | undefined) => ModelKey | undefined;
|
|
14
|
+
projectSession?: {
|
|
15
|
+
metadata?: Record<string, unknown> | null;
|
|
16
|
+
} | null;
|
|
17
|
+
lastPromptModel?: ModelKey;
|
|
14
18
|
}
|
|
15
19
|
export interface RuntimeLocalAgent {
|
|
16
20
|
current: Agent | undefined;
|
|
@@ -64,7 +68,7 @@ export declare function resolveCurrentAgentName(input: {
|
|
|
64
68
|
explicitAgentName?: string;
|
|
65
69
|
lastAgentName?: string;
|
|
66
70
|
}): string | undefined;
|
|
67
|
-
export declare function useRuntimeLocal({ agents: rawAgents, providers, config, sessionId, boundAgentName, defaultAgentName, resolveServerDefault, }: UseRuntimeLocalOptions): RuntimeLocal;
|
|
71
|
+
export declare function useRuntimeLocal({ agents: rawAgents, providers, config, sessionId, boundAgentName, defaultAgentName, resolveServerDefault, projectSession, lastPromptModel, }: UseRuntimeLocalOptions): RuntimeLocal;
|
|
68
72
|
export type UseOpenCodeLocalOptions = UseRuntimeLocalOptions;
|
|
69
73
|
export type OpenCodeLocalAgent = RuntimeLocalAgent;
|
|
70
74
|
export type OpenCodeLocalModel = RuntimeLocalModel;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { flattenModels, isOfferedModel } from './model-flatten.js';
|
|
3
3
|
import { composerSelectableAgents } from '../core/agents/composer-agents.js';
|
|
4
|
-
import { resolveComposerModel } from '../core/models/composer-model.js';
|
|
4
|
+
import { resolveComposerModel, sessionModelCandidates } from '../core/models/composer-model.js';
|
|
5
5
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
6
|
import { createAgentSelectionScope } from './agent-selection-scope.js';
|
|
7
7
|
import { useBeeuniRouteProjectId } from './route-project.js';
|
|
@@ -65,7 +65,7 @@ export function resolveCurrentAgentName(input) {
|
|
|
65
65
|
defaultAgentName ??
|
|
66
66
|
(input.sessionId ? undefined : input.lastAgentName));
|
|
67
67
|
}
|
|
68
|
-
export function useRuntimeLocal({ agents: rawAgents, providers, config, sessionId, boundAgentName, defaultAgentName, resolveServerDefault, }) {
|
|
68
|
+
export function useRuntimeLocal({ agents: rawAgents, providers, config, sessionId, boundAgentName, defaultAgentName, resolveServerDefault, projectSession, lastPromptModel, }) {
|
|
69
69
|
const providerMode = useMemo(() => modelProviderMode(providers), [providers]);
|
|
70
70
|
const flatModels = useMemo(() => flattenModels(providers, { providerMode }), [providers, providerMode]);
|
|
71
71
|
const projectId = useBeeuniRouteProjectId();
|
|
@@ -119,11 +119,23 @@ export function useRuntimeLocal({ agents: rawAgents, providers, config, sessionI
|
|
|
119
119
|
return visibleAgents[0];
|
|
120
120
|
}, [visibleAgents, currentAgentName]);
|
|
121
121
|
const agentModelSlotKey = useMemo(() => agentScopedModelSelectionKey(providerMode, currentAgent?.name), [providerMode, currentAgent?.name]);
|
|
122
|
+
const sessionModels = useMemo(() => sessionModelCandidates({
|
|
123
|
+
session: projectSession,
|
|
124
|
+
lastPromptModel,
|
|
125
|
+
gatewayEnabled: providerMode === 'gateway',
|
|
126
|
+
}), [
|
|
127
|
+
projectSession?.metadata?.opencode_model,
|
|
128
|
+
projectSession?.metadata?.opencode_model_source,
|
|
129
|
+
lastPromptModel?.providerID,
|
|
130
|
+
lastPromptModel?.modelID,
|
|
131
|
+
providerMode,
|
|
132
|
+
]);
|
|
122
133
|
const modelResolution = useMemo(() => resolveComposerModel({
|
|
123
134
|
models: flatModels,
|
|
124
135
|
picks: [
|
|
125
136
|
scopedSessionModelKey ? modelStore.getSessionModel(scopedSessionModelKey) : undefined,
|
|
126
137
|
sessionId ? modelStore.getSessionModel(sessionId) : undefined,
|
|
138
|
+
...sessionModels,
|
|
127
139
|
modelStore.getSelectedModel(agentModelSlotKey),
|
|
128
140
|
currentAgent ? modelStore.getSelectedModel(currentAgent.name) : undefined,
|
|
129
141
|
],
|
|
@@ -140,6 +152,7 @@ export function useRuntimeLocal({ agents: rawAgents, providers, config, sessionI
|
|
|
140
152
|
agentModelSlotKey,
|
|
141
153
|
currentAgent,
|
|
142
154
|
resolveServerDefault,
|
|
155
|
+
sessionModels,
|
|
143
156
|
config?.model,
|
|
144
157
|
providers,
|
|
145
158
|
modelStore,
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { Command } from '../../core/runtime/runtime-types.js';
|
|
2
|
-
export declare function useRuntimeCommands(): import("@tanstack/react-query").UseQueryResult<Command[], Error>;
|
|
2
|
+
export declare function useRuntimeCommands(options?: UseRuntimeCommandsOptions): import("@tanstack/react-query").UseQueryResult<Command[], Error>;
|
|
3
|
+
export interface UseRuntimeCommandsOptions {
|
|
4
|
+
agent?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class CommandNotEnabledError extends Error {
|
|
7
|
+
readonly command: string;
|
|
8
|
+
readonly agent: string;
|
|
9
|
+
readonly status = 403;
|
|
10
|
+
readonly code = "command_not_enabled";
|
|
11
|
+
constructor(command: string, agent: string);
|
|
12
|
+
}
|
|
3
13
|
export interface ExecuteRuntimeCommandInput {
|
|
4
14
|
sessionId: string;
|
|
5
15
|
command: string;
|
|
@@ -4,7 +4,8 @@ import { getClient } from '../../core/runtime/client.js';
|
|
|
4
4
|
import { useRuntimeSupports } from '../use-runtime-supports.js';
|
|
5
5
|
import { runtimeKeys, useRuntimeReady } from './keys.js';
|
|
6
6
|
import { unwrap, asRuntimeList } from './shared.js';
|
|
7
|
-
export function useRuntimeCommands() {
|
|
7
|
+
export function useRuntimeCommands(options = {}) {
|
|
8
|
+
const { agent } = options;
|
|
8
9
|
const runtimeReady = useRuntimeReady();
|
|
9
10
|
const supported = useRuntimeSupports('session.commands');
|
|
10
11
|
return useQuery({
|
|
@@ -14,11 +15,26 @@ export function useRuntimeCommands() {
|
|
|
14
15
|
const result = await client.command.list();
|
|
15
16
|
return asRuntimeList(unwrap(result));
|
|
16
17
|
},
|
|
18
|
+
select: agent
|
|
19
|
+
? (commands) => commands.filter((command) => !command.agents || command.agents.includes(agent))
|
|
20
|
+
: undefined,
|
|
17
21
|
enabled: runtimeReady && supported,
|
|
18
22
|
staleTime: Infinity,
|
|
19
23
|
gcTime: 10 * 60 * 1000,
|
|
20
24
|
});
|
|
21
25
|
}
|
|
26
|
+
export class CommandNotEnabledError extends Error {
|
|
27
|
+
command;
|
|
28
|
+
agent;
|
|
29
|
+
status = 403;
|
|
30
|
+
code = 'command_not_enabled';
|
|
31
|
+
constructor(command, agent) {
|
|
32
|
+
super(`The agent "${agent}" cannot run /${command}.`);
|
|
33
|
+
this.command = command;
|
|
34
|
+
this.agent = agent;
|
|
35
|
+
this.name = 'CommandNotEnabledError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
22
38
|
export async function executeRuntimeCommand({ sessionId, command, args, agent, model, variant, }) {
|
|
23
39
|
const client = getClient();
|
|
24
40
|
const result = await client.session.command({
|
|
@@ -29,6 +45,10 @@ export async function executeRuntimeCommand({ sessionId, command, args, agent, m
|
|
|
29
45
|
...(model ? { model } : {}),
|
|
30
46
|
...(variant ? { variant } : {}),
|
|
31
47
|
});
|
|
48
|
+
const body = result.error;
|
|
49
|
+
if (result.response?.status === 403 && body?.error === 'command_not_enabled') {
|
|
50
|
+
throw new CommandNotEnabledError(String(body.command ?? command), String(body.agent ?? agent ?? ''));
|
|
51
|
+
}
|
|
32
52
|
unwrap(result);
|
|
33
53
|
}
|
|
34
54
|
export function useExecuteRuntimeCommand() {
|
|
@@ -1,10 +1,37 @@
|
|
|
1
1
|
import { getClient } from '../../core/runtime/client.js';
|
|
2
2
|
import { unwrap } from './shared.js';
|
|
3
|
-
|
|
3
|
+
const repliesInFlight = new Map();
|
|
4
|
+
function permissionAlreadyAnswered(result) {
|
|
5
|
+
if (result.response?.status !== 404)
|
|
6
|
+
return false;
|
|
7
|
+
const err = result.error;
|
|
8
|
+
if (typeof err === 'string') {
|
|
9
|
+
return err.toLowerCase().includes('permission request not found');
|
|
10
|
+
}
|
|
11
|
+
if (!err || typeof err !== 'object')
|
|
12
|
+
return false;
|
|
13
|
+
const rec = err;
|
|
14
|
+
const data = rec.data && typeof rec.data === 'object' ? rec.data : undefined;
|
|
15
|
+
const message = data?.message ?? rec.message ?? rec.error ?? '';
|
|
16
|
+
return String(message).toLowerCase().includes('permission request not found');
|
|
17
|
+
}
|
|
18
|
+
async function sendPermissionReply(requestId, reply, message) {
|
|
4
19
|
const client = getClient();
|
|
5
20
|
const result = await client.permission.reply({ requestID: requestId, reply, message });
|
|
21
|
+
if (permissionAlreadyAnswered(result))
|
|
22
|
+
return;
|
|
6
23
|
unwrap(result);
|
|
7
24
|
}
|
|
25
|
+
export async function replyToPermission(requestId, reply, message) {
|
|
26
|
+
const inFlight = repliesInFlight.get(requestId);
|
|
27
|
+
if (inFlight)
|
|
28
|
+
return inFlight;
|
|
29
|
+
const send = sendPermissionReply(requestId, reply, message).finally(() => {
|
|
30
|
+
repliesInFlight.delete(requestId);
|
|
31
|
+
});
|
|
32
|
+
repliesInFlight.set(requestId, send);
|
|
33
|
+
return send;
|
|
34
|
+
}
|
|
8
35
|
const KNOWN_PERMISSION_TYPES = [
|
|
9
36
|
'bash',
|
|
10
37
|
'edit',
|
|
@@ -9,7 +9,7 @@ export declare function shouldScanPastEmptySessionPages(data: {
|
|
|
9
9
|
pages: ProjectSessionPage[];
|
|
10
10
|
pageParams: unknown[];
|
|
11
11
|
} | undefined, hasNextPage: boolean): boolean;
|
|
12
|
-
export interface UseProjectSessionsOptions extends Pick<ListProjectSessionsOptions, 'scope' | 'limit' | 'parent' | 'startedBy' | 'q' | 'labels'> {
|
|
12
|
+
export interface UseProjectSessionsOptions extends Pick<ListProjectSessionsOptions, 'scope' | 'limit' | 'parent' | 'startedBy' | 'q' | 'labels' | 'view'> {
|
|
13
13
|
enabled?: boolean;
|
|
14
14
|
refetchInterval?: number | false | ((sessions: ProjectSession[]) => number | false);
|
|
15
15
|
refetchOnWindowFocus?: boolean;
|
|
@@ -31,9 +31,9 @@ export function shouldScanPastEmptySessionPages(data, hasNextPage) {
|
|
|
31
31
|
}
|
|
32
32
|
export function useProjectSessions(projectId, options) {
|
|
33
33
|
const scope = options?.scope ?? 'visible';
|
|
34
|
-
const { parent, startedBy, q, labels } = options ?? {};
|
|
34
|
+
const { parent, startedBy, q, labels, view } = options ?? {};
|
|
35
35
|
const query = useInfiniteQuery({
|
|
36
|
-
queryKey: qk.project.sessionsPaged(projectId, scope, { parent, startedBy, q, labels }),
|
|
36
|
+
queryKey: qk.project.sessionsPaged(projectId, scope, { parent, startedBy, q, labels, view }),
|
|
37
37
|
initialPageParam: null,
|
|
38
38
|
queryFn: ({ pageParam }) => listProjectSessionsPage(projectId, {
|
|
39
39
|
scope,
|
|
@@ -43,6 +43,7 @@ export function useProjectSessions(projectId, options) {
|
|
|
43
43
|
startedBy,
|
|
44
44
|
q,
|
|
45
45
|
labels,
|
|
46
|
+
view,
|
|
46
47
|
}),
|
|
47
48
|
getNextPageParam: projectSessionsPageParam,
|
|
48
49
|
enabled: options?.enabled ?? true,
|
|
@@ -55,12 +56,12 @@ export function useProjectSessions(projectId, options) {
|
|
|
55
56
|
return interval(flattenProjectSessionPages(query.state.data));
|
|
56
57
|
},
|
|
57
58
|
});
|
|
58
|
-
const isScanning = shouldScanPastEmptySessionPages(query.data, query.hasNextPage);
|
|
59
|
-
const { isFetching, fetchNextPage } = query;
|
|
59
|
+
const isScanning = shouldScanPastEmptySessionPages(query.data, query.hasNextPage) && !query.isError;
|
|
60
|
+
const { isFetching, data, dataUpdatedAt, fetchNextPage } = query;
|
|
60
61
|
useEffect(() => {
|
|
61
62
|
if (isScanning && !isFetching)
|
|
62
63
|
void fetchNextPage();
|
|
63
|
-
}, [isScanning, isFetching, fetchNextPage]);
|
|
64
|
+
}, [isScanning, isFetching, data, dataUpdatedAt, fetchNextPage]);
|
|
64
65
|
return {
|
|
65
66
|
...query,
|
|
66
67
|
isScanning,
|
|
@@ -22,6 +22,7 @@ export function usePromptAttachments(projectId, options = {}) {
|
|
|
22
22
|
return useMemo(() => ({
|
|
23
23
|
add: controller.add,
|
|
24
24
|
addMany: controller.addMany,
|
|
25
|
+
restore: controller.restore,
|
|
25
26
|
retry: controller.retry,
|
|
26
27
|
remove: controller.remove,
|
|
27
28
|
abort: controller.abort,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ApiReviewItem, type ReviewItemsPage, type ReviewItemsQuery } from '../core/rest/projects-client/index.js';
|
|
2
|
+
export declare function useReviewSummary(projectId: string, options?: {
|
|
3
|
+
enabled?: boolean;
|
|
4
|
+
refetchInterval?: number | false;
|
|
5
|
+
}): import("@tanstack/react-query").UseQueryResult<import("../index.js").ReviewSummary, Error>;
|
|
6
|
+
export declare function nextReviewItemsCursor(page: ReviewItemsPage): string | undefined;
|
|
7
|
+
export declare function reviewItemsOf(data: {
|
|
8
|
+
pages: ReadonlyArray<Pick<ReviewItemsPage, 'review_items'>>;
|
|
9
|
+
} | undefined): ApiReviewItem[];
|
|
10
|
+
export declare function useReviewItemPages(projectId: string, query?: ReviewItemsQuery, options?: {
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
refetchInterval?: number | false;
|
|
13
|
+
}): import("@tanstack/react-query").UseInfiniteQueryResult<import("@tanstack/react-query").InfiniteData<ReviewItemsPage, unknown>, Error>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
|
|
3
|
+
import { getReviewSummary, listReviewItems, } from '../core/rest/projects-client/index.js';
|
|
4
|
+
import { qk } from './query-keys.js';
|
|
5
|
+
export function useReviewSummary(projectId, options) {
|
|
6
|
+
const enabled = Boolean(projectId) && options?.enabled !== false;
|
|
7
|
+
return useQuery({
|
|
8
|
+
queryKey: qk.project.reviewSummary(projectId),
|
|
9
|
+
queryFn: () => getReviewSummary(projectId),
|
|
10
|
+
enabled,
|
|
11
|
+
staleTime: 5_000,
|
|
12
|
+
refetchInterval: enabled ? (options?.refetchInterval ?? 60_000) : false,
|
|
13
|
+
refetchOnWindowFocus: false,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function nextReviewItemsCursor(page) {
|
|
17
|
+
return page.next_cursor ?? undefined;
|
|
18
|
+
}
|
|
19
|
+
export function reviewItemsOf(data) {
|
|
20
|
+
return data?.pages.flatMap((page) => page.review_items) ?? [];
|
|
21
|
+
}
|
|
22
|
+
export function useReviewItemPages(projectId, query = {}, options) {
|
|
23
|
+
return useInfiniteQuery({
|
|
24
|
+
queryKey: qk.project.reviewItemPages(projectId, query),
|
|
25
|
+
queryFn: ({ pageParam }) => listReviewItems(projectId, { ...query, cursor: pageParam }),
|
|
26
|
+
initialPageParam: undefined,
|
|
27
|
+
getNextPageParam: nextReviewItemsCursor,
|
|
28
|
+
enabled: Boolean(projectId) && options?.enabled !== false,
|
|
29
|
+
staleTime: 5_000,
|
|
30
|
+
refetchInterval: options?.refetchInterval ?? false,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useEffect, useRef } from 'react';
|
|
3
|
-
import { getSupabaseAccessToken } from '../core/http/auth.js';
|
|
3
|
+
import { getAuthToken as getSupabaseAccessToken } from '../core/http/auth.js';
|
|
4
4
|
import { CONNECTION_FAULT_GRACE_MS, getSessionHealth, isRuntimeReady, } from '../core/session/index.js';
|
|
5
5
|
import { incrementSandboxFail, markInitialCheckDone, resetForServerSwitch, resetSandboxFail, setRuntimeHealth, setRuntimeCapabilities, setSandboxStatus, useSandboxConnectionStore, } from '../browser/stores/sandbox-connection-store.js';
|
|
6
6
|
import { useServerStore } from '../browser/stores/server-store.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type SessionListState } from '../core/rest/projects-client/sessions.js';
|
|
2
|
+
export declare function useSessionListState(projectId: string): {
|
|
3
|
+
isPending: boolean;
|
|
4
|
+
setPinned: (sessionId: string, pinned: boolean) => Promise<SessionListState>;
|
|
5
|
+
setArchived: (sessionId: string, archived: boolean) => Promise<SessionListState>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { setSessionArchived, setSessionPinned, } from '../core/rest/projects-client/sessions.js';
|
|
5
|
+
import { qk } from './query-keys.js';
|
|
6
|
+
import { updateCachedProjectSessions } from './session-cache-write.js';
|
|
7
|
+
function changedState(session, change, now) {
|
|
8
|
+
if ('pinned' in change) {
|
|
9
|
+
return { pinned_at: change.pinned ? (session.pinned_at ?? now) : null, archived_at: change.pinned ? null : (session.archived_at ?? null) };
|
|
10
|
+
}
|
|
11
|
+
return { archived_at: change.archived ? (session.archived_at ?? now) : null, pinned_at: change.archived ? null : (session.pinned_at ?? null) };
|
|
12
|
+
}
|
|
13
|
+
export function useSessionListState(projectId) {
|
|
14
|
+
const client = useQueryClient();
|
|
15
|
+
const write = (sessionId, state) => updateCachedProjectSessions(client, projectId, (sessions) => sessions.map((session) => (session.session_id === sessionId ? { ...session, ...state(session) } : session)));
|
|
16
|
+
const mutation = useMutation({
|
|
17
|
+
mutationFn: ({ sessionId, change }) => 'pinned' in change
|
|
18
|
+
? setSessionPinned(projectId, sessionId, change.pinned)
|
|
19
|
+
: setSessionArchived(projectId, sessionId, change.archived),
|
|
20
|
+
onMutate: ({ sessionId, change }) => {
|
|
21
|
+
const now = new Date().toISOString();
|
|
22
|
+
write(sessionId, (session) => changedState(session, change, now));
|
|
23
|
+
},
|
|
24
|
+
onSuccess: (state, { sessionId }) => write(sessionId, () => state),
|
|
25
|
+
onSettled: () => client.invalidateQueries({ queryKey: [...qk.project.sessionsScope(projectId), 'list-paged'] }),
|
|
26
|
+
});
|
|
27
|
+
const { mutateAsync, isPending } = mutation;
|
|
28
|
+
const actions = useMemo(() => ({
|
|
29
|
+
setPinned: (sessionId, pinned) => mutateAsync({ sessionId, change: { pinned } }),
|
|
30
|
+
setArchived: (sessionId, archived) => mutateAsync({ sessionId, change: { archived } }),
|
|
31
|
+
}), [mutateAsync]);
|
|
32
|
+
return { ...actions, isPending };
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type SessionControlStreamOptions } from '../core/session/control-stream.js';
|
|
2
|
+
import { type LoadSessionLogPage, type SessionLogDialect } from '../core/session-log/source.js';
|
|
3
|
+
import type { SessionLog, SessionLogThread } from '../core/session-log/types.js';
|
|
4
|
+
import { type SessionMessagesOptions, type SessionMessagesSource } from './use-session-messages.js';
|
|
5
|
+
export declare function useSessionLog(session: SessionMessagesSource): (SessionLog & {
|
|
6
|
+
source: 'v1' | 'v2';
|
|
7
|
+
}) | null;
|
|
8
|
+
export declare function useSessionLogRecord(session: Pick<SessionMessagesSource, 'sessionId'>): Partial<Omit<SessionLog, 'threads'>> | null;
|
|
9
|
+
export declare function useSessionLogThread(session: SessionMessagesSource, threadId?: string | null, options?: SessionMessagesOptions): SessionLogThread | null;
|
|
10
|
+
export declare function useSessionLogSync(projectId: string, sessionId: string, options: {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
loader?: LoadSessionLogPage | null;
|
|
13
|
+
joinStream?: (options: SessionControlStreamOptions) => {
|
|
14
|
+
close: () => void;
|
|
15
|
+
};
|
|
16
|
+
}): SessionLogDialect;
|