@opengeni/core 0.4.7 → 0.4.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/core",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "OpenGeni framework-agnostic core: the domain, access, and billing layers (neutral access, off-HTTP V2 surface). Behavior-preserving extraction from apps/api — keeps Hono's HTTPException for error throwing (typed-errors cleanup deferred).",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -34,15 +34,15 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@modelcontextprotocol/sdk": "^1.29.0",
37
- "@opengeni/codex": "^0.2.2",
38
- "@opengeni/config": "^0.5.0",
37
+ "@opengeni/codex": "^0.2.3",
38
+ "@opengeni/config": "^0.5.1",
39
39
  "@opengeni/contracts": "^0.10.0",
40
- "@opengeni/db": "^0.7.0",
41
- "@opengeni/documents": "^0.2.9",
42
- "@opengeni/events": "^0.3.0",
40
+ "@opengeni/db": "^0.7.2",
41
+ "@opengeni/documents": "^0.2.11",
42
+ "@opengeni/events": "^0.3.2",
43
43
  "@opengeni/observability": "^0.3.0",
44
- "@opengeni/runtime": "^0.7.0",
45
- "@opengeni/storage": "^0.2.9",
44
+ "@opengeni/runtime": "^0.7.1",
45
+ "@opengeni/storage": "^0.2.10",
46
46
  "hono": "^4.12.18"
47
47
  },
48
48
  "engines": {
@@ -235,6 +235,10 @@ async function delegatedAccessContext(
235
235
  // Caller identity: the turn that minted this token. Tools classify the
236
236
  // CALLER from this instead of re-reading the live active pointer.
237
237
  ...(payload.turnId ? { turnId: payload.turnId } : {}),
238
+ ...(payload.attemptId ? { attemptId: payload.attemptId } : {}),
239
+ ...(payload.executionGeneration
240
+ ? { executionGeneration: payload.executionGeneration }
241
+ : {}),
238
242
  },
239
243
  },
240
244
  ],
@@ -0,0 +1,527 @@
1
+ import type {
2
+ ComposerDraft,
3
+ DeleteSessionQueueItemRequest,
4
+ EditSessionQueueItemRequest,
5
+ MoveSessionQueueItemRequest,
6
+ SaveComposerDraftRequest,
7
+ SessionCommandReceipt,
8
+ SessionControlRequest,
9
+ SessionControlResponse,
10
+ SessionQueueMutationResponse,
11
+ SteerSessionQueueItemRequest,
12
+ WorkspaceInferenceControlRequest,
13
+ WorkspaceInferenceControlResponse,
14
+ } from "@opengeni/contracts";
15
+ import { reasoningEffortForMetadata } from "@opengeni/contracts";
16
+ import {
17
+ deleteSessionQueueItemInTransaction,
18
+ editQueuedTurnInTransaction,
19
+ getComposerDraftInTransaction,
20
+ getSession,
21
+ getSessionEvent,
22
+ getWorkspaceControlEvent,
23
+ getSessionQueueSnapshot,
24
+ moveQueuedTurnInTransaction,
25
+ mutateSessionControlInTransaction,
26
+ mutateWorkspaceControlInTransaction,
27
+ saveComposerDraftInTransaction,
28
+ sendAgentMessageInTransaction,
29
+ serializeEffectiveSessionControl,
30
+ steerAgentSessionInTransaction,
31
+ steerQueuedTurnInTransaction,
32
+ withWorkspaceRls,
33
+ withWorkspaceSubjectRls,
34
+ type Database,
35
+ type SessionCommandReceiptRow,
36
+ } from "@opengeni/db";
37
+ import {
38
+ publishDurableSessionEvents,
39
+ publishDurableWorkspaceControlEvent,
40
+ type EventBus,
41
+ } from "@opengeni/events";
42
+ import type { SessionWorkflowClient } from "../dependencies";
43
+
44
+ export type HumanSessionCommandContext = {
45
+ accountId: string;
46
+ workspaceId: string;
47
+ sessionId: string;
48
+ subjectId: string;
49
+ };
50
+
51
+ export type AgentSessionCommandContext = {
52
+ accountId: string;
53
+ workspaceId: string;
54
+ callerSessionId: string;
55
+ callerTurnId: string;
56
+ callerAttemptId: string;
57
+ callerExecutionGeneration: number;
58
+ };
59
+
60
+ function agentActor(context: AgentSessionCommandContext) {
61
+ return {
62
+ type: "agent_attempt" as const,
63
+ sessionId: context.callerSessionId,
64
+ turnId: context.callerTurnId,
65
+ attemptId: context.callerAttemptId,
66
+ executionGeneration: context.callerExecutionGeneration,
67
+ };
68
+ }
69
+
70
+ async function publishAndWakeAgentCommand(
71
+ deps: {
72
+ db: Database;
73
+ bus: EventBus;
74
+ workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
75
+ },
76
+ input: {
77
+ accountId: string;
78
+ workspaceId: string;
79
+ sessionId: string;
80
+ eventIds: string[];
81
+ workflowId: string;
82
+ wakeRevision: number | null;
83
+ shouldSignal: boolean;
84
+ interruptionCount: number;
85
+ },
86
+ ): Promise<void> {
87
+ await publishSessionEventIds(deps, input.workspaceId, input.sessionId, input.eventIds);
88
+ if (!input.shouldSignal || input.wakeRevision === null) return;
89
+ try {
90
+ await deps.workflowClient.wakeSessionWorkflow({
91
+ accountId: input.accountId,
92
+ workspaceId: input.workspaceId,
93
+ sessionId: input.sessionId,
94
+ workflowId: input.workflowId,
95
+ wakeRevision: input.wakeRevision,
96
+ ...(input.interruptionCount > 0 ? { interruptionRequested: true } : {}),
97
+ });
98
+ } catch (error) {
99
+ console.warn(
100
+ `[session-commands] immediate Agent command wake failed for ${input.workspaceId}/${input.sessionId}; durable outbox will retry`,
101
+ error,
102
+ );
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Nudge the one bounded dispatcher after a set-based control transaction. The
108
+ * API never materializes descendant session ids; Postgres remains the complete
109
+ * wake ledger and the 10-second Schedule repairs a lost immediate trigger.
110
+ */
111
+ async function requestControlWakeDispatch(
112
+ deps: {
113
+ workflowClient: Pick<SessionWorkflowClient, "requestSessionWorkflowWakeDispatch">;
114
+ },
115
+ wakeCount: number,
116
+ ): Promise<void> {
117
+ if (wakeCount === 0) return;
118
+ try {
119
+ await deps.workflowClient.requestSessionWorkflowWakeDispatch();
120
+ } catch (error) {
121
+ console.warn(
122
+ `[session-commands] immediate control wake dispatch failed for ${wakeCount} committed revisions; durable outbox will retry`,
123
+ error,
124
+ );
125
+ }
126
+ }
127
+
128
+ async function publishSessionEventIds(
129
+ deps: { db: Database; bus: EventBus },
130
+ workspaceId: string,
131
+ sessionId: string,
132
+ eventIds: string[],
133
+ ): Promise<void> {
134
+ if (eventIds.length === 0) return;
135
+ const events = await Promise.all(
136
+ eventIds.map((eventId) => getSessionEvent(deps.db, workspaceId, eventId)),
137
+ );
138
+ await publishDurableSessionEvents(
139
+ deps.bus,
140
+ workspaceId,
141
+ sessionId,
142
+ events.filter((event): event is NonNullable<typeof event> => event !== null),
143
+ );
144
+ }
145
+
146
+ async function publishWorkspaceControlEvent(
147
+ deps: { db: Database; bus: EventBus },
148
+ workspaceId: string,
149
+ eventId: string | null,
150
+ ): Promise<void> {
151
+ if (!eventId) return;
152
+ const event = await getWorkspaceControlEvent(deps.db, workspaceId, eventId);
153
+ if (!event) {
154
+ throw new Error(`Committed workspace control event disappeared: ${eventId}`);
155
+ }
156
+ await publishDurableWorkspaceControlEvent(deps.bus, workspaceId, event);
157
+ }
158
+
159
+ export async function sendAgentSessionMessage(
160
+ deps: {
161
+ db: Database;
162
+ bus: EventBus;
163
+ workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
164
+ },
165
+ context: AgentSessionCommandContext,
166
+ input: { targetSessionId: string; text: string; idempotencyKey: string },
167
+ ) {
168
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
169
+ scoped.transaction((tx) =>
170
+ sendAgentMessageInTransaction(tx as unknown as Database, {
171
+ accountId: context.accountId,
172
+ workspaceId: context.workspaceId,
173
+ targetSessionId: input.targetSessionId,
174
+ actor: agentActor(context),
175
+ operationKey: input.idempotencyKey,
176
+ text: input.text,
177
+ }),
178
+ ),
179
+ );
180
+ await publishAndWakeAgentCommand(deps, {
181
+ accountId: context.accountId,
182
+ workspaceId: context.workspaceId,
183
+ sessionId: input.targetSessionId,
184
+ eventIds: result.eventIds,
185
+ workflowId: result.workflowId,
186
+ wakeRevision: result.wakeRevision,
187
+ shouldSignal: result.shouldSignal,
188
+ interruptionCount: 0,
189
+ });
190
+ await publishWorkspaceControlEvent(deps, context.workspaceId, result.workspaceControlEventId);
191
+ return result;
192
+ }
193
+
194
+ export async function steerAgentSession(
195
+ deps: {
196
+ db: Database;
197
+ bus: EventBus;
198
+ workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
199
+ },
200
+ context: AgentSessionCommandContext,
201
+ input: { targetSessionId: string; instruction: string; idempotencyKey: string },
202
+ ) {
203
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
204
+ scoped.transaction((tx) =>
205
+ steerAgentSessionInTransaction(tx as unknown as Database, {
206
+ accountId: context.accountId,
207
+ workspaceId: context.workspaceId,
208
+ targetSessionId: input.targetSessionId,
209
+ actor: agentActor(context),
210
+ operationKey: input.idempotencyKey,
211
+ instruction: input.instruction,
212
+ }),
213
+ ),
214
+ );
215
+ await publishAndWakeAgentCommand(deps, {
216
+ accountId: context.accountId,
217
+ workspaceId: context.workspaceId,
218
+ sessionId: input.targetSessionId,
219
+ eventIds: result.eventIds,
220
+ workflowId: result.workflowId,
221
+ wakeRevision: result.wakeRevision,
222
+ shouldSignal: result.shouldSignal,
223
+ interruptionCount: result.interruptionCount,
224
+ });
225
+ await publishWorkspaceControlEvent(deps, context.workspaceId, result.workspaceControlEventId);
226
+ return result;
227
+ }
228
+
229
+ export async function controlAgentSessionWorkstream(
230
+ deps: {
231
+ db: Database;
232
+ bus: EventBus;
233
+ workflowClient: Pick<SessionWorkflowClient, "requestSessionWorkflowWakeDispatch">;
234
+ },
235
+ context: AgentSessionCommandContext,
236
+ input: {
237
+ targetSessionId: string;
238
+ action: "pause" | "resume";
239
+ idempotencyKey: string;
240
+ reason?: string | null;
241
+ },
242
+ ) {
243
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
244
+ scoped.transaction((tx) =>
245
+ mutateSessionControlInTransaction(tx as unknown as Database, {
246
+ accountId: context.accountId,
247
+ workspaceId: context.workspaceId,
248
+ sessionId: input.targetSessionId,
249
+ actor: agentActor(context),
250
+ operationKey: input.idempotencyKey,
251
+ action: input.action,
252
+ reason: input.reason ?? null,
253
+ }),
254
+ ),
255
+ );
256
+ await publishSessionEventIds(deps, context.workspaceId, input.targetSessionId, [
257
+ result.sessionControlEventId,
258
+ ]);
259
+ await publishWorkspaceControlEvent(deps, context.workspaceId, result.workspaceControlEventId);
260
+ await requestControlWakeDispatch(deps, result.wakeCount);
261
+ return result;
262
+ }
263
+
264
+ function receipt(row: SessionCommandReceiptRow): SessionCommandReceipt {
265
+ return {
266
+ id: row.id,
267
+ action: row.action,
268
+ operationKey: row.operationKey,
269
+ targetSessionId: row.targetSessionId,
270
+ targetTurnId: row.targetTurnId,
271
+ appliedControlRevision: row.appliedControlRevision,
272
+ appliedQueueVersion: row.appliedQueueVersion,
273
+ appliedTurnVersion: row.appliedTurnVersion,
274
+ appliedDraftRevision: row.appliedDraftRevision,
275
+ createdAt: row.createdAt.toISOString(),
276
+ };
277
+ }
278
+
279
+ function composerDraft(
280
+ row: Awaited<ReturnType<typeof getComposerDraftInTransaction>>,
281
+ ): ComposerDraft | null {
282
+ if (!row) return null;
283
+ return {
284
+ revision: row.revision,
285
+ text: row.text,
286
+ resources: row.resources as ComposerDraft["resources"],
287
+ tools: row.tools as ComposerDraft["tools"],
288
+ model: row.model,
289
+ reasoningEffort: row.reasoningEffort as ComposerDraft["reasoningEffort"],
290
+ sourceTurnId: row.sourceTurnId,
291
+ sourceTurnVersion: row.sourceTurnVersion,
292
+ updatedAt: row.updatedAt.toISOString(),
293
+ };
294
+ }
295
+
296
+ async function authoritativeQueue(db: Database, workspaceId: string, sessionId: string) {
297
+ const snapshot = await getSessionQueueSnapshot(db, workspaceId, sessionId);
298
+ if (!snapshot) throw new Error(`Session not found: ${sessionId}`);
299
+ return snapshot;
300
+ }
301
+
302
+ export async function moveHumanQueuePrompt(
303
+ deps: { db: Database; bus: EventBus },
304
+ context: HumanSessionCommandContext,
305
+ turnId: string,
306
+ input: MoveSessionQueueItemRequest,
307
+ ): Promise<SessionQueueMutationResponse> {
308
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
309
+ scoped.transaction((tx) =>
310
+ moveQueuedTurnInTransaction(tx as unknown as Database, {
311
+ ...context,
312
+ turnId,
313
+ beforeTurnId: input.beforeTurnId,
314
+ expectedQueueVersion: input.expectedQueueVersion,
315
+ actor: { type: "human", subjectId: context.subjectId },
316
+ operationKey: input.clientEventId,
317
+ }),
318
+ ),
319
+ );
320
+ const response = {
321
+ receipt: receipt(result.receipt),
322
+ snapshot: await authoritativeQueue(deps.db, context.workspaceId, context.sessionId),
323
+ };
324
+ await publishSessionEventIds(deps, context.workspaceId, context.sessionId, result.eventIds);
325
+ return response;
326
+ }
327
+
328
+ export async function deleteHumanQueuePrompt(
329
+ deps: { db: Database; bus: EventBus },
330
+ context: HumanSessionCommandContext,
331
+ turnId: string,
332
+ input: DeleteSessionQueueItemRequest,
333
+ ): Promise<SessionQueueMutationResponse> {
334
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
335
+ scoped.transaction((tx) =>
336
+ deleteSessionQueueItemInTransaction(tx as unknown as Database, {
337
+ ...context,
338
+ turnId,
339
+ expectedTurnVersion: input.expectedTurnVersion,
340
+ actor: { type: "human", subjectId: context.subjectId },
341
+ operationKey: input.clientEventId,
342
+ reason: input.reason ?? null,
343
+ }),
344
+ ),
345
+ );
346
+ const response = {
347
+ receipt: receipt(result.receipt),
348
+ snapshot: await authoritativeQueue(deps.db, context.workspaceId, context.sessionId),
349
+ };
350
+ await publishSessionEventIds(deps, context.workspaceId, context.sessionId, result.eventIds);
351
+ return response;
352
+ }
353
+
354
+ export async function editHumanQueuePrompt(
355
+ deps: { db: Database; bus: EventBus },
356
+ context: HumanSessionCommandContext,
357
+ turnId: string,
358
+ input: EditSessionQueueItemRequest,
359
+ ): Promise<SessionQueueMutationResponse> {
360
+ const result = await withWorkspaceSubjectRls(
361
+ deps.db,
362
+ context.workspaceId,
363
+ context.subjectId,
364
+ (scoped) =>
365
+ scoped.transaction((tx) =>
366
+ editQueuedTurnInTransaction(tx as unknown as Database, {
367
+ ...context,
368
+ turnId,
369
+ expectedTurnVersion: input.expectedTurnVersion,
370
+ expectedDraftRevision: input.expectedDraftRevision,
371
+ replaceDraft: input.replaceDraft,
372
+ actor: { type: "human", subjectId: context.subjectId },
373
+ operationKey: input.clientEventId,
374
+ }),
375
+ ),
376
+ );
377
+ const response = {
378
+ receipt: receipt(result.receipt),
379
+ snapshot: await authoritativeQueue(deps.db, context.workspaceId, context.sessionId),
380
+ draft: composerDraft(result.draft)!,
381
+ };
382
+ await publishSessionEventIds(deps, context.workspaceId, context.sessionId, result.eventIds);
383
+ return response;
384
+ }
385
+
386
+ export async function steerHumanQueuePrompt(
387
+ deps: { db: Database; bus: EventBus },
388
+ context: HumanSessionCommandContext,
389
+ turnId: string,
390
+ input: SteerSessionQueueItemRequest,
391
+ ): Promise<SessionQueueMutationResponse> {
392
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
393
+ scoped.transaction((tx) =>
394
+ steerQueuedTurnInTransaction(tx as unknown as Database, {
395
+ ...context,
396
+ turnId,
397
+ expectedTurnVersion: input.expectedTurnVersion,
398
+ controlEtag: input.controlEtag ?? null,
399
+ actor: { type: "human", subjectId: context.subjectId },
400
+ operationKey: input.clientEventId,
401
+ }),
402
+ ),
403
+ );
404
+ const response = {
405
+ receipt: receipt(result.receipt),
406
+ snapshot: await authoritativeQueue(deps.db, context.workspaceId, context.sessionId),
407
+ };
408
+ await publishSessionEventIds(deps, context.workspaceId, context.sessionId, result.eventIds);
409
+ await publishWorkspaceControlEvent(deps, context.workspaceId, result.workspaceControlEventId);
410
+ return response;
411
+ }
412
+
413
+ export async function controlHumanSessionWorkstream(
414
+ deps: {
415
+ db: Database;
416
+ bus: EventBus;
417
+ workflowClient: Pick<SessionWorkflowClient, "requestSessionWorkflowWakeDispatch">;
418
+ },
419
+ context: HumanSessionCommandContext,
420
+ input: SessionControlRequest,
421
+ ): Promise<SessionControlResponse> {
422
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
423
+ scoped.transaction((tx) =>
424
+ mutateSessionControlInTransaction(tx as unknown as Database, {
425
+ accountId: context.accountId,
426
+ workspaceId: context.workspaceId,
427
+ sessionId: context.sessionId,
428
+ actor: { type: "human", subjectId: context.subjectId },
429
+ operationKey: input.clientEventId,
430
+ action: input.action,
431
+ reason: input.reason ?? null,
432
+ expectedControlEtag: input.expectedControlEtag ?? null,
433
+ }),
434
+ ),
435
+ );
436
+ const response = {
437
+ receipt: receipt(result.receipt),
438
+ effectiveControl: serializeEffectiveSessionControl(result.control),
439
+ interruptionCount: result.interruptionCount,
440
+ wakeCount: result.wakeCount,
441
+ };
442
+ await publishSessionEventIds(deps, context.workspaceId, context.sessionId, [
443
+ result.sessionControlEventId,
444
+ ]);
445
+ await publishWorkspaceControlEvent(deps, context.workspaceId, result.workspaceControlEventId);
446
+ await requestControlWakeDispatch(deps, result.wakeCount);
447
+ return response;
448
+ }
449
+
450
+ export async function controlHumanWorkspace(
451
+ deps: {
452
+ db: Database;
453
+ bus: EventBus;
454
+ workflowClient: Pick<SessionWorkflowClient, "requestSessionWorkflowWakeDispatch">;
455
+ },
456
+ context: Omit<HumanSessionCommandContext, "sessionId">,
457
+ input: WorkspaceInferenceControlRequest,
458
+ ): Promise<WorkspaceInferenceControlResponse> {
459
+ const result = await withWorkspaceRls(deps.db, context.workspaceId, (scoped) =>
460
+ scoped.transaction((tx) =>
461
+ mutateWorkspaceControlInTransaction(tx as unknown as Database, {
462
+ accountId: context.accountId,
463
+ workspaceId: context.workspaceId,
464
+ actor: { type: "human", subjectId: context.subjectId },
465
+ operationKey: input.clientEventId,
466
+ action: input.action,
467
+ reason: input.reason ?? null,
468
+ expectedRevision: input.expectedRevision ?? null,
469
+ }),
470
+ ),
471
+ );
472
+ const response = {
473
+ receipt: receipt(result.receipt),
474
+ state: result.workspaceState,
475
+ revision: result.revision,
476
+ interruptionCount: result.interruptionCount,
477
+ wakeCount: result.wakeCount,
478
+ };
479
+ await publishWorkspaceControlEvent(deps, context.workspaceId, result.workspaceControlEventId);
480
+ await requestControlWakeDispatch(deps, result.wakeCount);
481
+ return response;
482
+ }
483
+
484
+ export async function getHumanComposerDraft(
485
+ db: Database,
486
+ context: HumanSessionCommandContext,
487
+ ): Promise<ComposerDraft> {
488
+ const row = await withWorkspaceSubjectRls(db, context.workspaceId, context.subjectId, (scoped) =>
489
+ getComposerDraftInTransaction(scoped, {
490
+ workspaceId: context.workspaceId,
491
+ sessionId: context.sessionId,
492
+ subjectId: context.subjectId,
493
+ }),
494
+ );
495
+ const mapped = composerDraft(row);
496
+ if (mapped) return mapped;
497
+ const session = await getSession(db, context.workspaceId, context.sessionId);
498
+ if (!session) throw new Error(`Session not found: ${context.sessionId}`);
499
+ return {
500
+ revision: 0,
501
+ text: "",
502
+ resources: [],
503
+ tools: [],
504
+ model: session.model,
505
+ reasoningEffort: reasoningEffortForMetadata(session.metadata, "medium"),
506
+ sourceTurnId: null,
507
+ sourceTurnVersion: null,
508
+ updatedAt: null,
509
+ };
510
+ }
511
+
512
+ export async function saveHumanComposerDraft(
513
+ db: Database,
514
+ context: HumanSessionCommandContext,
515
+ input: SaveComposerDraftRequest,
516
+ ): Promise<ComposerDraft> {
517
+ const row = await withWorkspaceSubjectRls(db, context.workspaceId, context.subjectId, (scoped) =>
518
+ scoped.transaction((tx) =>
519
+ saveComposerDraftInTransaction(tx as unknown as Database, {
520
+ ...context,
521
+ ...input,
522
+ subjectId: context.subjectId,
523
+ }),
524
+ ),
525
+ );
526
+ return composerDraft(row)!;
527
+ }
@@ -20,8 +20,10 @@ export type SessionWorkflowClient = {
20
20
  sessionId: string;
21
21
  workflowId: string;
22
22
  wakeRevision: number;
23
- controlEventId?: string;
23
+ interruptionRequested?: boolean;
24
24
  }) => Promise<void>;
25
+ /** Trigger one bounded drain of already-committed workflow-wake revisions. */
26
+ requestSessionWorkflowWakeDispatch: () => Promise<void>;
25
27
  // Dedicated, revision-carrying nudge for a durable Codex capacity waiter.
26
28
  // Optional for embedded/back-compat clients: callers may fall back to the
27
29
  // generic queueChanged wake because Postgres wakeRevision is authoritative.
@@ -41,17 +43,6 @@ export type SessionWorkflowClient = {
41
43
  workflowId: string;
42
44
  workflowWakeRevision: number;
43
45
  }) => Promise<void>;
44
- // A durable Pause/Steer control must reach the workflow even when its previous
45
- // run returned idle. signalWithStart either delivers to the live workflow or
46
- // starts the session workflow with the control already buffered.
47
- signalSessionControl: (input: {
48
- accountId: string;
49
- workspaceId: string;
50
- sessionId: string;
51
- eventId: string;
52
- workflowId: string;
53
- workflowWakeRevision: number;
54
- }) => Promise<void>;
55
46
  syncScheduledTask: (input: { task: ScheduledTask }) => Promise<void>;
56
47
  deleteScheduledTaskSchedule: (input: { temporalScheduleId: string }) => Promise<void>;
57
48
  triggerScheduledTask: (input: {
@@ -129,6 +120,6 @@ export type AcceptSessionUserMessageDependencies = Pick<
129
120
  AppDependencies,
130
121
  "settings" | "db" | "bus"
131
122
  > & {
132
- workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow" | "signalSessionControl">;
123
+ workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
133
124
  objectStorage: ObjectStorageDependency;
134
125
  };