@opengeni/db 1.0.1 → 3.2.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-4SR4HKKA.js → chunk-2EH4WRHL.js} +19 -11
- package/dist/chunk-2EH4WRHL.js.map +1 -0
- package/dist/{chunk-CUPM3FGB.js → chunk-2PRS4J5Q.js} +3 -3
- package/dist/chunk-6HMM2R5T.js +390 -0
- package/dist/chunk-6HMM2R5T.js.map +1 -0
- package/dist/{chunk-ZWREYEWA.js → chunk-AZHW7R5V.js} +56 -11
- package/dist/chunk-AZHW7R5V.js.map +1 -0
- package/dist/{chunk-LTG3S6ZY.js → chunk-E6CLMKEE.js} +2 -2
- package/dist/{chunk-6ZYKCRFO.js → chunk-KRLPEMLH.js} +7591 -4417
- package/dist/chunk-KRLPEMLH.js.map +1 -0
- package/dist/chunk-NAB6FKFN.js +516 -0
- package/dist/chunk-NAB6FKFN.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-UZNXG44K.js +4508 -0
- package/dist/chunk-UZNXG44K.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 +85 -0
- package/dist/connection-token-resolver.d.ts +30 -1
- package/dist/database.d.ts +23 -4
- 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 +1606 -81
- package/dist/index.js +21898 -8147
- 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 +29 -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 +43 -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 +268 -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 +28 -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/drizzle/0342_slack_route_prompt_single_pending.sql +32 -0
- package/drizzle/0343_personal_document_force_rls_lock_repair.sql +146 -0
- package/drizzle/0344_private_session_visibility_transition_gate.sql +85 -0
- package/drizzle/0345_tenant_scoped_session_tenancy_fence.sql +2839 -0
- package/drizzle/0346_document_migration_audit_surface.sql +454 -0
- package/drizzle/0347_connection_authority_convergence_evidence.sql +396 -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 +167 -0
- package/src/connection-token-resolver.ts +263 -31
- package/src/database.ts +87 -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 +11676 -1550
- 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 +995 -0
- package/src/pr-review.ts +890 -0
- package/src/preference-registry.ts +31 -1
- package/src/provision-roles.ts +905 -6
- package/src/runtime-posture-cli.ts +2 -0
- package/src/runtime-posture.ts +1317 -72
- package/src/schema.ts +3316 -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 +441 -85
- package/src/session-realtime-context.ts +4 -6
- package/src/session-realtime-ledger.ts +28 -14
- package/src/session-realtime-mirror.ts +1 -1
- package/src/session-tenancy.ts +410 -49
- package/src/session-tool-call-settlement.ts +38 -29
- package/src/slack-routing-personal-workspace.ts +67 -0
- package/src/slack-routing.ts +867 -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 +138 -11
- 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-CUPM3FGB.js.map → chunk-2PRS4J5Q.js.map} +0 -0
- /package/dist/{chunk-LTG3S6ZY.js.map → chunk-E6CLMKEE.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
|
}
|
|
@@ -1430,18 +1549,40 @@ export async function submitHumanPromptInTransaction(
|
|
|
1430
1549
|
text: string;
|
|
1431
1550
|
context: string;
|
|
1432
1551
|
};
|
|
1552
|
+
/** False when the human input originated inside the active realtime provider session. */
|
|
1553
|
+
mirrorToRealtime?: boolean;
|
|
1433
1554
|
source: "user" | "api";
|
|
1434
1555
|
/** Record the admitted run's durable usage fact in this transaction. */
|
|
1435
1556
|
recordAgentRunUsage?: boolean;
|
|
1436
1557
|
personalConnectionDelegations?: McpPersonalConnectionDelegation[];
|
|
1558
|
+
personalResourceAttachment?: PersonalResourceAttachmentIntent;
|
|
1437
1559
|
mcpCredentialUpdates?: Array<{
|
|
1438
1560
|
id: string;
|
|
1439
1561
|
headersEncrypted: Record<string, string>;
|
|
1440
1562
|
}>;
|
|
1563
|
+
/** Request-scoped callers bound the control prefix wait; lifecycle callers omit it. */
|
|
1564
|
+
controlLockTimeoutMs?: number;
|
|
1441
1565
|
},
|
|
1442
1566
|
): Promise<SubmitHumanPromptResult> {
|
|
1443
1567
|
const annotations = TimelineAnnotations.parse(input.annotations ?? []);
|
|
1444
|
-
|
|
1568
|
+
// Send is inert queue admission while paused; Steer deliberately resumes.
|
|
1569
|
+
// Tell the lock helper which path may need the exclusive control prefix.
|
|
1570
|
+
const admission = await lockWorkspaceInferenceControlForAdmission(db, {
|
|
1571
|
+
workspaceId: input.workspaceId,
|
|
1572
|
+
sessionId: input.sessionId,
|
|
1573
|
+
resumePausedBranch: input.delivery === "steer",
|
|
1574
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
1575
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
1576
|
+
: {}),
|
|
1577
|
+
});
|
|
1578
|
+
const workspaceControl = admission.control;
|
|
1579
|
+
if (input.actor.type === "human") {
|
|
1580
|
+
await setSubjectRlsContext(db, input.actor.subjectId);
|
|
1581
|
+
await assertActiveManagedHumanOrganizationMembership(db, {
|
|
1582
|
+
accountId: input.accountId,
|
|
1583
|
+
subjectId: input.actor.subjectId,
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1445
1586
|
await lockSessionEventWriteRows(db, {
|
|
1446
1587
|
workspaceId: input.workspaceId,
|
|
1447
1588
|
controlLock: "already_locked",
|
|
@@ -1466,7 +1607,10 @@ export async function submitHumanPromptInTransaction(
|
|
|
1466
1607
|
source: input.source,
|
|
1467
1608
|
turnMetadata: input.turnMetadata ?? {},
|
|
1468
1609
|
messagePresentation: input.messagePresentation ?? null,
|
|
1610
|
+
mirrorToRealtime: input.mirrorToRealtime ?? true,
|
|
1469
1611
|
mcpCredentialUpdates: input.mcpCredentialUpdates ?? [],
|
|
1612
|
+
personalConnectionDelegations: input.personalConnectionDelegations ?? [],
|
|
1613
|
+
personalResourceAttachment: input.personalResourceAttachment ?? null,
|
|
1470
1614
|
...(input.actor.type === "service"
|
|
1471
1615
|
? {
|
|
1472
1616
|
serviceInitiator: {
|
|
@@ -1524,12 +1668,32 @@ export async function submitHumanPromptInTransaction(
|
|
|
1524
1668
|
if (!accepted || !replayTurn || events.length !== eventIds.length) {
|
|
1525
1669
|
throw new SessionControlInvariantError("Replayed prompt rows are incomplete");
|
|
1526
1670
|
}
|
|
1671
|
+
const replayDraft =
|
|
1672
|
+
input.expectedDraftRevision === null || input.expectedDraftRevision === undefined
|
|
1673
|
+
? null
|
|
1674
|
+
: await getComposerDraftInTransaction(db, {
|
|
1675
|
+
workspaceId: input.workspaceId,
|
|
1676
|
+
sessionId: input.sessionId,
|
|
1677
|
+
subjectId: input.subjectId,
|
|
1678
|
+
});
|
|
1527
1679
|
return {
|
|
1528
1680
|
receipt: reserved.receipt,
|
|
1681
|
+
routing:
|
|
1682
|
+
reserved.receipt.result.routing === "accepted_for_execution" ||
|
|
1683
|
+
reserved.receipt.result.routing === "queued_for_execution" ||
|
|
1684
|
+
reserved.receipt.result.routing === "accepted_for_steering"
|
|
1685
|
+
? reserved.receipt.result.routing
|
|
1686
|
+
: input.delivery === "steer"
|
|
1687
|
+
? "accepted_for_steering"
|
|
1688
|
+
: // Pre-routing receipts cannot reconstruct admission-time activity
|
|
1689
|
+
// or Pause truth. Queue is the only conservative placement; a
|
|
1690
|
+
// later turn.started event moves it into chat without duplication.
|
|
1691
|
+
"queued_for_execution",
|
|
1529
1692
|
queueVersion: Number(reserved.receipt.appliedQueueVersion),
|
|
1530
1693
|
accepted,
|
|
1531
1694
|
events,
|
|
1532
1695
|
turn: mapSubmittedPromptTurn(replayTurn),
|
|
1696
|
+
draft: replayDraft,
|
|
1533
1697
|
acceptedEventId,
|
|
1534
1698
|
eventIds,
|
|
1535
1699
|
turnId,
|
|
@@ -1550,34 +1714,39 @@ export async function submitHumanPromptInTransaction(
|
|
|
1550
1714
|
throw new SessionControlConflictError();
|
|
1551
1715
|
}
|
|
1552
1716
|
|
|
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
1717
|
const session = await lockSession(db, input.workspaceId, input.sessionId);
|
|
1571
1718
|
if (session.status === "cancelled") {
|
|
1572
1719
|
throw new QueueCommandConflictError(
|
|
1573
1720
|
"QUEUE_PROMPT_STARTED",
|
|
1574
|
-
"Cancelled session cannot accept work",
|
|
1575
|
-
{
|
|
1576
|
-
queueVersion: session.queueVersion,
|
|
1577
|
-
},
|
|
1721
|
+
"Cancelled session subtree cannot accept work",
|
|
1722
|
+
{ queueVersion: session.queueVersion },
|
|
1578
1723
|
);
|
|
1579
1724
|
}
|
|
1580
1725
|
|
|
1726
|
+
// Send is queue admission, never a hidden control mutation. A paused Send
|
|
1727
|
+
// remains inert behind the existing gate until the user explicitly resumes.
|
|
1728
|
+
// Steer is the intentional exception: it replaces the current direction and
|
|
1729
|
+
// therefore activates the selected branch atomically.
|
|
1730
|
+
const resumed =
|
|
1731
|
+
input.delivery === "send"
|
|
1732
|
+
? {
|
|
1733
|
+
revision: before.controlVersion,
|
|
1734
|
+
control: before,
|
|
1735
|
+
changed: false,
|
|
1736
|
+
workspaceControlEventId: null,
|
|
1737
|
+
}
|
|
1738
|
+
: await autoResumeSessionBranchInTransaction(db, {
|
|
1739
|
+
workspaceId: input.workspaceId,
|
|
1740
|
+
sessionId: input.sessionId,
|
|
1741
|
+
actor:
|
|
1742
|
+
input.actor.type === "agent_attempt"
|
|
1743
|
+
? `attempt:${input.actor.attemptId}`
|
|
1744
|
+
: input.actor.subjectId,
|
|
1745
|
+
reason: input.actor.type === "service" ? "service_steer" : "human_steer",
|
|
1746
|
+
observedControlEtag: input.controlEtag ?? null,
|
|
1747
|
+
admission,
|
|
1748
|
+
});
|
|
1749
|
+
|
|
1581
1750
|
const draft =
|
|
1582
1751
|
input.expectedDraftRevision === null || input.expectedDraftRevision === undefined
|
|
1583
1752
|
? null
|
|
@@ -1710,6 +1879,28 @@ export async function submitHumanPromptInTransaction(
|
|
|
1710
1879
|
input.subjectLabel,
|
|
1711
1880
|
);
|
|
1712
1881
|
}
|
|
1882
|
+
const acceptedInitiatingHumanSubjectId = editedSourceTurn
|
|
1883
|
+
? (editedSourceTurn.initiatingHumanSubjectId ??
|
|
1884
|
+
(editedSourceTurn.initiatorKind === "subject" ? editedSourceTurn.initiatorSubjectId : null))
|
|
1885
|
+
: (frozenInitiator.initiatingHumanSubjectId ??
|
|
1886
|
+
(frozenInitiator.initiator.kind === "subject" ? frozenInitiator.initiator.subjectId : null));
|
|
1887
|
+
if (
|
|
1888
|
+
(input.personalConnectionDelegations ?? []).some(
|
|
1889
|
+
(delegation) => delegation.userDelegation !== undefined,
|
|
1890
|
+
) ||
|
|
1891
|
+
input.personalResourceAttachment !== undefined
|
|
1892
|
+
) {
|
|
1893
|
+
if (!acceptedInitiatingHumanSubjectId) {
|
|
1894
|
+
throw new SessionControlInvariantError("Personal authority requires an exact causal human");
|
|
1895
|
+
}
|
|
1896
|
+
await db.execute(
|
|
1897
|
+
sql`select set_config(
|
|
1898
|
+
'opengeni.initiating_human_subject_id',
|
|
1899
|
+
${acceptedInitiatingHumanSubjectId},
|
|
1900
|
+
true
|
|
1901
|
+
)`,
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1713
1904
|
const xaiProviderAccountAuthoritySnapshot = editedSourceTurn
|
|
1714
1905
|
? XaiProviderAccountAuthoritySnapshotV1.parse(
|
|
1715
1906
|
editedSourceTurn.xaiProviderAccountAuthoritySnapshot,
|
|
@@ -1726,6 +1917,13 @@ export async function submitHumanPromptInTransaction(
|
|
|
1726
1917
|
editedSourceModelContext !== undefined
|
|
1727
1918
|
? editedSourceModelContext
|
|
1728
1919
|
: (input.modelContext ?? null);
|
|
1920
|
+
const existingQueued = await loadQueuedTurns(db, input.workspaceId, input.sessionId, true);
|
|
1921
|
+
const routing: SessionPromptRouting =
|
|
1922
|
+
input.delivery === "steer"
|
|
1923
|
+
? "accepted_for_steering"
|
|
1924
|
+
: before.state === "paused" || session.activeTurnId || existingQueued.length > 0
|
|
1925
|
+
? "queued_for_execution"
|
|
1926
|
+
: "accepted_for_execution";
|
|
1729
1927
|
let sequence = session.lastSequence;
|
|
1730
1928
|
const eventValues: SessionEventInsertWithPayload[] = [
|
|
1731
1929
|
{
|
|
@@ -1753,12 +1951,12 @@ export async function submitHumanPromptInTransaction(
|
|
|
1753
1951
|
...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),
|
|
1754
1952
|
...(input.latencyMode ? { latencyMode: input.latencyMode } : {}),
|
|
1755
1953
|
delivery: input.delivery,
|
|
1954
|
+
routing,
|
|
1756
1955
|
initiator: frozenInitiator.initiator,
|
|
1757
1956
|
},
|
|
1758
1957
|
occurredAt: now,
|
|
1759
1958
|
},
|
|
1760
1959
|
];
|
|
1761
|
-
const existingQueued = await loadQueuedTurns(db, input.workspaceId, input.sessionId, true);
|
|
1762
1960
|
const [turn] = await db
|
|
1763
1961
|
.insert(schema.sessionTurns)
|
|
1764
1962
|
.values(
|
|
@@ -1772,6 +1970,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
1772
1970
|
temporalWorkflowId: workflowId,
|
|
1773
1971
|
status: "queued",
|
|
1774
1972
|
source: input.source,
|
|
1973
|
+
promptRouting: routing,
|
|
1775
1974
|
position: input.delivery === "steer" ? 0 : existingQueued.length + 1,
|
|
1776
1975
|
prompt: input.text,
|
|
1777
1976
|
annotations,
|
|
@@ -1788,14 +1987,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
1788
1987
|
: (input.turnMetadata ?? {}),
|
|
1789
1988
|
lineage: { actor: input.actor.type },
|
|
1790
1989
|
...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,
|
|
1990
|
+
initiatingHumanSubjectId: acceptedInitiatingHumanSubjectId,
|
|
1799
1991
|
personalConnectionDelegations: editedSourceTurn
|
|
1800
1992
|
? editedSourceTurn.personalConnectionDelegations
|
|
1801
1993
|
: (input.personalConnectionDelegations ?? []),
|
|
@@ -1810,6 +2002,49 @@ export async function submitHumanPromptInTransaction(
|
|
|
1810
2002
|
.returning();
|
|
1811
2003
|
if (!turn) throw new SessionControlInvariantError("Prompt turn was not inserted");
|
|
1812
2004
|
let committedTurn = turn;
|
|
2005
|
+
const personalResourceExpectedAuthorityEpoch =
|
|
2006
|
+
input.personalResourceAttachment?.expectedAuthorityEpoch;
|
|
2007
|
+
let acceptedPersonalResources: Awaited<
|
|
2008
|
+
ReturnType<typeof acceptTurnPersonalResourceAttachmentInTransaction>
|
|
2009
|
+
> | null = null;
|
|
2010
|
+
if (input.personalResourceAttachment) {
|
|
2011
|
+
if (personalResourceExpectedAuthorityEpoch === undefined) {
|
|
2012
|
+
throw new SessionControlInvariantError(
|
|
2013
|
+
"Personal-resource attachment requires an expected authority epoch",
|
|
2014
|
+
);
|
|
2015
|
+
}
|
|
2016
|
+
acceptedPersonalResources = await acceptTurnPersonalResourceAttachmentInTransaction(db, {
|
|
2017
|
+
accountId: input.accountId,
|
|
2018
|
+
workspaceId: input.workspaceId,
|
|
2019
|
+
sessionId: input.sessionId,
|
|
2020
|
+
turnId,
|
|
2021
|
+
subjectId: acceptedInitiatingHumanSubjectId!,
|
|
2022
|
+
intent: {
|
|
2023
|
+
...input.personalResourceAttachment,
|
|
2024
|
+
expectedAuthorityEpoch: personalResourceExpectedAuthorityEpoch,
|
|
2025
|
+
},
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
2028
|
+
if (acceptedPersonalResources) {
|
|
2029
|
+
committedTurn = {
|
|
2030
|
+
...turn,
|
|
2031
|
+
personalResourceAttachmentSummary: acceptedPersonalResources.summary,
|
|
2032
|
+
personalResourceProtocolVersion: 1,
|
|
2033
|
+
};
|
|
2034
|
+
eventValues.push({
|
|
2035
|
+
accountId: input.accountId,
|
|
2036
|
+
workspaceId: input.workspaceId,
|
|
2037
|
+
sessionId: input.sessionId,
|
|
2038
|
+
turnId,
|
|
2039
|
+
sequence: ++sequence,
|
|
2040
|
+
type: "session.personal_resources.attached",
|
|
2041
|
+
payload: {
|
|
2042
|
+
turnId,
|
|
2043
|
+
...acceptedPersonalResources.summary,
|
|
2044
|
+
},
|
|
2045
|
+
occurredAt: now,
|
|
2046
|
+
});
|
|
2047
|
+
}
|
|
1813
2048
|
eventValues.push({
|
|
1814
2049
|
accountId: input.accountId,
|
|
1815
2050
|
workspaceId: input.workspaceId,
|
|
@@ -1821,6 +2056,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
1821
2056
|
turnId,
|
|
1822
2057
|
triggerEventId: acceptedEventId,
|
|
1823
2058
|
source: input.source,
|
|
2059
|
+
routing,
|
|
1824
2060
|
initiator: frozenInitiator.initiator,
|
|
1825
2061
|
},
|
|
1826
2062
|
occurredAt: now,
|
|
@@ -1919,6 +2155,29 @@ export async function submitHumanPromptInTransaction(
|
|
|
1919
2155
|
});
|
|
1920
2156
|
}
|
|
1921
2157
|
|
|
2158
|
+
// A human/API prompt is external input for the goal. A goal paused only by
|
|
2159
|
+
// its continuation ceiling (`max_auto_continuations`, pacing rather than
|
|
2160
|
+
// intent) resumes in this same commit; a user/API/agent/limits pause is never
|
|
2161
|
+
// touched here. Goal row FOR UPDATE follows the session and turn locks above,
|
|
2162
|
+
// the order the claim transaction uses.
|
|
2163
|
+
const goalAutoResumed = await autoResumeGoalPausedByCapInTransaction(db, {
|
|
2164
|
+
workspaceId: input.workspaceId,
|
|
2165
|
+
sessionId: input.sessionId,
|
|
2166
|
+
cause: { kind: "human_prompt", turnId },
|
|
2167
|
+
now,
|
|
2168
|
+
});
|
|
2169
|
+
if (goalAutoResumed) {
|
|
2170
|
+
eventValues.push({
|
|
2171
|
+
accountId: input.accountId,
|
|
2172
|
+
workspaceId: input.workspaceId,
|
|
2173
|
+
sessionId: input.sessionId,
|
|
2174
|
+
sequence: ++sequence,
|
|
2175
|
+
type: "goal.resumed",
|
|
2176
|
+
payload: goalAutoResumed.payload,
|
|
2177
|
+
occurredAt: now,
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
|
|
1922
2181
|
const ordered =
|
|
1923
2182
|
input.delivery === "steer" ? [turn, ...existingQueued] : [...existingQueued, turn];
|
|
1924
2183
|
await normalizeQueuePositions(
|
|
@@ -1945,13 +2204,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
1945
2204
|
.insert(schema.sessionEvents)
|
|
1946
2205
|
.values(withLosslessContentWriteVersion(eventValues, "payload", "payloadCodecVersion"))
|
|
1947
2206
|
.returning();
|
|
1948
|
-
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";
|
|
2207
|
+
if (input.actor.type === "human" && input.mirrorToRealtime !== false) {
|
|
1955
2208
|
await mirrorSessionRealtimeContextInTransaction(db, {
|
|
1956
2209
|
accountId: input.accountId,
|
|
1957
2210
|
workspaceId: input.workspaceId,
|
|
@@ -1962,12 +2215,12 @@ export async function submitHumanPromptInTransaction(
|
|
|
1962
2215
|
channel: null,
|
|
1963
2216
|
text: renderRealtimeHumanInputContext({
|
|
1964
2217
|
delivery: input.delivery,
|
|
1965
|
-
routing
|
|
2218
|
+
routing,
|
|
1966
2219
|
text: renderTimelineAnnotationsForModel(input.text, annotations),
|
|
1967
2220
|
}),
|
|
1968
2221
|
payload: {
|
|
1969
2222
|
delivery: input.delivery,
|
|
1970
|
-
routing
|
|
2223
|
+
routing,
|
|
1971
2224
|
acceptedEventId,
|
|
1972
2225
|
instruction: "OpenGeni accepted and routed this user input; do not delegate it again.",
|
|
1973
2226
|
},
|
|
@@ -1989,8 +2242,25 @@ export async function submitHumanPromptInTransaction(
|
|
|
1989
2242
|
updatedAt: now,
|
|
1990
2243
|
})
|
|
1991
2244
|
.where(eq(schema.sessions.id, input.sessionId));
|
|
1992
|
-
|
|
1993
|
-
await db
|
|
2245
|
+
const [nextDraft] = draft
|
|
2246
|
+
? await db
|
|
2247
|
+
.update(schema.composerDrafts)
|
|
2248
|
+
.set({
|
|
2249
|
+
revision: draft.revision + 1,
|
|
2250
|
+
text: "",
|
|
2251
|
+
annotations: [],
|
|
2252
|
+
resources: [],
|
|
2253
|
+
tools: [],
|
|
2254
|
+
toolsProvided: false,
|
|
2255
|
+
sourceTurnId: null,
|
|
2256
|
+
sourceTurnVersion: null,
|
|
2257
|
+
updatedAt: now,
|
|
2258
|
+
})
|
|
2259
|
+
.where(eq(schema.composerDrafts.id, draft.id))
|
|
2260
|
+
.returning()
|
|
2261
|
+
: [undefined];
|
|
2262
|
+
if (draft && !nextDraft) {
|
|
2263
|
+
throw new SessionControlInvariantError("Accepted composer draft did not rotate");
|
|
1994
2264
|
}
|
|
1995
2265
|
const wakeRevision = await registerSessionWorkflowWakeInTransaction(db, {
|
|
1996
2266
|
accountId: input.accountId,
|
|
@@ -2051,7 +2321,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
2051
2321
|
controlRevision: resumed.revision,
|
|
2052
2322
|
queueVersion,
|
|
2053
2323
|
turnVersion: turn.version,
|
|
2054
|
-
...(
|
|
2324
|
+
...(nextDraft ? { draftRevision: nextDraft.revision } : {}),
|
|
2055
2325
|
result: {
|
|
2056
2326
|
turnId,
|
|
2057
2327
|
acceptedEventId,
|
|
@@ -2060,6 +2330,7 @@ export async function submitHumanPromptInTransaction(
|
|
|
2060
2330
|
interruptionCount,
|
|
2061
2331
|
replacedTurnId,
|
|
2062
2332
|
workspaceControlEventId: resumed.workspaceControlEventId,
|
|
2333
|
+
routing,
|
|
2063
2334
|
...(input.turnExecutionPolicy
|
|
2064
2335
|
? {
|
|
2065
2336
|
executionPolicy: turnExecutionPolicyAuditMetadata(input.turnExecutionPolicy, turnId),
|
|
@@ -2074,10 +2345,12 @@ export async function submitHumanPromptInTransaction(
|
|
|
2074
2345
|
}
|
|
2075
2346
|
return {
|
|
2076
2347
|
receipt,
|
|
2348
|
+
routing,
|
|
2077
2349
|
queueVersion,
|
|
2078
2350
|
accepted,
|
|
2079
2351
|
events,
|
|
2080
2352
|
turn: mapSubmittedPromptTurn(committedTurn),
|
|
2353
|
+
draft: nextDraft ?? null,
|
|
2081
2354
|
acceptedEventId,
|
|
2082
2355
|
eventIds,
|
|
2083
2356
|
turnId,
|
|
@@ -2097,9 +2370,18 @@ export async function sendAgentMessageInTransaction(
|
|
|
2097
2370
|
actor: Extract<SessionCommandActor, { type: "agent_attempt" }>;
|
|
2098
2371
|
operationKey: string;
|
|
2099
2372
|
text: string;
|
|
2373
|
+
/**
|
|
2374
|
+
* Bound the workspace control prefix wait (request-scoped API callers pass
|
|
2375
|
+
* `workspaceControlRequestLockTimeoutMs()`); omit for lifecycle callers.
|
|
2376
|
+
*/
|
|
2377
|
+
controlLockTimeoutMs?: number;
|
|
2100
2378
|
},
|
|
2101
2379
|
): Promise<AgentInternalUpdateCommandResult> {
|
|
2102
|
-
const workspaceControl = await lockWorkspaceInferenceControl(db, input.workspaceId, "share"
|
|
2380
|
+
const workspaceControl = await lockWorkspaceInferenceControl(db, input.workspaceId, "share", {
|
|
2381
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
2382
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
2383
|
+
: {}),
|
|
2384
|
+
});
|
|
2103
2385
|
await lockSessionEventWriteRows(db, {
|
|
2104
2386
|
workspaceId: input.workspaceId,
|
|
2105
2387
|
controlLock: "already_locked",
|
|
@@ -2148,11 +2430,13 @@ export async function sendAgentMessageInTransaction(
|
|
|
2148
2430
|
targetSessionId: input.targetSessionId,
|
|
2149
2431
|
action: "message",
|
|
2150
2432
|
});
|
|
2151
|
-
const
|
|
2433
|
+
const inheritedConnectionAuthority = await personalConnectionDelegationsForAgentActor(
|
|
2152
2434
|
db,
|
|
2153
2435
|
input.workspaceId,
|
|
2154
2436
|
input.actor,
|
|
2437
|
+
input.targetSessionId,
|
|
2155
2438
|
);
|
|
2439
|
+
const personalConnectionDelegations = inheritedConnectionAuthority.delegations;
|
|
2156
2440
|
const xaiAuthority = await xaiAuthorityForAgentActor(db, input.workspaceId, input.actor);
|
|
2157
2441
|
const session = await lockSession(db, input.workspaceId, input.targetSessionId);
|
|
2158
2442
|
if (session.status === "cancelled") {
|
|
@@ -2195,6 +2479,12 @@ export async function sendAgentMessageInTransaction(
|
|
|
2195
2479
|
callerTurnId: input.actor.turnId,
|
|
2196
2480
|
callerAttemptId: input.actor.attemptId,
|
|
2197
2481
|
callerExecutionGeneration: input.actor.executionGeneration,
|
|
2482
|
+
...(inheritedConnectionAuthority.connectionAuthoritySubjectId
|
|
2483
|
+
? {
|
|
2484
|
+
connectionAuthoritySubjectId:
|
|
2485
|
+
inheritedConnectionAuthority.connectionAuthoritySubjectId,
|
|
2486
|
+
}
|
|
2487
|
+
: {}),
|
|
2198
2488
|
...(xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}),
|
|
2199
2489
|
},
|
|
2200
2490
|
personalConnectionDelegations,
|
|
@@ -2210,29 +2500,52 @@ export async function sendAgentMessageInTransaction(
|
|
|
2210
2500
|
)
|
|
2211
2501
|
.returning({ id: schema.sessionSystemUpdates.id });
|
|
2212
2502
|
if (!update) throw new SessionControlInvariantError("Agent message was not inserted");
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2503
|
+
// An Agent message is external input for the target's goal. A goal paused
|
|
2504
|
+
// only by its continuation ceiling (`max_auto_continuations`, pacing rather
|
|
2505
|
+
// than intent) resumes in this same commit; any other pause stays. Goal row
|
|
2506
|
+
// FOR UPDATE follows the session lock above, the goal tools' order.
|
|
2507
|
+
const goalAutoResumed = await autoResumeGoalPausedByCapInTransaction(db, {
|
|
2508
|
+
workspaceId: input.workspaceId,
|
|
2509
|
+
sessionId: input.targetSessionId,
|
|
2510
|
+
cause: { kind: "agent_message", updateId: update.id },
|
|
2511
|
+
now,
|
|
2512
|
+
});
|
|
2513
|
+
const eventValues: SessionEventInsertWithPayload[] = [
|
|
2514
|
+
{
|
|
2515
|
+
accountId: input.accountId,
|
|
2516
|
+
workspaceId: input.workspaceId,
|
|
2517
|
+
sessionId: input.targetSessionId,
|
|
2518
|
+
sequence: session.lastSequence + 1,
|
|
2519
|
+
type: "system.update.pending",
|
|
2520
|
+
payload: {
|
|
2521
|
+
updateId: update.id,
|
|
2522
|
+
kind: "agent_message",
|
|
2523
|
+
sourceSessionId: input.actor.sessionId,
|
|
2524
|
+
},
|
|
2525
|
+
occurredAt: now,
|
|
2526
|
+
},
|
|
2527
|
+
...(goalAutoResumed
|
|
2528
|
+
? [
|
|
2529
|
+
{
|
|
2530
|
+
accountId: input.accountId,
|
|
2531
|
+
workspaceId: input.workspaceId,
|
|
2532
|
+
sessionId: input.targetSessionId,
|
|
2533
|
+
sequence: session.lastSequence + 2,
|
|
2534
|
+
type: "goal.resumed" as const,
|
|
2535
|
+
payload: goalAutoResumed.payload,
|
|
2536
|
+
occurredAt: now,
|
|
2227
2537
|
},
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
)
|
|
2538
|
+
]
|
|
2539
|
+
: []),
|
|
2540
|
+
];
|
|
2541
|
+
const insertedEvents = await db
|
|
2542
|
+
.insert(schema.sessionEvents)
|
|
2543
|
+
.values(withLosslessContentWriteVersion(eventValues, "payload", "payloadCodecVersion"))
|
|
2234
2544
|
.returning({ id: schema.sessionEvents.id });
|
|
2235
|
-
if (
|
|
2545
|
+
if (insertedEvents.length !== eventValues.length) {
|
|
2546
|
+
throw new SessionControlInvariantError("Agent message event was not inserted");
|
|
2547
|
+
}
|
|
2548
|
+
const eventIds = insertedEvents.map((event) => event.id);
|
|
2236
2549
|
const workflowId = session.temporalWorkflowId ?? `session-${session.id}`;
|
|
2237
2550
|
const runnable = !realtimeActive && session.activeTurnId === null && effective.state === "active";
|
|
2238
2551
|
const wake = runnable
|
|
@@ -2246,7 +2559,7 @@ export async function sendAgentMessageInTransaction(
|
|
|
2246
2559
|
await db
|
|
2247
2560
|
.update(schema.sessions)
|
|
2248
2561
|
.set({
|
|
2249
|
-
lastSequence: session.lastSequence +
|
|
2562
|
+
lastSequence: session.lastSequence + eventValues.length,
|
|
2250
2563
|
...(runnable ? { status: "queued" as const } : {}),
|
|
2251
2564
|
updatedAt: now,
|
|
2252
2565
|
})
|
|
@@ -2275,7 +2588,7 @@ export async function sendAgentMessageInTransaction(
|
|
|
2275
2588
|
const receipt = await updateSessionCommandReceiptResult(db, reserved.receipt.id, {
|
|
2276
2589
|
result: {
|
|
2277
2590
|
updateId: update.id,
|
|
2278
|
-
eventIds
|
|
2591
|
+
eventIds,
|
|
2279
2592
|
wakeRevision: wake?.wakeRevision ?? null,
|
|
2280
2593
|
workflowId,
|
|
2281
2594
|
effectiveState: effective.state,
|
|
@@ -2284,7 +2597,7 @@ export async function sendAgentMessageInTransaction(
|
|
|
2284
2597
|
return {
|
|
2285
2598
|
receipt,
|
|
2286
2599
|
updateId: update.id,
|
|
2287
|
-
eventIds
|
|
2600
|
+
eventIds,
|
|
2288
2601
|
wakeRevision: wake?.wakeRevision ?? null,
|
|
2289
2602
|
shouldSignal: wake?.shouldSignal ?? false,
|
|
2290
2603
|
workflowId,
|
|
@@ -2304,9 +2617,18 @@ export async function steerAgentSessionInTransaction(
|
|
|
2304
2617
|
actor: Extract<SessionCommandActor, { type: "agent_attempt" }>;
|
|
2305
2618
|
operationKey: string;
|
|
2306
2619
|
instruction: string;
|
|
2620
|
+
/** Request-scoped callers bound the control prefix wait; lifecycle callers omit it. */
|
|
2621
|
+
controlLockTimeoutMs?: number;
|
|
2307
2622
|
},
|
|
2308
2623
|
): Promise<AgentInternalUpdateCommandResult> {
|
|
2309
|
-
await
|
|
2624
|
+
const admission = await lockWorkspaceInferenceControlForAdmission(db, {
|
|
2625
|
+
workspaceId: input.workspaceId,
|
|
2626
|
+
sessionId: input.targetSessionId,
|
|
2627
|
+
resumePausedBranch: true,
|
|
2628
|
+
...(input.controlLockTimeoutMs !== undefined
|
|
2629
|
+
? { lockTimeoutMs: input.controlLockTimeoutMs }
|
|
2630
|
+
: {}),
|
|
2631
|
+
});
|
|
2310
2632
|
await lockSessionEventWriteRows(db, {
|
|
2311
2633
|
workspaceId: input.workspaceId,
|
|
2312
2634
|
controlLock: "already_locked",
|
|
@@ -2358,17 +2680,20 @@ export async function steerAgentSessionInTransaction(
|
|
|
2358
2680
|
targetSessionId: input.targetSessionId,
|
|
2359
2681
|
action: "steer",
|
|
2360
2682
|
});
|
|
2361
|
-
const
|
|
2683
|
+
const inheritedConnectionAuthority = await personalConnectionDelegationsForAgentActor(
|
|
2362
2684
|
db,
|
|
2363
2685
|
input.workspaceId,
|
|
2364
2686
|
input.actor,
|
|
2687
|
+
input.targetSessionId,
|
|
2365
2688
|
);
|
|
2689
|
+
const personalConnectionDelegations = inheritedConnectionAuthority.delegations;
|
|
2366
2690
|
const xaiAuthority = await xaiAuthorityForAgentActor(db, input.workspaceId, input.actor);
|
|
2367
2691
|
const resumed = await autoResumeSessionBranchInTransaction(db, {
|
|
2368
2692
|
workspaceId: input.workspaceId,
|
|
2369
2693
|
sessionId: input.targetSessionId,
|
|
2370
2694
|
actor: `attempt:${input.actor.attemptId}`,
|
|
2371
2695
|
reason: "agent_steer",
|
|
2696
|
+
admission,
|
|
2372
2697
|
});
|
|
2373
2698
|
const session = await lockSession(db, input.workspaceId, input.targetSessionId);
|
|
2374
2699
|
if (session.status === "cancelled") {
|
|
@@ -2378,6 +2703,20 @@ export async function steerAgentSessionInTransaction(
|
|
|
2378
2703
|
{ queueVersion: session.queueVersion },
|
|
2379
2704
|
);
|
|
2380
2705
|
}
|
|
2706
|
+
const now = new Date();
|
|
2707
|
+
const updateId = crypto.randomUUID();
|
|
2708
|
+
// An Agent Steer is external input for the target's goal. A goal paused only
|
|
2709
|
+
// by its continuation ceiling (`max_auto_continuations`, pacing rather than
|
|
2710
|
+
// intent) resumes here, before the supersession, so the Steer starts a fresh
|
|
2711
|
+
// continuation epoch; any other pause stays. Goal row FOR UPDATE follows the
|
|
2712
|
+
// session lock above; the `goal.resumed` fact is appended below at the next
|
|
2713
|
+
// sequence of this same commit.
|
|
2714
|
+
const goalAutoResumed = await autoResumeGoalPausedByCapInTransaction(db, {
|
|
2715
|
+
workspaceId: input.workspaceId,
|
|
2716
|
+
sessionId: input.targetSessionId,
|
|
2717
|
+
cause: { kind: "agent_steer_instruction", updateId },
|
|
2718
|
+
now,
|
|
2719
|
+
});
|
|
2381
2720
|
const supersession = await supersedeSessionCurrentDirectionInTransaction(db, {
|
|
2382
2721
|
accountId: input.accountId,
|
|
2383
2722
|
workspaceId: input.workspaceId,
|
|
@@ -2400,13 +2739,13 @@ export async function steerAgentSessionInTransaction(
|
|
|
2400
2739
|
),
|
|
2401
2740
|
)
|
|
2402
2741
|
.returning({ id: schema.sessionSystemUpdates.id });
|
|
2403
|
-
const now = new Date();
|
|
2404
2742
|
const [update] = await db
|
|
2405
2743
|
.insert(schema.sessionSystemUpdates)
|
|
2406
2744
|
.values(
|
|
2407
2745
|
withLosslessContentWriteVersion(
|
|
2408
2746
|
withLosslessContentWriteVersion(
|
|
2409
2747
|
{
|
|
2748
|
+
id: updateId,
|
|
2410
2749
|
accountId: input.accountId,
|
|
2411
2750
|
workspaceId: input.workspaceId,
|
|
2412
2751
|
sessionId: input.targetSessionId,
|
|
@@ -2425,6 +2764,12 @@ export async function steerAgentSessionInTransaction(
|
|
|
2425
2764
|
callerTurnId: input.actor.turnId,
|
|
2426
2765
|
callerAttemptId: input.actor.attemptId,
|
|
2427
2766
|
callerExecutionGeneration: input.actor.executionGeneration,
|
|
2767
|
+
...(inheritedConnectionAuthority.connectionAuthoritySubjectId
|
|
2768
|
+
? {
|
|
2769
|
+
connectionAuthoritySubjectId:
|
|
2770
|
+
inheritedConnectionAuthority.connectionAuthoritySubjectId,
|
|
2771
|
+
}
|
|
2772
|
+
: {}),
|
|
2428
2773
|
...(xaiAuthority.subjectId ? { xaiAuthoritySubjectId: xaiAuthority.subjectId } : {}),
|
|
2429
2774
|
},
|
|
2430
2775
|
personalConnectionDelegations,
|
|
@@ -2506,6 +2851,17 @@ export async function steerAgentSessionInTransaction(
|
|
|
2506
2851
|
occurredAt: now,
|
|
2507
2852
|
},
|
|
2508
2853
|
);
|
|
2854
|
+
if (goalAutoResumed) {
|
|
2855
|
+
events.push({
|
|
2856
|
+
accountId: input.accountId,
|
|
2857
|
+
workspaceId: input.workspaceId,
|
|
2858
|
+
sessionId: input.targetSessionId,
|
|
2859
|
+
sequence: ++sequence,
|
|
2860
|
+
type: "goal.resumed",
|
|
2861
|
+
payload: goalAutoResumed.payload,
|
|
2862
|
+
occurredAt: now,
|
|
2863
|
+
});
|
|
2864
|
+
}
|
|
2509
2865
|
const insertedEvents = await db
|
|
2510
2866
|
.insert(schema.sessionEvents)
|
|
2511
2867
|
.values(withLosslessContentWriteVersion(events, "payload", "payloadCodecVersion"))
|