@opengeni/core 0.21.10 → 0.28.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/access/index.d.ts +1 -1
- package/dist/application/new-session-drafts.d.ts +1 -1
- package/dist/application/session-commands.d.ts +2 -2
- package/dist/billing/limits.d.ts +1 -1
- package/dist/canonical-human-identities.d.ts +12 -0
- package/dist/canonical-human-identities.js +23 -0
- package/dist/canonical-human-identities.js.map +1 -0
- package/dist/chunk-6WKPWE5S.js +2380 -0
- package/dist/chunk-6WKPWE5S.js.map +1 -0
- package/dist/chunk-IBOEYG6N.js +34 -0
- package/dist/chunk-IBOEYG6N.js.map +1 -0
- package/dist/chunk-JJU6I5XD.js +2713 -0
- package/dist/chunk-JJU6I5XD.js.map +1 -0
- package/dist/chunk-NYPMQ7NO.js +2270 -0
- package/dist/chunk-NYPMQ7NO.js.map +1 -0
- package/dist/dependencies.d.ts +30 -6
- package/dist/domain/capabilities.d.ts +28 -3
- package/dist/domain/company-profile-durable-learning-adapter.d.ts +39 -0
- package/dist/domain/conversation-integrations.d.ts +225 -0
- package/dist/domain/durable-learning-slack-publication.d.ts +72 -0
- package/dist/domain/editable-artifacts/agent-application.d.ts +192 -0
- package/dist/domain/editable-artifacts/durable-export-postgres.d.ts +4 -0
- package/dist/domain/editable-artifacts/durable-export.d.ts +212 -0
- package/dist/domain/editable-artifacts/errors.d.ts +47 -0
- package/dist/domain/editable-artifacts/hash.d.ts +11 -0
- package/dist/domain/editable-artifacts/in-memory.d.ts +99 -0
- package/dist/domain/editable-artifacts/index.d.ts +14 -0
- package/dist/domain/editable-artifacts/ports.d.ts +341 -0
- package/dist/domain/editable-artifacts/postgres-adapters.d.ts +13 -0
- package/dist/domain/editable-artifacts/service.d.ts +105 -0
- package/dist/domain/editable-artifacts/snapshot-compaction.d.ts +44 -0
- package/dist/domain/editable-artifacts/snapshot-verifier-genesis.d.ts +50 -0
- package/dist/domain/editable-artifacts/snapshot-verifier-materialization.d.ts +21 -0
- package/dist/domain/editable-artifacts/snapshot-verifier.d.ts +118 -0
- package/dist/domain/editable-artifacts/types.d.ts +410 -0
- package/dist/domain/fiken.d.ts +35 -0
- package/dist/domain/memory-slack-delivery.d.ts +19 -0
- package/dist/domain/packs.d.ts +29 -1
- package/dist/domain/personal-connection-delegations.d.ts +9 -1
- package/dist/domain/scheduled-tasks.d.ts +2 -2
- package/dist/domain/session-tool-policy.d.ts +2 -2
- package/dist/domain/sessions.d.ts +24 -8
- package/dist/domain/skill-imports.d.ts +32 -0
- package/dist/domain/slack-publication-secret-safety.d.ts +8 -0
- package/dist/domain/timeline-annotations.d.ts +5 -0
- package/dist/domain/video-generation-capabilities.d.ts +10 -0
- package/dist/domain/video-generation.d.ts +47 -0
- package/dist/editable-artifact-live/application.d.ts +69 -0
- package/dist/editable-artifact-live/errors.d.ts +1 -0
- package/dist/editable-artifact-live/index.d.ts +8 -0
- package/dist/editable-artifact-live/outbox-dispatcher.d.ts +162 -0
- package/dist/editable-artifact-live/ports.d.ts +100 -0
- package/dist/editable-artifact-live/server.d.ts +71 -0
- package/dist/editable-artifact-live/ticket.d.ts +40 -0
- package/dist/editable-artifact-live/types.d.ts +213 -0
- package/dist/editable-artifact-live/wire.d.ts +34 -0
- package/dist/editable-artifact-live.d.ts +2 -0
- package/dist/editable-artifact-live.js +58 -0
- package/dist/editable-artifact-live.js.map +1 -0
- package/dist/editable-artifacts.d.ts +2 -0
- package/dist/editable-artifacts.js +179 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/index.d.ts +37 -26
- package/dist/index.js +4145 -959
- package/dist/index.js.map +1 -1
- package/dist/managed-session.d.ts +6 -2
- package/dist/rigs/index.d.ts +1 -1
- package/dist/rigs/provider-images.d.ts +31 -0
- package/dist/sandbox/fleet.d.ts +8 -5
- package/dist/sandbox/routing.d.ts +1 -0
- package/dist/session-authorization.d.ts +4 -2
- package/dist/transcription.d.ts +5 -0
- package/dist/workflow-wake-contract.d.ts +7 -0
- package/package.json +22 -10
- package/src/access/index.ts +14 -2
- package/src/application/new-session-drafts.ts +2 -0
- package/src/application/session-commands.ts +188 -107
- package/src/canonical-human-identities.ts +27 -0
- package/src/dependencies.ts +34 -2
- package/src/domain/capabilities.ts +729 -408
- package/src/domain/company-profile-durable-learning-adapter.ts +221 -0
- package/src/domain/conversation-integrations.ts +1238 -0
- package/src/domain/durable-learning-slack-publication.ts +202 -0
- package/src/domain/editable-artifacts/agent-application.ts +687 -0
- package/src/domain/editable-artifacts/durable-export-postgres.ts +139 -0
- package/src/domain/editable-artifacts/durable-export.ts +734 -0
- package/src/domain/editable-artifacts/errors.ts +115 -0
- package/src/domain/editable-artifacts/hash.ts +131 -0
- package/src/domain/editable-artifacts/in-memory.ts +1662 -0
- package/src/domain/editable-artifacts/index.ts +14 -0
- package/src/domain/editable-artifacts/ports.ts +462 -0
- package/src/domain/editable-artifacts/postgres-adapters.ts +49 -0
- package/src/domain/editable-artifacts/service.ts +2402 -0
- package/src/domain/editable-artifacts/snapshot-compaction.ts +246 -0
- package/src/domain/editable-artifacts/snapshot-verifier-genesis.ts +235 -0
- package/src/domain/editable-artifacts/snapshot-verifier-materialization.ts +74 -0
- package/src/domain/editable-artifacts/snapshot-verifier.ts +687 -0
- package/src/domain/editable-artifacts/types.ts +835 -0
- package/src/domain/fiken.ts +88 -0
- package/src/domain/insights.ts +163 -50
- package/src/domain/memory-slack-delivery.ts +204 -0
- package/src/domain/memory-slack-publication.ts +5 -2
- package/src/domain/packs.ts +266 -5
- package/src/domain/personal-connection-delegations.ts +97 -6
- package/src/domain/scheduled-tasks.ts +171 -29
- package/src/domain/session-tool-policy.ts +8 -2
- package/src/domain/sessions.ts +395 -148
- package/src/domain/skill-imports.ts +350 -0
- package/src/domain/slack-publication-secret-safety.ts +42 -0
- package/src/domain/timeline-annotations.ts +204 -0
- package/src/domain/video-generation-capabilities.ts +104 -0
- package/src/domain/video-generation.ts +249 -0
- package/src/editable-artifact-live/application.ts +182 -0
- package/src/editable-artifact-live/errors.ts +4 -0
- package/src/editable-artifact-live/index.ts +8 -0
- package/src/editable-artifact-live/outbox-dispatcher.ts +916 -0
- package/src/editable-artifact-live/ports.ts +139 -0
- package/src/editable-artifact-live/server.ts +1707 -0
- package/src/editable-artifact-live/ticket.ts +217 -0
- package/src/editable-artifact-live/types.ts +286 -0
- package/src/editable-artifact-live/wire.ts +95 -0
- package/src/editable-artifact-live.ts +2 -0
- package/src/editable-artifacts.ts +2 -0
- package/src/index.ts +15 -0
- package/src/managed-session.ts +19 -2
- package/src/rigs/index.ts +26 -19
- package/src/rigs/provider-images.ts +110 -0
- package/src/sandbox/fleet.ts +72 -66
- package/src/sandbox/routing.ts +6 -3
- package/src/session-authorization.ts +187 -52
- package/src/transcription.ts +5 -0
- package/src/workflow-wake-contract.ts +8 -0
|
@@ -8,11 +8,13 @@ import {
|
|
|
8
8
|
type SessionAuthorizationTarget,
|
|
9
9
|
} from "@opengeni/contracts";
|
|
10
10
|
import {
|
|
11
|
+
getSessionAuthorityProjection,
|
|
11
12
|
getSession,
|
|
12
|
-
getSessionRootId,
|
|
13
13
|
getSessionTurnForAttempt,
|
|
14
14
|
getSlackInteractionSessionAccessForSession,
|
|
15
|
+
withSessionRlsActorContext,
|
|
15
16
|
type Database,
|
|
17
|
+
type SessionRlsActorContext,
|
|
16
18
|
} from "@opengeni/db";
|
|
17
19
|
import type { AppDependencies } from "./dependencies";
|
|
18
20
|
|
|
@@ -46,6 +48,91 @@ export type ResolvedSessionAuthorization = {
|
|
|
46
48
|
reauthorizeAfterMs: number | null;
|
|
47
49
|
};
|
|
48
50
|
|
|
51
|
+
type ResolvedSessionAuthorizationActor = {
|
|
52
|
+
actor: SessionAuthorizationActor;
|
|
53
|
+
callerParentSessionId: string | null;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
type ResolvedSessionAuthorizationTarget = {
|
|
57
|
+
target: SessionAuthorizationTarget;
|
|
58
|
+
parentSessionId: string | null;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
function grantHasAgentAttemptAuthority(grant: AccessGrant): boolean {
|
|
62
|
+
const hasAgentAttemptClaim =
|
|
63
|
+
grant.metadata?.["turnId"] !== undefined ||
|
|
64
|
+
grant.metadata?.["attemptId"] !== undefined ||
|
|
65
|
+
grant.metadata?.["executionGeneration"] !== undefined;
|
|
66
|
+
return grant.principalKind ? grant.principalKind === "agent_attempt" : hasAgentAttemptClaim;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Read-only access an immediate child may use against its parent. Upstream
|
|
71
|
+
* mutation is deliberately limited to `session.append`: letting a child Pause,
|
|
72
|
+
* Steer, or otherwise mutate its parent would let it influence siblings through
|
|
73
|
+
* the parent's recursive control and shared state.
|
|
74
|
+
*/
|
|
75
|
+
const AGENT_PARENT_READ_OPERATIONS = new Set<SessionAuthorizationOperation>([
|
|
76
|
+
"session.read",
|
|
77
|
+
"session.events.read",
|
|
78
|
+
"session.stream.read",
|
|
79
|
+
"session.turns.read",
|
|
80
|
+
"session.queue.read",
|
|
81
|
+
"session.composer.read",
|
|
82
|
+
"session.lineage.read",
|
|
83
|
+
"session.capture.read",
|
|
84
|
+
"session.files.read",
|
|
85
|
+
"session.git.read",
|
|
86
|
+
"session.terminal.read",
|
|
87
|
+
"session.viewer.read",
|
|
88
|
+
"session.goal.read",
|
|
89
|
+
"session.human_input.read",
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
function enforceAgentSessionHierarchy(
|
|
93
|
+
actor: Extract<SessionAuthorizationActor, { kind: "agent_attempt" }>,
|
|
94
|
+
callerParentSessionId: string | null,
|
|
95
|
+
target: ResolvedSessionAuthorizationTarget,
|
|
96
|
+
operation: SessionAuthorizationOperation,
|
|
97
|
+
): "target" | "root" {
|
|
98
|
+
if (target.target.sessionId === actor.callerSessionId) return "root";
|
|
99
|
+
|
|
100
|
+
// A manager may inspect and operate an immediate child. Existing permission
|
|
101
|
+
// and host-policy checks still apply; lineage never grants a capability.
|
|
102
|
+
if (target.parentSessionId === actor.callerSessionId) return "target";
|
|
103
|
+
|
|
104
|
+
// A child may report to and inspect its immediate parent, but cannot mutate
|
|
105
|
+
// the parent except through the canonical machine-input message boundary.
|
|
106
|
+
if (callerParentSessionId === target.target.sessionId) {
|
|
107
|
+
if (operation === "session.append" || AGENT_PARENT_READ_OPERATIONS.has(operation)) {
|
|
108
|
+
return "target";
|
|
109
|
+
}
|
|
110
|
+
throw new SessionAuthorizationDeniedError("forbidden");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Siblings, skipped generations, other branches, and unrelated roots are
|
|
114
|
+
// never cross-session authority for a live agent attempt.
|
|
115
|
+
throw new SessionAuthorizationDeniedError("forbidden");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function sessionRlsActorForAuthorization(
|
|
119
|
+
authorization: ResolvedSessionAuthorization,
|
|
120
|
+
): SessionRlsActorContext {
|
|
121
|
+
return authorization.actor.kind === "agent_attempt"
|
|
122
|
+
? {
|
|
123
|
+
subjectId: authorization.actor.subjectId,
|
|
124
|
+
initiatingHumanSubjectId: authorization.actor.initiatingHumanSubjectId,
|
|
125
|
+
}
|
|
126
|
+
: { subjectId: authorization.actor.subjectId };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function withResolvedSessionAuthorization<T>(
|
|
130
|
+
authorization: ResolvedSessionAuthorization,
|
|
131
|
+
fn: () => Promise<T>,
|
|
132
|
+
): Promise<T> {
|
|
133
|
+
return await withSessionRlsActorContext(sessionRlsActorForAuthorization(authorization), fn);
|
|
134
|
+
}
|
|
135
|
+
|
|
49
136
|
/**
|
|
50
137
|
* Prove that a first-party request belongs to the exact currently active
|
|
51
138
|
* attempt of the named caller session. Unlike the optional embedding-host ACL
|
|
@@ -56,7 +143,7 @@ export async function requireLiveAgentAttemptAuthorization(
|
|
|
56
143
|
grant: AccessGrant,
|
|
57
144
|
callerSessionId: string,
|
|
58
145
|
): Promise<Extract<SessionAuthorizationActor, { kind: "agent_attempt" }>> {
|
|
59
|
-
const actor = await resolveSessionAuthorizationActor(db, grant);
|
|
146
|
+
const { actor } = await resolveSessionAuthorizationActor(db, grant);
|
|
60
147
|
if (actor.kind !== "agent_attempt" || actor.callerSessionId !== callerSessionId) {
|
|
61
148
|
throw new SessionAuthorizationDeniedError("caller_stale");
|
|
62
149
|
}
|
|
@@ -84,17 +171,52 @@ export async function requireSessionAuthorization(
|
|
|
84
171
|
},
|
|
85
172
|
): Promise<ResolvedSessionAuthorization | null> {
|
|
86
173
|
const port = deps.sessionAuthorization;
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
174
|
+
const isAgentAttempt = grantHasAgentAttemptAuthority(grant);
|
|
175
|
+
const [slackAccess, authority] = await Promise.all([
|
|
176
|
+
getSlackInteractionSessionAccessForSession(deps.db, {
|
|
177
|
+
accountId: grant.accountId,
|
|
178
|
+
workspaceId: grant.workspaceId,
|
|
179
|
+
sessionId: input.sessionId,
|
|
180
|
+
}),
|
|
181
|
+
getSessionAuthorityProjection(deps.db, grant.workspaceId, input.sessionId),
|
|
182
|
+
]);
|
|
183
|
+
|
|
184
|
+
// Preserve the standalone workspace-shared path. Private sessions continue
|
|
185
|
+
// through the durable actor and ownership checks even without a host port.
|
|
186
|
+
if (
|
|
187
|
+
!port &&
|
|
188
|
+
!isAgentAttempt &&
|
|
189
|
+
slackAccess?.visibility !== "private" &&
|
|
190
|
+
authority?.visibility !== "user_private"
|
|
191
|
+
) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
if (!authority) throw new SessionAuthorizationDeniedError("not_found");
|
|
195
|
+
|
|
196
|
+
const [resolvedActor, resolvedTarget] = await Promise.all([
|
|
197
|
+
resolveSessionAuthorizationActor(deps.db, grant),
|
|
198
|
+
resolveSessionAuthorizationTarget(deps.db, grant, input.sessionId),
|
|
199
|
+
]);
|
|
200
|
+
const actor = resolvedActor.actor;
|
|
201
|
+
const target = resolvedTarget.target;
|
|
202
|
+
const agentRelatedSessionAccess =
|
|
203
|
+
actor.kind === "agent_attempt"
|
|
204
|
+
? enforceAgentSessionHierarchy(
|
|
205
|
+
actor,
|
|
206
|
+
resolvedActor.callerParentSessionId,
|
|
207
|
+
resolvedTarget,
|
|
208
|
+
input.operation,
|
|
209
|
+
)
|
|
210
|
+
: null;
|
|
211
|
+
|
|
212
|
+
if (authority.visibility === "user_private") {
|
|
213
|
+
const allowed =
|
|
214
|
+
authority.ownerSubjectId !== null &&
|
|
215
|
+
(actor.kind === "subject"
|
|
216
|
+
? actor.subjectId === authority.ownerSubjectId
|
|
217
|
+
: actor.initiatingHumanSubjectId === authority.ownerSubjectId);
|
|
218
|
+
if (!allowed) throw new SessionAuthorizationDeniedError("forbidden");
|
|
219
|
+
}
|
|
98
220
|
if (slackAccess?.visibility === "private") {
|
|
99
221
|
const allowed =
|
|
100
222
|
actor.kind === "subject"
|
|
@@ -102,7 +224,14 @@ export async function requireSessionAuthorization(
|
|
|
102
224
|
: actor.callerRootSessionId === target.rootSessionId;
|
|
103
225
|
if (!allowed) throw new SessionAuthorizationDeniedError("forbidden");
|
|
104
226
|
}
|
|
105
|
-
if (!port)
|
|
227
|
+
if (!port) {
|
|
228
|
+
return {
|
|
229
|
+
actor,
|
|
230
|
+
target,
|
|
231
|
+
relatedSessionAccess: agentRelatedSessionAccess ?? "root",
|
|
232
|
+
reauthorizeAfterMs: null,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
106
235
|
|
|
107
236
|
let rawDecision: unknown;
|
|
108
237
|
try {
|
|
@@ -127,7 +256,10 @@ export async function requireSessionAuthorization(
|
|
|
127
256
|
return {
|
|
128
257
|
actor,
|
|
129
258
|
target,
|
|
130
|
-
relatedSessionAccess:
|
|
259
|
+
relatedSessionAccess:
|
|
260
|
+
agentRelatedSessionAccess === "target"
|
|
261
|
+
? "target"
|
|
262
|
+
: (parsed.data.relatedSessionAccess ?? "target"),
|
|
131
263
|
reauthorizeAfterMs: parsed.data.reauthorizeAfterMs ?? null,
|
|
132
264
|
};
|
|
133
265
|
}
|
|
@@ -139,8 +271,12 @@ export async function requireSessionAuthorizationListScope(
|
|
|
139
271
|
surface: SessionAuthorizationSurface,
|
|
140
272
|
): Promise<SessionAuthorizationListScope | null> {
|
|
141
273
|
const port = deps.sessionAuthorization;
|
|
274
|
+
const isAgentAttempt = grantHasAgentAttemptAuthority(grant);
|
|
275
|
+
if (!port && !isAgentAttempt) return null;
|
|
276
|
+
const { actor } = await resolveSessionAuthorizationActor(deps.db, grant);
|
|
277
|
+
// Standalone agents may retain compact workspace discovery, but only while
|
|
278
|
+
// the signed caller attempt is still the exact live attempt.
|
|
142
279
|
if (!port) return null;
|
|
143
|
-
const actor = await resolveSessionAuthorizationActor(deps.db, grant);
|
|
144
280
|
let rawScope: unknown;
|
|
145
281
|
try {
|
|
146
282
|
rawScope = await port.resolveListScope({
|
|
@@ -168,39 +304,34 @@ async function resolveSessionAuthorizationTarget(
|
|
|
168
304
|
db: Database,
|
|
169
305
|
grant: AccessGrant,
|
|
170
306
|
sessionId: string,
|
|
171
|
-
): Promise<
|
|
307
|
+
): Promise<ResolvedSessionAuthorizationTarget> {
|
|
172
308
|
const session = await getSession(db, grant.workspaceId, sessionId);
|
|
173
309
|
if (!session || session.accountId !== grant.accountId) {
|
|
174
310
|
throw new SessionAuthorizationDeniedError("not_found");
|
|
175
311
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
throw new SessionAuthorizationUnavailableError({ cause: error });
|
|
181
|
-
}
|
|
182
|
-
if (!rootSessionId) {
|
|
183
|
-
throw new SessionAuthorizationDeniedError("not_found");
|
|
184
|
-
}
|
|
185
|
-
return { sessionId: session.id, rootSessionId };
|
|
312
|
+
return {
|
|
313
|
+
target: { sessionId: session.id, rootSessionId: session.rootSessionId },
|
|
314
|
+
parentSessionId: session.parentSessionId,
|
|
315
|
+
};
|
|
186
316
|
}
|
|
187
|
-
|
|
188
317
|
async function resolveSessionAuthorizationActor(
|
|
189
318
|
db: Database,
|
|
190
319
|
grant: AccessGrant,
|
|
191
|
-
): Promise<
|
|
320
|
+
): Promise<ResolvedSessionAuthorizationActor> {
|
|
192
321
|
const callerSessionId = grant.metadata?.["sessionId"];
|
|
193
322
|
const turnId = grant.metadata?.["turnId"];
|
|
194
323
|
const attemptId = grant.metadata?.["attemptId"];
|
|
195
324
|
const executionGeneration = grant.metadata?.["executionGeneration"];
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
325
|
+
const isAgentAttempt = grantHasAgentAttemptAuthority(grant);
|
|
326
|
+
if (!isAgentAttempt) {
|
|
327
|
+
return {
|
|
328
|
+
actor: SessionAuthorizationActor.parse({
|
|
329
|
+
kind: "subject",
|
|
330
|
+
subjectId: grant.subjectId,
|
|
331
|
+
...(grant.subjectLabel ? { subjectLabel: grant.subjectLabel } : {}),
|
|
332
|
+
}),
|
|
333
|
+
callerParentSessionId: null,
|
|
334
|
+
};
|
|
204
335
|
}
|
|
205
336
|
if (
|
|
206
337
|
typeof callerSessionId !== "string" ||
|
|
@@ -212,10 +343,9 @@ async function resolveSessionAuthorizationActor(
|
|
|
212
343
|
) {
|
|
213
344
|
throw new SessionAuthorizationDeniedError("caller_stale");
|
|
214
345
|
}
|
|
215
|
-
const [callerSession, turn
|
|
346
|
+
const [callerSession, turn] = await Promise.all([
|
|
216
347
|
getSession(db, grant.workspaceId, callerSessionId),
|
|
217
348
|
getSessionTurnForAttempt(db, grant.workspaceId, callerSessionId, attemptId),
|
|
218
|
-
getSessionRootId(db, grant.workspaceId, callerSessionId).catch(() => null),
|
|
219
349
|
]);
|
|
220
350
|
if (
|
|
221
351
|
!callerSession ||
|
|
@@ -223,20 +353,25 @@ async function resolveSessionAuthorizationActor(
|
|
|
223
353
|
!turn ||
|
|
224
354
|
turn.id !== turnId ||
|
|
225
355
|
turn.executionGeneration !== executionGeneration ||
|
|
226
|
-
callerSession.activeTurnId !== turn.id
|
|
227
|
-
!callerRootSessionId
|
|
356
|
+
callerSession.activeTurnId !== turn.id
|
|
228
357
|
) {
|
|
229
358
|
throw new SessionAuthorizationDeniedError("caller_stale");
|
|
230
359
|
}
|
|
231
|
-
return
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
360
|
+
return {
|
|
361
|
+
actor: SessionAuthorizationActor.parse({
|
|
362
|
+
kind: "agent_attempt",
|
|
363
|
+
subjectId: grant.subjectId,
|
|
364
|
+
callerSessionId,
|
|
365
|
+
callerRootSessionId: callerSession.rootSessionId,
|
|
366
|
+
turnId,
|
|
367
|
+
attemptId,
|
|
368
|
+
executionGeneration,
|
|
369
|
+
initiator: turn.initiator,
|
|
370
|
+
initiatorContext: turn.initiatorContext,
|
|
371
|
+
initiatingHumanSubjectId:
|
|
372
|
+
turn.initiatingHumanSubjectId ??
|
|
373
|
+
(turn.initiator.kind === "subject" ? turn.initiator.subjectId : null),
|
|
374
|
+
}),
|
|
375
|
+
callerParentSessionId: callerSession.parentSessionId,
|
|
376
|
+
};
|
|
242
377
|
}
|
package/src/transcription.ts
CHANGED
|
@@ -19,6 +19,8 @@ export type TranscriptionLimits = {
|
|
|
19
19
|
export type TranscriptionRequest = {
|
|
20
20
|
workspaceId: string;
|
|
21
21
|
accountId: string;
|
|
22
|
+
/** Authenticated human/service subject used for provider-account authority. */
|
|
23
|
+
subjectId: string;
|
|
22
24
|
audio: Uint8Array;
|
|
23
25
|
mimeType: string;
|
|
24
26
|
/** Optional client-reported duration; enforced as a soft ceiling before upstream. */
|
|
@@ -87,6 +89,7 @@ export function statusForVoiceInputError(code: VoiceInputErrorCode): number {
|
|
|
87
89
|
/** Optional workspace scope for readiness checks during provider selection. */
|
|
88
90
|
export type TranscriptionAvailabilityContext = {
|
|
89
91
|
workspaceId?: string | undefined;
|
|
92
|
+
subjectId?: string | undefined;
|
|
90
93
|
};
|
|
91
94
|
|
|
92
95
|
/**
|
|
@@ -109,6 +112,8 @@ export type TranscriptionProvider = {
|
|
|
109
112
|
mimeType: string;
|
|
110
113
|
filename: string;
|
|
111
114
|
workspaceId: string;
|
|
115
|
+
accountId: string;
|
|
116
|
+
subjectId: string;
|
|
112
117
|
requestId: string;
|
|
113
118
|
signal?: AbortSignal | undefined;
|
|
114
119
|
}): Promise<{ text: string; languages: string[] }>;
|
|
@@ -4,3 +4,11 @@ export const SESSION_WORKFLOW_WAKE_DISPATCHER_SCHEDULE_ID =
|
|
|
4
4
|
export const SESSION_WORKFLOW_WAKE_DISPATCHER_WORKFLOW_TYPE =
|
|
5
5
|
"sessionWorkflowWakeDispatcherWorkflow";
|
|
6
6
|
export const SESSION_WORKFLOW_WAKE_DISPATCHER_PERIOD_MS = 10_000;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Temporal delivers activity cancellation through heartbeats. Keep both the
|
|
10
|
+
* activity's local heartbeat timer and the worker's SDK throttle at this bound
|
|
11
|
+
* so the end-to-end Pause/Steer physical-cancellation contract is not already
|
|
12
|
+
* exhausted before sandbox/tool quiescence and replacement admission begin.
|
|
13
|
+
*/
|
|
14
|
+
export const TURN_ACTIVITY_CANCELLATION_HEARTBEAT_INTERVAL_MS = 500;
|