@pasko70/pibo 3.2.7 → 3.4.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/dist/agent-runtime/capabilities.js +5 -0
- package/dist/agent-runtime/contract.js +2 -0
- package/dist/agent-runtime/routed-session.js +68 -11
- package/dist/agent-runtimes/codex-native/adapter.js +4 -1
- package/dist/agent-runtimes/codex-native/process.js +1 -1
- package/dist/agent-runtimes/codex-native/protocol-version.js +6 -6
- package/dist/agent-runtimes/codex-native/thread.js +26 -4
- package/dist/agent-runtimes/omp/adapter.js +1 -0
- package/dist/agent-runtimes/omp/process.js +23 -3
- package/dist/agent-runtimes/omp/protocol-version.js +2 -0
- package/dist/agent-runtimes/pi/adapter.js +5 -1
- package/dist/agent-runtimes/pi/model-catalog.js +2 -2
- package/dist/agent-runtimes/pi/routed-session.js +53 -5
- package/dist/agent-runtimes/pi/runtime.js +6 -3
- package/dist/apps/chat/chat-api-routes.js +12 -38
- package/dist/apps/chat/chat-request-normalizers.js +15 -50
- package/dist/apps/chat/data/legacy-project-migration.js +492 -0
- package/dist/apps/chat/data/room-service.js +2 -2
- package/dist/apps/chat/data/workflow-session-model.js +1 -0
- package/dist/apps/chat/data/workflow-session-service.js +352 -0
- package/dist/apps/chat/rooms.js +1 -1
- package/dist/apps/chat/session-metadata.js +30 -0
- package/dist/apps/chat/trace.js +15 -2
- package/dist/apps/chat/types/rooms.js +30 -0
- package/dist/apps/chat/web-app.js +355 -651
- package/dist/apps/chat/workflow-catalog.js +18 -18
- package/dist/apps/chat/{project-workflow-human-actions.js → workflow-human-actions.js} +14 -14
- package/dist/apps/chat/workflow-manual-trigger-runtime.js +5 -1
- package/dist/apps/chat/workflow-persistence.js +20 -28
- package/dist/apps/chat/{project-workflow-sessions.js → workflow-sessions.js} +18 -17
- package/dist/apps/chat-ui/assets/{dist-ENXYFYda.js → dist-AhtdAETR.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CGgUuVB6.js → dist-Bk_L1qbJ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DG6T1maU.js → dist-Dyp6sLQn.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CFtZTGHa.js → dist-jVaiGXFD.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BikaGikn.js → dist-t25moyJS.js} +1 -1
- package/dist/apps/chat-ui/assets/index-CZjNw-aK.js +228 -0
- package/dist/apps/chat-ui/assets/index-CcEjFITM.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-Spj6M0tn.js +43 -0
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/compute/pool/cli.js +1 -1
- package/dist/compute/pool/seeds.js +2 -3
- package/dist/config/config.js +1 -1
- package/dist/core/session-router.js +19 -10
- package/dist/debug/agents.js +9 -3
- package/dist/plugins/builtin.js +2 -0
- package/dist/plugins/registry.js +1 -0
- package/dist/previews/cli.js +154 -79
- package/dist/previews/compute-worker.js +37 -0
- package/dist/previews/config.js +2 -1
- package/dist/previews/migrations/session-ownership.js +7 -0
- package/dist/previews/proxy.js +4 -2
- package/dist/previews/public-setup.js +108 -0
- package/dist/previews/store.js +20 -13
- package/dist/previews/web-app.js +12 -2
- package/dist/providers/openai-gpt56.js +41 -3
- package/dist/sessions/workflow-session-kind.js +0 -3
- package/dist/subagents/context.js +2 -2
- package/dist/subagents/observation-query.js +49 -6
- package/dist/subagents/observation-text-regex.js +124 -0
- package/dist/subagents/tool.js +3 -2
- package/dist/tools/hashline.js +64 -0
- package/npm-shrinkwrap.json +786 -284
- package/package.json +11 -6
- package/packages/workflows/README.md +21 -0
- package/packages/workflows/dist/api/index.d.ts +48 -0
- package/packages/workflows/dist/api/index.d.ts.map +1 -0
- package/packages/workflows/dist/api/index.js +96 -0
- package/packages/workflows/dist/api/index.js.map +1 -0
- package/packages/workflows/dist/definition-hash.d.ts +4 -0
- package/packages/workflows/dist/definition-hash.d.ts.map +1 -0
- package/packages/workflows/dist/definition-hash.js +27 -0
- package/packages/workflows/dist/definition-hash.js.map +1 -0
- package/packages/workflows/dist/fixtures/index.d.ts +39 -0
- package/packages/workflows/dist/fixtures/index.d.ts.map +1 -0
- package/packages/workflows/dist/fixtures/index.js +608 -0
- package/packages/workflows/dist/fixtures/index.js.map +1 -0
- package/packages/workflows/dist/index.d.ts +16 -0
- package/packages/workflows/dist/index.d.ts.map +1 -0
- package/packages/workflows/dist/index.js +10 -0
- package/packages/workflows/dist/index.js.map +1 -0
- package/packages/workflows/dist/inspection/index.d.ts +47 -0
- package/packages/workflows/dist/inspection/index.d.ts.map +1 -0
- package/packages/workflows/dist/inspection/index.js +131 -0
- package/packages/workflows/dist/inspection/index.js.map +1 -0
- package/packages/workflows/dist/registry/index.d.ts +30 -0
- package/packages/workflows/dist/registry/index.d.ts.map +1 -0
- package/packages/workflows/dist/registry/index.js +161 -0
- package/packages/workflows/dist/registry/index.js.map +1 -0
- package/packages/workflows/dist/runtime/adapter-node.d.ts +28 -0
- package/packages/workflows/dist/runtime/adapter-node.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/adapter-node.js +172 -0
- package/packages/workflows/dist/runtime/adapter-node.js.map +1 -0
- package/packages/workflows/dist/runtime/agent-node.d.ts +32 -0
- package/packages/workflows/dist/runtime/agent-node.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/agent-node.js +231 -0
- package/packages/workflows/dist/runtime/agent-node.js.map +1 -0
- package/packages/workflows/dist/runtime/agent-runtime.d.ts +25 -0
- package/packages/workflows/dist/runtime/agent-runtime.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/agent-runtime.js +111 -0
- package/packages/workflows/dist/runtime/agent-runtime.js.map +1 -0
- package/packages/workflows/dist/runtime/code-node.d.ts +31 -0
- package/packages/workflows/dist/runtime/code-node.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/code-node.js +223 -0
- package/packages/workflows/dist/runtime/code-node.js.map +1 -0
- package/packages/workflows/dist/runtime/dispatch-failures.d.ts +36 -0
- package/packages/workflows/dist/runtime/dispatch-failures.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/dispatch-failures.js +80 -0
- package/packages/workflows/dist/runtime/dispatch-failures.js.map +1 -0
- package/packages/workflows/dist/runtime/edge-payloads.d.ts +3 -0
- package/packages/workflows/dist/runtime/edge-payloads.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/edge-payloads.js +11 -0
- package/packages/workflows/dist/runtime/edge-payloads.js.map +1 -0
- package/packages/workflows/dist/runtime/edge-transfer.d.ts +39 -0
- package/packages/workflows/dist/runtime/edge-transfer.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/edge-transfer.js +356 -0
- package/packages/workflows/dist/runtime/edge-transfer.js.map +1 -0
- package/packages/workflows/dist/runtime/human-action.d.ts +43 -0
- package/packages/workflows/dist/runtime/human-action.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/human-action.js +231 -0
- package/packages/workflows/dist/runtime/human-action.js.map +1 -0
- package/packages/workflows/dist/runtime/human-node.d.ts +27 -0
- package/packages/workflows/dist/runtime/human-node.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/human-node.js +126 -0
- package/packages/workflows/dist/runtime/human-node.js.map +1 -0
- package/packages/workflows/dist/runtime/ids.d.ts +2 -0
- package/packages/workflows/dist/runtime/ids.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/ids.js +4 -0
- package/packages/workflows/dist/runtime/ids.js.map +1 -0
- package/packages/workflows/dist/runtime/index.d.ts +23 -0
- package/packages/workflows/dist/runtime/index.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/index.js +12 -0
- package/packages/workflows/dist/runtime/index.js.map +1 -0
- package/packages/workflows/dist/runtime/manual-trigger.d.ts +51 -0
- package/packages/workflows/dist/runtime/manual-trigger.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/manual-trigger.js +403 -0
- package/packages/workflows/dist/runtime/manual-trigger.js.map +1 -0
- package/packages/workflows/dist/runtime/nested-workflow-node.d.ts +48 -0
- package/packages/workflows/dist/runtime/nested-workflow-node.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/nested-workflow-node.js +246 -0
- package/packages/workflows/dist/runtime/nested-workflow-node.js.map +1 -0
- package/packages/workflows/dist/runtime/one-node-agent.d.ts +34 -0
- package/packages/workflows/dist/runtime/one-node-agent.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/one-node-agent.js +334 -0
- package/packages/workflows/dist/runtime/one-node-agent.js.map +1 -0
- package/packages/workflows/dist/runtime/persistence.d.ts +9 -0
- package/packages/workflows/dist/runtime/persistence.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/persistence.js +67 -0
- package/packages/workflows/dist/runtime/persistence.js.map +1 -0
- package/packages/workflows/dist/runtime/pibo-routing.d.ts +126 -0
- package/packages/workflows/dist/runtime/pibo-routing.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/pibo-routing.js +96 -0
- package/packages/workflows/dist/runtime/pibo-routing.js.map +1 -0
- package/packages/workflows/dist/runtime/prompts.d.ts +20 -0
- package/packages/workflows/dist/runtime/prompts.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/prompts.js +235 -0
- package/packages/workflows/dist/runtime/prompts.js.map +1 -0
- package/packages/workflows/dist/runtime/retry.d.ts +35 -0
- package/packages/workflows/dist/runtime/retry.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/retry.js +80 -0
- package/packages/workflows/dist/runtime/retry.js.map +1 -0
- package/packages/workflows/dist/runtime/state.d.ts +14 -0
- package/packages/workflows/dist/runtime/state.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/state.js +139 -0
- package/packages/workflows/dist/runtime/state.js.map +1 -0
- package/packages/workflows/dist/runtime/time.d.ts +6 -0
- package/packages/workflows/dist/runtime/time.d.ts.map +1 -0
- package/packages/workflows/dist/runtime/time.js +42 -0
- package/packages/workflows/dist/runtime/time.js.map +1 -0
- package/packages/workflows/dist/store/catalog-records.d.ts +18 -0
- package/packages/workflows/dist/store/catalog-records.d.ts.map +1 -0
- package/packages/workflows/dist/store/catalog-records.js +59 -0
- package/packages/workflows/dist/store/catalog-records.js.map +1 -0
- package/packages/workflows/dist/store/contracts.d.ts +149 -0
- package/packages/workflows/dist/store/contracts.d.ts.map +1 -0
- package/packages/workflows/dist/store/contracts.js +2 -0
- package/packages/workflows/dist/store/contracts.js.map +1 -0
- package/packages/workflows/dist/store/draft-writes.d.ts +7 -0
- package/packages/workflows/dist/store/draft-writes.d.ts.map +1 -0
- package/packages/workflows/dist/store/draft-writes.js +18 -0
- package/packages/workflows/dist/store/draft-writes.js.map +1 -0
- package/packages/workflows/dist/store/index.d.ts +55 -0
- package/packages/workflows/dist/store/index.d.ts.map +1 -0
- package/packages/workflows/dist/store/index.js +650 -0
- package/packages/workflows/dist/store/index.js.map +1 -0
- package/packages/workflows/dist/store/list-query.d.ts +13 -0
- package/packages/workflows/dist/store/list-query.d.ts.map +1 -0
- package/packages/workflows/dist/store/list-query.js +20 -0
- package/packages/workflows/dist/store/list-query.js.map +1 -0
- package/packages/workflows/dist/store/row-mappers.d.ts +206 -0
- package/packages/workflows/dist/store/row-mappers.d.ts.map +1 -0
- package/packages/workflows/dist/store/row-mappers.js +262 -0
- package/packages/workflows/dist/store/row-mappers.js.map +1 -0
- package/packages/workflows/dist/store/schema.d.ts +13 -0
- package/packages/workflows/dist/store/schema.d.ts.map +1 -0
- package/packages/workflows/dist/store/schema.js +458 -0
- package/packages/workflows/dist/store/schema.js.map +1 -0
- package/packages/workflows/dist/store/write-values.d.ts +18 -0
- package/packages/workflows/dist/store/write-values.d.ts.map +1 -0
- package/packages/workflows/dist/store/write-values.js +227 -0
- package/packages/workflows/dist/store/write-values.js.map +1 -0
- package/packages/workflows/dist/types/index.d.ts +1202 -0
- package/packages/workflows/dist/types/index.d.ts.map +1 -0
- package/packages/workflows/dist/types/index.js +8 -0
- package/packages/workflows/dist/types/index.js.map +1 -0
- package/packages/workflows/dist/validation/diagnostics.d.ts +27 -0
- package/packages/workflows/dist/validation/diagnostics.d.ts.map +1 -0
- package/packages/workflows/dist/validation/diagnostics.js +104 -0
- package/packages/workflows/dist/validation/diagnostics.js.map +1 -0
- package/packages/workflows/dist/validation/graph-cycles.d.ts +4 -0
- package/packages/workflows/dist/validation/graph-cycles.d.ts.map +1 -0
- package/packages/workflows/dist/validation/graph-cycles.js +130 -0
- package/packages/workflows/dist/validation/graph-cycles.js.map +1 -0
- package/packages/workflows/dist/validation/graph-edges.d.ts +5 -0
- package/packages/workflows/dist/validation/graph-edges.d.ts.map +1 -0
- package/packages/workflows/dist/validation/graph-edges.js +48 -0
- package/packages/workflows/dist/validation/graph-edges.js.map +1 -0
- package/packages/workflows/dist/validation/graph-ports.d.ts +5 -0
- package/packages/workflows/dist/validation/graph-ports.d.ts.map +1 -0
- package/packages/workflows/dist/validation/graph-ports.js +55 -0
- package/packages/workflows/dist/validation/graph-ports.js.map +1 -0
- package/packages/workflows/dist/validation/index.d.ts +18 -0
- package/packages/workflows/dist/validation/index.d.ts.map +1 -0
- package/packages/workflows/dist/validation/index.js +175 -0
- package/packages/workflows/dist/validation/index.js.map +1 -0
- package/packages/workflows/dist/validation/json-schema.d.ts +12 -0
- package/packages/workflows/dist/validation/json-schema.d.ts.map +1 -0
- package/packages/workflows/dist/validation/json-schema.js +556 -0
- package/packages/workflows/dist/validation/json-schema.js.map +1 -0
- package/packages/workflows/dist/validation/registry-refs.d.ts +21 -0
- package/packages/workflows/dist/validation/registry-refs.d.ts.map +1 -0
- package/packages/workflows/dist/validation/registry-refs.js +283 -0
- package/packages/workflows/dist/validation/registry-refs.js.map +1 -0
- package/packages/workflows/dist/validation/retry-policy.d.ts +3 -0
- package/packages/workflows/dist/validation/retry-policy.d.ts.map +1 -0
- package/packages/workflows/dist/validation/retry-policy.js +114 -0
- package/packages/workflows/dist/validation/retry-policy.js.map +1 -0
- package/packages/workflows/dist/validation/schema-declarations.d.ts +5 -0
- package/packages/workflows/dist/validation/schema-declarations.d.ts.map +1 -0
- package/packages/workflows/dist/validation/schema-declarations.js +36 -0
- package/packages/workflows/dist/validation/schema-declarations.js.map +1 -0
- package/packages/workflows/dist/validation/state-access.d.ts +4 -0
- package/packages/workflows/dist/validation/state-access.d.ts.map +1 -0
- package/packages/workflows/dist/validation/state-access.js +121 -0
- package/packages/workflows/dist/validation/state-access.js.map +1 -0
- package/packages/workflows/dist/xstate/index.d.ts +73 -0
- package/packages/workflows/dist/xstate/index.d.ts.map +1 -0
- package/packages/workflows/dist/xstate/index.js +728 -0
- package/packages/workflows/dist/xstate/index.js.map +1 -0
- package/packages/workflows/package.json +23 -0
- package/dist/apps/chat/data/project-service.js +0 -1029
- package/dist/apps/chat-ui/assets/index-BwT5grLv.css +0 -1
- package/dist/apps/chat-ui/assets/index-PTJanD3E.js +0 -228
- package/dist/apps/chat-vscode-web/assets/index-D1bpAUkR.js +0 -43
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import os from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
3
4
|
import { monitorEventLoopDelay } from "node:perf_hooks";
|
|
4
5
|
import { PiboSteeringUnavailableError } from "../../core/events.js";
|
|
5
6
|
import { OutputRenderSequencer, validRenderSequence } from "../../core/output-render-sequence.js";
|
|
@@ -12,12 +13,12 @@ import { summarizeSessionSignalStatus } from "../../signals/status.js";
|
|
|
12
13
|
import { PiboWebHttpError, readJsonBody, responseJson } from "../../web/http.js";
|
|
13
14
|
import { OutputCompactor } from "./output-compactor.js";
|
|
14
15
|
import { isLiveOnlyOutputEvent, isPersistableOutputEvent, isPiboOutputEvent } from "./output-event-policy.js";
|
|
15
|
-
import { chatRoomIdFromMetadata, isDefaultPiboRoom, isPiboRoomArchived, roomWorkspaceFromMetadata, withChatRoomId, withPiboRoomWorkspace, } from "./types/rooms.js";
|
|
16
|
+
import { chatRoomIdFromMetadata, comparePiboRoomsBySidebarOrder, isDefaultPiboRoom, isPiboRoomArchived, isPiboRoomPinned, piboRoomSidebarOrder, roomWorkspaceFromMetadata, withChatRoomId, withPiboRoomPinned, withPiboRoomSidebarOrder, withPiboRoomWorkspace, } from "./types/rooms.js";
|
|
16
17
|
import { chatStreamFramesFromOutputEvent, createChatStreamState, nextTransientChatStreamFrameId } from "./stream.js";
|
|
17
18
|
import { buildSessionNodes, buildTraceView, TRACE_PROJECTION_VERSION } from "./trace.js";
|
|
18
19
|
import { DEFAULT_TRACE_EVENTS_PAGE_SIZE, annotateTracePage, etagForVersion, estimateTraceViewBytes, traceCacheEstimatedBytes, liveSnapshotVersion, requestMatchesVersion, setTraceCache, traceProjectionStatus, traceCacheKey, withLiveSnapshots, withRawTraceTail, } from "./chat-trace-helpers.js";
|
|
19
20
|
import { TRACE_V2_DEFAULT_TIMELINE_LIMIT, TRACE_V2_MAX_TIMELINE_LIMIT, TRACE_V2_PAYLOAD_DEFAULT_LIMIT_BYTES, TRACE_V2_PAYLOAD_MAX_LIMIT_BYTES, TRACE_V2_RAW_EVENTS_DEFAULT_LIMIT, TRACE_V2_RAW_EVENTS_MAX_LIMIT, TRACE_V2_TIMELINE_HARD_BYTES, TRACE_IMAGE_MAX_COUNT, parseTracePayloadRef, readTraceImagePayload, readTracePayloadChunk, traceRawEventsPageFromEvents, traceTimelinePageFromView, } from "./trace-v2.js";
|
|
20
|
-
import { isChatWebSessionArchived } from "./session-metadata.js";
|
|
21
|
+
import { chatWebSessionSidebarOrder, compareChatWebSessionsBySidebarOrder, isChatWebSessionArchived, isChatWebSessionPinned, withChatWebSessionPinned, withChatWebSessionSidebarOrder, } from "./session-metadata.js";
|
|
21
22
|
import { withWorkflowSessionKind } from "../../sessions/workflow-session-kind.js";
|
|
22
23
|
import { CustomAgentTargetReferenceError, CustomAgentStore, createDefaultCustomAgentStore, previewCustomAgentCreate, previewCustomAgentUpdate, } from "./agent-store.js";
|
|
23
24
|
import { loadPiboModelDefaults, } from "../../core/model-defaults.js";
|
|
@@ -39,7 +40,8 @@ import { ChatRoomService, PiboRoomHierarchyCycleError } from "./data/room-servic
|
|
|
39
40
|
import { ChatSessionQueryService } from "./data/session-query-service.js";
|
|
40
41
|
import { ChatTimelineQueryService } from "./data/timeline-query-service.js";
|
|
41
42
|
import { ChatHistoryQueryService } from "./data/history-query-service.js";
|
|
42
|
-
import {
|
|
43
|
+
import { ChatWorkflowSessionService, } from "./data/workflow-session-service.js";
|
|
44
|
+
import { migrateLegacyProjects } from "./data/legacy-project-migration.js";
|
|
43
45
|
import { PiboDataStore } from "../../data/pibo-store.js";
|
|
44
46
|
import { createDefaultPiboCronStore } from "../../cron/store.js";
|
|
45
47
|
import { createDefaultPiboLoopStore } from "../../loops/store.js";
|
|
@@ -56,12 +58,12 @@ import { responseChatSpeechProviders, responseChatSpeechSessionSpeak, responseCh
|
|
|
56
58
|
import { chatSettingsRoute, chatSettingsRouteInvalidatesBootstrapCatalog, chatSettingsRouteRequiresSameOrigin, handleChatSettingsRoute, } from "./chat-settings-routes.js";
|
|
57
59
|
import { chatCapabilityRoute, chatCapabilityRouteRequiresSameOrigin, handleChatCapabilityRoute, } from "./chat-capability-routes.js";
|
|
58
60
|
import { chatUserSkillRoute, chatUserSkillRouteRequiresSameOrigin, handleChatUserSkillRoute, syncChatUserSkills, } from "./chat-user-skill-routes.js";
|
|
59
|
-
import { CHAT_WEB_API_PREFIX, agentFolderResourceId, agentResourceId,
|
|
60
|
-
import {
|
|
61
|
+
import { CHAT_WEB_API_PREFIX, agentFolderResourceId, agentResourceId, roomResourcePath, sessionActionResource, sessionResourceId, sessionWorkflowResource, signalResource, workflowArchiveResourceId, workflowCatalogResourceId, workflowDraftActionResource, workflowDraftManualTriggerRunResource, workflowDraftResourceId, workflowDuplicateResourceId, workflowNextDraftResourceId, workflowPickerKind, workflowPromptAssetResourceId, workflowVersionResource, } from "./chat-api-routes.js";
|
|
62
|
+
import { buildStreamingFixtureSchedule, createAgentInput, createAgentUpdate, createRoomUpdate, createSessionUpdate, normalizeAgentArchived, normalizeAgentFolderName, normalizeClientTxnId, normalizeMessageDelivery, normalizeMessageText, normalizeParentRoomId, normalizeRoomDeleteConfirmation, normalizeRoomName, normalizeRoomTopic, normalizeRoomType, normalizeRoomWorkspace, normalizeSessionDeleteConfirmation, normalizeSessionTitle, normalizeStreamingFixtureCadenceMs, normalizeStreamingFixtureDeltas, normalizeStreamingFixtureMix, normalizeStreamingFixturePreludeMessages, normalizeStreamingFixturePreludeOnly, normalizeStreamingFixtureProfile, normalizeStreamingFixtureSuppressLiveDeltas, normalizeStreamingFixtureTraceSnapshots, normalizeStreamingFixtureToolInterleaving, resolveCreateSessionProfile, } from "./chat-request-normalizers.js";
|
|
61
63
|
import { ChatWorkflowArchiveStore, ChatWorkflowDraftStore, ChatWorkflowLifecycleEventStore, ChatWorkflowPromptAssetStore, ChatWorkflowPublishedVersionStore, ChatWorkflowTombstoneStore, hashWorkflowDefinitionJson, normalizeWorkflowPromptAssetLabel, sanitizeWorkflowDiagnostics, } from "./workflow-persistence.js";
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
import { STATIC_WORKFLOW_VERSION_CATALOG,
|
|
64
|
+
import { normalizeWorkflowHumanActionBody, workflowHumanActionDiagnosticResponse, workflowHumanActionLifecyclePayload, workflowHumanActionRuntimeDiagnostic, workflowHumanActionSubmittedLifecyclePayload, workflowPendingHumanActionFromToken, validateWorkflowHumanActionRequest, } from "./workflow-human-actions.js";
|
|
65
|
+
import { createWorkflowRunCurrent, createWorkflowSessionSnapshot, normalizeWorkflowSessionConfiguration, workflowVersionFromSnapshot, } from "./workflow-sessions.js";
|
|
66
|
+
import { STATIC_WORKFLOW_VERSION_CATALOG, buildWorkflowVersionCatalog, buildWorkflowVersionOptions, buildWorkflowCatalogInspect as buildWorkflowCatalogInspectWithServices, buildWorkflowCatalogList as buildWorkflowCatalogListWithServices, buildWorkflowVersionHistory, buildWorkflowVersionInspect as buildWorkflowVersionInspectWithServices, buildWorkflowVersionList as buildWorkflowVersionListWithServices, buildWorkflowVersionPicker, createPublishedWorkflowDefinition, selectWorkflowCatalogDisplayVersion, workflowDefinitionTags, workflowVersionPickerOptionFromCatalogRecord, } from "./workflow-catalog.js";
|
|
65
67
|
import { cloneJsonObject, isWorkflowValidationPipelineDiagnostic, normalizeWorkflowValidationTrigger, normalizeWorkflowVersionIntent, parseWorkflowDraftDefinitionFromPatch, summarizeWorkflowDiagnostics, withoutRawWorkflowIrParseDiagnostic, } from "./workflow-validation-helpers.js";
|
|
66
68
|
import { validateWorkflowEdgeAdapterOutputCompatibilityLike, validateWorkflowEdgeDirectCompatibilityLike, } from "./workflow-edge-compatibility.js";
|
|
67
69
|
import { runWorkflowManualTextTrigger, } from "./workflow-manual-trigger-runtime.js";
|
|
@@ -236,6 +238,13 @@ function createReliabilityStore(path) {
|
|
|
236
238
|
function createDataStore(options) {
|
|
237
239
|
return new PiboDataStore(options.dataStorePath, { payloadRootDir: options.dataPayloadRootDir });
|
|
238
240
|
}
|
|
241
|
+
function workflowStorePath(options, dataStore) {
|
|
242
|
+
if (options.workflowStorePath)
|
|
243
|
+
return options.workflowStorePath;
|
|
244
|
+
if (dataStore.path === ":memory:")
|
|
245
|
+
return ":memory:";
|
|
246
|
+
return join(dirname(dataStore.path), "pibo-workflows.sqlite");
|
|
247
|
+
}
|
|
239
248
|
function resolveVscodeWebUrl(value) {
|
|
240
249
|
const trimmed = value?.trim();
|
|
241
250
|
if (!trimmed)
|
|
@@ -750,7 +759,7 @@ function listSharedSessions(context) {
|
|
|
750
759
|
const profiles = context.channelContext.getProfiles?.();
|
|
751
760
|
return sessions
|
|
752
761
|
.map((session) => canonicalizeSessionProfile(context, session, profiles))
|
|
753
|
-
.sort(
|
|
762
|
+
.sort(compareChatWebSessionsBySidebarOrder);
|
|
754
763
|
}
|
|
755
764
|
function canonicalizeSessionProfile(context, session, profiles = context.channelContext.getProfiles?.()) {
|
|
756
765
|
const canonicalProfile = canonicalProfileName(profiles, session.profile);
|
|
@@ -818,7 +827,7 @@ function paginateSessionNodes(nodes, input) {
|
|
|
818
827
|
}
|
|
819
828
|
function sessionTreeVersion(nodes) {
|
|
820
829
|
return nodes
|
|
821
|
-
.map((node) => `${node.piboSessionId}:${node.lastActivityAt ?? ""}:${node.status}:${node.archived ? "1" : "0"}`)
|
|
830
|
+
.map((node) => `${node.piboSessionId}:${node.lastActivityAt ?? ""}:${node.status}:${node.archived ? "1" : "0"}:${node.pinned ? "1" : "0"}:${node.sidebarOrder ?? ""}`)
|
|
822
831
|
.join("|");
|
|
823
832
|
}
|
|
824
833
|
function selectedRoomIdForSession(state, context, session) {
|
|
@@ -875,92 +884,67 @@ function requireRoom(state, roomId, webSession, action = "read") {
|
|
|
875
884
|
}
|
|
876
885
|
return room;
|
|
877
886
|
}
|
|
878
|
-
function listSharedProjects(state, _webSession, options = {}) {
|
|
879
|
-
return state.projectService.listProjects(options);
|
|
880
|
-
}
|
|
881
|
-
function requireSharedProject(state, _webSession, projectId, options = {}) {
|
|
882
|
-
try {
|
|
883
|
-
return state.projectService.requireProject(projectId, options);
|
|
884
|
-
}
|
|
885
|
-
catch {
|
|
886
|
-
throw new PiboWebHttpError("Project not found", 404);
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
887
|
function createSharedChatSession(context, webSession, profile, room) {
|
|
888
|
+
const normalSessions = sessionsInRoom(listSharedSessions(context), room.id)
|
|
889
|
+
.filter((session) => !session.parentId && !isChatWebSessionArchived(session) && !isChatWebSessionPinned(session));
|
|
890
890
|
return context.channelContext.createSession({
|
|
891
891
|
channel: CHAT_WEB_CHANNEL,
|
|
892
892
|
kind: "chat",
|
|
893
893
|
profile,
|
|
894
894
|
workspace: roomWorkspaceFromMetadata(room.metadata) ?? getDefaultPiboWorkspace(),
|
|
895
|
-
metadata: withChatRoomId(undefined, room.id),
|
|
895
|
+
metadata: withChatWebSessionSidebarOrder(withChatRoomId(undefined, room.id), nextChatWebSessionSidebarOrder(normalSessions)),
|
|
896
896
|
});
|
|
897
897
|
}
|
|
898
|
-
function
|
|
899
|
-
const
|
|
898
|
+
function createWorkflowSession(input) {
|
|
899
|
+
const normalSessions = sessionsInRoom(listSharedSessions(input.context), input.room.id)
|
|
900
|
+
.filter((session) => !session.parentId && !isChatWebSessionArchived(session) && !isChatWebSessionPinned(session));
|
|
900
901
|
const session = input.context.channelContext.createSession({
|
|
901
902
|
channel: CHAT_WEB_CHANNEL,
|
|
902
903
|
kind: "chat",
|
|
903
904
|
profile: input.profile,
|
|
904
|
-
workspace: input.
|
|
905
|
+
workspace: input.workspace ?? roomWorkspaceFromMetadata(input.room.metadata) ?? getDefaultPiboWorkspace(),
|
|
905
906
|
...(input.title ? { title: input.title } : {}),
|
|
906
|
-
...(input.configuration
|
|
907
|
-
metadata: withWorkflowSessionKind({
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
...(input.configuration ? { projectWorkflowConfiguration: input.configuration } : {}),
|
|
913
|
-
}, "main_workflow"),
|
|
907
|
+
...(input.configuration.model ? { activeModel: input.configuration.model } : {}),
|
|
908
|
+
metadata: withWorkflowSessionKind(withChatWebSessionSidebarOrder({
|
|
909
|
+
...withChatRoomId(undefined, input.room.id),
|
|
910
|
+
workflowId: input.workflow.id,
|
|
911
|
+
workflowVersion: input.workflow.version,
|
|
912
|
+
}, nextChatWebSessionSidebarOrder(normalSessions)), "main_workflow"),
|
|
914
913
|
});
|
|
915
|
-
input.state.
|
|
916
|
-
projectId: input.project.id,
|
|
914
|
+
const workflowSession = input.state.workflowService.addWorkflowSession({
|
|
917
915
|
piboSessionId: session.id,
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
title: session.title,
|
|
922
|
-
state: input.configuredWorkflow ? "configured" : undefined,
|
|
916
|
+
workflowId: input.workflow.id,
|
|
917
|
+
workflowVersion: input.workflow.version,
|
|
918
|
+
state: "configured",
|
|
923
919
|
configuration: input.configuration,
|
|
924
920
|
});
|
|
925
921
|
input.state.sessionQuery.upsertSession(session);
|
|
926
|
-
return session;
|
|
922
|
+
return { session, workflowSession };
|
|
927
923
|
}
|
|
928
|
-
function
|
|
924
|
+
function resolveWorkflowSelection(state, workflowIdValue, workflowVersionValue, options = {}) {
|
|
929
925
|
if (options.requireExplicitWorkflowId && (workflowIdValue === undefined || workflowIdValue === null || workflowIdValue === "")) {
|
|
930
926
|
throw new PiboWebHttpError("Workflow id is required", 400);
|
|
931
927
|
}
|
|
932
|
-
const workflowId =
|
|
933
|
-
const workflowVersion =
|
|
934
|
-
if (options.requireExplicitVersion && !workflowVersion)
|
|
928
|
+
const workflowId = normalizeWorkflowId(workflowIdValue);
|
|
929
|
+
const workflowVersion = normalizeWorkflowVersion(workflowVersionValue);
|
|
930
|
+
if (options.requireExplicitVersion && !workflowVersion)
|
|
935
931
|
throw new PiboWebHttpError("Workflow version is required", 400);
|
|
936
|
-
|
|
937
|
-
const candidates = buildProjectWorkflowVersionCatalog(state).filter((option) => option.id === workflowId);
|
|
932
|
+
const candidates = buildWorkflowVersionCatalog(state).filter((option) => option.id === workflowId);
|
|
938
933
|
const selected = candidates.find((option) => workflowVersion === undefined || option.version === workflowVersion);
|
|
939
|
-
if (!selected)
|
|
934
|
+
if (!selected)
|
|
940
935
|
throw new PiboWebHttpError(`Unknown workflow version: ${workflowId}${workflowVersion ? `@${workflowVersion}` : ""}`, 400);
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
}
|
|
945
|
-
if (selected.status !== "published") {
|
|
936
|
+
if (selected.status === "archived")
|
|
937
|
+
throw new PiboWebHttpError(`Workflow version '${selected.id}@${selected.version}' is archived and cannot create a Workflow Session`, 400);
|
|
938
|
+
if (selected.status !== "published")
|
|
946
939
|
throw new PiboWebHttpError(`Workflow version '${selected.id}@${selected.version}' is not published`, 400);
|
|
947
|
-
}
|
|
948
940
|
return workflowVersionPickerOptionFromCatalogRecord({ ...selected, status: "published" });
|
|
949
941
|
}
|
|
950
|
-
function
|
|
951
|
-
const workflowId = normalizeProjectWorkflowId(value);
|
|
952
|
-
if (workflowId !== "simple-chat")
|
|
953
|
-
throw new PiboWebHttpError("Only the simple-chat workflow is available in V1", 400);
|
|
954
|
-
return workflowId;
|
|
955
|
-
}
|
|
956
|
-
function normalizeProjectWorkflowId(value) {
|
|
957
|
-
if (value === undefined || value === null || value === "")
|
|
958
|
-
return "simple-chat";
|
|
942
|
+
function normalizeWorkflowId(value) {
|
|
959
943
|
if (typeof value !== "string" || !value.trim())
|
|
960
|
-
throw new PiboWebHttpError("Workflow id
|
|
944
|
+
throw new PiboWebHttpError("Workflow id is required", 400);
|
|
961
945
|
return value.trim();
|
|
962
946
|
}
|
|
963
|
-
function
|
|
947
|
+
function normalizeWorkflowVersion(value) {
|
|
964
948
|
if (value === undefined || value === null || value === "")
|
|
965
949
|
return undefined;
|
|
966
950
|
if (typeof value !== "string" || !value.trim())
|
|
@@ -1032,18 +1016,14 @@ function requireWorkflowDeleteConfirmation(value, workflowId) {
|
|
|
1032
1016
|
throw new PiboWebHttpError(`Type "${workflowId}" to delete this workflow.`, 400);
|
|
1033
1017
|
}
|
|
1034
1018
|
}
|
|
1035
|
-
|
|
1036
|
-
"title",
|
|
1037
|
-
"archived",
|
|
1038
|
-
]);
|
|
1039
|
-
function validateProjectWorkflowSnapshotForStart(snapshot, input) {
|
|
1019
|
+
function validateWorkflowSnapshotForStart(snapshot, input) {
|
|
1040
1020
|
const diagnostics = sanitizeWorkflowDiagnostics(validateWorkflowDefinitionForV2(snapshot.effectiveDefinition, input));
|
|
1041
1021
|
return {
|
|
1042
1022
|
diagnostics,
|
|
1043
1023
|
validation: summarizeWorkflowDiagnostics(diagnostics, "before_workflow_start"),
|
|
1044
1024
|
};
|
|
1045
1025
|
}
|
|
1046
|
-
function
|
|
1026
|
+
function updateWorkflowRunSessionMetadata(input) {
|
|
1047
1027
|
if (input.session.metadata?.workflowRunId === input.workflowRunId)
|
|
1048
1028
|
return;
|
|
1049
1029
|
const updateSession = input.context.channelContext.updateSession;
|
|
@@ -1574,8 +1554,8 @@ function requireValidatedWorkflowDraft(state, context, webSession, draftId, trig
|
|
|
1574
1554
|
return serializeWorkflowDraft(record);
|
|
1575
1555
|
}
|
|
1576
1556
|
function duplicateWorkflowIntoDraft(state, webSession, workflowIdValue, workflowVersionValue) {
|
|
1577
|
-
const workflowId =
|
|
1578
|
-
const workflowVersion =
|
|
1557
|
+
const workflowId = normalizeWorkflowId(workflowIdValue);
|
|
1558
|
+
const workflowVersion = normalizeWorkflowVersion(workflowVersionValue);
|
|
1579
1559
|
const published = selectPublishedWorkflowVersion(state, workflowId, workflowVersion);
|
|
1580
1560
|
if (!published)
|
|
1581
1561
|
throw new PiboWebHttpError("Published workflow version not found", 404);
|
|
@@ -1626,8 +1606,8 @@ function duplicateWorkflowIntoDraft(state, webSession, workflowIdValue, workflow
|
|
|
1626
1606
|
return serializeWorkflowDraft(draft);
|
|
1627
1607
|
}
|
|
1628
1608
|
function createNextVersionDraftFromPublishedWorkflow(state, webSession, workflowIdValue, workflowVersionValue) {
|
|
1629
|
-
const workflowId =
|
|
1630
|
-
const workflowVersion =
|
|
1609
|
+
const workflowId = normalizeWorkflowId(workflowIdValue);
|
|
1610
|
+
const workflowVersion = normalizeWorkflowVersion(workflowVersionValue);
|
|
1631
1611
|
const published = selectPublishedWorkflowVersion(state, workflowId, workflowVersion);
|
|
1632
1612
|
if (!published)
|
|
1633
1613
|
throw new PiboWebHttpError("Published workflow version not found", 404);
|
|
@@ -1684,7 +1664,7 @@ function createNextVersionDraftFromPublishedWorkflow(state, webSession, workflow
|
|
|
1684
1664
|
return { draft: serializeWorkflowDraft(draft), reused: false };
|
|
1685
1665
|
}
|
|
1686
1666
|
function archiveWorkflowIdentity(state, context, webSession, workflowIdValue, reasonValue) {
|
|
1687
|
-
const workflowId =
|
|
1667
|
+
const workflowId = normalizeWorkflowId(workflowIdValue);
|
|
1688
1668
|
const catalog = buildWorkflowCatalogList(state, context, webSession, { includeArchived: true });
|
|
1689
1669
|
const workflow = catalog.workflows.find((record) => record.id === workflowId);
|
|
1690
1670
|
if (!workflow)
|
|
@@ -1714,7 +1694,7 @@ function archiveWorkflowIdentity(state, context, webSession, workflowIdValue, re
|
|
|
1714
1694
|
return { workflow: archivedWorkflow, archiveState };
|
|
1715
1695
|
}
|
|
1716
1696
|
function deleteWorkflowIdentity(state, context, webSession, workflowIdValue, body) {
|
|
1717
|
-
const workflowId =
|
|
1697
|
+
const workflowId = normalizeWorkflowId(workflowIdValue);
|
|
1718
1698
|
const catalog = buildWorkflowCatalogList(state, context, webSession, { includeArchived: true });
|
|
1719
1699
|
const workflow = catalog.workflows.find((record) => record.id === workflowId);
|
|
1720
1700
|
if (!workflow)
|
|
@@ -1747,7 +1727,7 @@ function deleteWorkflowIdentity(state, context, webSession, workflowIdValue, bod
|
|
|
1747
1727
|
return { workflowId, deleted: true, tombstone };
|
|
1748
1728
|
}
|
|
1749
1729
|
function selectPublishedWorkflowVersion(state, workflowId, version) {
|
|
1750
|
-
const options =
|
|
1730
|
+
const options = buildWorkflowVersionOptions(state).filter((option) => option.id === workflowId);
|
|
1751
1731
|
const selected = version ? options.find((option) => option.version === version) : options[0];
|
|
1752
1732
|
if (!selected)
|
|
1753
1733
|
return undefined;
|
|
@@ -1915,7 +1895,9 @@ function normalizeWorkflowDraftManualTriggerRunBody(body) {
|
|
|
1915
1895
|
throw new PiboWebHttpError("Manual trigger node id is required", 400);
|
|
1916
1896
|
if (typeof body.input !== "string")
|
|
1917
1897
|
throw new PiboWebHttpError("Manual trigger input must be text", 400);
|
|
1918
|
-
|
|
1898
|
+
if (body.roomId !== undefined && typeof body.roomId !== "string")
|
|
1899
|
+
throw new PiboWebHttpError("Room id must be a string", 400);
|
|
1900
|
+
return { triggerNodeId, input: body.input, roomId: typeof body.roomId === "string" ? body.roomId.trim() || undefined : undefined, workspace: body.workspace === undefined ? undefined : normalizeRoomWorkspace(body.workspace) };
|
|
1919
1901
|
}
|
|
1920
1902
|
function resolveWorkflowRuntimeProfile(input) {
|
|
1921
1903
|
const profile = input.context.channelContext.getProfiles?.().find((candidate) => candidate.name === input.requestedId || candidate.aliases.includes(input.requestedId));
|
|
@@ -2202,7 +2184,7 @@ function validateWorkflowNestedNodeLike(nodeId, node, input, diagnostics) {
|
|
|
2202
2184
|
const workflowId = typeof node.workflowId === "string" ? node.workflowId.trim() : undefined;
|
|
2203
2185
|
const workflowVersion = typeof node.workflowVersion === "string" ? node.workflowVersion.trim() : undefined;
|
|
2204
2186
|
const selected = workflowId
|
|
2205
|
-
?
|
|
2187
|
+
? buildWorkflowVersionOptions(input.state).find((option) => option.id === workflowId && (!workflowVersion || option.version === workflowVersion))
|
|
2206
2188
|
: undefined;
|
|
2207
2189
|
if (!selected) {
|
|
2208
2190
|
const registryRef = workflowId ? `${workflowId}${workflowVersion ? `@${workflowVersion}` : ""}` : undefined;
|
|
@@ -2422,7 +2404,7 @@ async function deleteSessionsForAgentProfile(state, context, webSession, profile
|
|
|
2422
2404
|
}
|
|
2423
2405
|
const orderedIds = [...ids].sort((left, right) => sessionDepth(sessionsById.get(right), sessionsById) - sessionDepth(sessionsById.get(left), sessionsById));
|
|
2424
2406
|
for (const id of orderedIds) {
|
|
2425
|
-
await
|
|
2407
|
+
await deleteSession(id);
|
|
2426
2408
|
state.sessionQuery.deleteSessions([id]);
|
|
2427
2409
|
state.eventCommands.deleteSessions([id]);
|
|
2428
2410
|
}
|
|
@@ -2449,7 +2431,7 @@ async function deleteSessionSubtree(state, context, webSession, rootSession) {
|
|
|
2449
2431
|
}
|
|
2450
2432
|
const orderedIds = [...ids].sort((left, right) => sessionDepth(sessionsById.get(right), sessionsById) - sessionDepth(sessionsById.get(left), sessionsById));
|
|
2451
2433
|
for (const id of orderedIds) {
|
|
2452
|
-
await
|
|
2434
|
+
await deleteSession(id);
|
|
2453
2435
|
state.sessionQuery.deleteSessions([id]);
|
|
2454
2436
|
state.eventCommands.deleteSessions([id]);
|
|
2455
2437
|
}
|
|
@@ -2490,7 +2472,7 @@ async function deleteRoomTree(state, context, webSession, room, confirmName) {
|
|
|
2490
2472
|
}
|
|
2491
2473
|
const orderedSessionIds = [...ids].sort((left, right) => sessionDepth(sessionsById.get(right), sessionsById) - sessionDepth(sessionsById.get(left), sessionsById));
|
|
2492
2474
|
for (const id of orderedSessionIds) {
|
|
2493
|
-
await
|
|
2475
|
+
await deleteSession(id);
|
|
2494
2476
|
state.sessionQuery.deleteSessions([id]);
|
|
2495
2477
|
state.eventCommands.deleteSessions([id]);
|
|
2496
2478
|
}
|
|
@@ -2703,6 +2685,95 @@ async function resolveContextBuildRuntime(context, runtimeInstanceId) {
|
|
|
2703
2685
|
function indexSharedSessions(sessionQuery, sessions) {
|
|
2704
2686
|
sessionQuery.upsertSessionsIfChanged(sessions);
|
|
2705
2687
|
}
|
|
2688
|
+
function nextChatWebRoomSidebarOrder(rooms) {
|
|
2689
|
+
return rooms.reduce((maximum, room) => {
|
|
2690
|
+
const createdOrder = Date.parse(room.createdAt) || 0;
|
|
2691
|
+
return Math.max(maximum, piboRoomSidebarOrder(room) ?? createdOrder);
|
|
2692
|
+
}, 0) + 1;
|
|
2693
|
+
}
|
|
2694
|
+
function reorderChatWebRoom(input) {
|
|
2695
|
+
if (input.room.parentRoomId || input.targetRoom.parentRoomId) {
|
|
2696
|
+
throw new PiboWebHttpError("Only top-level rooms can be reordered", 400);
|
|
2697
|
+
}
|
|
2698
|
+
if (isDefaultPiboRoom(input.room) || isDefaultPiboRoom(input.targetRoom)) {
|
|
2699
|
+
throw new PiboWebHttpError("Shared Chat cannot be reordered", 400);
|
|
2700
|
+
}
|
|
2701
|
+
if (isPiboRoomArchived(input.room) || isPiboRoomArchived(input.targetRoom)) {
|
|
2702
|
+
throw new PiboWebHttpError("Archived rooms cannot be reordered", 400);
|
|
2703
|
+
}
|
|
2704
|
+
const pinned = isPiboRoomPinned(input.room);
|
|
2705
|
+
if (pinned !== isPiboRoomPinned(input.targetRoom)) {
|
|
2706
|
+
throw new PiboWebHttpError("Pinned and unpinned rooms cannot be reordered together", 400);
|
|
2707
|
+
}
|
|
2708
|
+
const ordered = input.state.roomService.listRooms()
|
|
2709
|
+
.filter((room) => !room.parentRoomId && !isDefaultPiboRoom(room) && !isPiboRoomArchived(room) && isPiboRoomPinned(room) === pinned)
|
|
2710
|
+
.sort(comparePiboRoomsBySidebarOrder);
|
|
2711
|
+
const movedIndex = ordered.findIndex((room) => room.id === input.room.id);
|
|
2712
|
+
const targetIndex = ordered.findIndex((room) => room.id === input.targetRoom.id);
|
|
2713
|
+
if (movedIndex < 0 || targetIndex < 0)
|
|
2714
|
+
throw new PiboWebHttpError("Room ordering target not found", 404);
|
|
2715
|
+
if (movedIndex === targetIndex)
|
|
2716
|
+
return ordered.map((room) => room.id);
|
|
2717
|
+
const [moved] = ordered.splice(movedIndex, 1);
|
|
2718
|
+
const remainingTargetIndex = ordered.findIndex((room) => room.id === input.targetRoom.id);
|
|
2719
|
+
ordered.splice(input.position === "before" ? remainingTargetIndex : remainingTargetIndex + 1, 0, moved);
|
|
2720
|
+
const orderBase = nextChatWebRoomSidebarOrder(ordered) + ordered.length - 1;
|
|
2721
|
+
for (const [index, room] of ordered.entries()) {
|
|
2722
|
+
const updated = input.state.roomService.updateRoom(room.id, {
|
|
2723
|
+
metadata: withPiboRoomSidebarOrder(room.metadata, orderBase - index),
|
|
2724
|
+
});
|
|
2725
|
+
if (!updated)
|
|
2726
|
+
throw new PiboWebHttpError("Room not found", 404);
|
|
2727
|
+
}
|
|
2728
|
+
return ordered.map((room) => room.id);
|
|
2729
|
+
}
|
|
2730
|
+
function nextChatWebSessionSidebarOrder(sessions) {
|
|
2731
|
+
return sessions.reduce((maximum, session) => {
|
|
2732
|
+
const createdOrder = Date.parse(session.createdAt) || 0;
|
|
2733
|
+
return Math.max(maximum, chatWebSessionSidebarOrder(session) ?? createdOrder);
|
|
2734
|
+
}, 0) + 1;
|
|
2735
|
+
}
|
|
2736
|
+
function reorderChatWebSession(input) {
|
|
2737
|
+
if (input.session.parentId || input.targetSession.parentId) {
|
|
2738
|
+
throw new PiboWebHttpError("Only top-level sessions can be reordered", 400);
|
|
2739
|
+
}
|
|
2740
|
+
if (isChatWebSessionArchived(input.session) || isChatWebSessionArchived(input.targetSession)) {
|
|
2741
|
+
throw new PiboWebHttpError("Archived sessions cannot be reordered", 400);
|
|
2742
|
+
}
|
|
2743
|
+
const roomId = chatRoomIdFromMetadata(input.session.metadata);
|
|
2744
|
+
const targetRoomId = chatRoomIdFromMetadata(input.targetSession.metadata);
|
|
2745
|
+
if (!roomId || roomId !== targetRoomId)
|
|
2746
|
+
throw new PiboWebHttpError("Sessions must belong to the same room", 400);
|
|
2747
|
+
const pinned = isChatWebSessionPinned(input.session);
|
|
2748
|
+
if (pinned !== isChatWebSessionPinned(input.targetSession)) {
|
|
2749
|
+
throw new PiboWebHttpError("Pinned and unpinned sessions cannot be reordered together", 400);
|
|
2750
|
+
}
|
|
2751
|
+
const updateSession = input.context.channelContext.updateSession;
|
|
2752
|
+
if (!updateSession)
|
|
2753
|
+
throw new PiboWebHttpError("Session updates are not available", 501);
|
|
2754
|
+
const ordered = sessionsInRoom(listSharedSessions(input.context), roomId)
|
|
2755
|
+
.filter((session) => !session.parentId && !isChatWebSessionArchived(session) && isChatWebSessionPinned(session) === pinned)
|
|
2756
|
+
.sort(compareChatWebSessionsBySidebarOrder);
|
|
2757
|
+
const movedIndex = ordered.findIndex((session) => session.id === input.session.id);
|
|
2758
|
+
const targetIndex = ordered.findIndex((session) => session.id === input.targetSession.id);
|
|
2759
|
+
if (movedIndex < 0 || targetIndex < 0)
|
|
2760
|
+
throw new PiboWebHttpError("Session ordering target not found", 404);
|
|
2761
|
+
if (movedIndex === targetIndex)
|
|
2762
|
+
return ordered.map((session) => session.id);
|
|
2763
|
+
const [moved] = ordered.splice(movedIndex, 1);
|
|
2764
|
+
const remainingTargetIndex = ordered.findIndex((session) => session.id === input.targetSession.id);
|
|
2765
|
+
ordered.splice(input.position === "before" ? remainingTargetIndex : remainingTargetIndex + 1, 0, moved);
|
|
2766
|
+
const orderBase = nextChatWebSessionSidebarOrder(ordered) + ordered.length - 1;
|
|
2767
|
+
for (const [index, session] of ordered.entries()) {
|
|
2768
|
+
const updated = updateSession(session.id, {
|
|
2769
|
+
metadata: withChatWebSessionSidebarOrder(session.metadata, orderBase - index),
|
|
2770
|
+
});
|
|
2771
|
+
if (!updated)
|
|
2772
|
+
throw new PiboWebHttpError("Session not found", 404);
|
|
2773
|
+
input.state.sessionQuery.upsertSession(updated);
|
|
2774
|
+
}
|
|
2775
|
+
return ordered.map((session) => session.id);
|
|
2776
|
+
}
|
|
2706
2777
|
function markSessionsRead(state, sessions) {
|
|
2707
2778
|
for (const session of sessions) {
|
|
2708
2779
|
const latestStreamId = state.timelineQuery.getLatestStreamId({ piboSessionId: session.id });
|
|
@@ -3172,284 +3243,75 @@ function createEventStream(input) {
|
|
|
3172
3243
|
},
|
|
3173
3244
|
});
|
|
3174
3245
|
}
|
|
3175
|
-
|
|
3176
|
-
const
|
|
3177
|
-
const
|
|
3178
|
-
let storedProjectSessions = input.state.projectService
|
|
3179
|
-
.listProjectSessions(selectedProject.id, { includeArchived: input.includeArchived })
|
|
3180
|
-
.filter((projectSession) => projectSession.workflowId === "simple-chat");
|
|
3181
|
-
if (selectedProject.id === sharedDefaultProject.id && storedProjectSessions.length === 0) {
|
|
3182
|
-
const session = createProjectChatSession({
|
|
3183
|
-
state: input.state,
|
|
3184
|
-
context: input.context,
|
|
3185
|
-
webSession: input.webSession,
|
|
3186
|
-
project: sharedDefaultProject,
|
|
3187
|
-
profile: input.defaultProfile,
|
|
3188
|
-
workflowId: "simple-chat",
|
|
3189
|
-
});
|
|
3190
|
-
storedProjectSessions = [input.state.projectService.getProjectSession(session.id)];
|
|
3191
|
-
}
|
|
3192
|
-
const projectSessions = storedProjectSessions;
|
|
3193
|
-
const rootSessions = projectSessions
|
|
3194
|
-
.map((projectSession) => input.context.channelContext.getSession(projectSession.piboSessionId))
|
|
3195
|
-
.filter((session) => Boolean(session));
|
|
3196
|
-
const sessions = collectProjectSessionTreeSessions(rootSessions, listSharedSessions(input.context));
|
|
3197
|
-
const requestedSession = input.piboSessionId ? sessions.find((session) => session.id === input.piboSessionId) : undefined;
|
|
3198
|
-
const selectedSession = requestedSession ?? sessions.find((session) => session.id === selectedProject.currentMainSessionId) ?? sessions[0];
|
|
3199
|
-
indexSharedSessions(input.state.sessionQuery, sessions);
|
|
3200
|
-
const nodes = await buildSessionNodes(sessions, input.state.sessionQuery.listSessions(), selectedProject.projectFolder, new Map(), { skipPiMetadataFallback: true });
|
|
3201
|
-
applyProjectSessionArchiveState(nodes, new Map(projectSessions.map((projectSession) => [projectSession.piboSessionId, Boolean(projectSession.archived)])));
|
|
3202
|
-
return {
|
|
3203
|
-
identity: input.webSession.authSession.identity,
|
|
3204
|
-
sharedDefaultProject,
|
|
3205
|
-
project: selectedProject,
|
|
3206
|
-
projects: listSharedProjects(input.state, input.webSession, { includeArchived: input.includeArchived }),
|
|
3207
|
-
projectSessions,
|
|
3208
|
-
workflowLifecycleEvents: [],
|
|
3209
|
-
...(selectedSession ? { session: selectedSession, selectedPiboSessionId: selectedSession.id } : {}),
|
|
3210
|
-
selectedProjectId: selectedProject.id,
|
|
3211
|
-
sessions: nodes,
|
|
3212
|
-
...(await loadBootstrapCatalog(input.state, input.context, input.webSession)),
|
|
3213
|
-
};
|
|
3214
|
-
}
|
|
3215
|
-
function collectProjectSessionTreeSessions(rootSessions, candidateSessions) {
|
|
3216
|
-
const sessionsById = new Map(rootSessions.map((session) => [session.id, session]));
|
|
3217
|
-
let changed = true;
|
|
3218
|
-
while (changed) {
|
|
3219
|
-
changed = false;
|
|
3220
|
-
for (const session of candidateSessions) {
|
|
3221
|
-
if (sessionsById.has(session.id))
|
|
3222
|
-
continue;
|
|
3223
|
-
if (!session.parentId || !sessionsById.has(session.parentId))
|
|
3224
|
-
continue;
|
|
3225
|
-
sessionsById.set(session.id, session);
|
|
3226
|
-
changed = true;
|
|
3227
|
-
}
|
|
3228
|
-
}
|
|
3229
|
-
return [...sessionsById.values()].sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
3230
|
-
}
|
|
3231
|
-
function enrichProjectSessionWorkflowDefinitionLink(state, projectSession) {
|
|
3232
|
-
if (!isProjectWorkflowBackedSession(projectSession))
|
|
3233
|
-
return projectSession;
|
|
3234
|
-
const snapshot = state.projectService.getWorkflowSessionSnapshotForSession(projectSession.piboSessionId);
|
|
3235
|
-
const workflowId = projectSession.workflowId;
|
|
3236
|
-
const workflowVersion = projectSession.workflowVersion ?? snapshot?.workflow.version;
|
|
3246
|
+
function enrichWorkflowSession(state, workflowSession) {
|
|
3247
|
+
const snapshot = state.workflowService.getWorkflowSessionSnapshotForSession(workflowSession.piboSessionId);
|
|
3248
|
+
const workflowVersion = workflowSession.workflowVersion ?? snapshot?.workflow.version;
|
|
3237
3249
|
const catalogRecord = workflowVersion
|
|
3238
|
-
?
|
|
3250
|
+
? buildWorkflowVersionCatalog(state).find((record) => record.id === workflowSession.workflowId && record.version === workflowVersion)
|
|
3239
3251
|
: undefined;
|
|
3240
3252
|
const snapshotHash = snapshot?.workflow.effectiveDefinitionHash ?? snapshot?.deletedDefinitionFallback.effectiveDefinitionHash;
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
const
|
|
3255
|
-
const
|
|
3253
|
+
const workflowDefinitionLink = catalogRecord && catalogRecord.status !== "deleted"
|
|
3254
|
+
? { status: "live", workflowId: workflowSession.workflowId, workflowVersion: catalogRecord.version, title: catalogRecord.title, ...(snapshotHash ? { definitionHash: snapshotHash } : {}), href: workflowDefinitionViewerPath(catalogRecord.id, catalogRecord.version) }
|
|
3255
|
+
: { status: "snapshot_only_definition_deleted", workflowId: workflowSession.workflowId, ...(workflowVersion ? { workflowVersion } : {}), title: snapshot?.deletedDefinitionFallback.title ?? snapshot?.workflow.title ?? workflowSession.workflowId, ...(snapshotHash ? { definitionHash: snapshotHash } : {}), tombstoneLabel: snapshot?.deletedDefinitionFallback.tombstoneLabel ?? "No published catalog version is available. Inspection uses the immutable Workflow snapshot." };
|
|
3256
|
+
const waitTokens = workflowSession.workflowRunId ? state.workflowService.listWorkflowWaitTokens({ piboSessionId: workflowSession.piboSessionId, workflowRunId: workflowSession.workflowRunId, status: "pending", limit: 20 }) : [];
|
|
3257
|
+
return { ...workflowSession, workflowDefinitionLink, ...(waitTokens.length ? { pendingHumanActions: waitTokens.map((token) => workflowPendingHumanActionFromToken(token, WORKFLOW_HUMAN_ACTION_REF_OPTIONS)) } : {}) };
|
|
3258
|
+
}
|
|
3259
|
+
function inspectWorkflowSession(state, context, piboSessionId) {
|
|
3260
|
+
requireSharedSession(context, piboSessionId);
|
|
3261
|
+
const link = state.workflowService.getWorkflowSession(piboSessionId);
|
|
3262
|
+
if (!link)
|
|
3263
|
+
throw new PiboWebHttpError("Workflow session not found", 404);
|
|
3264
|
+
const workflowSession = enrichWorkflowSession(state, link);
|
|
3265
|
+
const snapshot = state.workflowService.getWorkflowSessionSnapshotForSession(piboSessionId);
|
|
3266
|
+
const run = state.workflowService.getWorkflowRunForSession(piboSessionId);
|
|
3267
|
+
const workflowRunId = run?.id ?? workflowSession.workflowRunId;
|
|
3268
|
+
const definitionSnapshot = run?.definitionSnapshotId ? state.workflowService.runtimeStore.getDefinitionSnapshot(run.definitionSnapshotId) : undefined;
|
|
3256
3269
|
return {
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3270
|
+
workflowSession,
|
|
3271
|
+
...(definitionSnapshot ? { definitionSnapshot } : {}),
|
|
3272
|
+
...(snapshot ? { snapshot } : {}),
|
|
3273
|
+
...(run ? { run } : {}),
|
|
3274
|
+
waitTokens: state.workflowService.listWorkflowWaitTokens({ piboSessionId, ...(workflowRunId ? { workflowRunId } : {}), limit: 200 }),
|
|
3275
|
+
humanActions: state.workflowService.listWorkflowHumanActions({ piboSessionId, ...(workflowRunId ? { workflowRunId } : {}), limit: 200 }),
|
|
3276
|
+
nodeAttempts: workflowRunId ? state.workflowService.runtimeStore.listNodeAttempts({ workflowRunId, limit: 200 }) : [],
|
|
3277
|
+
edgeTransfers: workflowRunId ? state.workflowService.runtimeStore.listEdgeTransfers({ workflowRunId, limit: 200 }) : [],
|
|
3278
|
+
lifecycleEvents: [...new Map([
|
|
3279
|
+
...state.workflowLifecycleEventStore.listEvents({ piboSessionId, limit: 200 }),
|
|
3280
|
+
...(workflowRunId ? state.workflowLifecycleEventStore.listEvents({ workflowRunId, limit: 200 }) : []),
|
|
3281
|
+
].map((event) => [event.id, event])).values()].sort((left, right) => right.createdAt.localeCompare(left.createdAt) || right.id.localeCompare(left.id)),
|
|
3266
3282
|
};
|
|
3267
3283
|
}
|
|
3268
|
-
function
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
if (!waitTokens.length)
|
|
3279
|
-
return projectSession;
|
|
3280
|
-
return {
|
|
3281
|
-
...projectSession,
|
|
3282
|
-
pendingHumanActions: waitTokens.map((token) => projectWorkflowPendingHumanActionFromToken(token, WORKFLOW_HUMAN_ACTION_REF_OPTIONS)),
|
|
3283
|
-
};
|
|
3284
|
-
}
|
|
3285
|
-
function submitProjectWorkflowHumanAction(input) {
|
|
3286
|
-
const project = requireSharedProject(input.state, input.webSession, input.projectId);
|
|
3287
|
-
const session = requireSharedSession(input.context, input.piboSessionId);
|
|
3288
|
-
const projectSession = input.state.projectService.getProjectSession(session.id);
|
|
3289
|
-
if (!projectSession || projectSession.projectId !== project.id)
|
|
3290
|
-
throw new PiboWebHttpError("Project workflow session not found", 404);
|
|
3291
|
-
if (!projectSession.workflowRunId) {
|
|
3292
|
-
return projectWorkflowHumanActionDiagnosticResponse("Project workflow session has no workflow run to resolve", [{
|
|
3293
|
-
code: "WorkflowRuntimeError.workflowRunMissing",
|
|
3294
|
-
message: "This Project workflow session has not started a workflow run, so no human wait token can be resolved.",
|
|
3295
|
-
severity: "error",
|
|
3296
|
-
path: "$.workflowRunId",
|
|
3297
|
-
hint: "Start the configured workflow session before submitting human actions.",
|
|
3298
|
-
}], 409, undefined, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3299
|
-
}
|
|
3300
|
-
const normalized = normalizeProjectWorkflowHumanActionBody(input.body);
|
|
3301
|
-
if (normalized.diagnostics.length) {
|
|
3302
|
-
return projectWorkflowHumanActionDiagnosticResponse("Human action request is invalid", normalized.diagnostics, 400, undefined, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3303
|
-
}
|
|
3284
|
+
function submitWorkflowHumanAction(input) {
|
|
3285
|
+
requireSharedSession(input.context, input.piboSessionId);
|
|
3286
|
+
const workflowSession = input.state.workflowService.getWorkflowSession(input.piboSessionId);
|
|
3287
|
+
if (!workflowSession)
|
|
3288
|
+
throw new PiboWebHttpError("Workflow session not found", 404);
|
|
3289
|
+
if (!workflowSession.workflowRunId)
|
|
3290
|
+
return workflowHumanActionDiagnosticResponse("Workflow session has no workflow run to resolve", [{ code: "WorkflowRuntimeError.workflowRunMissing", message: "This Workflow session has not started a run.", severity: "error", path: "$.workflowRunId", hint: "Start the configured Workflow session before submitting human actions." }], 409, undefined, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3291
|
+
const normalized = normalizeWorkflowHumanActionBody(input.body);
|
|
3292
|
+
if (normalized.diagnostics.length)
|
|
3293
|
+
return workflowHumanActionDiagnosticResponse("Human action request is invalid", normalized.diagnostics, 400, undefined, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3304
3294
|
const request = normalized.request;
|
|
3305
|
-
const waitToken = input.state.
|
|
3306
|
-
const validation =
|
|
3307
|
-
projectSession,
|
|
3308
|
-
waitToken,
|
|
3309
|
-
request,
|
|
3310
|
-
humanActionOptions: WORKFLOW_HUMAN_ACTION_REF_OPTIONS,
|
|
3311
|
-
});
|
|
3295
|
+
const waitToken = input.state.workflowService.getWorkflowWaitToken(request.waitTokenId);
|
|
3296
|
+
const validation = validateWorkflowHumanActionRequest({ workflowSession, waitToken, request, humanActionOptions: WORKFLOW_HUMAN_ACTION_REF_OPTIONS });
|
|
3312
3297
|
if (validation.diagnostics.length) {
|
|
3313
|
-
const responseWaitToken = waitToken && validation.expiredAt
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
piboSessionId: session.id,
|
|
3317
|
-
workflowRunId: projectSession.workflowRunId,
|
|
3318
|
-
waitTokenId: waitToken.id,
|
|
3319
|
-
resolvedAt: validation.checkedAt,
|
|
3320
|
-
}).waitToken
|
|
3321
|
-
: waitToken;
|
|
3322
|
-
recordWorkflowLifecycleEvent(input.state, input.webSession, {
|
|
3323
|
-
type: "workflow.human_action.submitted",
|
|
3324
|
-
workflowId: projectSession.workflowId,
|
|
3325
|
-
...(projectSession.workflowVersion ? { workflowVersion: projectSession.workflowVersion } : {}),
|
|
3326
|
-
projectId: project.id,
|
|
3327
|
-
piboSessionId: session.id,
|
|
3328
|
-
workflowRunId: projectSession.workflowRunId,
|
|
3329
|
-
status: "blocked",
|
|
3330
|
-
diagnostics: validation.diagnostics,
|
|
3331
|
-
payload: projectWorkflowHumanActionLifecyclePayload(request),
|
|
3332
|
-
});
|
|
3333
|
-
return projectWorkflowHumanActionDiagnosticResponse("Human action was rejected by wait-token validation", validation.diagnostics, validation.httpStatus, responseWaitToken, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3298
|
+
const responseWaitToken = waitToken && validation.expiredAt ? input.state.workflowService.expireWorkflowWaitToken({ piboSessionId: input.piboSessionId, workflowRunId: workflowSession.workflowRunId, waitTokenId: waitToken.id, resolvedAt: validation.checkedAt }).waitToken : waitToken;
|
|
3299
|
+
recordWorkflowLifecycleEvent(input.state, input.webSession, { type: "workflow.human_action.submitted", workflowId: workflowSession.workflowId, workflowVersion: workflowSession.workflowVersion, piboSessionId: input.piboSessionId, workflowRunId: workflowSession.workflowRunId, status: "blocked", diagnostics: validation.diagnostics, payload: workflowHumanActionLifecyclePayload(request) });
|
|
3300
|
+
return workflowHumanActionDiagnosticResponse("Human action was rejected by wait-token validation", validation.diagnostics, validation.httpStatus, responseWaitToken, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3334
3301
|
}
|
|
3335
3302
|
try {
|
|
3336
|
-
const result = input.state.
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
workflowRunId: projectSession.workflowRunId,
|
|
3340
|
-
waitTokenId: request.waitTokenId,
|
|
3341
|
-
...(validation.actionRef?.id ? { actionId: validation.actionRef.id } : {}),
|
|
3342
|
-
kind: validation.actionKind,
|
|
3343
|
-
actor: {
|
|
3344
|
-
userId: input.webSession.authSession.identity.userId,
|
|
3345
|
-
...(input.webSession.authSession.identity.email ? { email: input.webSession.authSession.identity.email } : {}),
|
|
3346
|
-
},
|
|
3347
|
-
...(request.payload !== undefined ? { payload: request.payload } : {}),
|
|
3348
|
-
});
|
|
3349
|
-
const enrichedProjectSession = enrichProjectSessionWorkflowWaitTokens(input.state, enrichProjectSessionWorkflowDefinitionLink(input.state, result.projectSession));
|
|
3350
|
-
recordWorkflowLifecycleEvent(input.state, input.webSession, {
|
|
3351
|
-
type: "workflow.human_action.submitted",
|
|
3352
|
-
workflowId: result.projectSession.workflowId,
|
|
3353
|
-
...(result.projectSession.workflowVersion ? { workflowVersion: result.projectSession.workflowVersion } : {}),
|
|
3354
|
-
projectId: project.id,
|
|
3355
|
-
piboSessionId: session.id,
|
|
3356
|
-
workflowRunId: result.run.id,
|
|
3357
|
-
status: "submitted",
|
|
3358
|
-
diagnostics: [],
|
|
3359
|
-
payload: projectWorkflowHumanActionSubmittedLifecyclePayload(result.waitToken.id, result.action),
|
|
3360
|
-
});
|
|
3361
|
-
return responseJson({
|
|
3362
|
-
ok: true,
|
|
3363
|
-
projectSession: enrichedProjectSession,
|
|
3364
|
-
waitToken: result.waitToken,
|
|
3365
|
-
action: result.action,
|
|
3366
|
-
run: result.run,
|
|
3367
|
-
diagnostics: [],
|
|
3368
|
-
}, { status: result.action.kind === "cancel" ? 200 : 202 });
|
|
3303
|
+
const result = input.state.workflowService.resolveWorkflowHumanAction({ piboSessionId: input.piboSessionId, workflowRunId: workflowSession.workflowRunId, waitTokenId: request.waitTokenId, ...(validation.actionRef?.id ? { actionId: validation.actionRef.id } : {}), kind: validation.actionKind, actor: { userId: input.webSession.authSession.identity.userId, ...(input.webSession.authSession.identity.email ? { email: input.webSession.authSession.identity.email } : {}) }, ...(request.payload !== undefined ? { payload: request.payload } : {}) });
|
|
3304
|
+
recordWorkflowLifecycleEvent(input.state, input.webSession, { type: "workflow.human_action.submitted", workflowId: result.workflowSession.workflowId, workflowVersion: result.workflowSession.workflowVersion, piboSessionId: input.piboSessionId, workflowRunId: result.run.id, status: "submitted", diagnostics: [], payload: workflowHumanActionSubmittedLifecyclePayload(result.waitToken.id, result.action) });
|
|
3305
|
+
return responseJson({ ok: true, workflowSession: enrichWorkflowSession(input.state, result.workflowSession), waitToken: result.waitToken, action: result.action, run: result.run, diagnostics: [] }, { status: result.action.kind === "cancel" ? 200 : 202 });
|
|
3369
3306
|
}
|
|
3370
3307
|
catch (error) {
|
|
3371
|
-
const diagnostics = [
|
|
3372
|
-
|
|
3373
|
-
type: "workflow.human_action.submitted",
|
|
3374
|
-
workflowId: projectSession.workflowId,
|
|
3375
|
-
...(projectSession.workflowVersion ? { workflowVersion: projectSession.workflowVersion } : {}),
|
|
3376
|
-
projectId: project.id,
|
|
3377
|
-
piboSessionId: session.id,
|
|
3378
|
-
workflowRunId: projectSession.workflowRunId,
|
|
3379
|
-
status: "blocked",
|
|
3380
|
-
diagnostics,
|
|
3381
|
-
payload: projectWorkflowHumanActionLifecyclePayload(request),
|
|
3382
|
-
});
|
|
3383
|
-
const responseWaitToken = input.state.projectService.getProjectWorkflowWaitToken(request.waitTokenId) ?? waitToken;
|
|
3384
|
-
return projectWorkflowHumanActionDiagnosticResponse("Human action was rejected by wait-token validation", diagnostics, 409, responseWaitToken, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3308
|
+
const diagnostics = [workflowHumanActionRuntimeDiagnostic(error, request.waitTokenId)];
|
|
3309
|
+
return workflowHumanActionDiagnosticResponse("Human action was rejected by wait-token validation", diagnostics, 409, input.state.workflowService.getWorkflowWaitToken(request.waitTokenId) ?? waitToken, WORKFLOW_HUMAN_ACTION_REF_OPTIONS);
|
|
3385
3310
|
}
|
|
3386
3311
|
}
|
|
3387
|
-
function isProjectWorkflowBackedSession(projectSession) {
|
|
3388
|
-
return Boolean(projectSession.workflowRunId) || projectSession.state === "workflow" || projectSession.workflowId !== "simple-chat";
|
|
3389
|
-
}
|
|
3390
3312
|
function workflowDefinitionViewerPath(workflowId, workflowVersion) {
|
|
3391
3313
|
return `${CHAT_WEB_MOUNT_PATH}/workflows/view/${encodeURIComponent(workflowId)}/${encodeURIComponent(workflowVersion)}`;
|
|
3392
3314
|
}
|
|
3393
|
-
function applyProjectSessionArchiveState(nodes, archivedBySessionId) {
|
|
3394
|
-
for (const node of nodes) {
|
|
3395
|
-
const archived = archivedBySessionId.get(node.piboSessionId);
|
|
3396
|
-
if (archived !== undefined)
|
|
3397
|
-
node.archived = archived;
|
|
3398
|
-
applyProjectSessionArchiveState(node.children, archivedBySessionId);
|
|
3399
|
-
}
|
|
3400
|
-
}
|
|
3401
|
-
async function sendProjectMessage(input) {
|
|
3402
|
-
const text = normalizeMessageText(input.body.text);
|
|
3403
|
-
const delivery = normalizeMessageDelivery(input.body.delivery);
|
|
3404
|
-
const clientTxnId = normalizeClientTxnId(input.body.clientTxnId);
|
|
3405
|
-
if (typeof input.body.piboSessionId !== "string")
|
|
3406
|
-
throw new PiboWebHttpError("Project session is required", 400);
|
|
3407
|
-
const selectedSession = requireSharedSession(input.context, input.body.piboSessionId);
|
|
3408
|
-
const projectSession = input.state.projectService.getProjectSession(selectedSession.id);
|
|
3409
|
-
if (!projectSession)
|
|
3410
|
-
throw new PiboWebHttpError("Project session not found", 404);
|
|
3411
|
-
requireSharedProject(input.state, input.webSession, projectSession.projectId);
|
|
3412
|
-
const actorId = auditActorIdFor(input.webSession);
|
|
3413
|
-
const duplicate = clientTxnId ? input.state.eventCommands.findByClientTxn(undefined, actorId, clientTxnId) : undefined;
|
|
3414
|
-
if (duplicate)
|
|
3415
|
-
return responseJson({ duplicate: true, event: duplicate });
|
|
3416
|
-
const accepted = input.state.eventCommands.appendEvent({
|
|
3417
|
-
piboSessionId: selectedSession.id,
|
|
3418
|
-
eventType: "user.message.accepted",
|
|
3419
|
-
actorType: "user",
|
|
3420
|
-
actorId,
|
|
3421
|
-
clientTxnId,
|
|
3422
|
-
retentionClass: "chat_message",
|
|
3423
|
-
payload: {
|
|
3424
|
-
type: "user.message.accepted",
|
|
3425
|
-
piboSessionId: selectedSession.id,
|
|
3426
|
-
projectId: projectSession.projectId,
|
|
3427
|
-
text,
|
|
3428
|
-
delivery,
|
|
3429
|
-
...(clientTxnId ? { clientTxnId } : {}),
|
|
3430
|
-
},
|
|
3431
|
-
});
|
|
3432
|
-
for (const listener of input.state.liveListeners)
|
|
3433
|
-
listener(accepted);
|
|
3434
|
-
const messageId = clientTxnId ?? randomUUID();
|
|
3435
|
-
try {
|
|
3436
|
-
const output = await input.context.channelContext.emit({
|
|
3437
|
-
type: "message",
|
|
3438
|
-
piboSessionId: selectedSession.id,
|
|
3439
|
-
id: messageId,
|
|
3440
|
-
text,
|
|
3441
|
-
delivery,
|
|
3442
|
-
source: "user",
|
|
3443
|
-
});
|
|
3444
|
-
return responseJson({ accepted, output });
|
|
3445
|
-
}
|
|
3446
|
-
catch (error) {
|
|
3447
|
-
if (error instanceof PiboSteeringUnavailableError || error instanceof AgentRuntimeBindingMissingError) {
|
|
3448
|
-
throw new PiboWebHttpError(error.message, 409);
|
|
3449
|
-
}
|
|
3450
|
-
throw error;
|
|
3451
|
-
}
|
|
3452
|
-
}
|
|
3453
3315
|
function startChatStreamingFixture(input) {
|
|
3454
3316
|
const requestedRoomId = typeof input.body.roomId === "string" ? input.body.roomId : undefined;
|
|
3455
3317
|
const selectedSession = resolveRequestedSession(input.state, input.context, input.webSession, input.defaultProfile, typeof input.body.piboSessionId === "string" ? input.body.piboSessionId : undefined, requestedRoomId);
|
|
@@ -3678,6 +3540,11 @@ export function createChatWebApp(options = {}) {
|
|
|
3678
3540
|
const defaultProfile = options.defaultProfile ?? "base";
|
|
3679
3541
|
const dataStore = createDataStore(options);
|
|
3680
3542
|
const reliabilityStore = createReliabilityStore(options.reliabilityStorePath);
|
|
3543
|
+
const workflowService = new ChatWorkflowSessionService(workflowStorePath(options, dataStore));
|
|
3544
|
+
if (dataStore.path !== ":memory:" && workflowService.path !== ":memory:") {
|
|
3545
|
+
migrateLegacyProjects({ dataStore, workflowService });
|
|
3546
|
+
}
|
|
3547
|
+
const workflowCatalogStore = workflowService.catalogDataStore;
|
|
3681
3548
|
const eventLoopDelay = monitorEventLoopDelay({ resolution: 20 });
|
|
3682
3549
|
eventLoopDelay.enable();
|
|
3683
3550
|
const state = {
|
|
@@ -3687,7 +3554,7 @@ export function createChatWebApp(options = {}) {
|
|
|
3687
3554
|
eventCommands: new ChatEventCommandService(dataStore),
|
|
3688
3555
|
readState: new ChatReadStateService(dataStore),
|
|
3689
3556
|
roomService: new ChatRoomService(dataStore),
|
|
3690
|
-
|
|
3557
|
+
workflowService,
|
|
3691
3558
|
agentStore: createAgentStore(options.agentStorePath),
|
|
3692
3559
|
reliabilityStore,
|
|
3693
3560
|
cronStore: createDefaultPiboCronStore({ path: options.cronStorePath }),
|
|
@@ -3713,12 +3580,12 @@ export function createChatWebApp(options = {}) {
|
|
|
3713
3580
|
globalRoot: options.userSkillGlobalRoot ?? os.homedir(),
|
|
3714
3581
|
workspaceRoot: options.userSkillWorkspaceRoot ?? process.cwd(),
|
|
3715
3582
|
}),
|
|
3716
|
-
workflowDraftStore: new ChatWorkflowDraftStore(
|
|
3717
|
-
workflowPublishedVersionStore: new ChatWorkflowPublishedVersionStore(
|
|
3718
|
-
workflowArchiveStore: new ChatWorkflowArchiveStore(
|
|
3719
|
-
workflowTombstoneStore: new ChatWorkflowTombstoneStore(
|
|
3720
|
-
workflowLifecycleEventStore: new ChatWorkflowLifecycleEventStore(
|
|
3721
|
-
workflowPromptAssetStore: new ChatWorkflowPromptAssetStore(
|
|
3583
|
+
workflowDraftStore: new ChatWorkflowDraftStore(workflowCatalogStore),
|
|
3584
|
+
workflowPublishedVersionStore: new ChatWorkflowPublishedVersionStore(workflowCatalogStore),
|
|
3585
|
+
workflowArchiveStore: new ChatWorkflowArchiveStore(workflowCatalogStore),
|
|
3586
|
+
workflowTombstoneStore: new ChatWorkflowTombstoneStore(workflowCatalogStore),
|
|
3587
|
+
workflowLifecycleEventStore: new ChatWorkflowLifecycleEventStore(workflowCatalogStore),
|
|
3588
|
+
workflowPromptAssetStore: new ChatWorkflowPromptAssetStore(workflowCatalogStore),
|
|
3722
3589
|
telemetryRetentionMaintenance: {},
|
|
3723
3590
|
integrations,
|
|
3724
3591
|
};
|
|
@@ -3739,7 +3606,7 @@ export function createChatWebApp(options = {}) {
|
|
|
3739
3606
|
state.subscribedContext = undefined;
|
|
3740
3607
|
state.eventLoopDelay.disable();
|
|
3741
3608
|
state.outputPersistenceRetries.dispose();
|
|
3742
|
-
state.
|
|
3609
|
+
state.workflowService.close();
|
|
3743
3610
|
state.agentStore.close();
|
|
3744
3611
|
state.reliabilityStore.close();
|
|
3745
3612
|
state.cronStore.close();
|
|
@@ -4000,306 +3867,66 @@ export function createChatWebApp(options = {}) {
|
|
|
4000
3867
|
if (response)
|
|
4001
3868
|
return response;
|
|
4002
3869
|
}
|
|
4003
|
-
if (url.pathname === `${CHAT_WEB_API_PREFIX}/
|
|
4004
|
-
const webSession = await requireSession(request, context);
|
|
4005
|
-
return responseJson(await buildProjectsBootstrap({
|
|
4006
|
-
state,
|
|
4007
|
-
context,
|
|
4008
|
-
webSession,
|
|
4009
|
-
defaultProfile,
|
|
4010
|
-
projectId: url.searchParams.get("projectId") || undefined,
|
|
4011
|
-
piboSessionId: url.searchParams.get("piboSessionId") || undefined,
|
|
4012
|
-
includeArchived: parseBooleanSearchParam(url, "includeArchived"),
|
|
4013
|
-
}));
|
|
4014
|
-
}
|
|
4015
|
-
if (url.pathname === `${CHAT_WEB_API_PREFIX}/projects/message` && request.method === "POST") {
|
|
4016
|
-
requireSameOriginJsonRequest(request);
|
|
4017
|
-
const webSession = await requireSession(request, context);
|
|
4018
|
-
const body = await readJsonBody(request);
|
|
4019
|
-
return sendProjectMessage({ state, context, webSession, defaultProfile, body });
|
|
4020
|
-
}
|
|
4021
|
-
if (url.pathname === `${CHAT_WEB_API_PREFIX}/projects` && request.method === "GET") {
|
|
4022
|
-
const webSession = await requireSession(request, context);
|
|
4023
|
-
return responseJson({ projects: listSharedProjects(state, webSession, { includeArchived: parseBooleanSearchParam(url, "includeArchived") }) });
|
|
4024
|
-
}
|
|
4025
|
-
if (url.pathname === `${CHAT_WEB_API_PREFIX}/projects` && request.method === "POST") {
|
|
4026
|
-
requireSameOriginJsonRequest(request);
|
|
4027
|
-
const webSession = await requireSession(request, context);
|
|
4028
|
-
const body = await readJsonBody(request);
|
|
4029
|
-
try {
|
|
4030
|
-
const project = state.projectService.createProject({
|
|
4031
|
-
name: normalizeRoomName(body.name),
|
|
4032
|
-
description: normalizeProjectDescription(body.description),
|
|
4033
|
-
projectFolder: normalizeProjectPath(body.projectFolder),
|
|
4034
|
-
createFolder: body.createFolder === true,
|
|
4035
|
-
});
|
|
4036
|
-
return responseJson({ project }, { status: 201 });
|
|
4037
|
-
}
|
|
4038
|
-
catch (error) {
|
|
4039
|
-
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
4040
|
-
}
|
|
4041
|
-
}
|
|
4042
|
-
const projectResource = projectResourcePath(url.pathname);
|
|
4043
|
-
if (projectResource && projectResource.child === undefined && request.method === "PATCH") {
|
|
3870
|
+
if (url.pathname === `${CHAT_WEB_API_PREFIX}/workflow-sessions` && request.method === "POST") {
|
|
4044
3871
|
requireSameOriginJsonRequest(request);
|
|
4045
3872
|
const webSession = await requireSession(request, context);
|
|
4046
3873
|
const body = await readJsonBody(request);
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
}
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
throw error;
|
|
4063
|
-
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
4064
|
-
}
|
|
3874
|
+
const room = typeof body.roomId === "string" && body.roomId.trim() ? requireRoom(state, body.roomId.trim(), webSession, "write") : state.roomService.ensureDefaultRoom();
|
|
3875
|
+
const workspace = body.workspace === undefined ? undefined : normalizeRoomWorkspace(body.workspace);
|
|
3876
|
+
const profile = resolveCreateSessionProfile(context, defaultProfile, body.profile);
|
|
3877
|
+
const workflow = resolveWorkflowSelection(state, body.workflowId, body.workflowVersion, { requireExplicitWorkflowId: true, requireExplicitVersion: true });
|
|
3878
|
+
const published = resolvePublishedWorkflowDefinitionForProfile(state, workflow, profile);
|
|
3879
|
+
const baseDefinition = cloneJsonObject(published.definition);
|
|
3880
|
+
const configuration = normalizeWorkflowSessionConfiguration(body, baseDefinition);
|
|
3881
|
+
const validation = validatePublishedWorkflowBoundary({ state, context, webSession, definition: baseDefinition, trigger: "before_workflow_session_creation" });
|
|
3882
|
+
recordWorkflowLifecycleEvent(state, webSession, { type: "workflow.validation.completed", workflowId: workflow.id, workflowVersion: workflow.version, status: validation.validation.ok ? "accepted" : "blocked", validation: validation.validation, diagnostics: validation.diagnostics, payload: { trigger: validation.validation.trigger, boundary: "workflow_session_creation" } });
|
|
3883
|
+
if (!validation.validation.ok)
|
|
3884
|
+
return workflowValidationBlockedResponse("Workflow version has validation errors and cannot create a Workflow Session", validation, { workflow });
|
|
3885
|
+
const created = createWorkflowSession({ state, context, room, workspace, profile, workflow, title: normalizeSessionTitle(body.title) ?? undefined, configuration });
|
|
3886
|
+
const snapshot = state.workflowService.saveWorkflowSessionSnapshot(createWorkflowSessionSnapshot({ webSession, session: created.session, workflow: published, baseDefinition, configuration, validation }));
|
|
3887
|
+
recordWorkflowLifecycleEvent(state, webSession, { type: "workflow.session.created", workflowId: workflow.id, workflowVersion: workflow.version, piboSessionId: created.session.id, status: "accepted", validation: validation.validation, diagnostics: validation.diagnostics, payload: { snapshotId: snapshot.id, profile, roomId: room.id } });
|
|
3888
|
+
return responseJson({ session: created.session, workflowSession: enrichWorkflowSession(state, created.workflowSession), workflow, configuration, snapshot, validation: validation.validation, diagnostics: validation.diagnostics }, { status: 201 });
|
|
4065
3889
|
}
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
try {
|
|
4071
|
-
const project = requireSharedProject(state, webSession, projectResource.projectId, { includeArchived: true });
|
|
4072
|
-
if (project.metadata.default === true)
|
|
4073
|
-
throw new PiboWebHttpError("Project Manager cannot be deleted", 400);
|
|
4074
|
-
return responseJson(state.projectService.deleteProject(projectResource.projectId, {
|
|
4075
|
-
confirmName: normalizeRoomDeleteConfirmation(body.confirmName),
|
|
4076
|
-
deleteFiles: body.deleteFiles === true,
|
|
4077
|
-
}));
|
|
4078
|
-
}
|
|
4079
|
-
catch (error) {
|
|
4080
|
-
if (error instanceof PiboWebHttpError)
|
|
4081
|
-
throw error;
|
|
4082
|
-
throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
|
|
4083
|
-
}
|
|
3890
|
+
const workflowResource = sessionWorkflowResource(url.pathname);
|
|
3891
|
+
if (workflowResource && workflowResource.action === undefined && request.method === "GET") {
|
|
3892
|
+
await requireSession(request, context);
|
|
3893
|
+
return responseJson(inspectWorkflowSession(state, context, workflowResource.piboSessionId));
|
|
4084
3894
|
}
|
|
4085
|
-
|
|
4086
|
-
if (workflowHumanActionResource && request.method === "POST") {
|
|
3895
|
+
if (workflowResource?.action === "human-actions" && request.method === "POST") {
|
|
4087
3896
|
requireSameOriginJsonRequest(request);
|
|
4088
3897
|
const webSession = await requireSession(request, context);
|
|
4089
|
-
|
|
4090
|
-
return submitProjectWorkflowHumanAction({
|
|
4091
|
-
state,
|
|
4092
|
-
context,
|
|
4093
|
-
webSession,
|
|
4094
|
-
projectId: workflowHumanActionResource.projectId,
|
|
4095
|
-
piboSessionId: workflowHumanActionResource.piboSessionId,
|
|
4096
|
-
body,
|
|
4097
|
-
});
|
|
3898
|
+
return submitWorkflowHumanAction({ state, context, webSession, piboSessionId: workflowResource.piboSessionId, body: await readJsonBody(request) });
|
|
4098
3899
|
}
|
|
4099
|
-
if (
|
|
3900
|
+
if (workflowResource?.action === "start" && request.method === "POST") {
|
|
4100
3901
|
requireSameOriginJsonRequest(request);
|
|
4101
3902
|
const webSession = await requireSession(request, context);
|
|
4102
|
-
const
|
|
4103
|
-
const
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
const
|
|
4107
|
-
const baseDefinition = cloneJsonObject(publishedWorkflow.definition);
|
|
4108
|
-
const configuration = normalizeProjectWorkflowSessionConfiguration(body, baseDefinition);
|
|
4109
|
-
const validation = validatePublishedWorkflowBoundary({
|
|
4110
|
-
state,
|
|
4111
|
-
context,
|
|
4112
|
-
webSession,
|
|
4113
|
-
definition: baseDefinition,
|
|
4114
|
-
trigger: "before_project_session_creation",
|
|
4115
|
-
});
|
|
4116
|
-
recordWorkflowLifecycleEvent(state, webSession, {
|
|
4117
|
-
type: "workflow.validation.completed",
|
|
4118
|
-
workflowId: workflowSelection.id,
|
|
4119
|
-
workflowVersion: workflowSelection.version,
|
|
4120
|
-
projectId: project.id,
|
|
4121
|
-
status: validation.validation.ok ? "accepted" : "blocked",
|
|
4122
|
-
validation: validation.validation,
|
|
4123
|
-
diagnostics: validation.diagnostics,
|
|
4124
|
-
payload: { trigger: validation.validation.trigger, boundary: "project_session_creation" },
|
|
4125
|
-
});
|
|
4126
|
-
if (!validation.validation.ok) {
|
|
4127
|
-
return workflowValidationBlockedResponse("Workflow version has validation errors and cannot be used to create a Project session", validation, { workflow: workflowSelection });
|
|
4128
|
-
}
|
|
4129
|
-
const session = createProjectChatSession({
|
|
4130
|
-
state,
|
|
4131
|
-
context,
|
|
4132
|
-
webSession,
|
|
4133
|
-
project,
|
|
4134
|
-
profile,
|
|
4135
|
-
workflowId: workflowSelection.id,
|
|
4136
|
-
workflowVersion: workflowSelection.version,
|
|
4137
|
-
title: normalizeSessionTitle(body.title) ?? undefined,
|
|
4138
|
-
configuredWorkflow: true,
|
|
4139
|
-
configuration,
|
|
4140
|
-
});
|
|
4141
|
-
const snapshot = state.projectService.saveWorkflowSessionSnapshot(createProjectWorkflowSessionSnapshot({
|
|
4142
|
-
webSession,
|
|
4143
|
-
project,
|
|
4144
|
-
session,
|
|
4145
|
-
workflow: publishedWorkflow,
|
|
4146
|
-
baseDefinition,
|
|
4147
|
-
configuration,
|
|
4148
|
-
validation,
|
|
4149
|
-
}));
|
|
4150
|
-
const projectSession = state.projectService.getProjectSession(session.id);
|
|
4151
|
-
recordWorkflowLifecycleEvent(state, webSession, {
|
|
4152
|
-
type: "project.workflow_session.created",
|
|
4153
|
-
workflowId: workflowSelection.id,
|
|
4154
|
-
workflowVersion: workflowSelection.version,
|
|
4155
|
-
projectId: project.id,
|
|
4156
|
-
piboSessionId: session.id,
|
|
4157
|
-
status: "accepted",
|
|
4158
|
-
validation: validation.validation,
|
|
4159
|
-
diagnostics: validation.diagnostics,
|
|
4160
|
-
payload: { snapshotId: snapshot.id, profile },
|
|
4161
|
-
});
|
|
4162
|
-
return responseJson({ session, projectSession, workflow: workflowSelection, configuration, snapshot, validation: validation.validation, diagnostics: validation.diagnostics }, { status: 201 });
|
|
4163
|
-
}
|
|
4164
|
-
const workflowSessionStart = projectWorkflowSessionStartResource(url.pathname);
|
|
4165
|
-
if (workflowSessionStart && request.method === "POST") {
|
|
4166
|
-
requireSameOriginJsonRequest(request);
|
|
4167
|
-
const webSession = await requireSession(request, context);
|
|
4168
|
-
const session = requireSharedSession(context, workflowSessionStart.piboSessionId);
|
|
4169
|
-
const project = requireSharedProject(state, webSession, workflowSessionStart.projectId);
|
|
4170
|
-
const projectSession = state.projectService.getProjectSession(session.id);
|
|
4171
|
-
if (!projectSession || projectSession.projectId !== project.id)
|
|
4172
|
-
throw new PiboWebHttpError("Project workflow session not found", 404);
|
|
4173
|
-
const snapshot = state.projectService.getWorkflowSessionSnapshotForSession(session.id);
|
|
3903
|
+
const session = requireSharedSession(context, workflowResource.piboSessionId);
|
|
3904
|
+
const workflowSession = state.workflowService.getWorkflowSession(session.id);
|
|
3905
|
+
if (!workflowSession)
|
|
3906
|
+
throw new PiboWebHttpError("Workflow session not found", 404);
|
|
3907
|
+
const snapshot = state.workflowService.getWorkflowSessionSnapshotForSession(session.id);
|
|
4174
3908
|
if (!snapshot)
|
|
4175
|
-
throw new PiboWebHttpError("
|
|
4176
|
-
const
|
|
4177
|
-
if (
|
|
4178
|
-
const
|
|
4179
|
-
if (
|
|
4180
|
-
|
|
4181
|
-
return responseJson({
|
|
4182
|
-
projectSession,
|
|
4183
|
-
workflow: workflowSelection,
|
|
4184
|
-
snapshot,
|
|
4185
|
-
run: existingRun,
|
|
4186
|
-
alreadyStarted: true,
|
|
4187
|
-
validation: existingRun.validation ?? summarizeWorkflowDiagnostics([], "before_workflow_start"),
|
|
4188
|
-
diagnostics: [],
|
|
4189
|
-
message: "Workflow run already exists for this Project session.",
|
|
4190
|
-
}, { status: 200 });
|
|
3909
|
+
throw new PiboWebHttpError("Workflow session snapshot not found", 409);
|
|
3910
|
+
const workflow = workflowVersionFromSnapshot(snapshot);
|
|
3911
|
+
if (workflowSession.workflowRunId) {
|
|
3912
|
+
const run = state.workflowService.getWorkflowRun(workflowSession.workflowRunId);
|
|
3913
|
+
if (run) {
|
|
3914
|
+
updateWorkflowRunSessionMetadata({ state, context, session, workflowRunId: run.id });
|
|
3915
|
+
return responseJson({ workflowSession: enrichWorkflowSession(state, workflowSession), run, snapshot, workflow, alreadyStarted: true, validation: run.validation ?? summarizeWorkflowDiagnostics([], "before_workflow_start"), diagnostics: [], message: "Workflow run already exists for this Workflow Session." });
|
|
4191
3916
|
}
|
|
4192
3917
|
}
|
|
4193
|
-
const validation =
|
|
4194
|
-
recordWorkflowLifecycleEvent(state, webSession, {
|
|
4195
|
-
type: "workflow.validation.completed",
|
|
4196
|
-
workflowId: workflowSelection.id,
|
|
4197
|
-
workflowVersion: workflowSelection.version,
|
|
4198
|
-
projectId: project.id,
|
|
4199
|
-
piboSessionId: session.id,
|
|
4200
|
-
workflowRunId: projectSession.workflowRunId,
|
|
4201
|
-
status: validation.validation.ok ? "accepted" : "blocked",
|
|
4202
|
-
validation: validation.validation,
|
|
4203
|
-
diagnostics: validation.diagnostics,
|
|
4204
|
-
payload: { trigger: validation.validation.trigger, boundary: "workflow_start", snapshotId: snapshot.id },
|
|
4205
|
-
});
|
|
3918
|
+
const validation = validateWorkflowSnapshotForStart(snapshot, { state, context, webSession });
|
|
3919
|
+
recordWorkflowLifecycleEvent(state, webSession, { type: "workflow.validation.completed", workflowId: workflow.id, workflowVersion: workflow.version, piboSessionId: session.id, workflowRunId: workflowSession.workflowRunId, status: validation.validation.ok ? "accepted" : "blocked", validation: validation.validation, diagnostics: validation.diagnostics, payload: { trigger: validation.validation.trigger, boundary: "workflow_start", snapshotId: snapshot.id } });
|
|
4206
3920
|
if (!validation.validation.ok) {
|
|
4207
|
-
recordWorkflowLifecycleEvent(state, webSession, {
|
|
4208
|
-
|
|
4209
|
-
workflowId: workflowSelection.id,
|
|
4210
|
-
workflowVersion: workflowSelection.version,
|
|
4211
|
-
projectId: project.id,
|
|
4212
|
-
piboSessionId: session.id,
|
|
4213
|
-
workflowRunId: projectSession.workflowRunId,
|
|
4214
|
-
status: "blocked",
|
|
4215
|
-
validation: validation.validation,
|
|
4216
|
-
diagnostics: validation.diagnostics,
|
|
4217
|
-
payload: { snapshotId: snapshot.id, profile: session.profile },
|
|
4218
|
-
});
|
|
4219
|
-
return workflowValidationBlockedResponse("Workflow session has validation errors and cannot be started", validation, { projectSession, workflow: workflowSelection });
|
|
4220
|
-
}
|
|
4221
|
-
const startResult = state.projectService.startWorkflowSessionRun({
|
|
4222
|
-
projectId: project.id,
|
|
4223
|
-
piboSessionId: session.id,
|
|
4224
|
-
runId: `wfr_${randomUUID()}`,
|
|
4225
|
-
workflowId: snapshot.workflow.id,
|
|
4226
|
-
workflowVersion: snapshot.workflow.version,
|
|
4227
|
-
snapshotId: snapshot.id,
|
|
4228
|
-
effectiveDefinitionHash: snapshot.workflow.effectiveDefinitionHash,
|
|
4229
|
-
current: createProjectWorkflowRunCurrent(snapshot.effectiveDefinition),
|
|
4230
|
-
inputValues: snapshot.inputValues,
|
|
4231
|
-
validation: validation.validation,
|
|
4232
|
-
});
|
|
4233
|
-
updateProjectWorkflowRunSessionMetadata({ state, context, session, workflowRunId: startResult.run.id });
|
|
4234
|
-
recordWorkflowLifecycleEvent(state, webSession, {
|
|
4235
|
-
type: "project.workflow_start.accepted",
|
|
4236
|
-
workflowId: workflowSelection.id,
|
|
4237
|
-
workflowVersion: workflowSelection.version,
|
|
4238
|
-
projectId: project.id,
|
|
4239
|
-
piboSessionId: session.id,
|
|
4240
|
-
workflowRunId: startResult.run.id,
|
|
4241
|
-
status: "accepted",
|
|
4242
|
-
validation: validation.validation,
|
|
4243
|
-
diagnostics: validation.diagnostics,
|
|
4244
|
-
payload: { snapshotId: snapshot.id, profile: session.profile, alreadyStarted: startResult.alreadyStarted },
|
|
4245
|
-
});
|
|
4246
|
-
if (!startResult.alreadyStarted) {
|
|
4247
|
-
recordWorkflowLifecycleEvent(state, webSession, {
|
|
4248
|
-
type: "workflow.run.status_changed",
|
|
4249
|
-
workflowId: workflowSelection.id,
|
|
4250
|
-
workflowVersion: workflowSelection.version,
|
|
4251
|
-
projectId: project.id,
|
|
4252
|
-
piboSessionId: session.id,
|
|
4253
|
-
workflowRunId: startResult.run.id,
|
|
4254
|
-
status: "changed",
|
|
4255
|
-
validation: validation.validation,
|
|
4256
|
-
diagnostics: validation.diagnostics,
|
|
4257
|
-
payload: { snapshotId: snapshot.id, state: startResult.run.status, current: startResult.run.current },
|
|
4258
|
-
});
|
|
4259
|
-
}
|
|
4260
|
-
return responseJson({
|
|
4261
|
-
projectSession: startResult.projectSession,
|
|
4262
|
-
workflow: workflowSelection,
|
|
4263
|
-
snapshot,
|
|
4264
|
-
run: startResult.run,
|
|
4265
|
-
alreadyStarted: startResult.alreadyStarted,
|
|
4266
|
-
validation: validation.validation,
|
|
4267
|
-
diagnostics: validation.diagnostics,
|
|
4268
|
-
message: startResult.alreadyStarted ? "Workflow run already exists for this Project session." : "Workflow run started.",
|
|
4269
|
-
}, { status: startResult.alreadyStarted ? 200 : 202 });
|
|
4270
|
-
}
|
|
4271
|
-
if (projectResource && projectResource.child === "sessions" && request.method === "POST") {
|
|
4272
|
-
requireSameOriginJsonRequest(request);
|
|
4273
|
-
const webSession = await requireSession(request, context);
|
|
4274
|
-
const body = await readJsonBody(request);
|
|
4275
|
-
const project = requireSharedProject(state, webSession, projectResource.projectId);
|
|
4276
|
-
const profile = resolveCreateSessionProfile(context, defaultProfile, body.profile);
|
|
4277
|
-
const workflowId = normalizeLegacyProjectWorkflowId(body.workflowId);
|
|
4278
|
-
const session = createProjectChatSession({ state, context, webSession, project, profile, workflowId });
|
|
4279
|
-
return responseJson({ session, projectSession: state.projectService.getProjectSession(session.id) }, { status: 201 });
|
|
4280
|
-
}
|
|
4281
|
-
const projectSessionId = projectSessionResourceId(url.pathname);
|
|
4282
|
-
if (projectSessionId && request.method === "PATCH") {
|
|
4283
|
-
requireSameOriginJsonRequest(request);
|
|
4284
|
-
const webSession = await requireSession(request, context);
|
|
4285
|
-
const selectedSession = resolveRequestedSession(state, context, webSession, defaultProfile, projectSessionId);
|
|
4286
|
-
const body = await readJsonBody(request);
|
|
4287
|
-
assertProjectSessionPatchFields(body);
|
|
4288
|
-
const updateSession = context.channelContext.updateSession;
|
|
4289
|
-
if (!updateSession)
|
|
4290
|
-
throw new PiboWebHttpError("Session updates are not available", 501);
|
|
4291
|
-
const title = normalizeSessionTitle(body.title);
|
|
4292
|
-
let updated = selectedSession;
|
|
4293
|
-
if (title !== undefined) {
|
|
4294
|
-
const next = updateSession(selectedSession.id, { title });
|
|
4295
|
-
if (!next)
|
|
4296
|
-
throw new PiboWebHttpError("Session not found", 404);
|
|
4297
|
-
updated = next;
|
|
4298
|
-
state.sessionQuery.upsertSession(updated);
|
|
3921
|
+
recordWorkflowLifecycleEvent(state, webSession, { type: "workflow.start.blocked", workflowId: workflow.id, workflowVersion: workflow.version, piboSessionId: session.id, status: "blocked", validation: validation.validation, diagnostics: validation.diagnostics, payload: { snapshotId: snapshot.id, profile: session.profile } });
|
|
3922
|
+
return workflowValidationBlockedResponse("Workflow Session has validation errors and cannot be started", validation, { workflowSession, workflow });
|
|
4299
3923
|
}
|
|
4300
|
-
const
|
|
4301
|
-
|
|
4302
|
-
|
|
3924
|
+
const started = state.workflowService.startWorkflowSessionRun({ piboSessionId: session.id, runId: `wfr_${randomUUID()}`, workflowId: snapshot.workflow.id, workflowVersion: snapshot.workflow.version, snapshotId: snapshot.id, effectiveDefinitionHash: snapshot.workflow.effectiveDefinitionHash, current: createWorkflowRunCurrent(snapshot.effectiveDefinition), inputValues: snapshot.inputValues, validation: validation.validation });
|
|
3925
|
+
updateWorkflowRunSessionMetadata({ state, context, session, workflowRunId: started.run.id });
|
|
3926
|
+
recordWorkflowLifecycleEvent(state, webSession, { type: "workflow.start.accepted", workflowId: workflow.id, workflowVersion: workflow.version, piboSessionId: session.id, workflowRunId: started.run.id, status: "accepted", validation: validation.validation, diagnostics: validation.diagnostics, payload: { snapshotId: snapshot.id, profile: session.profile, alreadyStarted: started.alreadyStarted } });
|
|
3927
|
+
if (!started.alreadyStarted)
|
|
3928
|
+
recordWorkflowLifecycleEvent(state, webSession, { type: "workflow.run.status_changed", workflowId: workflow.id, workflowVersion: workflow.version, piboSessionId: session.id, workflowRunId: started.run.id, status: "changed", validation: validation.validation, diagnostics: validation.diagnostics, payload: { snapshotId: snapshot.id, state: started.run.status, current: started.run.current } });
|
|
3929
|
+
return responseJson({ workflowSession: enrichWorkflowSession(state, started.workflowSession), run: started.run, snapshot, workflow, alreadyStarted: started.alreadyStarted, validation: validation.validation, diagnostics: validation.diagnostics, message: started.alreadyStarted ? "Workflow run already exists for this Workflow Session." : "Workflow run recorded. General graph execution is not connected to this surface; supported manual triggers run from the editor." }, { status: started.alreadyStarted ? 200 : 202 });
|
|
4303
3930
|
}
|
|
4304
3931
|
if (url.pathname === `${CHAT_WEB_API_PREFIX}/signals/statuses` && request.method === "GET") {
|
|
4305
3932
|
await requireSession(request, context);
|
|
@@ -4475,6 +4102,7 @@ export function createChatWebApp(options = {}) {
|
|
|
4475
4102
|
});
|
|
4476
4103
|
return workflowValidationBlockedResponse("Workflow draft has validation errors and cannot be test-run", validation, { draft: serializeWorkflowDraft(record) });
|
|
4477
4104
|
}
|
|
4105
|
+
const room = body.roomId ? requireRoom(state, body.roomId, webSession, "write") : state.roomService.ensureDefaultRoom();
|
|
4478
4106
|
const result = await runWorkflowManualTextTrigger({
|
|
4479
4107
|
definition: record.definition,
|
|
4480
4108
|
triggerNodeId: body.triggerNodeId,
|
|
@@ -4483,11 +4111,31 @@ export function createChatWebApp(options = {}) {
|
|
|
4483
4111
|
draftId: record.draftId,
|
|
4484
4112
|
channelContext: context.channelContext,
|
|
4485
4113
|
channel: CHAT_WEB_CHANNEL,
|
|
4486
|
-
|
|
4114
|
+
roomId: room.id,
|
|
4115
|
+
defaultWorkspace: body.workspace ?? room.workspace ?? getDefaultPiboWorkspace(),
|
|
4487
4116
|
onSessionCreated: (session) => state.sessionQuery.upsertSession(session),
|
|
4488
4117
|
resolveProfile: (profileId) => resolveWorkflowRuntimeProfile({ context, requestedId: profileId }),
|
|
4489
4118
|
});
|
|
4490
4119
|
const diagnostics = result.ok ? validation.diagnostics : sanitizeWorkflowDiagnostics([...validation.diagnostics, ...result.diagnostics]);
|
|
4120
|
+
if (result.run) {
|
|
4121
|
+
const run = result.run;
|
|
4122
|
+
const store = state.workflowService.runtimeStore;
|
|
4123
|
+
store.transaction(() => {
|
|
4124
|
+
const hash = hashWorkflowDefinitionJson(record.definition);
|
|
4125
|
+
const existing = store.listDefinitionSnapshots({ workflowId: run.workflowId, workflowVersion: run.workflowVersion, hash, limit: 1 })[0];
|
|
4126
|
+
const definitionSnapshotId = existing?.id ?? `wfds_${run.id}`;
|
|
4127
|
+
if (!existing)
|
|
4128
|
+
store.saveDefinitionSnapshot({ id: definitionSnapshotId, workflowId: run.workflowId, workflowVersion: run.workflowVersion, hash, definition: record.definition, createdAt: run.createdAt });
|
|
4129
|
+
store.saveRun({ ...run, piboSessionId: result.nodeAttempts.find((attempt) => attempt.piboSessionId)?.piboSessionId, definitionSnapshotId, workflowDefinitionHash: hash, current: { status: run.status, nodeId: result.nodeAttempts.at(-1)?.nodeId }, state: { global: {} } });
|
|
4130
|
+
for (const attempt of result.nodeAttempts) {
|
|
4131
|
+
store.saveNodeAttempt({ ...attempt, attempt: 1 });
|
|
4132
|
+
if (attempt.piboSessionId)
|
|
4133
|
+
state.workflowService.addWorkflowSession({ piboSessionId: attempt.piboSessionId, workflowId: run.workflowId, workflowVersion: run.workflowVersion, workflowRunId: run.id, state: run.status });
|
|
4134
|
+
}
|
|
4135
|
+
for (const transfer of result.edgeTransfers)
|
|
4136
|
+
store.saveEdgeTransfer(transfer);
|
|
4137
|
+
});
|
|
4138
|
+
}
|
|
4491
4139
|
recordWorkflowLifecycleEvent(state, webSession, {
|
|
4492
4140
|
type: result.ok ? "workflow.editor_test_run.completed" : "workflow.editor_test_run.failed",
|
|
4493
4141
|
workflowId: record.workflowId,
|
|
@@ -4624,13 +4272,12 @@ export function createChatWebApp(options = {}) {
|
|
|
4624
4272
|
return responseJson(archiveWorkflowIdentity(state, context, webSession, archiveWorkflowId, body.reason));
|
|
4625
4273
|
}
|
|
4626
4274
|
if (url.pathname === `${CHAT_WEB_API_PREFIX}/workflows/lifecycle-events` && request.method === "GET") {
|
|
4627
|
-
|
|
4275
|
+
await requireSession(request, context);
|
|
4628
4276
|
return responseJson({
|
|
4629
4277
|
events: state.workflowLifecycleEventStore.listEvents({
|
|
4630
4278
|
type: url.searchParams.get("type") ?? undefined,
|
|
4631
4279
|
workflowId: url.searchParams.get("workflowId") ?? undefined,
|
|
4632
4280
|
draftId: url.searchParams.get("draftId") ?? undefined,
|
|
4633
|
-
projectId: url.searchParams.get("projectId") ?? undefined,
|
|
4634
4281
|
piboSessionId: url.searchParams.get("piboSessionId") ?? undefined,
|
|
4635
4282
|
workflowRunId: url.searchParams.get("workflowRunId") ?? undefined,
|
|
4636
4283
|
limit: parsePositiveIntSearchParam(url, "limit", 100, 500),
|
|
@@ -4942,12 +4589,42 @@ export function createChatWebApp(options = {}) {
|
|
|
4942
4589
|
sessions: await buildSessionNodes(ownedSessions, state.sessionQuery.listSessions(), process.cwd(), new Map(), sessionNodeHistoryOptions(context)),
|
|
4943
4590
|
});
|
|
4944
4591
|
}
|
|
4592
|
+
if (roomResource?.child === "order" && request.method === "PATCH") {
|
|
4593
|
+
requireSameOriginJsonRequest(request);
|
|
4594
|
+
const webSession = await requireSession(request, context);
|
|
4595
|
+
const room = requireRoom(state, roomResource.roomId, webSession, "admin");
|
|
4596
|
+
const body = await readJsonBody(request);
|
|
4597
|
+
if (typeof body.targetRoomId !== "string" || !body.targetRoomId) {
|
|
4598
|
+
throw new PiboWebHttpError("targetRoomId is required", 400);
|
|
4599
|
+
}
|
|
4600
|
+
if (body.position !== "before" && body.position !== "after") {
|
|
4601
|
+
throw new PiboWebHttpError("position must be before or after", 400);
|
|
4602
|
+
}
|
|
4603
|
+
const targetRoom = requireRoom(state, body.targetRoomId, webSession, "admin");
|
|
4604
|
+
return responseJson({
|
|
4605
|
+
orderedRoomIds: reorderChatWebRoom({ state, room, targetRoom, position: body.position }),
|
|
4606
|
+
});
|
|
4607
|
+
}
|
|
4945
4608
|
if (roomResource && roomResource.child === undefined && request.method === "PATCH") {
|
|
4946
4609
|
requireSameOriginJsonRequest(request);
|
|
4947
4610
|
const webSession = await requireSession(request, context);
|
|
4948
4611
|
const existingRoom = requireRoom(state, roomResource.roomId, webSession, "admin");
|
|
4949
4612
|
const body = await readJsonBody(request);
|
|
4613
|
+
if (body.pinned !== undefined && existingRoom.parentRoomId) {
|
|
4614
|
+
throw new PiboWebHttpError("Only top-level rooms can be pinned", 400);
|
|
4615
|
+
}
|
|
4616
|
+
if (body.pinned === true && (body.archived === true || isPiboRoomArchived(existingRoom))) {
|
|
4617
|
+
throw new PiboWebHttpError("Archived rooms cannot be pinned", 400);
|
|
4618
|
+
}
|
|
4950
4619
|
const update = createRoomUpdate(existingRoom, body);
|
|
4620
|
+
if (typeof body.pinned === "boolean") {
|
|
4621
|
+
const targetGroup = state.roomService.listRooms().filter((room) => !room.parentRoomId
|
|
4622
|
+
&& !isDefaultPiboRoom(room)
|
|
4623
|
+
&& !isPiboRoomArchived(room)
|
|
4624
|
+
&& room.id !== existingRoom.id
|
|
4625
|
+
&& isPiboRoomPinned(room) === body.pinned);
|
|
4626
|
+
update.metadata = withPiboRoomPinned(update.metadata ?? existingRoom.metadata, body.pinned, nextChatWebRoomSidebarOrder(targetGroup));
|
|
4627
|
+
}
|
|
4951
4628
|
if (update.parentRoomId)
|
|
4952
4629
|
requireRoom(state, update.parentRoomId, webSession, "admin");
|
|
4953
4630
|
let room;
|
|
@@ -5082,6 +4759,28 @@ export function createChatWebApp(options = {}) {
|
|
|
5082
4759
|
throw new PiboWebHttpError(message, status);
|
|
5083
4760
|
}
|
|
5084
4761
|
}
|
|
4762
|
+
if (sessionAction?.action === "order" && request.method === "PATCH") {
|
|
4763
|
+
requireSameOriginJsonRequest(request);
|
|
4764
|
+
const webSession = await requireSession(request, context);
|
|
4765
|
+
const selectedSession = resolveRequestedSession(state, context, webSession, defaultProfile, sessionAction.piboSessionId);
|
|
4766
|
+
const body = await readJsonBody(request);
|
|
4767
|
+
if (typeof body.targetPiboSessionId !== "string" || !body.targetPiboSessionId) {
|
|
4768
|
+
throw new PiboWebHttpError("targetPiboSessionId is required", 400);
|
|
4769
|
+
}
|
|
4770
|
+
if (body.position !== "before" && body.position !== "after") {
|
|
4771
|
+
throw new PiboWebHttpError("position must be before or after", 400);
|
|
4772
|
+
}
|
|
4773
|
+
const targetSession = resolveRequestedSession(state, context, webSession, defaultProfile, body.targetPiboSessionId);
|
|
4774
|
+
return responseJson({
|
|
4775
|
+
orderedSessionIds: reorderChatWebSession({
|
|
4776
|
+
state,
|
|
4777
|
+
context,
|
|
4778
|
+
session: selectedSession,
|
|
4779
|
+
targetSession,
|
|
4780
|
+
position: body.position,
|
|
4781
|
+
}),
|
|
4782
|
+
});
|
|
4783
|
+
}
|
|
5085
4784
|
const patchSessionId = sessionResourceId(url.pathname);
|
|
5086
4785
|
if (patchSessionId && request.method === "PATCH") {
|
|
5087
4786
|
requireSameOriginJsonRequest(request);
|
|
@@ -5095,7 +4794,23 @@ export function createChatWebApp(options = {}) {
|
|
|
5095
4794
|
if (body.profile !== undefined && (state.activeTraceSessions.has(selectedSession.id) || state.sessionQuery.hasSessionActivity(selectedSession.id))) {
|
|
5096
4795
|
throw new PiboWebHttpError("Session profile can only be changed before the first message.", 400);
|
|
5097
4796
|
}
|
|
4797
|
+
if (body.pinned !== undefined && selectedSession.parentId) {
|
|
4798
|
+
throw new PiboWebHttpError("Only top-level sessions can be pinned", 400);
|
|
4799
|
+
}
|
|
4800
|
+
if (body.pinned === true && (body.archived === true || isChatWebSessionArchived(selectedSession))) {
|
|
4801
|
+
throw new PiboWebHttpError("Archived sessions cannot be pinned", 400);
|
|
4802
|
+
}
|
|
5098
4803
|
const update = createSessionUpdate(context, selectedSession, body);
|
|
4804
|
+
if (typeof body.pinned === "boolean") {
|
|
4805
|
+
const roomId = chatRoomIdFromMetadata(selectedSession.metadata);
|
|
4806
|
+
const targetGroup = roomId
|
|
4807
|
+
? sessionsInRoom(listSharedSessions(context), roomId).filter((session) => !session.parentId
|
|
4808
|
+
&& !isChatWebSessionArchived(session)
|
|
4809
|
+
&& session.id !== selectedSession.id
|
|
4810
|
+
&& isChatWebSessionPinned(session) === body.pinned)
|
|
4811
|
+
: [];
|
|
4812
|
+
update.metadata = withChatWebSessionPinned(update.metadata ?? selectedSession.metadata, body.pinned, nextChatWebSessionSidebarOrder(targetGroup));
|
|
4813
|
+
}
|
|
5099
4814
|
if ("activeModel" in update) {
|
|
5100
4815
|
try {
|
|
5101
4816
|
await context.channelContext.setLiveSessionActiveModel?.(selectedSession.id, update.activeModel ?? undefined);
|
|
@@ -5709,17 +5424,6 @@ export function createChatWebApp(options = {}) {
|
|
|
5709
5424
|
const selectedSession = resolveRequestedSession(state, context, webSession, defaultProfile, requestedPiboSessionId, requestedRoomId);
|
|
5710
5425
|
const cursor = parseSseCursor(url.searchParams.get("since")) ?? parseSseCursor(request.headers.get("last-event-id"));
|
|
5711
5426
|
const transientReplayCursor = parseTransientReplayCursor(url.searchParams.get("liveSince"));
|
|
5712
|
-
if (!requestedRoomId && state.projectService.getProjectSession(selectedSession.id)) {
|
|
5713
|
-
return createEventStream({
|
|
5714
|
-
piboSessionId: selectedSession.id,
|
|
5715
|
-
activePiboSessionId: selectedSession.id,
|
|
5716
|
-
mode: streamMode,
|
|
5717
|
-
context,
|
|
5718
|
-
state,
|
|
5719
|
-
cursor,
|
|
5720
|
-
transientReplayCursor,
|
|
5721
|
-
});
|
|
5722
|
-
}
|
|
5723
5427
|
const roomId = requestedRoomId ?? selectedRoomIdForSession(state, context, selectedSession);
|
|
5724
5428
|
requireRoom(state, roomId, webSession, "read");
|
|
5725
5429
|
const streamPiboSessionId = requestedPiboSessionId || !requestedRoomId ? selectedSession.id : undefined;
|