@opengeni/contracts 2.9.2 → 2.13.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/artifacts.d.ts +121 -0
- package/dist/atlassian.js +11 -11
- package/dist/{chunk-4IVHBXRI.js → chunk-7ABONTXE.js} +42 -2
- package/dist/chunk-7ABONTXE.js.map +1 -0
- package/dist/{chunk-7RMTKFJW.js → chunk-7Q6HPDY2.js} +8 -8
- package/dist/{chunk-AWNGBY5I.js → chunk-DPCCW6U7.js} +7395 -6619
- package/dist/chunk-DPCCW6U7.js.map +1 -0
- package/dist/{chunk-N6GRVXAJ.js → chunk-NPBM4QSK.js} +2 -2
- package/dist/connection-authority.js +11 -11
- package/dist/editable-artifact-codec-registry.js +2 -2
- package/dist/editable-artifact-live.js +2 -2
- package/dist/editable-artifact-serialized-commit.js +3 -3
- package/dist/editable-artifacts.js +13 -13
- package/dist/github-repository-contracts.d.ts +36 -0
- package/dist/github-repository-contracts.js +59 -0
- package/dist/github-repository-contracts.js.map +1 -0
- package/dist/github-repository.d.ts +14 -0
- package/dist/github-repository.js +36 -0
- package/dist/github-repository.js.map +1 -0
- package/dist/google-drive.js +12 -12
- package/dist/index.d.ts +809 -70
- package/dist/index.js +299 -135
- package/dist/mcp-oauth.d.ts +71 -0
- package/dist/model-context-inspector.d.ts +205 -0
- package/dist/model-picker-order.d.ts +23 -0
- package/dist/model-picker-order.js +42 -0
- package/dist/model-picker-order.js.map +1 -0
- package/dist/organization-membership-lifecycle.d.ts +17 -0
- package/dist/personal-github.js +11 -11
- package/dist/session-mcp-projections.d.ts +210 -0
- package/dist/session-titles.d.ts +35 -0
- package/dist/session-titles.js +9 -3
- package/dist/tool-catalog.d.ts +271 -0
- package/dist/workspace-learning-policy.d.ts +1 -1
- package/package.json +13 -1
- package/src/artifacts.ts +111 -1
- package/src/github-repository-contracts.ts +85 -0
- package/src/github-repository.ts +59 -0
- package/src/index.ts +486 -52
- package/src/mcp-oauth.ts +68 -0
- package/src/model-context-inspector.ts +104 -0
- package/src/model-picker-order.ts +87 -0
- package/src/organization-membership-lifecycle.ts +20 -0
- package/src/session-mcp-projections.ts +268 -0
- package/src/session-titles.ts +100 -0
- package/src/tool-catalog.ts +136 -0
- package/src/workspace-learning-policy.ts +4 -3
- package/dist/chunk-4IVHBXRI.js.map +0 -1
- package/dist/chunk-AWNGBY5I.js.map +0 -1
- /package/dist/{chunk-7RMTKFJW.js.map → chunk-7Q6HPDY2.js.map} +0 -0
- /package/dist/{chunk-N6GRVXAJ.js.map → chunk-NPBM4QSK.js.map} +0 -0
package/src/tool-catalog.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
export const ATTEMPT_TOOL_CATALOG_VERSION = 1 as const;
|
|
4
|
+
export const TOOL_GATEWAY_CATALOG_VERSION = 1 as const;
|
|
4
5
|
export const ATTEMPT_TOOL_CATALOG_MAX_ENTRIES = 4_096;
|
|
5
6
|
export const ATTEMPT_TOOL_CATALOG_MAX_BYTES = 16 * 1024 * 1024;
|
|
6
7
|
export const ATTEMPT_TOOL_CATALOG_MAX_PATH_SEGMENTS = 8;
|
|
@@ -43,6 +44,10 @@ export const AttemptToolIdentity = z
|
|
|
43
44
|
.strict();
|
|
44
45
|
export type AttemptToolIdentity = z.infer<typeof AttemptToolIdentity>;
|
|
45
46
|
|
|
47
|
+
/** Protocol-neutral tool identity shared by MCP, HTTP/SDK, agents, and Codemode. */
|
|
48
|
+
export const ToolGatewayIdentity = AttemptToolIdentity;
|
|
49
|
+
export type ToolGatewayIdentity = AttemptToolIdentity;
|
|
50
|
+
|
|
46
51
|
export const AttemptToolCatalogIcon = z
|
|
47
52
|
.object({
|
|
48
53
|
src: z.string().min(1).max(8_192),
|
|
@@ -88,6 +93,64 @@ export const AttemptToolCatalogEntry = z
|
|
|
88
93
|
.strict();
|
|
89
94
|
export type AttemptToolCatalogEntry = z.infer<typeof AttemptToolCatalogEntry>;
|
|
90
95
|
|
|
96
|
+
/** One canonical gateway entry. Adapter-specific names are projections, never authority. */
|
|
97
|
+
export const ToolGatewayCatalogEntry = AttemptToolCatalogEntry;
|
|
98
|
+
export type ToolGatewayCatalogEntry = AttemptToolCatalogEntry;
|
|
99
|
+
|
|
100
|
+
export const ToolGatewayCatalog = z
|
|
101
|
+
.object({
|
|
102
|
+
version: z.literal(TOOL_GATEWAY_CATALOG_VERSION),
|
|
103
|
+
accountId: z.string().uuid(),
|
|
104
|
+
workspaceId: z.string().uuid(),
|
|
105
|
+
generation: z.number().int().positive(),
|
|
106
|
+
digest: sha256,
|
|
107
|
+
createdAt: z.string().datetime({ offset: true }),
|
|
108
|
+
entries: z.array(ToolGatewayCatalogEntry).max(ATTEMPT_TOOL_CATALOG_MAX_ENTRIES),
|
|
109
|
+
})
|
|
110
|
+
.strict()
|
|
111
|
+
.superRefine((catalog, context) => {
|
|
112
|
+
const identities = new Set<string>();
|
|
113
|
+
const modelNames = new Set<string>();
|
|
114
|
+
const toolPaths = new Set<string>();
|
|
115
|
+
for (const [index, entry] of catalog.entries.entries()) {
|
|
116
|
+
const identity = `${entry.identity.serverId}\u0000${entry.identity.toolName}`;
|
|
117
|
+
const toolPath = entry.codemodePath.join(".");
|
|
118
|
+
if (identities.has(identity)) {
|
|
119
|
+
context.addIssue({
|
|
120
|
+
code: "custom",
|
|
121
|
+
path: ["entries", index, "identity"],
|
|
122
|
+
message: "duplicate tool identity",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (modelNames.has(entry.modelName)) {
|
|
126
|
+
context.addIssue({
|
|
127
|
+
code: "custom",
|
|
128
|
+
path: ["entries", index, "modelName"],
|
|
129
|
+
message: "duplicate model tool name",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (toolPaths.has(toolPath)) {
|
|
133
|
+
context.addIssue({
|
|
134
|
+
code: "custom",
|
|
135
|
+
path: ["entries", index, "codemodePath"],
|
|
136
|
+
message: "duplicate tool path",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
identities.add(identity);
|
|
140
|
+
modelNames.add(entry.modelName);
|
|
141
|
+
toolPaths.add(toolPath);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
export type ToolGatewayCatalog = z.infer<typeof ToolGatewayCatalog>;
|
|
145
|
+
|
|
146
|
+
export const ToolGatewayCaller = z
|
|
147
|
+
.object({
|
|
148
|
+
kind: z.enum(["model", "codemode", "http", "mcp", "browser"]),
|
|
149
|
+
subjectId: z.string().min(1).max(1_024),
|
|
150
|
+
})
|
|
151
|
+
.strict();
|
|
152
|
+
export type ToolGatewayCaller = z.infer<typeof ToolGatewayCaller>;
|
|
153
|
+
|
|
91
154
|
export const AttemptToolCatalog = z
|
|
92
155
|
.object({
|
|
93
156
|
version: z.literal(ATTEMPT_TOOL_CATALOG_VERSION),
|
|
@@ -251,6 +314,79 @@ export const AttemptToolResult = z
|
|
|
251
314
|
.loose();
|
|
252
315
|
export type AttemptToolResult = z.infer<typeof AttemptToolResult>;
|
|
253
316
|
|
|
317
|
+
export const ToolGatewayResult = AttemptToolResult;
|
|
318
|
+
export type ToolGatewayResult = AttemptToolResult;
|
|
319
|
+
|
|
320
|
+
export const ToolGatewayCallRequest = z
|
|
321
|
+
.object({
|
|
322
|
+
operationId: z.string().uuid().optional(),
|
|
323
|
+
catalogDigest: sha256,
|
|
324
|
+
identity: ToolGatewayIdentity,
|
|
325
|
+
arguments: jsonObject,
|
|
326
|
+
/** Host-owned Site context. Publisher-controlled iframe code cannot set it. */
|
|
327
|
+
siteArtifactId: z.string().uuid().optional(),
|
|
328
|
+
siteVersionId: z.string().uuid().optional(),
|
|
329
|
+
/** Opaque, server-issued, single-use capability for an approval-required call. */
|
|
330
|
+
approvalToken: z
|
|
331
|
+
.string()
|
|
332
|
+
.regex(/^ogta_[A-Za-z0-9_-]{43}$/u)
|
|
333
|
+
.optional(),
|
|
334
|
+
})
|
|
335
|
+
.strict()
|
|
336
|
+
.superRefine(requireCompleteSiteToolContext);
|
|
337
|
+
export type ToolGatewayCallRequest = z.infer<typeof ToolGatewayCallRequest>;
|
|
338
|
+
|
|
339
|
+
export const ToolGatewayApprovalRequest = z
|
|
340
|
+
.object({
|
|
341
|
+
operationId: z.string().uuid(),
|
|
342
|
+
catalogDigest: sha256,
|
|
343
|
+
identity: ToolGatewayIdentity,
|
|
344
|
+
arguments: jsonObject,
|
|
345
|
+
})
|
|
346
|
+
.strict();
|
|
347
|
+
export type ToolGatewayApprovalRequest = z.infer<typeof ToolGatewayApprovalRequest>;
|
|
348
|
+
|
|
349
|
+
export const ToolGatewayApprovalResponse = z
|
|
350
|
+
.object({
|
|
351
|
+
operationId: z.string().uuid(),
|
|
352
|
+
catalogDigest: sha256,
|
|
353
|
+
identity: ToolGatewayIdentity,
|
|
354
|
+
approvalToken: z.string().regex(/^ogta_[A-Za-z0-9_-]{43}$/u),
|
|
355
|
+
expiresAt: z.string().datetime({ offset: true }),
|
|
356
|
+
})
|
|
357
|
+
.strict();
|
|
358
|
+
export type ToolGatewayApprovalResponse = z.infer<typeof ToolGatewayApprovalResponse>;
|
|
359
|
+
|
|
360
|
+
export const ToolGatewayCallResponse = z
|
|
361
|
+
.object({
|
|
362
|
+
operationId: z.string().uuid(),
|
|
363
|
+
catalogDigest: sha256,
|
|
364
|
+
result: ToolGatewayResult,
|
|
365
|
+
})
|
|
366
|
+
.strict();
|
|
367
|
+
export type ToolGatewayCallResponse = z.infer<typeof ToolGatewayCallResponse>;
|
|
368
|
+
|
|
369
|
+
export const ToolGatewayDeclarationsResponse = z
|
|
370
|
+
.object({
|
|
371
|
+
catalogDigest: sha256,
|
|
372
|
+
moduleSpecifier: z.string().min(1).max(512),
|
|
373
|
+
source: z.string().max(16 * 1024 * 1024),
|
|
374
|
+
})
|
|
375
|
+
.strict();
|
|
376
|
+
export type ToolGatewayDeclarationsResponse = z.infer<typeof ToolGatewayDeclarationsResponse>;
|
|
377
|
+
|
|
378
|
+
function requireCompleteSiteToolContext(
|
|
379
|
+
value: { siteArtifactId?: string | undefined; siteVersionId?: string | undefined },
|
|
380
|
+
context: z.RefinementCtx,
|
|
381
|
+
): void {
|
|
382
|
+
if ((value.siteArtifactId === undefined) === (value.siteVersionId === undefined)) return;
|
|
383
|
+
context.addIssue({
|
|
384
|
+
code: "custom",
|
|
385
|
+
message: "siteArtifactId and siteVersionId must be provided together",
|
|
386
|
+
path: [value.siteArtifactId === undefined ? "siteArtifactId" : "siteVersionId"],
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
254
390
|
export const CodemodeOperationState = z.enum([
|
|
255
391
|
"queued",
|
|
256
392
|
"running",
|
|
@@ -4,8 +4,8 @@ export const WORKSPACE_LEARNING_POLICY_MAX_SOURCE_OVERRIDES = 256;
|
|
|
4
4
|
export const WORKSPACE_LEARNING_POLICY_SOURCE_KIND_MAX_CHARS = 96;
|
|
5
5
|
export const WORKSPACE_LEARNING_POLICY_SOURCE_ID_MAX_CHARS = 1_024;
|
|
6
6
|
export const WORKSPACE_LEARNING_POLICY_REASON_MAX_CHARS = 4_096;
|
|
7
|
-
export const
|
|
8
|
-
"workspace-learning-policy:default-
|
|
7
|
+
export const WORKSPACE_LEARNING_POLICY_DEFAULT_SUGGEST_REVISION_ID =
|
|
8
|
+
"workspace-learning-policy:default-suggest:v1";
|
|
9
9
|
|
|
10
10
|
export const WorkspaceLearningMode = z.enum(["off", "suggest", "automatic"]);
|
|
11
11
|
export type WorkspaceLearningMode = z.infer<typeof WorkspaceLearningMode>;
|
|
@@ -220,7 +220,8 @@ export function resolveWorkspaceLearningPolicyEffectiveMode(
|
|
|
220
220
|
policyRevision: parsedSnapshot.revision,
|
|
221
221
|
activationVersion: parsedSnapshot.activationVersion,
|
|
222
222
|
snapshotId: parsedSnapshot.id,
|
|
223
|
-
revisionId:
|
|
223
|
+
revisionId:
|
|
224
|
+
parsedSnapshot.revision?.id ?? WORKSPACE_LEARNING_POLICY_DEFAULT_SUGGEST_REVISION_ID,
|
|
224
225
|
snapshotHash: parsedSnapshot.snapshotHash,
|
|
225
226
|
});
|
|
226
227
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/session-titles.ts"],"sourcesContent":["/** Human-authored session titles keep the existing public API ceiling. */\nexport const SESSION_TITLE_MAX_CHARACTERS = 200;\n\n/**\n * Automatic titles are intentionally much shorter than the manual rename\n * ceiling. This is measured in grapheme clusters so emoji and combining text\n * are never split into malformed display strings.\n */\nexport const AUTOMATIC_SESSION_TITLE_MAX_GRAPHEMES = 80;\n\n/**\n * Safe durable title used until semantic generation succeeds. It contains no\n * user prompt bytes, so provider failure/offline operation cannot leak a\n * credential or leave a raw prompt prefix in navigation surfaces.\n */\nexport const AUTOMATIC_SESSION_TITLE_FALLBACK = \"New conversation\";\n\nlet titleSegmenter: Intl.Segmenter | null | undefined;\n\nconst KNOWN_SENSITIVE_VALUE_PATTERNS = [\n /-----BEGIN [A-Z ]*PRIVATE KEY-----/iu,\n /\\bBearer\\s+[A-Za-z0-9._~+/=-]{8,}/iu,\n /\\b(?:sk-(?:proj-)?|gh[oprsu]_|github_pat_|glpat-|xox[baprs]-)[A-Za-z0-9_-]{8,}/iu,\n /\\bAKIA[0-9A-Z]{16}\\b/u,\n /\\bAIza[0-9A-Za-z_-]{20,}\\b/u,\n /\\beyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/u,\n /[?&](?:access_token|api_key|apikey|password|secret|token)=[^\\s&#]+/iu,\n] as const;\n\nconst URI_SCHEME_CANDIDATE_PATTERN = /\\b[a-z][a-z0-9+.-]*:\\S+/giu;\nconst WINDOWS_DRIVE_PATH_PATTERN = /^[a-z]:[\\\\/](?![\\\\/])[^:]*$/iu;\n\nconst SCHEMELESS_HOST_CANDIDATE_PATTERN =\n /\\b(?:www\\.)?(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?(?::\\d{1,5})?(?:[/?#][^\\s]*)?/giu;\n\nconst SCHEMELESS_LOCAL_NETWORK_PATTERNS = [\n /\\blocalhost(?:(?::\\d{1,5})(?:[/?#][^\\s]*)?|[/?#][^\\s]*)/iu,\n /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)(?:(?::\\d{1,5})(?:[/?#][^\\s]*)?|[/?#][^\\s]*)/u,\n /\\[(?=[0-9a-f:.]*:[0-9a-f:.]*\\])[0-9a-f:.]+\\](?:(?::\\d{1,5})(?:[/?#][^\\s]*)?|[/?#][^\\s]*)/iu,\n] as const;\n\nconst FILE_LIKE_HOST_SUFFIXES = new Set([\n \"css\",\n \"html\",\n \"js\",\n \"json\",\n \"jsx\",\n \"lock\",\n \"md\",\n \"sql\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"xml\",\n \"yaml\",\n \"yml\",\n]);\n\n// These authorities are established framework/namespace notation whose exact\n// casing is meaningful. Keep this exception deliberately narrow: generic\n// PascalCase or uppercase authorities remain host-like because an uppercase\n// real domain (for example MICROSOFT.COM/Admin) must not bypass the URL gate.\nconst DOTTED_TECHNOLOGY_PATH_AUTHORITIES = new Set([\n \"ASP.NET\",\n \"AWS.SDK\",\n \"Microsoft.Extensions\",\n \"System.IO\",\n]);\n\nconst SECRET_ASSIGNMENT_CANDIDATE_PATTERN =\n /(?:^|[^A-Za-z0-9])(?:(['\"])([A-Za-z][A-Za-z0-9_. -]*)\\1|([A-Za-z][A-Za-z0-9_.-]*))\\s*[=:]\\s*[^\\s,;]+/gu;\n\nconst SECRET_LABEL_ASSIGNMENT_PATTERN =\n /\\b(?:api[ _-]?key|access[ _-]?token|auth[ _-]?token|credential|credentials|password|passwd|private[ _-]?key|secret|token)\\b\\s*[=:]\\s*[^\\s,;]+/iu;\n\nconst SENSITIVE_ASSIGNMENT_KEY_SUFFIXES = new Set([\n \"credential\",\n \"credentials\",\n \"password\",\n \"passwd\",\n \"secret\",\n \"token\",\n]);\n\nconst COMPACT_SENSITIVE_ASSIGNMENT_KEY_SUFFIXES = [\n \"apikey\",\n \"accesskey\",\n \"accesskeyid\",\n \"accesstoken\",\n \"authtoken\",\n \"credential\",\n \"credentials\",\n \"password\",\n \"passwd\",\n \"privatekey\",\n \"secret\",\n \"secretkey\",\n \"token\",\n] as const;\n\nconst SENSITIVE_ASSIGNMENT_KEY_WORD_SUFFIXES = [\n [\"api\", \"key\"],\n [\"access\", \"key\"],\n [\"access\", \"key\", \"id\"],\n [\"auth\", \"key\"],\n [\"private\", \"key\"],\n [\"secret\", \"key\"],\n] as const;\n\nfunction hasWordSuffix(words: readonly string[], suffix: readonly string[]): boolean {\n if (words.length < suffix.length) return false;\n const offset = words.length - suffix.length;\n return suffix.every((word, index) => words[offset + index] === word);\n}\n\nfunction containsSensitiveAssignment(value: string): boolean {\n for (const match of value.matchAll(SECRET_ASSIGNMENT_CANDIDATE_PATTERN)) {\n const key = match[2] ?? match[3];\n if (!key) continue;\n const words = key\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter(Boolean);\n const last = words.at(-1);\n if (last && SENSITIVE_ASSIGNMENT_KEY_SUFFIXES.has(last)) return true;\n if (last && COMPACT_SENSITIVE_ASSIGNMENT_KEY_SUFFIXES.some((suffix) => last.endsWith(suffix))) {\n return true;\n }\n if (SENSITIVE_ASSIGNMENT_KEY_WORD_SUFFIXES.some((suffix) => hasWordSuffix(words, suffix))) {\n return true;\n }\n }\n return false;\n}\n\nfunction containsUriScheme(value: string): boolean {\n for (const match of value.matchAll(URI_SCHEME_CANDIDATE_PATTERN)) {\n // A Windows drive path is the one scheme-shaped token accepted here. Keep\n // the exception exact: one separator after the drive letter and no later\n // colon, so x://host and a nested scheme remain rejected.\n if (!WINDOWS_DRIVE_PATH_PATTERN.test(match[0])) return true;\n }\n return false;\n}\n\nfunction isDottedTechnologyPath(candidate: string): boolean {\n if (/[?:#]/u.test(candidate)) return false;\n const [authority, ...pathSegments] = candidate.split(\"/\");\n if (!authority || pathSegments.length === 0 || pathSegments.some((segment) => !segment)) {\n return false;\n }\n if (\n !DOTTED_TECHNOLOGY_PATH_AUTHORITIES.has(authority) ||\n pathSegments.some((segment) => !/^[A-Z][A-Za-z0-9_-]*$/u.test(segment))\n ) {\n return false;\n }\n return true;\n}\n\nfunction containsSchemelessUrl(value: string): boolean {\n if (SCHEMELESS_LOCAL_NETWORK_PATTERNS.some((pattern) => pattern.test(value))) return true;\n\n for (const match of value.matchAll(SCHEMELESS_HOST_CANDIDATE_PATTERN)) {\n const candidate = match[0];\n if (candidate.toLowerCase().startsWith(\"www.\")) return true;\n if (!/[/?#]/u.test(candidate)) continue;\n\n const authority = candidate.split(/[/?#]/u, 1)[0] ?? \"\";\n const hostname = authority.replace(/:\\d{1,5}$/u, \"\");\n const suffix = hostname.split(\".\").at(-1)?.toLowerCase();\n if (suffix && FILE_LIKE_HOST_SUFFIXES.has(suffix)) continue;\n if (isDottedTechnologyPath(candidate)) continue;\n return true;\n }\n return false;\n}\n\nconst OPAQUE_IDENTIFIER_PATTERN =\n /\\b(?=[A-Za-z0-9_-]{32,}\\b)(?=[A-Za-z0-9_-]*[A-Za-z])(?=[A-Za-z0-9_-]*\\d)[A-Za-z0-9_-]+\\b/u;\n\nconst DEFAULT_IGNORABLE_CODE_POINTS = /\\p{Default_Ignorable_Code_Point}+/gu;\nconst ESCAPED_QUOTE_DELIMITERS = /\\\\+(?=[\"'])/gu;\n\nconst TITLE_LABEL_PATTERN =\n /^(?:(?:suggested|generated|concise)\\s+)?(?:(?:session|chat|conversation|task)\\s+)?title\\s*[:\\-–—]\\s*/iu;\n\nconst LEADING_BOILERPLATE_PATTERNS = [\n /^(?:hi|hello|hey)(?:\\s+there)?\\s*[,!:.\\-–—]*\\s*/iu,\n /^(?:i\\s+(?:would\\s+like|want|need)\\s+you\\s+to|i['’]d\\s+like\\s+you\\s+to)\\s+/iu,\n /^(?:please\\s+)?(?:can|could|would|will)\\s+you\\s+/iu,\n /^(?:your|the)\\s+(?:task|job)\\s+is\\s+to\\s+/iu,\n /^(?:please\\s+)?help\\s+me\\s+(?:to\\s+)?/iu,\n /^please(?:\\s*[,!:.\\-–—]+\\s*|\\s+|$)/iu,\n] as const;\n\nfunction automaticTitleDetectionValue(value: string): string {\n // Detection uses a compatibility-normalized shadow value so fullwidth\n // punctuation/letters, invisible token splits, and serialized quote\n // delimiters cannot evade the policy.\n // The accepted title itself stays byte-for-byte in the user's language and\n // emoji form; this shadow is never returned or persisted.\n return value\n .normalize(\"NFKC\")\n .replace(DEFAULT_IGNORABLE_CODE_POINTS, \"\")\n .replace(ESCAPED_QUOTE_DELIMITERS, \"\");\n}\n\nfunction hasVisibleAutomaticTitleContent(value: string): boolean {\n return automaticTitleDetectionValue(value).trim().length > 0;\n}\n\n/**\n * Whether a bounded automatic-title candidate contains a credential, URL, or\n * opaque identifier that must stay out of navigation and other display-title\n * surfaces. Callers handling an unbounded source must bound it before invoking\n * this helper.\n */\nexport function containsSensitiveAutomaticSessionTitleValue(value: string): boolean {\n const detectionValue = automaticTitleDetectionValue(value);\n\n if (KNOWN_SENSITIVE_VALUE_PATTERNS.some((pattern) => pattern.test(detectionValue))) return true;\n if (containsUriScheme(detectionValue)) return true;\n if (containsSchemelessUrl(detectionValue)) return true;\n if (SECRET_LABEL_ASSIGNMENT_PATTERN.test(detectionValue)) return true;\n if (containsSensitiveAssignment(detectionValue)) return true;\n if (OPAQUE_IDENTIFIER_PATTERN.test(detectionValue)) return true;\n return false;\n}\n\nfunction stripAutomaticTitleBoilerplate(value: string): string {\n let title = value;\n for (let pass = 0; pass < 4; pass += 1) {\n const before = title;\n title = title\n .replace(/^(?:```[^\\n]*|[\\s#>*_`\"'“”‘’\\-–—]+)+/u, \"\")\n .replace(TITLE_LABEL_PATTERN, \"\");\n for (const pattern of LEADING_BOILERPLATE_PATTERNS) {\n title = title.replace(pattern, \"\");\n }\n title = title.trim();\n if (title === before) break;\n }\n return title;\n}\n\nfunction automaticTitleGraphemes(value: string): string[] {\n if (titleSegmenter === undefined) {\n titleSegmenter =\n typeof Intl.Segmenter === \"function\"\n ? new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n : null;\n }\n if (titleSegmenter) {\n return Array.from(titleSegmenter.segment(value), (part) => part.segment);\n }\n\n // Older embedded runtimes may not ship Intl.Segmenter. Preserve surrogate\n // pairs plus common combining/emoji sequences instead of failing module load\n // or slicing UTF-16 code units.\n const graphemes: string[] = [];\n for (const point of value) {\n const prior = graphemes.at(-1);\n if (\n prior &&\n (/^[\\p{Mark}\\u{FE0E}\\u{FE0F}\\p{Emoji_Modifier}]$/u.test(point) ||\n point === \"\\u200d\" ||\n prior.endsWith(\"\\u200d\"))\n ) {\n graphemes[graphemes.length - 1] = `${prior}${point}`;\n } else {\n graphemes.push(point);\n }\n }\n return graphemes;\n}\n\n/** Bound an already-normalized automatic-title candidate without splitting graphemes. */\nexport function boundAutomaticSessionTitle(value: string): string {\n const words = value.split(/\\s+/u);\n const wordBounded = words.length > 10 ? words.slice(0, 10).join(\" \") : value;\n const graphemes = automaticTitleGraphemes(wordBounded);\n if (graphemes.length <= AUTOMATIC_SESSION_TITLE_MAX_GRAPHEMES) return wordBounded;\n\n const prefix = graphemes.slice(0, AUTOMATIC_SESSION_TITLE_MAX_GRAPHEMES).join(\"\");\n const lastWhitespace = prefix.search(/\\s+\\S*$/u);\n return (lastWhitespace >= 16 ? prefix.slice(0, lastWhitespace) : prefix).trimEnd();\n}\n\n/**\n * Normalize a model/system-authored title before it reaches durable session\n * metadata. Human renames intentionally do not use this path.\n *\n * Returns null when the candidate is empty, only boilerplate, or appears to\n * contain a credential/opaque prompt value. Callers should retain the current\n * title (normally {@link AUTOMATIC_SESSION_TITLE_FALLBACK}) in that case.\n */\nexport function normalizeAutomaticSessionTitle(value: string): string | null {\n const firstLine = value\n .replace(/[\\u0000-\\u001f\\u007f-\\u009f]+/gu, \"\\n\")\n .split(/\\n+/u)\n .map((line) => line.trim())\n .find(Boolean);\n if (\n !firstLine ||\n !hasVisibleAutomaticTitleContent(firstLine) ||\n containsSensitiveAutomaticSessionTitleValue(firstLine)\n ) {\n return null;\n }\n\n let title = stripAutomaticTitleBoilerplate(firstLine)\n .replace(/\\s+/gu, \" \")\n .replace(/[\\s.!?,;:\\-–—]+$/u, \"\")\n .trim();\n if (\n !title ||\n !hasVisibleAutomaticTitleContent(title) ||\n containsSensitiveAutomaticSessionTitleValue(title)\n ) {\n return null;\n }\n\n title = boundAutomaticSessionTitle(title)\n .replace(/[\\s.!?,;:\\-–—]+$/u, \"\")\n .trim();\n if (!title || !hasVisibleAutomaticTitleContent(title)) return null;\n return title;\n}\n"],"mappings":"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","names":[]}
|