@opengeni/contracts 1.0.1 → 2.3.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-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-NX5JNF4L.js → chunk-XW2RKNEU.js} +9410 -5799
- package/dist/chunk-XW2RKNEU.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 +1 -0
- package/dist/google-drive.js +14 -13
- 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 +12426 -1313
- package/dist/index.js +855 -115
- package/dist/interaction.d.ts +68 -0
- package/dist/knowledge.d.ts +119 -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/governed-learning-activation.ts +191 -0
- package/src/governed-learning-evaluator.ts +176 -0
- package/src/index.ts +3148 -369
- package/src/interaction.ts +55 -1
- package/src/knowledge.ts +118 -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-NX5JNF4L.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
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { ConnectionMetadata } from "./index";
|
|
4
|
+
|
|
5
|
+
export const PERSONAL_GITHUB_PROVIDER_DOMAIN = "github.com" as const;
|
|
6
|
+
export const PERSONAL_GITHUB_PROVIDER_FAMILY = "github" as const;
|
|
7
|
+
export const PERSONAL_GITHUB_CREDENTIAL_ROLE = "opengeni_github_personal" as const;
|
|
8
|
+
export const PERSONAL_GITHUB_CONNECTION_SURFACE_ID = "github:personal" as const;
|
|
9
|
+
export const PERSONAL_GITHUB_REQUESTED_SCOPES = ["repo"] as const;
|
|
10
|
+
export const PERSONAL_GITHUB_AUTHORIZATION_URL =
|
|
11
|
+
"https://github.com/login/oauth/authorize" as const;
|
|
12
|
+
export const PERSONAL_GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token" as const;
|
|
13
|
+
export const PERSONAL_GITHUB_USER_URL = "https://api.github.com/user" as const;
|
|
14
|
+
export const PERSONAL_GITHUB_API_ORIGIN = "https://api.github.com" as const;
|
|
15
|
+
export const PERSONAL_GITHUB_REPOSITORY_CATALOG_MAX = 100 as const;
|
|
16
|
+
|
|
17
|
+
export const PersonalGitHubRepositoryId = z.string().regex(/^[1-9]\d*$/u);
|
|
18
|
+
export type PersonalGitHubRepositoryId = z.infer<typeof PersonalGitHubRepositoryId>;
|
|
19
|
+
|
|
20
|
+
export const PersonalGitHubRepositoryAccess = z.enum(["read", "write"]);
|
|
21
|
+
export type PersonalGitHubRepositoryAccess = z.infer<typeof PersonalGitHubRepositoryAccess>;
|
|
22
|
+
|
|
23
|
+
export const PersonalGitHubRepositoryPermissions = z
|
|
24
|
+
.object({
|
|
25
|
+
pull: z.boolean(),
|
|
26
|
+
push: z.boolean(),
|
|
27
|
+
admin: z.boolean(),
|
|
28
|
+
maintain: z.boolean(),
|
|
29
|
+
triage: z.boolean(),
|
|
30
|
+
})
|
|
31
|
+
.strict();
|
|
32
|
+
export type PersonalGitHubRepositoryPermissions = z.infer<
|
|
33
|
+
typeof PersonalGitHubRepositoryPermissions
|
|
34
|
+
>;
|
|
35
|
+
|
|
36
|
+
export const PersonalGitHubRepositoryVisibility = z.enum(["public", "private", "internal"]);
|
|
37
|
+
export type PersonalGitHubRepositoryVisibility = z.infer<typeof PersonalGitHubRepositoryVisibility>;
|
|
38
|
+
|
|
39
|
+
const PersonalGitHubRepositoryFullName = z
|
|
40
|
+
.string()
|
|
41
|
+
.min(3)
|
|
42
|
+
.max(140)
|
|
43
|
+
.regex(/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9_.-]{1,100}$/u);
|
|
44
|
+
|
|
45
|
+
export function canonicalPersonalGitHubRepositoryUrl(fullName: string): string {
|
|
46
|
+
return `https://github.com/${fullName}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** A bounded, credential-free projection verified directly against GitHub. */
|
|
50
|
+
export const PersonalGitHubRepository = z
|
|
51
|
+
.object({
|
|
52
|
+
repositoryId: PersonalGitHubRepositoryId,
|
|
53
|
+
fullName: PersonalGitHubRepositoryFullName,
|
|
54
|
+
canonicalUrl: z.string().url().max(512),
|
|
55
|
+
defaultBranch: z.string().min(1).max(255),
|
|
56
|
+
visibility: PersonalGitHubRepositoryVisibility,
|
|
57
|
+
private: z.boolean(),
|
|
58
|
+
archived: z.boolean(),
|
|
59
|
+
disabled: z.boolean(),
|
|
60
|
+
permissions: PersonalGitHubRepositoryPermissions,
|
|
61
|
+
})
|
|
62
|
+
.strict()
|
|
63
|
+
.superRefine((repository, context) => {
|
|
64
|
+
if (repository.canonicalUrl !== canonicalPersonalGitHubRepositoryUrl(repository.fullName)) {
|
|
65
|
+
context.addIssue({
|
|
66
|
+
code: "custom",
|
|
67
|
+
path: ["canonicalUrl"],
|
|
68
|
+
message: "canonicalUrl must be derived from fullName",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (repository.private !== (repository.visibility === "private")) {
|
|
72
|
+
context.addIssue({
|
|
73
|
+
code: "custom",
|
|
74
|
+
path: ["private"],
|
|
75
|
+
message: "private must agree with visibility",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
export type PersonalGitHubRepository = z.infer<typeof PersonalGitHubRepository>;
|
|
80
|
+
|
|
81
|
+
export const PersonalGitHubSelectedRepository = PersonalGitHubRepository.safeExtend({
|
|
82
|
+
selectedAccess: PersonalGitHubRepositoryAccess,
|
|
83
|
+
selectionGeneration: z.number().int().positive(),
|
|
84
|
+
selectedAt: z.string().datetime({ offset: true }),
|
|
85
|
+
lastVerifiedAt: z.string().datetime({ offset: true }),
|
|
86
|
+
}).strict();
|
|
87
|
+
export type PersonalGitHubSelectedRepository = z.infer<typeof PersonalGitHubSelectedRepository>;
|
|
88
|
+
|
|
89
|
+
export const PersonalGitHubRepositorySelectionState = z
|
|
90
|
+
.object({
|
|
91
|
+
connectionAuthorityGeneration: z.number().int().positive(),
|
|
92
|
+
credentialBindingId: z.string().uuid(),
|
|
93
|
+
providerPrincipalId: PersonalGitHubRepositoryId,
|
|
94
|
+
selectionGeneration: z.number().int().nonnegative(),
|
|
95
|
+
repositories: z
|
|
96
|
+
.array(PersonalGitHubSelectedRepository)
|
|
97
|
+
.max(PERSONAL_GITHUB_REPOSITORY_CATALOG_MAX),
|
|
98
|
+
})
|
|
99
|
+
.strict();
|
|
100
|
+
export type PersonalGitHubRepositorySelectionState = z.infer<
|
|
101
|
+
typeof PersonalGitHubRepositorySelectionState
|
|
102
|
+
>;
|
|
103
|
+
|
|
104
|
+
export const ListPersonalGitHubRepositoriesQuery = z
|
|
105
|
+
.object({
|
|
106
|
+
cursor: z.coerce.number().int().positive().max(10_000).default(1),
|
|
107
|
+
limit: z.coerce.number().int().min(1).max(PERSONAL_GITHUB_REPOSITORY_CATALOG_MAX).default(50),
|
|
108
|
+
})
|
|
109
|
+
.strict();
|
|
110
|
+
export type ListPersonalGitHubRepositoriesQuery = z.infer<
|
|
111
|
+
typeof ListPersonalGitHubRepositoriesQuery
|
|
112
|
+
>;
|
|
113
|
+
|
|
114
|
+
export const PersonalGitHubRepositoryCatalogItem = PersonalGitHubRepository.safeExtend({
|
|
115
|
+
selectedAccess: PersonalGitHubRepositoryAccess.nullable(),
|
|
116
|
+
}).strict();
|
|
117
|
+
export type PersonalGitHubRepositoryCatalogItem = z.infer<
|
|
118
|
+
typeof PersonalGitHubRepositoryCatalogItem
|
|
119
|
+
>;
|
|
120
|
+
|
|
121
|
+
export const ListPersonalGitHubRepositoriesResponse = z
|
|
122
|
+
.object({
|
|
123
|
+
repositories: z
|
|
124
|
+
.array(PersonalGitHubRepositoryCatalogItem)
|
|
125
|
+
.max(PERSONAL_GITHUB_REPOSITORY_CATALOG_MAX),
|
|
126
|
+
nextCursor: z.number().int().positive().nullable(),
|
|
127
|
+
selection: PersonalGitHubRepositorySelectionState,
|
|
128
|
+
})
|
|
129
|
+
.strict();
|
|
130
|
+
export type ListPersonalGitHubRepositoriesResponse = z.infer<
|
|
131
|
+
typeof ListPersonalGitHubRepositoriesResponse
|
|
132
|
+
>;
|
|
133
|
+
|
|
134
|
+
export const PersonalGitHubRepositorySelectionInput = z
|
|
135
|
+
.object({
|
|
136
|
+
repositoryId: PersonalGitHubRepositoryId,
|
|
137
|
+
fullName: PersonalGitHubRepositoryFullName,
|
|
138
|
+
access: PersonalGitHubRepositoryAccess,
|
|
139
|
+
})
|
|
140
|
+
.strict();
|
|
141
|
+
export type PersonalGitHubRepositorySelectionInput = z.infer<
|
|
142
|
+
typeof PersonalGitHubRepositorySelectionInput
|
|
143
|
+
>;
|
|
144
|
+
|
|
145
|
+
export const ReplacePersonalGitHubRepositorySelectionsRequest = z
|
|
146
|
+
.object({
|
|
147
|
+
expectedConnectionAuthorityGeneration: z.number().int().positive(),
|
|
148
|
+
expectedSelectionGeneration: z.number().int().nonnegative(),
|
|
149
|
+
idempotencyKey: z.string().trim().min(1).max(200),
|
|
150
|
+
repositories: z
|
|
151
|
+
.array(PersonalGitHubRepositorySelectionInput)
|
|
152
|
+
.max(PERSONAL_GITHUB_REPOSITORY_CATALOG_MAX),
|
|
153
|
+
})
|
|
154
|
+
.strict()
|
|
155
|
+
.superRefine((request, context) => {
|
|
156
|
+
const repositoryIds = new Set<string>();
|
|
157
|
+
const fullNames = new Set<string>();
|
|
158
|
+
request.repositories.forEach((repository, index) => {
|
|
159
|
+
const normalizedFullName = repository.fullName.toLowerCase();
|
|
160
|
+
if (repositoryIds.has(repository.repositoryId)) {
|
|
161
|
+
context.addIssue({
|
|
162
|
+
code: "custom",
|
|
163
|
+
path: ["repositories", index, "repositoryId"],
|
|
164
|
+
message: "repositoryId must be unique",
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (fullNames.has(normalizedFullName)) {
|
|
168
|
+
context.addIssue({
|
|
169
|
+
code: "custom",
|
|
170
|
+
path: ["repositories", index, "fullName"],
|
|
171
|
+
message: "fullName must be unique",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
repositoryIds.add(repository.repositoryId);
|
|
175
|
+
fullNames.add(normalizedFullName);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
export type ReplacePersonalGitHubRepositorySelectionsRequest = z.infer<
|
|
179
|
+
typeof ReplacePersonalGitHubRepositorySelectionsRequest
|
|
180
|
+
>;
|
|
181
|
+
|
|
182
|
+
export const VerifyPersonalGitHubRepositorySelectionsRequest = z
|
|
183
|
+
.object({
|
|
184
|
+
expectedConnectionAuthorityGeneration: z.number().int().positive(),
|
|
185
|
+
expectedSelectionGeneration: z.number().int().nonnegative(),
|
|
186
|
+
idempotencyKey: z.string().trim().min(1).max(200),
|
|
187
|
+
})
|
|
188
|
+
.strict();
|
|
189
|
+
export type VerifyPersonalGitHubRepositorySelectionsRequest = z.infer<
|
|
190
|
+
typeof VerifyPersonalGitHubRepositorySelectionsRequest
|
|
191
|
+
>;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Owner-visible, credential-free metadata for one dedicated personal GitHub
|
|
195
|
+
* OAuth connection. Repository selections are a separate authority and never
|
|
196
|
+
* live in this credential record.
|
|
197
|
+
*/
|
|
198
|
+
export const PersonalGitHubConnectionMetadata = z
|
|
199
|
+
.object({
|
|
200
|
+
credentialRole: z.literal(PERSONAL_GITHUB_CREDENTIAL_ROLE),
|
|
201
|
+
providerFamily: z.literal(PERSONAL_GITHUB_PROVIDER_FAMILY),
|
|
202
|
+
providerPrincipalId: z.string().regex(/^\d+$/u),
|
|
203
|
+
githubUserId: z.string().regex(/^\d+$/u),
|
|
204
|
+
githubLogin: z.string().min(1).max(100),
|
|
205
|
+
oauthEnvironment: z.string().min(1).max(128),
|
|
206
|
+
oauthClientMarker: z.string().regex(/^[a-f0-9]{32}$/u),
|
|
207
|
+
credentialBindingId: z.string().uuid(),
|
|
208
|
+
connectedAt: z.string().datetime({ offset: true }),
|
|
209
|
+
lastVerifiedAt: z.string().datetime({ offset: true }),
|
|
210
|
+
disconnectedAt: z.string().datetime({ offset: true }).nullable().optional(),
|
|
211
|
+
refreshTokenExpiresAt: z.string().datetime({ offset: true }).nullable().optional(),
|
|
212
|
+
})
|
|
213
|
+
.passthrough();
|
|
214
|
+
export type PersonalGitHubConnectionMetadata = z.infer<typeof PersonalGitHubConnectionMetadata>;
|
|
215
|
+
|
|
216
|
+
export const PersonalGitHubOAuthStartRequest = z
|
|
217
|
+
.object({
|
|
218
|
+
/** Existing exact connection generation to re-authorize in place. */
|
|
219
|
+
connectionId: z.string().uuid().optional(),
|
|
220
|
+
/** Same-workspace UI path restored after the callback. */
|
|
221
|
+
returnPath: z.string().min(1).max(2048).optional(),
|
|
222
|
+
})
|
|
223
|
+
.strict();
|
|
224
|
+
export type PersonalGitHubOAuthStartRequest = z.infer<typeof PersonalGitHubOAuthStartRequest>;
|
|
225
|
+
|
|
226
|
+
export const PersonalGitHubOAuthStartResponse = z
|
|
227
|
+
.object({
|
|
228
|
+
authorizationUrl: z.string().url(),
|
|
229
|
+
expiresAt: z.string().datetime({ offset: true }),
|
|
230
|
+
})
|
|
231
|
+
.strict();
|
|
232
|
+
export type PersonalGitHubOAuthStartResponse = z.infer<typeof PersonalGitHubOAuthStartResponse>;
|
|
233
|
+
|
|
234
|
+
export const PersonalGitHubConnectionStatusResponse = z
|
|
235
|
+
.object({
|
|
236
|
+
enabled: z.boolean(),
|
|
237
|
+
connection: ConnectionMetadata.nullable(),
|
|
238
|
+
reviewUrl: z.string().url().nullable(),
|
|
239
|
+
})
|
|
240
|
+
.strict();
|
|
241
|
+
export type PersonalGitHubConnectionStatusResponse = z.infer<
|
|
242
|
+
typeof PersonalGitHubConnectionStatusResponse
|
|
243
|
+
>;
|
|
244
|
+
|
|
245
|
+
export const PersonalGitHubDisconnectRequest = z
|
|
246
|
+
.object({
|
|
247
|
+
expectedVersion: z.number().int().positive(),
|
|
248
|
+
idempotencyKey: z.string().trim().min(1).max(200),
|
|
249
|
+
})
|
|
250
|
+
.strict();
|
|
251
|
+
export type PersonalGitHubDisconnectRequest = z.infer<typeof PersonalGitHubDisconnectRequest>;
|
|
252
|
+
|
|
253
|
+
export function isPersonalGitHubConnection(
|
|
254
|
+
connection: Pick<z.infer<typeof ConnectionMetadata>, "providerDomain" | "kind" | "metadata">,
|
|
255
|
+
): boolean {
|
|
256
|
+
return (
|
|
257
|
+
connection.providerDomain.toLowerCase() === PERSONAL_GITHUB_PROVIDER_DOMAIN &&
|
|
258
|
+
connection.kind === "oauth2" &&
|
|
259
|
+
PersonalGitHubConnectionMetadata.safeParse(connection.metadata).success
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function hasReservedPersonalGitHubMetadata(
|
|
264
|
+
metadata: Record<string, unknown> | undefined,
|
|
265
|
+
): boolean {
|
|
266
|
+
return metadata?.credentialRole === PERSONAL_GITHUB_CREDENTIAL_ROLE;
|
|
267
|
+
}
|
|
@@ -174,6 +174,11 @@ export const PreferenceRegistryEvent = z.object({
|
|
|
174
174
|
});
|
|
175
175
|
export type PreferenceRegistryEvent = z.infer<typeof PreferenceRegistryEvent>;
|
|
176
176
|
|
|
177
|
+
export const PreferenceRegistryActivationAuthority = z.enum(["human_confirmed", "automatic"]);
|
|
178
|
+
export type PreferenceRegistryActivationAuthority = z.infer<
|
|
179
|
+
typeof PreferenceRegistryActivationAuthority
|
|
180
|
+
>;
|
|
181
|
+
|
|
177
182
|
export const PreferenceRegistryDescriptor = z.object({
|
|
178
183
|
id: z.string().uuid(),
|
|
179
184
|
stableKey: PreferenceRegistryStableKey,
|
|
@@ -185,6 +190,18 @@ export const PreferenceRegistryDescriptor = z.object({
|
|
|
185
190
|
contentHash: hash,
|
|
186
191
|
precedence: PreferenceRegistryPrecedence,
|
|
187
192
|
provenance: PreferenceRegistryDescriptorProvenance,
|
|
193
|
+
// How the active revision became active, derived from the governed-learning
|
|
194
|
+
// activation receipt rather than stored on the revision. `provenance.trust`
|
|
195
|
+
// stays the frozen creation-time fact - a revision proposed by an agent is
|
|
196
|
+
// `untrusted_proposal` forever, which is correct and immutable - while this
|
|
197
|
+
// says whether a human explicitly confirmed the activation or policy
|
|
198
|
+
// activated it automatically. Null when the revision became active outside
|
|
199
|
+
// governed learning, so no receipt describes it.
|
|
200
|
+
// Defaulted, not merely nullable: snapshots written before this field
|
|
201
|
+
// existed are immutable and their stored JSON simply has no answer. Parsing
|
|
202
|
+
// those as null is the truthful reading, and it keeps their pinned
|
|
203
|
+
// descriptor hash valid because the stored text is untouched.
|
|
204
|
+
activationAuthority: PreferenceRegistryActivationAuthority.nullable().default(null),
|
|
188
205
|
expiresAt: z.string().datetime().nullable(),
|
|
189
206
|
retrievalHandle: z.string().min(1).max(512),
|
|
190
207
|
});
|
package/src/remember.ts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
|
|
4
|
+
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_TOO_LONG_MESSAGE,
|
|
5
|
+
AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS,
|
|
6
|
+
AGENT_AUTHORED_PREFERENCE_CONTENT_TOO_LONG_MESSAGE,
|
|
7
|
+
} from "./agent-authored-durable-text";
|
|
8
|
+
import {
|
|
9
|
+
CompanyBrainLearningDecisionSummary,
|
|
10
|
+
CompanyBrainLearningStepFailure,
|
|
11
|
+
} from "./company-brain-governed-writes";
|
|
12
|
+
import { GovernedLearningActivationDestination } from "./governed-learning-activation";
|
|
13
|
+
import { HumanInputQuestion } from "./index";
|
|
14
|
+
import {
|
|
15
|
+
PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS,
|
|
16
|
+
PREFERENCE_REGISTRY_TITLE_MAX_CHARS,
|
|
17
|
+
PreferenceRegistryStableKey,
|
|
18
|
+
} from "./preference-registry";
|
|
19
|
+
import { WorkspaceInstructionPolicyTarget } from "./workspace-instruction-policies";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Explicit user-directed durable write ("remember X for this workspace").
|
|
23
|
+
*
|
|
24
|
+
* The lane is the Company Brain area the content belongs to:
|
|
25
|
+
* - `preference`: a Ways-of-working preference (how agents should act);
|
|
26
|
+
* - `instruction_policy`: a mandatory workspace rule ("always"/"never");
|
|
27
|
+
* - `knowledge`: a company/product/people fact.
|
|
28
|
+
*
|
|
29
|
+
* v1 supports the workspace scope only. Personal and organization scopes are
|
|
30
|
+
* separate authorities that are not yet active for governed writes.
|
|
31
|
+
*/
|
|
32
|
+
export const RememberLane = z.enum(["preference", "instruction_policy", "knowledge"]);
|
|
33
|
+
export type RememberLane = z.infer<typeof RememberLane>;
|
|
34
|
+
|
|
35
|
+
export const RememberScope = z.enum(["workspace"]);
|
|
36
|
+
export type RememberScope = z.infer<typeof RememberScope>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Ceiling for the Knowledge lane, which is retrieval evidence rather than
|
|
40
|
+
* always-composed prompt text. The prompt-composed lanes are bounded far more
|
|
41
|
+
* tightly: see `AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS` and
|
|
42
|
+
* `AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS`.
|
|
43
|
+
*/
|
|
44
|
+
export const REMEMBER_CONTENT_MAX_CHARS = 4_000;
|
|
45
|
+
|
|
46
|
+
const rememberBase = {
|
|
47
|
+
operationId: z.string().uuid(),
|
|
48
|
+
scope: RememberScope.default("workspace"),
|
|
49
|
+
/** The exact user-directed content to remember, in the user's words. */
|
|
50
|
+
content: z.string().trim().min(1).max(REMEMBER_CONTENT_MAX_CHARS),
|
|
51
|
+
/** Why the agent believes the user asked for this to be remembered. */
|
|
52
|
+
reason: z.string().trim().min(1).max(4_096),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const RememberRequest = z.discriminatedUnion("lane", [
|
|
56
|
+
z
|
|
57
|
+
.object({
|
|
58
|
+
...rememberBase,
|
|
59
|
+
lane: z.literal("preference"),
|
|
60
|
+
// Only the short title/description descriptors are prompt-composed; the
|
|
61
|
+
// content is retrieved on demand, so this length is retrieval cost rather
|
|
62
|
+
// than standing prompt cost, and gets more room than a rule rather than
|
|
63
|
+
// less.
|
|
64
|
+
content: z
|
|
65
|
+
.string()
|
|
66
|
+
.trim()
|
|
67
|
+
.min(1)
|
|
68
|
+
.max(
|
|
69
|
+
AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS,
|
|
70
|
+
AGENT_AUTHORED_PREFERENCE_CONTENT_TOO_LONG_MESSAGE,
|
|
71
|
+
),
|
|
72
|
+
stableKey: PreferenceRegistryStableKey,
|
|
73
|
+
title: z.string().trim().min(1).max(PREFERENCE_REGISTRY_TITLE_MAX_CHARS),
|
|
74
|
+
description: z
|
|
75
|
+
.string()
|
|
76
|
+
.trim()
|
|
77
|
+
.min(1)
|
|
78
|
+
.max(PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS),
|
|
79
|
+
})
|
|
80
|
+
.strict(),
|
|
81
|
+
z
|
|
82
|
+
.object({
|
|
83
|
+
...rememberBase,
|
|
84
|
+
lane: z.literal("instruction_policy"),
|
|
85
|
+
// A mandatory rule is composed verbatim into the prompt of every session
|
|
86
|
+
// it applies to, for as long as it stays active, so this is the tightest
|
|
87
|
+
// agent budget in the Company Brain.
|
|
88
|
+
content: z
|
|
89
|
+
.string()
|
|
90
|
+
.trim()
|
|
91
|
+
.min(1)
|
|
92
|
+
.max(
|
|
93
|
+
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
|
|
94
|
+
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_TOO_LONG_MESSAGE,
|
|
95
|
+
),
|
|
96
|
+
target: WorkspaceInstructionPolicyTarget.default({
|
|
97
|
+
kind: "policy",
|
|
98
|
+
scope: "global",
|
|
99
|
+
roleKey: null,
|
|
100
|
+
}),
|
|
101
|
+
})
|
|
102
|
+
.strict(),
|
|
103
|
+
z
|
|
104
|
+
.object({
|
|
105
|
+
...rememberBase,
|
|
106
|
+
lane: z.literal("knowledge"),
|
|
107
|
+
/** Short entity label the fact is about (company, product, person, team, ...). */
|
|
108
|
+
subject: z.string().trim().min(1).max(512),
|
|
109
|
+
})
|
|
110
|
+
.strict(),
|
|
111
|
+
]);
|
|
112
|
+
export type RememberRequest = z.infer<typeof RememberRequest>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Bound structured human-input question that authorizes a confirmed remember.
|
|
116
|
+
* The question id binds the exact confirmation target: the
|
|
117
|
+
* `knowledge_change_proposals` id for Ways-of-working lanes, or the
|
|
118
|
+
* `knowledge_claims` id for the Knowledge lane.
|
|
119
|
+
*/
|
|
120
|
+
export const REMEMBER_HUMAN_INPUT_SAVE_OPTION = "save" as const;
|
|
121
|
+
export const REMEMBER_HUMAN_INPUT_SKIP_OPTION = "skip" as const;
|
|
122
|
+
export function rememberHumanInputQuestionId(targetId: string): string {
|
|
123
|
+
return `remember:${targetId}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// z.lazy: this module is re-exported from ./index, so resolve the question
|
|
127
|
+
// schema at parse time instead of at import time.
|
|
128
|
+
export const RememberHumanInputPrompt = z.object({
|
|
129
|
+
questions: z.array(z.lazy(() => HumanInputQuestion)).length(1),
|
|
130
|
+
allowSkip: z.literal(false),
|
|
131
|
+
});
|
|
132
|
+
export type RememberHumanInputPrompt = z.infer<typeof RememberHumanInputPrompt>;
|
|
133
|
+
|
|
134
|
+
export const RememberActivationSummary = z.discriminatedUnion("destination", [
|
|
135
|
+
z.object({
|
|
136
|
+
destination: GovernedLearningActivationDestination,
|
|
137
|
+
receiptId: z.string().uuid(),
|
|
138
|
+
destinationRevisionId: z.string().uuid().nullable(),
|
|
139
|
+
effectiveAt: z.string().datetime().nullable(),
|
|
140
|
+
authorityKind: z.enum(["automatic", "human_confirmed"]),
|
|
141
|
+
/** The `/learning` API/SDK history exposes exact undo for this receipt. */
|
|
142
|
+
undo: z.literal("learning_history"),
|
|
143
|
+
}),
|
|
144
|
+
z.object({
|
|
145
|
+
destination: z.literal("knowledge"),
|
|
146
|
+
receiptId: z.string().uuid(),
|
|
147
|
+
claimId: z.string().uuid(),
|
|
148
|
+
approvalReviewId: z.string().uuid(),
|
|
149
|
+
effectiveAt: z.string().datetime().nullable(),
|
|
150
|
+
authorityKind: z.literal("human_confirmed"),
|
|
151
|
+
/** Knowledge approvals are undone through the Knowledge review lifecycle (`knowledge_correct` or a human revocation). */
|
|
152
|
+
undo: z.literal("knowledge_review"),
|
|
153
|
+
}),
|
|
154
|
+
]);
|
|
155
|
+
export type RememberActivationSummary = z.infer<typeof RememberActivationSummary>;
|
|
156
|
+
|
|
157
|
+
export const RememberReceipt = z.discriminatedUnion("status", [
|
|
158
|
+
/** Learning policy is off for this source: nothing durable was written. */
|
|
159
|
+
z.object({
|
|
160
|
+
status: z.literal("blocked"),
|
|
161
|
+
operationId: z.string().uuid(),
|
|
162
|
+
lane: RememberLane,
|
|
163
|
+
scope: RememberScope,
|
|
164
|
+
reason: z.literal("learning_policy_off"),
|
|
165
|
+
}),
|
|
166
|
+
/** Kept for callers that still expect review-only Knowledge; not returned by `remember` today. */
|
|
167
|
+
z.object({
|
|
168
|
+
status: z.literal("proposed_for_review"),
|
|
169
|
+
operationId: z.string().uuid(),
|
|
170
|
+
lane: RememberLane,
|
|
171
|
+
scope: RememberScope,
|
|
172
|
+
noteId: z.string().uuid(),
|
|
173
|
+
claimId: z.string().uuid(),
|
|
174
|
+
evidenceId: z.string().uuid(),
|
|
175
|
+
reviewId: z.string().uuid().nullable(),
|
|
176
|
+
}),
|
|
177
|
+
/** Activated immediately (automatic policy) through the destination lifecycle. */
|
|
178
|
+
z.object({
|
|
179
|
+
status: z.literal("activated"),
|
|
180
|
+
operationId: z.string().uuid(),
|
|
181
|
+
lane: RememberLane,
|
|
182
|
+
scope: RememberScope,
|
|
183
|
+
noteId: z.string().uuid(),
|
|
184
|
+
proposalId: z.string().uuid(),
|
|
185
|
+
learning: CompanyBrainLearningDecisionSummary.nullable(),
|
|
186
|
+
activation: RememberActivationSummary,
|
|
187
|
+
}),
|
|
188
|
+
/**
|
|
189
|
+
* The proposal is durable but the workspace policy will not activate it on
|
|
190
|
+
* its own. The agent must ask the human exactly this question through the
|
|
191
|
+
* built-in `request_human_input` tool, then call `remember_confirm` with the
|
|
192
|
+
* returned request id.
|
|
193
|
+
*/
|
|
194
|
+
z.object({
|
|
195
|
+
status: z.literal("confirmation_required"),
|
|
196
|
+
operationId: z.string().uuid(),
|
|
197
|
+
lane: RememberLane,
|
|
198
|
+
scope: RememberScope,
|
|
199
|
+
noteId: z.string().uuid(),
|
|
200
|
+
/** Ways-of-working lanes confirm a change proposal; Knowledge confirms the claim. */
|
|
201
|
+
proposalId: z.string().uuid().nullable(),
|
|
202
|
+
claimId: z.string().uuid(),
|
|
203
|
+
learning: CompanyBrainLearningDecisionSummary.nullable(),
|
|
204
|
+
learningFailure: CompanyBrainLearningStepFailure.nullable(),
|
|
205
|
+
humanInput: RememberHumanInputPrompt,
|
|
206
|
+
confirmWith: z.literal("remember_confirm"),
|
|
207
|
+
}),
|
|
208
|
+
]);
|
|
209
|
+
export type RememberReceipt = z.infer<typeof RememberReceipt>;
|
|
210
|
+
|
|
211
|
+
export const RememberConfirmRequest = z.discriminatedUnion("target", [
|
|
212
|
+
z
|
|
213
|
+
.object({
|
|
214
|
+
target: z.literal("proposal"),
|
|
215
|
+
operationId: z.string().uuid(),
|
|
216
|
+
proposalId: z.string().uuid(),
|
|
217
|
+
/** `learning.receiptId` from the `confirmation_required` remember receipt. */
|
|
218
|
+
decisionReceiptId: z.string().uuid(),
|
|
219
|
+
/** The `requestId` returned by `request_human_input`. */
|
|
220
|
+
humanInputRequestId: z.string().uuid(),
|
|
221
|
+
})
|
|
222
|
+
.strict(),
|
|
223
|
+
z
|
|
224
|
+
.object({
|
|
225
|
+
target: z.literal("knowledge_claim"),
|
|
226
|
+
operationId: z.string().uuid(),
|
|
227
|
+
claimId: z.string().uuid(),
|
|
228
|
+
humanInputRequestId: z.string().uuid(),
|
|
229
|
+
})
|
|
230
|
+
.strict(),
|
|
231
|
+
]);
|
|
232
|
+
export type RememberConfirmRequest = z.infer<typeof RememberConfirmRequest>;
|
|
233
|
+
|
|
234
|
+
export const RememberConfirmReceipt = z.object({
|
|
235
|
+
status: z.literal("activated"),
|
|
236
|
+
operationId: z.string().uuid(),
|
|
237
|
+
proposalId: z.string().uuid().nullable(),
|
|
238
|
+
claimId: z.string().uuid(),
|
|
239
|
+
decisionReceiptId: z.string().uuid().nullable(),
|
|
240
|
+
activation: RememberActivationSummary,
|
|
241
|
+
});
|
|
242
|
+
export type RememberConfirmReceipt = z.infer<typeof RememberConfirmReceipt>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { RetainedArtifactReferenceSchema } from "./retained-output";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Channel-A currently returns one bounded binary-safe read. Keep publication
|
|
7
|
+
* below that ceiling so an extra sentinel byte can distinguish an exact file
|
|
8
|
+
* from a truncated prefix.
|
|
9
|
+
*/
|
|
10
|
+
export const SANDBOX_FILE_ARTIFACT_MAX_BYTES = 25 * 1024 * 1024 - 1;
|
|
11
|
+
|
|
12
|
+
export const PublishSandboxFileArtifactRequest = z
|
|
13
|
+
.object({
|
|
14
|
+
path: z.string().min(1).max(4_096),
|
|
15
|
+
})
|
|
16
|
+
.strict();
|
|
17
|
+
export type PublishSandboxFileArtifactRequest = z.infer<typeof PublishSandboxFileArtifactRequest>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Closed model/UI receipt for one exact sandbox-file publication. Storage
|
|
21
|
+
* locators and signed URLs never cross this boundary.
|
|
22
|
+
*/
|
|
23
|
+
export const SandboxFileArtifactReceipt = z
|
|
24
|
+
.object({
|
|
25
|
+
type: z.literal("sandbox_file"),
|
|
26
|
+
sandboxPath: z.string().min(1).max(4_096),
|
|
27
|
+
filename: z.string().min(1).max(1_024),
|
|
28
|
+
artifact: RetainedArtifactReferenceSchema,
|
|
29
|
+
})
|
|
30
|
+
.strict()
|
|
31
|
+
.superRefine((value, context) => {
|
|
32
|
+
const pathSegments = value.sandboxPath.split("/");
|
|
33
|
+
if (
|
|
34
|
+
!value.sandboxPath.startsWith("/workspace/") ||
|
|
35
|
+
value.sandboxPath.includes("\0") ||
|
|
36
|
+
pathSegments.some(
|
|
37
|
+
(segment, index) => index > 1 && (!segment || segment === "." || segment === ".."),
|
|
38
|
+
) ||
|
|
39
|
+
pathSegments.at(-1) !== value.filename
|
|
40
|
+
) {
|
|
41
|
+
context.addIssue({
|
|
42
|
+
code: "custom",
|
|
43
|
+
path: ["sandboxPath"],
|
|
44
|
+
message: "sandbox path must canonically identify the published filename in /workspace",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (value.artifact.kind !== "file" || value.artifact.retention.policy !== "workspace_file") {
|
|
48
|
+
context.addIssue({
|
|
49
|
+
code: "custom",
|
|
50
|
+
path: ["artifact"],
|
|
51
|
+
message: "sandbox files require a permanent workspace-file artifact",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (
|
|
55
|
+
value.artifact.originalBytes < 1 ||
|
|
56
|
+
value.artifact.originalBytes > SANDBOX_FILE_ARTIFACT_MAX_BYTES
|
|
57
|
+
) {
|
|
58
|
+
context.addIssue({
|
|
59
|
+
code: "custom",
|
|
60
|
+
path: ["artifact", "originalBytes"],
|
|
61
|
+
message: "sandbox file size is outside the publication byte limit",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
export type SandboxFileArtifactReceipt = z.infer<typeof SandboxFileArtifactReceipt>;
|
package/src/sandbox-snapshots.ts
CHANGED
|
@@ -52,6 +52,84 @@ export type NativeSnapshotDescriptor = {
|
|
|
52
52
|
|
|
53
53
|
export type WorkspaceArchiveDescriptor = TarWorkspaceArchiveDescriptor | NativeSnapshotDescriptor;
|
|
54
54
|
|
|
55
|
+
export const WORKSPACE_ARCHIVE_OBJECT_REF_SCHEMA = "sandbox_archive_object_v1" as const;
|
|
56
|
+
|
|
57
|
+
/** Compact object-storage locator for portable tar bytes. The SHA-256/size in
|
|
58
|
+
* `workspaceArchiveMeta` remain the verification authority. */
|
|
59
|
+
export type WorkspaceArchiveObjectRef = {
|
|
60
|
+
schema: typeof WORKSPACE_ARCHIVE_OBJECT_REF_SCHEMA;
|
|
61
|
+
key: string;
|
|
62
|
+
sha256: string;
|
|
63
|
+
bytes: number;
|
|
64
|
+
backend: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const OBJECT_KEY =
|
|
68
|
+
/^sandbox-archives\/v1\/[0-9a-f-]{36}\/[0-9a-f-]{36}\/[0-9a-f-]{36}\/wa1:[0-9]{13}:[0-9a-f]{64}\.tar$/i;
|
|
69
|
+
|
|
70
|
+
export function parseWorkspaceArchiveObjectRef(value: unknown): WorkspaceArchiveObjectRef | null {
|
|
71
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
72
|
+
const candidate = value as Partial<WorkspaceArchiveObjectRef>;
|
|
73
|
+
if (
|
|
74
|
+
candidate.schema !== WORKSPACE_ARCHIVE_OBJECT_REF_SCHEMA ||
|
|
75
|
+
typeof candidate.key !== "string" ||
|
|
76
|
+
!OBJECT_KEY.test(candidate.key) ||
|
|
77
|
+
typeof candidate.sha256 !== "string" ||
|
|
78
|
+
!SHA256.test(candidate.sha256) ||
|
|
79
|
+
!nonnegativeInteger(candidate.bytes) ||
|
|
80
|
+
candidate.bytes <= 0 ||
|
|
81
|
+
typeof candidate.backend !== "string" ||
|
|
82
|
+
candidate.backend.length === 0 ||
|
|
83
|
+
candidate.backend.length > 64
|
|
84
|
+
) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
schema: WORKSPACE_ARCHIVE_OBJECT_REF_SCHEMA,
|
|
89
|
+
key: candidate.key,
|
|
90
|
+
sha256: candidate.sha256,
|
|
91
|
+
bytes: candidate.bytes,
|
|
92
|
+
backend: candidate.backend,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function workspaceArchiveObjectKey(input: {
|
|
97
|
+
accountId: string;
|
|
98
|
+
workspaceId: string;
|
|
99
|
+
sandboxGroupId: string;
|
|
100
|
+
revision: string;
|
|
101
|
+
}): string {
|
|
102
|
+
return `sandbox-archives/v1/${input.accountId}/${input.workspaceId}/${input.sandboxGroupId}/${input.revision}.tar`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function workspaceArchivePayloadPresent(
|
|
106
|
+
sessionState: Record<string, unknown> | null | undefined,
|
|
107
|
+
): boolean {
|
|
108
|
+
if (!sessionState) return false;
|
|
109
|
+
if (
|
|
110
|
+
typeof sessionState.workspaceArchive === "string" &&
|
|
111
|
+
sessionState.workspaceArchive.length > 0
|
|
112
|
+
) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
return parseWorkspaceArchiveObjectRef(sessionState.workspaceArchiveRef) !== null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Restore may inline object bytes in memory for hydrate. That copy must never
|
|
119
|
+
* be published onto a lease when a durable object-storage ref exists. */
|
|
120
|
+
export function omitInlineWorkspaceArchiveWhenObjectRefPresent(
|
|
121
|
+
sessionState: Record<string, unknown>,
|
|
122
|
+
): Record<string, unknown> {
|
|
123
|
+
const next = { ...sessionState };
|
|
124
|
+
if (parseWorkspaceArchiveObjectRef(next.workspaceArchiveRef)) {
|
|
125
|
+
delete next.workspaceArchive;
|
|
126
|
+
}
|
|
127
|
+
if (parseWorkspaceArchiveObjectRef(next.workspaceArchivePrevRef)) {
|
|
128
|
+
delete next.workspaceArchivePrev;
|
|
129
|
+
}
|
|
130
|
+
return next;
|
|
131
|
+
}
|
|
132
|
+
|
|
55
133
|
export const NATIVE_SNAPSHOT_PREFIXES: ReadonlyArray<{
|
|
56
134
|
provider: NativeSnapshotProvider;
|
|
57
135
|
prefix: string;
|