@opengeni/core 0.12.10 → 0.14.4
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 +22 -0
- package/dist/application/new-session-drafts.d.ts +14 -0
- package/dist/application/session-commands.d.ts +107 -0
- package/dist/billing/limits.d.ts +29 -0
- package/dist/dependencies.d.ts +137 -0
- package/dist/domain/capabilities.d.ts +62 -0
- package/dist/domain/environments.d.ts +33 -0
- package/dist/domain/insights.d.ts +11 -0
- package/dist/domain/packs.d.ts +27 -0
- package/dist/domain/resources.d.ts +32 -0
- package/dist/domain/scheduled-tasks.d.ts +72 -0
- package/dist/domain/session-tool-policy.d.ts +31 -0
- package/dist/domain/sessions.d.ts +256 -0
- package/dist/domain/slack-bot.d.ts +19 -0
- package/dist/domain/workspace-members.d.ts +34 -0
- package/dist/index.d.ts +23 -1199
- package/dist/index.js +693 -53
- package/dist/index.js.map +1 -1
- package/dist/managed-auth-type.d.ts +2 -0
- package/dist/rigs/index.d.ts +57 -0
- package/dist/sandbox/fleet.d.ts +197 -0
- package/dist/sandbox/routing.d.ts +55 -0
- package/dist/sandbox-types.d.ts +52 -0
- package/dist/session-authorization.d.ts +36 -0
- package/dist/transcription.d.ts +71 -0
- package/dist/workflow-wake-contract.d.ts +4 -0
- package/package.json +11 -11
- package/src/access/index.ts +73 -2
- package/src/application/new-session-drafts.ts +3 -0
- package/src/application/session-commands.ts +3 -1
- package/src/dependencies.ts +5 -0
- package/src/domain/insights.ts +480 -0
- package/src/domain/session-tool-policy.ts +17 -25
- package/src/domain/sessions.ts +75 -4
- package/src/domain/slack-bot.ts +2 -4
- package/src/index.ts +2 -0
- package/src/sandbox/fleet.ts +96 -33
- package/src/sandbox/routing.ts +29 -7
- package/src/transcription.ts +142 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { type Settings } from "@opengeni/config";
|
|
2
|
+
import { SessionSpawnDenial, type AccessGrant, type CreateSessionResponse, type GoalSpec, type FirstPartyMcpToolName, type Permission, type ReasoningEffort, type ResourceRef, type Session, type SessionSkill, type SessionEvent, SessionMcpApprovalPolicy, type SessionMcpCredentialUpdateInput, type SessionMcpServerMetadata, type UpdateSessionMcpApprovalPolicyResponse, type UpdateSessionToolPolicyRequest, type SessionAuthorizationPort, type SessionToolPolicy, type SessionTurn, type ToolRef, type TurnInitiator, type TurnInitiatorContext, type TurnExecutionPolicyV1 } from "@opengeni/contracts";
|
|
3
|
+
import { type CreateSessionMcpServerInput, type Database, type UpdateSessionMcpServerCredentialsInput, type SessionCommandActor } from "@opengeni/db";
|
|
4
|
+
import { type EventBus } from "@opengeni/events";
|
|
5
|
+
import type { AcceptSessionUserMessageDependencies, ApiRouteDeps, SessionWorkflowClient } from "../dependencies";
|
|
6
|
+
/** Transport-neutral typed denial raised only after its audit row committed. */
|
|
7
|
+
export declare class SessionSpawnDeniedError extends Error {
|
|
8
|
+
readonly denial: SessionSpawnDenial;
|
|
9
|
+
constructor(denial: SessionSpawnDenial);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolve per-session first-party tool visibility without consulting
|
|
13
|
+
* authorization. Top-level omission snapshots the complete runtime default;
|
|
14
|
+
* child omission snapshots the parent's exact effective selection. Explicit
|
|
15
|
+
* [] is authoritative and must never widen.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveFirstPartyMcpToolsForCreate(requested: FirstPartyMcpToolName[] | undefined, parentStored: FirstPartyMcpToolName[] | null | undefined): FirstPartyMcpToolName[];
|
|
18
|
+
export declare function sessionSpawnDenialEnvelope(error: SessionSpawnDeniedError): {
|
|
19
|
+
readonly error: {
|
|
20
|
+
readonly code: "nested_agent_depth_exceeded" | "nested_agent_depth_override_forbidden";
|
|
21
|
+
readonly message: string;
|
|
22
|
+
readonly details: {
|
|
23
|
+
readonly denial: {
|
|
24
|
+
id: string;
|
|
25
|
+
accountId: string;
|
|
26
|
+
workspaceId: string;
|
|
27
|
+
parentSessionId: string | null;
|
|
28
|
+
rootSessionId: string | null;
|
|
29
|
+
currentDepth: number;
|
|
30
|
+
attemptedDepth: number;
|
|
31
|
+
effectiveMaxNestedAgentDepth: number;
|
|
32
|
+
requestedMaxNestedAgentDepthOverride: number | null;
|
|
33
|
+
policySource: "default" | "deployment" | "session" | "workspace";
|
|
34
|
+
policySessionId: string | null;
|
|
35
|
+
subjectId: string | null;
|
|
36
|
+
code: "nested_agent_depth_exceeded" | "nested_agent_depth_override_forbidden";
|
|
37
|
+
idempotencyKey: string | null;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare function settingsWithSessionMcpServerMetadata(settings: Settings, servers: SessionMcpServerMetadata[]): Settings;
|
|
44
|
+
export declare function createAndStartSession(input: {
|
|
45
|
+
requestedSessionId?: string;
|
|
46
|
+
db: Database;
|
|
47
|
+
bus: EventBus;
|
|
48
|
+
workflowClient: SessionWorkflowClient;
|
|
49
|
+
accountId: string;
|
|
50
|
+
workspaceId: string;
|
|
51
|
+
initialMessage: string;
|
|
52
|
+
turnInstructions?: string | null;
|
|
53
|
+
resources: ResourceRef[];
|
|
54
|
+
skills?: SessionSkill[];
|
|
55
|
+
tools: ToolRef[];
|
|
56
|
+
toolPolicy: SessionToolPolicy;
|
|
57
|
+
clientEventId?: string;
|
|
58
|
+
model: string;
|
|
59
|
+
reasoningEffort: Settings["openaiReasoningEffort"];
|
|
60
|
+
/** Session default Fast/standard; mirrored into metadata when set. */
|
|
61
|
+
latencyMode?: "standard" | "priority" | "fast";
|
|
62
|
+
turnExecutionPolicy: TurnExecutionPolicyV1;
|
|
63
|
+
sandboxBackend: Settings["sandboxBackend"];
|
|
64
|
+
metadata: Record<string, unknown>;
|
|
65
|
+
createdBy?: TurnInitiator;
|
|
66
|
+
createdByContext?: TurnInitiatorContext;
|
|
67
|
+
createdByActor?: Extract<SessionCommandActor, {
|
|
68
|
+
type: "agent_attempt";
|
|
69
|
+
}> | null;
|
|
70
|
+
variableSet?: {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
} | null;
|
|
74
|
+
rigId?: string | null;
|
|
75
|
+
rigVersionId?: string | null;
|
|
76
|
+
goal?: GoalSpec | null;
|
|
77
|
+
instructions?: string | null;
|
|
78
|
+
firstPartyMcpPermissions?: Permission[] | null;
|
|
79
|
+
firstPartyMcpTools: FirstPartyMcpToolName[];
|
|
80
|
+
mcpServers?: CreateSessionMcpServerInput[];
|
|
81
|
+
sessionMcpServers?: SessionMcpServerMetadata[];
|
|
82
|
+
parentSessionId?: string | null;
|
|
83
|
+
createIdempotencyKey?: string | null;
|
|
84
|
+
sandboxGroupId?: string | null;
|
|
85
|
+
sandboxOs?: Session["sandboxOs"];
|
|
86
|
+
seedTargetSandbox?: {
|
|
87
|
+
sandboxId: string;
|
|
88
|
+
settings: Settings;
|
|
89
|
+
workingDir?: string | null;
|
|
90
|
+
} | null;
|
|
91
|
+
consumeNewSessionDraft?: {
|
|
92
|
+
subjectId: string;
|
|
93
|
+
expectedRevision: number;
|
|
94
|
+
} | null;
|
|
95
|
+
maxNestedAgentDepthOverride?: number | null;
|
|
96
|
+
allowNestedAgentDepthIncrease?: boolean;
|
|
97
|
+
subjectId?: string | null;
|
|
98
|
+
}): Promise<CreateSessionResponse>;
|
|
99
|
+
export declare function workflowIdForSession(sessionId: string): string;
|
|
100
|
+
/**
|
|
101
|
+
* Reject an explicit model that the host does not expose. The set of usable
|
|
102
|
+
* models is the union surfaced by `configuredAllowedModels` (the built-in
|
|
103
|
+
* provider's allow-list plus every registry provider's ids); a `model` outside
|
|
104
|
+
* it cannot be resolved to a provider at run time, so we fail the request at
|
|
105
|
+
* the API edge with 422 rather than enqueuing a turn the worker can't honor.
|
|
106
|
+
*
|
|
107
|
+
* `model` is the explicit, caller-supplied value (null/undefined when omitted).
|
|
108
|
+
* An omitted model defaults to `settings.openaiModel` downstream — which is
|
|
109
|
+
* always first in `configuredAllowedModels` — so only an explicit value is
|
|
110
|
+
* checked. Centralized here so every model-carrying choke point
|
|
111
|
+
* (create-session, user-message/turn-accept, queued-turn update, and
|
|
112
|
+
* scheduled-task agentConfig — a scheduled task is a session the worker runs
|
|
113
|
+
* later) and the MCP surfaces that share them validate identically and cannot
|
|
114
|
+
* drift.
|
|
115
|
+
*/
|
|
116
|
+
export declare function canonicalConfiguredModel(settings: Settings, model: string | null | undefined): string | null | undefined;
|
|
117
|
+
export declare function assertConfiguredModel(settings: Settings, model: string | null | undefined): void;
|
|
118
|
+
export declare const CODEX_COMPACTION_V2_PROVIDER_LOCKED: "codex_compaction_v2_provider_locked";
|
|
119
|
+
/** Session is frozen on Codex remote compaction v2; non-Codex models are refused. */
|
|
120
|
+
export declare class CodexCompactionV2ProviderLockedError extends Error {
|
|
121
|
+
readonly code: "codex_compaction_v2_provider_locked";
|
|
122
|
+
readonly productModelId: string;
|
|
123
|
+
constructor(productModelId: string);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Fail closed when a remote_v2 session would run a non-Codex product model.
|
|
127
|
+
* Portable sessions and non-Codex sessions keep free mid-session provider swap.
|
|
128
|
+
*/
|
|
129
|
+
export declare function assertSessionAllowsProductModel(session: Pick<Session, "codexCompactionMode">, productModelId: string | null | undefined): void;
|
|
130
|
+
/**
|
|
131
|
+
* Reject a model the WORKSPACE's model policy blocks, at the same choke points
|
|
132
|
+
* as assertConfiguredModel — a 422 at the edge instead of a queued turn the
|
|
133
|
+
* worker's authoritative post-resolution gate would fail. `model` is the
|
|
134
|
+
* EFFECTIVE value the caller is about to persist: pass the explicit value at
|
|
135
|
+
* message/turn-update/scheduled-task edges (omitted inherits an
|
|
136
|
+
* already-validated stored default), but at session CREATION pass
|
|
137
|
+
* `payload.model ?? settings.openaiModel` — an omitted model stamps the
|
|
138
|
+
* deployment default onto the session, and under a restricted policy that
|
|
139
|
+
* default may be exactly the provider the policy exists to block.
|
|
140
|
+
*/
|
|
141
|
+
export declare function assertWorkspaceModelPolicyAllows(db: Database, settings: Settings, workspaceId: string, model: string | null | undefined): Promise<void>;
|
|
142
|
+
export declare function requireQueuedTurnForApi(db: Database, workspaceId: string, sessionId: string, turnId: string): Promise<SessionTurn>;
|
|
143
|
+
export declare function reasoningEffortForSession(metadata: Record<string, unknown>, fallback: Settings["openaiReasoningEffort"]): Settings["openaiReasoningEffort"];
|
|
144
|
+
export declare function latencyModeForSession(metadata: Record<string, unknown>, fallback?: "standard" | "priority" | "fast"): "standard" | "priority" | "fast";
|
|
145
|
+
/**
|
|
146
|
+
* Appends a `user.message` to an existing session and enqueues the resulting
|
|
147
|
+
* turn, merging requested resources/tools into the session and waking the
|
|
148
|
+
* workflow. Shared by the public events route and the first-party MCP
|
|
149
|
+
* `session_send_message` tool so the two surfaces cannot drift. Callers own
|
|
150
|
+
* resource/tool validation and the per-message usage limit before calling.
|
|
151
|
+
*/
|
|
152
|
+
export declare function postUserMessageTurn(input: {
|
|
153
|
+
db: Database;
|
|
154
|
+
bus: EventBus;
|
|
155
|
+
workflowClient: Pick<SessionWorkflowClient, "wakeSessionWorkflow">;
|
|
156
|
+
settings: Settings;
|
|
157
|
+
accountId: string;
|
|
158
|
+
workspaceId: string;
|
|
159
|
+
sessionId: string;
|
|
160
|
+
text: string;
|
|
161
|
+
turnInstructions?: string | null;
|
|
162
|
+
resources: ResourceRef[];
|
|
163
|
+
model?: string | null;
|
|
164
|
+
reasoningEffort?: Settings["openaiReasoningEffort"] | null;
|
|
165
|
+
latencyMode?: "standard" | "priority" | "fast" | null;
|
|
166
|
+
clientEventId?: string;
|
|
167
|
+
mcpCredentialUpdates?: UpdateSessionMcpServerCredentialsInput[];
|
|
168
|
+
delivery?: "send" | "steer";
|
|
169
|
+
origin?: "human" | "operator";
|
|
170
|
+
actor?: string;
|
|
171
|
+
actorLabel?: string;
|
|
172
|
+
commandActor?: SessionCommandActor;
|
|
173
|
+
controlEtag?: string | null;
|
|
174
|
+
expectedDraftRevision?: number | null;
|
|
175
|
+
reasoningEffortFallback?: Settings["openaiReasoningEffort"];
|
|
176
|
+
turnExecutionPolicy: TurnExecutionPolicyV1;
|
|
177
|
+
}): Promise<{
|
|
178
|
+
accepted: SessionEvent;
|
|
179
|
+
turn: SessionTurn;
|
|
180
|
+
}>;
|
|
181
|
+
/**
|
|
182
|
+
* Full create-session flow shared by `POST /sessions` and the first-party MCP
|
|
183
|
+
* `session_create` tool: payload validation, resource/tool/variableSet
|
|
184
|
+
* checks, usage limits, session start, and usage recording. `rawPayload` is
|
|
185
|
+
* the unparsed request body so absent-vs-empty execution-context fields keep
|
|
186
|
+
* their meaning: a child inherits omitted resources/tools/mcpServers from its
|
|
187
|
+
* trusted immediate parent, while explicit arrays (including []) win. A
|
|
188
|
+
* top-level create with omitted tools applies workspace-default capability MCPs.
|
|
189
|
+
*/
|
|
190
|
+
export declare function createSessionForRequest(deps: ApiRouteDeps, grant: AccessGrant, workspaceId: string, rawPayload: unknown): Promise<Session>;
|
|
191
|
+
/**
|
|
192
|
+
* Full accept-user-message flow shared by the `user.message` branch of
|
|
193
|
+
* `POST /sessions/:id/events` and the first-party MCP `session_send_message`
|
|
194
|
+
* tool: resource/tool validation, usage limits, the locked append + turn
|
|
195
|
+
* enqueue, and usage recording. `toolsProvided: false` durably preserves an
|
|
196
|
+
* Tool selection is durable session state and never rides a follow-up prompt.
|
|
197
|
+
*/
|
|
198
|
+
export declare function acceptSessionUserMessage(deps: AcceptSessionUserMessageDependencies, grant: AccessGrant, workspaceId: string, sessionId: string, input: {
|
|
199
|
+
text: string;
|
|
200
|
+
turnInstructions?: string | null;
|
|
201
|
+
resources?: ResourceRef[];
|
|
202
|
+
model?: string | null;
|
|
203
|
+
reasoningEffort?: ReasoningEffort | null;
|
|
204
|
+
latencyMode?: "standard" | "priority" | "fast" | null;
|
|
205
|
+
clientEventId?: string;
|
|
206
|
+
mcpCredentialUpdates?: SessionMcpCredentialUpdateInput[];
|
|
207
|
+
delivery?: "send" | "steer";
|
|
208
|
+
origin?: "human" | "operator";
|
|
209
|
+
controlEtag?: string | null;
|
|
210
|
+
expectedDraftRevision?: number | null;
|
|
211
|
+
}): Promise<{
|
|
212
|
+
accepted: SessionEvent;
|
|
213
|
+
turn: SessionTurn;
|
|
214
|
+
}>;
|
|
215
|
+
/**
|
|
216
|
+
* Shared title-write path for the manual rename route AND both MCP tools
|
|
217
|
+
* (set_session_title / set_other_session_title). The clobber guard lives in
|
|
218
|
+
* the db `updateSessionTitle` UPDATE: an agent write is skipped when a user
|
|
219
|
+
* title already pinned the session. On a real write we emit `session.title_set`
|
|
220
|
+
* exactly like goal mutations emit their events; when nothing changed (agent
|
|
221
|
+
* write blocked by the user lock) we emit nothing. Returns whether a write
|
|
222
|
+
* happened so callers can avoid double work.
|
|
223
|
+
*/
|
|
224
|
+
export declare function updateSessionTitle(deps: {
|
|
225
|
+
db: Database;
|
|
226
|
+
bus: EventBus;
|
|
227
|
+
sessionAuthorization?: SessionAuthorizationPort | null;
|
|
228
|
+
}, grant: AccessGrant, sessionId: string, title: string, source: "user" | "agent"): Promise<{
|
|
229
|
+
updated: boolean;
|
|
230
|
+
title: string | null;
|
|
231
|
+
relatedSessionAccess: "target" | "root";
|
|
232
|
+
}>;
|
|
233
|
+
/**
|
|
234
|
+
* Update one existing session MCP server's approval policy. The database
|
|
235
|
+
* serializes this write with attempt claim under the session lock: an already
|
|
236
|
+
* claimed attempt retains its immutable snapshot, while the next claim captures
|
|
237
|
+
* this value. No attempt is cancelled, restarted, or reinterpreted.
|
|
238
|
+
*/
|
|
239
|
+
export declare function updateSessionMcpApprovalPolicy(deps: {
|
|
240
|
+
db: Database;
|
|
241
|
+
bus: EventBus;
|
|
242
|
+
sessionAuthorization?: SessionAuthorizationPort | null;
|
|
243
|
+
}, grant: AccessGrant, sessionId: string, serverId: string, requireApproval: SessionMcpApprovalPolicy): Promise<UpdateSessionMcpApprovalPolicyResponse>;
|
|
244
|
+
/**
|
|
245
|
+
* Replace the durable session tool policy. The target and its parent (when
|
|
246
|
+
* present) are locked by the DB event-writer helper, and the update/event are
|
|
247
|
+
* committed under one version-fenced transaction. An already claimed turn
|
|
248
|
+
* keeps its immutable snapshot; the next attempt observes this policy.
|
|
249
|
+
*/
|
|
250
|
+
export declare function updateSessionToolPolicy(deps: {
|
|
251
|
+
db: Database;
|
|
252
|
+
bus: EventBus;
|
|
253
|
+
settings: Settings;
|
|
254
|
+
sessionAuthorization?: SessionAuthorizationPort | null;
|
|
255
|
+
}, grant: AccessGrant, sessionId: string, request: UpdateSessionToolPolicyRequest): Promise<Session>;
|
|
256
|
+
export declare function readSessionLineage(deps: Pick<ApiRouteDeps, "db" | "sessionAuthorization">, grant: AccessGrant, sessionId: string): Promise<import("@opengeni/db").SessionLineage>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AccessGrant, type ConnectionMetadata, type OpenGeniSlackBotConnectionMetadata as OpenGeniSlackBotMetadata, type Session } from "@opengeni/contracts";
|
|
2
|
+
import { type ConnectionMetadataWithVerification, type Database } from "@opengeni/db";
|
|
3
|
+
export declare function openGeniSlackBotMetadata(metadata: Record<string, unknown>): OpenGeniSlackBotMetadata | null;
|
|
4
|
+
export declare function isOpenGeniSlackBotConnection(connection: ConnectionMetadata & Partial<Pick<ConnectionMetadataWithVerification, "verifiedInstallAt" | "verifiedInstallVersion">>): boolean;
|
|
5
|
+
export declare function hasReservedOpenGeniSlackBotMetadata(metadata: Record<string, unknown> | null | undefined): boolean;
|
|
6
|
+
export declare function hasReservedOpenGeniSlackBotSessionMetadata(metadata: Record<string, unknown> | null | undefined): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Internal, pre-authorized lookup used by the scheduler and Slack tool adapter.
|
|
9
|
+
* Public callers must perform their permission check before calling this helper.
|
|
10
|
+
*/
|
|
11
|
+
export declare function requireOpenGeniSlackBotConnection(db: Database, workspaceId: string, connectionId: string): Promise<ConnectionMetadata>;
|
|
12
|
+
export declare function validateOpenGeniSlackBotConnectionSelection(db: Database, grant: AccessGrant, workspaceId: string, connectionId: string): Promise<ConnectionMetadata>;
|
|
13
|
+
export declare function scheduledSlackBotConnectionId(metadata: Record<string, unknown> | null | undefined): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* The scheduler writes the connection pointer together with immutable creator
|
|
16
|
+
* provenance. Requiring both prevents ordinary session metadata from becoming
|
|
17
|
+
* an authorization mechanism for a workspace-shared bot credential.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isTrustedScheduledSlackBotSession(session: Pick<Session, "createdBy" | "createdByContext" | "metadata">): boolean;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { WorkspaceMember } from "@opengeni/contracts";
|
|
2
|
+
/** A member can manage other members (directly or via the admin wildcard). */
|
|
3
|
+
export declare function memberCanAdminister(member: Pick<WorkspaceMember, "permissions">): boolean;
|
|
4
|
+
/** Only `user:` subjects are people; `api_key:` subjects belong to API keys. */
|
|
5
|
+
export declare function isUserMember(member: Pick<WorkspaceMember, "subjectId">): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Turn an email lookup result into the membership subject id. A null id means
|
|
8
|
+
* no registered user matched the email — email invites for not-yet-registered
|
|
9
|
+
* users are deferred, so that is a 404 (not a 400) at the API surface.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveMemberSubjectId(userId: string | null): string;
|
|
12
|
+
/**
|
|
13
|
+
* Guard the member-remove path. Refuses (409) to remove the caller's own
|
|
14
|
+
* membership and refuses to remove the last member that still holds an admin
|
|
15
|
+
* permission, so a workspace can never be orphaned with no one able to manage
|
|
16
|
+
* it. `members` is the full roster (every subject, including api_key ones —
|
|
17
|
+
* an api_key with workspace:admin still counts as an administering subject).
|
|
18
|
+
*/
|
|
19
|
+
export declare function assertWorkspaceMemberRemovable(input: {
|
|
20
|
+
members: WorkspaceMember[];
|
|
21
|
+
subjectId: string;
|
|
22
|
+
callerSubjectId: string;
|
|
23
|
+
}): void;
|
|
24
|
+
/**
|
|
25
|
+
* Guard the workspace-delete path before any external/DB mutation. Refuses
|
|
26
|
+
* (409) to delete the account's last workspace, and refuses while any session
|
|
27
|
+
* could still be running in Temporal (there is no clean per-session terminate
|
|
28
|
+
* to call first, so we will not orphan a workflow — the operator must stop the
|
|
29
|
+
* sessions first).
|
|
30
|
+
*/
|
|
31
|
+
export declare function assertWorkspaceDeletable(input: {
|
|
32
|
+
workspaceCountForAccount: number;
|
|
33
|
+
activeSessionCount: number;
|
|
34
|
+
}): void;
|