@opengeni/db 1.0.1 → 3.1.0-canary.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/attached-browser-devices.d.ts +7 -0
- package/dist/automations.d.ts +154 -0
- package/dist/canonical-human-identities.js +3 -3
- package/dist/capability-integrations.d.ts +13 -0
- package/dist/child-lifecycle-notices.d.ts +68 -0
- package/dist/{chunk-LTG3S6ZY.js → chunk-EULAN2NP.js} +2 -2
- package/dist/{chunk-CUPM3FGB.js → chunk-NJVZPWXY.js} +3 -3
- package/dist/{chunk-4SR4HKKA.js → chunk-NMUBV7Z5.js} +19 -11
- package/dist/chunk-NMUBV7Z5.js.map +1 -0
- package/dist/chunk-OF5OBB76.js +4457 -0
- package/dist/chunk-OF5OBB76.js.map +1 -0
- package/dist/{chunk-6ZYKCRFO.js → chunk-PR2WMLOQ.js} +7580 -4417
- package/dist/chunk-PR2WMLOQ.js.map +1 -0
- package/dist/{chunk-ZWREYEWA.js → chunk-SCPUJS53.js} +41 -4
- package/dist/chunk-SCPUJS53.js.map +1 -0
- package/dist/{chunk-SK7YYHBI.js → chunk-SIBYBA2D.js} +46 -1
- package/dist/chunk-SIBYBA2D.js.map +1 -0
- package/dist/chunk-TIKF3KTI.js +383 -0
- package/dist/chunk-TIKF3KTI.js.map +1 -0
- package/dist/chunk-ZZ5LJEFX.js +516 -0
- package/dist/chunk-ZZ5LJEFX.js.map +1 -0
- package/dist/codemode-operations.d.ts +1 -6
- package/dist/company-brain-context-selection-schema.d.ts +705 -0
- package/dist/company-brain-context-selection.d.ts +94 -0
- package/dist/company-brain-governed-writes.d.ts +24 -0
- package/dist/company-brain.d.ts +55 -0
- package/dist/company-profile-agent-admin.d.ts +15 -0
- package/dist/company-profile-schema.d.ts +619 -2
- package/dist/company-profile.d.ts +9 -4
- package/dist/connection-authority.d.ts +95 -0
- package/dist/connection-scopes.d.ts +8 -0
- package/dist/connection-tenancy-backfill.d.ts +41 -0
- package/dist/connection-token-resolver.d.ts +30 -1
- package/dist/database.d.ts +19 -0
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.d.ts +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation-schema.d.ts +984 -0
- package/dist/governed-learning-activation.d.ts +98 -0
- package/dist/governed-learning-evaluator-schema.d.ts +633 -0
- package/dist/governed-learning-evaluator.d.ts +28 -0
- package/dist/index.d.ts +1595 -81
- package/dist/index.js +21571 -8126
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +18 -0
- package/dist/integration-bindings.d.ts +1 -0
- package/dist/integration-facets.d.ts +30 -0
- package/dist/interaction-placement-loss.d.ts +22 -0
- package/dist/managed-human-provisioning.d.ts +25 -0
- package/dist/memory-domain.d.ts +3 -3
- package/dist/migrate.d.ts +11 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +43 -5
- package/dist/organization-membership-backfill.d.ts +174 -0
- package/dist/organization-membership-lifecycle.d.ts +162 -0
- package/dist/pr-review.d.ts +107 -0
- package/dist/preference-registry-schema.d.ts +2 -0
- package/dist/preference-registry.d.ts +2 -0
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +22 -8
- package/dist/schema.d.ts +24914 -13703
- package/dist/schema.js +99 -1
- package/dist/scoped-knowledge-schema.d.ts +52 -1
- package/dist/session-background-commands.d.ts +125 -0
- package/dist/session-background-commands.js +34 -0
- package/dist/session-background-commands.js.map +1 -0
- package/dist/session-control.d.ts +156 -3
- package/dist/session-goal-pacing.d.ts +68 -0
- package/dist/session-queue-commands.d.ts +41 -4
- package/dist/session-realtime-ledger.d.ts +2 -0
- package/dist/session-tenancy.d.ts +71 -1
- package/dist/session-tenancy.js +25 -3
- package/dist/session-tool-call-settlement.d.ts +9 -4
- package/dist/slack-routing-personal-workspace.d.ts +23 -0
- package/dist/slack-routing.d.ts +153 -0
- package/dist/slack-task-policy-schema.d.ts +34 -0
- package/dist/slack-task-policy.d.ts +8 -0
- package/dist/slack-user-link-access.d.ts +1 -0
- package/dist/task-notes-schema.d.ts +594 -0
- package/dist/task-notes.d.ts +39 -0
- package/dist/turn-initiator.d.ts +2 -0
- package/dist/user-resource-authority.d.ts +109 -0
- package/dist/video-generation.js +3 -3
- package/dist/workspace-authority.d.ts +81 -0
- package/dist/workspace-instruction-policies-schema.d.ts +279 -0
- package/dist/workspace-instruction-policies.d.ts +62 -0
- package/dist/workspace-learning-policy.d.ts +1 -0
- package/dist/workspace-membership-permissions.d.ts +2 -0
- package/drizzle/0240_enrollment_connection_authority.sql +39 -0
- package/drizzle/0241_atomic_personal_resource_delegation.sql +1000 -0
- package/drizzle/0241_enrollment_agent_runtime.sql +70 -0
- package/drizzle/0244_slack_app_home_refresh_queue.sql +120 -0
- package/drizzle/0245_model_context_contribution_facts.sql +88 -0
- package/drizzle/0246_integration_personal_instance_authority.sql +70 -0
- package/drizzle/0247_terraform_stacks_provenance_repair.sql +428 -0
- package/drizzle/0248_terraform_stacks_component_resolution_fence.sql +83 -0
- package/drizzle/0249_personal_resource_delegation_authority_correction.sql +662 -0
- package/drizzle/0250_direct_retained_process_owner_liveness.sql +199 -0
- package/drizzle/0251_connected_machine_operation_policy.sql +45 -0
- package/drizzle/0252_scheduled_personal_resource_delegation.sql +1867 -0
- package/drizzle/0253_common_user_resource_authority_lifecycle.sql +1555 -0
- package/drizzle/0254_scoped_variable_set_authority.sql +1255 -0
- package/drizzle/0255_company_brain_governed_write_proposals.sql +524 -0
- package/drizzle/0256_connection_authority_delegation.sql +703 -0
- package/drizzle/0257_goal_revision_decisions_and_root_constraints.sql +436 -0
- package/drizzle/0258_three_scope_document_knowledge_authority.sql +1273 -0
- package/drizzle/0259_company_brain_context_selection_receipts.sql +869 -0
- package/drizzle/0260_task_note_knowledge_promotion.sql +820 -0
- package/drizzle/0261_preference_knowledge_proposal_actor_binding.sql +471 -0
- package/drizzle/0262_scoped_connected_machines_and_rigs.sql +1700 -0
- package/drizzle/0263_organization_membership_lifecycle.sql +3284 -0
- package/drizzle/0264_connection_authority_runtime_activation.sql +1084 -0
- package/drizzle/0266_company_brain_context_receipt_inspection.sql +156 -0
- package/drizzle/0268_governed_learning_decision_receipts.sql +825 -0
- package/drizzle/0269_governed_learning_activation_controller.sql +1874 -0
- package/drizzle/0270_governed_learning_history_inspection.sql +170 -0
- package/drizzle/0271_company_brain_retrieval_only_default.sql +524 -0
- package/drizzle/0272_human_confirmed_learning_activation.sql +591 -0
- package/drizzle/0273_scheduled_variable_set_materialization.sql +268 -0
- package/drizzle/0274_human_confirmed_knowledge_review.sql +310 -0
- package/drizzle/0275_scheduled_connection_authority.sql +5527 -0
- package/drizzle/0276_onboarding_proposal_initiating_human_guc.sql +198 -0
- package/drizzle/0277_workspace_writer_authority_attribution.sql +393 -0
- package/drizzle/0278_workspace_membership_removal_fencing.sql +1174 -0
- package/drizzle/0279_workspace_connection_use_lane.sql +343 -0
- package/drizzle/0280_connection_and_variable_set_audit_attribution.sql +773 -0
- package/drizzle/0281_viewer_holder_authority_claims.sql +52 -0
- package/drizzle/0282_variable_set_session_attach_attribution.sql +178 -0
- package/drizzle/0283_editable_spreadsheet_authored_state.sql +82 -0
- package/drizzle/0284_truthful_human_confirmed_review_reason.sql +930 -0
- package/drizzle/0285_organization_tenancy_inventory.sql +329 -0
- package/drizzle/0286_widen_task_note_expiry_ceiling.sql +391 -0
- package/drizzle/0287_open_suffix_pending_tool_calls.sql +18 -0
- package/drizzle/0288_attached_browser_reenrollment.sql +64 -0
- package/drizzle/0289_session_composer_policy_authority.sql +597 -0
- package/drizzle/0290_organization_membership_backfill.sql +268 -0
- package/drizzle/0291_resource_authority_classification_assertion.sql +371 -0
- package/drizzle/0292_truthful_tenancy_inventory_counters.sql +291 -0
- package/drizzle/0293_confirm_time_rule_rebaseline.sql +615 -0
- package/drizzle/0294_preference_activation_authority.sql +237 -0
- package/drizzle/0295_retire_legacy_standing_memory_mode.sql +476 -0
- package/drizzle/0296_force_rls_backfill_noop_repair.sql +215 -0
- package/drizzle/0297_session_ownership_classification_and_backfill.sql +752 -0
- package/drizzle/0298_organization_tenancy_parity.sql +609 -0
- package/drizzle/0299_organization_membership_lock_order.sql +291 -0
- package/drizzle/0300_tenancy_backfill_ledger.sql +459 -0
- package/drizzle/0301_session_snapshot_and_pin_visibility.sql +181 -0
- package/drizzle/0302_personal_workspace_session_ownership.sql +303 -0
- package/drizzle/0303_session_tenancy_product_activation.sql +919 -0
- package/drizzle/0304_personal_workspace_private_session_reads.sql +97 -0
- package/drizzle/0305_personal_resource_grant_management.sql +584 -0
- package/drizzle/0306_atomic_personal_resource_attachments.sql +1374 -0
- package/drizzle/0307_session_attention_state.sql +51 -0
- package/drizzle/0308_session_archives.sql +35 -0
- package/drizzle/0309_channel_project_pins.sql +6 -0
- package/drizzle/0310_channel_project_order.sql +27 -0
- package/drizzle/0311_company_scope_and_private_session_create.sql +656 -0
- package/drizzle/0312_quiescent_session_tree_deletion.sql +39 -0
- package/drizzle/0313_private_child_session_authority.sql +365 -0
- package/drizzle/0314_unregistered_organization_invitations.sql +606 -0
- package/drizzle/0315_personal_github_repository_selection.sql +624 -0
- package/drizzle/0316_human_confirmed_activation_resumed_generation.sql +869 -0
- package/drizzle/0317_session_goal_continuation_hold.sql +64 -0
- package/drizzle/0318_session_turn_startup_milestones.sql +115 -0
- package/drizzle/0319_event_triggered_automations.sql +254 -0
- package/drizzle/0320_pr_review_pack.sql +113 -0
- package/drizzle/0321_slack_bot_environment_display_name.sql +15 -0
- package/drizzle/0322_session_turns_unclaimed_prompt_trigger_index.sql +5 -0
- package/drizzle/0323_organization_private_session_enablement.sql +489 -0
- package/drizzle/0324_human_confirmed_company_profile_agent_admin.sql +856 -0
- package/drizzle/0325_child_lifecycle_notices.sql +44 -0
- package/drizzle/0326_interaction_operation_error_codes.sql +62 -0
- package/drizzle/0327_slack_first_task_hint.sql +29 -0
- package/drizzle/0328_session_background_commands.sql +590 -0
- package/drizzle/0329_slack_orchestration_delivery_events.sql +91 -0
- package/drizzle/0330_api_key_descriptions.sql +20 -0
- package/drizzle/0331_managed_organization_creation.sql +163 -0
- package/drizzle/0332_organization_shared_workspace_control_plane.sql +539 -0
- package/drizzle/0333_session_turn_prompt_routing.sql +45 -0
- package/drizzle/0334_connected_machine_workspace_root.sql +99 -0
- package/drizzle/0335_slack_workspace_routing.sql +460 -0
- package/drizzle/0336_atomic_session_fork_visibility.sql +667 -0
- package/drizzle/0337_slack_routed_action_handles.sql +189 -0
- package/drizzle/0338_atomic_connected_machine_attachments.sql +410 -0
- package/drizzle/0339_document_authority_reclassification.sql +1153 -0
- package/drizzle/0340_tenancy_backfill_activation_evidence.sql +1347 -0
- package/drizzle/0341_slack_routing_probe_organization_fence.sql +109 -0
- package/package.json +10 -6
- package/src/attached-browser-devices.ts +233 -5
- package/src/automations.ts +911 -0
- package/src/browser-sessions.ts +10 -0
- package/src/capability-integrations.ts +175 -1
- package/src/child-lifecycle-notices.ts +241 -0
- package/src/codemode-operations.ts +1 -35
- package/src/company-brain-context-selection-schema.ts +100 -0
- package/src/company-brain-context-selection.ts +359 -0
- package/src/company-brain-governed-writes.ts +1170 -0
- package/src/company-brain.ts +309 -0
- package/src/company-profile-agent-admin.ts +225 -0
- package/src/company-profile-schema.ts +121 -1
- package/src/company-profile.ts +21 -0
- package/src/computer-sessions.ts +10 -1
- package/src/connection-authority.ts +290 -0
- package/src/connection-scopes.ts +20 -0
- package/src/connection-tenancy-backfill.ts +81 -0
- package/src/connection-token-resolver.ts +263 -31
- package/src/database.ts +75 -2
- package/src/editable-artifacts-schema.ts +10 -5
- package/src/editable-artifacts.ts +21 -11
- package/src/governed-learning-activation-schema.ts +121 -0
- package/src/governed-learning-activation.ts +588 -0
- package/src/governed-learning-evaluator-schema.ts +72 -0
- package/src/governed-learning-evaluator.ts +217 -0
- package/src/index.ts +11651 -1548
- package/src/insights.ts +107 -0
- package/src/integration-bindings.ts +88 -6
- package/src/integration-facets.ts +287 -84
- package/src/interaction-placement-loss.ts +234 -0
- package/src/managed-human-provisioning.ts +116 -0
- package/src/memory-domain.ts +27 -32
- package/src/migrate.ts +77 -1
- package/src/new-session-drafts.ts +229 -35
- package/src/organization-membership-backfill.ts +735 -0
- package/src/organization-membership-lifecycle.ts +985 -0
- package/src/pr-review.ts +890 -0
- package/src/preference-registry.ts +31 -1
- package/src/provision-roles.ts +877 -6
- package/src/runtime-posture-cli.ts +2 -0
- package/src/runtime-posture.ts +1291 -76
- package/src/schema.ts +3303 -428
- package/src/scoped-knowledge-schema.ts +16 -8
- package/src/scoped-knowledge.ts +1 -1
- package/src/session-background-commands.ts +759 -0
- package/src/session-control.ts +640 -74
- package/src/session-goal-pacing.ts +126 -0
- package/src/session-queue-commands.ts +437 -84
- package/src/session-realtime-context.ts +3 -3
- package/src/session-realtime-ledger.ts +22 -11
- package/src/session-realtime-mirror.ts +1 -1
- package/src/session-tenancy.ts +403 -49
- package/src/session-tool-call-settlement.ts +38 -29
- package/src/slack-routing-personal-workspace.ts +67 -0
- package/src/slack-routing.ts +469 -0
- package/src/slack-task-policy-schema.ts +5 -0
- package/src/slack-task-policy.ts +18 -0
- package/src/slack-user-link-access.ts +17 -1
- package/src/task-notes-schema.ts +74 -0
- package/src/task-notes.ts +124 -2
- package/src/turn-initiator.ts +8 -0
- package/src/user-resource-authority.ts +377 -0
- package/src/workspace-authority.ts +160 -0
- package/src/workspace-instruction-policies-schema.ts +53 -1
- package/src/workspace-instruction-policies.ts +528 -77
- package/src/workspace-learning-policy.ts +21 -5
- package/src/workspace-membership-permissions.ts +9 -0
- package/dist/chunk-4SR4HKKA.js.map +0 -1
- package/dist/chunk-6ZYKCRFO.js.map +0 -1
- package/dist/chunk-NXAFLCQX.js +0 -2468
- package/dist/chunk-NXAFLCQX.js.map +0 -1
- package/dist/chunk-SK7YYHBI.js.map +0 -1
- package/dist/chunk-WD5ROSLL.js +0 -117
- package/dist/chunk-WD5ROSLL.js.map +0 -1
- package/dist/chunk-ZWREYEWA.js.map +0 -1
- /package/dist/{chunk-LTG3S6ZY.js.map → chunk-EULAN2NP.js.map} +0 -0
- /package/dist/{chunk-CUPM3FGB.js.map → chunk-NJVZPWXY.js.map} +0 -0
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
XaiProviderAccountAuthoritySnapshotV1,
|
|
4
4
|
DraftTimelineAnnotations,
|
|
5
5
|
McpPersonalConnectionDelegations,
|
|
6
|
+
PersonalResourceAttachmentSummary,
|
|
6
7
|
TimelineAnnotations,
|
|
7
8
|
metadataWithTurnExecutionPolicyV1,
|
|
8
9
|
mergeResourceRefs,
|
|
@@ -19,15 +20,17 @@ import {
|
|
|
19
20
|
type SandboxOs,
|
|
20
21
|
type SessionEvent,
|
|
21
22
|
type SessionEventType,
|
|
23
|
+
type SessionPromptRouting,
|
|
22
24
|
type SessionTurn,
|
|
23
25
|
type SessionTurnSource,
|
|
24
26
|
type SessionTurnStatus,
|
|
25
27
|
type ToolRef,
|
|
26
28
|
type TurnExecutionPolicyV1,
|
|
27
29
|
type TimelineAnnotation,
|
|
30
|
+
type PersonalResourceAttachmentIntent,
|
|
28
31
|
} from "@opengeni/contracts";
|
|
29
32
|
import { and, asc, eq, inArray, sql } from "drizzle-orm";
|
|
30
|
-
import type
|
|
33
|
+
import { setSubjectRlsContext, type Database, type SessionActivityDatabase } from "./database";
|
|
31
34
|
import {
|
|
32
35
|
fromPostgresLosslessJson,
|
|
33
36
|
fromPostgresLosslessText,
|
|
@@ -42,6 +45,7 @@ import {
|
|
|
42
45
|
evaluateSessionControl,
|
|
43
46
|
lockSessionEventWriteRows,
|
|
44
47
|
lockWorkspaceInferenceControl,
|
|
48
|
+
lockWorkspaceInferenceControlForAdmission,
|
|
45
49
|
registerInternalUpdateWakeInTransaction,
|
|
46
50
|
reserveSessionCommandReceipt,
|
|
47
51
|
registerSessionWorkflowWakeInTransaction,
|
|
@@ -52,6 +56,7 @@ import {
|
|
|
52
56
|
updateSessionCommandReceiptResult,
|
|
53
57
|
} from "./session-control";
|
|
54
58
|
import { sessionRealtimeIsActiveInTransaction } from "./session-realtime-state";
|
|
59
|
+
import { autoResumeGoalPausedByCapInTransaction } from "./session-goal-pacing";
|
|
55
60
|
import {
|
|
56
61
|
mirrorSessionRealtimeContextInTransaction,
|
|
57
62
|
renderRealtimeHumanInputContext,
|
|
@@ -65,6 +70,8 @@ import {
|
|
|
65
70
|
type FrozenTurnInitiator,
|
|
66
71
|
} from "./turn-initiator";
|
|
67
72
|
import { resolveXaiProviderAccountAuthoritySnapshotForAcceptanceInTransaction } from "./xai-subscription";
|
|
73
|
+
import { assertActiveManagedHumanOrganizationMembership } from "./organization-membership-lifecycle";
|
|
74
|
+
import { acceptTurnPersonalResourceAttachmentInTransaction } from "./user-resource-authority";
|
|
68
75
|
|
|
69
76
|
type SessionEventInsertWithPayload = typeof schema.sessionEvents.$inferInsert & {
|
|
70
77
|
payload: unknown;
|
|
@@ -77,7 +84,8 @@ export type QueueCommandConflictCode =
|
|
|
77
84
|
| "PROMPT_CHANGED"
|
|
78
85
|
| "DRAFT_CHANGED"
|
|
79
86
|
| "DRAFT_NOT_EMPTY"
|
|
80
|
-
| "EDIT_SOURCE_CHANGED"
|
|
87
|
+
| "EDIT_SOURCE_CHANGED"
|
|
88
|
+
| "ONCE_ATTACHMENT_IMMUTABLE";
|
|
81
89
|
|
|
82
90
|
export class QueueCommandConflictError extends Error {
|
|
83
91
|
readonly name = "QueueCommandConflictError";
|
|
@@ -113,14 +121,19 @@ export type EditQueueCommandResult = QueueCommandResult & {
|
|
|
113
121
|
export type SteerQueueCommandResult = QueueCommandResult & {
|
|
114
122
|
interruptionCount: number;
|
|
115
123
|
workspaceControlEventId: string | null;
|
|
124
|
+
workflowId: string;
|
|
125
|
+
wakeRevision: number;
|
|
116
126
|
};
|
|
117
127
|
|
|
118
128
|
export type SubmitHumanPromptResult = {
|
|
119
129
|
receipt: SessionCommandReceiptRow;
|
|
130
|
+
routing: SessionPromptRouting;
|
|
120
131
|
queueVersion: number;
|
|
121
132
|
accepted: SessionEvent;
|
|
122
133
|
events: SessionEvent[];
|
|
123
134
|
turn: SessionTurn;
|
|
135
|
+
/** Current actor/session composer after an exact draft-bound submission. */
|
|
136
|
+
draft: ComposerDraftRow | null;
|
|
124
137
|
/** Backward-compatible row identities for lower-level callers. */
|
|
125
138
|
acceptedEventId: string;
|
|
126
139
|
eventIds: string[];
|
|
@@ -170,7 +183,7 @@ function mapSubmittedPromptTurn(row: typeof schema.sessionTurns.$inferSelect): S
|
|
|
170
183
|
toolsProvided: row.toolsProvided,
|
|
171
184
|
model: row.model,
|
|
172
185
|
reasoningEffort: row.reasoningEffort as ReasoningEffort,
|
|
173
|
-
latencyMode:
|
|
186
|
+
latencyMode: row.latencyMode as LatencyMode,
|
|
174
187
|
sandboxBackend: row.sandboxBackend as SandboxBackend,
|
|
175
188
|
sandboxOs: (row.sandboxOs as SandboxOs | null) ?? null,
|
|
176
189
|
metadata: row.metadata,
|
|
@@ -185,6 +198,9 @@ function mapSubmittedPromptTurn(row: typeof schema.sessionTurns.$inferSelect): S
|
|
|
185
198
|
),
|
|
186
199
|
initiatorContext: row.initiatorContext ?? {},
|
|
187
200
|
personalConnections,
|
|
201
|
+
personalResources: row.personalResourceAttachmentSummary
|
|
202
|
+
? PersonalResourceAttachmentSummary.parse(row.personalResourceAttachmentSummary)
|
|
203
|
+
: null,
|
|
188
204
|
cancelledBy: row.cancelledBy,
|
|
189
205
|
cancelReason: row.cancelReason,
|
|
190
206
|
startedAt: row.startedAt ? row.startedAt.toISOString() : null,
|
|
@@ -211,9 +227,16 @@ async function personalConnectionDelegationsForAgentActor(
|
|
|
211
227
|
db: Database,
|
|
212
228
|
workspaceId: string,
|
|
213
229
|
actor: Extract<SessionCommandActor, { type: "agent_attempt" }>,
|
|
214
|
-
|
|
230
|
+
targetSessionId: string,
|
|
231
|
+
): Promise<{
|
|
232
|
+
delegations: McpPersonalConnectionDelegation[];
|
|
233
|
+
connectionAuthoritySubjectId: string | null;
|
|
234
|
+
}> {
|
|
215
235
|
const [row] = await db
|
|
216
|
-
.select({
|
|
236
|
+
.select({
|
|
237
|
+
delegations: schema.sessionTurns.personalConnectionDelegations,
|
|
238
|
+
initiatingHumanSubjectId: schema.sessionTurns.initiatingHumanSubjectId,
|
|
239
|
+
})
|
|
217
240
|
.from(schema.sessionTurns)
|
|
218
241
|
.where(
|
|
219
242
|
and(
|
|
@@ -234,7 +257,37 @@ async function personalConnectionDelegationsForAgentActor(
|
|
|
234
257
|
`Agent authority turn has malformed personal MCP delegation state: ${actor.sessionId}/${actor.turnId}`,
|
|
235
258
|
);
|
|
236
259
|
}
|
|
237
|
-
|
|
260
|
+
// Agent messages and Agent Steer create new accepted work. A once grant is
|
|
261
|
+
// already bound to the caller turn, while a session grant may be projected
|
|
262
|
+
// only into another turn of that exact session. Always grants can cross the
|
|
263
|
+
// direct parent/child boundary subject to the live admission fences.
|
|
264
|
+
const delegations = parsed.data
|
|
265
|
+
.filter((delegation) => {
|
|
266
|
+
const authority = delegation.userDelegation;
|
|
267
|
+
if (!authority) return true;
|
|
268
|
+
if (authority.mode === "once") return false;
|
|
269
|
+
if (authority.mode === "session") return authority.sessionId === targetSessionId;
|
|
270
|
+
return true;
|
|
271
|
+
})
|
|
272
|
+
.map((delegation) => ({ ...delegation }));
|
|
273
|
+
const activated = delegations.filter((delegation) => delegation.userDelegation);
|
|
274
|
+
if (activated.length === 0) {
|
|
275
|
+
return { delegations, connectionAuthoritySubjectId: null };
|
|
276
|
+
}
|
|
277
|
+
const connectionAuthoritySubjectId = row.initiatingHumanSubjectId;
|
|
278
|
+
if (!connectionAuthoritySubjectId) {
|
|
279
|
+
throw new SessionControlInvariantError(
|
|
280
|
+
`Agent authority turn lost its causal human: ${actor.sessionId}/${actor.turnId}`,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
for (const delegation of activated) {
|
|
284
|
+
if (delegation.ownerSubjectId !== connectionAuthoritySubjectId) {
|
|
285
|
+
throw new SessionControlInvariantError(
|
|
286
|
+
`Agent authority turn causal human does not own retained connection authority: ${actor.sessionId}/${actor.turnId}`,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return { delegations, connectionAuthoritySubjectId };
|
|
238
291
|
}
|
|
239
292
|
|
|
240
293
|
async function xaiAuthorityForAgentActor(
|
|
@@ -664,10 +717,19 @@ export async function saveComposerDraftInTransaction(
|
|
|
664
717
|
resources: ResourceRef[];
|
|
665
718
|
model: string;
|
|
666
719
|
reasoningEffort: ReasoningEffort;
|
|
667
|
-
latencyMode
|
|
720
|
+
latencyMode: LatencyMode;
|
|
721
|
+
/**
|
|
722
|
+
* Bound the workspace control prefix wait (request-scoped API callers pass
|
|
723
|
+
* `workspaceControlRequestLockTimeoutMs()`); omit for lifecycle callers.
|
|
724
|
+
*/
|
|
725
|
+
controlLockTimeoutMs?: number;
|
|
668
726
|
},
|
|
669
727
|
): Promise<ComposerDraftRow> {
|
|
670
|
-
await lockWorkspaceInferenceControl(db, input.workspaceId, "share"
|
|
728
|
+
await lockWorkspaceInferenceControl(db, input.workspaceId, "share", {
|
|
729
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
730
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
731
|
+
: {}),
|
|
732
|
+
});
|
|
671
733
|
await lockSessionEventWriteRows(db, {
|
|
672
734
|
workspaceId: input.workspaceId,
|
|
673
735
|
controlLock: "already_locked",
|
|
@@ -698,7 +760,7 @@ export async function saveComposerDraftInTransaction(
|
|
|
698
760
|
toolsProvided: false,
|
|
699
761
|
model: input.model,
|
|
700
762
|
reasoningEffort: input.reasoningEffort,
|
|
701
|
-
latencyMode: input.latencyMode
|
|
763
|
+
latencyMode: input.latencyMode,
|
|
702
764
|
// A queue edit is still the same accepted work item. Preserve its frozen
|
|
703
765
|
// initiator through arbitrary draft saves; only a genuinely new compose or
|
|
704
766
|
// Steer captures the submitting actor.
|
|
@@ -728,9 +790,18 @@ export async function moveQueuedTurnInTransaction(
|
|
|
728
790
|
expectedQueueVersion: number;
|
|
729
791
|
actor: SessionCommandActor;
|
|
730
792
|
operationKey: string;
|
|
793
|
+
/**
|
|
794
|
+
* Bound the workspace control prefix wait (request-scoped API callers pass
|
|
795
|
+
* `workspaceControlRequestLockTimeoutMs()`); omit for lifecycle callers.
|
|
796
|
+
*/
|
|
797
|
+
controlLockTimeoutMs?: number;
|
|
731
798
|
},
|
|
732
799
|
): Promise<QueueCommandResult> {
|
|
733
|
-
await lockWorkspaceInferenceControl(db, input.workspaceId, "share"
|
|
800
|
+
await lockWorkspaceInferenceControl(db, input.workspaceId, "share", {
|
|
801
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
802
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
803
|
+
: {}),
|
|
804
|
+
});
|
|
734
805
|
await lockSessionEventWriteRows(db, {
|
|
735
806
|
workspaceId: input.workspaceId,
|
|
736
807
|
controlLock: "already_locked",
|
|
@@ -864,9 +935,18 @@ export async function deleteSessionQueueItemInTransaction(
|
|
|
864
935
|
actor: SessionCommandActor;
|
|
865
936
|
operationKey: string;
|
|
866
937
|
reason?: string | null;
|
|
938
|
+
/**
|
|
939
|
+
* Bound the workspace control prefix wait (request-scoped API callers pass
|
|
940
|
+
* `workspaceControlRequestLockTimeoutMs()`); omit for lifecycle callers.
|
|
941
|
+
*/
|
|
942
|
+
controlLockTimeoutMs?: number;
|
|
867
943
|
},
|
|
868
944
|
): Promise<QueueCommandResult> {
|
|
869
|
-
await lockWorkspaceInferenceControl(db, input.workspaceId, "share"
|
|
945
|
+
await lockWorkspaceInferenceControl(db, input.workspaceId, "share", {
|
|
946
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
947
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
948
|
+
: {}),
|
|
949
|
+
});
|
|
870
950
|
await lockSessionEventWriteRows(db, {
|
|
871
951
|
workspaceId: input.workspaceId,
|
|
872
952
|
controlLock: "already_locked",
|
|
@@ -997,9 +1077,18 @@ export async function editQueuedTurnInTransaction(
|
|
|
997
1077
|
replaceDraft: boolean;
|
|
998
1078
|
actor: SessionCommandActor;
|
|
999
1079
|
operationKey: string;
|
|
1080
|
+
/**
|
|
1081
|
+
* Bound the workspace control prefix wait (request-scoped API callers pass
|
|
1082
|
+
* `workspaceControlRequestLockTimeoutMs()`); omit for lifecycle callers.
|
|
1083
|
+
*/
|
|
1084
|
+
controlLockTimeoutMs?: number;
|
|
1000
1085
|
},
|
|
1001
1086
|
): Promise<EditQueueCommandResult> {
|
|
1002
|
-
await lockWorkspaceInferenceControl(db, input.workspaceId, "share"
|
|
1087
|
+
await lockWorkspaceInferenceControl(db, input.workspaceId, "share", {
|
|
1088
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
1089
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
1090
|
+
: {}),
|
|
1091
|
+
});
|
|
1003
1092
|
await lockSessionEventWriteRows(db, {
|
|
1004
1093
|
workspaceId: input.workspaceId,
|
|
1005
1094
|
controlLock: "already_locked",
|
|
@@ -1070,6 +1159,17 @@ export async function editQueuedTurnInTransaction(
|
|
|
1070
1159
|
draftRevision,
|
|
1071
1160
|
});
|
|
1072
1161
|
}
|
|
1162
|
+
if (turn.personalResourceAttachmentSummary?.mode === "once") {
|
|
1163
|
+
throw new QueueCommandConflictError(
|
|
1164
|
+
"ONCE_ATTACHMENT_IMMUTABLE",
|
|
1165
|
+
"A queued prompt with a once personal-resource attachment cannot be edited into new work",
|
|
1166
|
+
{
|
|
1167
|
+
queueVersion: session.queueVersion,
|
|
1168
|
+
turnVersion: turn.version,
|
|
1169
|
+
draftRevision,
|
|
1170
|
+
},
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1073
1173
|
const nextDraftRevision = draftRevision + 1;
|
|
1074
1174
|
const draftValues = {
|
|
1075
1175
|
accountId: input.accountId,
|
|
@@ -1177,9 +1277,19 @@ export async function steerQueuedTurnInTransaction(
|
|
|
1177
1277
|
controlEtag?: string | null;
|
|
1178
1278
|
actor: SessionCommandActor;
|
|
1179
1279
|
operationKey: string;
|
|
1280
|
+
/** Request-scoped callers bound the control prefix wait; lifecycle callers omit it. */
|
|
1281
|
+
controlLockTimeoutMs?: number;
|
|
1180
1282
|
},
|
|
1181
1283
|
): Promise<SteerQueueCommandResult> {
|
|
1182
|
-
const
|
|
1284
|
+
const admission = await lockWorkspaceInferenceControlForAdmission(db, {
|
|
1285
|
+
workspaceId: input.workspaceId,
|
|
1286
|
+
sessionId: input.sessionId,
|
|
1287
|
+
resumePausedBranch: true,
|
|
1288
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
1289
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
1290
|
+
: {}),
|
|
1291
|
+
});
|
|
1292
|
+
const workspaceControl = admission.control;
|
|
1183
1293
|
await lockSessionEventWriteRows(db, {
|
|
1184
1294
|
workspaceId: input.workspaceId,
|
|
1185
1295
|
controlLock: "already_locked",
|
|
@@ -1207,6 +1317,10 @@ export async function steerQueuedTurnInTransaction(
|
|
|
1207
1317
|
});
|
|
1208
1318
|
if (reserved.replay && reserved.receipt.appliedQueueVersion !== null) {
|
|
1209
1319
|
const replaySession = await lockSession(db, input.workspaceId, input.sessionId);
|
|
1320
|
+
const wakeRevision = Number(reserved.receipt.result.wakeRevision ?? 0);
|
|
1321
|
+
if (wakeRevision < 1) {
|
|
1322
|
+
throw new SessionControlInvariantError("Replayed queue Steer receipt has no wake revision");
|
|
1323
|
+
}
|
|
1210
1324
|
return {
|
|
1211
1325
|
receipt: reserved.receipt,
|
|
1212
1326
|
queueVersion: replaySession.queueVersion,
|
|
@@ -1217,6 +1331,8 @@ export async function steerQueuedTurnInTransaction(
|
|
|
1217
1331
|
typeof reserved.receipt.result.workspaceControlEventId === "string"
|
|
1218
1332
|
? reserved.receipt.result.workspaceControlEventId
|
|
1219
1333
|
: null,
|
|
1334
|
+
workflowId: replaySession.temporalWorkflowId ?? `session-${input.sessionId}`,
|
|
1335
|
+
wakeRevision,
|
|
1220
1336
|
replay: true,
|
|
1221
1337
|
};
|
|
1222
1338
|
}
|
|
@@ -1244,6 +1360,7 @@ export async function steerQueuedTurnInTransaction(
|
|
|
1244
1360
|
: input.actor.subjectId,
|
|
1245
1361
|
reason: "human_steer",
|
|
1246
1362
|
observedControlEtag: input.controlEtag ?? null,
|
|
1363
|
+
admission,
|
|
1247
1364
|
});
|
|
1248
1365
|
const session = await lockSession(db, input.workspaceId, input.sessionId);
|
|
1249
1366
|
const rows = await loadQueuedTurns(db, input.workspaceId, input.sessionId, true);
|
|
@@ -1395,6 +1512,8 @@ export async function steerQueuedTurnInTransaction(
|
|
|
1395
1512
|
eventIds: eventRows.map((event) => event.id),
|
|
1396
1513
|
interruptionCount,
|
|
1397
1514
|
workspaceControlEventId: resumed.workspaceControlEventId,
|
|
1515
|
+
workflowId: session.temporalWorkflowId ?? `session-${input.sessionId}`,
|
|
1516
|
+
wakeRevision,
|
|
1398
1517
|
replay: false,
|
|
1399
1518
|
};
|
|
1400
1519
|
}
|
|
@@ -1434,14 +1553,34 @@ export async function submitHumanPromptInTransaction(
|
|
|
1434
1553
|
/** Record the admitted run's durable usage fact in this transaction. */
|
|
1435
1554
|
recordAgentRunUsage?: boolean;
|
|
1436
1555
|
personalConnectionDelegations?: McpPersonalConnectionDelegation[];
|
|
1556
|
+
personalResourceAttachment?: PersonalResourceAttachmentIntent;
|
|
1437
1557
|
mcpCredentialUpdates?: Array<{
|
|
1438
1558
|
id: string;
|
|
1439
1559
|
headersEncrypted: Record<string, string>;
|
|
1440
1560
|
}>;
|
|
1561
|
+
/** Request-scoped callers bound the control prefix wait; lifecycle callers omit it. */
|
|
1562
|
+
controlLockTimeoutMs?: number;
|
|
1441
1563
|
},
|
|
1442
1564
|
): Promise<SubmitHumanPromptResult> {
|
|
1443
1565
|
const annotations = TimelineAnnotations.parse(input.annotations ?? []);
|
|
1444
|
-
|
|
1566
|
+
// Send is inert queue admission while paused; Steer deliberately resumes.
|
|
1567
|
+
// Tell the lock helper which path may need the exclusive control prefix.
|
|
1568
|
+
const admission = await lockWorkspaceInferenceControlForAdmission(db, {
|
|
1569
|
+
workspaceId: input.workspaceId,
|
|
1570
|
+
sessionId: input.sessionId,
|
|
1571
|
+
resumePausedBranch: input.delivery === "steer",
|
|
1572
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
1573
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
1574
|
+
: {}),
|
|
1575
|
+
});
|
|
1576
|
+
const workspaceControl = admission.control;
|
|
1577
|
+
if (input.actor.type === "human") {
|
|
1578
|
+
await setSubjectRlsContext(db, input.actor.subjectId);
|
|
1579
|
+
await assertActiveManagedHumanOrganizationMembership(db, {
|
|
1580
|
+
accountId: input.accountId,
|
|
1581
|
+
subjectId: input.actor.subjectId,
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1445
1584
|
await lockSessionEventWriteRows(db, {
|
|
1446
1585
|
workspaceId: input.workspaceId,
|
|
1447
1586
|
controlLock: "already_locked",
|
|
@@ -1467,6 +1606,8 @@ export async function submitHumanPromptInTransaction(
|
|
|
1467
1606
|
turnMetadata: input.turnMetadata ?? {},
|
|
1468
1607
|
messagePresentation: input.messagePresentation ?? null,
|
|
1469
1608
|
mcpCredentialUpdates: input.mcpCredentialUpdates ?? [],
|
|
1609
|
+
personalConnectionDelegations: input.personalConnectionDelegations ?? [],
|
|
1610
|
+
personalResourceAttachment: input.personalResourceAttachment ?? null,
|
|
1470
1611
|
...(input.actor.type === "service"
|
|
1471
1612
|
? {
|
|
1472
1613
|
serviceInitiator: {
|
|
@@ -1524,12 +1665,32 @@ export async function submitHumanPromptInTransaction(
|
|
|
1524
1665
|
if (!accepted || !replayTurn || events.length !== eventIds.length) {
|
|
1525
1666
|
throw new SessionControlInvariantError("Replayed prompt rows are incomplete");
|
|
1526
1667
|
}
|
|
1668
|
+
const replayDraft =
|
|
1669
|
+
input.expectedDraftRevision === null || input.expectedDraftRevision === undefined
|
|
1670
|
+
? null
|
|
1671
|
+
: await getComposerDraftInTransaction(db, {
|
|
1672
|
+
workspaceId: input.workspaceId,
|
|
1673
|
+
sessionId: input.sessionId,
|
|
1674
|
+
subjectId: input.subjectId,
|
|
1675
|
+
});
|
|
1527
1676
|
return {
|
|
1528
1677
|
receipt: reserved.receipt,
|
|
1678
|
+
routing:
|
|
1679
|
+
reserved.receipt.result.routing === "accepted_for_execution" ||
|
|
1680
|
+
reserved.receipt.result.routing === "queued_for_execution" ||
|
|
1681
|
+
reserved.receipt.result.routing === "accepted_for_steering"
|
|
1682
|
+
? reserved.receipt.result.routing
|
|
1683
|
+
: input.delivery === "steer"
|
|
1684
|
+
? "accepted_for_steering"
|
|
1685
|
+
: // Pre-routing receipts cannot reconstruct admission-time activity
|
|
1686
|
+
// or Pause truth. Queue is the only conservative placement; a
|
|
1687
|
+
// later turn.started event moves it into chat without duplication.
|
|
1688
|
+
"queued_for_execution",
|
|
1529
1689
|
queueVersion: Number(reserved.receipt.appliedQueueVersion),
|
|
1530
1690
|
accepted,
|
|
1531
1691
|
events,
|
|
1532
1692
|
turn: mapSubmittedPromptTurn(replayTurn),
|
|
1693
|
+
draft: replayDraft,
|
|
1533
1694
|
acceptedEventId,
|
|
1534
1695
|
eventIds,
|
|
1535
1696
|
turnId,
|
|
@@ -1550,34 +1711,39 @@ export async function submitHumanPromptInTransaction(
|
|
|
1550
1711
|
throw new SessionControlConflictError();
|
|
1551
1712
|
}
|
|
1552
1713
|
|
|
1553
|
-
const resumed = await autoResumeSessionBranchInTransaction(db, {
|
|
1554
|
-
workspaceId: input.workspaceId,
|
|
1555
|
-
sessionId: input.sessionId,
|
|
1556
|
-
actor:
|
|
1557
|
-
input.actor.type === "agent_attempt"
|
|
1558
|
-
? `attempt:${input.actor.attemptId}`
|
|
1559
|
-
: input.actor.subjectId,
|
|
1560
|
-
reason:
|
|
1561
|
-
input.actor.type === "service"
|
|
1562
|
-
? input.delivery === "steer"
|
|
1563
|
-
? "service_steer"
|
|
1564
|
-
: "service_send"
|
|
1565
|
-
: input.delivery === "steer"
|
|
1566
|
-
? "human_steer"
|
|
1567
|
-
: "human_send",
|
|
1568
|
-
observedControlEtag: input.controlEtag ?? null,
|
|
1569
|
-
});
|
|
1570
1714
|
const session = await lockSession(db, input.workspaceId, input.sessionId);
|
|
1571
1715
|
if (session.status === "cancelled") {
|
|
1572
1716
|
throw new QueueCommandConflictError(
|
|
1573
1717
|
"QUEUE_PROMPT_STARTED",
|
|
1574
|
-
"Cancelled session cannot accept work",
|
|
1575
|
-
{
|
|
1576
|
-
queueVersion: session.queueVersion,
|
|
1577
|
-
},
|
|
1718
|
+
"Cancelled session subtree cannot accept work",
|
|
1719
|
+
{ queueVersion: session.queueVersion },
|
|
1578
1720
|
);
|
|
1579
1721
|
}
|
|
1580
1722
|
|
|
1723
|
+
// Send is queue admission, never a hidden control mutation. A paused Send
|
|
1724
|
+
// remains inert behind the existing gate until the user explicitly resumes.
|
|
1725
|
+
// Steer is the intentional exception: it replaces the current direction and
|
|
1726
|
+
// therefore activates the selected branch atomically.
|
|
1727
|
+
const resumed =
|
|
1728
|
+
input.delivery === "send"
|
|
1729
|
+
? {
|
|
1730
|
+
revision: before.controlVersion,
|
|
1731
|
+
control: before,
|
|
1732
|
+
changed: false,
|
|
1733
|
+
workspaceControlEventId: null,
|
|
1734
|
+
}
|
|
1735
|
+
: await autoResumeSessionBranchInTransaction(db, {
|
|
1736
|
+
workspaceId: input.workspaceId,
|
|
1737
|
+
sessionId: input.sessionId,
|
|
1738
|
+
actor:
|
|
1739
|
+
input.actor.type === "agent_attempt"
|
|
1740
|
+
? `attempt:${input.actor.attemptId}`
|
|
1741
|
+
: input.actor.subjectId,
|
|
1742
|
+
reason: input.actor.type === "service" ? "service_steer" : "human_steer",
|
|
1743
|
+
observedControlEtag: input.controlEtag ?? null,
|
|
1744
|
+
admission,
|
|
1745
|
+
});
|
|
1746
|
+
|
|
1581
1747
|
const draft =
|
|
1582
1748
|
input.expectedDraftRevision === null || input.expectedDraftRevision === undefined
|
|
1583
1749
|
? null
|
|
@@ -1710,6 +1876,28 @@ export async function submitHumanPromptInTransaction(
|
|
|
1710
1876
|
input.subjectLabel,
|
|
1711
1877
|
);
|
|
1712
1878
|
}
|
|
1879
|
+
const acceptedInitiatingHumanSubjectId = editedSourceTurn
|
|
1880
|
+
? (editedSourceTurn.initiatingHumanSubjectId ??
|
|
1881
|
+
(editedSourceTurn.initiatorKind === "subject" ? editedSourceTurn.initiatorSubjectId : null))
|
|
1882
|
+
: (frozenInitiator.initiatingHumanSubjectId ??
|
|
1883
|
+
(frozenInitiator.initiator.kind === "subject" ? frozenInitiator.initiator.subjectId : null));
|
|
1884
|
+
if (
|
|
1885
|
+
(input.personalConnectionDelegations ?? []).some(
|
|
1886
|
+
(delegation) => delegation.userDelegation !== undefined,
|
|
1887
|
+
) ||
|
|
1888
|
+
input.personalResourceAttachment !== undefined
|
|
1889
|
+
) {
|
|
1890
|
+
if (!acceptedInitiatingHumanSubjectId) {
|
|
1891
|
+
throw new SessionControlInvariantError("Personal authority requires an exact causal human");
|
|
1892
|
+
}
|
|
1893
|
+
await db.execute(
|
|
1894
|
+
sql`select set_config(
|
|
1895
|
+
'opengeni.initiating_human_subject_id',
|
|
1896
|
+
${acceptedInitiatingHumanSubjectId},
|
|
1897
|
+
true
|
|
1898
|
+
)`,
|
|
1899
|
+
);
|
|
1900
|
+
}
|
|
1713
1901
|
const xaiProviderAccountAuthoritySnapshot = editedSourceTurn
|
|
1714
1902
|
? XaiProviderAccountAuthoritySnapshotV1.parse(
|
|
1715
1903
|
editedSourceTurn.xaiProviderAccountAuthoritySnapshot,
|
|
@@ -1726,6 +1914,13 @@ export async function submitHumanPromptInTransaction(
|
|
|
1726
1914
|
editedSourceModelContext !== undefined
|
|
1727
1915
|
? editedSourceModelContext
|
|
1728
1916
|
: (input.modelContext ?? null);
|
|
1917
|
+
const existingQueued = await loadQueuedTurns(db, input.workspaceId, input.sessionId, true);
|
|
1918
|
+
const routing: SessionPromptRouting =
|
|
1919
|
+
input.delivery === "steer"
|
|
1920
|
+
? "accepted_for_steering"
|
|
1921
|
+
: before.state === "paused" || session.activeTurnId || existingQueued.length > 0
|
|
1922
|
+
? "queued_for_execution"
|
|
1923
|
+
: "accepted_for_execution";
|
|
1729
1924
|
let sequence = session.lastSequence;
|
|
1730
1925
|
const eventValues: SessionEventInsertWithPayload[] = [
|
|
1731
1926
|
{
|
|
@@ -1753,12 +1948,12 @@ export async function submitHumanPromptInTransaction(
|
|
|
1753
1948
|
...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),
|
|
1754
1949
|
...(input.latencyMode ? { latencyMode: input.latencyMode } : {}),
|
|
1755
1950
|
delivery: input.delivery,
|
|
1951
|
+
routing,
|
|
1756
1952
|
initiator: frozenInitiator.initiator,
|
|
1757
1953
|
},
|
|
1758
1954
|
occurredAt: now,
|
|
1759
1955
|
},
|
|
1760
1956
|
];
|
|
1761
|
-
const existingQueued = await loadQueuedTurns(db, input.workspaceId, input.sessionId, true);
|
|
1762
1957
|
const [turn] = await db
|
|
1763
1958
|
.insert(schema.sessionTurns)
|
|
1764
1959
|
.values(
|
|
@@ -1772,6 +1967,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
1772
1967
|
temporalWorkflowId: workflowId,
|
|
1773
1968
|
status: "queued",
|
|
1774
1969
|
source: input.source,
|
|
1970
|
+
promptRouting: routing,
|
|
1775
1971
|
position: input.delivery === "steer" ? 0 : existingQueued.length + 1,
|
|
1776
1972
|
prompt: input.text,
|
|
1777
1973
|
annotations,
|
|
@@ -1788,14 +1984,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
1788
1984
|
: (input.turnMetadata ?? {}),
|
|
1789
1985
|
lineage: { actor: input.actor.type },
|
|
1790
1986
|
...initiatorColumns(frozenInitiator),
|
|
1791
|
-
initiatingHumanSubjectId:
|
|
1792
|
-
? (editedSourceTurn.initiatingHumanSubjectId ??
|
|
1793
|
-
(editedSourceTurn.initiatorKind === "subject"
|
|
1794
|
-
? editedSourceTurn.initiatorSubjectId
|
|
1795
|
-
: null))
|
|
1796
|
-
: frozenInitiator.initiator.kind === "subject"
|
|
1797
|
-
? frozenInitiator.initiator.subjectId
|
|
1798
|
-
: null,
|
|
1987
|
+
initiatingHumanSubjectId: acceptedInitiatingHumanSubjectId,
|
|
1799
1988
|
personalConnectionDelegations: editedSourceTurn
|
|
1800
1989
|
? editedSourceTurn.personalConnectionDelegations
|
|
1801
1990
|
: (input.personalConnectionDelegations ?? []),
|
|
@@ -1810,6 +1999,49 @@ export async function submitHumanPromptInTransaction(
|
|
|
1810
1999
|
.returning();
|
|
1811
2000
|
if (!turn) throw new SessionControlInvariantError("Prompt turn was not inserted");
|
|
1812
2001
|
let committedTurn = turn;
|
|
2002
|
+
const personalResourceExpectedAuthorityEpoch =
|
|
2003
|
+
input.personalResourceAttachment?.expectedAuthorityEpoch;
|
|
2004
|
+
let acceptedPersonalResources: Awaited<
|
|
2005
|
+
ReturnType<typeof acceptTurnPersonalResourceAttachmentInTransaction>
|
|
2006
|
+
> | null = null;
|
|
2007
|
+
if (input.personalResourceAttachment) {
|
|
2008
|
+
if (personalResourceExpectedAuthorityEpoch === undefined) {
|
|
2009
|
+
throw new SessionControlInvariantError(
|
|
2010
|
+
"Personal-resource attachment requires an expected authority epoch",
|
|
2011
|
+
);
|
|
2012
|
+
}
|
|
2013
|
+
acceptedPersonalResources = await acceptTurnPersonalResourceAttachmentInTransaction(db, {
|
|
2014
|
+
accountId: input.accountId,
|
|
2015
|
+
workspaceId: input.workspaceId,
|
|
2016
|
+
sessionId: input.sessionId,
|
|
2017
|
+
turnId,
|
|
2018
|
+
subjectId: acceptedInitiatingHumanSubjectId!,
|
|
2019
|
+
intent: {
|
|
2020
|
+
...input.personalResourceAttachment,
|
|
2021
|
+
expectedAuthorityEpoch: personalResourceExpectedAuthorityEpoch,
|
|
2022
|
+
},
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
2025
|
+
if (acceptedPersonalResources) {
|
|
2026
|
+
committedTurn = {
|
|
2027
|
+
...turn,
|
|
2028
|
+
personalResourceAttachmentSummary: acceptedPersonalResources.summary,
|
|
2029
|
+
personalResourceProtocolVersion: 1,
|
|
2030
|
+
};
|
|
2031
|
+
eventValues.push({
|
|
2032
|
+
accountId: input.accountId,
|
|
2033
|
+
workspaceId: input.workspaceId,
|
|
2034
|
+
sessionId: input.sessionId,
|
|
2035
|
+
turnId,
|
|
2036
|
+
sequence: ++sequence,
|
|
2037
|
+
type: "session.personal_resources.attached",
|
|
2038
|
+
payload: {
|
|
2039
|
+
turnId,
|
|
2040
|
+
...acceptedPersonalResources.summary,
|
|
2041
|
+
},
|
|
2042
|
+
occurredAt: now,
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
1813
2045
|
eventValues.push({
|
|
1814
2046
|
accountId: input.accountId,
|
|
1815
2047
|
workspaceId: input.workspaceId,
|
|
@@ -1821,6 +2053,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
1821
2053
|
turnId,
|
|
1822
2054
|
triggerEventId: acceptedEventId,
|
|
1823
2055
|
source: input.source,
|
|
2056
|
+
routing,
|
|
1824
2057
|
initiator: frozenInitiator.initiator,
|
|
1825
2058
|
},
|
|
1826
2059
|
occurredAt: now,
|
|
@@ -1919,6 +2152,29 @@ export async function submitHumanPromptInTransaction(
|
|
|
1919
2152
|
});
|
|
1920
2153
|
}
|
|
1921
2154
|
|
|
2155
|
+
// A human/API prompt is external input for the goal. A goal paused only by
|
|
2156
|
+
// its continuation ceiling (`max_auto_continuations`, pacing rather than
|
|
2157
|
+
// intent) resumes in this same commit; a user/API/agent/limits pause is never
|
|
2158
|
+
// touched here. Goal row FOR UPDATE follows the session and turn locks above,
|
|
2159
|
+
// the order the claim transaction uses.
|
|
2160
|
+
const goalAutoResumed = await autoResumeGoalPausedByCapInTransaction(db, {
|
|
2161
|
+
workspaceId: input.workspaceId,
|
|
2162
|
+
sessionId: input.sessionId,
|
|
2163
|
+
cause: { kind: "human_prompt", turnId },
|
|
2164
|
+
now,
|
|
2165
|
+
});
|
|
2166
|
+
if (goalAutoResumed) {
|
|
2167
|
+
eventValues.push({
|
|
2168
|
+
accountId: input.accountId,
|
|
2169
|
+
workspaceId: input.workspaceId,
|
|
2170
|
+
sessionId: input.sessionId,
|
|
2171
|
+
sequence: ++sequence,
|
|
2172
|
+
type: "goal.resumed",
|
|
2173
|
+
payload: goalAutoResumed.payload,
|
|
2174
|
+
occurredAt: now,
|
|
2175
|
+
});
|
|
2176
|
+
}
|
|
2177
|
+
|
|
1922
2178
|
const ordered =
|
|
1923
2179
|
input.delivery === "steer" ? [turn, ...existingQueued] : [...existingQueued, turn];
|
|
1924
2180
|
await normalizeQueuePositions(
|
|
@@ -1946,12 +2202,6 @@ export async function submitHumanPromptInTransaction(
|
|
|
1946
2202
|
.values(withLosslessContentWriteVersion(eventValues, "payload", "payloadCodecVersion"))
|
|
1947
2203
|
.returning();
|
|
1948
2204
|
if (input.actor.type === "human") {
|
|
1949
|
-
const realtimeRouting =
|
|
1950
|
-
input.delivery === "steer"
|
|
1951
|
-
? "accepted_for_steering"
|
|
1952
|
-
: session.activeTurnId || existingQueued.length > 0
|
|
1953
|
-
? "queued_for_execution"
|
|
1954
|
-
: "accepted_for_execution";
|
|
1955
2205
|
await mirrorSessionRealtimeContextInTransaction(db, {
|
|
1956
2206
|
accountId: input.accountId,
|
|
1957
2207
|
workspaceId: input.workspaceId,
|
|
@@ -1962,12 +2212,12 @@ export async function submitHumanPromptInTransaction(
|
|
|
1962
2212
|
channel: null,
|
|
1963
2213
|
text: renderRealtimeHumanInputContext({
|
|
1964
2214
|
delivery: input.delivery,
|
|
1965
|
-
routing
|
|
2215
|
+
routing,
|
|
1966
2216
|
text: renderTimelineAnnotationsForModel(input.text, annotations),
|
|
1967
2217
|
}),
|
|
1968
2218
|
payload: {
|
|
1969
2219
|
delivery: input.delivery,
|
|
1970
|
-
routing
|
|
2220
|
+
routing,
|
|
1971
2221
|
acceptedEventId,
|
|
1972
2222
|
instruction: "OpenGeni accepted and routed this user input; do not delegate it again.",
|
|
1973
2223
|
},
|
|
@@ -1989,8 +2239,25 @@ export async function submitHumanPromptInTransaction(
|
|
|
1989
2239
|
updatedAt: now,
|
|
1990
2240
|
})
|
|
1991
2241
|
.where(eq(schema.sessions.id, input.sessionId));
|
|
1992
|
-
|
|
1993
|
-
await db
|
|
2242
|
+
const [nextDraft] = draft
|
|
2243
|
+
? await db
|
|
2244
|
+
.update(schema.composerDrafts)
|
|
2245
|
+
.set({
|
|
2246
|
+
revision: draft.revision + 1,
|
|
2247
|
+
text: "",
|
|
2248
|
+
annotations: [],
|
|
2249
|
+
resources: [],
|
|
2250
|
+
tools: [],
|
|
2251
|
+
toolsProvided: false,
|
|
2252
|
+
sourceTurnId: null,
|
|
2253
|
+
sourceTurnVersion: null,
|
|
2254
|
+
updatedAt: now,
|
|
2255
|
+
})
|
|
2256
|
+
.where(eq(schema.composerDrafts.id, draft.id))
|
|
2257
|
+
.returning()
|
|
2258
|
+
: [undefined];
|
|
2259
|
+
if (draft && !nextDraft) {
|
|
2260
|
+
throw new SessionControlInvariantError("Accepted composer draft did not rotate");
|
|
1994
2261
|
}
|
|
1995
2262
|
const wakeRevision = await registerSessionWorkflowWakeInTransaction(db, {
|
|
1996
2263
|
accountId: input.accountId,
|
|
@@ -2051,7 +2318,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
2051
2318
|
controlRevision: resumed.revision,
|
|
2052
2319
|
queueVersion,
|
|
2053
2320
|
turnVersion: turn.version,
|
|
2054
|
-
...(
|
|
2321
|
+
...(nextDraft ? { draftRevision: nextDraft.revision } : {}),
|
|
2055
2322
|
result: {
|
|
2056
2323
|
turnId,
|
|
2057
2324
|
acceptedEventId,
|
|
@@ -2060,6 +2327,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
2060
2327
|
interruptionCount,
|
|
2061
2328
|
replacedTurnId,
|
|
2062
2329
|
workspaceControlEventId: resumed.workspaceControlEventId,
|
|
2330
|
+
routing,
|
|
2063
2331
|
...(input.turnExecutionPolicy
|
|
2064
2332
|
? {
|
|
2065
2333
|
executionPolicy: turnExecutionPolicyAuditMetadata(input.turnExecutionPolicy, turnId),
|
|
@@ -2074,10 +2342,12 @@ export async function submitHumanPromptInTransaction(
|
|
|
2074
2342
|
}
|
|
2075
2343
|
return {
|
|
2076
2344
|
receipt,
|
|
2345
|
+
routing,
|
|
2077
2346
|
queueVersion,
|
|
2078
2347
|
accepted,
|
|
2079
2348
|
events,
|
|
2080
2349
|
turn: mapSubmittedPromptTurn(committedTurn),
|
|
2350
|
+
draft: nextDraft ?? null,
|
|
2081
2351
|
acceptedEventId,
|
|
2082
2352
|
eventIds,
|
|
2083
2353
|
turnId,
|
|
@@ -2097,9 +2367,18 @@ export async function sendAgentMessageInTransaction(
|
|
|
2097
2367
|
actor: Extract<SessionCommandActor, { type: "agent_attempt" }>;
|
|
2098
2368
|
operationKey: string;
|
|
2099
2369
|
text: string;
|
|
2370
|
+
/**
|
|
2371
|
+
* Bound the workspace control prefix wait (request-scoped API callers pass
|
|
2372
|
+
* `workspaceControlRequestLockTimeoutMs()`); omit for lifecycle callers.
|
|
2373
|
+
*/
|
|
2374
|
+
controlLockTimeoutMs?: number;
|
|
2100
2375
|
},
|
|
2101
2376
|
): Promise<AgentInternalUpdateCommandResult> {
|
|
2102
|
-
const workspaceControl = await lockWorkspaceInferenceControl(db, input.workspaceId, "share"
|
|
2377
|
+
const workspaceControl = await lockWorkspaceInferenceControl(db, input.workspaceId, "share", {
|
|
2378
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
2379
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
2380
|
+
: {}),
|
|
2381
|
+
});
|
|
2103
2382
|
await lockSessionEventWriteRows(db, {
|
|
2104
2383
|
workspaceId: input.workspaceId,
|
|
2105
2384
|
controlLock: "already_locked",
|
|
@@ -2148,11 +2427,13 @@ export async function sendAgentMessageInTransaction(
|
|
|
2148
2427
|
targetSessionId: input.targetSessionId,
|
|
2149
2428
|
action: "message",
|
|
2150
2429
|
});
|
|
2151
|
-
const
|
|
2430
|
+
const inheritedConnectionAuthority = await personalConnectionDelegationsForAgentActor(
|
|
2152
2431
|
db,
|
|
2153
2432
|
input.workspaceId,
|
|
2154
2433
|
input.actor,
|
|
2434
|
+
input.targetSessionId,
|
|
2155
2435
|
);
|
|
2436
|
+
const personalConnectionDelegations = inheritedConnectionAuthority.delegations;
|
|
2156
2437
|
const xaiAuthority = await xaiAuthorityForAgentActor(db, input.workspaceId, input.actor);
|
|
2157
2438
|
const session = await lockSession(db, input.workspaceId, input.targetSessionId);
|
|
2158
2439
|
if (session.status === "cancelled") {
|
|
@@ -2195,6 +2476,12 @@ export async function sendAgentMessageInTransaction(
|
|
|
2195
2476
|
callerTurnId: input.actor.turnId,
|
|
2196
2477
|
callerAttemptId: input.actor.attemptId,
|
|
2197
2478
|
callerExecutionGeneration: input.actor.executionGeneration,
|
|
2479
|
+
...(inheritedConnectionAuthority.connectionAuthoritySubjectId
|
|
2480
|
+
? {
|
|
2481
|
+
connectionAuthoritySubjectId:
|
|
2482
|
+
inheritedConnectionAuthority.connectionAuthoritySubjectId,
|
|
2483
|
+
}
|
|
2484
|
+
: {}),
|
|
2198
2485
|
...(xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}),
|
|
2199
2486
|
},
|
|
2200
2487
|
personalConnectionDelegations,
|
|
@@ -2210,29 +2497,52 @@ export async function sendAgentMessageInTransaction(
|
|
|
2210
2497
|
)
|
|
2211
2498
|
.returning({ id: schema.sessionSystemUpdates.id });
|
|
2212
2499
|
if (!update) throw new SessionControlInvariantError("Agent message was not inserted");
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2500
|
+
// An Agent message is external input for the target's goal. A goal paused
|
|
2501
|
+
// only by its continuation ceiling (`max_auto_continuations`, pacing rather
|
|
2502
|
+
// than intent) resumes in this same commit; any other pause stays. Goal row
|
|
2503
|
+
// FOR UPDATE follows the session lock above, the goal tools' order.
|
|
2504
|
+
const goalAutoResumed = await autoResumeGoalPausedByCapInTransaction(db, {
|
|
2505
|
+
workspaceId: input.workspaceId,
|
|
2506
|
+
sessionId: input.targetSessionId,
|
|
2507
|
+
cause: { kind: "agent_message", updateId: update.id },
|
|
2508
|
+
now,
|
|
2509
|
+
});
|
|
2510
|
+
const eventValues: SessionEventInsertWithPayload[] = [
|
|
2511
|
+
{
|
|
2512
|
+
accountId: input.accountId,
|
|
2513
|
+
workspaceId: input.workspaceId,
|
|
2514
|
+
sessionId: input.targetSessionId,
|
|
2515
|
+
sequence: session.lastSequence + 1,
|
|
2516
|
+
type: "system.update.pending",
|
|
2517
|
+
payload: {
|
|
2518
|
+
updateId: update.id,
|
|
2519
|
+
kind: "agent_message",
|
|
2520
|
+
sourceSessionId: input.actor.sessionId,
|
|
2521
|
+
},
|
|
2522
|
+
occurredAt: now,
|
|
2523
|
+
},
|
|
2524
|
+
...(goalAutoResumed
|
|
2525
|
+
? [
|
|
2526
|
+
{
|
|
2527
|
+
accountId: input.accountId,
|
|
2528
|
+
workspaceId: input.workspaceId,
|
|
2529
|
+
sessionId: input.targetSessionId,
|
|
2530
|
+
sequence: session.lastSequence + 2,
|
|
2531
|
+
type: "goal.resumed" as const,
|
|
2532
|
+
payload: goalAutoResumed.payload,
|
|
2533
|
+
occurredAt: now,
|
|
2227
2534
|
},
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
)
|
|
2535
|
+
]
|
|
2536
|
+
: []),
|
|
2537
|
+
];
|
|
2538
|
+
const insertedEvents = await db
|
|
2539
|
+
.insert(schema.sessionEvents)
|
|
2540
|
+
.values(withLosslessContentWriteVersion(eventValues, "payload", "payloadCodecVersion"))
|
|
2234
2541
|
.returning({ id: schema.sessionEvents.id });
|
|
2235
|
-
if (
|
|
2542
|
+
if (insertedEvents.length !== eventValues.length) {
|
|
2543
|
+
throw new SessionControlInvariantError("Agent message event was not inserted");
|
|
2544
|
+
}
|
|
2545
|
+
const eventIds = insertedEvents.map((event) => event.id);
|
|
2236
2546
|
const workflowId = session.temporalWorkflowId ?? `session-${session.id}`;
|
|
2237
2547
|
const runnable = !realtimeActive && session.activeTurnId === null && effective.state === "active";
|
|
2238
2548
|
const wake = runnable
|
|
@@ -2246,7 +2556,7 @@ export async function sendAgentMessageInTransaction(
|
|
|
2246
2556
|
await db
|
|
2247
2557
|
.update(schema.sessions)
|
|
2248
2558
|
.set({
|
|
2249
|
-
lastSequence: session.lastSequence +
|
|
2559
|
+
lastSequence: session.lastSequence + eventValues.length,
|
|
2250
2560
|
...(runnable ? { status: "queued" as const } : {}),
|
|
2251
2561
|
updatedAt: now,
|
|
2252
2562
|
})
|
|
@@ -2275,7 +2585,7 @@ export async function sendAgentMessageInTransaction(
|
|
|
2275
2585
|
const receipt = await updateSessionCommandReceiptResult(db, reserved.receipt.id, {
|
|
2276
2586
|
result: {
|
|
2277
2587
|
updateId: update.id,
|
|
2278
|
-
eventIds
|
|
2588
|
+
eventIds,
|
|
2279
2589
|
wakeRevision: wake?.wakeRevision ?? null,
|
|
2280
2590
|
workflowId,
|
|
2281
2591
|
effectiveState: effective.state,
|
|
@@ -2284,7 +2594,7 @@ export async function sendAgentMessageInTransaction(
|
|
|
2284
2594
|
return {
|
|
2285
2595
|
receipt,
|
|
2286
2596
|
updateId: update.id,
|
|
2287
|
-
eventIds
|
|
2597
|
+
eventIds,
|
|
2288
2598
|
wakeRevision: wake?.wakeRevision ?? null,
|
|
2289
2599
|
shouldSignal: wake?.shouldSignal ?? false,
|
|
2290
2600
|
workflowId,
|
|
@@ -2304,9 +2614,18 @@ export async function steerAgentSessionInTransaction(
|
|
|
2304
2614
|
actor: Extract<SessionCommandActor, { type: "agent_attempt" }>;
|
|
2305
2615
|
operationKey: string;
|
|
2306
2616
|
instruction: string;
|
|
2617
|
+
/** Request-scoped callers bound the control prefix wait; lifecycle callers omit it. */
|
|
2618
|
+
controlLockTimeoutMs?: number;
|
|
2307
2619
|
},
|
|
2308
2620
|
): Promise<AgentInternalUpdateCommandResult> {
|
|
2309
|
-
await
|
|
2621
|
+
const admission = await lockWorkspaceInferenceControlForAdmission(db, {
|
|
2622
|
+
workspaceId: input.workspaceId,
|
|
2623
|
+
sessionId: input.targetSessionId,
|
|
2624
|
+
resumePausedBranch: true,
|
|
2625
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
2626
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
2627
|
+
: {}),
|
|
2628
|
+
});
|
|
2310
2629
|
await lockSessionEventWriteRows(db, {
|
|
2311
2630
|
workspaceId: input.workspaceId,
|
|
2312
2631
|
controlLock: "already_locked",
|
|
@@ -2358,17 +2677,20 @@ export async function steerAgentSessionInTransaction(
|
|
|
2358
2677
|
targetSessionId: input.targetSessionId,
|
|
2359
2678
|
action: "steer",
|
|
2360
2679
|
});
|
|
2361
|
-
const
|
|
2680
|
+
const inheritedConnectionAuthority = await personalConnectionDelegationsForAgentActor(
|
|
2362
2681
|
db,
|
|
2363
2682
|
input.workspaceId,
|
|
2364
2683
|
input.actor,
|
|
2684
|
+
input.targetSessionId,
|
|
2365
2685
|
);
|
|
2686
|
+
const personalConnectionDelegations = inheritedConnectionAuthority.delegations;
|
|
2366
2687
|
const xaiAuthority = await xaiAuthorityForAgentActor(db, input.workspaceId, input.actor);
|
|
2367
2688
|
const resumed = await autoResumeSessionBranchInTransaction(db, {
|
|
2368
2689
|
workspaceId: input.workspaceId,
|
|
2369
2690
|
sessionId: input.targetSessionId,
|
|
2370
2691
|
actor: `attempt:${input.actor.attemptId}`,
|
|
2371
2692
|
reason: "agent_steer",
|
|
2693
|
+
admission,
|
|
2372
2694
|
});
|
|
2373
2695
|
const session = await lockSession(db, input.workspaceId, input.targetSessionId);
|
|
2374
2696
|
if (session.status === "cancelled") {
|
|
@@ -2378,6 +2700,20 @@ export async function steerAgentSessionInTransaction(
|
|
|
2378
2700
|
{ queueVersion: session.queueVersion },
|
|
2379
2701
|
);
|
|
2380
2702
|
}
|
|
2703
|
+
const now = new Date();
|
|
2704
|
+
const updateId = crypto.randomUUID();
|
|
2705
|
+
// An Agent Steer is external input for the target's goal. A goal paused only
|
|
2706
|
+
// by its continuation ceiling (`max_auto_continuations`, pacing rather than
|
|
2707
|
+
// intent) resumes here, before the supersession, so the Steer starts a fresh
|
|
2708
|
+
// continuation epoch; any other pause stays. Goal row FOR UPDATE follows the
|
|
2709
|
+
// session lock above; the `goal.resumed` fact is appended below at the next
|
|
2710
|
+
// sequence of this same commit.
|
|
2711
|
+
const goalAutoResumed = await autoResumeGoalPausedByCapInTransaction(db, {
|
|
2712
|
+
workspaceId: input.workspaceId,
|
|
2713
|
+
sessionId: input.targetSessionId,
|
|
2714
|
+
cause: { kind: "agent_steer_instruction", updateId },
|
|
2715
|
+
now,
|
|
2716
|
+
});
|
|
2381
2717
|
const supersession = await supersedeSessionCurrentDirectionInTransaction(db, {
|
|
2382
2718
|
accountId: input.accountId,
|
|
2383
2719
|
workspaceId: input.workspaceId,
|
|
@@ -2400,13 +2736,13 @@ export async function steerAgentSessionInTransaction(
|
|
|
2400
2736
|
),
|
|
2401
2737
|
)
|
|
2402
2738
|
.returning({ id: schema.sessionSystemUpdates.id });
|
|
2403
|
-
const now = new Date();
|
|
2404
2739
|
const [update] = await db
|
|
2405
2740
|
.insert(schema.sessionSystemUpdates)
|
|
2406
2741
|
.values(
|
|
2407
2742
|
withLosslessContentWriteVersion(
|
|
2408
2743
|
withLosslessContentWriteVersion(
|
|
2409
2744
|
{
|
|
2745
|
+
id: updateId,
|
|
2410
2746
|
accountId: input.accountId,
|
|
2411
2747
|
workspaceId: input.workspaceId,
|
|
2412
2748
|
sessionId: input.targetSessionId,
|
|
@@ -2425,6 +2761,12 @@ export async function steerAgentSessionInTransaction(
|
|
|
2425
2761
|
callerTurnId: input.actor.turnId,
|
|
2426
2762
|
callerAttemptId: input.actor.attemptId,
|
|
2427
2763
|
callerExecutionGeneration: input.actor.executionGeneration,
|
|
2764
|
+
...(inheritedConnectionAuthority.connectionAuthoritySubjectId
|
|
2765
|
+
? {
|
|
2766
|
+
connectionAuthoritySubjectId:
|
|
2767
|
+
inheritedConnectionAuthority.connectionAuthoritySubjectId,
|
|
2768
|
+
}
|
|
2769
|
+
: {}),
|
|
2428
2770
|
...(xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}),
|
|
2429
2771
|
},
|
|
2430
2772
|
personalConnectionDelegations,
|
|
@@ -2506,6 +2848,17 @@ export async function steerAgentSessionInTransaction(
|
|
|
2506
2848
|
occurredAt: now,
|
|
2507
2849
|
},
|
|
2508
2850
|
);
|
|
2851
|
+
if (goalAutoResumed) {
|
|
2852
|
+
events.push({
|
|
2853
|
+
accountId: input.accountId,
|
|
2854
|
+
workspaceId: input.workspaceId,
|
|
2855
|
+
sessionId: input.targetSessionId,
|
|
2856
|
+
sequence: ++sequence,
|
|
2857
|
+
type: "goal.resumed",
|
|
2858
|
+
payload: goalAutoResumed.payload,
|
|
2859
|
+
occurredAt: now,
|
|
2860
|
+
});
|
|
2861
|
+
}
|
|
2509
2862
|
const insertedEvents = await db
|
|
2510
2863
|
.insert(schema.sessionEvents)
|
|
2511
2864
|
.values(withLosslessContentWriteVersion(events, "payload", "payloadCodecVersion"))
|