@opengeni/contracts 0.50.0 → 2.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/agent-authored-durable-text.d.ts +64 -0
- package/dist/atlassian.d.ts +1 -0
- package/dist/atlassian.js +14 -13
- package/dist/{chunk-Y3MLSLB4.js → chunk-3SIZGL3O.js} +42 -30
- package/dist/chunk-3SIZGL3O.js.map +1 -0
- package/dist/{chunk-JBCIY7QD.js → chunk-7RMTKFJW.js} +45 -22
- package/dist/chunk-7RMTKFJW.js.map +1 -0
- package/dist/{chunk-Q6A7XT2N.js → chunk-7ZZ3R27P.js} +9598 -6021
- package/dist/chunk-7ZZ3R27P.js.map +1 -0
- package/dist/{chunk-5UDNP7AO.js → chunk-MRWYRAS5.js} +56 -8
- package/dist/chunk-MRWYRAS5.js.map +1 -0
- package/dist/{chunk-LW7OH6CS.js → chunk-N6GRVXAJ.js} +6 -5
- package/dist/chunk-N6GRVXAJ.js.map +1 -0
- package/dist/{chunk-TZ6YEYN4.js → chunk-NVJMJWLL.js} +3 -1
- package/dist/chunk-NVJMJWLL.js.map +1 -0
- package/dist/chunk-PX3VCKAU.js +29 -0
- package/dist/chunk-PX3VCKAU.js.map +1 -0
- package/dist/{chunk-LSB7GRLG.js → chunk-TXTQIYCV.js} +15 -11
- package/dist/chunk-TXTQIYCV.js.map +1 -0
- package/dist/{chunk-CADSX6UN.js → chunk-Y3KNXVTD.js} +2 -2
- package/dist/chunk-YBW5JSA3.js +251 -0
- package/dist/chunk-YBW5JSA3.js.map +1 -0
- package/dist/company-brain-governed-writes.d.ts +475 -0
- package/dist/company-brain.d.ts +398 -0
- package/dist/company-profile.d.ts +268 -0
- package/dist/connection-authority.d.ts +501 -0
- package/dist/connection-authority.js +364 -0
- package/dist/connection-authority.js.map +1 -0
- package/dist/connector-attachments.d.ts +95 -0
- package/dist/connector-attachments.js +51 -0
- package/dist/connector-attachments.js.map +1 -0
- package/dist/editable-artifact-codec-registry.d.ts +16 -7
- package/dist/editable-artifact-codec-registry.js +18 -8
- package/dist/editable-artifact-committed-transaction.d.ts +2 -2
- package/dist/editable-artifact-committed-transaction.js +2 -2
- package/dist/editable-artifact-live.d.ts +11 -12
- package/dist/editable-artifact-live.js +111 -46
- package/dist/editable-artifact-live.js.map +1 -1
- package/dist/editable-artifact-serialized-commit.d.ts +2 -1
- package/dist/editable-artifact-serialized-commit.js +9 -8
- package/dist/editable-artifact-versions.d.ts +20 -5
- package/dist/editable-artifact-versions.js +23 -5
- package/dist/editable-artifacts.d.ts +2 -0
- package/dist/editable-artifacts.js +51 -39
- package/dist/google-drive.d.ts +89 -1
- package/dist/google-drive.js +78 -17
- package/dist/google-drive.js.map +1 -1
- package/dist/governed-learning-activation.d.ts +154 -0
- package/dist/governed-learning-evaluator.d.ts +152 -0
- package/dist/index.d.ts +12395 -1426
- package/dist/index.js +837 -115
- package/dist/interaction.d.ts +68 -0
- package/dist/knowledge.d.ts +192 -0
- package/dist/organization-membership-lifecycle.d.ts +516 -0
- package/dist/permissions.d.ts +52 -0
- package/dist/personal-github.d.ts +319 -0
- package/dist/personal-github.js +209 -0
- package/dist/personal-github.js.map +1 -0
- package/dist/preference-registry.d.ts +17 -0
- package/dist/remember.d.ts +331 -0
- package/dist/sandbox-file-artifacts.d.ts +56 -0
- package/dist/sandbox-snapshots.d.ts +21 -0
- package/dist/slack-bot-scopes.d.ts +34 -14
- package/dist/slack-bot-scopes.js +5 -1
- package/dist/spreadsheet-artifact-commands.d.ts +2 -3
- package/dist/spreadsheet-artifact-commands.js +4 -2
- package/dist/spreadsheet-artifact-query.js +3 -2
- package/dist/task-notes.d.ts +42 -1
- package/dist/tool-result-spill.d.ts +16 -0
- package/dist/workspace-instruction-policies.d.ts +81 -0
- package/dist/workspace-learning-administration.d.ts +289 -0
- package/package.json +13 -1
- package/src/agent-authored-durable-text.ts +105 -0
- package/src/company-brain-governed-writes.ts +356 -0
- package/src/company-brain.ts +201 -0
- package/src/company-profile.ts +122 -1
- package/src/connection-authority.ts +413 -0
- package/src/connector-attachments.ts +327 -0
- package/src/editable-artifact-codec-registry.ts +55 -17
- package/src/editable-artifact-committed-transaction.ts +44 -31
- package/src/editable-artifact-live.ts +123 -57
- package/src/editable-artifact-serialized-commit.ts +2 -1
- package/src/editable-artifact-versions.ts +26 -5
- package/src/editable-artifacts.ts +2 -0
- package/src/google-drive.ts +76 -4
- package/src/governed-learning-activation.ts +191 -0
- package/src/governed-learning-evaluator.ts +176 -0
- package/src/index.ts +3182 -483
- package/src/interaction.ts +55 -1
- package/src/knowledge.ts +133 -6
- package/src/organization-membership-lifecycle.ts +330 -0
- package/src/permissions.ts +55 -0
- package/src/personal-github.ts +267 -0
- package/src/preference-registry.ts +17 -0
- package/src/remember.ts +242 -0
- package/src/sandbox-file-artifacts.ts +65 -0
- package/src/sandbox-snapshots.ts +78 -0
- package/src/slack-bot-scopes.ts +81 -9
- package/src/spreadsheet-artifact-commands.ts +12 -13
- package/src/task-notes.ts +14 -1
- package/src/tool-result-spill.ts +35 -0
- package/src/workspace-instruction-policies.ts +30 -0
- package/src/workspace-learning-administration.ts +88 -0
- package/dist/chunk-5UDNP7AO.js.map +0 -1
- package/dist/chunk-BVGIYW7D.js +0 -11
- package/dist/chunk-BVGIYW7D.js.map +0 -1
- package/dist/chunk-JBCIY7QD.js.map +0 -1
- package/dist/chunk-LSB7GRLG.js.map +0 -1
- package/dist/chunk-LW7OH6CS.js.map +0 -1
- package/dist/chunk-Q6A7XT2N.js.map +0 -1
- package/dist/chunk-TZ6YEYN4.js.map +0 -1
- package/dist/chunk-Y3MLSLB4.js.map +0 -1
- /package/dist/{chunk-CADSX6UN.js.map → chunk-Y3KNXVTD.js.map} +0 -0
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { Permission } from "./permissions";
|
|
2
3
|
import { ScopedKnowledgeScope } from "./scoped-knowledge";
|
|
3
4
|
import {
|
|
4
5
|
boundSessionEventPayload,
|
|
@@ -10,11 +11,14 @@ import { MemorySlackPublicationDistribution } from "./memory-slack-delivery";
|
|
|
10
11
|
import { WorkspaceInstructionPolicyRoleKeyInput } from "./workspace-instruction-policies";
|
|
11
12
|
import { ClientResumableVoiceInputConfig } from "./transcription-recordings";
|
|
12
13
|
import { MediaGenerationResult } from "./video-generation";
|
|
14
|
+
import { KnowledgeProviderCitation } from "./knowledge";
|
|
15
|
+
import { XaiProviderAccountAuthoritySnapshotV1 } from "./xai-provider-account-authority";
|
|
13
16
|
|
|
14
17
|
export * from "./slack-bot-scopes";
|
|
15
18
|
export * from "./slack-task-policy";
|
|
16
19
|
export * from "./atlassian";
|
|
17
20
|
export * from "./connector-destinations";
|
|
21
|
+
export * from "./connector-attachments";
|
|
18
22
|
export * from "./memory-slack-delivery";
|
|
19
23
|
export * from "./image-generation";
|
|
20
24
|
export * from "./video-generation";
|
|
@@ -22,7 +26,10 @@ export * from "./editable-artifacts";
|
|
|
22
26
|
export * from "./editable-artifact-committed-transaction";
|
|
23
27
|
export * from "./editable-artifact-serialized-commit";
|
|
24
28
|
export * from "./tool-catalog";
|
|
29
|
+
export * from "./tool-result-spill";
|
|
25
30
|
export * from "./interaction";
|
|
31
|
+
export * from "./sandbox-file-artifacts";
|
|
32
|
+
export * from "./permissions";
|
|
26
33
|
|
|
27
34
|
export {
|
|
28
35
|
CreateWorkspaceArtifactRequest,
|
|
@@ -118,15 +125,21 @@ export {
|
|
|
118
125
|
export {
|
|
119
126
|
NATIVE_SNAPSHOT_PREFIXES,
|
|
120
127
|
WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION,
|
|
128
|
+
WORKSPACE_ARCHIVE_OBJECT_REF_SCHEMA,
|
|
121
129
|
backendForNativeSnapshotProvider,
|
|
122
130
|
decodeNativeSnapshotRef,
|
|
123
131
|
encodeNativeSnapshotRef,
|
|
132
|
+
omitInlineWorkspaceArchiveWhenObjectRefPresent,
|
|
124
133
|
parseWorkspaceArchiveDescriptor,
|
|
134
|
+
parseWorkspaceArchiveObjectRef,
|
|
135
|
+
workspaceArchiveObjectKey,
|
|
136
|
+
workspaceArchivePayloadPresent,
|
|
125
137
|
type NativeSnapshotDescriptor,
|
|
126
138
|
type NativeSnapshotProvider,
|
|
127
139
|
type NativeSnapshotRef,
|
|
128
140
|
type TarWorkspaceArchiveDescriptor,
|
|
129
141
|
type WorkspaceArchiveDescriptor,
|
|
142
|
+
type WorkspaceArchiveObjectRef,
|
|
130
143
|
type WorkspaceTreeFingerprint,
|
|
131
144
|
} from "./sandbox-snapshots";
|
|
132
145
|
|
|
@@ -147,11 +160,12 @@ export const SessionStatus = z.enum([
|
|
|
147
160
|
]);
|
|
148
161
|
export type SessionStatus = z.infer<typeof SessionStatus>;
|
|
149
162
|
|
|
150
|
-
//
|
|
163
|
+
// 12 backends; 3-way enum parity (contracts / sdk / deployment) is pinned by
|
|
151
164
|
// `packages/sdk/test/contract-parity.test.ts`. Every member is ADDITIVE AT THE
|
|
152
165
|
// END (the parity test pins positions): the original four, then the six cloud
|
|
153
166
|
// backends, then `selfhosted` (bring-your-own-compute — a user's own machine
|
|
154
|
-
// enrolled as a first-class sandbox)
|
|
167
|
+
// enrolled as a first-class sandbox), then `opensandbox` (an optional
|
|
168
|
+
// Kubernetes-native provisioned sandbox provider).
|
|
155
169
|
export const SandboxBackend = z.enum([
|
|
156
170
|
"docker",
|
|
157
171
|
"modal",
|
|
@@ -164,6 +178,7 @@ export const SandboxBackend = z.enum([
|
|
|
164
178
|
"cloudflare",
|
|
165
179
|
"vercel",
|
|
166
180
|
"selfhosted",
|
|
181
|
+
"opensandbox",
|
|
167
182
|
]);
|
|
168
183
|
export type SandboxBackend = z.infer<typeof SandboxBackend>;
|
|
169
184
|
|
|
@@ -189,6 +204,7 @@ export const SANDBOX_PROVIDER_INSTANCE_ID_FIELDS_BY_BACKEND = {
|
|
|
189
204
|
cloudflare: ["sandboxId"],
|
|
190
205
|
vercel: ["sandboxId"],
|
|
191
206
|
selfhosted: ["agentId"],
|
|
207
|
+
opensandbox: ["sandboxId"],
|
|
192
208
|
} as const satisfies Record<SandboxBackend, readonly string[]>;
|
|
193
209
|
export const LEGACY_SANDBOX_PROVIDER_INSTANCE_ID_FIELDS = [
|
|
194
210
|
"sandboxId",
|
|
@@ -593,6 +609,36 @@ export const CAPABILITY_DESCRIPTORS: Record<SandboxBackend, CapabilityDescriptor
|
|
|
593
609
|
persistable: false,
|
|
594
610
|
supportsRunAs: false,
|
|
595
611
|
},
|
|
612
|
+
// Optional Kubernetes-native provisioned sandbox through OpenSandbox.
|
|
613
|
+
// Desktop-class when the box image includes ttyd/browserd/Xvfb: PTY over ttyd,
|
|
614
|
+
// noVNC and browserd over signed URI-mode ingress. OpenGeni owns persistence
|
|
615
|
+
// through its portable tar checkpoint path in object storage; native
|
|
616
|
+
// OpenSandbox pause/resume and snapshots are deliberately not used.
|
|
617
|
+
opensandbox: {
|
|
618
|
+
backend: "opensandbox",
|
|
619
|
+
backendId: "opensandbox",
|
|
620
|
+
tier: "desktop",
|
|
621
|
+
os: { supported: ["linux"], default: "linux" },
|
|
622
|
+
capabilities: {
|
|
623
|
+
FileSystem: { available: true, readOnly: false },
|
|
624
|
+
Terminal: { available: true, transport: "sse-events", pty: true },
|
|
625
|
+
Git: { available: true },
|
|
626
|
+
DesktopStream: { available: true, transport: "vnc-ws" },
|
|
627
|
+
Recording: { available: true },
|
|
628
|
+
},
|
|
629
|
+
lifetime: {
|
|
630
|
+
requiresSnapshotRollover: false,
|
|
631
|
+
hasIdleKiller: false,
|
|
632
|
+
supportsSuspendResume: false,
|
|
633
|
+
resumeIsLockFree: true,
|
|
634
|
+
},
|
|
635
|
+
snapshot: { kind: "tar-only", hasTarFallback: true },
|
|
636
|
+
portExposure: { kind: "provider-tunnel", supportsOnDemandPorts: true },
|
|
637
|
+
workspaceRoot: "/workspace",
|
|
638
|
+
nativeBucketMount: false,
|
|
639
|
+
persistable: true,
|
|
640
|
+
supportsRunAs: false,
|
|
641
|
+
},
|
|
596
642
|
};
|
|
597
643
|
|
|
598
644
|
export const ReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
@@ -672,91 +718,6 @@ export const SessionSpawnDenial = z.object({
|
|
|
672
718
|
});
|
|
673
719
|
export type SessionSpawnDenial = z.infer<typeof SessionSpawnDenial>;
|
|
674
720
|
|
|
675
|
-
export const Permission = z.enum([
|
|
676
|
-
"account:read",
|
|
677
|
-
"account:admin",
|
|
678
|
-
"members:manage",
|
|
679
|
-
"workspace:create",
|
|
680
|
-
"billing:read",
|
|
681
|
-
"billing:manage",
|
|
682
|
-
"workspace:read",
|
|
683
|
-
"workspace:admin",
|
|
684
|
-
"sessions:create",
|
|
685
|
-
"sessions:read",
|
|
686
|
-
"sessions:control",
|
|
687
|
-
// sandbox workspace (sandbox contract §C.3 / crosscut PART 1.2). stream:view is a
|
|
688
|
-
// REAL, distinct permission — strictly BROADER than sessions:read — because the
|
|
689
|
-
// pixel plane (Channel B) exposes raw pixels: a viewer can see content the
|
|
690
|
-
// structured Channel-A event log never captured. sessions:read is NOT
|
|
691
|
-
// permission to watch raw pixels.
|
|
692
|
-
"stream:view",
|
|
693
|
-
// SEPARATE from stream:view: raw input to the desktop (bypasses approvalQueue /
|
|
694
|
-
// interrupt). NEVER granted by default in v1 (the input plane is OFF —
|
|
695
|
-
// streamControlEnabled=false); the permission exists so later hardening is a
|
|
696
|
-
// flag flip, not a redesign.
|
|
697
|
-
"stream:control",
|
|
698
|
-
// Accept the pixel-plane secret-leak acknowledgment (consent gate before the
|
|
699
|
-
// un-redacted desktop URL is handed out).
|
|
700
|
-
"stream:acknowledge",
|
|
701
|
-
"files:upload",
|
|
702
|
-
"files:read",
|
|
703
|
-
// Channel-A structured write surface (FS writes / apply-patch); distinct from
|
|
704
|
-
// files:read so a read-only viewer can't mutate the box filesystem.
|
|
705
|
-
"files:write",
|
|
706
|
-
// Attach to an interactive PTY (terminal-as-pty, Channel A); distinct from
|
|
707
|
-
// sessions:read which only reads the command-output firehose.
|
|
708
|
-
"terminal:attach",
|
|
709
|
-
"documents:manage",
|
|
710
|
-
"documents:search",
|
|
711
|
-
"scheduled_tasks:manage",
|
|
712
|
-
"scheduled_tasks:run",
|
|
713
|
-
"github:manage",
|
|
714
|
-
"github:use",
|
|
715
|
-
"api_keys:manage",
|
|
716
|
-
"connections:read",
|
|
717
|
-
"connections:write",
|
|
718
|
-
/** @deprecated alias of variable-sets:manage */
|
|
719
|
-
"environments:manage",
|
|
720
|
-
/** @deprecated alias of variable-sets:use */
|
|
721
|
-
"environments:use",
|
|
722
|
-
"variable-sets:list",
|
|
723
|
-
"variable-sets:read",
|
|
724
|
-
"variable-sets:write",
|
|
725
|
-
"variable-sets:manage",
|
|
726
|
-
"variable-sets:use",
|
|
727
|
-
"secrets:list",
|
|
728
|
-
"secrets:read",
|
|
729
|
-
"secrets:write",
|
|
730
|
-
// Attach or rotate per-session third-party MCP server credentials. Deliberately
|
|
731
|
-
// not part of the worker's default first-party MCP permission set: a sandboxed
|
|
732
|
-
// agent must not be able to hand itself new bearer credentials.
|
|
733
|
-
"mcp_servers:attach",
|
|
734
|
-
// Programmatic sandbox -> tool access through the first-party MCP gate. This is
|
|
735
|
-
// intentionally narrow and is never part of first-party MCP defaults; callers
|
|
736
|
-
// must receive it through an explicit delegated `ogd_` mint carrying sessionId.
|
|
737
|
-
"codemode:call",
|
|
738
|
-
"goals:manage",
|
|
739
|
-
// Bring-your-own-compute (M5). enrollments:read lists a workspace's machines;
|
|
740
|
-
// enrollments:manage approves a device-flow enrollment (the LOUD whole-machine
|
|
741
|
-
// consent) + revokes a machine. Distinct from sessions/stream perms because an
|
|
742
|
-
// enrollment grants WHOLE-MACHINE access to a user's own hardware — a high-trust,
|
|
743
|
-
// admin-shaped action. workspace:admin is the super-wildcard over both.
|
|
744
|
-
"enrollments:read",
|
|
745
|
-
"enrollments:manage",
|
|
746
|
-
// Rigs (workspace-scoped, versioned sandbox machine definitions). rigs:use is
|
|
747
|
-
// read + propose-change (the agent-native, additive path a sandboxed session
|
|
748
|
-
// is trusted with); rigs:manage is create/edit/activate/promote/delete (the
|
|
749
|
-
// admin-shaped path that mints or rolls versions). workspace:admin is the
|
|
750
|
-
// super-wildcard over both.
|
|
751
|
-
"rigs:use",
|
|
752
|
-
"rigs:manage",
|
|
753
|
-
// Workspace-published HTML artifacts. Read permits listing/source retrieval;
|
|
754
|
-
// publish permits create, version publication, and rollback.
|
|
755
|
-
"artifacts:read",
|
|
756
|
-
"artifacts:publish",
|
|
757
|
-
]);
|
|
758
|
-
export type Permission = z.infer<typeof Permission>;
|
|
759
|
-
|
|
760
721
|
/**
|
|
761
722
|
* Capability-first permissions signed into a session's first-party OpenGeni
|
|
762
723
|
* MCP token when a top-level creator does not explicitly narrow them.
|
|
@@ -780,8 +741,12 @@ export const DEFAULT_FIRST_PARTY_MCP_PERMISSIONS = [
|
|
|
780
741
|
// tools resolve an already-installed workspace principal. Credentials stay
|
|
781
742
|
// inside the broker and remain subject to each tool's own authorization.
|
|
782
743
|
"connections:read",
|
|
744
|
+
"variable-sets:list",
|
|
745
|
+
"variable-sets:write",
|
|
746
|
+
"variable-sets:attach",
|
|
783
747
|
"variable-sets:use",
|
|
784
|
-
"
|
|
748
|
+
"secrets:list",
|
|
749
|
+
"secrets:write",
|
|
785
750
|
"rigs:use",
|
|
786
751
|
"github:use",
|
|
787
752
|
"artifacts:read",
|
|
@@ -801,6 +766,7 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
|
|
|
801
766
|
"goal_set",
|
|
802
767
|
"goal_update",
|
|
803
768
|
"goal_progress",
|
|
769
|
+
"goal_wait",
|
|
804
770
|
"goal_complete",
|
|
805
771
|
"goal_pause",
|
|
806
772
|
"memory_search",
|
|
@@ -811,6 +777,18 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
|
|
|
811
777
|
"task_notes_list",
|
|
812
778
|
"task_note_save",
|
|
813
779
|
"task_note_archive",
|
|
780
|
+
"task_note_replace",
|
|
781
|
+
"knowledge_propose",
|
|
782
|
+
"knowledge_correct",
|
|
783
|
+
"task_note_promote_knowledge",
|
|
784
|
+
"task_note_promote_instruction_policy",
|
|
785
|
+
"task_note_promote_preference",
|
|
786
|
+
"instruction_policy_propose",
|
|
787
|
+
"preference_propose",
|
|
788
|
+
"remember",
|
|
789
|
+
"remember_confirm",
|
|
790
|
+
"company_profile_propose",
|
|
791
|
+
"company_profile_confirm",
|
|
814
792
|
"sandboxes_list",
|
|
815
793
|
"sandbox_attach",
|
|
816
794
|
"sandbox_swap",
|
|
@@ -825,11 +803,13 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
|
|
|
825
803
|
"sessions_list",
|
|
826
804
|
"session_get",
|
|
827
805
|
"session_events",
|
|
806
|
+
"session_wait",
|
|
828
807
|
"session_create",
|
|
829
808
|
"session_send_message",
|
|
830
809
|
"session_pause",
|
|
831
810
|
"session_resume",
|
|
832
811
|
"session_steer",
|
|
812
|
+
"session_human_input_respond",
|
|
833
813
|
"set_other_session_title",
|
|
834
814
|
"interaction_discover",
|
|
835
815
|
"browser_open",
|
|
@@ -888,6 +868,7 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
|
|
|
888
868
|
"scheduled_tasks_delete",
|
|
889
869
|
"scheduled_task_runs_list",
|
|
890
870
|
"slack_bot_list_channels",
|
|
871
|
+
"slack_bot_search",
|
|
891
872
|
"slack_bot_channel_history",
|
|
892
873
|
"slack_bot_thread_replies",
|
|
893
874
|
"slack_bot_list_users",
|
|
@@ -914,6 +895,7 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
|
|
|
914
895
|
"artifacts_create",
|
|
915
896
|
"artifacts_publish",
|
|
916
897
|
"artifacts_rollback",
|
|
898
|
+
"sandbox_file_publish",
|
|
917
899
|
"editable_artifact_list",
|
|
918
900
|
"editable_artifact_create",
|
|
919
901
|
"editable_artifact_import",
|
|
@@ -964,8 +946,15 @@ const FIRST_PARTY_IN_PROCESS_TOOL_NAME_SET = new Set<FirstPartyMcpToolName>(
|
|
|
964
946
|
* trustworthy logical-delivery identity. Server-owned Slack delivery paths
|
|
965
947
|
* call the internal client directly with their own durable operation IDs.
|
|
966
948
|
*/
|
|
949
|
+
// Names kept so previously written data still parses - immutable scheduled-task
|
|
950
|
+
// execution snapshots recorded the tool set that was default at the time, and
|
|
951
|
+
// they are strictly re-parsed on replay. Retiring a tool must not strand an
|
|
952
|
+
// accepted occurrence. These are never registered, never default, and never
|
|
953
|
+
// authorized; they exist so history stays readable.
|
|
967
954
|
const FIRST_PARTY_COMPATIBILITY_ONLY_TOOL_NAMES = [
|
|
968
955
|
"slack_bot_post_message",
|
|
956
|
+
"memory_save",
|
|
957
|
+
"memory_correct",
|
|
969
958
|
] as const satisfies readonly FirstPartyMcpToolName[];
|
|
970
959
|
|
|
971
960
|
const FIRST_PARTY_COMPATIBILITY_ONLY_TOOL_NAME_SET = new Set<FirstPartyMcpToolName>(
|
|
@@ -998,6 +987,10 @@ export const EDITABLE_ARTIFACT_MCP_CODEMODE_PATHS = {
|
|
|
998
987
|
*/
|
|
999
988
|
export const DEFAULT_FIRST_PARTY_MCP_TOOLS = FIRST_PARTY_MCP_TOOL_NAMES.filter(
|
|
1000
989
|
(name) =>
|
|
990
|
+
// Memory V1 writes are retired entirely; `remember` and task-note
|
|
991
|
+
// promotion own durable agent writes.
|
|
992
|
+
name !== "memory_save" &&
|
|
993
|
+
name !== "memory_correct" &&
|
|
1001
994
|
!name.startsWith("social_") &&
|
|
1002
995
|
!name.startsWith("x_") &&
|
|
1003
996
|
!name.startsWith("reddit_") &&
|
|
@@ -1053,6 +1046,178 @@ export const PersonalResourceRetentionMode = z.enum(["retain", "delete_after"]);
|
|
|
1053
1046
|
export type PersonalResourceRetentionMode = z.infer<typeof PersonalResourceRetentionMode>;
|
|
1054
1047
|
|
|
1055
1048
|
export const SessionTenancyVisibility = z.enum(["user_private", "workspace_shared"]);
|
|
1049
|
+
|
|
1050
|
+
export const UserResourceAuthorityScope = z.literal("user");
|
|
1051
|
+
export const UserResourceKind = z.enum([
|
|
1052
|
+
"connection",
|
|
1053
|
+
"document",
|
|
1054
|
+
"variable_set",
|
|
1055
|
+
"rig",
|
|
1056
|
+
"connected_machine",
|
|
1057
|
+
]);
|
|
1058
|
+
export type UserResourceKind = z.infer<typeof UserResourceKind>;
|
|
1059
|
+
|
|
1060
|
+
export const USER_RESOURCE_ACTION_BY_KIND = {
|
|
1061
|
+
connection: "connection.use",
|
|
1062
|
+
document: "document.read",
|
|
1063
|
+
variable_set: "variable_set.use",
|
|
1064
|
+
rig: "rig.use",
|
|
1065
|
+
connected_machine: "connected_machine.use",
|
|
1066
|
+
} as const satisfies Record<UserResourceKind, string>;
|
|
1067
|
+
|
|
1068
|
+
export const UserResourceLifecycleGrantMode = z.enum(["once", "session", "always"]);
|
|
1069
|
+
export const PERSONAL_RESOURCE_SHARED_OUTPUT_WARNING_VERSION = 1 as const;
|
|
1070
|
+
export const PERSONAL_RESOURCE_SHARED_OUTPUT_WARNING =
|
|
1071
|
+
"Personal resources used in a workspace-shared session may influence outputs visible to other workspace members. The underlying credentials and secret values are not shared by the attachment itself.";
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* Owner-authored issuance intent for the fixed personal Variable Set/Rig/
|
|
1075
|
+
* Connected Machine closure selected by one session. The server derives every resource,
|
|
1076
|
+
* authority and action from the locked session; callers never nominate grants.
|
|
1077
|
+
*/
|
|
1078
|
+
export const PersonalResourceAttachmentIntent = z
|
|
1079
|
+
.object({
|
|
1080
|
+
mode: UserResourceLifecycleGrantMode,
|
|
1081
|
+
expectedAuthorityEpoch: z.number().int().positive().optional(),
|
|
1082
|
+
workspaceSharedAcknowledged: z.boolean().default(false),
|
|
1083
|
+
sharedOutputWarningVersion: z.literal(PERSONAL_RESOURCE_SHARED_OUTPUT_WARNING_VERSION),
|
|
1084
|
+
})
|
|
1085
|
+
.strict();
|
|
1086
|
+
export type PersonalResourceAttachmentIntent = z.infer<typeof PersonalResourceAttachmentIntent>;
|
|
1087
|
+
|
|
1088
|
+
function requireEstablishedPersonalResourceEpoch(
|
|
1089
|
+
value: {
|
|
1090
|
+
personalResourceAttachment?: PersonalResourceAttachmentIntent | undefined;
|
|
1091
|
+
},
|
|
1092
|
+
context: z.RefinementCtx,
|
|
1093
|
+
): void {
|
|
1094
|
+
if (
|
|
1095
|
+
value.personalResourceAttachment !== undefined &&
|
|
1096
|
+
value.personalResourceAttachment.expectedAuthorityEpoch === undefined
|
|
1097
|
+
) {
|
|
1098
|
+
context.addIssue({
|
|
1099
|
+
code: z.ZodIssueCode.custom,
|
|
1100
|
+
path: ["personalResourceAttachment", "expectedAuthorityEpoch"],
|
|
1101
|
+
message: "established-session attachment requires expectedAuthorityEpoch",
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/** Credential-free accepted-work projection. Resource ids remain private. */
|
|
1107
|
+
export const PersonalResourceAttachmentSummary = z
|
|
1108
|
+
.object({
|
|
1109
|
+
mode: UserResourceLifecycleGrantMode,
|
|
1110
|
+
context: SessionTenancyVisibility,
|
|
1111
|
+
resourceCount: z.number().int().positive(),
|
|
1112
|
+
resourceKinds: z
|
|
1113
|
+
.array(z.enum(["variable_set", "rig", "connected_machine"]))
|
|
1114
|
+
.min(1)
|
|
1115
|
+
.max(3),
|
|
1116
|
+
sharedOutputWarningVersion: z.literal(PERSONAL_RESOURCE_SHARED_OUTPUT_WARNING_VERSION),
|
|
1117
|
+
})
|
|
1118
|
+
.strict();
|
|
1119
|
+
export type PersonalResourceAttachmentSummary = z.infer<typeof PersonalResourceAttachmentSummary>;
|
|
1120
|
+
/** Public owner-management deliberately excludes race-prone standalone `once`. */
|
|
1121
|
+
export const ManagedUserResourceGrantMode = z.enum(["session", "always"]);
|
|
1122
|
+
export const UserResourceAuthorityGrant = z.object({
|
|
1123
|
+
grantId: z.string().uuid(),
|
|
1124
|
+
targetWorkspaceId: z.string().uuid(),
|
|
1125
|
+
targetSessionId: z.string().uuid().nullable(),
|
|
1126
|
+
action: z.enum([
|
|
1127
|
+
"connection.use",
|
|
1128
|
+
"document.read",
|
|
1129
|
+
"variable_set.use",
|
|
1130
|
+
"rig.use",
|
|
1131
|
+
"connected_machine.use",
|
|
1132
|
+
]),
|
|
1133
|
+
mode: UserResourceLifecycleGrantMode,
|
|
1134
|
+
context: SessionTenancyVisibility,
|
|
1135
|
+
authorityEpoch: z.number().int().positive().nullable(),
|
|
1136
|
+
generation: z.number().int().positive(),
|
|
1137
|
+
status: z.enum(["active", "consumed", "revoked", "expired"]),
|
|
1138
|
+
expiresAt: z.string().datetime().nullable(),
|
|
1139
|
+
delegation: z.lazy(() => UserResourceDelegation),
|
|
1140
|
+
});
|
|
1141
|
+
export const UserResourceAuthoritySummary = z.object({
|
|
1142
|
+
authorityId: z.string().uuid(),
|
|
1143
|
+
resourceKind: UserResourceKind,
|
|
1144
|
+
resourceId: z.string().uuid(),
|
|
1145
|
+
originWorkspaceId: z.string().uuid().nullable(),
|
|
1146
|
+
generation: z.number().int().positive(),
|
|
1147
|
+
status: z.enum(["active", "retained", "revoked"]),
|
|
1148
|
+
grants: z.array(UserResourceAuthorityGrant),
|
|
1149
|
+
});
|
|
1150
|
+
export const ListUserResourceAuthoritiesQuery = z.object({
|
|
1151
|
+
scope: UserResourceAuthorityScope,
|
|
1152
|
+
resourceKind: UserResourceKind,
|
|
1153
|
+
cursor: z.string().uuid().optional(),
|
|
1154
|
+
limit: z.coerce.number().int().min(1).max(100).default(50),
|
|
1155
|
+
});
|
|
1156
|
+
export const ListUserResourceAuthoritiesResponse = z.object({
|
|
1157
|
+
scope: UserResourceAuthorityScope,
|
|
1158
|
+
authorities: z.array(UserResourceAuthoritySummary),
|
|
1159
|
+
nextCursor: z.string().uuid().nullable(),
|
|
1160
|
+
});
|
|
1161
|
+
export const IssueUserResourceGrantRequest = z
|
|
1162
|
+
.object({
|
|
1163
|
+
scope: UserResourceAuthorityScope,
|
|
1164
|
+
resourceKind: UserResourceKind,
|
|
1165
|
+
mode: ManagedUserResourceGrantMode,
|
|
1166
|
+
context: SessionTenancyVisibility,
|
|
1167
|
+
sessionId: z.string().uuid().nullable().optional(),
|
|
1168
|
+
expectedAuthorityEpoch: z.number().int().positive().nullable().optional(),
|
|
1169
|
+
workspaceSharedAcknowledged: z.boolean().default(false),
|
|
1170
|
+
})
|
|
1171
|
+
.superRefine((value, context) => {
|
|
1172
|
+
if (value.context === "workspace_shared" && !value.workspaceSharedAcknowledged) {
|
|
1173
|
+
context.addIssue({
|
|
1174
|
+
code: "custom",
|
|
1175
|
+
path: ["workspaceSharedAcknowledged"],
|
|
1176
|
+
message: "workspace_shared requires durable shared-output acknowledgement",
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
if (value.mode === "always" && (value.sessionId || value.expectedAuthorityEpoch)) {
|
|
1180
|
+
context.addIssue({
|
|
1181
|
+
code: "custom",
|
|
1182
|
+
path: ["sessionId"],
|
|
1183
|
+
message: "always is unbound from session authority",
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
if (value.mode === "session" && (!value.sessionId || !value.expectedAuthorityEpoch)) {
|
|
1187
|
+
context.addIssue({
|
|
1188
|
+
code: "custom",
|
|
1189
|
+
path: ["sessionId"],
|
|
1190
|
+
message: "session grants require a target session and expectedAuthorityEpoch",
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
});
|
|
1194
|
+
export const UserResourceGrantMutationResponse = z.object({
|
|
1195
|
+
scope: UserResourceAuthorityScope,
|
|
1196
|
+
grant: UserResourceAuthorityGrant,
|
|
1197
|
+
});
|
|
1198
|
+
export const UserResourceGrantRevocationResponse = z.object({
|
|
1199
|
+
scope: UserResourceAuthorityScope,
|
|
1200
|
+
grant: z.object({
|
|
1201
|
+
grantId: z.string().uuid(),
|
|
1202
|
+
generation: z.number().int().positive(),
|
|
1203
|
+
status: z.literal("revoked"),
|
|
1204
|
+
revokedAt: z.string().datetime(),
|
|
1205
|
+
}),
|
|
1206
|
+
});
|
|
1207
|
+
export const RevokeUserResourceGrantQuery = z.object({
|
|
1208
|
+
scope: UserResourceAuthorityScope,
|
|
1209
|
+
});
|
|
1210
|
+
export type UserResourceAuthorityGrant = z.infer<typeof UserResourceAuthorityGrant>;
|
|
1211
|
+
export type UserResourceAuthoritySummary = z.infer<typeof UserResourceAuthoritySummary>;
|
|
1212
|
+
export type ListUserResourceAuthoritiesQuery = z.infer<typeof ListUserResourceAuthoritiesQuery>;
|
|
1213
|
+
export type ListUserResourceAuthoritiesResponse = z.infer<
|
|
1214
|
+
typeof ListUserResourceAuthoritiesResponse
|
|
1215
|
+
>;
|
|
1216
|
+
export type IssueUserResourceGrantRequest = z.infer<typeof IssueUserResourceGrantRequest>;
|
|
1217
|
+
export type UserResourceGrantMutationResponse = z.infer<typeof UserResourceGrantMutationResponse>;
|
|
1218
|
+
export type UserResourceGrantRevocationResponse = z.infer<
|
|
1219
|
+
typeof UserResourceGrantRevocationResponse
|
|
1220
|
+
>;
|
|
1056
1221
|
export type SessionTenancyVisibility = z.infer<typeof SessionTenancyVisibility>;
|
|
1057
1222
|
|
|
1058
1223
|
/** Public/session API vocabulary. Persistence keeps the explicit tenancy names. */
|
|
@@ -1274,6 +1439,100 @@ export const SessionTenancyPublicProjection = z.object({
|
|
|
1274
1439
|
});
|
|
1275
1440
|
export type SessionTenancyPublicProjection = z.infer<typeof SessionTenancyPublicProjection>;
|
|
1276
1441
|
|
|
1442
|
+
export const SessionTenancyBlocker = z.enum([
|
|
1443
|
+
"nonterminal_turn",
|
|
1444
|
+
"nonterminal_attempt",
|
|
1445
|
+
"unsettled_interruption",
|
|
1446
|
+
"pending_system_update",
|
|
1447
|
+
"pending_human_input",
|
|
1448
|
+
"pending_tool_receipt",
|
|
1449
|
+
"run_state",
|
|
1450
|
+
"active_goal",
|
|
1451
|
+
"capacity_waiter",
|
|
1452
|
+
"active_realtime",
|
|
1453
|
+
"active_scheduled_task",
|
|
1454
|
+
"workspace_mutation_admission",
|
|
1455
|
+
"retained_process",
|
|
1456
|
+
"active_sandbox_access",
|
|
1457
|
+
"shared_sandbox_group",
|
|
1458
|
+
]);
|
|
1459
|
+
export type SessionTenancyBlocker = z.infer<typeof SessionTenancyBlocker>;
|
|
1460
|
+
|
|
1461
|
+
export const SESSION_OPERATION_KEY_MAX_CHARS = 256;
|
|
1462
|
+
const SessionTenancyIdempotencyKey = z.string().trim().min(1).max(SESSION_OPERATION_KEY_MAX_CHARS);
|
|
1463
|
+
|
|
1464
|
+
export const UpdateSessionVisibilityRequest = z
|
|
1465
|
+
.object({
|
|
1466
|
+
visibility: SessionVisibility,
|
|
1467
|
+
expectedAuthorityEpoch: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
1468
|
+
idempotencyKey: SessionTenancyIdempotencyKey,
|
|
1469
|
+
})
|
|
1470
|
+
.strict();
|
|
1471
|
+
export type UpdateSessionVisibilityRequest = z.infer<typeof UpdateSessionVisibilityRequest>;
|
|
1472
|
+
|
|
1473
|
+
export const UpdateSessionVisibilityResponse = z
|
|
1474
|
+
.object({
|
|
1475
|
+
operationId: z.string().uuid(),
|
|
1476
|
+
eventId: z.string().uuid().nullable(),
|
|
1477
|
+
eventSequence: z.number().int().positive().nullable(),
|
|
1478
|
+
visibility: SessionVisibility,
|
|
1479
|
+
authorityEpoch: z.number().int().positive(),
|
|
1480
|
+
changed: z.boolean(),
|
|
1481
|
+
replay: z.boolean(),
|
|
1482
|
+
revokedGrantCount: z.number().int().nonnegative(),
|
|
1483
|
+
})
|
|
1484
|
+
.strict()
|
|
1485
|
+
.superRefine((value, context) => {
|
|
1486
|
+
if (value.changed !== (value.eventId !== null && value.eventSequence !== null)) {
|
|
1487
|
+
context.addIssue({
|
|
1488
|
+
code: "custom",
|
|
1489
|
+
path: ["changed"],
|
|
1490
|
+
message: "changed must match the presence of the durable event receipt",
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
if ((value.eventId === null) !== (value.eventSequence === null)) {
|
|
1494
|
+
context.addIssue({
|
|
1495
|
+
code: "custom",
|
|
1496
|
+
path: ["eventId"],
|
|
1497
|
+
message: "eventId and eventSequence must be present or absent together",
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
});
|
|
1501
|
+
export type UpdateSessionVisibilityResponse = z.infer<typeof UpdateSessionVisibilityResponse>;
|
|
1502
|
+
|
|
1503
|
+
export const ForkSessionRequest = z
|
|
1504
|
+
.object({
|
|
1505
|
+
idempotencyKey: SessionTenancyIdempotencyKey,
|
|
1506
|
+
visibility: SessionVisibility,
|
|
1507
|
+
workspaceSharedAcknowledged: z.boolean(),
|
|
1508
|
+
})
|
|
1509
|
+
.strict()
|
|
1510
|
+
.superRefine((value, context) => {
|
|
1511
|
+
if (value.visibility === "private" && value.workspaceSharedAcknowledged) {
|
|
1512
|
+
context.addIssue({
|
|
1513
|
+
code: "custom",
|
|
1514
|
+
path: ["workspaceSharedAcknowledged"],
|
|
1515
|
+
message: "workspaceSharedAcknowledged must be false for a private destination",
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1519
|
+
export type ForkSessionRequest = z.infer<typeof ForkSessionRequest>;
|
|
1520
|
+
|
|
1521
|
+
export const ForkSessionResponse = z
|
|
1522
|
+
.object({
|
|
1523
|
+
operationId: z.string().uuid(),
|
|
1524
|
+
eventId: z.string().uuid(),
|
|
1525
|
+
eventSequence: z.number().int().positive(),
|
|
1526
|
+
sessionId: z.string().uuid(),
|
|
1527
|
+
workspaceId: z.string().uuid(),
|
|
1528
|
+
visibility: SessionVisibility,
|
|
1529
|
+
authorityEpoch: z.literal(1),
|
|
1530
|
+
copiedHistoryItemCount: z.number().int().nonnegative(),
|
|
1531
|
+
replay: z.boolean(),
|
|
1532
|
+
})
|
|
1533
|
+
.strict();
|
|
1534
|
+
export type ForkSessionResponse = z.infer<typeof ForkSessionResponse>;
|
|
1535
|
+
|
|
1277
1536
|
export const ManagedAccount = z.object({
|
|
1278
1537
|
id: z.string().uuid(),
|
|
1279
1538
|
name: z.string(),
|
|
@@ -1621,6 +1880,37 @@ export const WorkspaceVoiceInputSettings = z
|
|
|
1621
1880
|
.strict();
|
|
1622
1881
|
export type WorkspaceVoiceInputSettings = z.infer<typeof WorkspaceVoiceInputSettings>;
|
|
1623
1882
|
|
|
1883
|
+
/** Model policy inherited by newly created chats and scheduled tasks. */
|
|
1884
|
+
export const WorkspaceSessionDefaults = z
|
|
1885
|
+
.object({
|
|
1886
|
+
model: z.string().trim().min(1).max(256),
|
|
1887
|
+
reasoningEffort: ReasoningEffort,
|
|
1888
|
+
})
|
|
1889
|
+
.strict();
|
|
1890
|
+
export type WorkspaceSessionDefaults = z.infer<typeof WorkspaceSessionDefaults>;
|
|
1891
|
+
|
|
1892
|
+
/**
|
|
1893
|
+
* Exact capability selection inherited by new top-level sessions.
|
|
1894
|
+
*
|
|
1895
|
+
* The product UI presents understandable capability groups, but persistence
|
|
1896
|
+
* stays source-of-truth exact: MCP server ids and first-party tool names. This
|
|
1897
|
+
* keeps the runtime independent from presentation labels and lets a session
|
|
1898
|
+
* narrow the resulting policy without changing the workspace default.
|
|
1899
|
+
*/
|
|
1900
|
+
export const WorkspaceSessionToolDefaults = z
|
|
1901
|
+
.object({
|
|
1902
|
+
mcpServerIds: z
|
|
1903
|
+
.array(z.string().trim().min(1).max(128))
|
|
1904
|
+
.max(128)
|
|
1905
|
+
.transform((ids) => [...new Set(ids)]),
|
|
1906
|
+
firstPartyMcpTools: z
|
|
1907
|
+
.array(FirstPartyMcpToolName)
|
|
1908
|
+
.max(512)
|
|
1909
|
+
.transform((tools) => [...new Set(tools)]),
|
|
1910
|
+
})
|
|
1911
|
+
.strict();
|
|
1912
|
+
export type WorkspaceSessionToolDefaults = z.infer<typeof WorkspaceSessionToolDefaults>;
|
|
1913
|
+
|
|
1624
1914
|
/** Client-safe voice-input capability projection. Never includes provider secrets. */
|
|
1625
1915
|
export const ClientVoiceInputConfig = z
|
|
1626
1916
|
.object({
|
|
@@ -1714,17 +2004,79 @@ export const DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS = {
|
|
|
1714
2004
|
channelPolicy: { mode: "bot_member" },
|
|
1715
2005
|
} as const satisfies WorkspaceSlackReactionSummonSettings;
|
|
1716
2006
|
|
|
2007
|
+
/**
|
|
2008
|
+
* Per-workspace switches for the two Slack orchestration notices: a pointer
|
|
2009
|
+
* card when a child worker of a Slack-originated session blocks on human input
|
|
2010
|
+
* or a tool approval, and a one-line notice when that session's goal pauses for
|
|
2011
|
+
* budget or the continuation cap.
|
|
2012
|
+
*
|
|
2013
|
+
* Both are OFF unless this workspace explicitly turned them on. An unsolicited
|
|
2014
|
+
* Slack post is worse than a missed one, and the in-app rail and priority feed
|
|
2015
|
+
* already surface a blocked child, so an absent, malformed, or partially
|
|
2016
|
+
* invalid setting resolves to both disabled - see
|
|
2017
|
+
* `resolveWorkspaceSlackOrchestrationNoticeSettings`.
|
|
2018
|
+
*
|
|
2019
|
+
* Deliberately not `.strict()`: this is a KNOWN key of the stored settings bag,
|
|
2020
|
+
* so rejecting it rejects the whole bag and silently reverts memoryEnabled,
|
|
2021
|
+
* agentHumanInputEnabled, codexCompactionDefault, voiceInput, and the Slack
|
|
2022
|
+
* reaction shortcut to their defaults too. An unknown key here is a notice a
|
|
2023
|
+
* newer release added, and a rollback must not cost five unrelated settings.
|
|
2024
|
+
* An invalid VALUE still fails the bag, and therefore fails closed to silence.
|
|
2025
|
+
*/
|
|
2026
|
+
export const WorkspaceSlackOrchestrationNoticeSettings = z.object({
|
|
2027
|
+
childRequiresAction: z.boolean().optional(),
|
|
2028
|
+
goalPaused: z.boolean().optional(),
|
|
2029
|
+
});
|
|
2030
|
+
export type WorkspaceSlackOrchestrationNoticeSettings = z.infer<
|
|
2031
|
+
typeof WorkspaceSlackOrchestrationNoticeSettings
|
|
2032
|
+
>;
|
|
2033
|
+
|
|
2034
|
+
/**
|
|
2035
|
+
* The resolved answer: every notice is an explicit boolean, never absent.
|
|
2036
|
+
* Spelled out rather than derived with `Required<>`, which would keep the
|
|
2037
|
+
* `| undefined` that the optional zod fields carry into their inferred type.
|
|
2038
|
+
*/
|
|
2039
|
+
export type ResolvedWorkspaceSlackOrchestrationNoticeSettings = {
|
|
2040
|
+
childRequiresAction: boolean;
|
|
2041
|
+
goalPaused: boolean;
|
|
2042
|
+
};
|
|
2043
|
+
|
|
2044
|
+
export const DEFAULT_WORKSPACE_SLACK_ORCHESTRATION_NOTICE_SETTINGS = {
|
|
2045
|
+
childRequiresAction: false,
|
|
2046
|
+
goalPaused: false,
|
|
2047
|
+
} as const satisfies ResolvedWorkspaceSlackOrchestrationNoticeSettings;
|
|
2048
|
+
|
|
2049
|
+
// Memory V1's standing prompt block is retired, but the enum deliberately still
|
|
2050
|
+
// ACCEPTS `legacy_standing`. `.passthrough()` only preserves unknown keys - it
|
|
2051
|
+
// does not rescue a known key holding a value the enum rejects - so collapsing
|
|
2052
|
+
// this to one value would fail the whole settings parse for any workspace that
|
|
2053
|
+
// opted in. Every resolver here is "parse the bag, fall back on failure", so
|
|
2054
|
+
// that single rejection would silently revert memoryEnabled,
|
|
2055
|
+
// agentHumanInputEnabled, codexCompactionDefault, voiceInput and Slack summon
|
|
2056
|
+
// to their defaults. The value is accepted and then ignored: see
|
|
2057
|
+
// resolveWorkspaceMemoryPromptMode.
|
|
1717
2058
|
export const WorkspaceMemoryPromptMode = z.enum(["legacy_standing", "retrieval_only"]);
|
|
1718
2059
|
export type WorkspaceMemoryPromptMode = z.infer<typeof WorkspaceMemoryPromptMode>;
|
|
1719
2060
|
|
|
2061
|
+
/**
|
|
2062
|
+
* What an already-accepted turn recorded. Snapshots and receipts are immutable,
|
|
2063
|
+
* so turns accepted before the standing block was retired still read back
|
|
2064
|
+
* `legacy_standing`. That is a fact about history, not a mode anyone can pick -
|
|
2065
|
+
* keep the two apart so retiring the setting never rewrites the record.
|
|
2066
|
+
*/
|
|
2067
|
+
export const HistoricalMemoryPromptMode = z.enum(["legacy_standing", "retrieval_only"]);
|
|
2068
|
+
export type HistoricalMemoryPromptMode = z.infer<typeof HistoricalMemoryPromptMode>;
|
|
2069
|
+
|
|
1720
2070
|
// Validates the KNOWN keys of workspaces.settings; passthrough keeps unknown
|
|
1721
2071
|
// (future) keys rather than stripping them. memoryEnabled defaults off and the
|
|
1722
|
-
//
|
|
2072
|
+
// Memory V1 prompt mode is always retrieval-only composition;
|
|
1723
2073
|
// voiceInput defaults to enabled when the deployment has a provider.
|
|
1724
2074
|
export const WorkspaceSettingsSchema = z
|
|
1725
2075
|
.object({
|
|
1726
2076
|
memoryEnabled: z.boolean().optional(),
|
|
1727
2077
|
memoryPromptMode: WorkspaceMemoryPromptMode.optional(),
|
|
2078
|
+
sessionDefaults: WorkspaceSessionDefaults.optional(),
|
|
2079
|
+
sessionToolDefaults: WorkspaceSessionToolDefaults.optional(),
|
|
1728
2080
|
/** Preferred workspace voice-input toggle. */
|
|
1729
2081
|
voiceInput: WorkspaceVoiceInputSettings.optional(),
|
|
1730
2082
|
/**
|
|
@@ -1744,6 +2096,11 @@ export const WorkspaceSettingsSchema = z
|
|
|
1744
2096
|
// Optional Slack reaction invocation. Absent/invalid fails closed to the
|
|
1745
2097
|
// disabled default via resolveWorkspaceSlackReactionSummonSettings.
|
|
1746
2098
|
slackReactionSummon: WorkspaceSlackReactionSummonSettings.optional(),
|
|
2099
|
+
// Optional Slack orchestration notices (blocked child worker, paused goal).
|
|
2100
|
+
// BOTH DEFAULT OFF: absent, malformed, or partially invalid settings fail
|
|
2101
|
+
// closed to disabled via resolveWorkspaceSlackOrchestrationNoticeSettings,
|
|
2102
|
+
// because an unsolicited Slack post is worse than a missed one.
|
|
2103
|
+
slackOrchestrationNotices: WorkspaceSlackOrchestrationNoticeSettings.optional(),
|
|
1747
2104
|
})
|
|
1748
2105
|
.passthrough();
|
|
1749
2106
|
export type WorkspaceSettings = z.infer<typeof WorkspaceSettingsSchema>;
|
|
@@ -1754,10 +2111,31 @@ export function resolveWorkspaceMemoryEnabled(settings: unknown): boolean {
|
|
|
1754
2111
|
return parsed.success ? parsed.data.memoryEnabled === true : false;
|
|
1755
2112
|
}
|
|
1756
2113
|
|
|
1757
|
-
/**
|
|
1758
|
-
export function
|
|
2114
|
+
/** Explicit defaults for new chats/schedules, or null for deployment defaults. */
|
|
2115
|
+
export function resolveWorkspaceSessionDefaults(
|
|
2116
|
+
settings: unknown,
|
|
2117
|
+
): WorkspaceSessionDefaults | null {
|
|
2118
|
+
const parsed = WorkspaceSettingsSchema.safeParse(settings ?? {});
|
|
2119
|
+
return parsed.success ? (parsed.data.sessionDefaults ?? null) : null;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
/** Exact capability defaults for new sessions, or null for deployment defaults. */
|
|
2123
|
+
export function resolveWorkspaceSessionToolDefaults(
|
|
2124
|
+
settings: unknown,
|
|
2125
|
+
): WorkspaceSessionToolDefaults | null {
|
|
1759
2126
|
const parsed = WorkspaceSettingsSchema.safeParse(settings ?? {});
|
|
1760
|
-
return parsed.success ? (parsed.data.
|
|
2127
|
+
return parsed.success ? (parsed.data.sessionToolDefaults ?? null) : null;
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
/**
|
|
2131
|
+
* Memory V1 prompt mode. Always `retrieval_only`: the standing pinned/recency
|
|
2132
|
+
* block is retired, so an absent, unrecognized, or stored-`legacy_standing`
|
|
2133
|
+
* setting all resolve the same way. Kept as a function so the call sites and
|
|
2134
|
+
* the frozen SQL snapshot keep agreeing without each one having to learn that
|
|
2135
|
+
* the choice is gone.
|
|
2136
|
+
*/
|
|
2137
|
+
export function resolveWorkspaceMemoryPromptMode(): "retrieval_only" {
|
|
2138
|
+
return "retrieval_only";
|
|
1761
2139
|
}
|
|
1762
2140
|
|
|
1763
2141
|
/** Default Codex compaction mode for new Codex sessions (remote_v2 when unset). */
|
|
@@ -1814,6 +2192,30 @@ export function resolveWorkspaceSlackReactionSummonSettings(
|
|
|
1814
2192
|
: { ...configured, channelPolicy: { mode: "bot_member" } };
|
|
1815
2193
|
}
|
|
1816
2194
|
|
|
2195
|
+
/**
|
|
2196
|
+
* Resolve the two Slack orchestration notice switches, failing closed.
|
|
2197
|
+
*
|
|
2198
|
+
* Off is the product decision, not a placeholder: the in-app rail and priority
|
|
2199
|
+
* feed already surface a blocked child worker and a paused goal, so a missed
|
|
2200
|
+
* Slack post costs a delay while an unsolicited one costs the thread's
|
|
2201
|
+
* credibility. Absent settings, a settings bag this schema rejects, and a
|
|
2202
|
+
* partially invalid notice object therefore all resolve to both disabled -
|
|
2203
|
+
* only an explicit `true` on a valid bag turns a notice on.
|
|
2204
|
+
*/
|
|
2205
|
+
export function resolveWorkspaceSlackOrchestrationNoticeSettings(
|
|
2206
|
+
settings: unknown,
|
|
2207
|
+
): ResolvedWorkspaceSlackOrchestrationNoticeSettings {
|
|
2208
|
+
const parsed = WorkspaceSettingsSchema.safeParse(settings ?? {});
|
|
2209
|
+
const configured = parsed.success ? parsed.data.slackOrchestrationNotices : undefined;
|
|
2210
|
+
return {
|
|
2211
|
+
childRequiresAction:
|
|
2212
|
+
configured?.childRequiresAction ??
|
|
2213
|
+
DEFAULT_WORKSPACE_SLACK_ORCHESTRATION_NOTICE_SETTINGS.childRequiresAction,
|
|
2214
|
+
goalPaused:
|
|
2215
|
+
configured?.goalPaused ?? DEFAULT_WORKSPACE_SLACK_ORCHESTRATION_NOTICE_SETTINGS.goalPaused,
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2218
|
+
|
|
1817
2219
|
export function workspaceSlackReactionChannelAllowed(
|
|
1818
2220
|
settings: WorkspaceSlackReactionSummonSettings,
|
|
1819
2221
|
channelId: string,
|
|
@@ -1831,6 +2233,8 @@ export const UpdateWorkspaceSettingsRequest = z
|
|
|
1831
2233
|
.object({
|
|
1832
2234
|
memoryEnabled: z.boolean().optional(),
|
|
1833
2235
|
memoryPromptMode: WorkspaceMemoryPromptMode.optional(),
|
|
2236
|
+
sessionDefaults: WorkspaceSessionDefaults.optional(),
|
|
2237
|
+
sessionToolDefaults: WorkspaceSessionToolDefaults.optional(),
|
|
1834
2238
|
voiceInput: WorkspaceVoiceInputSettings.optional(),
|
|
1835
2239
|
/** @deprecated Prefer `voiceInput`. Kept for one compatibility release. */
|
|
1836
2240
|
transcription: WorkspaceTranscriptionPolicy.optional(),
|
|
@@ -1838,6 +2242,7 @@ export const UpdateWorkspaceSettingsRequest = z
|
|
|
1838
2242
|
codexCompactionDefault: CodexCompactionMode.optional(),
|
|
1839
2243
|
agentHumanInputEnabled: z.boolean().optional(),
|
|
1840
2244
|
slackReactionSummon: WorkspaceSlackReactionSummonSettings.optional(),
|
|
2245
|
+
slackOrchestrationNotices: WorkspaceSlackOrchestrationNoticeSettings.optional(),
|
|
1841
2246
|
})
|
|
1842
2247
|
.passthrough();
|
|
1843
2248
|
export type UpdateWorkspaceSettingsRequest = z.infer<typeof UpdateWorkspaceSettingsRequest>;
|
|
@@ -2348,6 +2753,17 @@ export const StreamTokenPayload = z.object({
|
|
|
2348
2753
|
// Short TTL (120s default); rotation is event-driven under the epoch fence,
|
|
2349
2754
|
// not on a keepalive clock.
|
|
2350
2755
|
exp: z.number().int().positive(),
|
|
2756
|
+
// The authenticated subject the token was minted for (0281). Optional for
|
|
2757
|
+
// rolling compatibility: old verifiers strip it, old mints omit it.
|
|
2758
|
+
subjectId: z.string().min(1).max(512).optional(),
|
|
2759
|
+
// The session authority epoch observed at mint (0281). The relay tracks the
|
|
2760
|
+
// highest value presented per LIVE channel and rejects tokens below that
|
|
2761
|
+
// floor. The floor is defense-in-depth, not the revocation authority: it
|
|
2762
|
+
// lives only as long as the channel does (both sides detached, the
|
|
2763
|
+
// half-open reaper, or a relay restart reset it), so a stale in-TTL token
|
|
2764
|
+
// can still attach to a fresh channel. Real revocation is the mint refusing
|
|
2765
|
+
// to issue new tokens plus the 120 s TTL bounding the old ones.
|
|
2766
|
+
authorityEpoch: z.number().int().positive().optional(),
|
|
2351
2767
|
});
|
|
2352
2768
|
export type StreamTokenPayload = z.infer<typeof StreamTokenPayload>;
|
|
2353
2769
|
|
|
@@ -2509,6 +2925,7 @@ export const ApiKey = z.object({
|
|
|
2509
2925
|
accountId: z.string().uuid(),
|
|
2510
2926
|
workspaceId: z.string().uuid().nullable(),
|
|
2511
2927
|
name: z.string(),
|
|
2928
|
+
description: z.string().nullable(),
|
|
2512
2929
|
prefix: z.string(),
|
|
2513
2930
|
permissions: z.array(Permission),
|
|
2514
2931
|
expiresAt: z.string().nullable(),
|
|
@@ -2521,6 +2938,7 @@ export type ApiKey = z.infer<typeof ApiKey>;
|
|
|
2521
2938
|
|
|
2522
2939
|
export const CreateApiKeyRequest = z.object({
|
|
2523
2940
|
name: z.string().min(1),
|
|
2941
|
+
description: z.string().trim().min(1).max(500).optional(),
|
|
2524
2942
|
workspaceId: z.string().uuid().optional(),
|
|
2525
2943
|
permissions: z.array(Permission).min(1),
|
|
2526
2944
|
expiresAt: z.string().datetime({ offset: true }).optional(),
|
|
@@ -2674,6 +3092,59 @@ export type InsightsBillingPath = z.infer<typeof InsightsBillingPath>;
|
|
|
2674
3092
|
export const InsightsPricingSource = z.enum(["configured_list_price", "gateway_reported"]);
|
|
2675
3093
|
export type InsightsPricingSource = z.infer<typeof InsightsPricingSource>;
|
|
2676
3094
|
|
|
3095
|
+
export const ModelContextContributionSource = z.enum([
|
|
3096
|
+
"workspace_instruction_policy",
|
|
3097
|
+
"legacy_workspace_instructions",
|
|
3098
|
+
"preference_registry_descriptor",
|
|
3099
|
+
"company_profile",
|
|
3100
|
+
"legacy_memory_v1",
|
|
3101
|
+
"runtime_skill_catalog",
|
|
3102
|
+
]);
|
|
3103
|
+
export type ModelContextContributionSource = z.infer<typeof ModelContextContributionSource>;
|
|
3104
|
+
|
|
3105
|
+
/** Content-free per-call summary of model-visible Company Brain material. */
|
|
3106
|
+
export const ModelContextContributionSummary = z
|
|
3107
|
+
.object({
|
|
3108
|
+
source: ModelContextContributionSource,
|
|
3109
|
+
items: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
|
|
3110
|
+
utf8Bytes: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
|
|
3111
|
+
estimatedTokens: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
|
|
3112
|
+
})
|
|
3113
|
+
.strict();
|
|
3114
|
+
export type ModelContextContributionSummary = z.infer<typeof ModelContextContributionSummary>;
|
|
3115
|
+
|
|
3116
|
+
export const ModelContextContributionSummaries = z
|
|
3117
|
+
.array(ModelContextContributionSummary)
|
|
3118
|
+
.max(6)
|
|
3119
|
+
.superRefine((summaries, context) => {
|
|
3120
|
+
const seen = new Set<ModelContextContributionSource>();
|
|
3121
|
+
for (const [index, summary] of summaries.entries()) {
|
|
3122
|
+
if (seen.has(summary.source)) {
|
|
3123
|
+
context.addIssue({
|
|
3124
|
+
code: "custom",
|
|
3125
|
+
message: "Model context contribution sources must be unique",
|
|
3126
|
+
path: [index, "source"],
|
|
3127
|
+
});
|
|
3128
|
+
}
|
|
3129
|
+
seen.add(summary.source);
|
|
3130
|
+
}
|
|
3131
|
+
});
|
|
3132
|
+
|
|
3133
|
+
export const InsightsPromptContributionRow = ModelContextContributionSummary.extend({
|
|
3134
|
+
calls: z.number().int().nonnegative(),
|
|
3135
|
+
});
|
|
3136
|
+
export type InsightsPromptContributionRow = z.infer<typeof InsightsPromptContributionRow>;
|
|
3137
|
+
|
|
3138
|
+
export const InsightsPromptContributions = z.object({
|
|
3139
|
+
/** Sum of UTF-8 byte / 4 estimates across calls with contribution receipts. */
|
|
3140
|
+
estimatedTokens: z.number().int().nonnegative(),
|
|
3141
|
+
utf8Bytes: z.number().int().nonnegative(),
|
|
3142
|
+
coveredCalls: z.number().int().nonnegative(),
|
|
3143
|
+
totalCalls: z.number().int().nonnegative(),
|
|
3144
|
+
sources: z.array(InsightsPromptContributionRow),
|
|
3145
|
+
});
|
|
3146
|
+
export type InsightsPromptContributions = z.infer<typeof InsightsPromptContributions>;
|
|
3147
|
+
|
|
2677
3148
|
export const InsightsModelUsageRow = z.object({
|
|
2678
3149
|
id: z.string().min(1),
|
|
2679
3150
|
model: z.string().min(1),
|
|
@@ -2840,6 +3311,13 @@ export const WorkspaceInsightsSnapshot = z.object({
|
|
|
2840
3311
|
drivers: z.array(InsightsSpendDriver),
|
|
2841
3312
|
schedules: z.array(InsightsScheduleRow),
|
|
2842
3313
|
recentCalls: z.array(InsightsModelCallRow),
|
|
3314
|
+
promptContributions: InsightsPromptContributions.default({
|
|
3315
|
+
estimatedTokens: 0,
|
|
3316
|
+
utf8Bytes: 0,
|
|
3317
|
+
coveredCalls: 0,
|
|
3318
|
+
totalCalls: 0,
|
|
3319
|
+
sources: [],
|
|
3320
|
+
}),
|
|
2843
3321
|
warmSeconds: z.number().nonnegative(),
|
|
2844
3322
|
priorWarmSeconds: z.number().nonnegative(),
|
|
2845
3323
|
warmGroups: z.array(InsightsWarmGroupRow),
|
|
@@ -2988,6 +3466,11 @@ export const GitCredentialRepositoryRef = z.object({
|
|
|
2988
3466
|
access: GitRepositoryAccess.optional(),
|
|
2989
3467
|
uri: z.string().min(1),
|
|
2990
3468
|
ref: z.string().min(1),
|
|
3469
|
+
/** Immutable commit the caller expects `ref` to materialize. */
|
|
3470
|
+
expectedCommitSha: z
|
|
3471
|
+
.string()
|
|
3472
|
+
.regex(/^[0-9a-f]{40}$/)
|
|
3473
|
+
.optional(),
|
|
2991
3474
|
repositoryId: GitProviderRepositoryId.optional(),
|
|
2992
3475
|
installationId: GitProviderRepositoryId.optional(),
|
|
2993
3476
|
projectId: GitProviderRepositoryId.optional(),
|
|
@@ -3112,9 +3595,25 @@ export type GitCredentials = {
|
|
|
3112
3595
|
export type SandboxSecretsRequest = {
|
|
3113
3596
|
accountId: string;
|
|
3114
3597
|
workspaceId: string;
|
|
3115
|
-
//
|
|
3116
|
-
//
|
|
3598
|
+
// Exact live attempt authority. Hosts MUST revalidate this tuple, the
|
|
3599
|
+
// session's selected resource identity, and any personal-resource grant
|
|
3600
|
+
// immediately before returning plaintext.
|
|
3601
|
+
sessionId: string;
|
|
3602
|
+
turnId: string;
|
|
3603
|
+
attemptId: string;
|
|
3604
|
+
executionGeneration: number;
|
|
3605
|
+
// Organization/workspace Variable Sets may be materialized by a pure
|
|
3606
|
+
// service turn (for example, the scheduler). Personal Variable Sets still
|
|
3607
|
+
// require this causal human and an exact personal-resource grant.
|
|
3608
|
+
initiator: TurnInitiator;
|
|
3609
|
+
initiatingHumanSubjectId: string | null;
|
|
3117
3610
|
variableSetId: string;
|
|
3611
|
+
/**
|
|
3612
|
+
* Exact accepted scheduled-occurrence generation. Present only for scheduled
|
|
3613
|
+
* attempts; ordinary live turns omit it, so hosts that predate this field keep
|
|
3614
|
+
* working unchanged for those.
|
|
3615
|
+
*/
|
|
3616
|
+
expectedGeneration?: number | null;
|
|
3118
3617
|
};
|
|
3119
3618
|
|
|
3120
3619
|
export type SandboxSecrets = {
|
|
@@ -3122,8 +3621,19 @@ export type SandboxSecrets = {
|
|
|
3122
3621
|
// `environmentsEncryptionKeyBytes` decrypt. Same shape the self-mint path
|
|
3123
3622
|
// produces (plaintext name→value).
|
|
3124
3623
|
values: Record<string, string>;
|
|
3125
|
-
//
|
|
3624
|
+
// Exact scope/resource echoes are mandatory so a host routing bug cannot
|
|
3625
|
+
// inject a sibling tenant, resource, or stale attempt's plaintext.
|
|
3626
|
+
accountId: string;
|
|
3126
3627
|
workspaceId: string;
|
|
3628
|
+
sessionId: string;
|
|
3629
|
+
turnId: string;
|
|
3630
|
+
attemptId: string;
|
|
3631
|
+
executionGeneration: number;
|
|
3632
|
+
variableSetId: string;
|
|
3633
|
+
/** Must echo the request's `expectedGeneration` when one was supplied. */
|
|
3634
|
+
expectedGeneration?: number | null;
|
|
3635
|
+
scope: VariableSetScope;
|
|
3636
|
+
generation: number;
|
|
3127
3637
|
// Optional variableSet metadata; when omitted the activity uses the
|
|
3128
3638
|
// variableSetId as both id and name (the local decrypt carries the row's
|
|
3129
3639
|
// id/name/description, but only `id` is load-bearing downstream).
|
|
@@ -3287,12 +3797,127 @@ export const McpPersonalConnectionDelegation = z
|
|
|
3287
3797
|
.object({
|
|
3288
3798
|
serverId: z.string().min(1).max(256),
|
|
3289
3799
|
connectionId: z.string().uuid(),
|
|
3800
|
+
/**
|
|
3801
|
+
* Immutable physical workspace that owns an activated common-user
|
|
3802
|
+
* connection. It is server-resolved from the selected authority and lets
|
|
3803
|
+
* provider adapters load only that exact row when the accepted turn runs
|
|
3804
|
+
* in another workspace of the same organization.
|
|
3805
|
+
*/
|
|
3806
|
+
originWorkspaceId: z.string().uuid().optional(),
|
|
3290
3807
|
ownerSubjectId: z.string().min(1).max(512),
|
|
3291
3808
|
providerDomain: z.string().min(1).max(2048),
|
|
3292
3809
|
kind: z.enum(["oauth2", "api_key", "app_install", "delegated"]).optional(),
|
|
3293
|
-
connectionType: z.enum(["mcp", "social", "atlassian"]).optional(),
|
|
3810
|
+
connectionType: z.enum(["mcp", "social", "atlassian", "github_personal"]).optional(),
|
|
3811
|
+
/**
|
|
3812
|
+
* Explicit common-authority grant selected by the owning human. Omission is
|
|
3813
|
+
* retained only for legacy_user connections that cannot yet participate in
|
|
3814
|
+
* the organization-user authority lifecycle.
|
|
3815
|
+
*/
|
|
3816
|
+
userDelegation: UserResourceDelegation.optional(),
|
|
3817
|
+
/**
|
|
3818
|
+
* Personal GitHub only: the exact repository authority frozen when this
|
|
3819
|
+
* accepted work was admitted. The credential binding is evidence, not an
|
|
3820
|
+
* authorization; physical provider use must revalidate every mutable
|
|
3821
|
+
* connection/grant/selection fence against this snapshot.
|
|
3822
|
+
*/
|
|
3823
|
+
personalGitHubRepositorySelection: z
|
|
3824
|
+
.object({
|
|
3825
|
+
credentialBindingId: z.string().uuid(),
|
|
3826
|
+
connectionAuthorityGeneration: z.number().int().positive(),
|
|
3827
|
+
selectionGeneration: z.number().int().positive(),
|
|
3828
|
+
repositories: z
|
|
3829
|
+
.array(
|
|
3830
|
+
z
|
|
3831
|
+
.object({
|
|
3832
|
+
repositoryId: z.string().regex(/^[1-9]\d*$/u),
|
|
3833
|
+
fullName: z.string().min(3).max(140),
|
|
3834
|
+
canonicalUrl: z.string().url().max(512),
|
|
3835
|
+
ref: z.string().min(1).max(255),
|
|
3836
|
+
access: GitRepositoryAccess,
|
|
3837
|
+
selectionGeneration: z.number().int().positive(),
|
|
3838
|
+
})
|
|
3839
|
+
.strict(),
|
|
3840
|
+
)
|
|
3841
|
+
.min(1)
|
|
3842
|
+
.max(100),
|
|
3843
|
+
})
|
|
3844
|
+
.strict()
|
|
3845
|
+
.optional(),
|
|
3846
|
+
/**
|
|
3847
|
+
* Google Drive publication only: the exact output destination frozen when
|
|
3848
|
+
* this delegation was accepted, so a later connection-settings change can
|
|
3849
|
+
* never redirect an already-accepted turn's publication. Structurally
|
|
3850
|
+
* mirrors GoogleDriveOutputDestination (defined in ./google-drive, which
|
|
3851
|
+
* imports this module - hence the inline shape). Absent on pre-freeze
|
|
3852
|
+
* turns, which keep the bounded legacy live-resolution behavior.
|
|
3853
|
+
*/
|
|
3854
|
+
outputDestination: z
|
|
3855
|
+
.object({
|
|
3856
|
+
folderId: z.string().min(1).max(256),
|
|
3857
|
+
folderName: z.string().min(1).max(1024),
|
|
3858
|
+
driveId: z.string().min(1).max(256).nullable(),
|
|
3859
|
+
location: z.enum(["my_drive", "shared_drive"]),
|
|
3860
|
+
selectedAt: z.string().datetime({ offset: true }),
|
|
3861
|
+
})
|
|
3862
|
+
.strict()
|
|
3863
|
+
.optional(),
|
|
3294
3864
|
})
|
|
3295
|
-
.strict()
|
|
3865
|
+
.strict()
|
|
3866
|
+
.superRefine((delegation, context) => {
|
|
3867
|
+
const personalGitHub = delegation.connectionType === "github_personal";
|
|
3868
|
+
if (personalGitHub !== (delegation.personalGitHubRepositorySelection !== undefined)) {
|
|
3869
|
+
context.addIssue({
|
|
3870
|
+
code: "custom",
|
|
3871
|
+
path: ["personalGitHubRepositorySelection"],
|
|
3872
|
+
message: "personal GitHub delegation requires one repository authority snapshot",
|
|
3873
|
+
});
|
|
3874
|
+
}
|
|
3875
|
+
if (!personalGitHub) return;
|
|
3876
|
+
if (
|
|
3877
|
+
delegation.serverId !== "github:personal" ||
|
|
3878
|
+
delegation.providerDomain !== "github.com" ||
|
|
3879
|
+
delegation.kind !== "oauth2" ||
|
|
3880
|
+
!delegation.originWorkspaceId ||
|
|
3881
|
+
!delegation.userDelegation
|
|
3882
|
+
) {
|
|
3883
|
+
context.addIssue({
|
|
3884
|
+
code: "custom",
|
|
3885
|
+
message: "personal GitHub delegation requires exact user-owned connection authority",
|
|
3886
|
+
});
|
|
3887
|
+
}
|
|
3888
|
+
const repositories = delegation.personalGitHubRepositorySelection?.repositories ?? [];
|
|
3889
|
+
const repositoryIds = new Set<string>();
|
|
3890
|
+
const canonicalUrls = new Set<string>();
|
|
3891
|
+
repositories.forEach((repository, index) => {
|
|
3892
|
+
const canonicalUrl = repository.canonicalUrl.toLowerCase();
|
|
3893
|
+
if (
|
|
3894
|
+
!/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9_.-]{1,100}$/u.test(repository.fullName) ||
|
|
3895
|
+
repository.canonicalUrl !== `https://github.com/${repository.fullName}`
|
|
3896
|
+
) {
|
|
3897
|
+
context.addIssue({
|
|
3898
|
+
code: "custom",
|
|
3899
|
+
path: ["personalGitHubRepositorySelection", "repositories", index, "canonicalUrl"],
|
|
3900
|
+
message: "personal GitHub repository identity must be canonical",
|
|
3901
|
+
});
|
|
3902
|
+
}
|
|
3903
|
+
if (repositoryIds.has(repository.repositoryId)) {
|
|
3904
|
+
context.addIssue({
|
|
3905
|
+
code: "custom",
|
|
3906
|
+
path: ["personalGitHubRepositorySelection", "repositories", index, "repositoryId"],
|
|
3907
|
+
message: "personal GitHub repositories must be unique by provider id",
|
|
3908
|
+
});
|
|
3909
|
+
}
|
|
3910
|
+
if (canonicalUrls.has(canonicalUrl)) {
|
|
3911
|
+
context.addIssue({
|
|
3912
|
+
code: "custom",
|
|
3913
|
+
path: ["personalGitHubRepositorySelection", "repositories", index, "canonicalUrl"],
|
|
3914
|
+
message: "personal GitHub repositories must be unique by canonical URL",
|
|
3915
|
+
});
|
|
3916
|
+
}
|
|
3917
|
+
repositoryIds.add(repository.repositoryId);
|
|
3918
|
+
canonicalUrls.add(canonicalUrl);
|
|
3919
|
+
});
|
|
3920
|
+
});
|
|
3296
3921
|
export type McpPersonalConnectionDelegation = z.infer<typeof McpPersonalConnectionDelegation>;
|
|
3297
3922
|
|
|
3298
3923
|
/**
|
|
@@ -3317,12 +3942,44 @@ export const McpPersonalConnectionDelegations = z
|
|
|
3317
3942
|
}
|
|
3318
3943
|
});
|
|
3319
3944
|
|
|
3320
|
-
export const McpPersonalConnectionSummary =
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3945
|
+
export const McpPersonalConnectionSummary = z
|
|
3946
|
+
.object({
|
|
3947
|
+
serverId: z.string().min(1).max(256),
|
|
3948
|
+
providerDomain: z.string().min(1).max(2048),
|
|
3949
|
+
})
|
|
3950
|
+
.strict();
|
|
3324
3951
|
export type McpPersonalConnectionSummary = z.infer<typeof McpPersonalConnectionSummary>;
|
|
3325
3952
|
|
|
3953
|
+
/**
|
|
3954
|
+
* Public, credential-free selection of one exact personal connection grant for
|
|
3955
|
+
* one selected MCP/first-party server. The owner is always derived server-side.
|
|
3956
|
+
*/
|
|
3957
|
+
export const McpConnectionAuthoritySelection = z
|
|
3958
|
+
.object({
|
|
3959
|
+
serverId: z.string().min(1).max(256),
|
|
3960
|
+
connectionId: z.string().uuid(),
|
|
3961
|
+
userDelegation: UserResourceDelegation,
|
|
3962
|
+
})
|
|
3963
|
+
.strict();
|
|
3964
|
+
export type McpConnectionAuthoritySelection = z.infer<typeof McpConnectionAuthoritySelection>;
|
|
3965
|
+
|
|
3966
|
+
export const McpConnectionAuthoritySelections = z
|
|
3967
|
+
.array(McpConnectionAuthoritySelection)
|
|
3968
|
+
.max(128)
|
|
3969
|
+
.superRefine((selections, context) => {
|
|
3970
|
+
const seen = new Set<string>();
|
|
3971
|
+
for (const [index, selection] of selections.entries()) {
|
|
3972
|
+
if (seen.has(selection.serverId)) {
|
|
3973
|
+
context.addIssue({
|
|
3974
|
+
code: "custom",
|
|
3975
|
+
message: "connection authority selections must be unique by serverId",
|
|
3976
|
+
path: [index, "serverId"],
|
|
3977
|
+
});
|
|
3978
|
+
}
|
|
3979
|
+
seen.add(selection.serverId);
|
|
3980
|
+
}
|
|
3981
|
+
});
|
|
3982
|
+
|
|
3326
3983
|
export type McpCredentialsRequest = {
|
|
3327
3984
|
accountId: string;
|
|
3328
3985
|
workspaceId: string;
|
|
@@ -3353,6 +4010,10 @@ export type McpCredentialsRequest = {
|
|
|
3353
4010
|
toolName?: string;
|
|
3354
4011
|
connectionRef: McpServerConnectionRef;
|
|
3355
4012
|
forceRefresh: boolean;
|
|
4013
|
+
/** Canonical credential-free authority frozen on the accepted turn. */
|
|
4014
|
+
connectionUseAuthority?: unknown;
|
|
4015
|
+
/** Stable idempotency key for this one physical provider request. */
|
|
4016
|
+
connectionUseRequestId?: string;
|
|
3356
4017
|
};
|
|
3357
4018
|
|
|
3358
4019
|
export type McpCredentialAuthNeededReason =
|
|
@@ -3551,13 +4212,35 @@ export const CreateCheckoutResponse = z.object({
|
|
|
3551
4212
|
});
|
|
3552
4213
|
export type CreateCheckoutResponse = z.infer<typeof CreateCheckoutResponse>;
|
|
3553
4214
|
|
|
4215
|
+
export const CreateBillingPortalRequest = z.object({
|
|
4216
|
+
accountId: z.string().uuid().optional(),
|
|
4217
|
+
returnUrl: z.string().url().optional(),
|
|
4218
|
+
});
|
|
4219
|
+
export type CreateBillingPortalRequest = z.infer<typeof CreateBillingPortalRequest>;
|
|
4220
|
+
|
|
4221
|
+
export const CreateBillingPortalResponse = z.object({
|
|
4222
|
+
portalSessionId: z.string(),
|
|
4223
|
+
url: z.string().url(),
|
|
4224
|
+
});
|
|
4225
|
+
export type CreateBillingPortalResponse = z.infer<typeof CreateBillingPortalResponse>;
|
|
4226
|
+
|
|
3554
4227
|
export const RepositoryResourceRef = z.object({
|
|
3555
4228
|
kind: z.literal("repository"),
|
|
3556
4229
|
uri: z.string().min(1),
|
|
3557
4230
|
ref: z.string().min(1),
|
|
4231
|
+
/**
|
|
4232
|
+
* Optional immutable Git object fence. Repository materialization must fail
|
|
4233
|
+
* when the checked-out HEAD is not this exact commit. Event-driven sessions
|
|
4234
|
+
* use it to prevent a mutable PR branch from changing underneath a review.
|
|
4235
|
+
*/
|
|
4236
|
+
expectedCommitSha: z
|
|
4237
|
+
.string()
|
|
4238
|
+
.regex(/^[0-9a-f]{40}$/)
|
|
4239
|
+
.optional(),
|
|
3558
4240
|
mountPath: z.string().min(1).optional(),
|
|
3559
4241
|
subpath: z.string().min(1).optional(),
|
|
3560
4242
|
provider: GitCredentialProvider.optional(),
|
|
4243
|
+
connectionType: z.literal("github_personal").optional(),
|
|
3561
4244
|
credentialBindingId: GitCredentialBindingId.optional(),
|
|
3562
4245
|
access: GitRepositoryAccess.optional(),
|
|
3563
4246
|
repositoryId: GitProviderRepositoryId.optional(),
|
|
@@ -3717,6 +4400,8 @@ export type FileResourceRef = z.infer<typeof FileResourceRef>;
|
|
|
3717
4400
|
* reconstruct the same typed attachment input after a model switch or retry.
|
|
3718
4401
|
*/
|
|
3719
4402
|
export const MODEL_ATTACHMENT_REFS_FIELD = "opengeni_attachment_refs" as const;
|
|
4403
|
+
/** Private marker for the compact attachment-reference carrier created by compaction. */
|
|
4404
|
+
export const MODEL_ATTACHMENT_CATALOG_MARKER = "opengeni_attachment_catalog" as const;
|
|
3720
4405
|
/**
|
|
3721
4406
|
* Structured timeline annotations retained beside the deterministic user-text
|
|
3722
4407
|
* projection in canonical history. Provider adapters remove this OpenGeni
|
|
@@ -3816,6 +4501,25 @@ export function defaultRepositoryMountPath(
|
|
|
3816
4501
|
);
|
|
3817
4502
|
}
|
|
3818
4503
|
|
|
4504
|
+
/** Durable SDK/UI artifact root. Provisioned boxes also mount this path;
|
|
4505
|
+
* Connected Machine execution does not treat it as an alias. */
|
|
4506
|
+
export const VIRTUAL_WORKSPACE_ROOT = "/workspace" as const;
|
|
4507
|
+
|
|
4508
|
+
/**
|
|
4509
|
+
* Cwd-relative path for shell/exec prompts. Durable receipts and `sandbox:` UI
|
|
4510
|
+
* links keep the durable `/workspace/...` form. Tool receipts use the relative
|
|
4511
|
+
* projection so they remain usable from either a provisioned box root or a
|
|
4512
|
+
* Connected Machine's truthful host-native cwd.
|
|
4513
|
+
*/
|
|
4514
|
+
export function sandboxShellPath(virtualPath: string): string {
|
|
4515
|
+
if (virtualPath === VIRTUAL_WORKSPACE_ROOT) return ".";
|
|
4516
|
+
if (virtualPath.startsWith(`${VIRTUAL_WORKSPACE_ROOT}/`)) {
|
|
4517
|
+
const relative = virtualPath.slice(VIRTUAL_WORKSPACE_ROOT.length + 1);
|
|
4518
|
+
return relative.length > 0 ? relative : ".";
|
|
4519
|
+
}
|
|
4520
|
+
return virtualPath;
|
|
4521
|
+
}
|
|
4522
|
+
|
|
3819
4523
|
/** Resolve the exact mount used by API normalization, manifests, and clone hooks. */
|
|
3820
4524
|
export const DEFAULT_FILE_RESOURCE_MOUNT_ROOT = ".opengeni/files" as const;
|
|
3821
4525
|
|
|
@@ -3984,6 +4688,9 @@ export const Document = z.object({
|
|
|
3984
4688
|
authorityKind: DocumentAuthorityKind,
|
|
3985
4689
|
authorityWorkspaceId: z.string().uuid().nullable(),
|
|
3986
4690
|
authoritySubjectId: z.string().nullable(),
|
|
4691
|
+
// Opaque handle used by the owning human to issue explicit personal-scope
|
|
4692
|
+
// grants. Organization/workspace and legacy anchored personal rows are null.
|
|
4693
|
+
authorityId: z.string().uuid().nullable().optional(),
|
|
3987
4694
|
visibility: DocumentVisibility,
|
|
3988
4695
|
createdBy: z.string().nullable(),
|
|
3989
4696
|
agentAccess: z.boolean(),
|
|
@@ -4025,6 +4732,7 @@ export const DocumentSearchResult = z.object({
|
|
|
4025
4732
|
authorityKind: DocumentAuthorityKind,
|
|
4026
4733
|
authorityWorkspaceId: z.string().uuid().nullable(),
|
|
4027
4734
|
authoritySubjectId: z.string().nullable(),
|
|
4735
|
+
citation: KnowledgeProviderCitation.nullable().optional(),
|
|
4028
4736
|
});
|
|
4029
4737
|
export type DocumentSearchResult = z.infer<typeof DocumentSearchResult>;
|
|
4030
4738
|
|
|
@@ -4054,6 +4762,7 @@ export const IndexedDocumentProvenance = z.object({
|
|
|
4054
4762
|
authoritySubjectId: z.string().nullable(),
|
|
4055
4763
|
createdBy: z.string().nullable(),
|
|
4056
4764
|
createdAt: z.string(),
|
|
4765
|
+
citation: KnowledgeProviderCitation.nullable().optional(),
|
|
4057
4766
|
});
|
|
4058
4767
|
export type IndexedDocumentProvenance = z.infer<typeof IndexedDocumentProvenance>;
|
|
4059
4768
|
|
|
@@ -4134,6 +4843,77 @@ export const MoveDocumentRequest = z.object({
|
|
|
4134
4843
|
});
|
|
4135
4844
|
export type MoveDocumentRequest = z.infer<typeof MoveDocumentRequest>;
|
|
4136
4845
|
|
|
4846
|
+
export const DocumentAuthorityTuple = z.object({
|
|
4847
|
+
kind: DocumentAuthorityKind,
|
|
4848
|
+
workspaceId: z.string().uuid().nullable(),
|
|
4849
|
+
subjectId: z.string().nullable(),
|
|
4850
|
+
authorityId: z.string().uuid().nullable(),
|
|
4851
|
+
});
|
|
4852
|
+
export type DocumentAuthorityTuple = z.infer<typeof DocumentAuthorityTuple>;
|
|
4853
|
+
|
|
4854
|
+
export const ReclassifyDocumentAuthorityRequest = z.object({
|
|
4855
|
+
operationId: z.string().uuid(),
|
|
4856
|
+
expectedAuthority: DocumentAuthorityTuple,
|
|
4857
|
+
targetAuthorityKind: DocumentAuthorityKind,
|
|
4858
|
+
});
|
|
4859
|
+
export type ReclassifyDocumentAuthorityRequest = z.infer<typeof ReclassifyDocumentAuthorityRequest>;
|
|
4860
|
+
|
|
4861
|
+
export const DocumentAuthorityReclassification = z.object({
|
|
4862
|
+
operationId: z.string().uuid(),
|
|
4863
|
+
documentId: z.string().uuid(),
|
|
4864
|
+
previousAuthority: DocumentAuthorityTuple,
|
|
4865
|
+
authority: DocumentAuthorityTuple,
|
|
4866
|
+
createdAt: z.string().datetime({ offset: true }),
|
|
4867
|
+
});
|
|
4868
|
+
export type DocumentAuthorityReclassification = z.infer<typeof DocumentAuthorityReclassification>;
|
|
4869
|
+
|
|
4870
|
+
export const DOCUMENT_AUTHORITY_RECLASSIFICATION_LIST_DEFAULT_LIMIT = 50;
|
|
4871
|
+
export const DOCUMENT_AUTHORITY_RECLASSIFICATION_LIST_MAX_LIMIT = 100;
|
|
4872
|
+
export const DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS = 1_024;
|
|
4873
|
+
|
|
4874
|
+
export const ListDocumentAuthorityReclassificationsQuery = z.object({
|
|
4875
|
+
limit: z.coerce
|
|
4876
|
+
.number()
|
|
4877
|
+
.int()
|
|
4878
|
+
.positive()
|
|
4879
|
+
.max(DOCUMENT_AUTHORITY_RECLASSIFICATION_LIST_MAX_LIMIT)
|
|
4880
|
+
.default(DOCUMENT_AUTHORITY_RECLASSIFICATION_LIST_DEFAULT_LIMIT),
|
|
4881
|
+
cursor: z.string().min(1).max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS).optional(),
|
|
4882
|
+
});
|
|
4883
|
+
export type ListDocumentAuthorityReclassificationsQuery = z.infer<
|
|
4884
|
+
typeof ListDocumentAuthorityReclassificationsQuery
|
|
4885
|
+
>;
|
|
4886
|
+
|
|
4887
|
+
export const ListDocumentAuthorityReclassificationsResponse = z.object({
|
|
4888
|
+
receipts: z.array(DocumentAuthorityReclassification),
|
|
4889
|
+
hasMore: z.boolean(),
|
|
4890
|
+
nextCursor: z.string().max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS).nullable(),
|
|
4891
|
+
});
|
|
4892
|
+
export type ListDocumentAuthorityReclassificationsResponse = z.infer<
|
|
4893
|
+
typeof ListDocumentAuthorityReclassificationsResponse
|
|
4894
|
+
>;
|
|
4895
|
+
|
|
4896
|
+
export const RunDocumentDefaultCollectionBackfillRequest = z.object({
|
|
4897
|
+
runId: z.string().uuid(),
|
|
4898
|
+
operationId: z.string().uuid(),
|
|
4899
|
+
batchSize: z.number().int().min(1).max(100).default(50),
|
|
4900
|
+
});
|
|
4901
|
+
export type RunDocumentDefaultCollectionBackfillRequest = z.infer<
|
|
4902
|
+
typeof RunDocumentDefaultCollectionBackfillRequest
|
|
4903
|
+
>;
|
|
4904
|
+
|
|
4905
|
+
export const DocumentDefaultCollectionBackfill = z.object({
|
|
4906
|
+
runId: z.string().uuid(),
|
|
4907
|
+
operationId: z.string().uuid(),
|
|
4908
|
+
status: z.enum(["running", "completed"]),
|
|
4909
|
+
lastWorkspaceId: z.string().uuid().nullable(),
|
|
4910
|
+
processedCount: z.number().int().nonnegative(),
|
|
4911
|
+
createdCount: z.number().int().nonnegative(),
|
|
4912
|
+
adoptedCount: z.number().int().nonnegative(),
|
|
4913
|
+
completedAt: z.string().datetime({ offset: true }).nullable(),
|
|
4914
|
+
});
|
|
4915
|
+
export type DocumentDefaultCollectionBackfill = z.infer<typeof DocumentDefaultCollectionBackfill>;
|
|
4916
|
+
|
|
4137
4917
|
export const DocumentSearchRequest = z.object({
|
|
4138
4918
|
query: z.string().min(1),
|
|
4139
4919
|
baseIds: z.array(z.string().uuid()).optional(),
|
|
@@ -4279,9 +5059,15 @@ export type WorkspaceMemorySearchResponse = z.infer<typeof WorkspaceMemorySearch
|
|
|
4279
5059
|
export const ToolRef = z.object({
|
|
4280
5060
|
kind: z.literal("mcp"),
|
|
4281
5061
|
id: z.string().min(1),
|
|
5062
|
+
// Session-scoped startup choice. `true` prepares this server's authorized
|
|
5063
|
+
// schemas before the first model request; absent/false keeps it behind
|
|
5064
|
+
// progressive discovery. This never grants a server or tool permission.
|
|
5065
|
+
eager: z.boolean().optional(),
|
|
4282
5066
|
// Non-fatal-on-connect marker for MCP server refs that can degrade
|
|
4283
5067
|
// gracefully. On new input, absent/false is STRICT: the id must be configured
|
|
4284
|
-
// and an unavailable registered server fails
|
|
5068
|
+
// and an unavailable registered server fails closed when its preparation is
|
|
5069
|
+
// demanded. Only the independent eager marker makes that a startup failure.
|
|
5070
|
+
// Persisted refs are
|
|
4285
5071
|
// intersected with the current registry at each turn boundary, so a server
|
|
4286
5072
|
// disconnected after admission is retained in policy/audit truth but skipped
|
|
4287
5073
|
// until it is registered again. `optional:true` additionally makes runtime
|
|
@@ -4478,10 +5264,14 @@ export function mergeToolRefs(existing: ToolRef[], additions: ToolRef[]): ToolRe
|
|
|
4478
5264
|
// strict occurrence upgrades the merged ref so an unavailable server fails
|
|
4479
5265
|
// the turn. This preserves the fail-loud default when defaults, packs, and
|
|
4480
5266
|
// per-turn tool selections are combined.
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
5267
|
+
const optional = prior.optional === true && tool.optional === true ? true : undefined;
|
|
5268
|
+
const eager = prior.eager === true || tool.eager === true ? true : undefined;
|
|
5269
|
+
byKey.set(key, {
|
|
5270
|
+
kind: "mcp",
|
|
5271
|
+
id: prior.id,
|
|
5272
|
+
...(optional ? { optional } : {}),
|
|
5273
|
+
...(eager ? { eager } : {}),
|
|
5274
|
+
});
|
|
4485
5275
|
}
|
|
4486
5276
|
return order.map((key) => byKey.get(key)!);
|
|
4487
5277
|
}
|
|
@@ -4635,6 +5425,9 @@ export const SESSION_GOAL_TEXT_MAX_BYTES = 8 * 1024;
|
|
|
4635
5425
|
export const SESSION_GOAL_SUCCESS_CRITERIA_MAX_BYTES = 8 * 1024;
|
|
4636
5426
|
export const SESSION_GOAL_RATIONALE_MAX_BYTES = 2 * 1024;
|
|
4637
5427
|
export const SESSION_GOAL_PROGRESS_MAX_BYTES = 4 * 1024;
|
|
5428
|
+
export const SESSION_GOAL_ROOT_CONSTRAINT_MAX_BYTES = 512;
|
|
5429
|
+
export const SESSION_GOAL_ROOT_CONSTRAINTS_MAX_BYTES = 4 * 1024;
|
|
5430
|
+
export const SESSION_GOAL_ROOT_CONSTRAINTS_MAX_ITEMS = 16;
|
|
4638
5431
|
|
|
4639
5432
|
export function sessionGoalUtf8Bytes(value: string): number {
|
|
4640
5433
|
return new TextEncoder().encode(value).byteLength;
|
|
@@ -4649,6 +5442,43 @@ function boundedSessionGoalString(maxBytes: number, field: string) {
|
|
|
4649
5442
|
});
|
|
4650
5443
|
}
|
|
4651
5444
|
|
|
5445
|
+
function compareUtf8(left: string, right: string): number {
|
|
5446
|
+
const encoder = new TextEncoder();
|
|
5447
|
+
const leftBytes = encoder.encode(left);
|
|
5448
|
+
const rightBytes = encoder.encode(right);
|
|
5449
|
+
const length = Math.min(leftBytes.length, rightBytes.length);
|
|
5450
|
+
for (let index = 0; index < length; index += 1) {
|
|
5451
|
+
const difference = leftBytes[index]! - rightBytes[index]!;
|
|
5452
|
+
if (difference !== 0) return difference;
|
|
5453
|
+
}
|
|
5454
|
+
return leftBytes.length - rightBytes.length;
|
|
5455
|
+
}
|
|
5456
|
+
|
|
5457
|
+
export function normalizeSessionGoalRootConstraints(values: readonly string[]): string[] {
|
|
5458
|
+
// PostgreSQL btrim(text) removes U+0020 at both ends. Keep the public
|
|
5459
|
+
// projector byte-equivalent with the storage trigger instead of using
|
|
5460
|
+
// JavaScript trim(), whose Unicode whitespace set is broader.
|
|
5461
|
+
return [...new Set(values.map((value) => value.replace(/^ +| +$/g, "")))].sort(compareUtf8);
|
|
5462
|
+
}
|
|
5463
|
+
|
|
5464
|
+
export const SessionGoalRootConstraintsWrite = z
|
|
5465
|
+
.array(boundedSessionGoalString(SESSION_GOAL_ROOT_CONSTRAINT_MAX_BYTES, "goal root constraint"))
|
|
5466
|
+
.transform(normalizeSessionGoalRootConstraints)
|
|
5467
|
+
.pipe(
|
|
5468
|
+
z
|
|
5469
|
+
.array(z.string().min(1))
|
|
5470
|
+
.max(SESSION_GOAL_ROOT_CONSTRAINTS_MAX_ITEMS)
|
|
5471
|
+
.refine(
|
|
5472
|
+
(values) =>
|
|
5473
|
+
values.reduce((total, value) => total + sessionGoalUtf8Bytes(value), 0) <=
|
|
5474
|
+
SESSION_GOAL_ROOT_CONSTRAINTS_MAX_BYTES,
|
|
5475
|
+
{
|
|
5476
|
+
message: `goal root constraints exceed ${SESSION_GOAL_ROOT_CONSTRAINTS_MAX_BYTES} aggregate UTF-8 bytes`,
|
|
5477
|
+
},
|
|
5478
|
+
),
|
|
5479
|
+
);
|
|
5480
|
+
export type SessionGoalRootConstraintsWrite = z.infer<typeof SessionGoalRootConstraintsWrite>;
|
|
5481
|
+
|
|
4652
5482
|
const SessionGoalTextWrite = boundedSessionGoalString(SESSION_GOAL_TEXT_MAX_BYTES, "goal text");
|
|
4653
5483
|
const SessionGoalSuccessCriteriaWrite = boundedSessionGoalString(
|
|
4654
5484
|
SESSION_GOAL_SUCCESS_CRITERIA_MAX_BYTES,
|
|
@@ -4667,6 +5497,7 @@ export const SessionGoalSnapshot = z.discriminatedUnion("state", [
|
|
|
4667
5497
|
objectiveRevision: z.number().int().positive(),
|
|
4668
5498
|
text: SessionGoalTextWrite,
|
|
4669
5499
|
successCriteria: SessionGoalSuccessCriteriaWrite.nullable(),
|
|
5500
|
+
rootConstraints: SessionGoalRootConstraintsWrite.default([]),
|
|
4670
5501
|
mutationPolicy: SessionGoalMutationPolicy,
|
|
4671
5502
|
capturedAt: z.string(),
|
|
4672
5503
|
}),
|
|
@@ -4685,22 +5516,57 @@ export const SessionGoalRevision = z.object({
|
|
|
4685
5516
|
resultObjectiveRevision: z.number().int().positive().nullable(),
|
|
4686
5517
|
text: z.string().min(1),
|
|
4687
5518
|
successCriteria: z.string().nullable(),
|
|
5519
|
+
rootConstraints: z.array(z.string().min(1)).default([]),
|
|
4688
5520
|
mutationPolicy: SessionGoalMutationPolicy,
|
|
4689
5521
|
rationale: z.string().min(1),
|
|
4690
5522
|
actor: z.enum(["agent", "api", "scheduled_task"]),
|
|
4691
5523
|
actorTurnId: z.string().uuid().nullable(),
|
|
4692
5524
|
actorAttemptId: z.string().uuid().nullable(),
|
|
4693
5525
|
proposalId: z.string().uuid().nullable(),
|
|
5526
|
+
rollbackOfRevisionId: z.string().uuid().nullable(),
|
|
4694
5527
|
createdAt: z.string(),
|
|
4695
5528
|
});
|
|
4696
5529
|
export type SessionGoalRevision = z.infer<typeof SessionGoalRevision>;
|
|
4697
5530
|
|
|
5531
|
+
export const SESSION_GOAL_REVISION_LIST_DEFAULT_LIMIT = 50;
|
|
5532
|
+
export const SESSION_GOAL_REVISION_LIST_MAX_LIMIT = 100;
|
|
5533
|
+
|
|
5534
|
+
export const ListSessionGoalRevisionsQuery = z.object({
|
|
5535
|
+
limit: z.coerce
|
|
5536
|
+
.number()
|
|
5537
|
+
.int()
|
|
5538
|
+
.positive()
|
|
5539
|
+
.max(SESSION_GOAL_REVISION_LIST_MAX_LIMIT)
|
|
5540
|
+
.default(SESSION_GOAL_REVISION_LIST_DEFAULT_LIMIT),
|
|
5541
|
+
before: z.string().uuid().optional(),
|
|
5542
|
+
});
|
|
5543
|
+
export type ListSessionGoalRevisionsQuery = z.infer<typeof ListSessionGoalRevisionsQuery>;
|
|
5544
|
+
|
|
5545
|
+
export const ListSessionGoalRevisionsResponse = z.object({
|
|
5546
|
+
revisions: z.array(SessionGoalRevision),
|
|
5547
|
+
hasMore: z.boolean(),
|
|
5548
|
+
nextCursor: z.string().uuid().nullable(),
|
|
5549
|
+
});
|
|
5550
|
+
export type ListSessionGoalRevisionsResponse = z.infer<typeof ListSessionGoalRevisionsResponse>;
|
|
5551
|
+
|
|
4698
5552
|
export const ApplySessionGoalRevisionRequest = z.object({
|
|
4699
5553
|
expectedObjectiveRevision: z.number().int().positive(),
|
|
4700
5554
|
rationale: SessionGoalRationaleWrite.optional(),
|
|
4701
5555
|
});
|
|
4702
5556
|
export type ApplySessionGoalRevisionRequest = z.infer<typeof ApplySessionGoalRevisionRequest>;
|
|
4703
5557
|
|
|
5558
|
+
export const RejectSessionGoalRevisionRequest = z.object({
|
|
5559
|
+
expectedObjectiveRevision: z.number().int().positive(),
|
|
5560
|
+
rationale: SessionGoalRationaleWrite,
|
|
5561
|
+
});
|
|
5562
|
+
export type RejectSessionGoalRevisionRequest = z.infer<typeof RejectSessionGoalRevisionRequest>;
|
|
5563
|
+
|
|
5564
|
+
export const RollbackSessionGoalRevisionRequest = z.object({
|
|
5565
|
+
expectedObjectiveRevision: z.number().int().positive(),
|
|
5566
|
+
rationale: SessionGoalRationaleWrite,
|
|
5567
|
+
});
|
|
5568
|
+
export type RollbackSessionGoalRevisionRequest = z.infer<typeof RollbackSessionGoalRevisionRequest>;
|
|
5569
|
+
|
|
4704
5570
|
export const SessionGoalPausedReason = z.enum([
|
|
4705
5571
|
"agent",
|
|
4706
5572
|
"user_pause",
|
|
@@ -4732,10 +5598,41 @@ export const SessionGoalContinuationReason = z.enum([
|
|
|
4732
5598
|
"provider_backpressure",
|
|
4733
5599
|
"session_cancelled",
|
|
4734
5600
|
"system_work_pending",
|
|
5601
|
+
"held_for_input",
|
|
5602
|
+
// Idle backoff: consecutive no-input continuations are paced, and the next
|
|
5603
|
+
// evaluation is armed as a delayed workflow wake at `nextAttemptAt`.
|
|
5604
|
+
"backoff_pending",
|
|
4735
5605
|
"missing_obligation",
|
|
4736
5606
|
]);
|
|
4737
5607
|
export type SessionGoalContinuationReason = z.infer<typeof SessionGoalContinuationReason>;
|
|
4738
5608
|
|
|
5609
|
+
/**
|
|
5610
|
+
* Why a paused goal became active again. `api` is the operator PATCH; the
|
|
5611
|
+
* system resumes only a `max_auto_continuations` pause, and only because new
|
|
5612
|
+
* external input arrived: a child result, scheduled occurrence, media result,
|
|
5613
|
+
* Agent message, Agent Steer, or human/API Send/Steer. The cap is pacing,
|
|
5614
|
+
* never user intent, so a `user_pause`/`api`/`agent`/`limits` pause is never
|
|
5615
|
+
* auto-resumed.
|
|
5616
|
+
*/
|
|
5617
|
+
export const SessionGoalResumedReason = z.enum(["api", "external_input"]);
|
|
5618
|
+
export type SessionGoalResumedReason = z.infer<typeof SessionGoalResumedReason>;
|
|
5619
|
+
|
|
5620
|
+
export const SessionGoalResumedEventPayload = z
|
|
5621
|
+
.object({
|
|
5622
|
+
goalId: z.string().uuid(),
|
|
5623
|
+
actor: z.enum(["api", "system"]),
|
|
5624
|
+
reason: SessionGoalResumedReason,
|
|
5625
|
+
cause: z
|
|
5626
|
+
.object({
|
|
5627
|
+
kind: z.string().min(1),
|
|
5628
|
+
updateId: z.string().uuid().optional(),
|
|
5629
|
+
turnId: z.string().uuid().optional(),
|
|
5630
|
+
})
|
|
5631
|
+
.optional(),
|
|
5632
|
+
})
|
|
5633
|
+
.passthrough();
|
|
5634
|
+
export type SessionGoalResumedEventPayload = z.infer<typeof SessionGoalResumedEventPayload>;
|
|
5635
|
+
|
|
4739
5636
|
export const SessionGoalContinuation = z.object({
|
|
4740
5637
|
state: SessionGoalContinuationState,
|
|
4741
5638
|
reason: SessionGoalContinuationReason,
|
|
@@ -4743,6 +5640,12 @@ export const SessionGoalContinuation = z.object({
|
|
|
4743
5640
|
observedRevision: z.number().int().nonnegative(),
|
|
4744
5641
|
nextAttemptAt: z.string().datetime({ offset: true }).nullable(),
|
|
4745
5642
|
lastError: z.string().nullable(),
|
|
5643
|
+
/**
|
|
5644
|
+
* The agent's stated reason for a `held_for_input` hold (`goal_wait`), so a
|
|
5645
|
+
* human can see why the goal is waiting and until when (`nextAttemptAt`).
|
|
5646
|
+
* Null for every other state; omitted by older servers.
|
|
5647
|
+
*/
|
|
5648
|
+
holdReason: z.string().nullable().optional(),
|
|
4746
5649
|
});
|
|
4747
5650
|
export type SessionGoalContinuation = z.infer<typeof SessionGoalContinuation>;
|
|
4748
5651
|
|
|
@@ -4754,6 +5657,7 @@ export const SessionGoal = z.object({
|
|
|
4754
5657
|
status: SessionGoalStatus,
|
|
4755
5658
|
text: z.string(),
|
|
4756
5659
|
successCriteria: z.string().nullable(),
|
|
5660
|
+
rootConstraints: z.array(z.string().min(1)).default([]),
|
|
4757
5661
|
evidence: z.string().nullable(),
|
|
4758
5662
|
rationale: z.string().nullable(),
|
|
4759
5663
|
pausedReason: z.string().nullable(),
|
|
@@ -4776,6 +5680,7 @@ export type SessionGoal = z.infer<typeof SessionGoal>;
|
|
|
4776
5680
|
export const GoalSpec = z.object({
|
|
4777
5681
|
text: SessionGoalTextWrite,
|
|
4778
5682
|
successCriteria: SessionGoalSuccessCriteriaWrite.optional(),
|
|
5683
|
+
rootConstraints: SessionGoalRootConstraintsWrite.optional(),
|
|
4779
5684
|
maxAutoContinuations: z.number().int().positive().optional(),
|
|
4780
5685
|
mutationPolicy: SessionGoalMutationPolicy.optional(),
|
|
4781
5686
|
});
|
|
@@ -4789,6 +5694,7 @@ export const UpdateSessionGoalRequest = z.union([
|
|
|
4789
5694
|
z.object({
|
|
4790
5695
|
text: SessionGoalTextWrite,
|
|
4791
5696
|
successCriteria: SessionGoalSuccessCriteriaWrite.nullable().optional(),
|
|
5697
|
+
rootConstraints: SessionGoalRootConstraintsWrite.optional(),
|
|
4792
5698
|
mutationPolicy: SessionGoalMutationPolicy.optional(),
|
|
4793
5699
|
rationale: SessionGoalRationaleWrite,
|
|
4794
5700
|
expectedObjectiveRevision: z.number().int().positive(),
|
|
@@ -4836,6 +5742,40 @@ export const UpdateSessionPinRequest = z.object({
|
|
|
4836
5742
|
});
|
|
4837
5743
|
export type UpdateSessionPinRequest = z.infer<typeof UpdateSessionPinRequest>;
|
|
4838
5744
|
|
|
5745
|
+
/**
|
|
5746
|
+
* A member's durable follow-up state for one session. Reading the session does
|
|
5747
|
+
* not acknowledge it: `unread` changes only through this explicit mutation.
|
|
5748
|
+
* A foreground reader may provide `acknowledgedThroughSequence` with
|
|
5749
|
+
* `unread: false` so later server events remain unread instead of being
|
|
5750
|
+
* consumed by a delayed acknowledgement request.
|
|
5751
|
+
* `activelyWorking` is an independent personal label that survives read state.
|
|
5752
|
+
*/
|
|
5753
|
+
export const UpdateSessionAttentionRequest = z
|
|
5754
|
+
.object({
|
|
5755
|
+
unread: z.boolean().optional(),
|
|
5756
|
+
acknowledgedThroughSequence: z.number().int().nonnegative().optional(),
|
|
5757
|
+
activelyWorking: z.boolean().optional(),
|
|
5758
|
+
expectedVersion: z.number().int().nonnegative().optional(),
|
|
5759
|
+
})
|
|
5760
|
+
.strict()
|
|
5761
|
+
.refine((value) => value.unread !== undefined || value.activelyWorking !== undefined, {
|
|
5762
|
+
message: "unread or activelyWorking is required",
|
|
5763
|
+
})
|
|
5764
|
+
.refine((value) => value.acknowledgedThroughSequence === undefined || value.unread === false, {
|
|
5765
|
+
message: "acknowledgedThroughSequence requires unread false",
|
|
5766
|
+
path: ["acknowledgedThroughSequence"],
|
|
5767
|
+
});
|
|
5768
|
+
export type UpdateSessionAttentionRequest = z.infer<typeof UpdateSessionAttentionRequest>;
|
|
5769
|
+
|
|
5770
|
+
/** A member's personal archive state for a root chat. */
|
|
5771
|
+
export const UpdateSessionArchiveRequest = z
|
|
5772
|
+
.object({
|
|
5773
|
+
archived: z.boolean(),
|
|
5774
|
+
expectedVersion: z.number().int().nonnegative().optional(),
|
|
5775
|
+
})
|
|
5776
|
+
.strict();
|
|
5777
|
+
export type UpdateSessionArchiveRequest = z.infer<typeof UpdateSessionArchiveRequest>;
|
|
5778
|
+
|
|
4839
5779
|
// Operator context controls (slash-command palette: /clear, /compact). These
|
|
4840
5780
|
// are session/operator actions, NOT a structured way to talk to the agent —
|
|
4841
5781
|
// the human↔agent channel stays plain chat. Both require `sessions:control`.
|
|
@@ -4890,6 +5830,34 @@ export function isClearedRunStateBlob(serialized: string | null | undefined): bo
|
|
|
4890
5830
|
}
|
|
4891
5831
|
}
|
|
4892
5832
|
|
|
5833
|
+
/**
|
|
5834
|
+
* Sentinel written on a requires_action pause. Resume must not call
|
|
5835
|
+
* `RunState.fromString` on it; the open suffix on `session_pending_tool_calls`
|
|
5836
|
+
* plus paired history is the resume authority.
|
|
5837
|
+
*/
|
|
5838
|
+
export const OPEN_SUFFIX_RUN_STATE_MARKER = "$opengeniOpenSuffix" as const;
|
|
5839
|
+
|
|
5840
|
+
/** Canonical sentinel serializedRunState for a requires_action pause. */
|
|
5841
|
+
export const OPEN_SUFFIX_RUN_STATE_BLOB = JSON.stringify({
|
|
5842
|
+
[OPEN_SUFFIX_RUN_STATE_MARKER]: true,
|
|
5843
|
+
});
|
|
5844
|
+
|
|
5845
|
+
export function isOpenSuffixRunStateBlob(serialized: string | null | undefined): boolean {
|
|
5846
|
+
if (!serialized) {
|
|
5847
|
+
return false;
|
|
5848
|
+
}
|
|
5849
|
+
try {
|
|
5850
|
+
const parsed = JSON.parse(serialized) as unknown;
|
|
5851
|
+
return (
|
|
5852
|
+
typeof parsed === "object" &&
|
|
5853
|
+
parsed !== null &&
|
|
5854
|
+
(parsed as Record<string, unknown>)[OPEN_SUFFIX_RUN_STATE_MARKER] === true
|
|
5855
|
+
);
|
|
5856
|
+
} catch {
|
|
5857
|
+
return false;
|
|
5858
|
+
}
|
|
5859
|
+
}
|
|
5860
|
+
|
|
4893
5861
|
/** Trigger conversation compaction now. No body fields today (forward-room). */
|
|
4894
5862
|
export const CompactSessionContextRequest = z.object({}).strict();
|
|
4895
5863
|
export type CompactSessionContextRequest = z.infer<typeof CompactSessionContextRequest>;
|
|
@@ -5089,8 +6057,26 @@ export const SessionRealtimeInboundEntry = z
|
|
|
5089
6057
|
delegationItemId: z.string().max(1024).nullable().optional(),
|
|
5090
6058
|
text: z.string().max(131_072).nullable().optional(),
|
|
5091
6059
|
payload: z.record(z.string(), z.unknown()).optional(),
|
|
6060
|
+
// Application context attached to the exact delegation/transcript message.
|
|
6061
|
+
// It is ordinary model-visible user-message content when materialized, not
|
|
6062
|
+
// a secret or instruction-authority boundary.
|
|
6063
|
+
modelContext: z.string().trim().min(1).max(32768).optional(),
|
|
5092
6064
|
})
|
|
5093
|
-
.strict()
|
|
6065
|
+
.strict()
|
|
6066
|
+
.superRefine((entry, context) => {
|
|
6067
|
+
if (
|
|
6068
|
+
entry.modelContext !== undefined &&
|
|
6069
|
+
entry.kind !== "delegation_call" &&
|
|
6070
|
+
entry.kind !== "user_transcript" &&
|
|
6071
|
+
entry.kind !== "assistant_transcript"
|
|
6072
|
+
) {
|
|
6073
|
+
context.addIssue({
|
|
6074
|
+
code: "custom",
|
|
6075
|
+
path: ["modelContext"],
|
|
6076
|
+
message: "modelContext requires a delegation or finalized transcript entry",
|
|
6077
|
+
});
|
|
6078
|
+
}
|
|
6079
|
+
});
|
|
5094
6080
|
export type SessionRealtimeInboundEntry = z.infer<typeof SessionRealtimeInboundEntry>;
|
|
5095
6081
|
|
|
5096
6082
|
export const SyncSessionRealtimeLedgerRequest = SessionRealtimeOwnerProof.extend({
|
|
@@ -5153,7 +6139,12 @@ export type WorkspaceRealtimeModelCatalogResponse = z.infer<
|
|
|
5153
6139
|
export const SessionRealtimeState = z.enum(["active", "ended"]);
|
|
5154
6140
|
export type SessionRealtimeState = z.infer<typeof SessionRealtimeState>;
|
|
5155
6141
|
|
|
5156
|
-
export const SessionRealtimeEndReason = z.enum([
|
|
6142
|
+
export const SessionRealtimeEndReason = z.enum([
|
|
6143
|
+
"user_stop",
|
|
6144
|
+
"browser_unload",
|
|
6145
|
+
"lease_expired",
|
|
6146
|
+
"authority_revoked",
|
|
6147
|
+
]);
|
|
5157
6148
|
export type SessionRealtimeEndReason = z.infer<typeof SessionRealtimeEndReason>;
|
|
5158
6149
|
|
|
5159
6150
|
export const SessionRealtimeMode = z.object({
|
|
@@ -5221,6 +6212,9 @@ export const SessionAuthorizationOperation = z.enum([
|
|
|
5221
6212
|
"session.secret.read",
|
|
5222
6213
|
"session.codemode.call",
|
|
5223
6214
|
"session.pin.write",
|
|
6215
|
+
"session.attention.write",
|
|
6216
|
+
"session.archive.write",
|
|
6217
|
+
"session.delete",
|
|
5224
6218
|
"session.codex_account.write",
|
|
5225
6219
|
"session.realtime.start",
|
|
5226
6220
|
"session.realtime.control",
|
|
@@ -5237,6 +6231,7 @@ export const SessionAuthorizationOperation = z.enum([
|
|
|
5237
6231
|
"session.child.create",
|
|
5238
6232
|
"session.visibility.write",
|
|
5239
6233
|
"session.fork.create",
|
|
6234
|
+
"session.personal_resource.grant",
|
|
5240
6235
|
]);
|
|
5241
6236
|
export type SessionAuthorizationOperation = z.infer<typeof SessionAuthorizationOperation>;
|
|
5242
6237
|
|
|
@@ -5559,6 +6554,69 @@ export function renderTimelineAnnotationsForModel(
|
|
|
5559
6554
|
].join("\n");
|
|
5560
6555
|
}
|
|
5561
6556
|
|
|
6557
|
+
export const MODEL_CONTEXT_LABEL = "[Application context attached to this user message]" as const;
|
|
6558
|
+
export const SESSION_GOAL_CONTEXT_LABEL =
|
|
6559
|
+
"[Session goal frozen when this turn was accepted]" as const;
|
|
6560
|
+
|
|
6561
|
+
/**
|
|
6562
|
+
* Render the exact goal authority frozen with one accepted logical turn. Goal
|
|
6563
|
+
* state belongs at the chronological input boundary, not in the mutable
|
|
6564
|
+
* Agent.instructions prefix.
|
|
6565
|
+
*/
|
|
6566
|
+
export function renderSessionGoalContext(snapshot?: SessionGoalSnapshot): string | undefined {
|
|
6567
|
+
if (!snapshot || snapshot.state === "none") return undefined;
|
|
6568
|
+
const rootConstraints = snapshot.rootConstraints.length
|
|
6569
|
+
? `\nRoot constraints (must remain satisfied):\n${snapshot.rootConstraints.map((constraint) => `- ${constraint}`).join("\n")}`
|
|
6570
|
+
: "";
|
|
6571
|
+
if (snapshot.state === "completed") {
|
|
6572
|
+
return `Previous session goal (frozen at logical-turn acceptance; objective revision ${snapshot.objectiveRevision}; status completed): ${snapshot.text}\nSuccess criteria: ${snapshot.successCriteria ?? "none specified"}.${rootConstraints} This goal is complete and remains as historical context. If the user provides a new long-running objective, create it with opengeni__goal_set; goal_update cannot revise a completed goal.`;
|
|
6573
|
+
}
|
|
6574
|
+
const policy =
|
|
6575
|
+
snapshot.mutationPolicy === "review_changes"
|
|
6576
|
+
? "Semantic changes are proposals until a user applies them."
|
|
6577
|
+
: snapshot.mutationPolicy === "preserve_intent"
|
|
6578
|
+
? "You may directly refine wording without changing intent; adaptations and replacements are proposals until a user applies them."
|
|
6579
|
+
: "You may autonomously refine, adapt, or replace the goal when explicit user direction or material new evidence justifies it.";
|
|
6580
|
+
return `Standing session goal (frozen at logical-turn acceptance; objective revision ${snapshot.objectiveRevision}; status ${snapshot.state}): ${snapshot.text}\nSuccess criteria: ${snapshot.successCriteria ?? "none specified"}.${rootConstraints}\nMutation policy: ${snapshot.mutationPolicy}. ${policy} Treat later ordinary messages as additional context unless they explicitly redirect this objective. Root constraints are user/API authority and cannot be widened, removed, or rewritten by an agent. Semantic goal changes use opengeni__goal_update with the expected objective revision, change kind, and rationale.`;
|
|
6581
|
+
}
|
|
6582
|
+
|
|
6583
|
+
/**
|
|
6584
|
+
* Build one canonical user-role message body. `modelContext` is ordinary
|
|
6585
|
+
* message content, while `goalSnapshot` is the exact goal authority frozen at
|
|
6586
|
+
* turn acceptance. Both remain in the visible message's chronological
|
|
6587
|
+
* position, and presentation layers may omit their leading parts.
|
|
6588
|
+
*/
|
|
6589
|
+
export function renderUserMessageContentForModel(
|
|
6590
|
+
text: string,
|
|
6591
|
+
annotations: readonly TimelineAnnotation[],
|
|
6592
|
+
modelContext?: string | null,
|
|
6593
|
+
goalSnapshot?: SessionGoalSnapshot,
|
|
6594
|
+
): string | Array<{ type: "input_text"; text: string }> {
|
|
6595
|
+
const visibleContent = renderTimelineAnnotationsForModel(text, annotations);
|
|
6596
|
+
const context = modelContext?.trim();
|
|
6597
|
+
const goalContext = renderSessionGoalContext(goalSnapshot);
|
|
6598
|
+
if (!context && !goalContext) return visibleContent;
|
|
6599
|
+
return [
|
|
6600
|
+
...(goalContext
|
|
6601
|
+
? [
|
|
6602
|
+
{
|
|
6603
|
+
type: "input_text" as const,
|
|
6604
|
+
text: `${SESSION_GOAL_CONTEXT_LABEL}\n${goalContext}`,
|
|
6605
|
+
},
|
|
6606
|
+
]
|
|
6607
|
+
: []),
|
|
6608
|
+
...(context
|
|
6609
|
+
? [
|
|
6610
|
+
{
|
|
6611
|
+
type: "input_text" as const,
|
|
6612
|
+
text: `${MODEL_CONTEXT_LABEL}\n${context}`,
|
|
6613
|
+
},
|
|
6614
|
+
]
|
|
6615
|
+
: []),
|
|
6616
|
+
{ type: "input_text", text: visibleContent },
|
|
6617
|
+
];
|
|
6618
|
+
}
|
|
6619
|
+
|
|
5562
6620
|
export const SessionTurn = z
|
|
5563
6621
|
.object({
|
|
5564
6622
|
id: z.string().uuid(),
|
|
@@ -5579,7 +6637,7 @@ export const SessionTurn = z
|
|
|
5579
6637
|
toolsProvided: z.boolean().optional(),
|
|
5580
6638
|
model: z.string().min(1),
|
|
5581
6639
|
reasoningEffort: ReasoningEffort,
|
|
5582
|
-
latencyMode: LatencyMode
|
|
6640
|
+
latencyMode: LatencyMode,
|
|
5583
6641
|
sandboxBackend: SandboxBackend,
|
|
5584
6642
|
// Per-turn OS override. NULL = inherit the session's sandboxOs.
|
|
5585
6643
|
sandboxOs: SandboxOs.nullable(),
|
|
@@ -5592,6 +6650,8 @@ export const SessionTurn = z
|
|
|
5592
6650
|
initiatorContext: TurnInitiatorContext,
|
|
5593
6651
|
/** Secret-safe projection of the exact personal authority frozen on this turn. */
|
|
5594
6652
|
personalConnections: z.array(McpPersonalConnectionSummary).default([]),
|
|
6653
|
+
/** Safe summary only; opaque resource/grant identity remains private. */
|
|
6654
|
+
personalResources: PersonalResourceAttachmentSummary.nullable().default(null),
|
|
5595
6655
|
cancelledBy: z.string().nullable(),
|
|
5596
6656
|
cancelReason: z.string().nullable(),
|
|
5597
6657
|
startedAt: z.string().nullable(),
|
|
@@ -5653,10 +6713,18 @@ export const EffectiveSessionControl = z.object({
|
|
|
5653
6713
|
quiescencePendingCount: z.number().int().nonnegative(),
|
|
5654
6714
|
})
|
|
5655
6715
|
.nullable(),
|
|
6716
|
+
/** Independent command-cancellation settlement. Session pause/turn state is
|
|
6717
|
+
* intentionally not overloaded with process lifecycle. */
|
|
6718
|
+
backgroundCommandSettlement: z
|
|
6719
|
+
.object({
|
|
6720
|
+
state: z.literal("stopping"),
|
|
6721
|
+
commandCount: z.number().int().positive(),
|
|
6722
|
+
})
|
|
6723
|
+
.nullable()
|
|
6724
|
+
.optional(),
|
|
5656
6725
|
});
|
|
5657
6726
|
export type EffectiveSessionControl = z.infer<typeof EffectiveSessionControl>;
|
|
5658
6727
|
|
|
5659
|
-
export const SESSION_OPERATION_KEY_MAX_CHARS = 256;
|
|
5660
6728
|
const SessionOperationKey = z.string().min(1).max(SESSION_OPERATION_KEY_MAX_CHARS);
|
|
5661
6729
|
|
|
5662
6730
|
export const SessionCommandReceipt = z.object({
|
|
@@ -5673,6 +6741,14 @@ export const SessionCommandReceipt = z.object({
|
|
|
5673
6741
|
});
|
|
5674
6742
|
export type SessionCommandReceipt = z.infer<typeof SessionCommandReceipt>;
|
|
5675
6743
|
|
|
6744
|
+
/** The server-owned destination of an accepted human prompt at admission time. */
|
|
6745
|
+
export const SessionPromptRouting = z.enum([
|
|
6746
|
+
"accepted_for_execution",
|
|
6747
|
+
"queued_for_execution",
|
|
6748
|
+
"accepted_for_steering",
|
|
6749
|
+
]);
|
|
6750
|
+
export type SessionPromptRouting = z.infer<typeof SessionPromptRouting>;
|
|
6751
|
+
|
|
5676
6752
|
export const ComposerDraft = z.object({
|
|
5677
6753
|
revision: z.number().int().nonnegative(),
|
|
5678
6754
|
text: z.string(),
|
|
@@ -5680,7 +6756,7 @@ export const ComposerDraft = z.object({
|
|
|
5680
6756
|
resources: z.array(ResourceRef),
|
|
5681
6757
|
model: z.string().min(1),
|
|
5682
6758
|
reasoningEffort: ReasoningEffort,
|
|
5683
|
-
latencyMode: LatencyMode
|
|
6759
|
+
latencyMode: LatencyMode,
|
|
5684
6760
|
sourceTurnId: z.string().uuid().nullable(),
|
|
5685
6761
|
sourceTurnVersion: z.number().int().positive().nullable(),
|
|
5686
6762
|
updatedAt: z.string().nullable(),
|
|
@@ -5726,12 +6802,39 @@ export const SaveComposerDraftRequest = ComposerDraft.pick({
|
|
|
5726
6802
|
}).extend({ expectedRevision: z.number().int().nonnegative() });
|
|
5727
6803
|
export type SaveComposerDraftRequest = z.infer<typeof SaveComposerDraftRequest>;
|
|
5728
6804
|
|
|
6805
|
+
/**
|
|
6806
|
+
* Submit one exact established-session draft. Content is repeated only as an
|
|
6807
|
+
* integrity fence for outcome-unknown idempotent replay; the matching durable
|
|
6808
|
+
* draft revision remains authoritative and is atomically rotated on acceptance.
|
|
6809
|
+
*/
|
|
6810
|
+
export const SubmitComposerDraftRequest = ComposerDraft.pick({
|
|
6811
|
+
text: true,
|
|
6812
|
+
annotations: true,
|
|
6813
|
+
resources: true,
|
|
6814
|
+
model: true,
|
|
6815
|
+
reasoningEffort: true,
|
|
6816
|
+
latencyMode: true,
|
|
6817
|
+
})
|
|
6818
|
+
.extend({
|
|
6819
|
+
expectedDraftRevision: z.number().int().positive(),
|
|
6820
|
+
clientEventId: SessionOperationKey,
|
|
6821
|
+
delivery: z.enum(["send", "steer"]),
|
|
6822
|
+
controlEtag: z.string().min(1).optional(),
|
|
6823
|
+
modelContext: z.string().trim().min(1).max(32768).optional(),
|
|
6824
|
+
mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
|
|
6825
|
+
connectionAuthorities: McpConnectionAuthoritySelections.default([]),
|
|
6826
|
+
personalResourceAttachment: PersonalResourceAttachmentIntent.optional(),
|
|
6827
|
+
})
|
|
6828
|
+
.superRefine(requireEstablishedPersonalResourceEpoch);
|
|
6829
|
+
export type SubmitComposerDraftRequest = z.infer<typeof SubmitComposerDraftRequest>;
|
|
6830
|
+
|
|
5729
6831
|
/**
|
|
5730
6832
|
* Create-only options saved with an actor's private pre-session draft. This is
|
|
5731
6833
|
* deliberately narrower than CreateSessionRequest: idempotency/event keys and
|
|
5732
6834
|
* credential-bearing MCP server inputs are per-attempt data, never draft state.
|
|
5733
6835
|
*/
|
|
5734
6836
|
export const NewSessionDraftOptions = z.object({
|
|
6837
|
+
visibility: SessionVisibility.optional(),
|
|
5735
6838
|
sandboxBackend: SandboxBackend.optional(),
|
|
5736
6839
|
targetSandboxId: z.string().uuid().optional(),
|
|
5737
6840
|
workingDir: z.string().min(1).optional(),
|
|
@@ -5743,6 +6846,31 @@ export const NewSessionDraftOptions = z.object({
|
|
|
5743
6846
|
});
|
|
5744
6847
|
export type NewSessionDraftOptions = z.infer<typeof NewSessionDraftOptions>;
|
|
5745
6848
|
|
|
6849
|
+
/**
|
|
6850
|
+
* Actor-private successful-create history for the new-session composer. Project
|
|
6851
|
+
* entries and their machine entries are MRU ordered. A null target means the
|
|
6852
|
+
* managed sandbox; a null working directory means the machine's launch root.
|
|
6853
|
+
*/
|
|
6854
|
+
export const NewSessionSelectionHistory = z.object({
|
|
6855
|
+
projects: z
|
|
6856
|
+
.array(
|
|
6857
|
+
z.object({
|
|
6858
|
+
channelId: z.string().uuid().nullable(),
|
|
6859
|
+
targetSandboxId: z.string().uuid().nullable(),
|
|
6860
|
+
machines: z
|
|
6861
|
+
.array(
|
|
6862
|
+
z.object({
|
|
6863
|
+
sandboxId: z.string().uuid(),
|
|
6864
|
+
workingDir: z.string().min(1).max(4096).nullable(),
|
|
6865
|
+
}),
|
|
6866
|
+
)
|
|
6867
|
+
.max(20),
|
|
6868
|
+
}),
|
|
6869
|
+
)
|
|
6870
|
+
.max(50),
|
|
6871
|
+
});
|
|
6872
|
+
export type NewSessionSelectionHistory = z.infer<typeof NewSessionSelectionHistory>;
|
|
6873
|
+
|
|
5746
6874
|
/** Actor-private, server-authoritative composer state before a session exists. */
|
|
5747
6875
|
export const NewSessionDraft = z.object({
|
|
5748
6876
|
revision: z.number().int().nonnegative(),
|
|
@@ -5753,8 +6881,9 @@ export const NewSessionDraft = z.object({
|
|
|
5753
6881
|
toolsProvided: z.boolean().default(false),
|
|
5754
6882
|
model: z.string().min(1),
|
|
5755
6883
|
reasoningEffort: ReasoningEffort,
|
|
5756
|
-
latencyMode: LatencyMode
|
|
6884
|
+
latencyMode: LatencyMode,
|
|
5757
6885
|
options: NewSessionDraftOptions,
|
|
6886
|
+
selectionHistory: NewSessionSelectionHistory.default({ projects: [] }),
|
|
5758
6887
|
updatedAt: z.string().nullable(),
|
|
5759
6888
|
});
|
|
5760
6889
|
export type NewSessionDraft = z.infer<typeof NewSessionDraft>;
|
|
@@ -5993,40 +7122,211 @@ export const SessionSystemUpdateKind = z.enum([
|
|
|
5993
7122
|
"agent_steer_instruction",
|
|
5994
7123
|
"child_terminal_result",
|
|
5995
7124
|
"media_generation_result",
|
|
7125
|
+
"child_requires_action",
|
|
7126
|
+
"child_requires_action_resolved",
|
|
7127
|
+
"child_paused",
|
|
7128
|
+
"child_waiting_capacity",
|
|
7129
|
+
"child_progress",
|
|
5996
7130
|
]);
|
|
5997
7131
|
export type SessionSystemUpdateKind = z.infer<typeof SessionSystemUpdateKind>;
|
|
5998
7132
|
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
7133
|
+
/**
|
|
7134
|
+
* How a newly pending machine input affects an idle receiving session.
|
|
7135
|
+
* `immediate` registers a workflow wake in the same commit (the behaviour of
|
|
7136
|
+
* every pre-existing kind) and ends a `goal_wait` hold at the next idle
|
|
7137
|
+
* evaluation; `deferred` only inserts the durable pending row plus its
|
|
7138
|
+
* `system.update.pending` event and is delivered coalesced with the next claim.
|
|
7139
|
+
*/
|
|
7140
|
+
export type SessionSystemUpdateWakeClass = "immediate" | "deferred";
|
|
7141
|
+
|
|
7142
|
+
export const SESSION_SYSTEM_UPDATE_WAKE_CLASS: Record<
|
|
7143
|
+
SessionSystemUpdateKind,
|
|
7144
|
+
SessionSystemUpdateWakeClass
|
|
7145
|
+
> = {
|
|
7146
|
+
scheduled_occurrence: "immediate",
|
|
7147
|
+
goal_continuation: "immediate",
|
|
7148
|
+
agent_message: "immediate",
|
|
7149
|
+
agent_steer_instruction: "immediate",
|
|
7150
|
+
child_terminal_result: "immediate",
|
|
7151
|
+
media_generation_result: "immediate",
|
|
7152
|
+
child_requires_action: "immediate",
|
|
7153
|
+
child_requires_action_resolved: "deferred",
|
|
7154
|
+
child_paused: "deferred",
|
|
7155
|
+
child_waiting_capacity: "deferred",
|
|
7156
|
+
child_progress: "deferred",
|
|
7157
|
+
};
|
|
7158
|
+
|
|
7159
|
+
/**
|
|
7160
|
+
* Kinds a child session's lifecycle produces for its parent. Every one of them
|
|
7161
|
+
* travels through `session_system_update_outbox`, and none of them may
|
|
7162
|
+
* autonomously wake a parent whose goal is not active.
|
|
7163
|
+
*/
|
|
7164
|
+
export const CHILD_LIFECYCLE_SYSTEM_UPDATE_KINDS = [
|
|
7165
|
+
"child_terminal_result",
|
|
7166
|
+
"child_requires_action",
|
|
7167
|
+
"child_requires_action_resolved",
|
|
7168
|
+
"child_paused",
|
|
7169
|
+
"child_waiting_capacity",
|
|
7170
|
+
"child_progress",
|
|
7171
|
+
] as const satisfies readonly SessionSystemUpdateKind[];
|
|
7172
|
+
export type ChildLifecycleSystemUpdateKind = (typeof CHILD_LIFECYCLE_SYSTEM_UPDATE_KINDS)[number];
|
|
7173
|
+
|
|
7174
|
+
const CHILD_LIFECYCLE_SYSTEM_UPDATE_KIND_SET: ReadonlySet<string> = new Set(
|
|
7175
|
+
CHILD_LIFECYCLE_SYSTEM_UPDATE_KINDS,
|
|
7176
|
+
);
|
|
7177
|
+
|
|
7178
|
+
export function isChildLifecycleSystemUpdateKind(
|
|
7179
|
+
kind: string,
|
|
7180
|
+
): kind is ChildLifecycleSystemUpdateKind {
|
|
7181
|
+
return CHILD_LIFECYCLE_SYSTEM_UPDATE_KIND_SET.has(kind);
|
|
7182
|
+
}
|
|
7183
|
+
|
|
7184
|
+
/** A child_paused notice requested by a human/API is action-required; an agent pause is informational. */
|
|
7185
|
+
export function childPausedClassification(
|
|
7186
|
+
actorKind: "human" | "api" | "agent",
|
|
7187
|
+
): "action_required" | "info" {
|
|
7188
|
+
return actorKind === "agent" ? "info" : "action_required";
|
|
7189
|
+
}
|
|
7190
|
+
|
|
7191
|
+
/** Whole child_requires_action payload bound (UTF-8 JSON bytes). */
|
|
7192
|
+
export const CHILD_REQUIRES_ACTION_PAYLOAD_MAX_BYTES = 8 * 1024;
|
|
7193
|
+
/** Bounded first-question preview inside a child_requires_action notice. */
|
|
7194
|
+
export const CHILD_REQUIRES_ACTION_QUESTION_PREVIEW_MAX_BYTES = 512;
|
|
7195
|
+
export const CHILD_REQUIRES_ACTION_MAX_REQUESTS = 20;
|
|
7196
|
+
export const CHILD_PAUSED_REASON_MAX_BYTES = 2 * 1024;
|
|
7197
|
+
export const CHILD_PROGRESS_NOTE_MAX_BYTES = 4 * 1024;
|
|
7198
|
+
|
|
7199
|
+
const boundedUtf8String = (maxBytes: number) =>
|
|
7200
|
+
z.string().refine((value) => new TextEncoder().encode(value).byteLength <= maxBytes, {
|
|
7201
|
+
message: `must be at most ${maxBytes} UTF-8 bytes`,
|
|
7202
|
+
});
|
|
7203
|
+
|
|
7204
|
+
export const ChildRequiresActionRequest = z.discriminatedUnion("kind", [
|
|
7205
|
+
z.object({
|
|
7206
|
+
kind: z.literal("human_input"),
|
|
7207
|
+
requestId: z.string().uuid(),
|
|
7208
|
+
questionCount: z.number().int().nonnegative(),
|
|
7209
|
+
firstQuestion: boundedUtf8String(CHILD_REQUIRES_ACTION_QUESTION_PREVIEW_MAX_BYTES),
|
|
7210
|
+
allowSkip: z.boolean(),
|
|
7211
|
+
expiresAt: z.string().nullable(),
|
|
7212
|
+
}),
|
|
7213
|
+
z.object({
|
|
7214
|
+
kind: z.literal("approval"),
|
|
7215
|
+
approvalId: boundedUtf8String(256),
|
|
7216
|
+
toolName: boundedUtf8String(128).nullable(),
|
|
7217
|
+
}),
|
|
7218
|
+
]);
|
|
7219
|
+
export type ChildRequiresActionRequest = z.infer<typeof ChildRequiresActionRequest>;
|
|
7220
|
+
|
|
7221
|
+
export const ChildRequiresActionPayload = z
|
|
7222
|
+
.object({
|
|
7223
|
+
type: z.literal("child_requires_action"),
|
|
7224
|
+
childSessionId: z.string().uuid(),
|
|
7225
|
+
childTurnId: z.string().uuid(),
|
|
7226
|
+
childTurnGeneration: z.number().int().positive(),
|
|
7227
|
+
requests: z.array(ChildRequiresActionRequest).max(CHILD_REQUIRES_ACTION_MAX_REQUESTS),
|
|
7228
|
+
truncated: z.boolean(),
|
|
7229
|
+
})
|
|
7230
|
+
.passthrough();
|
|
7231
|
+
export type ChildRequiresActionPayload = z.infer<typeof ChildRequiresActionPayload>;
|
|
7232
|
+
|
|
7233
|
+
export const ChildRequiresActionResolvedOutcome = z.enum([
|
|
7234
|
+
"answered",
|
|
7235
|
+
"skipped",
|
|
7236
|
+
"expired",
|
|
7237
|
+
"cancelled",
|
|
7238
|
+
"approved",
|
|
7239
|
+
"rejected",
|
|
7240
|
+
]);
|
|
7241
|
+
export type ChildRequiresActionResolvedOutcome = z.infer<typeof ChildRequiresActionResolvedOutcome>;
|
|
7242
|
+
|
|
7243
|
+
export const ChildRequiresActionRespondedByKind = z.enum([
|
|
7244
|
+
"human",
|
|
7245
|
+
"api",
|
|
7246
|
+
"agent_attempt",
|
|
7247
|
+
"system",
|
|
7248
|
+
]);
|
|
7249
|
+
export type ChildRequiresActionRespondedByKind = z.infer<typeof ChildRequiresActionRespondedByKind>;
|
|
7250
|
+
|
|
7251
|
+
export const ChildRequiresActionResolvedPayload = z
|
|
7252
|
+
.object({
|
|
7253
|
+
type: z.literal("child_requires_action_resolved"),
|
|
7254
|
+
childSessionId: z.string().uuid(),
|
|
7255
|
+
childTurnId: z.string().uuid(),
|
|
7256
|
+
childTurnGeneration: z.number().int().positive(),
|
|
7257
|
+
requestId: z.string().uuid().nullable(),
|
|
7258
|
+
approvalId: boundedUtf8String(256).nullable(),
|
|
7259
|
+
outcome: ChildRequiresActionResolvedOutcome,
|
|
7260
|
+
respondedByKind: ChildRequiresActionRespondedByKind,
|
|
7261
|
+
})
|
|
7262
|
+
.passthrough();
|
|
7263
|
+
export type ChildRequiresActionResolvedPayload = z.infer<typeof ChildRequiresActionResolvedPayload>;
|
|
7264
|
+
|
|
7265
|
+
export const ChildPausedPayload = z
|
|
7266
|
+
.object({
|
|
7267
|
+
type: z.literal("child_paused"),
|
|
7268
|
+
childSessionId: z.string().uuid(),
|
|
7269
|
+
operationId: z.string().uuid(),
|
|
7270
|
+
actorKind: z.enum(["human", "api", "agent"]),
|
|
7271
|
+
reason: boundedUtf8String(CHILD_PAUSED_REASON_MAX_BYTES).nullable(),
|
|
7272
|
+
})
|
|
7273
|
+
.passthrough();
|
|
7274
|
+
export type ChildPausedPayload = z.infer<typeof ChildPausedPayload>;
|
|
7275
|
+
|
|
7276
|
+
export const ChildWaitingCapacityPayload = z
|
|
7277
|
+
.object({
|
|
7278
|
+
type: z.literal("child_waiting_capacity"),
|
|
7279
|
+
childSessionId: z.string().uuid(),
|
|
7280
|
+
childTurnId: z.string().uuid(),
|
|
7281
|
+
provider: z.enum(["codex", "xai"]),
|
|
7282
|
+
nextCheckAt: z.string().nullable(),
|
|
7283
|
+
})
|
|
7284
|
+
.passthrough();
|
|
7285
|
+
export type ChildWaitingCapacityPayload = z.infer<typeof ChildWaitingCapacityPayload>;
|
|
7286
|
+
|
|
7287
|
+
export const ChildProgressPayload = z
|
|
7288
|
+
.object({
|
|
7289
|
+
type: z.literal("child_progress"),
|
|
7290
|
+
childSessionId: z.string().uuid(),
|
|
7291
|
+
goalId: z.string().uuid(),
|
|
7292
|
+
objectiveRevision: z.number().int().nonnegative(),
|
|
7293
|
+
operationId: z.string().uuid(),
|
|
7294
|
+
progressNote: boundedUtf8String(CHILD_PROGRESS_NOTE_MAX_BYTES),
|
|
7295
|
+
})
|
|
7296
|
+
.passthrough();
|
|
7297
|
+
export type ChildProgressPayload = z.infer<typeof ChildProgressPayload>;
|
|
7298
|
+
|
|
7299
|
+
export const SessionSystemUpdatePayload = z.discriminatedUnion("type", [
|
|
7300
|
+
z
|
|
7301
|
+
.object({
|
|
7302
|
+
type: z.literal("scheduled_occurrence"),
|
|
7303
|
+
text: z.string().min(1),
|
|
7304
|
+
scheduledTaskId: z.string().uuid(),
|
|
7305
|
+
scheduledTaskRunId: z.string().uuid(),
|
|
7306
|
+
resources: z.array(ResourceRef).optional(),
|
|
7307
|
+
tools: z.array(ToolRef).optional(),
|
|
7308
|
+
})
|
|
7309
|
+
.passthrough(),
|
|
7310
|
+
z
|
|
7311
|
+
.object({
|
|
7312
|
+
type: z.literal("goal_continuation"),
|
|
7313
|
+
goalId: z.string().uuid(),
|
|
7314
|
+
goalVersion: z.number().int().positive(),
|
|
7315
|
+
prompt: z.string().min(1),
|
|
7316
|
+
reason: z.string().optional(),
|
|
7317
|
+
})
|
|
7318
|
+
.passthrough(),
|
|
7319
|
+
z
|
|
7320
|
+
.object({
|
|
7321
|
+
type: z.literal("agent_message"),
|
|
7322
|
+
text: z.string().min(1),
|
|
7323
|
+
operationId: z.string().uuid(),
|
|
7324
|
+
})
|
|
7325
|
+
.passthrough(),
|
|
7326
|
+
z
|
|
7327
|
+
.object({
|
|
7328
|
+
type: z.literal("agent_steer_instruction"),
|
|
7329
|
+
instruction: z.string().min(1),
|
|
6030
7330
|
operationId: z.string().uuid(),
|
|
6031
7331
|
})
|
|
6032
7332
|
.passthrough(),
|
|
@@ -6038,6 +7338,11 @@ export const SessionSystemUpdatePayload = z.discriminatedUnion("type", [
|
|
|
6038
7338
|
})
|
|
6039
7339
|
.passthrough(),
|
|
6040
7340
|
MediaGenerationResult,
|
|
7341
|
+
ChildRequiresActionPayload,
|
|
7342
|
+
ChildRequiresActionResolvedPayload,
|
|
7343
|
+
ChildPausedPayload,
|
|
7344
|
+
ChildWaitingCapacityPayload,
|
|
7345
|
+
ChildProgressPayload,
|
|
6041
7346
|
]);
|
|
6042
7347
|
export type SessionSystemUpdatePayload = z.infer<typeof SessionSystemUpdatePayload>;
|
|
6043
7348
|
|
|
@@ -6154,11 +7459,16 @@ export function renderSessionSystemUpdateBatch(
|
|
|
6154
7459
|
|
|
6155
7460
|
export function sessionSystemUpdateBatchHistoryItem(
|
|
6156
7461
|
updates: Parameters<typeof renderSessionSystemUpdateBatch>[0],
|
|
7462
|
+
goalSnapshot?: SessionGoalSnapshot,
|
|
6157
7463
|
): { type: "message"; role: "system"; content: string } {
|
|
7464
|
+
const goalContext = renderSessionGoalContext(goalSnapshot);
|
|
6158
7465
|
return {
|
|
6159
7466
|
type: "message",
|
|
6160
7467
|
role: "system",
|
|
6161
|
-
content:
|
|
7468
|
+
content: [
|
|
7469
|
+
...(goalContext ? [`${SESSION_GOAL_CONTEXT_LABEL}\n${goalContext}`] : []),
|
|
7470
|
+
renderSessionSystemUpdateBatch(updates),
|
|
7471
|
+
].join("\n\n"),
|
|
6162
7472
|
};
|
|
6163
7473
|
}
|
|
6164
7474
|
|
|
@@ -6168,12 +7478,16 @@ export const VariableSetVariableName = z
|
|
|
6168
7478
|
.max(128);
|
|
6169
7479
|
export type VariableSetVariableName = z.infer<typeof VariableSetVariableName>;
|
|
6170
7480
|
|
|
6171
|
-
function withVariableSetIdAlias<T extends z.ZodRawShape>(
|
|
7481
|
+
function withVariableSetIdAlias<T extends z.ZodRawShape>(
|
|
7482
|
+
shape: T,
|
|
7483
|
+
options: { rejectKeys?: readonly string[] } = {},
|
|
7484
|
+
) {
|
|
6172
7485
|
return z.preprocess((input) => {
|
|
6173
7486
|
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
6174
7487
|
return input;
|
|
6175
7488
|
}
|
|
6176
7489
|
const record = input as Record<string, unknown>;
|
|
7490
|
+
if (options.rejectKeys?.some((key) => Object.hasOwn(record, key))) return null;
|
|
6177
7491
|
if (record.variableSetId !== undefined || record.environmentId === undefined) {
|
|
6178
7492
|
return record;
|
|
6179
7493
|
}
|
|
@@ -6204,10 +7518,16 @@ export const VariableSetSecret = z.object({
|
|
|
6204
7518
|
});
|
|
6205
7519
|
export type VariableSetSecret = z.infer<typeof VariableSetSecret>;
|
|
6206
7520
|
|
|
7521
|
+
export const VariableSetScope = z.enum(["organization", "workspace", "user"]);
|
|
7522
|
+
export type VariableSetScope = z.infer<typeof VariableSetScope>;
|
|
7523
|
+
|
|
6207
7524
|
export const VariableSet = z.object({
|
|
6208
7525
|
id: z.string().uuid(),
|
|
6209
7526
|
accountId: z.string().uuid(),
|
|
6210
7527
|
workspaceId: z.string().uuid(),
|
|
7528
|
+
scope: VariableSetScope,
|
|
7529
|
+
generation: z.number().int().positive(),
|
|
7530
|
+
status: z.enum(["active", "revoked"]),
|
|
6211
7531
|
name: z.string(),
|
|
6212
7532
|
description: z.string().nullable(),
|
|
6213
7533
|
variables: z.array(VariableSetVariableMetadata),
|
|
@@ -6221,6 +7541,8 @@ export const WorkspaceEnvironment = VariableSet;
|
|
|
6221
7541
|
export type WorkspaceEnvironment = VariableSet;
|
|
6222
7542
|
|
|
6223
7543
|
export const CreateVariableSetRequest = z.object({
|
|
7544
|
+
// Omitted remains the legacy workspace-owned creation path.
|
|
7545
|
+
scope: VariableSetScope.default("workspace"),
|
|
6224
7546
|
name: z.string().min(1).max(120),
|
|
6225
7547
|
description: z.string().max(2000).optional(),
|
|
6226
7548
|
variables: z
|
|
@@ -6419,6 +7741,9 @@ export const Rig = z.object({
|
|
|
6419
7741
|
id: z.string().uuid(),
|
|
6420
7742
|
accountId: z.string().uuid(),
|
|
6421
7743
|
workspaceId: z.string().uuid(),
|
|
7744
|
+
scope: ResourceAuthorityScope,
|
|
7745
|
+
generation: z.number().int().positive(),
|
|
7746
|
+
status: z.enum(["active", "revoked"]),
|
|
6422
7747
|
name: z.string(),
|
|
6423
7748
|
description: z.string().nullable(),
|
|
6424
7749
|
createdBy: z.string().nullable(),
|
|
@@ -6477,6 +7802,8 @@ export const RigChange = z.object({
|
|
|
6477
7802
|
export type RigChange = z.infer<typeof RigChange>;
|
|
6478
7803
|
|
|
6479
7804
|
export const CreateRigRequest = z.object({
|
|
7805
|
+
// Omitted remains the compatibility workspace-owned creation path.
|
|
7806
|
+
scope: ResourceAuthorityScope.default("workspace"),
|
|
6480
7807
|
name: z.string().min(1).max(120),
|
|
6481
7808
|
description: z.string().max(2000).optional(),
|
|
6482
7809
|
// Initial (version 1) content, inline.
|
|
@@ -6503,6 +7830,8 @@ export const Channel = z.object({
|
|
|
6503
7830
|
workspaceId: z.string().uuid(),
|
|
6504
7831
|
name: z.string(),
|
|
6505
7832
|
description: z.string().nullable(),
|
|
7833
|
+
pinned: z.boolean(),
|
|
7834
|
+
sortOrder: z.number().int().nonnegative(),
|
|
6506
7835
|
createdBy: z.string().nullable(),
|
|
6507
7836
|
createdAt: z.string(),
|
|
6508
7837
|
updatedAt: z.string(),
|
|
@@ -6518,9 +7847,16 @@ export type CreateChannelRequest = z.infer<typeof CreateChannelRequest>;
|
|
|
6518
7847
|
export const UpdateChannelRequest = z.object({
|
|
6519
7848
|
name: z.string().trim().min(1).max(80).optional(),
|
|
6520
7849
|
description: z.string().max(2000).nullable().optional(),
|
|
7850
|
+
pinned: z.boolean().optional(),
|
|
6521
7851
|
});
|
|
6522
7852
|
export type UpdateChannelRequest = z.infer<typeof UpdateChannelRequest>;
|
|
6523
7853
|
|
|
7854
|
+
/** Complete workspace project order. It is replaced atomically after a drag. */
|
|
7855
|
+
export const ReorderChannelsRequest = z
|
|
7856
|
+
.object({ channelIds: z.array(z.string().uuid()).min(1).max(200) })
|
|
7857
|
+
.strict();
|
|
7858
|
+
export type ReorderChannelsRequest = z.infer<typeof ReorderChannelsRequest>;
|
|
7859
|
+
|
|
6524
7860
|
// Re-files one session (rail organization only). null moves it back to the
|
|
6525
7861
|
// unfiled inbox.
|
|
6526
7862
|
export const UpdateSessionChannelRequest = z.object({
|
|
@@ -6686,25 +8022,313 @@ export const ScheduledTaskScheduleSpec = /* @__PURE__ */ z.discriminatedUnion("t
|
|
|
6686
8022
|
]);
|
|
6687
8023
|
export type ScheduledTaskScheduleSpec = z.infer<typeof ScheduledTaskScheduleSpec>;
|
|
6688
8024
|
|
|
6689
|
-
export const
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
8025
|
+
export const IncidentTelemetryExecutionClass = z.literal("incident_telemetry");
|
|
8026
|
+
export type IncidentTelemetryExecutionClass = z.infer<typeof IncidentTelemetryExecutionClass>;
|
|
8027
|
+
|
|
8028
|
+
const IncidentTelemetryIdentifier = z.string().trim().min(1).max(200);
|
|
8029
|
+
const IncidentTelemetryMetricName = z
|
|
8030
|
+
.string()
|
|
8031
|
+
.trim()
|
|
8032
|
+
.min(1)
|
|
8033
|
+
.max(200)
|
|
8034
|
+
.regex(/^[A-Za-z_:][A-Za-z0-9_:]*$/);
|
|
8035
|
+
const IncidentTelemetryLabelName = z
|
|
8036
|
+
.string()
|
|
8037
|
+
.trim()
|
|
8038
|
+
.min(1)
|
|
8039
|
+
.max(200)
|
|
8040
|
+
.regex(/^[A-Za-z_][A-Za-z0-9_]*$/);
|
|
8041
|
+
|
|
8042
|
+
export const IncidentTelemetrySeriesMetadata = z
|
|
8043
|
+
.object({
|
|
8044
|
+
metric: IncidentTelemetryMetricName,
|
|
8045
|
+
labels: z.array(IncidentTelemetryLabelName).min(1).max(64),
|
|
8046
|
+
})
|
|
8047
|
+
.strict();
|
|
8048
|
+
export type IncidentTelemetrySeriesMetadata = z.infer<typeof IncidentTelemetrySeriesMetadata>;
|
|
8049
|
+
|
|
8050
|
+
export const IncidentTelemetryDataRoute = z.discriminatedUnion("kind", [
|
|
8051
|
+
z
|
|
8052
|
+
.object({
|
|
8053
|
+
kind: z.literal("mcp"),
|
|
8054
|
+
serverId: SessionMcpServerId,
|
|
8055
|
+
})
|
|
8056
|
+
.strict(),
|
|
8057
|
+
z
|
|
8058
|
+
.object({
|
|
8059
|
+
kind: z.literal("first_party"),
|
|
8060
|
+
tool: FirstPartyMcpToolName,
|
|
8061
|
+
})
|
|
8062
|
+
.strict(),
|
|
8063
|
+
z
|
|
8064
|
+
.object({
|
|
8065
|
+
kind: z.literal("variable_set"),
|
|
8066
|
+
variableSetName: z.string().trim().min(1).max(120),
|
|
8067
|
+
variableNames: z.array(VariableSetVariableName).min(1).max(100),
|
|
8068
|
+
})
|
|
8069
|
+
.strict(),
|
|
8070
|
+
z
|
|
8071
|
+
.object({
|
|
8072
|
+
kind: z.literal("rig_credential_hook"),
|
|
8073
|
+
credentialHookId: IncidentTelemetryIdentifier,
|
|
8074
|
+
})
|
|
8075
|
+
.strict(),
|
|
8076
|
+
]);
|
|
8077
|
+
export type IncidentTelemetryDataRoute = z.infer<typeof IncidentTelemetryDataRoute>;
|
|
8078
|
+
|
|
8079
|
+
export const IncidentTelemetryPreflight = z
|
|
8080
|
+
.object({
|
|
8081
|
+
// These are exact selected resource refs, not discovery hints. The core
|
|
8082
|
+
// validator requires every entry to already be present in agentConfig.
|
|
8083
|
+
requiredResources: z.array(ResourceRef).max(100).default([]),
|
|
8084
|
+
requiredMcpServerIds: z.array(SessionMcpServerId).max(64).default([]),
|
|
8085
|
+
requiredFirstPartyMcpTools: z.array(FirstPartyMcpToolName).max(100).default([]),
|
|
8086
|
+
requiredFirstPartyMcpPermissions: z.array(Permission).max(100).default([]),
|
|
8087
|
+
requiredRig: z
|
|
8088
|
+
.object({
|
|
8089
|
+
name: z.string().trim().min(1).max(120),
|
|
8090
|
+
credentialHookIds: z.array(IncidentTelemetryIdentifier).max(50).default([]),
|
|
8091
|
+
})
|
|
8092
|
+
.strict()
|
|
8093
|
+
.nullable()
|
|
8094
|
+
.default(null),
|
|
8095
|
+
// Names only. The dispatch preflight never reads or decrypts values.
|
|
8096
|
+
requiredVariableSetNames: z.array(z.string().trim().min(1).max(120)).max(25).default([]),
|
|
8097
|
+
requiredVariableNames: z.array(VariableSetVariableName).max(100).default([]),
|
|
8098
|
+
dataSource: z
|
|
8099
|
+
.object({
|
|
8100
|
+
kind: z.literal("prometheus"),
|
|
8101
|
+
// Exposition endpoints such as /metrics are deliberately excluded.
|
|
8102
|
+
queryPath: z.enum(["/api/v1/query", "/api/v1/query_range"]),
|
|
8103
|
+
workspaceLabel: IncidentTelemetryLabelName,
|
|
8104
|
+
// Exact non-workspace labels whose values come from the validated
|
|
8105
|
+
// structured alert occurrence and bound every telemetry query.
|
|
8106
|
+
alertSelectorLabels: z.array(IncidentTelemetryLabelName).min(1).max(16),
|
|
8107
|
+
route: IncidentTelemetryDataRoute,
|
|
8108
|
+
requiredSeries: z.array(IncidentTelemetrySeriesMetadata).min(1).max(100),
|
|
8109
|
+
availableSeries: z.array(IncidentTelemetrySeriesMetadata).min(1).max(500),
|
|
8110
|
+
})
|
|
8111
|
+
.strict(),
|
|
8112
|
+
})
|
|
8113
|
+
.strict()
|
|
8114
|
+
.superRefine((value, context) => {
|
|
8115
|
+
for (const [index, label] of value.dataSource.alertSelectorLabels.entries()) {
|
|
8116
|
+
if (label === value.dataSource.workspaceLabel) {
|
|
8117
|
+
context.addIssue({
|
|
8118
|
+
code: "custom",
|
|
8119
|
+
path: ["dataSource", "alertSelectorLabels", index],
|
|
8120
|
+
message: "alert selector labels must be non-workspace labels",
|
|
8121
|
+
});
|
|
8122
|
+
}
|
|
8123
|
+
}
|
|
8124
|
+
for (const [index, series] of value.dataSource.requiredSeries.entries()) {
|
|
8125
|
+
if (!series.labels.includes(value.dataSource.workspaceLabel)) {
|
|
8126
|
+
context.addIssue({
|
|
8127
|
+
code: "custom",
|
|
8128
|
+
path: ["dataSource", "requiredSeries", index, "labels"],
|
|
8129
|
+
message: "required incident series must include the workspace label",
|
|
8130
|
+
});
|
|
8131
|
+
}
|
|
8132
|
+
for (const label of value.dataSource.alertSelectorLabels) {
|
|
8133
|
+
if (!series.labels.includes(label)) {
|
|
8134
|
+
context.addIssue({
|
|
8135
|
+
code: "custom",
|
|
8136
|
+
path: ["dataSource", "requiredSeries", index, "labels"],
|
|
8137
|
+
message: "required incident series must include every alert selector label",
|
|
8138
|
+
});
|
|
8139
|
+
}
|
|
8140
|
+
}
|
|
8141
|
+
}
|
|
8142
|
+
});
|
|
8143
|
+
export type IncidentTelemetryPreflight = z.infer<typeof IncidentTelemetryPreflight>;
|
|
8144
|
+
|
|
8145
|
+
/**
|
|
8146
|
+
* Canonical UTF-8 ingress limits for newly written scheduled execution truth.
|
|
8147
|
+
* They bound create/update requests and freshly accepted occurrence snapshots;
|
|
8148
|
+
* already-stored tasks are read back through the unbounded storage shape so a
|
|
8149
|
+
* legacy row can never become unreadable or undispatchable by a later cap.
|
|
8150
|
+
*/
|
|
8151
|
+
export const SCHEDULED_TASK_NAME_MAX_BYTES = 512;
|
|
8152
|
+
export const SCHEDULED_TASK_PROMPT_MAX_BYTES = 64 * 1024;
|
|
8153
|
+
export const SCHEDULED_TASK_METADATA_MAX_BYTES = 32 * 1024;
|
|
8154
|
+
export const SCHEDULED_TASK_AGENT_CONFIG_MAX_BYTES = 128 * 1024;
|
|
8155
|
+
export const SCHEDULED_TASK_ACCEPTED_EXECUTION_MAX_BYTES = 512 * 1024;
|
|
8156
|
+
/**
|
|
8157
|
+
* A scheduled occurrence is delivered as one durable internal update whose
|
|
8158
|
+
* payload (`scheduled_occurrence` text + resources + tools + ids) must fit the
|
|
8159
|
+
* canonical internal-update bound. Bounding it here at ingress means every
|
|
8160
|
+
* stored task that passed validation can also be delivered.
|
|
8161
|
+
*/
|
|
8162
|
+
export const SCHEDULED_TASK_OCCURRENCE_PAYLOAD_MAX_BYTES = 64 * 1024;
|
|
8163
|
+
/**
|
|
8164
|
+
* Ingress reserves headroom below that bound for what the worker adds to the
|
|
8165
|
+
* delivered payload (the first-party `opengeni` MCP tool ref and real ids), so
|
|
8166
|
+
* a request that passes validation can always be delivered.
|
|
8167
|
+
*/
|
|
8168
|
+
export const SCHEDULED_TASK_OCCURRENCE_PAYLOAD_INGRESS_HEADROOM_BYTES = 1024;
|
|
8169
|
+
export const SCHEDULED_TASK_PRODUCER_KEY_MAX_BYTES = 512;
|
|
8170
|
+
export const SCHEDULED_TASK_RESOURCE_MAX_COUNT = 100;
|
|
8171
|
+
export const SCHEDULED_TASK_TOOL_MAX_COUNT = 128;
|
|
8172
|
+
|
|
8173
|
+
const scheduledTaskUtf8Encoder = new TextEncoder();
|
|
8174
|
+
|
|
8175
|
+
function scheduledTaskUtf8Bytes(value: string): number {
|
|
8176
|
+
return scheduledTaskUtf8Encoder.encode(value).byteLength;
|
|
8177
|
+
}
|
|
8178
|
+
|
|
8179
|
+
function scheduledTaskJsonUtf8Bytes(value: unknown): number {
|
|
8180
|
+
try {
|
|
8181
|
+
const encoded = JSON.stringify(value);
|
|
8182
|
+
return encoded === undefined ? Number.POSITIVE_INFINITY : scheduledTaskUtf8Bytes(encoded);
|
|
8183
|
+
} catch {
|
|
8184
|
+
return Number.POSITIVE_INFINITY;
|
|
8185
|
+
}
|
|
8186
|
+
}
|
|
8187
|
+
|
|
8188
|
+
/**
|
|
8189
|
+
* UTF-8 size of the exact `scheduled_occurrence` internal-update payload the
|
|
8190
|
+
* worker delivers for one occurrence of this agent config (ids use fixed-width
|
|
8191
|
+
* placeholder UUIDs). Shared by ingress validation and worker admission.
|
|
8192
|
+
*/
|
|
8193
|
+
export function scheduledOccurrencePayloadUtf8Bytes(agentConfig: {
|
|
8194
|
+
prompt: string;
|
|
8195
|
+
resources?: readonly unknown[] | undefined;
|
|
8196
|
+
tools?: readonly unknown[] | undefined;
|
|
8197
|
+
}): number {
|
|
8198
|
+
const placeholder = "00000000-0000-4000-8000-000000000000";
|
|
8199
|
+
return scheduledTaskJsonUtf8Bytes({
|
|
8200
|
+
type: "scheduled_occurrence",
|
|
8201
|
+
text: agentConfig.prompt,
|
|
8202
|
+
scheduledTaskId: placeholder,
|
|
8203
|
+
scheduledTaskRunId: placeholder,
|
|
8204
|
+
...(agentConfig.resources?.length ? { resources: agentConfig.resources } : {}),
|
|
8205
|
+
...(agentConfig.tools?.length ? { tools: agentConfig.tools } : {}),
|
|
8206
|
+
});
|
|
8207
|
+
}
|
|
8208
|
+
|
|
8209
|
+
function scheduledTaskBoundedJsonObject(maxBytes: number, label: string) {
|
|
8210
|
+
return z.record(z.string(), z.unknown()).superRefine((value, context) => {
|
|
8211
|
+
if (scheduledTaskJsonUtf8Bytes(value) > maxBytes) {
|
|
8212
|
+
context.addIssue({
|
|
8213
|
+
code: "custom",
|
|
8214
|
+
message: `${label} exceeds ${maxBytes} UTF-8 bytes`,
|
|
8215
|
+
});
|
|
8216
|
+
}
|
|
8217
|
+
});
|
|
8218
|
+
}
|
|
8219
|
+
|
|
8220
|
+
function scheduledTaskBoundedString(maxBytes: number, label: string) {
|
|
8221
|
+
return z
|
|
8222
|
+
.string()
|
|
8223
|
+
.min(1)
|
|
8224
|
+
.superRefine((value, context) => {
|
|
8225
|
+
if (scheduledTaskUtf8Bytes(value) > maxBytes) {
|
|
8226
|
+
context.addIssue({
|
|
8227
|
+
code: "custom",
|
|
8228
|
+
message: `${label} exceeds ${maxBytes} UTF-8 bytes`,
|
|
8229
|
+
});
|
|
8230
|
+
}
|
|
8231
|
+
});
|
|
8232
|
+
}
|
|
8233
|
+
|
|
8234
|
+
/** Ingress-bounded task name for create/update requests. */
|
|
8235
|
+
export const ScheduledTaskNameInput = /* @__PURE__ */ scheduledTaskBoundedString(
|
|
8236
|
+
SCHEDULED_TASK_NAME_MAX_BYTES,
|
|
8237
|
+
"scheduled task name",
|
|
8238
|
+
);
|
|
8239
|
+
/** Ingress-bounded task metadata for create/update requests. */
|
|
8240
|
+
export const ScheduledTaskMetadataInput = /* @__PURE__ */ scheduledTaskBoundedJsonObject(
|
|
8241
|
+
SCHEDULED_TASK_METADATA_MAX_BYTES,
|
|
8242
|
+
"scheduled task metadata",
|
|
8243
|
+
);
|
|
8244
|
+
|
|
8245
|
+
function scheduledTaskAgentConfigShape(bounded: boolean) {
|
|
8246
|
+
return {
|
|
8247
|
+
prompt: bounded
|
|
8248
|
+
? scheduledTaskBoundedString(SCHEDULED_TASK_PROMPT_MAX_BYTES, "scheduled task prompt")
|
|
8249
|
+
: z.string().min(1),
|
|
8250
|
+
resources: bounded
|
|
8251
|
+
? z.array(ResourceRef).max(SCHEDULED_TASK_RESOURCE_MAX_COUNT).default([])
|
|
8252
|
+
: z.array(ResourceRef).default([]),
|
|
8253
|
+
tools: bounded
|
|
8254
|
+
? z
|
|
8255
|
+
.array(ToolRef)
|
|
8256
|
+
.max(SCHEDULED_TASK_TOOL_MAX_COUNT - 1)
|
|
8257
|
+
.default([])
|
|
8258
|
+
: z.array(ToolRef).default([]),
|
|
8259
|
+
metadata: bounded
|
|
8260
|
+
? ScheduledTaskMetadataInput.default({})
|
|
8261
|
+
: z.record(z.string(), z.unknown()).default({}),
|
|
8262
|
+
// Explicit workspace-shared OpenGeni Slack bot binding for scheduled runs.
|
|
8263
|
+
// The worker copies this non-secret pointer into session metadata; the
|
|
8264
|
+
// first-party Slack tools never fall back to a personal hosted-MCP grant.
|
|
8265
|
+
slackBotConnectionId: z.string().uuid().optional(),
|
|
8266
|
+
model: bounded
|
|
8267
|
+
? scheduledTaskBoundedString(512, "scheduled task model").optional()
|
|
8268
|
+
: z.string().min(1).optional(),
|
|
8269
|
+
reasoningEffort: ReasoningEffort.optional(),
|
|
8270
|
+
sandboxBackend: SandboxBackend.optional(),
|
|
8271
|
+
goal: GoalSpec.optional(),
|
|
8272
|
+
// Incident telemetry is the only special execution class. Omission keeps
|
|
8273
|
+
// every existing task on the byte-compatible ordinary dispatch path.
|
|
8274
|
+
executionClass: IncidentTelemetryExecutionClass.optional(),
|
|
8275
|
+
incidentTelemetryPreflight: IncidentTelemetryPreflight.optional(),
|
|
8276
|
+
// Durable task override. Scheduled dispatch is trusted to preserve this
|
|
8277
|
+
// snapshot even if the workspace/deployment policy narrows later.
|
|
8278
|
+
maxNestedAgentDepth: NestedAgentDepthValue.optional(),
|
|
8279
|
+
};
|
|
8280
|
+
}
|
|
8281
|
+
|
|
8282
|
+
function refineScheduledTaskAgentConfig(
|
|
8283
|
+
value: { executionClass?: unknown; incidentTelemetryPreflight?: unknown },
|
|
8284
|
+
context: z.RefinementCtx,
|
|
8285
|
+
): void {
|
|
8286
|
+
if (value.executionClass === "incident_telemetry" && !value.incidentTelemetryPreflight) {
|
|
8287
|
+
context.addIssue({
|
|
8288
|
+
code: "custom",
|
|
8289
|
+
path: ["incidentTelemetryPreflight"],
|
|
8290
|
+
message: "incident telemetry tasks require incidentTelemetryPreflight",
|
|
8291
|
+
});
|
|
8292
|
+
}
|
|
8293
|
+
if (value.executionClass !== "incident_telemetry" && value.incidentTelemetryPreflight) {
|
|
8294
|
+
context.addIssue({
|
|
8295
|
+
code: "custom",
|
|
8296
|
+
path: ["executionClass"],
|
|
8297
|
+
message: "incidentTelemetryPreflight requires executionClass=incident_telemetry",
|
|
8298
|
+
});
|
|
8299
|
+
}
|
|
8300
|
+
}
|
|
8301
|
+
|
|
8302
|
+
/** Storage/projection shape. Deliberately unbounded so stored rows always parse. */
|
|
8303
|
+
export const ScheduledTaskAgentConfig = /* @__PURE__ */ z
|
|
8304
|
+
.object(scheduledTaskAgentConfigShape(false))
|
|
8305
|
+
.superRefine(refineScheduledTaskAgentConfig);
|
|
6706
8306
|
export type ScheduledTaskAgentConfig = z.infer<typeof ScheduledTaskAgentConfig>;
|
|
6707
8307
|
|
|
8308
|
+
/** Ingress-bounded agent config for create/update requests. */
|
|
8309
|
+
export const ScheduledTaskAgentConfigInput = /* @__PURE__ */ z
|
|
8310
|
+
.object(scheduledTaskAgentConfigShape(true))
|
|
8311
|
+
.superRefine((value, context) => {
|
|
8312
|
+
if (scheduledTaskJsonUtf8Bytes(value) > SCHEDULED_TASK_AGENT_CONFIG_MAX_BYTES) {
|
|
8313
|
+
context.addIssue({
|
|
8314
|
+
code: "custom",
|
|
8315
|
+
message: `scheduled task agent config exceeds ${SCHEDULED_TASK_AGENT_CONFIG_MAX_BYTES} UTF-8 bytes`,
|
|
8316
|
+
});
|
|
8317
|
+
}
|
|
8318
|
+
if (
|
|
8319
|
+
scheduledOccurrencePayloadUtf8Bytes(value) >
|
|
8320
|
+
SCHEDULED_TASK_OCCURRENCE_PAYLOAD_MAX_BYTES -
|
|
8321
|
+
SCHEDULED_TASK_OCCURRENCE_PAYLOAD_INGRESS_HEADROOM_BYTES
|
|
8322
|
+
) {
|
|
8323
|
+
context.addIssue({
|
|
8324
|
+
code: "custom",
|
|
8325
|
+
message: `scheduled task prompt, resources, and tools exceed the ${SCHEDULED_TASK_OCCURRENCE_PAYLOAD_MAX_BYTES - SCHEDULED_TASK_OCCURRENCE_PAYLOAD_INGRESS_HEADROOM_BYTES} UTF-8 byte occurrence payload`,
|
|
8326
|
+
});
|
|
8327
|
+
}
|
|
8328
|
+
refineScheduledTaskAgentConfig(value, context);
|
|
8329
|
+
});
|
|
8330
|
+
export type ScheduledTaskAgentConfigInput = z.infer<typeof ScheduledTaskAgentConfigInput>;
|
|
8331
|
+
|
|
6708
8332
|
export const ScheduledTask = /* @__PURE__ */ z.object({
|
|
6709
8333
|
id: z.string().uuid(),
|
|
6710
8334
|
accountId: z.string().uuid(),
|
|
@@ -6723,6 +8347,8 @@ export const ScheduledTask = /* @__PURE__ */ z.object({
|
|
|
6723
8347
|
}),
|
|
6724
8348
|
createdByContext: TurnInitiatorContext.default({}),
|
|
6725
8349
|
personalConnections: z.array(McpPersonalConnectionSummary).default([]),
|
|
8350
|
+
authorityRevision: z.number().int().positive().default(1),
|
|
8351
|
+
executionDigest: z.string().regex(/^[0-9a-f]{64}$/u),
|
|
6726
8352
|
reusableSessionId: z.string().uuid().nullable(),
|
|
6727
8353
|
targetSessionId: z.string().uuid().nullable().default(null),
|
|
6728
8354
|
variableSetId: z.string().uuid().nullable().default(null),
|
|
@@ -6738,31 +8364,177 @@ export const ScheduledTask = /* @__PURE__ */ z.object({
|
|
|
6738
8364
|
});
|
|
6739
8365
|
export type ScheduledTask = z.infer<typeof ScheduledTask>;
|
|
6740
8366
|
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
8367
|
+
/**
|
|
8368
|
+
* Complete credential-free execution truth accepted for one scheduled agent
|
|
8369
|
+
* occurrence. Retries consume this immutable snapshot instead of a mutable
|
|
8370
|
+
* scheduled-task head.
|
|
8371
|
+
*/
|
|
8372
|
+
export const ScheduledTaskRunAcceptedExecution = /* @__PURE__ */ z
|
|
8373
|
+
.object({
|
|
8374
|
+
version: z.literal(1),
|
|
8375
|
+
task: ScheduledTask,
|
|
8376
|
+
resolvedModel: z.string().min(1),
|
|
8377
|
+
resolvedReasoningEffort: ReasoningEffort,
|
|
8378
|
+
resolvedLatencyMode: LatencyMode,
|
|
8379
|
+
resolvedSandboxBackend: SandboxBackend,
|
|
8380
|
+
resolvedSandboxOs: SandboxOs,
|
|
8381
|
+
resolvedTools: z.array(ToolRef).max(SCHEDULED_TASK_TOOL_MAX_COUNT),
|
|
8382
|
+
resolvedFirstPartyMcpTools: z.array(FirstPartyMcpToolName),
|
|
8383
|
+
resolvedFirstPartyMcpPermissions: z.array(Permission),
|
|
8384
|
+
resolvedVariableSet: z
|
|
8385
|
+
.object({
|
|
8386
|
+
id: z.string().uuid(),
|
|
8387
|
+
generation: z.number().int().positive(),
|
|
8388
|
+
})
|
|
8389
|
+
.strict()
|
|
8390
|
+
.nullable(),
|
|
8391
|
+
resolvedRig: z
|
|
8392
|
+
.object({
|
|
8393
|
+
id: z.string().uuid(),
|
|
8394
|
+
versionId: z.string().uuid(),
|
|
8395
|
+
defaultVariableSets: z
|
|
8396
|
+
.array(
|
|
8397
|
+
z
|
|
8398
|
+
.object({
|
|
8399
|
+
id: z.string().uuid(),
|
|
8400
|
+
generation: z.number().int().positive(),
|
|
8401
|
+
})
|
|
8402
|
+
.strict(),
|
|
8403
|
+
)
|
|
8404
|
+
.max(25),
|
|
8405
|
+
})
|
|
8406
|
+
.strict()
|
|
8407
|
+
.nullable(),
|
|
8408
|
+
resolvedSlackBotConnection: z
|
|
8409
|
+
.object({
|
|
8410
|
+
id: z.string().uuid(),
|
|
8411
|
+
version: z.number().int().positive(),
|
|
8412
|
+
verifiedInstallVersion: z.number().int().positive(),
|
|
8413
|
+
metadata: z
|
|
8414
|
+
.object({
|
|
8415
|
+
credentialRole: z.literal("opengeni_slack_bot"),
|
|
8416
|
+
credentialLabel: z.literal("OpenGeni Slack bot"),
|
|
8417
|
+
slackTeamId: z.string().min(1).max(64),
|
|
8418
|
+
slackTeamName: z.string().min(1).max(256),
|
|
8419
|
+
botUserId: z.string().min(1).max(64),
|
|
8420
|
+
botId: z.string().min(1).max(64),
|
|
8421
|
+
botDisplayName: z.enum(["OpenGeni", "OpenGeni Staging"]),
|
|
8422
|
+
verifiedAt: z.string().datetime({ offset: true }),
|
|
8423
|
+
})
|
|
8424
|
+
.passthrough(),
|
|
8425
|
+
})
|
|
8426
|
+
.strict()
|
|
8427
|
+
.nullable(),
|
|
8428
|
+
/**
|
|
8429
|
+
* The effective policy that an existing or already-materialized reusable
|
|
8430
|
+
* session will execute. Generated sessions carry null because their
|
|
8431
|
+
* accepted task policy is used to create the session itself.
|
|
8432
|
+
*/
|
|
8433
|
+
targetSessionExecution: z
|
|
8434
|
+
.object({
|
|
8435
|
+
sessionId: z.string().uuid(),
|
|
8436
|
+
visibility: z.enum(["user_private", "workspace_shared"]),
|
|
8437
|
+
authorityEpoch: z.number().int().positive(),
|
|
8438
|
+
model: z.string().min(1),
|
|
8439
|
+
reasoningEffort: ReasoningEffort,
|
|
8440
|
+
latencyMode: LatencyMode,
|
|
8441
|
+
tools: z.array(ToolRef).max(SCHEDULED_TASK_TOOL_MAX_COUNT),
|
|
8442
|
+
sandboxBackend: SandboxBackend,
|
|
8443
|
+
sandboxOs: SandboxOs,
|
|
8444
|
+
firstPartyMcpTools: z.array(FirstPartyMcpToolName),
|
|
8445
|
+
firstPartyMcpPermissions: z.array(Permission).nullable(),
|
|
8446
|
+
toolPolicy: SessionToolPolicy,
|
|
8447
|
+
mcpServerIds: z.array(z.string().min(1).max(256)).max(SCHEDULED_TASK_TOOL_MAX_COUNT),
|
|
8448
|
+
effectiveMcpServerIds: z
|
|
8449
|
+
.array(z.string().min(1).max(256))
|
|
8450
|
+
.max(SCHEDULED_TASK_TOOL_MAX_COUNT),
|
|
8451
|
+
toolPolicyVersion: z.number().int().nonnegative(),
|
|
8452
|
+
variableSetId: z.string().uuid().nullable(),
|
|
8453
|
+
variableSetGeneration: z.number().int().positive().nullable(),
|
|
8454
|
+
rigId: z.string().uuid().nullable(),
|
|
8455
|
+
rigVersionId: z.string().uuid().nullable(),
|
|
8456
|
+
rigDefaultVariableSets: z
|
|
8457
|
+
.array(
|
|
8458
|
+
z
|
|
8459
|
+
.object({
|
|
8460
|
+
id: z.string().uuid(),
|
|
8461
|
+
generation: z.number().int().positive(),
|
|
8462
|
+
})
|
|
8463
|
+
.strict(),
|
|
8464
|
+
)
|
|
8465
|
+
.max(25),
|
|
8466
|
+
maxNestedAgentDepthOverride: NestedAgentDepthValue.nullable(),
|
|
8467
|
+
effectiveMaxNestedAgentDepth: NestedAgentDepthValue,
|
|
8468
|
+
})
|
|
8469
|
+
.strict()
|
|
8470
|
+
.nullable(),
|
|
8471
|
+
generatedSessionBinding: z
|
|
8472
|
+
.object({
|
|
8473
|
+
createIdempotencyKey: z.string().min(1).max(512),
|
|
8474
|
+
effectiveMaxNestedAgentDepth: NestedAgentDepthValue,
|
|
8475
|
+
nestedAgentDepthPolicySource: NestedAgentDepthPolicySource,
|
|
8476
|
+
codexCompactionMode: CodexCompactionMode,
|
|
8477
|
+
})
|
|
8478
|
+
.strict()
|
|
8479
|
+
.nullable(),
|
|
8480
|
+
personalConnectionDelegations: McpPersonalConnectionDelegations,
|
|
8481
|
+
personalResourceAuthoritySubjectId: z.string().min(1).nullable(),
|
|
8482
|
+
/** One accepted human principal for every resource-bearing scheduled run. */
|
|
8483
|
+
causalHumanSubjectId: z.string().min(1).nullable().default(null),
|
|
8484
|
+
/** Exact revision-bound human membership proof; never inferred at execution. */
|
|
8485
|
+
causalHumanAuthority: z
|
|
8486
|
+
.object({
|
|
8487
|
+
subjectId: z.string().min(1),
|
|
8488
|
+
organizationMembershipId: z.string().uuid(),
|
|
8489
|
+
membershipAuthorizationRevision: z.number().int().positive(),
|
|
8490
|
+
})
|
|
8491
|
+
.strict()
|
|
8492
|
+
.nullable()
|
|
8493
|
+
.default(null),
|
|
8494
|
+
xaiProviderAccountAuthoritySnapshot: XaiProviderAccountAuthoritySnapshotV1,
|
|
8495
|
+
xaiAuthoritySubjectId: z.string().min(1).nullable(),
|
|
8496
|
+
connectionAuthoritySubjectId: z.string().min(1).nullable(),
|
|
8497
|
+
triggerInitiator: TurnInitiator,
|
|
8498
|
+
agentRunUsageIdempotencyKey: z.string().min(1).max(512).nullable(),
|
|
8499
|
+
incidentPreflightRequired: z.boolean(),
|
|
8500
|
+
alertOccurrenceLabels: z.record(z.string(), z.string()).nullable(),
|
|
8501
|
+
})
|
|
8502
|
+
.strict()
|
|
8503
|
+
.superRefine((value, context) => {
|
|
8504
|
+
if (scheduledTaskJsonUtf8Bytes(value) > SCHEDULED_TASK_ACCEPTED_EXECUTION_MAX_BYTES) {
|
|
8505
|
+
context.addIssue({
|
|
8506
|
+
code: "custom",
|
|
8507
|
+
message: `scheduled accepted execution exceeds ${SCHEDULED_TASK_ACCEPTED_EXECUTION_MAX_BYTES} UTF-8 bytes`,
|
|
8508
|
+
});
|
|
8509
|
+
}
|
|
8510
|
+
});
|
|
8511
|
+
export type ScheduledTaskRunAcceptedExecution = z.infer<typeof ScheduledTaskRunAcceptedExecution>;
|
|
8512
|
+
|
|
8513
|
+
export const KnowledgeSourceSyncFailure = /* @__PURE__ */ z.object({
|
|
8514
|
+
externalObjectId: KnowledgeSourceSyncSubject,
|
|
8515
|
+
code: z.enum([
|
|
8516
|
+
"authority_changed",
|
|
8517
|
+
"connection_reconnect_required",
|
|
8518
|
+
"provider_unavailable",
|
|
8519
|
+
"provider_rejected",
|
|
8520
|
+
"provider_payload_invalid",
|
|
8521
|
+
"content_unsupported",
|
|
8522
|
+
"content_too_large",
|
|
8523
|
+
"resource_limit",
|
|
8524
|
+
"item_processing_failed",
|
|
8525
|
+
"indexing_failed",
|
|
8526
|
+
"internal_failure",
|
|
8527
|
+
]),
|
|
8528
|
+
retryable: z.boolean(),
|
|
8529
|
+
message: z.string().min(1).max(1000),
|
|
8530
|
+
});
|
|
8531
|
+
export type KnowledgeSourceSyncFailure = z.infer<typeof KnowledgeSourceSyncFailure>;
|
|
8532
|
+
|
|
8533
|
+
export const KnowledgeSourceSyncRunSummary = /* @__PURE__ */ z.object({
|
|
8534
|
+
phase: z
|
|
8535
|
+
.enum(["queued", "inventory", "transfer", "index", "checkpoint", "completed", "failed"])
|
|
8536
|
+
.default("queued"),
|
|
8537
|
+
scanned: KnowledgeSourceSyncZeroInteger,
|
|
6766
8538
|
imported: KnowledgeSourceSyncZeroInteger,
|
|
6767
8539
|
unchanged: KnowledgeSourceSyncZeroInteger,
|
|
6768
8540
|
skipped: KnowledgeSourceSyncZeroInteger,
|
|
@@ -6788,6 +8560,12 @@ export const ScheduledTaskRun = /* @__PURE__ */ z.object({
|
|
|
6788
8560
|
accountId: z.string().uuid(),
|
|
6789
8561
|
workspaceId: z.string().uuid(),
|
|
6790
8562
|
taskId: z.string().uuid(),
|
|
8563
|
+
taskAuthorityRevision: z.number().int().positive().nullable().default(null),
|
|
8564
|
+
taskExecutionDigest: z
|
|
8565
|
+
.string()
|
|
8566
|
+
.regex(/^[0-9a-f]{64}$/u)
|
|
8567
|
+
.nullable()
|
|
8568
|
+
.default(null),
|
|
6791
8569
|
status: ScheduledTaskRunStatus,
|
|
6792
8570
|
triggerType: ScheduledTaskTriggerType,
|
|
6793
8571
|
scheduledAt: z.string().nullable(),
|
|
@@ -6805,7 +8583,7 @@ export const ScheduledTaskRun = /* @__PURE__ */ z.object({
|
|
|
6805
8583
|
export type ScheduledTaskRun = z.infer<typeof ScheduledTaskRun>;
|
|
6806
8584
|
|
|
6807
8585
|
const CreateAgentScheduledTaskRequest = /* @__PURE__ */ withVariableSetIdAlias({
|
|
6808
|
-
name:
|
|
8586
|
+
name: ScheduledTaskNameInput,
|
|
6809
8587
|
schedule: ScheduledTaskScheduleSpec,
|
|
6810
8588
|
action: z
|
|
6811
8589
|
.object({ kind: z.literal("agent_turn") })
|
|
@@ -6814,13 +8592,14 @@ const CreateAgentScheduledTaskRequest = /* @__PURE__ */ withVariableSetIdAlias({
|
|
|
6814
8592
|
runMode: ScheduledTaskRunMode.default("new_session_per_run"),
|
|
6815
8593
|
overlapPolicy: ScheduledTaskOverlapPolicy.default("allow_concurrent"),
|
|
6816
8594
|
targetSessionId: z.string().uuid().nullable().optional(),
|
|
6817
|
-
|
|
8595
|
+
connectionAuthorities: McpConnectionAuthoritySelections.default([]),
|
|
8596
|
+
agentConfig: ScheduledTaskAgentConfigInput,
|
|
6818
8597
|
status: ScheduledTaskStatus.default("active"),
|
|
6819
8598
|
variableSetId: z.string().uuid().nullable().optional(),
|
|
6820
8599
|
environmentId: z.string().uuid().nullable().optional(),
|
|
6821
8600
|
// The rig each run binds to (M3); its active version is resolved per fire.
|
|
6822
8601
|
rigId: z.string().uuid().nullable().optional(),
|
|
6823
|
-
metadata:
|
|
8602
|
+
metadata: ScheduledTaskMetadataInput.default({}),
|
|
6824
8603
|
}).superRefine((value, context) => {
|
|
6825
8604
|
if (value.runMode === "existing_session" && !value.targetSessionId) {
|
|
6826
8605
|
context.addIssue({
|
|
@@ -6868,6 +8647,7 @@ const CreateKnowledgeSourceSyncScheduledTaskRequest = /* @__PURE__ */ z
|
|
|
6868
8647
|
variableSetId: null,
|
|
6869
8648
|
environmentId: null,
|
|
6870
8649
|
rigId: null,
|
|
8650
|
+
connectionAuthorities: [],
|
|
6871
8651
|
}));
|
|
6872
8652
|
|
|
6873
8653
|
export const CreateScheduledTaskRequest = /* @__PURE__ */ z.union([
|
|
@@ -6876,59 +8656,393 @@ export const CreateScheduledTaskRequest = /* @__PURE__ */ z.union([
|
|
|
6876
8656
|
]);
|
|
6877
8657
|
export type CreateScheduledTaskRequest = z.infer<typeof CreateScheduledTaskRequest>;
|
|
6878
8658
|
|
|
6879
|
-
export const UpdateScheduledTaskRequest =
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
8659
|
+
export const UpdateScheduledTaskRequest = /* @__PURE__ */ withVariableSetIdAlias({
|
|
8660
|
+
name: ScheduledTaskNameInput.optional(),
|
|
8661
|
+
schedule: ScheduledTaskScheduleSpec.optional(),
|
|
8662
|
+
runMode: ScheduledTaskRunMode.optional(),
|
|
8663
|
+
overlapPolicy: ScheduledTaskOverlapPolicy.optional(),
|
|
8664
|
+
action: ScheduledTaskAction.optional(),
|
|
8665
|
+
targetSessionId: z.string().uuid().nullable().optional(),
|
|
8666
|
+
connectionAuthorities: McpConnectionAuthoritySelections.optional(),
|
|
8667
|
+
agentConfig: ScheduledTaskAgentConfigInput.optional(),
|
|
8668
|
+
status: ScheduledTaskStatus.optional(),
|
|
8669
|
+
variableSetId: z.string().uuid().nullable().optional(),
|
|
8670
|
+
environmentId: z.string().uuid().nullable().optional(),
|
|
8671
|
+
// The rig each run binds to (M3); null clears it. Its active version is
|
|
8672
|
+
// resolved per fire, so an update takes effect on the next dispatch.
|
|
8673
|
+
rigId: z.string().uuid().nullable().optional(),
|
|
8674
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
8675
|
+
}).superRefine((value, context) => {
|
|
8676
|
+
if (value.targetSessionId && value.runMode && value.runMode !== "existing_session") {
|
|
8677
|
+
context.addIssue({
|
|
8678
|
+
code: "custom",
|
|
8679
|
+
path: ["targetSessionId"],
|
|
8680
|
+
message: "targetSessionId requires runMode=existing_session",
|
|
8681
|
+
});
|
|
8682
|
+
}
|
|
8683
|
+
if (value.runMode === "existing_session" && value.targetSessionId === null) {
|
|
8684
|
+
context.addIssue({
|
|
8685
|
+
code: "custom",
|
|
8686
|
+
path: ["targetSessionId"],
|
|
8687
|
+
message: "targetSessionId cannot be null when runMode=existing_session",
|
|
8688
|
+
});
|
|
8689
|
+
}
|
|
8690
|
+
if (
|
|
8691
|
+
value.agentConfig?.goal &&
|
|
8692
|
+
(value.runMode === "existing_session" || Boolean(value.targetSessionId))
|
|
8693
|
+
) {
|
|
8694
|
+
context.addIssue({
|
|
8695
|
+
code: "custom",
|
|
8696
|
+
path: ["agentConfig", "goal"],
|
|
8697
|
+
message: "agentConfig.goal cannot be used with an existing-session target",
|
|
8698
|
+
});
|
|
8699
|
+
}
|
|
8700
|
+
});
|
|
8701
|
+
export type UpdateScheduledTaskRequest = z.infer<typeof UpdateScheduledTaskRequest>;
|
|
8702
|
+
|
|
8703
|
+
/**
|
|
8704
|
+
* Manual-trigger body. `triggerId` is a client-supplied idempotency token: a
|
|
8705
|
+
* retried trigger that reuses the same token charges once and starts one run.
|
|
8706
|
+
* Omitting it makes each call a distinct trigger (the server mints a token).
|
|
8707
|
+
*/
|
|
8708
|
+
export const TriggerScheduledTaskRequest = z.object({
|
|
8709
|
+
triggerId: z.string().min(1).max(128).optional(),
|
|
8710
|
+
});
|
|
8711
|
+
export type TriggerScheduledTaskRequest = z.infer<typeof TriggerScheduledTaskRequest>;
|
|
8712
|
+
|
|
8713
|
+
// ============ Event-triggered automations ============
|
|
8714
|
+
|
|
8715
|
+
export const AUTOMATION_WEBHOOK_MAX_BYTES = 2 * 1024 * 1024;
|
|
8716
|
+
export const AUTOMATION_EVENT_PAYLOAD_MAX_BYTES = 256 * 1024;
|
|
8717
|
+
export const AUTOMATION_SESSION_TEMPLATE_MAX_BYTES = 512 * 1024;
|
|
8718
|
+
export const AUTOMATION_MAX_MATCHED_TRIGGERS = 32;
|
|
8719
|
+
|
|
8720
|
+
const AutomationBoundedJson = z.record(z.string(), z.unknown()).superRefine((value, context) => {
|
|
8721
|
+
let bytes = Number.POSITIVE_INFINITY;
|
|
8722
|
+
try {
|
|
8723
|
+
bytes = new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
8724
|
+
} catch {
|
|
8725
|
+
// The shared JSON/protocol boundary reports the exact runtime path later;
|
|
8726
|
+
// this public ingress still fails closed on an unserializable value.
|
|
8727
|
+
}
|
|
8728
|
+
if (bytes > AUTOMATION_EVENT_PAYLOAD_MAX_BYTES) {
|
|
8729
|
+
context.addIssue({
|
|
8730
|
+
code: "custom",
|
|
8731
|
+
message: `automation JSON exceeds ${AUTOMATION_EVENT_PAYLOAD_MAX_BYTES} UTF-8 bytes`,
|
|
8732
|
+
});
|
|
8733
|
+
}
|
|
8734
|
+
});
|
|
8735
|
+
|
|
8736
|
+
export const AutomationAdapterId = z
|
|
8737
|
+
.string()
|
|
8738
|
+
.min(1)
|
|
8739
|
+
.max(128)
|
|
8740
|
+
.regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/);
|
|
8741
|
+
export type AutomationAdapterId = z.infer<typeof AutomationAdapterId>;
|
|
8742
|
+
|
|
8743
|
+
export const AutomationSourceStatus = z.enum(["active", "disabled"]);
|
|
8744
|
+
export type AutomationSourceStatus = z.infer<typeof AutomationSourceStatus>;
|
|
8745
|
+
|
|
8746
|
+
export const AutomationTriggerStatus = z.enum(["active", "paused", "disabled"]);
|
|
8747
|
+
export type AutomationTriggerStatus = z.infer<typeof AutomationTriggerStatus>;
|
|
8748
|
+
|
|
8749
|
+
export const AutomationRunStatus = z.enum([
|
|
8750
|
+
"queued",
|
|
8751
|
+
"dispatching",
|
|
8752
|
+
"dispatched",
|
|
8753
|
+
"skipped",
|
|
8754
|
+
"failed",
|
|
8755
|
+
]);
|
|
8756
|
+
export type AutomationRunStatus = z.infer<typeof AutomationRunStatus>;
|
|
8757
|
+
|
|
8758
|
+
export const AutomationEventStatus = z.enum(["accepted", "ignored", "failed"]);
|
|
8759
|
+
export type AutomationEventStatus = z.infer<typeof AutomationEventStatus>;
|
|
8760
|
+
|
|
8761
|
+
export const SignedJsonAutomationEnvelope = z
|
|
8762
|
+
.object({
|
|
8763
|
+
id: z.string().trim().min(1).max(1024).optional(),
|
|
8764
|
+
type: z.string().trim().min(1).max(256),
|
|
8765
|
+
occurrenceKey: z.string().trim().min(1).max(1024).optional(),
|
|
8766
|
+
occurredAt: z.string().datetime({ offset: true }).nullable().optional(),
|
|
8767
|
+
subject: z.string().trim().min(1).max(512).nullable().optional(),
|
|
8768
|
+
resource: z.string().trim().min(1).max(1024).nullable().optional(),
|
|
8769
|
+
data: z.record(z.string(), z.unknown()).default({}),
|
|
8770
|
+
})
|
|
8771
|
+
.strict();
|
|
8772
|
+
export type SignedJsonAutomationEnvelope = z.infer<typeof SignedJsonAutomationEnvelope>;
|
|
8773
|
+
|
|
8774
|
+
const AutomationSessionSkill = z
|
|
8775
|
+
.object({
|
|
8776
|
+
name: z
|
|
8777
|
+
.string()
|
|
8778
|
+
.min(1)
|
|
8779
|
+
.max(64)
|
|
8780
|
+
.regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/),
|
|
8781
|
+
description: z.string().min(1).max(2048).optional(),
|
|
8782
|
+
files: z
|
|
8783
|
+
.array(
|
|
8784
|
+
z.object({
|
|
8785
|
+
path: z
|
|
8786
|
+
.string()
|
|
8787
|
+
.min(1)
|
|
8788
|
+
.max(512)
|
|
8789
|
+
.refine(
|
|
8790
|
+
(path) =>
|
|
8791
|
+
!path.startsWith("/") &&
|
|
8792
|
+
!path.includes("\\") &&
|
|
8793
|
+
path
|
|
8794
|
+
.split("/")
|
|
8795
|
+
.every((segment) => segment.length > 0 && segment !== "." && segment !== ".."),
|
|
8796
|
+
"automation skill file path must be a safe relative POSIX path",
|
|
8797
|
+
),
|
|
8798
|
+
content: z.string().max(256 * 1024),
|
|
8799
|
+
}),
|
|
8800
|
+
)
|
|
8801
|
+
.min(1)
|
|
8802
|
+
.max(64),
|
|
8803
|
+
})
|
|
8804
|
+
.superRefine((skill, context) => {
|
|
8805
|
+
if (!skill.files.some((file) => file.path === "SKILL.md")) {
|
|
6897
8806
|
context.addIssue({
|
|
6898
8807
|
code: "custom",
|
|
6899
|
-
path: ["
|
|
6900
|
-
message: "
|
|
8808
|
+
path: ["files"],
|
|
8809
|
+
message: "automation skill must include a top-level SKILL.md file",
|
|
6901
8810
|
});
|
|
6902
8811
|
}
|
|
6903
|
-
|
|
8812
|
+
});
|
|
8813
|
+
|
|
8814
|
+
export const AutomationSessionTemplate = z
|
|
8815
|
+
.object({
|
|
8816
|
+
prompt: z
|
|
8817
|
+
.string()
|
|
8818
|
+
.trim()
|
|
8819
|
+
.min(1)
|
|
8820
|
+
.max(64 * 1024),
|
|
8821
|
+
instructions: z
|
|
8822
|
+
.string()
|
|
8823
|
+
.trim()
|
|
8824
|
+
.min(1)
|
|
8825
|
+
.max(64 * 1024)
|
|
8826
|
+
.nullable()
|
|
8827
|
+
.default(null),
|
|
8828
|
+
resources: z.array(ResourceRef).max(100).default([]),
|
|
8829
|
+
skills: z.array(AutomationSessionSkill).max(32).default([]),
|
|
8830
|
+
tools: z.array(ToolRef).max(128).default([]),
|
|
8831
|
+
firstPartyMcpTools: z.array(FirstPartyMcpToolName).max(128).default([]),
|
|
8832
|
+
firstPartyMcpPermissions: z.array(Permission).max(128).default([]),
|
|
8833
|
+
model: z.string().trim().min(1).max(512).nullable().default(null),
|
|
8834
|
+
reasoningEffort: ReasoningEffort.nullable().default(null),
|
|
8835
|
+
sandboxBackend: SandboxBackend.nullable().default(null),
|
|
8836
|
+
policyRole: z.string().trim().min(1).max(128).nullable().default(null),
|
|
8837
|
+
metadata: AutomationBoundedJson.default({}),
|
|
8838
|
+
})
|
|
8839
|
+
.strict()
|
|
8840
|
+
.superRefine((value, context) => {
|
|
8841
|
+
let bytes = Number.POSITIVE_INFINITY;
|
|
8842
|
+
try {
|
|
8843
|
+
bytes = new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
8844
|
+
} catch {
|
|
8845
|
+
// Fail through the size issue below.
|
|
8846
|
+
}
|
|
8847
|
+
if (bytes > AUTOMATION_SESSION_TEMPLATE_MAX_BYTES) {
|
|
6904
8848
|
context.addIssue({
|
|
6905
8849
|
code: "custom",
|
|
6906
|
-
|
|
6907
|
-
message: "targetSessionId cannot be null when runMode=existing_session",
|
|
8850
|
+
message: `automation session template exceeds ${AUTOMATION_SESSION_TEMPLATE_MAX_BYTES} UTF-8 bytes`,
|
|
6908
8851
|
});
|
|
6909
8852
|
}
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
8853
|
+
});
|
|
8854
|
+
export type AutomationSessionTemplate = z.infer<typeof AutomationSessionTemplate>;
|
|
8855
|
+
|
|
8856
|
+
export const AutomationNormalizedEvent = z
|
|
8857
|
+
.object({
|
|
8858
|
+
adapterId: AutomationAdapterId,
|
|
8859
|
+
eventType: z.string().trim().min(1).max(256),
|
|
8860
|
+
occurrenceKey: z.string().trim().min(1).max(1024),
|
|
8861
|
+
occurredAt: z.string().datetime({ offset: true }).nullable().default(null),
|
|
8862
|
+
subject: z.string().trim().min(1).max(512).nullable().default(null),
|
|
8863
|
+
resource: z.string().trim().min(1).max(1024).nullable().default(null),
|
|
8864
|
+
payload: AutomationBoundedJson,
|
|
8865
|
+
})
|
|
8866
|
+
.strict();
|
|
8867
|
+
export type AutomationNormalizedEvent = z.infer<typeof AutomationNormalizedEvent>;
|
|
8868
|
+
|
|
8869
|
+
export const AutomationAcceptedExecution = z
|
|
8870
|
+
.object({
|
|
8871
|
+
version: z.literal(1),
|
|
8872
|
+
accountId: z.string().uuid(),
|
|
8873
|
+
workspaceId: z.string().uuid(),
|
|
8874
|
+
sourceId: z.string().uuid(),
|
|
8875
|
+
sourceVersion: z.number().int().positive(),
|
|
8876
|
+
triggerId: z.string().uuid(),
|
|
8877
|
+
triggerRevision: z.number().int().positive(),
|
|
8878
|
+
eventId: z.string().uuid(),
|
|
8879
|
+
adapterId: AutomationAdapterId,
|
|
8880
|
+
occurrenceKey: z.string().min(1).max(1024),
|
|
8881
|
+
initialMessage: z
|
|
8882
|
+
.string()
|
|
8883
|
+
.min(1)
|
|
8884
|
+
.max(256 * 1024),
|
|
8885
|
+
sessionTemplate: AutomationSessionTemplate,
|
|
8886
|
+
serviceSubjectId: z.string().min(1).max(512),
|
|
8887
|
+
serviceLabel: z.string().min(1).max(200),
|
|
8888
|
+
provenance: AutomationBoundedJson,
|
|
8889
|
+
})
|
|
8890
|
+
.strict();
|
|
8891
|
+
export type AutomationAcceptedExecution = z.infer<typeof AutomationAcceptedExecution>;
|
|
8892
|
+
|
|
8893
|
+
export const CreateAutomationSourceRequest = z
|
|
8894
|
+
.object({
|
|
8895
|
+
name: z.string().trim().min(1).max(200),
|
|
8896
|
+
adapterId: AutomationAdapterId.default("signed-json.v1"),
|
|
8897
|
+
webhookSecret: z.string().min(16).max(65_536),
|
|
8898
|
+
configuration: AutomationBoundedJson.default({}),
|
|
8899
|
+
})
|
|
8900
|
+
.strict();
|
|
8901
|
+
export type CreateAutomationSourceRequest = z.infer<typeof CreateAutomationSourceRequest>;
|
|
8902
|
+
|
|
8903
|
+
export const UpdateAutomationSourceRequest = z
|
|
8904
|
+
.object({
|
|
8905
|
+
name: z.string().trim().min(1).max(200).optional(),
|
|
8906
|
+
webhookSecret: z.string().min(16).max(65_536).optional(),
|
|
8907
|
+
configuration: AutomationBoundedJson.optional(),
|
|
8908
|
+
status: AutomationSourceStatus.optional(),
|
|
8909
|
+
})
|
|
8910
|
+
.strict()
|
|
8911
|
+
.refine((value) => Object.keys(value).length > 0, "automation source update is empty");
|
|
8912
|
+
export type UpdateAutomationSourceRequest = z.infer<typeof UpdateAutomationSourceRequest>;
|
|
8913
|
+
|
|
8914
|
+
export const AutomationSource = z.object({
|
|
8915
|
+
id: z.string().uuid(),
|
|
8916
|
+
accountId: z.string().uuid(),
|
|
8917
|
+
workspaceId: z.string().uuid(),
|
|
8918
|
+
name: z.string(),
|
|
8919
|
+
adapterId: AutomationAdapterId,
|
|
8920
|
+
configuration: z.record(z.string(), z.unknown()),
|
|
8921
|
+
status: AutomationSourceStatus,
|
|
8922
|
+
version: z.number().int().positive(),
|
|
8923
|
+
packInstallationId: z.string().uuid().nullable(),
|
|
8924
|
+
packConnectorId: z.string().min(1).max(128).nullable(),
|
|
8925
|
+
hasWebhookSecret: z.boolean(),
|
|
8926
|
+
webhookPath: z.string().min(1),
|
|
8927
|
+
createdBySubjectId: z.string(),
|
|
8928
|
+
createdAt: z.string(),
|
|
8929
|
+
updatedAt: z.string(),
|
|
8930
|
+
});
|
|
8931
|
+
export type AutomationSource = z.infer<typeof AutomationSource>;
|
|
8932
|
+
|
|
8933
|
+
export const CreateAutomationTriggerRequest = z
|
|
8934
|
+
.object({
|
|
8935
|
+
sourceId: z.string().uuid(),
|
|
8936
|
+
name: z.string().trim().min(1).max(200),
|
|
8937
|
+
eventTypes: z.array(z.string().trim().min(1).max(256)).min(1).max(64),
|
|
8938
|
+
configuration: AutomationBoundedJson.default({}),
|
|
8939
|
+
parameters: AutomationBoundedJson.default({}),
|
|
8940
|
+
sessionTemplate: AutomationSessionTemplate,
|
|
8941
|
+
status: AutomationTriggerStatus.default("active"),
|
|
8942
|
+
packInstallationId: z.string().uuid().nullable().default(null),
|
|
8943
|
+
packTemplateId: z.string().trim().min(1).max(128).nullable().default(null),
|
|
8944
|
+
})
|
|
8945
|
+
.strict()
|
|
8946
|
+
.superRefine((value, context) => {
|
|
8947
|
+
if ((value.packInstallationId === null) !== (value.packTemplateId === null)) {
|
|
6914
8948
|
context.addIssue({
|
|
6915
8949
|
code: "custom",
|
|
6916
|
-
path: ["
|
|
6917
|
-
message: "
|
|
8950
|
+
path: ["packTemplateId"],
|
|
8951
|
+
message: "packInstallationId and packTemplateId must be supplied together",
|
|
6918
8952
|
});
|
|
6919
8953
|
}
|
|
6920
8954
|
});
|
|
6921
|
-
export type
|
|
8955
|
+
export type CreateAutomationTriggerRequest = z.infer<typeof CreateAutomationTriggerRequest>;
|
|
6922
8956
|
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
8957
|
+
export const UpdateAutomationTriggerRequest = z
|
|
8958
|
+
.object({
|
|
8959
|
+
expectedRevision: z.number().int().positive(),
|
|
8960
|
+
name: z.string().trim().min(1).max(200).optional(),
|
|
8961
|
+
eventTypes: z.array(z.string().trim().min(1).max(256)).min(1).max(64).optional(),
|
|
8962
|
+
configuration: AutomationBoundedJson.optional(),
|
|
8963
|
+
parameters: AutomationBoundedJson.optional(),
|
|
8964
|
+
sessionTemplate: AutomationSessionTemplate.optional(),
|
|
8965
|
+
status: AutomationTriggerStatus.optional(),
|
|
8966
|
+
})
|
|
8967
|
+
.strict()
|
|
8968
|
+
.refine((value) => Object.keys(value).some((key) => key !== "expectedRevision"), {
|
|
8969
|
+
message: "automation trigger update is empty",
|
|
8970
|
+
});
|
|
8971
|
+
export type UpdateAutomationTriggerRequest = z.infer<typeof UpdateAutomationTriggerRequest>;
|
|
8972
|
+
|
|
8973
|
+
export const AutomationTrigger = z.object({
|
|
8974
|
+
id: z.string().uuid(),
|
|
8975
|
+
accountId: z.string().uuid(),
|
|
8976
|
+
workspaceId: z.string().uuid(),
|
|
8977
|
+
sourceId: z.string().uuid(),
|
|
8978
|
+
name: z.string(),
|
|
8979
|
+
adapterId: AutomationAdapterId,
|
|
8980
|
+
eventTypes: z.array(z.string()),
|
|
8981
|
+
configuration: z.record(z.string(), z.unknown()),
|
|
8982
|
+
parameters: z.record(z.string(), z.unknown()),
|
|
8983
|
+
sessionTemplate: AutomationSessionTemplate,
|
|
8984
|
+
status: AutomationTriggerStatus,
|
|
8985
|
+
revision: z.number().int().positive(),
|
|
8986
|
+
packInstallationId: z.string().uuid().nullable(),
|
|
8987
|
+
packTemplateId: z.string().nullable(),
|
|
8988
|
+
createdBySubjectId: z.string(),
|
|
8989
|
+
createdAt: z.string(),
|
|
8990
|
+
updatedAt: z.string(),
|
|
6930
8991
|
});
|
|
6931
|
-
export type
|
|
8992
|
+
export type AutomationTrigger = z.infer<typeof AutomationTrigger>;
|
|
8993
|
+
|
|
8994
|
+
export const AutomationRun = z.object({
|
|
8995
|
+
id: z.string().uuid(),
|
|
8996
|
+
accountId: z.string().uuid(),
|
|
8997
|
+
workspaceId: z.string().uuid(),
|
|
8998
|
+
sourceId: z.string().uuid(),
|
|
8999
|
+
triggerId: z.string().uuid(),
|
|
9000
|
+
triggerRevision: z.number().int().positive(),
|
|
9001
|
+
eventId: z.string().uuid(),
|
|
9002
|
+
occurrenceKey: z.string(),
|
|
9003
|
+
status: AutomationRunStatus,
|
|
9004
|
+
sessionId: z.string().uuid().nullable(),
|
|
9005
|
+
errorCode: z.string().nullable(),
|
|
9006
|
+
createdAt: z.string(),
|
|
9007
|
+
updatedAt: z.string(),
|
|
9008
|
+
});
|
|
9009
|
+
export type AutomationRun = z.infer<typeof AutomationRun>;
|
|
9010
|
+
|
|
9011
|
+
export const AutomationWebhookResult = z.object({
|
|
9012
|
+
accepted: z.boolean(),
|
|
9013
|
+
duplicate: z.boolean(),
|
|
9014
|
+
ignoredReason: z.string().nullable(),
|
|
9015
|
+
eventId: z.string().uuid().nullable(),
|
|
9016
|
+
runIds: z.array(z.string().uuid()),
|
|
9017
|
+
});
|
|
9018
|
+
export type AutomationWebhookResult = z.infer<typeof AutomationWebhookResult>;
|
|
9019
|
+
|
|
9020
|
+
export const TriggerAutomationManuallyRequest = z
|
|
9021
|
+
.object({
|
|
9022
|
+
deliveryId: z.string().trim().min(1).max(512).optional(),
|
|
9023
|
+
eventType: z.string().trim().min(1).max(256),
|
|
9024
|
+
occurrenceKey: z.string().trim().min(1).max(1024),
|
|
9025
|
+
payload: AutomationBoundedJson.default({}),
|
|
9026
|
+
occurredAt: z.string().datetime({ offset: true }).nullable().default(null),
|
|
9027
|
+
subject: z.string().trim().min(1).max(512).nullable().default(null),
|
|
9028
|
+
resource: z.string().trim().min(1).max(1024).nullable().default(null),
|
|
9029
|
+
})
|
|
9030
|
+
.strict();
|
|
9031
|
+
export type TriggerAutomationManuallyRequest = z.infer<typeof TriggerAutomationManuallyRequest>;
|
|
9032
|
+
|
|
9033
|
+
export const CapabilityPackAutomationTemplate = z
|
|
9034
|
+
.object({
|
|
9035
|
+
id: z.string().min(1).max(128),
|
|
9036
|
+
name: z.string().min(1).max(200),
|
|
9037
|
+
description: z.string().min(1).max(4096),
|
|
9038
|
+
adapterId: AutomationAdapterId,
|
|
9039
|
+
eventTypes: z.array(z.string().min(1).max(256)).min(1).max(64),
|
|
9040
|
+
sessionTemplate: AutomationSessionTemplate,
|
|
9041
|
+
configuration: AutomationBoundedJson.default({}),
|
|
9042
|
+
connectionRequirement: z.string().min(1).max(128).nullable().default(null),
|
|
9043
|
+
})
|
|
9044
|
+
.strict();
|
|
9045
|
+
export type CapabilityPackAutomationTemplate = z.infer<typeof CapabilityPackAutomationTemplate>;
|
|
6932
9046
|
|
|
6933
9047
|
export const CapabilityPackConnectorAuthModel = z.enum([
|
|
6934
9048
|
"oauth2_authorization_code_pkce",
|
|
@@ -7235,6 +9349,7 @@ export const CapabilityPack = z.preprocess(
|
|
|
7235
9349
|
connectors: z.array(CapabilityPackConnector).default([]),
|
|
7236
9350
|
knowledge: z.array(CapabilityPackKnowledge).default([]),
|
|
7237
9351
|
scheduledTaskTemplates: z.array(CapabilityPackScheduledTaskTemplate).default([]),
|
|
9352
|
+
automationTemplates: z.array(CapabilityPackAutomationTemplate).max(64).optional(),
|
|
7238
9353
|
variableSet: CapabilityPackVariableSet.optional(),
|
|
7239
9354
|
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
7240
9355
|
})
|
|
@@ -7261,6 +9376,17 @@ export const CapabilityPack = z.preprocess(
|
|
|
7261
9376
|
}
|
|
7262
9377
|
componentKeys.add(key);
|
|
7263
9378
|
});
|
|
9379
|
+
const automationTemplateIds = new Set<string>();
|
|
9380
|
+
pack.automationTemplates?.forEach((template, index) => {
|
|
9381
|
+
if (automationTemplateIds.has(template.id)) {
|
|
9382
|
+
ctx.addIssue({
|
|
9383
|
+
code: "custom",
|
|
9384
|
+
message: `duplicate Pack automation template id: ${template.id}`,
|
|
9385
|
+
path: ["automationTemplates", index, "id"],
|
|
9386
|
+
});
|
|
9387
|
+
}
|
|
9388
|
+
automationTemplateIds.add(template.id);
|
|
9389
|
+
});
|
|
7264
9390
|
if (!pack.sandboxProviderImages?.modal) {
|
|
7265
9391
|
return;
|
|
7266
9392
|
}
|
|
@@ -7326,6 +9452,204 @@ export const PackInstallation = z.object({
|
|
|
7326
9452
|
});
|
|
7327
9453
|
export type PackInstallation = z.infer<typeof PackInstallation>;
|
|
7328
9454
|
|
|
9455
|
+
// ============ OpenGeni Review Bot — provider-neutral pull-request review automation ============
|
|
9456
|
+
|
|
9457
|
+
export const OPENGENI_PR_REVIEW_PACK_ID = "pr-review" as const;
|
|
9458
|
+
export const OPENGENI_PR_REVIEW_SESSION_ROLE = "pull_request_review" as const;
|
|
9459
|
+
|
|
9460
|
+
export const PrReviewProvider = GitCredentialProvider;
|
|
9461
|
+
export type PrReviewProvider = z.infer<typeof PrReviewProvider>;
|
|
9462
|
+
|
|
9463
|
+
export const PrReviewCredentialKind = /* @__PURE__ */ z.enum(["github_app", "provider_token"]);
|
|
9464
|
+
export type PrReviewCredentialKind = z.infer<typeof PrReviewCredentialKind>;
|
|
9465
|
+
|
|
9466
|
+
export const PrReviewWebhookAuthKind = /* @__PURE__ */ z.enum([
|
|
9467
|
+
"hmac_sha256",
|
|
9468
|
+
"shared_token",
|
|
9469
|
+
"basic",
|
|
9470
|
+
]);
|
|
9471
|
+
export type PrReviewWebhookAuthKind = z.infer<typeof PrReviewWebhookAuthKind>;
|
|
9472
|
+
|
|
9473
|
+
const PrReviewSecretInput = /* @__PURE__ */ (() => z.string().min(16).max(65_536))();
|
|
9474
|
+
|
|
9475
|
+
export const CreatePrReviewAppRegistrationRequest = /* @__PURE__ */ (() =>
|
|
9476
|
+
z
|
|
9477
|
+
.object({
|
|
9478
|
+
name: z.string().trim().min(1).max(200),
|
|
9479
|
+
provider: PrReviewProvider,
|
|
9480
|
+
providerBaseUrl: z.string().url().max(2048).optional(),
|
|
9481
|
+
appId: z.string().trim().min(1).max(512).optional(),
|
|
9482
|
+
credentialKind: PrReviewCredentialKind,
|
|
9483
|
+
privateKey: PrReviewSecretInput.optional(),
|
|
9484
|
+
accessToken: PrReviewSecretInput.optional(),
|
|
9485
|
+
accessTokenExpiresAt: z.string().datetime().nullable().optional(),
|
|
9486
|
+
webhookSecret: PrReviewSecretInput,
|
|
9487
|
+
webhookUsername: z.string().min(1).max(512).optional(),
|
|
9488
|
+
})
|
|
9489
|
+
.strict()
|
|
9490
|
+
.superRefine((value, context) => {
|
|
9491
|
+
if (value.provider === "github" && value.credentialKind !== "github_app") {
|
|
9492
|
+
context.addIssue({
|
|
9493
|
+
code: "custom",
|
|
9494
|
+
path: ["credentialKind"],
|
|
9495
|
+
message: "GitHub PR Review registrations require a dedicated GitHub App",
|
|
9496
|
+
});
|
|
9497
|
+
}
|
|
9498
|
+
if (value.provider === "github" && (!value.appId || !value.privateKey)) {
|
|
9499
|
+
context.addIssue({
|
|
9500
|
+
code: "custom",
|
|
9501
|
+
path: [!value.appId ? "appId" : "privateKey"],
|
|
9502
|
+
message: "GitHub PR Review registrations require the dedicated App ID and private key",
|
|
9503
|
+
});
|
|
9504
|
+
}
|
|
9505
|
+
if (value.provider !== "github" && value.credentialKind !== "provider_token") {
|
|
9506
|
+
context.addIssue({
|
|
9507
|
+
code: "custom",
|
|
9508
|
+
path: ["credentialKind"],
|
|
9509
|
+
message: "GitLab and Azure DevOps PR Review registrations require a provider token",
|
|
9510
|
+
});
|
|
9511
|
+
}
|
|
9512
|
+
if (value.credentialKind === "provider_token" && !value.accessToken) {
|
|
9513
|
+
context.addIssue({
|
|
9514
|
+
code: "custom",
|
|
9515
|
+
path: ["accessToken"],
|
|
9516
|
+
message: "provider_token credentials require accessToken",
|
|
9517
|
+
});
|
|
9518
|
+
}
|
|
9519
|
+
if (
|
|
9520
|
+
value.credentialKind === "github_app" &&
|
|
9521
|
+
(value.accessToken !== undefined || value.privateKey === undefined)
|
|
9522
|
+
) {
|
|
9523
|
+
context.addIssue({
|
|
9524
|
+
code: "custom",
|
|
9525
|
+
path: [value.accessToken !== undefined ? "accessToken" : "privateKey"],
|
|
9526
|
+
message: "GitHub App credentials require privateKey and cannot include accessToken",
|
|
9527
|
+
});
|
|
9528
|
+
}
|
|
9529
|
+
if (value.credentialKind === "provider_token" && value.privateKey !== undefined) {
|
|
9530
|
+
context.addIssue({
|
|
9531
|
+
code: "custom",
|
|
9532
|
+
path: ["privateKey"],
|
|
9533
|
+
message: "provider_token credentials cannot include a GitHub privateKey",
|
|
9534
|
+
});
|
|
9535
|
+
}
|
|
9536
|
+
if (value.provider === "github" && value.accessTokenExpiresAt !== undefined) {
|
|
9537
|
+
context.addIssue({
|
|
9538
|
+
code: "custom",
|
|
9539
|
+
path: ["accessTokenExpiresAt"],
|
|
9540
|
+
message: "GitHub App registrations do not use accessTokenExpiresAt",
|
|
9541
|
+
});
|
|
9542
|
+
}
|
|
9543
|
+
if (value.provider === "azure_devops" && !value.webhookUsername) {
|
|
9544
|
+
context.addIssue({
|
|
9545
|
+
code: "custom",
|
|
9546
|
+
path: ["webhookUsername"],
|
|
9547
|
+
message: "Azure DevOps service hooks require a Basic authentication username",
|
|
9548
|
+
});
|
|
9549
|
+
}
|
|
9550
|
+
}))();
|
|
9551
|
+
export type CreatePrReviewAppRegistrationRequest = z.infer<
|
|
9552
|
+
typeof CreatePrReviewAppRegistrationRequest
|
|
9553
|
+
>;
|
|
9554
|
+
|
|
9555
|
+
export const UpdatePrReviewAppRegistrationRequest = /* @__PURE__ */ (() =>
|
|
9556
|
+
z
|
|
9557
|
+
.object({
|
|
9558
|
+
name: z.string().trim().min(1).max(200).optional(),
|
|
9559
|
+
accessToken: PrReviewSecretInput.optional(),
|
|
9560
|
+
privateKey: PrReviewSecretInput.optional(),
|
|
9561
|
+
accessTokenExpiresAt: z.string().datetime().nullable().optional(),
|
|
9562
|
+
webhookSecret: PrReviewSecretInput.optional(),
|
|
9563
|
+
webhookUsername: z.string().min(1).max(512).optional(),
|
|
9564
|
+
status: z.enum(["active", "disabled"]).optional(),
|
|
9565
|
+
})
|
|
9566
|
+
.strict()
|
|
9567
|
+
.refine((value) => Object.keys(value).length > 0, {
|
|
9568
|
+
message: "PR Review registration update must change at least one field",
|
|
9569
|
+
}))();
|
|
9570
|
+
export type UpdatePrReviewAppRegistrationRequest = z.infer<
|
|
9571
|
+
typeof UpdatePrReviewAppRegistrationRequest
|
|
9572
|
+
>;
|
|
9573
|
+
|
|
9574
|
+
export const PrReviewAppRegistration = /* @__PURE__ */ (() =>
|
|
9575
|
+
z.object({
|
|
9576
|
+
id: z.string().uuid(),
|
|
9577
|
+
sourceId: z.string().uuid(),
|
|
9578
|
+
accountId: z.string().uuid(),
|
|
9579
|
+
workspaceId: z.string().uuid(),
|
|
9580
|
+
name: z.string(),
|
|
9581
|
+
provider: PrReviewProvider,
|
|
9582
|
+
providerBaseUrl: z.string().url(),
|
|
9583
|
+
appId: z.string().nullable(),
|
|
9584
|
+
credentialKind: PrReviewCredentialKind,
|
|
9585
|
+
hasCredential: z.boolean(),
|
|
9586
|
+
accessTokenExpiresAt: z.string().nullable(),
|
|
9587
|
+
webhookAuthKind: PrReviewWebhookAuthKind,
|
|
9588
|
+
hasWebhookSecret: z.boolean(),
|
|
9589
|
+
webhookUsername: z.string().nullable(),
|
|
9590
|
+
webhookPath: z.string(),
|
|
9591
|
+
status: z.enum(["active", "disabled"]),
|
|
9592
|
+
createdBySubjectId: z.string(),
|
|
9593
|
+
createdAt: z.string(),
|
|
9594
|
+
updatedAt: z.string(),
|
|
9595
|
+
}))();
|
|
9596
|
+
export type PrReviewAppRegistration = z.infer<typeof PrReviewAppRegistration>;
|
|
9597
|
+
|
|
9598
|
+
export const CreatePrReviewRepositoryBindingRequest = /* @__PURE__ */ (() =>
|
|
9599
|
+
z
|
|
9600
|
+
.object({
|
|
9601
|
+
registrationId: z.string().uuid(),
|
|
9602
|
+
repositoryUri: z.string().url().max(2048),
|
|
9603
|
+
repositoryFullName: z.string().trim().min(1).max(1024),
|
|
9604
|
+
providerRepositoryId: z.union([z.string().min(1).max(512), z.number().int().positive()]),
|
|
9605
|
+
installationId: z.union([z.string().min(1).max(512), z.number().int().positive()]).optional(),
|
|
9606
|
+
projectId: z.union([z.string().min(1).max(512), z.number().int().positive()]).optional(),
|
|
9607
|
+
model: z.string().min(1).max(512).nullable().optional(),
|
|
9608
|
+
additionalInstructions: z.string().max(16_384).nullable().optional(),
|
|
9609
|
+
status: z.enum(["active", "disabled"]).default("active"),
|
|
9610
|
+
})
|
|
9611
|
+
.strict())();
|
|
9612
|
+
export type CreatePrReviewRepositoryBindingRequest = z.infer<
|
|
9613
|
+
typeof CreatePrReviewRepositoryBindingRequest
|
|
9614
|
+
>;
|
|
9615
|
+
|
|
9616
|
+
export const UpdatePrReviewRepositoryBindingRequest = /* @__PURE__ */ (() =>
|
|
9617
|
+
z
|
|
9618
|
+
.object({
|
|
9619
|
+
model: z.string().min(1).max(512).nullable().optional(),
|
|
9620
|
+
additionalInstructions: z.string().max(16_384).nullable().optional(),
|
|
9621
|
+
status: z.enum(["active", "disabled"]).optional(),
|
|
9622
|
+
})
|
|
9623
|
+
.strict()
|
|
9624
|
+
.refine((value) => Object.keys(value).length > 0, {
|
|
9625
|
+
message: "PR Review repository update must change at least one field",
|
|
9626
|
+
}))();
|
|
9627
|
+
export type UpdatePrReviewRepositoryBindingRequest = z.infer<
|
|
9628
|
+
typeof UpdatePrReviewRepositoryBindingRequest
|
|
9629
|
+
>;
|
|
9630
|
+
|
|
9631
|
+
export const PrReviewRepositoryBinding = /* @__PURE__ */ (() =>
|
|
9632
|
+
z.object({
|
|
9633
|
+
id: z.string().uuid(),
|
|
9634
|
+
triggerId: z.string().uuid(),
|
|
9635
|
+
accountId: z.string().uuid(),
|
|
9636
|
+
workspaceId: z.string().uuid(),
|
|
9637
|
+
registrationId: z.string().uuid(),
|
|
9638
|
+
provider: PrReviewProvider,
|
|
9639
|
+
repositoryUri: z.string(),
|
|
9640
|
+
repositoryFullName: z.string(),
|
|
9641
|
+
providerRepositoryId: z.string(),
|
|
9642
|
+
installationId: z.string().nullable(),
|
|
9643
|
+
projectId: z.string().nullable(),
|
|
9644
|
+
model: z.string().nullable(),
|
|
9645
|
+
additionalInstructions: z.string().nullable(),
|
|
9646
|
+
status: z.enum(["active", "disabled"]),
|
|
9647
|
+
createdBySubjectId: z.string(),
|
|
9648
|
+
createdAt: z.string(),
|
|
9649
|
+
updatedAt: z.string(),
|
|
9650
|
+
}))();
|
|
9651
|
+
export type PrReviewRepositoryBinding = z.infer<typeof PrReviewRepositoryBinding>;
|
|
9652
|
+
|
|
7329
9653
|
export const EnablePackRequest = withVariableSetIdAlias({
|
|
7330
9654
|
variableSetId: z.string().uuid().optional(),
|
|
7331
9655
|
environmentId: z.string().uuid().optional(),
|
|
@@ -7547,6 +9871,8 @@ export const OPENGENI_PERSONAL_SLACK_MCP_URL = "https://mcp.slack.com/mcp" as co
|
|
|
7547
9871
|
export const OPENGENI_SLACK_BOT_CREDENTIAL_ROLE = "opengeni_slack_bot" as const;
|
|
7548
9872
|
export const OPENGENI_SLACK_BOT_CREDENTIAL_LABEL = "OpenGeni Slack bot" as const;
|
|
7549
9873
|
export const OPENGENI_SLACK_BOT_SESSION_METADATA_KEY = "opengeniSlackBotConnectionId" as const;
|
|
9874
|
+
export const OpenGeniSlackBotDisplayName = z.enum(["OpenGeni", "OpenGeni Staging"]);
|
|
9875
|
+
export type OpenGeniSlackBotDisplayName = z.infer<typeof OpenGeniSlackBotDisplayName>;
|
|
7550
9876
|
export const OpenGeniSlackBotConnectionMetadata = z
|
|
7551
9877
|
.object({
|
|
7552
9878
|
credentialRole: z.literal(OPENGENI_SLACK_BOT_CREDENTIAL_ROLE),
|
|
@@ -7555,7 +9881,7 @@ export const OpenGeniSlackBotConnectionMetadata = z
|
|
|
7555
9881
|
slackTeamName: z.string().min(1).max(256),
|
|
7556
9882
|
botUserId: z.string().min(1).max(64),
|
|
7557
9883
|
botId: z.string().min(1).max(64),
|
|
7558
|
-
botDisplayName:
|
|
9884
|
+
botDisplayName: OpenGeniSlackBotDisplayName,
|
|
7559
9885
|
verifiedAt: z.string().datetime({ offset: true }),
|
|
7560
9886
|
})
|
|
7561
9887
|
.passthrough();
|
|
@@ -7605,6 +9931,8 @@ export type FikenOAuthStartResponse = z.infer<typeof FikenOAuthStartResponse>;
|
|
|
7605
9931
|
|
|
7606
9932
|
export const ConnectionMetadata = z.object({
|
|
7607
9933
|
id: z.string().uuid(),
|
|
9934
|
+
/** Opaque owner-only handle used to manage this personal connection's grants. */
|
|
9935
|
+
authorityId: z.string().uuid().optional(),
|
|
7608
9936
|
accountId: z.string().uuid(),
|
|
7609
9937
|
workspaceId: z.string().uuid(),
|
|
7610
9938
|
subjectId: z.string().nullable(),
|
|
@@ -7734,7 +10062,7 @@ export const SlackInstallationBinding = z.object({
|
|
|
7734
10062
|
slackTeamName: z.string().min(1).max(256),
|
|
7735
10063
|
botId: z.string().min(1).max(64),
|
|
7736
10064
|
botUserId: z.string().min(1).max(64),
|
|
7737
|
-
botDisplayName:
|
|
10065
|
+
botDisplayName: OpenGeniSlackBotDisplayName,
|
|
7738
10066
|
state: SlackInstallationBindingState,
|
|
7739
10067
|
quarantineReason: z.string().min(1).nullable(),
|
|
7740
10068
|
version: z.number().int().positive(),
|
|
@@ -8240,6 +10568,43 @@ export const IntegrationFacetDefinitionSummary = z
|
|
|
8240
10568
|
.strict();
|
|
8241
10569
|
export type IntegrationFacetDefinitionSummary = z.infer<typeof IntegrationFacetDefinitionSummary>;
|
|
8242
10570
|
|
|
10571
|
+
/**
|
|
10572
|
+
* Presentation-only consent copy for an integration or connector. Never grants
|
|
10573
|
+
* a scope, selects a connection, or replaces server-side authorization; the UI
|
|
10574
|
+
* falls back to generic copy for any omitted field.
|
|
10575
|
+
*/
|
|
10576
|
+
export const IntegrationPresentation = z
|
|
10577
|
+
.object({
|
|
10578
|
+
providerName: z.string().min(1).max(120).optional(),
|
|
10579
|
+
icon: z.enum(["calendar", "cloud", "contacts", "files", "mail"]).optional(),
|
|
10580
|
+
introduction: z.string().min(1).max(500).optional(),
|
|
10581
|
+
capabilities: z
|
|
10582
|
+
.array(
|
|
10583
|
+
z
|
|
10584
|
+
.object({
|
|
10585
|
+
title: z.string().min(1).max(160),
|
|
10586
|
+
description: z.string().min(1).max(500),
|
|
10587
|
+
})
|
|
10588
|
+
.strict(),
|
|
10589
|
+
)
|
|
10590
|
+
.max(8)
|
|
10591
|
+
.optional(),
|
|
10592
|
+
permissionSummary: z.string().min(1).max(500).optional(),
|
|
10593
|
+
scopeLabels: z
|
|
10594
|
+
.record(
|
|
10595
|
+
z.string().min(1).max(1024),
|
|
10596
|
+
z
|
|
10597
|
+
.object({
|
|
10598
|
+
label: z.string().min(1).max(160),
|
|
10599
|
+
description: z.string().min(1).max(500),
|
|
10600
|
+
})
|
|
10601
|
+
.strict(),
|
|
10602
|
+
)
|
|
10603
|
+
.optional(),
|
|
10604
|
+
})
|
|
10605
|
+
.strict();
|
|
10606
|
+
export type IntegrationPresentation = z.infer<typeof IntegrationPresentation>;
|
|
10607
|
+
|
|
8243
10608
|
export const IntegrationDefinitionSummary = z
|
|
8244
10609
|
.object({
|
|
8245
10610
|
id: z.string().min(1).max(128),
|
|
@@ -8258,6 +10623,7 @@ export const IntegrationDefinitionSummary = z
|
|
|
8258
10623
|
scopes: z.array(z.string().min(1).max(1024)).max(256),
|
|
8259
10624
|
})
|
|
8260
10625
|
.strict(),
|
|
10626
|
+
presentation: IntegrationPresentation.optional(),
|
|
8261
10627
|
facets: z.array(IntegrationFacetDefinitionSummary).max(128),
|
|
8262
10628
|
})
|
|
8263
10629
|
.strict();
|
|
@@ -8291,6 +10657,8 @@ export const IntegrationFacetBindingSummary = z
|
|
|
8291
10657
|
lastErrorCode: z.string().min(1).max(120).nullable(),
|
|
8292
10658
|
createdAt: z.string().datetime({ offset: true }),
|
|
8293
10659
|
updatedAt: z.string().datetime({ offset: true }),
|
|
10660
|
+
directlyOwned: z.boolean(),
|
|
10661
|
+
owners: z.array(CapabilityComponentOwner),
|
|
8294
10662
|
})
|
|
8295
10663
|
.strict();
|
|
8296
10664
|
export type IntegrationFacetBindingSummary = z.infer<typeof IntegrationFacetBindingSummary>;
|
|
@@ -8813,11 +11181,59 @@ export const UninstallPluginResult = z
|
|
|
8813
11181
|
.strict();
|
|
8814
11182
|
export type UninstallPluginResult = z.infer<typeof UninstallPluginResult>;
|
|
8815
11183
|
|
|
11184
|
+
export const SessionBackgroundCommandState = z.enum(["running", "stopping", "exited", "lost"]);
|
|
11185
|
+
export type SessionBackgroundCommandState = z.infer<typeof SessionBackgroundCommandState>;
|
|
11186
|
+
|
|
11187
|
+
export const SessionBackgroundCommandProvider = z.enum(["managed", "connected_machine"]);
|
|
11188
|
+
export type SessionBackgroundCommandProvider = z.infer<typeof SessionBackgroundCommandProvider>;
|
|
11189
|
+
|
|
11190
|
+
export const SessionBackgroundCommandActivity = z
|
|
11191
|
+
.object({
|
|
11192
|
+
state: z.enum(["running", "stopping"]),
|
|
11193
|
+
count: z.number().int().positive(),
|
|
11194
|
+
})
|
|
11195
|
+
.strict();
|
|
11196
|
+
export type SessionBackgroundCommandActivity = z.infer<typeof SessionBackgroundCommandActivity>;
|
|
11197
|
+
|
|
11198
|
+
export const SessionBackgroundCommand = z
|
|
11199
|
+
.object({
|
|
11200
|
+
id: z.string().uuid(),
|
|
11201
|
+
workspaceId: z.string().uuid(),
|
|
11202
|
+
sessionId: z.string().uuid(),
|
|
11203
|
+
provider: SessionBackgroundCommandProvider,
|
|
11204
|
+
state: SessionBackgroundCommandState,
|
|
11205
|
+
commandPreview: z.string().max(512),
|
|
11206
|
+
cancelRequestedAt: z.string().nullable(),
|
|
11207
|
+
exitCode: z.number().int().nullable(),
|
|
11208
|
+
settlementReason: z.string().nullable(),
|
|
11209
|
+
startedAt: z.string(),
|
|
11210
|
+
settledAt: z.string().nullable(),
|
|
11211
|
+
updatedAt: z.string(),
|
|
11212
|
+
})
|
|
11213
|
+
.strict();
|
|
11214
|
+
export type SessionBackgroundCommand = z.infer<typeof SessionBackgroundCommand>;
|
|
11215
|
+
|
|
11216
|
+
export const SessionBackgroundCommandListResponse = z
|
|
11217
|
+
.object({ commands: z.array(SessionBackgroundCommand).max(1000) })
|
|
11218
|
+
.strict();
|
|
11219
|
+
export type SessionBackgroundCommandListResponse = z.infer<
|
|
11220
|
+
typeof SessionBackgroundCommandListResponse
|
|
11221
|
+
>;
|
|
11222
|
+
|
|
11223
|
+
export const CancelSessionBackgroundCommandResult = z
|
|
11224
|
+
.object({ command: SessionBackgroundCommand, accepted: z.boolean() })
|
|
11225
|
+
.strict();
|
|
11226
|
+
export type CancelSessionBackgroundCommandResult = z.infer<
|
|
11227
|
+
typeof CancelSessionBackgroundCommandResult
|
|
11228
|
+
>;
|
|
11229
|
+
|
|
8816
11230
|
export const Session = z.object({
|
|
8817
11231
|
id: z.string().uuid(),
|
|
8818
11232
|
workspaceId: z.string().uuid(),
|
|
8819
11233
|
accountId: z.string().uuid(),
|
|
8820
11234
|
status: SessionStatus,
|
|
11235
|
+
/** Additive list projection. Detail reads may omit it. */
|
|
11236
|
+
backgroundCommandActivity: SessionBackgroundCommandActivity.optional(),
|
|
8821
11237
|
initialMessage: z.string(),
|
|
8822
11238
|
title: z.string().nullable(),
|
|
8823
11239
|
titleSource: z.enum(["user", "agent"]).nullable(),
|
|
@@ -8846,6 +11262,8 @@ export const Session = z.object({
|
|
|
8846
11262
|
createdBy: TurnInitiator,
|
|
8847
11263
|
createdByContext: TurnInitiatorContext,
|
|
8848
11264
|
model: z.string(),
|
|
11265
|
+
reasoningEffort: ReasoningEffort,
|
|
11266
|
+
latencyMode: LatencyMode,
|
|
8849
11267
|
sandboxBackend: SandboxBackend,
|
|
8850
11268
|
// The OS the session's box runs. Defaults to 'linux' (today's only OS).
|
|
8851
11269
|
sandboxOs: SandboxOs,
|
|
@@ -8929,6 +11347,17 @@ export const Session = z.object({
|
|
|
8929
11347
|
pinnedAt: z.string().nullable().default(null),
|
|
8930
11348
|
/** Optimistic pin-state revision; zero represents an absent pin relation. */
|
|
8931
11349
|
pinVersion: z.number().int().nonnegative().default(0),
|
|
11350
|
+
/** Personal explicit acknowledgment state; opening the session never clears it. */
|
|
11351
|
+
unread: z.boolean().default(false),
|
|
11352
|
+
/** Personal power-user label for work the member intends to continue. */
|
|
11353
|
+
activelyWorking: z.boolean().default(false),
|
|
11354
|
+
/** Optimistic revision for unread/actively-working state. */
|
|
11355
|
+
attentionVersion: z.number().int().nonnegative().default(0),
|
|
11356
|
+
/** Personal archive state. Archived roots and their descendants leave the ordinary list. */
|
|
11357
|
+
archived: z.boolean().default(false),
|
|
11358
|
+
archivedAt: z.string().nullable().default(null),
|
|
11359
|
+
/** Optimistic archive-state revision; zero represents an absent personal relation. */
|
|
11360
|
+
archiveVersion: z.number().int().nonnegative().default(0),
|
|
8932
11361
|
/**
|
|
8933
11362
|
* Server-authoritative hierarchy summary populated on session-list reads.
|
|
8934
11363
|
* Detail reads may omit it. The rail uses this instead of guessing a tree
|
|
@@ -8943,10 +11372,24 @@ export const Session = z.object({
|
|
|
8943
11372
|
attentionDescendants: z.number().int().nonnegative(),
|
|
8944
11373
|
pausedDescendants: z.number().int().nonnegative(),
|
|
8945
11374
|
failedDescendants: z.number().int().nonnegative(),
|
|
11375
|
+
unreadDescendants: z.number().int().nonnegative().optional(),
|
|
11376
|
+
activelyWorkingDescendants: z.number().int().nonnegative().optional(),
|
|
11377
|
+
/**
|
|
11378
|
+
* Earliest moment one of the counted `attentionDescendants` entered
|
|
11379
|
+
* `requires_action` (the oldest still-open `requires_action` turn among
|
|
11380
|
+
* those descendants). Null when none is waiting; omitted by older servers.
|
|
11381
|
+
*/
|
|
11382
|
+
attentionSince: z.string().nullable().optional(),
|
|
8946
11383
|
/** Counts are lower bounds rather than exact totals when true. */
|
|
8947
11384
|
truncated: z.boolean().default(false),
|
|
8948
11385
|
})
|
|
8949
11386
|
.optional(),
|
|
11387
|
+
/**
|
|
11388
|
+
* When this session's own open turn entered `requires_action`. Populated by
|
|
11389
|
+
* list and lineage reads for sessions whose status is `requires_action`;
|
|
11390
|
+
* null otherwise and omitted by older servers or detail reads.
|
|
11391
|
+
*/
|
|
11392
|
+
requiresActionSince: z.string().nullable().optional(),
|
|
8950
11393
|
createdAt: z.string(),
|
|
8951
11394
|
updatedAt: z.string(),
|
|
8952
11395
|
});
|
|
@@ -9055,6 +11498,7 @@ export type SessionLineageResponse = z.infer<typeof SessionLineageResponse>;
|
|
|
9055
11498
|
|
|
9056
11499
|
export const SessionEventType = z.enum([
|
|
9057
11500
|
"session.created",
|
|
11501
|
+
"session.personal_resources.attached",
|
|
9058
11502
|
"session.visibility.changed",
|
|
9059
11503
|
// Defensive read/transport projection for a malformed or historically
|
|
9060
11504
|
// oversized retained event envelope. The original row stays durable; this
|
|
@@ -9083,13 +11527,20 @@ export const SessionEventType = z.enum([
|
|
|
9083
11527
|
"turn.superseded",
|
|
9084
11528
|
"turn.recovery.requested",
|
|
9085
11529
|
"turn.capacity_waiting",
|
|
11530
|
+
// Compact, attempt-fenced user-visible worker preparation checkpoints. The
|
|
11531
|
+
// payload phase is a closed enum and terminal events carry durationMs; no
|
|
11532
|
+
// session-specific value is ever promoted into Prometheus labels.
|
|
11533
|
+
"turn.startup.phase.started",
|
|
11534
|
+
"turn.startup.phase.completed",
|
|
11535
|
+
"turn.startup.phase.failed",
|
|
9086
11536
|
"agent.message.delta",
|
|
9087
11537
|
"agent.message.completed",
|
|
9088
11538
|
"agent.reasoning.delta",
|
|
9089
11539
|
"agent.toolCall.created",
|
|
9090
11540
|
"agent.toolCall.output",
|
|
9091
|
-
// Attempt-fenced
|
|
9092
|
-
//
|
|
11541
|
+
// Attempt-fenced provider Responses lifecycle metadata (request identity,
|
|
11542
|
+
// liveness policy, first-event/terminal phase, provider request id). Never
|
|
11543
|
+
// request body, credentials, or model output.
|
|
9093
11544
|
"agent.model.request",
|
|
9094
11545
|
"agent.model.usage",
|
|
9095
11546
|
"tool.auth_needed",
|
|
@@ -9102,6 +11553,8 @@ export const SessionEventType = z.enum([
|
|
|
9102
11553
|
"sandbox.operation.started",
|
|
9103
11554
|
"sandbox.operation.completed",
|
|
9104
11555
|
"sandbox.operation.failed",
|
|
11556
|
+
"session.command.backgrounded",
|
|
11557
|
+
"session.command.finished",
|
|
9105
11558
|
"sandbox.command.output.delta",
|
|
9106
11559
|
"artifact.created",
|
|
9107
11560
|
"goal.set",
|
|
@@ -9113,6 +11566,7 @@ export const SessionEventType = z.enum([
|
|
|
9113
11566
|
"goal.paused",
|
|
9114
11567
|
"goal.resumed",
|
|
9115
11568
|
"goal.cleared",
|
|
11569
|
+
"goal.held",
|
|
9116
11570
|
"goal.continuation",
|
|
9117
11571
|
"system.update.pending",
|
|
9118
11572
|
"system.update.delivered",
|
|
@@ -9305,6 +11759,7 @@ export const SESSION_EVENT_RAW_DELTA_TYPES = [
|
|
|
9305
11759
|
export const SESSION_EVENT_SEMANTIC_CLASS_TYPES = {
|
|
9306
11760
|
control: [
|
|
9307
11761
|
"session.status.changed",
|
|
11762
|
+
"session.command.backgrounded",
|
|
9308
11763
|
"session.requiresAction",
|
|
9309
11764
|
"session.humanInput.requested",
|
|
9310
11765
|
"user.pause",
|
|
@@ -9319,6 +11774,7 @@ export const SESSION_EVENT_SEMANTIC_CLASS_TYPES = {
|
|
|
9319
11774
|
"goal.paused",
|
|
9320
11775
|
"goal.resumed",
|
|
9321
11776
|
"goal.cleared",
|
|
11777
|
+
"goal.held",
|
|
9322
11778
|
"goal.continuation",
|
|
9323
11779
|
"system.update.pending",
|
|
9324
11780
|
"system.update.delivered",
|
|
@@ -9351,6 +11807,7 @@ export const SESSION_EVENT_SEMANTIC_CLASS_TYPES = {
|
|
|
9351
11807
|
"recording.available",
|
|
9352
11808
|
"recording.failed",
|
|
9353
11809
|
"terminal.pty.exited",
|
|
11810
|
+
"session.command.finished",
|
|
9354
11811
|
],
|
|
9355
11812
|
failure: [
|
|
9356
11813
|
"session.event.envelope_omitted",
|
|
@@ -9677,7 +12134,9 @@ export type FsNodeType = z.infer<typeof FsNodeType>;
|
|
|
9677
12134
|
// depth>0; the tree lazy-expands via repeated depth-1 lists at deeper paths.
|
|
9678
12135
|
export interface FsTreeNode {
|
|
9679
12136
|
name: string;
|
|
9680
|
-
|
|
12137
|
+
// Same namespace as the request: workspace-relative for relative requests,
|
|
12138
|
+
// canonical target path for requests rooted at FileSystem.root.
|
|
12139
|
+
path: string;
|
|
9681
12140
|
type: z.infer<typeof FsNodeType>;
|
|
9682
12141
|
sizeBytes: number | null; // null for dirs
|
|
9683
12142
|
mtimeMs: number | null;
|
|
@@ -9699,7 +12158,9 @@ export const FsTreeNode: z.ZodType<FsTreeNode> = z.lazy(() =>
|
|
|
9699
12158
|
) as z.ZodType<FsTreeNode>;
|
|
9700
12159
|
|
|
9701
12160
|
export const FsListRequest = z.object({
|
|
9702
|
-
|
|
12161
|
+
// "" = workspace root; canonical absolute paths must stay within the
|
|
12162
|
+
// selected target's advertised FileSystem.root.
|
|
12163
|
+
path: z.string().default(""),
|
|
9703
12164
|
depth: z.number().int().min(0).max(8).default(1),
|
|
9704
12165
|
maxEntries: z.number().int().positive().max(20_000).default(2_000),
|
|
9705
12166
|
includeHidden: z.boolean().default(true),
|
|
@@ -11221,134 +13682,154 @@ export const SessionControlResponse = z.object({
|
|
|
11221
13682
|
});
|
|
11222
13683
|
export type SessionControlResponse = z.infer<typeof SessionControlResponse>;
|
|
11223
13684
|
|
|
11224
|
-
export const
|
|
11225
|
-
|
|
11226
|
-
|
|
11227
|
-
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
|
|
11262
|
-
|
|
11263
|
-
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
|
|
11270
|
-
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11277
|
-
|
|
11278
|
-
|
|
11279
|
-
|
|
11280
|
-
|
|
11281
|
-
|
|
11282
|
-
|
|
11283
|
-
|
|
11284
|
-
|
|
11285
|
-
|
|
11286
|
-
|
|
11287
|
-
|
|
11288
|
-
|
|
11289
|
-
|
|
11290
|
-
|
|
11291
|
-
|
|
11292
|
-
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11297
|
-
|
|
11298
|
-
|
|
11299
|
-
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
.
|
|
11351
|
-
|
|
13685
|
+
export const SESSION_INSTRUCTIONS_MAX_CHARACTERS = 65_536;
|
|
13686
|
+
|
|
13687
|
+
export const CreateSessionRequest = withVariableSetIdAlias(
|
|
13688
|
+
{
|
|
13689
|
+
/**
|
|
13690
|
+
* Optional UUID preallocated by an embedding host. This lets the host durably
|
|
13691
|
+
* link its own projection before OpenGeni admits the initial turn. Replays
|
|
13692
|
+
* must pair it with the same idempotency key; OpenGeni never derives host
|
|
13693
|
+
* identity or authorization from the UUID.
|
|
13694
|
+
*/
|
|
13695
|
+
requestedSessionId: z.string().uuid().optional(),
|
|
13696
|
+
/** Top-level omission is workspace-visible. Agent-child omission inherits
|
|
13697
|
+
* the exact parent visibility; cross-visibility child creation is rejected.
|
|
13698
|
+
* Top-level private creation is an activated managed-cookie owning-human
|
|
13699
|
+
* capability, while a private child uses an exact live-parent-attempt
|
|
13700
|
+
* database capability. Both commit atomically. */
|
|
13701
|
+
visibility: SessionVisibility.default("workspace"),
|
|
13702
|
+
initialMessage: z.string().min(1).optional(),
|
|
13703
|
+
// Creates the durable session shell without fabricating a user message or
|
|
13704
|
+
// starting an underlying agent turn. Realtime can then become the first
|
|
13705
|
+
// interaction and use the ordinary Send/Steer path when it delegates.
|
|
13706
|
+
startMode: z.literal("realtime").optional(),
|
|
13707
|
+
// Model-visible application context attached to the initial user message.
|
|
13708
|
+
// Standard timeline rendering omits it, while full event/audit reads retain
|
|
13709
|
+
// it. This is ordinary user-role content, not secret or privileged input.
|
|
13710
|
+
modelContext: z.string().trim().min(1).max(32768).optional(),
|
|
13711
|
+
// Per-session agent persona/system instructions (org-visible metadata, NOT a
|
|
13712
|
+
// secret). Rides the SAME system-level instructions channel the per-workspace
|
|
13713
|
+
// agentInstructions rides, composed AFTER the workspace persona so it refines
|
|
13714
|
+
// it for this one session — how a host delivers per-agent-type prompts without
|
|
13715
|
+
// leaking them into the user-visible timeline (it is NEVER emitted as an
|
|
13716
|
+
// event, unlike goal/initialMessage). Trimmed, non-empty, and bounded by the
|
|
13717
|
+
// shared durable session-instruction contract. Absent ⇒ byte-identical to
|
|
13718
|
+
// today.
|
|
13719
|
+
instructions: z.string().trim().min(1).max(SESSION_INSTRUCTIONS_MAX_CHARACTERS).optional(),
|
|
13720
|
+
// Immutable prompt-policy role binding for matching one activated role
|
|
13721
|
+
// policy. This never derives from or grants a human workspace membership
|
|
13722
|
+
// role. Existing callers may continue to use normalized metadata.role as a
|
|
13723
|
+
// compatibility fallback by omitting this field.
|
|
13724
|
+
policyRole: WorkspaceInstructionPolicyRoleKeyInput.optional(),
|
|
13725
|
+
// For an agent-created child, omission inherits the trusted immediate
|
|
13726
|
+
// parent's repository/file context. An explicit array, including [], is
|
|
13727
|
+
// authoritative. Top-level omission remains []. Presence is resolved from
|
|
13728
|
+
// the raw request because this Zod default erases absent-vs-empty.
|
|
13729
|
+
resources: z.array(ResourceRef).default([]),
|
|
13730
|
+
// Inline skills are fixed onto the session. Child omission inherits the
|
|
13731
|
+
// trusted parent's selection; an explicit array, including [], wins.
|
|
13732
|
+
skills: SessionSkills.default([]),
|
|
13733
|
+
// The same child omission rule applies to selected MCP tool refs. Top-level
|
|
13734
|
+
// omission still applies workspace-default capability MCP tools; explicit []
|
|
13735
|
+
// suppresses those defaults (the first-party OpenGeni server remains added).
|
|
13736
|
+
tools: z.array(ToolRef).default([]),
|
|
13737
|
+
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
13738
|
+
model: z.string().min(1).optional(),
|
|
13739
|
+
reasoningEffort: ReasoningEffort.optional(),
|
|
13740
|
+
latencyMode: LatencyMode.optional(),
|
|
13741
|
+
sandboxBackend: SandboxBackend.optional(),
|
|
13742
|
+
// The enrolled machine (a sandbox id) to run this session on; seeds the
|
|
13743
|
+
// active-sandbox pointer at creation so the FIRST turn routes to the chosen
|
|
13744
|
+
// machine (race-free: the pointer is committed before the worker turn
|
|
13745
|
+
// workflow can read it). An invalid/unowned/offline target fails the create.
|
|
13746
|
+
targetSandboxId: z.string().uuid().optional(),
|
|
13747
|
+
// The working directory the targeted machine runs the session under. It may
|
|
13748
|
+
// be absolute or relative to the machine's persisted Hello root; the server
|
|
13749
|
+
// stores the resolved absolute value. Tilde is rejected because the control
|
|
13750
|
+
// plane has no authenticated home-directory fact. Only valid WITH
|
|
13751
|
+
// targetSandboxId; omitted selects the reported root.
|
|
13752
|
+
workingDir: z.string().min(1).optional(),
|
|
13753
|
+
// Variable set attachment is fixed at session creation; follow-up
|
|
13754
|
+
// user.message events cannot switch or add one.
|
|
13755
|
+
variableSetId: z.string().uuid().optional(),
|
|
13756
|
+
environmentId: z.string().uuid().optional(),
|
|
13757
|
+
// The rig to bind this session to (M3). Its ACTIVE version is resolved and
|
|
13758
|
+
// FROZEN onto the session at create. Omitted ⇒ inherit the workspace default;
|
|
13759
|
+
// null ⇒ explicitly create a rig-less session; UUID ⇒ bind that exact rig.
|
|
13760
|
+
// An id that does not name a rig in the workspace is a 422.
|
|
13761
|
+
rigId: z.string().uuid().nullable().optional(),
|
|
13762
|
+
// The workspace channel to file this session under (rail organization only).
|
|
13763
|
+
// Omitted/null ⇒ unfiled (inbox). An id that does not name a channel in the
|
|
13764
|
+
// workspace is a 422.
|
|
13765
|
+
channelId: z.string().uuid().nullable().optional(),
|
|
13766
|
+
goal: GoalSpec.optional(),
|
|
13767
|
+
clientEventId: SessionOperationKey.optional(),
|
|
13768
|
+
// Workspace-scoped CREATE idempotency key: collapses concurrent/retried
|
|
13769
|
+
// create calls carrying the same key to a single session (partial unique
|
|
13770
|
+
// index on (workspace_id, create_idempotency_key)). Distinct from
|
|
13771
|
+
// clientEventId, whose uniqueness is per-session and so cannot dedup the
|
|
13772
|
+
// creation of a brand-new session. Absent means no create-dedup (each call
|
|
13773
|
+
// is an independent create).
|
|
13774
|
+
idempotencyKey: z.string().min(1).max(200).optional(),
|
|
13775
|
+
// The exact actor-private pre-session draft revision represented by this
|
|
13776
|
+
// create. An ordinary create consumes only this revision. A realtime create
|
|
13777
|
+
// preserves the editable draft and atomically updates only successful-create
|
|
13778
|
+
// selection history. A newer sibling draft survives, while every failed
|
|
13779
|
+
// pre-initialization create leaves the submitted draft intact.
|
|
13780
|
+
expectedNewSessionDraftRevision: z.number().int().nonnegative().optional(),
|
|
13781
|
+
// A child may lower its inherited limit freely; an increase requires
|
|
13782
|
+
// workspace:admin and is checked again at the DB transaction boundary.
|
|
13783
|
+
maxNestedAgentDepth: NestedAgentDepthValue.optional(),
|
|
13784
|
+
// Permissions the session's first-party MCP token should carry. A top-level
|
|
13785
|
+
// omission uses the deployment's worker default; a child omission inherits
|
|
13786
|
+
// the creating session's effective grant. An explicit set is capped at
|
|
13787
|
+
// creation: every requested permission must be held by the creating grant.
|
|
13788
|
+
// A goal-bearing session whose explicit/effective set omits goals:manage is
|
|
13789
|
+
// rejected; creation never silently expands a child beyond that set.
|
|
13790
|
+
firstPartyMcpPermissions: z.array(Permission).optional(),
|
|
13791
|
+
// Exact model-visible selection from the broad first-party OpenGeni MCP
|
|
13792
|
+
// catalog. Omission selects the safe non-connector default; [] intentionally
|
|
13793
|
+
// exposes none.
|
|
13794
|
+
// This does not grant authority: every registered tool is permission-gated.
|
|
13795
|
+
firstPartyMcpTools: z.array(FirstPartyMcpToolName).optional(),
|
|
13796
|
+
// Third-party MCP servers attached only to this session. For an agent-created
|
|
13797
|
+
// child, omission snapshots its trusted immediate parent's server definitions,
|
|
13798
|
+
// policies, connection refs, and encrypted credentials. Explicit arrays,
|
|
13799
|
+
// including [], are authoritative; non-empty explicit arrays require attach
|
|
13800
|
+
// permission. Credential headers are write-only: create responses and events
|
|
13801
|
+
// expose only SessionMcpServerMetadata.
|
|
13802
|
+
mcpServers: z.array(SessionMcpServerInput).max(SESSION_MCP_SERVERS_MAX).default([]),
|
|
13803
|
+
/** Explicit personal-connection grants for the initial accepted turn. */
|
|
13804
|
+
connectionAuthorities: McpConnectionAuthoritySelections.default([]),
|
|
13805
|
+
/** Atomic owner issuance for the selected personal Variable Set/Rig closure. */
|
|
13806
|
+
personalResourceAttachment: PersonalResourceAttachmentIntent.optional(),
|
|
13807
|
+
// Shared-sandbox placement (addendum 05 §D.1). Three-way union; OMITTED ⇒
|
|
13808
|
+
// today's behavior (a context-dependent default resolved server-side: from
|
|
13809
|
+
// inside a session → "shared" with the creator's box, top-level → "new"),
|
|
13810
|
+
// except a named targetSandboxId is always an own-box create ("new") because
|
|
13811
|
+
// a machine target is a different compute home. Explicit "shared"/{groupId}
|
|
13812
|
+
// plus a machine target is a 422.
|
|
13813
|
+
// - "shared": join the CREATOR's box. Requires a parent session (inferred
|
|
13814
|
+
// from the worker-signed sessionId claim, never caller-supplied);
|
|
13815
|
+
// top-level "shared" is a 422.
|
|
13816
|
+
// - "new": mint a fresh singleton box (group ≡ the new session's id).
|
|
13817
|
+
// - {groupId}: join a SPECIFIC sibling group in THIS workspace (manager
|
|
13818
|
+
// fan-out). Validated workspace-scoped (cross-workspace → 404).
|
|
13819
|
+
// A shared spawn inherits the box's (backend, os) — it is literally the same
|
|
13820
|
+
// box; the child cannot pick its own backend. Cross-workspace sharing is
|
|
13821
|
+
// forbidden by construction (the parent/group reads are RLS-workspace-scoped).
|
|
13822
|
+
// ENV-AWARE: the box's variable set is fixed at creation, so a share requires
|
|
13823
|
+
// the SAME variableSetId as the creator's box. On a mismatch the inherited
|
|
13824
|
+
// default silently falls back to an own box; an explicit "shared"/{groupId}
|
|
13825
|
+
// request 422s at create (instead of the first turn dying on the SDK's
|
|
13826
|
+
// manifest-env guard).
|
|
13827
|
+
sandbox: z
|
|
13828
|
+
.union([z.literal("shared"), z.literal("new"), z.object({ groupId: z.string().uuid() })])
|
|
13829
|
+
.optional(),
|
|
13830
|
+
},
|
|
13831
|
+
{ rejectKeys: ["turnInstructions"] },
|
|
13832
|
+
).superRefine((value, context) => {
|
|
11352
13833
|
if (value.startMode !== "realtime" && value.initialMessage === undefined) {
|
|
11353
13834
|
context.addIssue({
|
|
11354
13835
|
code: z.ZodIssueCode.custom,
|
|
@@ -11363,9 +13844,46 @@ export const CreateSessionRequest = withVariableSetIdAlias({
|
|
|
11363
13844
|
message: "initialMessage must be omitted when startMode is realtime",
|
|
11364
13845
|
});
|
|
11365
13846
|
}
|
|
13847
|
+
if (value.startMode === "realtime" && value.modelContext !== undefined) {
|
|
13848
|
+
context.addIssue({
|
|
13849
|
+
code: z.ZodIssueCode.custom,
|
|
13850
|
+
path: ["modelContext"],
|
|
13851
|
+
message: "modelContext requires an initialMessage; attach it to a realtime entry instead",
|
|
13852
|
+
});
|
|
13853
|
+
}
|
|
13854
|
+
if (value.startMode === "realtime" && value.connectionAuthorities.length > 0) {
|
|
13855
|
+
context.addIssue({
|
|
13856
|
+
code: z.ZodIssueCode.custom,
|
|
13857
|
+
path: ["connectionAuthorities"],
|
|
13858
|
+
message:
|
|
13859
|
+
"connectionAuthorities require an accepted initial turn and are not supported by realtime session staging",
|
|
13860
|
+
});
|
|
13861
|
+
}
|
|
13862
|
+
if (value.startMode === "realtime" && value.personalResourceAttachment !== undefined) {
|
|
13863
|
+
context.addIssue({
|
|
13864
|
+
code: z.ZodIssueCode.custom,
|
|
13865
|
+
path: ["personalResourceAttachment"],
|
|
13866
|
+
message:
|
|
13867
|
+
"personalResourceAttachment requires an accepted initial turn and is not supported by realtime session staging",
|
|
13868
|
+
});
|
|
13869
|
+
}
|
|
13870
|
+
if (value.personalResourceAttachment?.expectedAuthorityEpoch !== undefined) {
|
|
13871
|
+
context.addIssue({
|
|
13872
|
+
code: z.ZodIssueCode.custom,
|
|
13873
|
+
path: ["personalResourceAttachment", "expectedAuthorityEpoch"],
|
|
13874
|
+
message: "new-session attachment authority epoch is derived by the server",
|
|
13875
|
+
});
|
|
13876
|
+
}
|
|
11366
13877
|
});
|
|
11367
13878
|
export type CreateSessionRequest = z.infer<typeof CreateSessionRequest>;
|
|
11368
13879
|
|
|
13880
|
+
export const SessionTenancyCreateCapabilities = z.object({
|
|
13881
|
+
activated: z.boolean(),
|
|
13882
|
+
canCreatePrivate: z.boolean(),
|
|
13883
|
+
reason: z.enum(["available", "not_activated", "managed_session_required", "unavailable"]),
|
|
13884
|
+
});
|
|
13885
|
+
export type SessionTenancyCreateCapabilities = z.infer<typeof SessionTenancyCreateCapabilities>;
|
|
13886
|
+
|
|
11369
13887
|
// Generic, host-neutral structured human input. One model tool call creates one
|
|
11370
13888
|
// request containing one or more questions; the durable response resumes that
|
|
11371
13889
|
// exact call. This is deliberately distinct from tool approval: an answer,
|
|
@@ -11389,6 +13907,9 @@ export const HumanInputQuestion = z
|
|
|
11389
13907
|
helpText: z.string().max(2048).nullable().optional(),
|
|
11390
13908
|
options: z.array(HumanInputOption).max(20).default([]),
|
|
11391
13909
|
required: z.boolean().default(true),
|
|
13910
|
+
// Retained on the wire for older hosts. OpenGeni's stock runtime and
|
|
13911
|
+
// surfaces always expose Other for choice questions, including requests
|
|
13912
|
+
// that were persisted before that became the default behavior.
|
|
11392
13913
|
allowOther: z.boolean().default(false),
|
|
11393
13914
|
// Selection bounds only — agents invent useless text char mins/maxes.
|
|
11394
13915
|
// Answer strings stay platform-capped on HumanInputAnswer (~8192).
|
|
@@ -11549,9 +14070,9 @@ export const SessionUserMessagePayload = z
|
|
|
11549
14070
|
.object({
|
|
11550
14071
|
text: z.string().default(""),
|
|
11551
14072
|
annotations: SubmittedTimelineAnnotations.default([]),
|
|
11552
|
-
//
|
|
11553
|
-
//
|
|
11554
|
-
|
|
14073
|
+
// Model-visible application context attached to this exact user message.
|
|
14074
|
+
// It is retained in full event/history data but omitted by standard UI.
|
|
14075
|
+
modelContext: z.string().trim().min(1).max(32768).optional(),
|
|
11555
14076
|
resources: z.array(ResourceRef).default([]),
|
|
11556
14077
|
model: z.string().min(1).optional(),
|
|
11557
14078
|
reasoningEffort: ReasoningEffort.optional(),
|
|
@@ -11561,9 +14082,13 @@ export const SessionUserMessagePayload = z
|
|
|
11561
14082
|
// Header-value rotation only. URL/name/tool settings are immutable after
|
|
11562
14083
|
// session create; persisted events expose metadata, never header values.
|
|
11563
14084
|
mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
|
|
14085
|
+
/** Explicit personal-connection grants for this exact logical turn. */
|
|
14086
|
+
connectionAuthorities: McpConnectionAuthoritySelections.default([]),
|
|
14087
|
+
personalResourceAttachment: PersonalResourceAttachmentIntent.optional(),
|
|
11564
14088
|
})
|
|
11565
14089
|
.strict()
|
|
11566
|
-
.superRefine(requireMessageTextOrAnnotations)
|
|
14090
|
+
.superRefine(requireMessageTextOrAnnotations)
|
|
14091
|
+
.superRefine(requireEstablishedPersonalResourceEpoch);
|
|
11567
14092
|
export type SessionUserMessagePayload = z.infer<typeof SessionUserMessagePayload>;
|
|
11568
14093
|
|
|
11569
14094
|
export const ClientSessionEvent = z.discriminatedUnion("type", [
|
|
@@ -11596,8 +14121,8 @@ export const SteerSessionMessageRequest = z
|
|
|
11596
14121
|
.object({
|
|
11597
14122
|
text: z.string().default(""),
|
|
11598
14123
|
annotations: SubmittedTimelineAnnotations.default([]),
|
|
11599
|
-
// Same
|
|
11600
|
-
|
|
14124
|
+
// Same model-visible message context as a queued user.message.
|
|
14125
|
+
modelContext: z.string().trim().min(1).max(32768).optional(),
|
|
11601
14126
|
resources: z.array(ResourceRef).default([]),
|
|
11602
14127
|
model: z.string().min(1).optional(),
|
|
11603
14128
|
reasoningEffort: ReasoningEffort.optional(),
|
|
@@ -11606,17 +14131,36 @@ export const SteerSessionMessageRequest = z
|
|
|
11606
14131
|
controlEtag: z.string().min(1).optional(),
|
|
11607
14132
|
expectedDraftRevision: z.number().int().nonnegative().optional(),
|
|
11608
14133
|
mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
|
|
14134
|
+
/** Explicit personal-connection grants for this exact steered turn. */
|
|
14135
|
+
connectionAuthorities: McpConnectionAuthoritySelections.default([]),
|
|
14136
|
+
personalResourceAttachment: PersonalResourceAttachmentIntent.optional(),
|
|
11609
14137
|
})
|
|
11610
14138
|
.strict()
|
|
11611
|
-
.superRefine(requireMessageTextOrAnnotations)
|
|
14139
|
+
.superRefine(requireMessageTextOrAnnotations)
|
|
14140
|
+
.superRefine(requireEstablishedPersonalResourceEpoch);
|
|
11612
14141
|
export type SteerSessionMessageRequest = z.infer<typeof SteerSessionMessageRequest>;
|
|
11613
14142
|
|
|
11614
14143
|
export const SteerSessionMessageResponse = z.object({
|
|
11615
14144
|
accepted: SessionEvent,
|
|
11616
14145
|
turn: SessionTurn,
|
|
14146
|
+
receipt: SessionCommandReceipt,
|
|
14147
|
+
routing: SessionPromptRouting,
|
|
14148
|
+
interruptionCount: z.number().int().nonnegative(),
|
|
14149
|
+
replay: z.boolean(),
|
|
11617
14150
|
});
|
|
11618
14151
|
export type SteerSessionMessageResponse = z.infer<typeof SteerSessionMessageResponse>;
|
|
11619
14152
|
|
|
14153
|
+
export const SubmitComposerDraftResponse = z.object({
|
|
14154
|
+
accepted: SessionEvent,
|
|
14155
|
+
turn: SessionTurn,
|
|
14156
|
+
draft: ComposerDraft,
|
|
14157
|
+
receipt: SessionCommandReceipt,
|
|
14158
|
+
routing: SessionPromptRouting,
|
|
14159
|
+
interruptionCount: z.number().int().nonnegative(),
|
|
14160
|
+
replay: z.boolean(),
|
|
14161
|
+
});
|
|
14162
|
+
export type SubmitComposerDraftResponse = z.infer<typeof SubmitComposerDraftResponse>;
|
|
14163
|
+
|
|
11620
14164
|
export const SessionBusMessage = z.object({
|
|
11621
14165
|
workspaceId: z.string().uuid(),
|
|
11622
14166
|
sessionId: z.string().uuid(),
|
|
@@ -11707,6 +14251,7 @@ export const ClientAuthConfig = z.discriminatedUnion("mode", [
|
|
|
11707
14251
|
z.object({
|
|
11708
14252
|
mode: z.literal("managedSession"),
|
|
11709
14253
|
session: z.literal("cookie"),
|
|
14254
|
+
emailVerificationRequired: z.boolean().default(true),
|
|
11710
14255
|
}),
|
|
11711
14256
|
]);
|
|
11712
14257
|
export type ClientAuthConfig = z.infer<typeof ClientAuthConfig>;
|
|
@@ -11971,6 +14516,9 @@ export type DeviceEnrollmentStartResponse = z.infer<typeof DeviceEnrollmentStart
|
|
|
11971
14516
|
export const DeviceEnrollmentApproveRequest = z.object({
|
|
11972
14517
|
userCode: z.string().min(1).max(64),
|
|
11973
14518
|
allowScreenControl: z.boolean().default(false),
|
|
14519
|
+
// Human-approved machines are private by default. Workspace/organization
|
|
14520
|
+
// publication is an explicit consent choice at this same loud boundary.
|
|
14521
|
+
scope: ResourceAuthorityScope.default("user"),
|
|
11974
14522
|
});
|
|
11975
14523
|
export type DeviceEnrollmentApproveRequest = z.infer<typeof DeviceEnrollmentApproveRequest>;
|
|
11976
14524
|
|
|
@@ -12043,6 +14591,8 @@ export type DeviceEnrollmentPollResponse = z.infer<typeof DeviceEnrollmentPollRe
|
|
|
12043
14591
|
// GET /enrollments — a workspace's machines (the Machines dashboard surface).
|
|
12044
14592
|
export const EnrollmentSummary = z.object({
|
|
12045
14593
|
id: z.string().uuid(),
|
|
14594
|
+
scope: ResourceAuthorityScope,
|
|
14595
|
+
generation: z.number().int().positive(),
|
|
12046
14596
|
pubkey: z.string(),
|
|
12047
14597
|
exposure: z.literal("whole-machine"),
|
|
12048
14598
|
hasDisplay: z.boolean(),
|
|
@@ -12239,9 +14789,137 @@ export const MachineState = z.enum([
|
|
|
12239
14789
|
]);
|
|
12240
14790
|
export type MachineState = z.infer<typeof MachineState>;
|
|
12241
14791
|
|
|
12242
|
-
export const MachineKind = z.enum(["modal", "selfhosted"]);
|
|
14792
|
+
export const MachineKind = z.enum(["modal", "selfhosted", "opensandbox"]);
|
|
12243
14793
|
export type MachineKind = z.infer<typeof MachineKind>;
|
|
12244
14794
|
|
|
14795
|
+
/** Diagnostic projection of the single live Connected-Machine runner authority.
|
|
14796
|
+
* It contains no bearer or NATS subject material. `supersededCount` is derived
|
|
14797
|
+
* from the monotonic generation; duplicate-denial evidence records valid
|
|
14798
|
+
* competing processes that were prevented from receiving work. */
|
|
14799
|
+
export const MachineConnectionAuthority = z.object({
|
|
14800
|
+
state: z.enum(["not_applicable", "unclaimed", "active", "expired"]),
|
|
14801
|
+
generation: z.number().int().nonnegative(),
|
|
14802
|
+
supersededCount: z.number().int().nonnegative(),
|
|
14803
|
+
leaseExpiresAt: z.string().nullable(),
|
|
14804
|
+
duplicateRunnerDeniedCount: z.number().int().nonnegative(),
|
|
14805
|
+
duplicateRunnerDeniedAt: z.string().nullable(),
|
|
14806
|
+
});
|
|
14807
|
+
export type MachineConnectionAuthority = z.infer<typeof MachineConnectionAuthority>;
|
|
14808
|
+
|
|
14809
|
+
export const MachineRuntimeCapabilities = z.object({
|
|
14810
|
+
exec: z.boolean(),
|
|
14811
|
+
filesystem: z.boolean(),
|
|
14812
|
+
git: z.boolean(),
|
|
14813
|
+
pty: z.boolean(),
|
|
14814
|
+
desktop: z.boolean(),
|
|
14815
|
+
opStream: z.boolean(),
|
|
14816
|
+
browserBridge: z.boolean(),
|
|
14817
|
+
operationResourcePolicy: z.boolean(),
|
|
14818
|
+
operationCpuQuota: z.boolean(),
|
|
14819
|
+
});
|
|
14820
|
+
export type MachineRuntimeCapabilities = z.infer<typeof MachineRuntimeCapabilities>;
|
|
14821
|
+
|
|
14822
|
+
export const MachineUpdateStatus = z.enum([
|
|
14823
|
+
"requested",
|
|
14824
|
+
"accepted",
|
|
14825
|
+
"waiting_for_idle",
|
|
14826
|
+
"downloading",
|
|
14827
|
+
"verifying",
|
|
14828
|
+
"applying",
|
|
14829
|
+
"restarting",
|
|
14830
|
+
"succeeded",
|
|
14831
|
+
"failed",
|
|
14832
|
+
]);
|
|
14833
|
+
export type MachineUpdateStatus = z.infer<typeof MachineUpdateStatus>;
|
|
14834
|
+
|
|
14835
|
+
export const MachineUpdateState = z.object({
|
|
14836
|
+
operationId: z.string().uuid(),
|
|
14837
|
+
status: MachineUpdateStatus,
|
|
14838
|
+
targetVersion: z.string(),
|
|
14839
|
+
expectedBinarySha256: z
|
|
14840
|
+
.string()
|
|
14841
|
+
.regex(/^[0-9a-f]{64}$/)
|
|
14842
|
+
.nullable(),
|
|
14843
|
+
errorCode: z.string().nullable(),
|
|
14844
|
+
retryable: z.boolean(),
|
|
14845
|
+
rolledBack: z.boolean(),
|
|
14846
|
+
requestedAt: z.string(),
|
|
14847
|
+
updatedAt: z.string(),
|
|
14848
|
+
completedAt: z.string().nullable(),
|
|
14849
|
+
});
|
|
14850
|
+
export type MachineUpdateState = z.infer<typeof MachineUpdateState>;
|
|
14851
|
+
|
|
14852
|
+
export const MachineRuntime = z.object({
|
|
14853
|
+
installedVersion: z.string().nullable(),
|
|
14854
|
+
binarySha256: z
|
|
14855
|
+
.string()
|
|
14856
|
+
.regex(/^[0-9a-f]{64}$/)
|
|
14857
|
+
.nullable(),
|
|
14858
|
+
updateChannel: z.enum(["stable", "beta"]).nullable(),
|
|
14859
|
+
desiredVersion: z.string().nullable(),
|
|
14860
|
+
versionState: z.enum(["unknown", "current", "outdated", "ahead", "updating", "update_failed"]),
|
|
14861
|
+
capabilities: MachineRuntimeCapabilities,
|
|
14862
|
+
update: MachineUpdateState.nullable(),
|
|
14863
|
+
});
|
|
14864
|
+
export type MachineRuntime = z.infer<typeof MachineRuntime>;
|
|
14865
|
+
|
|
14866
|
+
export const UpdateMachineAgentResponse = z.object({
|
|
14867
|
+
operationId: z.string().uuid(),
|
|
14868
|
+
accepted: z.boolean(),
|
|
14869
|
+
targetVersion: z.string(),
|
|
14870
|
+
});
|
|
14871
|
+
export type UpdateMachineAgentResponse = z.infer<typeof UpdateMachineAgentResponse>;
|
|
14872
|
+
|
|
14873
|
+
const OperationMemoryBytes = z.number().int().positive().max(Number.MAX_SAFE_INTEGER).nullable();
|
|
14874
|
+
const OperationCpuMillicores = z.number().int().positive().max(0xffff_ffff).nullable();
|
|
14875
|
+
|
|
14876
|
+
function operationPolicyShape(
|
|
14877
|
+
value: {
|
|
14878
|
+
memoryMaxBytes: number | null;
|
|
14879
|
+
memoryHighBytes: number | null;
|
|
14880
|
+
cpuMaxMillicores?: number | null | undefined;
|
|
14881
|
+
},
|
|
14882
|
+
ctx: z.RefinementCtx,
|
|
14883
|
+
): void {
|
|
14884
|
+
if (
|
|
14885
|
+
value.memoryMaxBytes !== null &&
|
|
14886
|
+
value.memoryHighBytes !== null &&
|
|
14887
|
+
value.memoryHighBytes > value.memoryMaxBytes
|
|
14888
|
+
) {
|
|
14889
|
+
ctx.addIssue({
|
|
14890
|
+
code: z.ZodIssueCode.custom,
|
|
14891
|
+
path: ["memoryHighBytes"],
|
|
14892
|
+
message: "memoryHighBytes cannot exceed memoryMaxBytes",
|
|
14893
|
+
});
|
|
14894
|
+
}
|
|
14895
|
+
}
|
|
14896
|
+
|
|
14897
|
+
/** Optional per-connection command resource policy. CPU is a period-independent
|
|
14898
|
+
* millicore ratio; runners choose a documented representable cgroup period. Null
|
|
14899
|
+
* values are unrestricted; revision is the optimistic concurrency fence. */
|
|
14900
|
+
export const MachineOperationPolicy = z
|
|
14901
|
+
.object({
|
|
14902
|
+
memoryMaxBytes: OperationMemoryBytes,
|
|
14903
|
+
memoryHighBytes: OperationMemoryBytes,
|
|
14904
|
+
cpuMaxMillicores: OperationCpuMillicores,
|
|
14905
|
+
revision: z.number().int().nonnegative(),
|
|
14906
|
+
updatedAt: z.string().nullable(),
|
|
14907
|
+
})
|
|
14908
|
+
.superRefine(operationPolicyShape);
|
|
14909
|
+
export type MachineOperationPolicy = z.infer<typeof MachineOperationPolicy>;
|
|
14910
|
+
|
|
14911
|
+
export const UpdateMachineOperationPolicyRequest = z
|
|
14912
|
+
.object({
|
|
14913
|
+
memoryMaxBytes: OperationMemoryBytes,
|
|
14914
|
+
memoryHighBytes: OperationMemoryBytes,
|
|
14915
|
+
cpuMaxMillicores: OperationCpuMillicores.optional(),
|
|
14916
|
+
expectedRevision: z.number().int().nonnegative(),
|
|
14917
|
+
})
|
|
14918
|
+
.superRefine(operationPolicyShape);
|
|
14919
|
+
export type UpdateMachineOperationPolicyRequest = z.infer<
|
|
14920
|
+
typeof UpdateMachineOperationPolicyRequest
|
|
14921
|
+
>;
|
|
14922
|
+
|
|
12245
14923
|
/**
|
|
12246
14924
|
* A machine as the Machines dashboard renders it. The workspace's enrolled
|
|
12247
14925
|
* selfhosted machines PLUS the session's synthetic Modal group box
|
|
@@ -12253,6 +14931,8 @@ export type MachineKind = z.infer<typeof MachineKind>;
|
|
|
12253
14931
|
export const MachineView = z.object({
|
|
12254
14932
|
sandboxId: z.string(),
|
|
12255
14933
|
enrollmentId: z.string().nullable(),
|
|
14934
|
+
scope: ResourceAuthorityScope.default("workspace"),
|
|
14935
|
+
generation: z.number().int().positive().default(1),
|
|
12256
14936
|
name: z.string(),
|
|
12257
14937
|
kind: MachineKind,
|
|
12258
14938
|
state: MachineState,
|
|
@@ -12271,6 +14951,12 @@ export const MachineView = z.object({
|
|
|
12271
14951
|
allowScreenControl: z.boolean(),
|
|
12272
14952
|
sharedSessionCount: z.number().int(),
|
|
12273
14953
|
lastSeenAt: z.string().nullable(),
|
|
14954
|
+
connectionAuthority: MachineConnectionAuthority,
|
|
14955
|
+
// Exact connected-agent build/capabilities and current update operation. Null
|
|
14956
|
+
// for managed/session sandboxes and pre-runtime-reporting synthetic rows.
|
|
14957
|
+
runtime: MachineRuntime.nullable().default(null),
|
|
14958
|
+
// Per-enrollment desired policy. Null for managed/session sandboxes.
|
|
14959
|
+
operationPolicy: MachineOperationPolicy.nullable().default(null),
|
|
12274
14960
|
metrics: MetricSample.nullable(),
|
|
12275
14961
|
});
|
|
12276
14962
|
export type MachineView = z.infer<typeof MachineView>;
|
|
@@ -12347,8 +15033,9 @@ function defineModelContractSchema<Schema>(factory: () => Schema): Schema {
|
|
|
12347
15033
|
return factory();
|
|
12348
15034
|
}
|
|
12349
15035
|
|
|
12350
|
-
export const ModelCapabilitySupportV1 =
|
|
12351
|
-
|
|
15036
|
+
export const ModelCapabilitySupportV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15037
|
+
z.enum(["supported", "unsupported", "unknown"]),
|
|
15038
|
+
);
|
|
12352
15039
|
export type ModelCapabilitySupportV1 = z.infer<typeof ModelCapabilitySupportV1>;
|
|
12353
15040
|
|
|
12354
15041
|
export const ModelCapabilityStateV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
@@ -12396,60 +15083,65 @@ export const ModelCapabilitiesV1 = /* @__PURE__ */ defineModelContractSchema(()
|
|
|
12396
15083
|
);
|
|
12397
15084
|
export type ModelCapabilitiesV1 = z.infer<typeof ModelCapabilitiesV1>;
|
|
12398
15085
|
|
|
12399
|
-
export const ModelCredentialSourceV1 =
|
|
12400
|
-
|
|
12401
|
-
z.union([
|
|
12402
|
-
z
|
|
12403
|
-
.object({
|
|
12404
|
-
kind: z.literal("deployment"),
|
|
12405
|
-
mechanism: z.enum(["api_key", "azure_ad_bearer"]),
|
|
12406
|
-
})
|
|
12407
|
-
.strict(),
|
|
12408
|
-
z
|
|
12409
|
-
.object({
|
|
12410
|
-
kind: z.literal("connected_subscription"),
|
|
12411
|
-
provider: z.enum(["codex", "xai"]),
|
|
12412
|
-
})
|
|
12413
|
-
.strict(),
|
|
12414
|
-
z
|
|
12415
|
-
.object({
|
|
12416
|
-
kind: z.literal("workspace_connection"),
|
|
12417
|
-
mechanism: z.literal("api_key"),
|
|
12418
|
-
})
|
|
12419
|
-
.strict(),
|
|
12420
|
-
]),
|
|
12421
|
-
);
|
|
12422
|
-
export type ModelCredentialSourceV1 = z.infer<typeof ModelCredentialSourceV1>;
|
|
12423
|
-
|
|
12424
|
-
export const ModelBillingAttributionV1 =
|
|
12425
|
-
/* @__PURE__ */ defineModelContractSchema(() =>
|
|
15086
|
+
export const ModelCredentialSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15087
|
+
z.union([
|
|
12426
15088
|
z
|
|
12427
15089
|
.object({
|
|
12428
|
-
|
|
12429
|
-
|
|
15090
|
+
kind: z.literal("deployment"),
|
|
15091
|
+
mechanism: z.enum(["api_key", "azure_ad_bearer"]),
|
|
12430
15092
|
})
|
|
12431
15093
|
.strict(),
|
|
12432
|
-
|
|
15094
|
+
z
|
|
15095
|
+
.object({
|
|
15096
|
+
kind: z.literal("connected_subscription"),
|
|
15097
|
+
provider: z.enum(["codex", "xai"]),
|
|
15098
|
+
})
|
|
15099
|
+
.strict(),
|
|
15100
|
+
z
|
|
15101
|
+
.object({
|
|
15102
|
+
kind: z.literal("workspace_connection"),
|
|
15103
|
+
mechanism: z.literal("api_key"),
|
|
15104
|
+
})
|
|
15105
|
+
.strict(),
|
|
15106
|
+
]),
|
|
15107
|
+
);
|
|
15108
|
+
export type ModelCredentialSourceV1 = z.infer<typeof ModelCredentialSourceV1>;
|
|
15109
|
+
|
|
15110
|
+
const TurnExecutionCredentialSourceV1 = z.union([
|
|
15111
|
+
ModelCredentialSourceV1,
|
|
15112
|
+
z
|
|
15113
|
+
.object({
|
|
15114
|
+
kind: z.literal("deployment"),
|
|
15115
|
+
mechanism: z.literal("none"),
|
|
15116
|
+
})
|
|
15117
|
+
.strict(),
|
|
15118
|
+
]);
|
|
15119
|
+
|
|
15120
|
+
export const ModelBillingAttributionV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15121
|
+
z
|
|
15122
|
+
.object({
|
|
15123
|
+
upstreamPayer: z.enum(["deployment", "workspace", "connected_subscription"]),
|
|
15124
|
+
metering: z.enum(["opengeni_credits", "external"]),
|
|
15125
|
+
})
|
|
15126
|
+
.strict(),
|
|
15127
|
+
);
|
|
12433
15128
|
export type ModelBillingAttributionV1 = z.infer<typeof ModelBillingAttributionV1>;
|
|
12434
15129
|
|
|
12435
15130
|
export const TURN_EXECUTION_POLICY_METADATA_KEY = "turnExecutionPolicyV1" as const;
|
|
12436
15131
|
|
|
12437
|
-
export const TurnExecutionModelSourceV1 =
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
);
|
|
15132
|
+
export const TurnExecutionModelSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15133
|
+
z.enum(["explicit", "session", "deployment", "continuation"]),
|
|
15134
|
+
);
|
|
12441
15135
|
export type TurnExecutionModelSourceV1 = z.infer<typeof TurnExecutionModelSourceV1>;
|
|
12442
15136
|
|
|
12443
|
-
export const TurnExecutionReasoningSourceV1 =
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
);
|
|
15137
|
+
export const TurnExecutionReasoningSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15138
|
+
z.enum(["explicit", "session", "deployment", "continuation"]),
|
|
15139
|
+
);
|
|
12447
15140
|
export type TurnExecutionReasoningSourceV1 = z.infer<typeof TurnExecutionReasoningSourceV1>;
|
|
12448
15141
|
|
|
12449
|
-
export const TurnExecutionLatencyModeSourceV1 =
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
);
|
|
15142
|
+
export const TurnExecutionLatencyModeSourceV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15143
|
+
z.enum(["explicit", "session", "deployment", "continuation"]),
|
|
15144
|
+
);
|
|
12453
15145
|
export type TurnExecutionLatencyModeSourceV1 = z.infer<typeof TurnExecutionLatencyModeSourceV1>;
|
|
12454
15146
|
|
|
12455
15147
|
/**
|
|
@@ -12477,7 +15169,7 @@ export const TurnExecutionPolicyV1 = /* @__PURE__ */ defineModelContractSchema((
|
|
|
12477
15169
|
providerId: z.string().min(1),
|
|
12478
15170
|
upstreamModelId: z.string().min(1),
|
|
12479
15171
|
wireApi: z.enum(["responses", "chat"]),
|
|
12480
|
-
credentialSource:
|
|
15172
|
+
credentialSource: TurnExecutionCredentialSourceV1,
|
|
12481
15173
|
billing: ModelBillingAttributionV1,
|
|
12482
15174
|
definitionVersion: z.string().regex(/^sha256:[a-f0-9]{64}$/u),
|
|
12483
15175
|
})
|
|
@@ -12651,60 +15343,59 @@ export const ClientModel = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
|
12651
15343
|
);
|
|
12652
15344
|
export type ClientModel = z.infer<typeof ClientModel>;
|
|
12653
15345
|
|
|
12654
|
-
export const ModelCredentialReadinessV1 =
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
.
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
|
|
12692
|
-
|
|
12693
|
-
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12697
|
-
|
|
12698
|
-
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12707
|
-
);
|
|
15346
|
+
export const ModelCredentialReadinessV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15347
|
+
z
|
|
15348
|
+
.object({
|
|
15349
|
+
status: z.enum(["ready", "not_ready", "error"]),
|
|
15350
|
+
reason: z
|
|
15351
|
+
.enum([
|
|
15352
|
+
"missing_credential",
|
|
15353
|
+
"needs_reauth",
|
|
15354
|
+
"prerequisites_missing",
|
|
15355
|
+
"resolver_error",
|
|
15356
|
+
"observation_stale",
|
|
15357
|
+
])
|
|
15358
|
+
.nullable(),
|
|
15359
|
+
basis: z.enum(["configuration", "connection", "resolver"]),
|
|
15360
|
+
checkedAt: z.string().datetime().nullable(),
|
|
15361
|
+
})
|
|
15362
|
+
.strict()
|
|
15363
|
+
.superRefine((readiness, context) => {
|
|
15364
|
+
if ((readiness.status === "ready") !== (readiness.reason === null)) {
|
|
15365
|
+
context.addIssue({
|
|
15366
|
+
code: "custom",
|
|
15367
|
+
path: ["reason"],
|
|
15368
|
+
message: "ready credential state requires no reason; non-ready state requires a reason",
|
|
15369
|
+
});
|
|
15370
|
+
}
|
|
15371
|
+
if ((readiness.status === "error") !== (readiness.reason === "resolver_error")) {
|
|
15372
|
+
context.addIssue({
|
|
15373
|
+
code: "custom",
|
|
15374
|
+
path: ["reason"],
|
|
15375
|
+
message:
|
|
15376
|
+
"credential errors require resolver_error and resolver_error requires error status",
|
|
15377
|
+
});
|
|
15378
|
+
}
|
|
15379
|
+
if (
|
|
15380
|
+
readiness.basis === "resolver" &&
|
|
15381
|
+
readiness.status === "ready" &&
|
|
15382
|
+
readiness.checkedAt === null
|
|
15383
|
+
) {
|
|
15384
|
+
context.addIssue({
|
|
15385
|
+
code: "custom",
|
|
15386
|
+
path: ["checkedAt"],
|
|
15387
|
+
message: "resolver readiness requires an observation timestamp",
|
|
15388
|
+
});
|
|
15389
|
+
}
|
|
15390
|
+
if (readiness.reason === "observation_stale" && readiness.checkedAt === null) {
|
|
15391
|
+
context.addIssue({
|
|
15392
|
+
code: "custom",
|
|
15393
|
+
path: ["checkedAt"],
|
|
15394
|
+
message: "a stale observation requires its observation timestamp",
|
|
15395
|
+
});
|
|
15396
|
+
}
|
|
15397
|
+
}),
|
|
15398
|
+
);
|
|
12708
15399
|
export type ModelCredentialReadinessV1 = z.infer<typeof ModelCredentialReadinessV1>;
|
|
12709
15400
|
|
|
12710
15401
|
export const ModelAvailabilityV1 = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
@@ -12727,21 +15418,21 @@ export const ModelAvailabilityV1 = /* @__PURE__ */ defineModelContractSchema(()
|
|
|
12727
15418
|
);
|
|
12728
15419
|
export type ModelAvailabilityV1 = z.infer<typeof ModelAvailabilityV1>;
|
|
12729
15420
|
|
|
12730
|
-
export const WorkspaceModelCatalogModel =
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
12735
|
-
|
|
12736
|
-
)
|
|
15421
|
+
export const WorkspaceModelCatalogModel = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15422
|
+
ClientModel.extend({
|
|
15423
|
+
credentialReadiness: ModelCredentialReadinessV1,
|
|
15424
|
+
/** Exact workspace-policy verdict without exposing provider identity. */
|
|
15425
|
+
policyAllowed: z.boolean().optional(),
|
|
15426
|
+
availability: ModelAvailabilityV1,
|
|
15427
|
+
}),
|
|
15428
|
+
);
|
|
12737
15429
|
export type WorkspaceModelCatalogModel = z.infer<typeof WorkspaceModelCatalogModel>;
|
|
12738
15430
|
|
|
12739
|
-
export const WorkspaceModelCatalogResponse =
|
|
12740
|
-
|
|
12741
|
-
z.
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
);
|
|
15431
|
+
export const WorkspaceModelCatalogResponse = /* @__PURE__ */ defineModelContractSchema(() =>
|
|
15432
|
+
z.object({
|
|
15433
|
+
models: z.array(WorkspaceModelCatalogModel),
|
|
15434
|
+
}),
|
|
15435
|
+
);
|
|
12745
15436
|
export type WorkspaceModelCatalogResponse = z.infer<typeof WorkspaceModelCatalogResponse>;
|
|
12746
15437
|
|
|
12747
15438
|
/**
|
|
@@ -12752,7 +15443,7 @@ export type WorkspaceModelCatalogResponse = z.infer<typeof WorkspaceModelCatalog
|
|
|
12752
15443
|
* that rollout boundary. Mutating clients send this value in
|
|
12753
15444
|
* `x-opengeni-api-contract`; the API rejects any other value before routing.
|
|
12754
15445
|
*/
|
|
12755
|
-
export const OPENGENI_API_CONTRACT_REVISION = "2026-08-
|
|
15446
|
+
export const OPENGENI_API_CONTRACT_REVISION = "2026-08-atomic-session-fork-visibility-v1" as const;
|
|
12756
15447
|
export const OPENGENI_API_CONTRACT_HEADER = "x-opengeni-api-contract" as const;
|
|
12757
15448
|
/** Bounded request/response identifier shared by browser, ingress, and API diagnostics. */
|
|
12758
15449
|
export const OPENGENI_CORRELATION_HEADER = "x-opengeni-correlation-id" as const;
|
|
@@ -12926,10 +15617,18 @@ export * from "./codex-fleet-policy";
|
|
|
12926
15617
|
export * from "./xai-provider-account-authority";
|
|
12927
15618
|
export * from "./workspace-instruction-policies";
|
|
12928
15619
|
export * from "./company-profile";
|
|
15620
|
+
export * from "./company-brain";
|
|
12929
15621
|
export * from "./workspace-learning-policy";
|
|
15622
|
+
export * from "./workspace-learning-administration";
|
|
12930
15623
|
export * from "./workspace-state";
|
|
12931
15624
|
export * from "./preference-registry";
|
|
12932
15625
|
export * from "./scoped-knowledge";
|
|
15626
|
+
export * from "./company-brain-governed-writes";
|
|
15627
|
+
export * from "./governed-learning-evaluator";
|
|
15628
|
+
export * from "./governed-learning-activation";
|
|
12933
15629
|
export * from "./knowledge";
|
|
12934
15630
|
export * from "./task-notes";
|
|
12935
15631
|
export * from "./canonical-human-identities";
|
|
15632
|
+
export * from "./organization-membership-lifecycle";
|
|
15633
|
+
export * from "./remember";
|
|
15634
|
+
export * from "./agent-authored-durable-text";
|