@nestm/storage 0.1.0-alpha.2 → 0.1.0-alpha.20
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/CHANGELOG.md +320 -0
- package/README.md +975 -29
- package/SECURITY.md +128 -0
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.d.ts +53 -0
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.d.ts.map +1 -0
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.js +370 -0
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.js.map +1 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.d.ts +91 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.d.ts.map +1 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.js +497 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.js.map +1 -0
- package/dist/ai-sdk/index.d.ts +3 -0
- package/dist/ai-sdk/index.d.ts.map +1 -0
- package/dist/ai-sdk/index.js +3 -0
- package/dist/ai-sdk/index.js.map +1 -0
- package/dist/bytes/index.d.ts +30 -0
- package/dist/bytes/index.d.ts.map +1 -0
- package/dist/bytes/index.js +96 -0
- package/dist/bytes/index.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/storage-staged-content.d.ts +39 -0
- package/dist/core/storage-staged-content.d.ts.map +1 -0
- package/dist/core/storage-staged-content.js +109 -0
- package/dist/core/storage-staged-content.js.map +1 -0
- package/dist/core/storage-streams.d.ts +19 -0
- package/dist/core/storage-streams.d.ts.map +1 -0
- package/dist/core/storage-streams.js +95 -0
- package/dist/core/storage-streams.js.map +1 -0
- package/dist/core/storage-text-edit.d.ts +38 -0
- package/dist/core/storage-text-edit.d.ts.map +1 -0
- package/dist/core/storage-text-edit.js +86 -0
- package/dist/core/storage-text-edit.js.map +1 -0
- package/dist/core/storage-text-stream-edit.d.ts +8 -0
- package/dist/core/storage-text-stream-edit.d.ts.map +1 -0
- package/dist/core/storage-text-stream-edit.js +114 -0
- package/dist/core/storage-text-stream-edit.js.map +1 -0
- package/dist/core/storage-text.d.ts +22 -0
- package/dist/core/storage-text.d.ts.map +1 -0
- package/dist/core/storage-text.js +69 -0
- package/dist/core/storage-text.js.map +1 -0
- package/dist/crypto/index.d.ts +2 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +2 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/storage-encrypted-content.d.ts +49 -0
- package/dist/crypto/storage-encrypted-content.d.ts.map +1 -0
- package/dist/crypto/storage-encrypted-content.js +212 -0
- package/dist/crypto/storage-encrypted-content.js.map +1 -0
- package/dist/files-sdk/azure/azure-conditional.d.ts +5 -0
- package/dist/files-sdk/azure/azure-conditional.d.ts.map +1 -0
- package/dist/files-sdk/azure/azure-conditional.js +184 -0
- package/dist/files-sdk/azure/azure-conditional.js.map +1 -0
- package/dist/files-sdk/azure/index.d.ts +10 -0
- package/dist/files-sdk/azure/index.d.ts.map +1 -0
- package/dist/files-sdk/azure/index.js +34 -0
- package/dist/files-sdk/azure/index.js.map +1 -0
- package/dist/files-sdk/files-sdk.driver.d.ts +85 -3
- package/dist/files-sdk/files-sdk.driver.d.ts.map +1 -1
- package/dist/files-sdk/files-sdk.driver.js +1437 -37
- package/dist/files-sdk/files-sdk.driver.js.map +1 -1
- package/dist/files-sdk/fs/index.d.ts +42 -0
- package/dist/files-sdk/fs/index.d.ts.map +1 -0
- package/dist/files-sdk/fs/index.js +1117 -0
- package/dist/files-sdk/fs/index.js.map +1 -0
- package/dist/files-sdk/index.d.ts +1 -1
- package/dist/files-sdk/index.d.ts.map +1 -1
- package/dist/files-sdk/index.js.map +1 -1
- package/dist/files-sdk/memory.d.ts +7 -0
- package/dist/files-sdk/memory.d.ts.map +1 -0
- package/dist/files-sdk/memory.js +72 -0
- package/dist/files-sdk/memory.js.map +1 -0
- package/dist/files-sdk/provider/index.d.ts +58 -0
- package/dist/files-sdk/provider/index.d.ts.map +1 -0
- package/dist/files-sdk/provider/index.js +169 -0
- package/dist/files-sdk/provider/index.js.map +1 -0
- package/dist/files-sdk/s3/construction-metadata.d.ts +9 -0
- package/dist/files-sdk/s3/construction-metadata.d.ts.map +1 -0
- package/dist/files-sdk/s3/construction-metadata.js +24 -0
- package/dist/files-sdk/s3/construction-metadata.js.map +1 -0
- package/dist/files-sdk/s3/index.d.ts +54 -0
- package/dist/files-sdk/s3/index.d.ts.map +1 -0
- package/dist/files-sdk/s3/index.js +1505 -0
- package/dist/files-sdk/s3/index.js.map +1 -0
- package/dist/gateway/index.d.ts +1 -1
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/storage-gateway-fastify-parser.d.ts.map +1 -1
- package/dist/gateway/storage-gateway-fastify-parser.js.map +1 -1
- package/dist/gateway/storage-gateway.controller.d.ts +12 -11
- package/dist/gateway/storage-gateway.controller.d.ts.map +1 -1
- package/dist/gateway/storage-gateway.controller.js +240 -70
- package/dist/gateway/storage-gateway.controller.js.map +1 -1
- package/dist/gateway/storage-gateway.guard.d.ts.map +1 -1
- package/dist/gateway/storage-gateway.guard.js.map +1 -1
- package/dist/gateway/storage-gateway.module.d.ts.map +1 -1
- package/dist/gateway/storage-gateway.module.js +60 -1
- package/dist/gateway/storage-gateway.module.js.map +1 -1
- package/dist/gateway/storage-gateway.tokens.d.ts +1 -0
- package/dist/gateway/storage-gateway.tokens.d.ts.map +1 -1
- package/dist/gateway/storage-gateway.tokens.js +1 -0
- package/dist/gateway/storage-gateway.tokens.js.map +1 -1
- package/dist/gateway/storage-gateway.types.d.ts +53 -10
- package/dist/gateway/storage-gateway.types.d.ts.map +1 -1
- package/dist/gateway/storage-gateway.types.js.map +1 -1
- package/dist/inject-storage.decorator.js.map +1 -1
- package/dist/storage-etag.d.ts +13 -0
- package/dist/storage-etag.d.ts.map +1 -0
- package/dist/storage-etag.js +31 -0
- package/dist/storage-etag.js.map +1 -0
- package/dist/storage-upload-control.d.ts.map +1 -1
- package/dist/storage.client.d.ts +14 -1
- package/dist/storage.client.d.ts.map +1 -1
- package/dist/storage.client.js +204 -2
- package/dist/storage.client.js.map +1 -1
- package/dist/storage.driver.d.ts +28 -1
- package/dist/storage.driver.d.ts.map +1 -1
- package/dist/storage.driver.js.map +1 -1
- package/dist/storage.error.d.ts +17 -10
- package/dist/storage.error.d.ts.map +1 -1
- package/dist/storage.error.js +47 -1
- package/dist/storage.error.js.map +1 -1
- package/dist/storage.module.d.ts.map +1 -1
- package/dist/storage.module.js.map +1 -1
- package/dist/storage.service.d.ts.map +1 -1
- package/dist/storage.service.js +28 -3
- package/dist/storage.service.js.map +1 -1
- package/dist/storage.tokens.js.map +1 -1
- package/dist/storage.types.d.ts +150 -1
- package/dist/storage.types.d.ts.map +1 -1
- package/dist/storage.types.js.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +3 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/provider-conformance.d.ts +65 -0
- package/dist/testing/provider-conformance.d.ts.map +1 -0
- package/dist/testing/provider-conformance.js +869 -0
- package/dist/testing/provider-conformance.js.map +1 -0
- package/dist/workspace/index.d.ts +12 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +10 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/storage-catalog-checkout.d.ts +7 -0
- package/dist/workspace/storage-catalog-checkout.d.ts.map +1 -0
- package/dist/workspace/storage-catalog-checkout.js +13 -0
- package/dist/workspace/storage-catalog-checkout.js.map +1 -0
- package/dist/workspace/storage-draft-stream.d.ts +3 -0
- package/dist/workspace/storage-draft-stream.d.ts.map +1 -0
- package/dist/workspace/storage-draft-stream.js +57 -0
- package/dist/workspace/storage-draft-stream.js.map +1 -0
- package/dist/workspace/storage-file-catalog.types.d.ts +73 -0
- package/dist/workspace/storage-file-catalog.types.d.ts.map +1 -0
- package/dist/workspace/storage-file-catalog.types.js +2 -0
- package/dist/workspace/storage-file-catalog.types.js.map +1 -0
- package/dist/workspace/storage-file-workflow.d.ts +7 -0
- package/dist/workspace/storage-file-workflow.d.ts.map +1 -0
- package/dist/workspace/storage-file-workflow.js +657 -0
- package/dist/workspace/storage-file-workflow.js.map +1 -0
- package/dist/workspace/storage-file-workflow.protection.d.ts +31 -0
- package/dist/workspace/storage-file-workflow.protection.d.ts.map +1 -0
- package/dist/workspace/storage-file-workflow.protection.js +339 -0
- package/dist/workspace/storage-file-workflow.protection.js.map +1 -0
- package/dist/workspace/storage-file-workflow.types.d.ts +184 -0
- package/dist/workspace/storage-file-workflow.types.d.ts.map +1 -0
- package/dist/workspace/storage-file-workflow.types.js +10 -0
- package/dist/workspace/storage-file-workflow.types.js.map +1 -0
- package/dist/workspace/storage-text-draft.d.ts +21 -0
- package/dist/workspace/storage-text-draft.d.ts.map +1 -0
- package/dist/workspace/storage-text-draft.js +77 -0
- package/dist/workspace/storage-text-draft.js.map +1 -0
- package/dist/workspace/storage-working-files.d.ts +34 -0
- package/dist/workspace/storage-working-files.d.ts.map +1 -0
- package/dist/workspace/storage-working-files.js +326 -0
- package/dist/workspace/storage-working-files.js.map +1 -0
- package/dist/workspace/storage-workspace.cursor.d.ts +71 -0
- package/dist/workspace/storage-workspace.cursor.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.cursor.js +408 -0
- package/dist/workspace/storage-workspace.cursor.js.map +1 -0
- package/dist/workspace/storage-workspace.d.ts +6 -0
- package/dist/workspace/storage-workspace.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.error.d.ts +32 -0
- package/dist/workspace/storage-workspace.error.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.error.js +75 -0
- package/dist/workspace/storage-workspace.error.js.map +1 -0
- package/dist/workspace/storage-workspace.js +849 -0
- package/dist/workspace/storage-workspace.js.map +1 -0
- package/dist/workspace/storage-workspace.path.d.ts +9 -0
- package/dist/workspace/storage-workspace.path.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.path.js +68 -0
- package/dist/workspace/storage-workspace.path.js.map +1 -0
- package/dist/workspace/storage-workspace.types.d.ts +123 -0
- package/dist/workspace/storage-workspace.types.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.types.js +22 -0
- package/dist/workspace/storage-workspace.types.js.map +1 -0
- package/package.json +99 -20
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-sdk-workspace-tools.js","sourceRoot":"","sources":["../../src/ai-sdk/ai-sdk-workspace-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { tool, type JSONValue, type ToolSet } from 'ai';\nimport { z } from 'zod';\n\nimport {\n STORAGE_WORKSPACE_MAX_CURSOR_BYTES,\n isStorageWorkspaceError,\n type StorageWorkspace,\n type StorageWorkspaceEntry,\n type StorageWorkspaceFile,\n type StorageWorkspaceTextFile,\n} from '../workspace/index.js';\nimport {\n StorageErrorCode,\n isStorageError,\n type StorageErrorCode as StorageErrorCodeValue,\n} from '../storage.error.js';\nimport { isCanonicalStorageEtag } from '../storage-etag.js';\n\nexport const AI_SDK_WORKSPACE_TOOL_NAMES = [\n 'workspace_list',\n 'workspace_stat',\n 'workspace_read_file',\n 'workspace_search',\n 'workspace_write_file',\n 'workspace_copy_file',\n 'workspace_move_file',\n 'workspace_delete_file',\n] as const;\n\nexport type AiSdkWorkspaceToolName =\n (typeof AI_SDK_WORKSPACE_TOOL_NAMES)[number];\n\nexport type AiSdkWorkspaceMutationToolName = Extract<\n AiSdkWorkspaceToolName,\n | 'workspace_write_file'\n | 'workspace_copy_file'\n | 'workspace_move_file'\n | 'workspace_delete_file'\n>;\n\n/**\n * Approval policy for mutation tools. An omitted entry defaults to requiring\n * approval, matching an omitted policy.\n */\nexport type AiSdkWorkspaceApprovalConfig =\n boolean | Partial<Record<AiSdkWorkspaceMutationToolName, boolean>>;\n\nexport type AiSdkWorkspaceMutationMode = 'conditional' | 'last-write-wins';\n\nexport interface AiSdkWorkspaceCreateConflict {\n /** The logical destination inside the mounted workspace. */\n readonly path: string;\n}\n\nexport type AiSdkWorkspaceCreateConflictMapper<Result extends JSONValue> = (\n conflict: AiSdkWorkspaceCreateConflict,\n) => PromiseLike<Result> | Result;\n\nexport interface CreateAiSdkWorkspaceToolsOptions<\n CreateConflictResult extends JSONValue = never,\n> {\n /** The already-mounted, policy-enforcing workspace exposed to the tools. */\n workspace: StorageWorkspace;\n /**\n * Optional tighter read ceiling. Values above the workspace ceiling are\n * clamped; the model cannot choose or raise this value.\n */\n maxReadBytes?: number;\n /** Mutation tools require approval by default. */\n requireApproval?: AiSdkWorkspaceApprovalConfig;\n /**\n * Selects the mutation contract exposed to the model. Conditional mode is\n * the default; last-write-wins uses the workspace's ordinary Files path.\n */\n mutationMode?: AiSdkWorkspaceMutationMode;\n /**\n * Maps an atomic create collision to an application result. When omitted,\n * the collision remains an AiSdkWorkspaceToolError like every other storage\n * failure. Replace conflicts are never mapped by this hook. This option is\n * valid only when mutationMode is conditional.\n */\n mapCreateConflict?: AiSdkWorkspaceCreateConflictMapper<CreateConflictResult>;\n}\n\nexport type AiSdkWorkspaceToolErrorCode = StorageErrorCodeValue;\n\nexport interface AiSdkWorkspaceToolErrorOptions {\n /** True when the failed operation may already have committed. */\n readonly applied?: boolean;\n /** Canonical ETag of the committed object, when the provider returned one. */\n readonly appliedEtag?: string;\n}\n\nconst SAFE_ERROR_MESSAGES: Readonly<\n Record<AiSdkWorkspaceToolErrorCode, string>\n> = {\n [StorageErrorCode.NOT_FOUND]: 'The requested workspace path was not found.',\n [StorageErrorCode.UNAUTHORIZED]:\n 'This operation is not permitted in the workspace.',\n [StorageErrorCode.CONFLICT]:\n 'The operation conflicts with current workspace state. Inspect the affected paths before retrying.',\n [StorageErrorCode.READ_ONLY]:\n 'This operation is not permitted in the workspace.',\n [StorageErrorCode.INVALID_ARGUMENT]: 'The workspace tool input was rejected.',\n [StorageErrorCode.NOT_SUPPORTED]:\n 'This workspace operation is not supported by the configured storage.',\n [StorageErrorCode.ABORTED]: 'The workspace operation was aborted.',\n [StorageErrorCode.TIMEOUT]: 'The workspace operation timed out.',\n [StorageErrorCode.LIMIT_EXCEEDED]:\n 'The workspace operation exceeded a configured limit.',\n [StorageErrorCode.PROVIDER]: 'The workspace operation failed.',\n};\n\n/**\n * Safe error exposed at the AI tool boundary. It deliberately carries no\n * provider error, storage key, mount prefix, store name, or cause. Applied\n * reconciliation metadata is retained so callers do not blindly retry a\n * mutation that may already have committed.\n */\nexport class AiSdkWorkspaceToolError extends Error {\n readonly code: AiSdkWorkspaceToolErrorCode;\n declare readonly applied?: true;\n declare readonly appliedEtag?: string;\n\n constructor(\n code: AiSdkWorkspaceToolErrorCode,\n options: AiSdkWorkspaceToolErrorOptions = {},\n ) {\n super(SAFE_ERROR_MESSAGES[code]);\n this.name = 'AiSdkWorkspaceToolError';\n this.code = code;\n if (options.applied === true) {\n this.applied = true;\n if (\n options.appliedEtag !== undefined &&\n isCanonicalStorageEtag(options.appliedEtag)\n ) {\n this.appliedEtag = options.appliedEtag;\n }\n }\n }\n}\n\nexport interface AiSdkWorkspaceFileResult {\n kind: 'file';\n path: string;\n name: string;\n size: number;\n contentType: string;\n etag?: string;\n lastModified?: string;\n}\n\nexport interface AiSdkWorkspaceDirectoryResult {\n kind: 'directory';\n path: string;\n name: string;\n}\n\nexport type AiSdkWorkspaceEntryResult =\n AiSdkWorkspaceFileResult | AiSdkWorkspaceDirectoryResult;\n\nexport interface AiSdkWorkspaceTextFileResult extends AiSdkWorkspaceFileResult {\n text: string;\n}\n\nexport interface AiSdkWorkspacePageResult {\n entries: AiSdkWorkspaceEntryResult[];\n cursor?: string;\n}\n\nconst mutationToolNames = new Set<AiSdkWorkspaceMutationToolName>([\n 'workspace_write_file',\n 'workspace_copy_file',\n 'workspace_move_file',\n 'workspace_delete_file',\n]);\nconst utf8Encoder = new TextEncoder();\nconst forbiddenUnicodeCharacter = /\\p{C}/u;\nconst workspaceCursor = /^[A-Za-z0-9._-]+$/u;\nconst windowsDeviceName = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\\..*)?$/iu;\n\nfunction isLogicalPath(value: string): boolean {\n if (\n value.length === 0 ||\n value.startsWith('/') ||\n value.endsWith('/') ||\n value !== value.normalize('NFC') ||\n value.includes('\\\\') ||\n forbiddenUnicodeCharacter.test(value)\n ) {\n return false;\n }\n\n return value\n .split('/')\n .every(\n (segment) =>\n segment.length > 0 &&\n segment !== '.' &&\n segment !== '..' &&\n !segment.includes(':') &&\n !segment.endsWith('.') &&\n !segment.endsWith(' ') &&\n !windowsDeviceName.test(segment),\n );\n}\n\nfunction logicalPath(label: string, maxBytes: number) {\n return z\n .string()\n .min(1)\n .refine(isLogicalPath, {\n message: `${label} must be a portable, NFC-normalized, relative POSIX workspace path.`,\n })\n .refine((value) => utf8Encoder.encode(value).byteLength <= maxBytes, {\n message: `${label} exceeds the ${maxBytes}-byte workspace path limit.`,\n })\n .describe(\n `${label}. Use an NFC-normalized relative POSIX path inside the mounted workspace. Empty, dot, parent, colon, trailing dot or space, and Windows reserved device segments are forbidden.`,\n );\n}\n\nfunction searchQuery(maxBytes: number) {\n return z\n .string()\n .min(1)\n .refine(\n (value) =>\n !value.includes('\\\\') && !forbiddenUnicodeCharacter.test(value),\n { message: 'Search query contains forbidden characters.' },\n )\n .refine((value) => utf8Encoder.encode(value).byteLength <= maxBytes, {\n message: `Search query exceeds the ${maxBytes}-byte workspace limit.`,\n })\n .describe('Path pattern or text to find inside the mounted workspace.');\n}\n\nfunction boundedEtag() {\n return z\n .string()\n .refine(isCanonicalStorageEtag, {\n message: 'ETag must be a canonical bare value of at most 1,024 bytes.',\n })\n .describe(\n 'Exact canonical bare ETag returned by the latest workspace stat or read.',\n );\n}\n\nfunction continuationCursor(description: string, maxBytes: number) {\n return z\n .string()\n .min(1)\n .max(Math.min(STORAGE_WORKSPACE_MAX_CURSOR_BYTES, maxBytes))\n .regex(\n workspaceCursor,\n 'Cursor must be the bounded opaque token returned by the workspace.',\n )\n .optional()\n .describe(description);\n}\n\nfunction positiveIntegerAtMost(maximum: number, description: string) {\n return z\n .number()\n .int()\n .positive()\n .max(maximum)\n .optional()\n .describe(description);\n}\n\nfunction operationOptions(signal: AbortSignal | undefined): {\n signal?: AbortSignal;\n} {\n return signal === undefined ? {} : { signal };\n}\n\nfunction resolveApproval(\n toolName: AiSdkWorkspaceMutationToolName,\n config: AiSdkWorkspaceApprovalConfig,\n): boolean {\n return typeof config === 'boolean' ? config : (config[toolName] ?? true);\n}\n\nfunction resolveReadLimit(\n workspace: StorageWorkspace,\n requested: number | undefined,\n): number {\n const workspaceLimit = workspace.limits.maxReadBytes;\n if (!Number.isSafeInteger(workspaceLimit) || workspaceLimit <= 0) {\n throw new RangeError(\n 'workspace.limits.maxReadBytes must be a positive safe integer.',\n );\n }\n if (\n requested !== undefined &&\n (!Number.isSafeInteger(requested) || requested <= 0)\n ) {\n throw new RangeError('maxReadBytes must be a positive safe integer.');\n }\n return Math.min(requested ?? workspaceLimit, workspaceLimit);\n}\n\nfunction sanitizeToolError(\n error: unknown,\n signal: AbortSignal | undefined,\n): AiSdkWorkspaceToolError {\n if (error instanceof AiSdkWorkspaceToolError) {\n return error;\n }\n const reconciliation =\n isStorageWorkspaceError(error) || isStorageError(error)\n ? {\n applied: error.applied,\n ...(error.appliedEtag !== undefined && {\n appliedEtag: error.appliedEtag,\n }),\n }\n : {};\n if (signal?.aborted === true) {\n return new AiSdkWorkspaceToolError(\n signal.reason instanceof Error && signal.reason.name === 'TimeoutError'\n ? StorageErrorCode.TIMEOUT\n : StorageErrorCode.ABORTED,\n reconciliation,\n );\n }\n if (isStorageWorkspaceError(error)) {\n return new AiSdkWorkspaceToolError(error.code, reconciliation);\n }\n if (isStorageError(error)) {\n return new AiSdkWorkspaceToolError(error.code, reconciliation);\n }\n if (error instanceof Error && error.name === 'TimeoutError')\n return new AiSdkWorkspaceToolError(\n StorageErrorCode.TIMEOUT,\n reconciliation,\n );\n if (error instanceof Error && error.name === 'AbortError')\n return new AiSdkWorkspaceToolError(\n StorageErrorCode.ABORTED,\n reconciliation,\n );\n return new AiSdkWorkspaceToolError(StorageErrorCode.PROVIDER);\n}\n\nasync function executeSafely<Result>(\n signal: AbortSignal | undefined,\n operation: () => Promise<Result>,\n): Promise<Result> {\n try {\n return await operation();\n } catch (error) {\n throw sanitizeToolError(error, signal);\n }\n}\n\nasync function executeCreateAware<\n Result,\n CreateConflictResult extends JSONValue,\n>(\n signal: AbortSignal | undefined,\n input: { mode: 'create' | 'replace'; path: string },\n operation: () => Promise<Result>,\n mapCreateConflict:\n AiSdkWorkspaceCreateConflictMapper<CreateConflictResult> | undefined,\n): Promise<CreateConflictResult | Result> {\n try {\n return await operation();\n } catch (error) {\n const safeError = sanitizeToolError(error, signal);\n if (\n input.mode === 'create' &&\n safeError.code === StorageErrorCode.CONFLICT &&\n safeError.applied !== true &&\n mapCreateConflict !== undefined\n ) {\n try {\n return await mapCreateConflict({ path: input.path });\n } catch {\n throw new AiSdkWorkspaceToolError(StorageErrorCode.PROVIDER);\n }\n }\n throw safeError;\n }\n}\n\nfunction serializeFile(file: StorageWorkspaceFile): AiSdkWorkspaceFileResult {\n if (file.etag !== undefined && !isCanonicalStorageEtag(file.etag)) {\n throw new Error('Workspace returned a malformed ETag.');\n }\n return {\n kind: 'file',\n path: file.path,\n name: file.name,\n size: file.size,\n contentType: file.contentType,\n ...(file.etag === undefined ? {} : { etag: file.etag }),\n ...(file.lastModified === undefined\n ? {}\n : { lastModified: file.lastModified.toISOString() }),\n };\n}\n\nfunction serializeEntry(\n entry: StorageWorkspaceEntry,\n): AiSdkWorkspaceEntryResult {\n return entry.kind === 'file'\n ? serializeFile(entry)\n : { kind: 'directory', path: entry.path, name: entry.name };\n}\n\nfunction serializeTextFile(\n file: StorageWorkspaceTextFile,\n): AiSdkWorkspaceTextFileResult {\n return { ...serializeFile(file), text: file.text };\n}\n\nfunction serializePage(page: {\n entries: StorageWorkspaceEntry[];\n cursor?: string;\n}): AiSdkWorkspacePageResult {\n return {\n entries: page.entries.map(serializeEntry),\n ...(page.cursor === undefined ? {} : { cursor: page.cursor }),\n };\n}\n\n/**\n * Creates Vercel AI SDK tools backed only by a mounted StorageWorkspace.\n *\n * A tool is omitted unless the workspace grants its required permission.\n * The workspace remains the enforcing boundary if a retained tool reference\n * is invoked after further narrowing.\n */\nexport function createAiSdkWorkspaceTools<\n CreateConflictResult extends JSONValue = never,\n>({\n workspace,\n maxReadBytes: requestedMaxReadBytes,\n mutationMode = 'conditional',\n requireApproval = true,\n mapCreateConflict,\n}: CreateAiSdkWorkspaceToolsOptions<CreateConflictResult>): ToolSet {\n if (mutationMode !== 'conditional' && mutationMode !== 'last-write-wins') {\n throw new RangeError(\n 'mutationMode must be \"conditional\" or \"last-write-wins\".',\n );\n }\n if (mutationMode === 'last-write-wins' && mapCreateConflict !== undefined) {\n throw new RangeError(\n 'mapCreateConflict is available only in conditional mutation mode.',\n );\n }\n const maxReadBytes = resolveReadLimit(workspace, requestedMaxReadBytes);\n const tools: ToolSet = {};\n const pathSchema = logicalPath('File path', workspace.limits.maxPathBytes);\n const directorySchema = logicalPath(\n 'Directory path',\n workspace.limits.maxPathBytes,\n );\n const etagSchema = boundedEtag();\n\n if (workspace.allows('list')) {\n tools.workspace_list = tool({\n description:\n 'List files and directories inside the mounted workspace. Omit directory to list the workspace root.',\n // Optional pagination and directory inputs are not compatible with\n // OpenAI strict function schemas, which require every property.\n strict: false,\n inputSchema: z\n .object({\n directory: directorySchema.optional(),\n recursive: z\n .boolean()\n .optional()\n .describe('Whether to include descendants recursively.'),\n limit: positiveIntegerAtMost(\n workspace.limits.maxPageSize,\n `Maximum entries to return, up to ${workspace.limits.maxPageSize}.`,\n ),\n cursor: continuationCursor(\n 'Opaque cursor returned by a preceding list call. It may be replayed before expiry while its provider continuation remains valid; repeat the same directory, recursive, and limit options when continuing.',\n workspace.limits.maxCursorBytes,\n ),\n })\n .strict(),\n execute: (input, { abortSignal }) =>\n executeSafely(abortSignal, async () =>\n serializePage(\n await workspace.list({\n ...(input.directory === undefined\n ? {}\n : { directory: input.directory }),\n ...(input.recursive === undefined\n ? {}\n : { recursive: input.recursive }),\n ...(input.limit === undefined ? {} : { limit: input.limit }),\n ...(input.cursor === undefined ? {} : { cursor: input.cursor }),\n ...operationOptions(abortSignal),\n }),\n ),\n ),\n });\n }\n\n if (workspace.allows('read')) {\n tools.workspace_stat = tool({\n description:\n mutationMode === 'conditional'\n ? 'Inspect a file inside the mounted workspace without reading its contents. Returns the ETag required for safe replace, move, and delete operations.'\n : 'Inspect a file inside the mounted workspace without reading its contents. Any returned ETag is informational in last-write-wins mode.',\n strict: true,\n inputSchema: z.object({ path: pathSchema }).strict(),\n execute: ({ path }, { abortSignal }) =>\n executeSafely(abortSignal, async () =>\n serializeFile(\n await workspace.stat(path, operationOptions(abortSignal)),\n ),\n ),\n });\n\n tools.workspace_read_file = tool({\n description: `Read a UTF-8 text file inside the mounted workspace. The result is bounded to ${maxReadBytes} bytes.`,\n strict: true,\n inputSchema: z.object({ path: pathSchema }).strict(),\n execute: ({ path }, { abortSignal }) =>\n executeSafely(abortSignal, async () =>\n serializeTextFile(\n await workspace.readText(path, {\n maxBytes: maxReadBytes,\n ...operationOptions(abortSignal),\n }),\n ),\n ),\n });\n }\n\n if (workspace.allows('search')) {\n tools.workspace_search = tool({\n description:\n 'Search logical paths inside the mounted workspace using a bounded glob, substring, or exact match. Omit directory to search from the workspace root.',\n // Search intentionally has optional filters and cursor inputs.\n strict: false,\n inputSchema: z\n .object({\n query: searchQuery(workspace.limits.maxPathBytes),\n directory: directorySchema.optional(),\n match: z\n .enum(['glob', 'substring', 'exact'])\n .optional()\n .describe('Matching strategy; defaults to glob.'),\n caseInsensitive: z.boolean().optional(),\n limit: positiveIntegerAtMost(\n workspace.limits.maxSearchResults,\n `Maximum matches to return, up to ${workspace.limits.maxSearchResults}.`,\n ),\n cursor: continuationCursor(\n 'Opaque cursor returned by a preceding search call. It may be replayed before expiry while its provider continuation remains valid; repeat the same query, directory, match, caseInsensitive, and limit options when continuing.',\n workspace.limits.maxCursorBytes,\n ),\n })\n .strict(),\n execute: (\n { query, directory, match, caseInsensitive, limit, cursor },\n { abortSignal },\n ) =>\n executeSafely(abortSignal, async () =>\n serializePage(\n await workspace.search(query, {\n ...(directory === undefined ? {} : { directory }),\n ...(match === undefined ? {} : { match }),\n ...(caseInsensitive === undefined ? {} : { caseInsensitive }),\n ...(limit === undefined ? {} : { limit }),\n ...(cursor === undefined ? {} : { cursor }),\n ...operationOptions(abortSignal),\n }),\n ),\n ),\n });\n }\n\n const commonWriteShape = {\n path: pathSchema,\n content: z\n .string()\n .refine(\n (value) =>\n utf8Encoder.encode(value).byteLength <=\n workspace.limits.maxWriteBytes,\n {\n message: `Content exceeds the ${workspace.limits.maxWriteBytes}-byte workspace write limit.`,\n },\n )\n .describe(\n `UTF-8 text to write. The workspace enforces its ${workspace.limits.maxWriteBytes}-byte write limit.`,\n ),\n };\n if (mutationMode === 'last-write-wins' && workspace.allows('write')) {\n const inputSchema = z.object(commonWriteShape).strict();\n tools.workspace_write_file = tool({\n description:\n 'Write a UTF-8 text file inside the mounted workspace. An existing destination is overwritten; the last successful writer wins.',\n strict: true,\n inputSchema,\n needsApproval: resolveApproval('workspace_write_file', requireApproval),\n execute: ({ path, content }, { abortSignal }) =>\n executeSafely(abortSignal, async () =>\n serializeFile(\n await workspace.writeFile(path, content, {\n mode: 'overwrite',\n ...operationOptions(abortSignal),\n }),\n ),\n ),\n });\n } else if (mutationMode === 'conditional') {\n const canCreate = workspace.allows('create');\n const canReplace = workspace.allows('replace');\n if (canCreate || canReplace) {\n const createSchema = z\n .object({ ...commonWriteShape, mode: z.literal('create') })\n .strict();\n const replaceSchema = z\n .object({\n ...commonWriteShape,\n mode: z.literal('replace'),\n etag: etagSchema,\n })\n .strict();\n const inputSchema =\n canCreate && canReplace\n ? z.discriminatedUnion('mode', [createSchema, replaceSchema])\n : canCreate\n ? createSchema\n : replaceSchema;\n\n tools.workspace_write_file = tool<\n z.infer<typeof inputSchema>,\n unknown,\n Record<string, unknown>\n >({\n description:\n canCreate && canReplace\n ? 'Create a new UTF-8 text file or replace an existing file inside the mounted workspace. Create fails if the destination exists; replace requires its current ETag.'\n : canCreate\n ? 'Create a new UTF-8 text file inside the mounted workspace. The operation fails if the destination already exists.'\n : 'Replace an existing UTF-8 text file inside the mounted workspace using its current ETag.',\n // The combined create/replace schema is a discriminated union. OpenAI\n // strict function tools reject its root-level oneOf, while the runtime\n // Zod schema continues to validate every tool call in non-strict mode.\n strict: !(canCreate && canReplace),\n inputSchema,\n needsApproval: resolveApproval('workspace_write_file', requireApproval),\n execute: (input, { abortSignal }) =>\n executeCreateAware(\n abortSignal,\n input,\n async () =>\n serializeFile(\n input.mode === 'create'\n ? await workspace.writeFile(input.path, input.content, {\n mode: 'create',\n ...operationOptions(abortSignal),\n })\n : await workspace.writeFile(input.path, input.content, {\n mode: 'replace',\n etag: input.etag,\n ...operationOptions(abortSignal),\n }),\n ),\n mapCreateConflict,\n ),\n });\n }\n }\n\n const canCopy = workspace.allows('copy') && workspace.allows('read');\n if (\n mutationMode === 'last-write-wins' &&\n canCopy &&\n workspace.allows('write')\n ) {\n tools.workspace_copy_file = tool({\n description:\n 'Copy the latest readable contents of a file inside the mounted workspace. The source remains intact, and an existing destination is overwritten.',\n strict: true,\n inputSchema: z\n .object({\n source: logicalPath(\n 'Source file path',\n workspace.limits.maxPathBytes,\n ),\n destination: logicalPath(\n 'Destination file path',\n workspace.limits.maxPathBytes,\n ),\n })\n .strict(),\n needsApproval: resolveApproval('workspace_copy_file', requireApproval),\n execute: ({ source, destination }, { abortSignal }) =>\n executeSafely(abortSignal, async () =>\n serializeFile(\n await workspace.copyFile(source, destination, {\n mode: 'overwrite',\n ...operationOptions(abortSignal),\n }),\n ),\n ),\n });\n } else if (\n mutationMode === 'conditional' &&\n canCopy &&\n workspace.allows('create')\n ) {\n tools.workspace_copy_file = tool({\n description:\n 'Copy an exact observed version of a file inside the mounted workspace. The source remains intact, and the operation fails if the source changed or the destination already exists.',\n strict: true,\n inputSchema: z\n .object({\n source: logicalPath(\n 'Source file path',\n workspace.limits.maxPathBytes,\n ),\n destination: logicalPath(\n 'Destination file path',\n workspace.limits.maxPathBytes,\n ),\n etag: etagSchema.describe(\n 'Exact ETag of the source returned by the latest workspace stat or read.',\n ),\n })\n .strict(),\n needsApproval: resolveApproval('workspace_copy_file', requireApproval),\n execute: ({ source, destination, etag }, { abortSignal }) =>\n executeSafely(abortSignal, async () =>\n serializeFile(\n await workspace.copyFile(source, destination, {\n etag,\n ...operationOptions(abortSignal),\n }),\n ),\n ),\n });\n }\n\n if (\n mutationMode === 'conditional' &&\n workspace.allows('move') &&\n workspace.allows('read') &&\n workspace.allows('delete') &&\n workspace.allows('create')\n ) {\n tools.workspace_move_file = tool({\n description:\n \"Move a file inside the mounted workspace using the source's current ETag. The operation fails if the destination already exists. If source deletion cannot be confirmed, the destination is retained and the tool reports a conflict; inspect both paths before retrying.\",\n strict: true,\n inputSchema: z\n .object({\n source: logicalPath(\n 'Source file path',\n workspace.limits.maxPathBytes,\n ),\n destination: logicalPath(\n 'Destination file path',\n workspace.limits.maxPathBytes,\n ),\n etag: etagSchema.describe(\n 'Exact ETag of the source returned by the latest workspace stat or read.',\n ),\n })\n .strict(),\n needsApproval: resolveApproval('workspace_move_file', requireApproval),\n execute: ({ source, destination, etag }, { abortSignal }) =>\n executeSafely(abortSignal, async () =>\n serializeFile(\n await workspace.moveFile(source, destination, {\n etag,\n ...operationOptions(abortSignal),\n }),\n ),\n ),\n });\n }\n\n if (\n mutationMode === 'last-write-wins' &&\n workspace.allows('delete') &&\n workspace.allows('write')\n ) {\n tools.workspace_delete_file = tool({\n description:\n 'Unconditionally delete the current file at a path inside the mounted workspace.',\n strict: true,\n inputSchema: z.object({ path: pathSchema }).strict(),\n needsApproval: resolveApproval('workspace_delete_file', requireApproval),\n execute: ({ path }, { abortSignal }) =>\n executeSafely(abortSignal, async () => {\n await workspace.deleteFile(path, {\n mode: 'unconditional',\n ...operationOptions(abortSignal),\n });\n return { deleted: true as const, path };\n }),\n });\n } else if (mutationMode === 'conditional' && workspace.allows('delete')) {\n tools.workspace_delete_file = tool({\n description:\n 'Delete a file inside the mounted workspace using its current ETag.',\n strict: true,\n inputSchema: z\n .object({\n path: pathSchema,\n etag: etagSchema,\n })\n .strict(),\n needsApproval: resolveApproval('workspace_delete_file', requireApproval),\n execute: ({ path, etag }, { abortSignal }) =>\n executeSafely(abortSignal, async () => {\n await workspace.deleteFile(path, {\n etag,\n ...operationOptions(abortSignal),\n });\n return { deleted: true as const, path };\n }),\n });\n }\n\n return tools;\n}\n\nexport function isAiSdkWorkspaceMutationToolName(\n value: string,\n): value is AiSdkWorkspaceMutationToolName {\n return mutationToolNames.has(value as AiSdkWorkspaceMutationToolName);\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { AI_SDK_WORKSPACE_TOOL_NAMES, AiSdkWorkspaceToolError, createAiSdkWorkspaceTools, isAiSdkWorkspaceMutationToolName, type AiSdkWorkspaceApprovalConfig, type AiSdkWorkspaceCreateConflict, type AiSdkWorkspaceCreateConflictMapper, type AiSdkWorkspaceDirectoryResult, type AiSdkWorkspaceEntryResult, type AiSdkWorkspaceFileResult, type AiSdkWorkspaceMutationMode, type AiSdkWorkspaceMutationToolName, type AiSdkWorkspacePageResult, type AiSdkWorkspaceTextFileResult, type AiSdkWorkspaceToolErrorCode, type AiSdkWorkspaceToolErrorOptions, type AiSdkWorkspaceToolName, type CreateAiSdkWorkspaceToolsOptions, } from './ai-sdk-workspace-tools.js';
|
|
2
|
+
export { createAiSdkFileWorkflowTools, createAiSdkCatalogFileTools, createAiSdkWorkingFileTools, createAiSdkCatalogFileEditSchemas, AI_SDK_FILE_WORKFLOW_TOOL_NAMES, AI_SDK_CATALOG_FILE_TOOL_NAMES, type CreateAiSdkFileWorkflowToolsOptions, type CreateAiSdkCatalogFileToolsOptions, } from './ai-sdk-file-workflow-tools.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai-sdk/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,yBAAyB,EACzB,gCAAgC,EAChC,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACvC,KAAK,6BAA6B,EAClC,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,8BAA8B,EACnC,KAAK,wBAAwB,EAC7B,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,KAAK,gCAAgC,GACtC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,iCAAiC,EACjC,+BAA+B,EAC/B,8BAA8B,EAC9B,KAAK,mCAAmC,EACxC,KAAK,kCAAkC,GACxC,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { AI_SDK_WORKSPACE_TOOL_NAMES, AiSdkWorkspaceToolError, createAiSdkWorkspaceTools, isAiSdkWorkspaceMutationToolName, } from './ai-sdk-workspace-tools.js';
|
|
2
|
+
export { createAiSdkFileWorkflowTools, createAiSdkCatalogFileTools, createAiSdkWorkingFileTools, createAiSdkCatalogFileEditSchemas, AI_SDK_FILE_WORKFLOW_TOOL_NAMES, AI_SDK_CATALOG_FILE_TOOL_NAMES, } from './ai-sdk-file-workflow-tools.js';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai-sdk/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,yBAAyB,EACzB,gCAAgC,GAejC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,iCAAiC,EACjC,+BAA+B,EAC/B,8BAA8B,GAG/B,MAAM,iCAAiC,CAAC","sourcesContent":["export {\n AI_SDK_WORKSPACE_TOOL_NAMES,\n AiSdkWorkspaceToolError,\n createAiSdkWorkspaceTools,\n isAiSdkWorkspaceMutationToolName,\n type AiSdkWorkspaceApprovalConfig,\n type AiSdkWorkspaceCreateConflict,\n type AiSdkWorkspaceCreateConflictMapper,\n type AiSdkWorkspaceDirectoryResult,\n type AiSdkWorkspaceEntryResult,\n type AiSdkWorkspaceFileResult,\n type AiSdkWorkspaceMutationMode,\n type AiSdkWorkspaceMutationToolName,\n type AiSdkWorkspacePageResult,\n type AiSdkWorkspaceTextFileResult,\n type AiSdkWorkspaceToolErrorCode,\n type AiSdkWorkspaceToolErrorOptions,\n type AiSdkWorkspaceToolName,\n type CreateAiSdkWorkspaceToolsOptions,\n} from './ai-sdk-workspace-tools.js';\nexport {\n createAiSdkFileWorkflowTools,\n createAiSdkCatalogFileTools,\n createAiSdkWorkingFileTools,\n createAiSdkCatalogFileEditSchemas,\n AI_SDK_FILE_WORKFLOW_TOOL_NAMES,\n AI_SDK_CATALOG_FILE_TOOL_NAMES,\n type CreateAiSdkFileWorkflowToolsOptions,\n type CreateAiSdkCatalogFileToolsOptions,\n} from './ai-sdk-file-workflow-tools.js';\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Browser-safe bounded byte helpers. No Node, framework, provider or AI imports. */
|
|
2
|
+
export declare function sha256StorageBytes(bytes: Uint8Array, options: {
|
|
3
|
+
readonly maxBytes: number;
|
|
4
|
+
readonly signal?: AbortSignal | undefined;
|
|
5
|
+
}): Promise<string>;
|
|
6
|
+
/** Defers only a valid incomplete suffix (at most 3 bytes), never malformed data. */
|
|
7
|
+
export declare function trimStorageUtf8Chunk(bytes: Uint8Array, options: {
|
|
8
|
+
readonly final: boolean;
|
|
9
|
+
}): Uint8Array;
|
|
10
|
+
export declare function encodeStorageBase64(bytes: Uint8Array, options: {
|
|
11
|
+
readonly maxBytes: number;
|
|
12
|
+
}): string;
|
|
13
|
+
export interface StorageChunkIntegrityReceipt {
|
|
14
|
+
readonly offset: number;
|
|
15
|
+
readonly size: number;
|
|
16
|
+
readonly sha256: string;
|
|
17
|
+
}
|
|
18
|
+
/** Verify receipt bounds, ordering and actual local bytes before skipping a chunk. */
|
|
19
|
+
export declare function verifyStorageChunkReceipt(blob: Blob, receipt: StorageChunkIntegrityReceipt, options: {
|
|
20
|
+
readonly offset: number;
|
|
21
|
+
readonly maxBytes: number;
|
|
22
|
+
readonly signal?: AbortSignal | undefined;
|
|
23
|
+
}): Promise<number>;
|
|
24
|
+
/** Bounded UTF-8 validation; filename/MIME classification remains host policy. */
|
|
25
|
+
export declare function isStorageUtf8Blob(blob: Blob, options: {
|
|
26
|
+
readonly chunkBytes: number;
|
|
27
|
+
readonly rejectNul?: boolean;
|
|
28
|
+
readonly signal?: AbortSignal | undefined;
|
|
29
|
+
}): Promise<boolean>;
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bytes/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE;IACP,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C,GACA,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACnC,UAAU,CA2BZ;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrC,MAAM,CAQR;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AACD,sFAAsF;AACtF,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,4BAA4B,EACrC,OAAO,EAAE;IACP,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C,GACA,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAED,kFAAkF;AAClF,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE;IACP,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C,GACA,OAAO,CAAC,OAAO,CAAC,CAoBlB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/** Browser-safe bounded byte helpers. No Node, framework, provider or AI imports. */
|
|
2
|
+
export async function sha256StorageBytes(bytes, options) {
|
|
3
|
+
budget(options.maxBytes);
|
|
4
|
+
options.signal?.throwIfAborted();
|
|
5
|
+
if (bytes.byteLength > options.maxBytes)
|
|
6
|
+
throw new RangeError('Chunk exceeds the byte budget.');
|
|
7
|
+
const hash = await crypto.subtle.digest('SHA-256', bytes.slice());
|
|
8
|
+
options.signal?.throwIfAborted();
|
|
9
|
+
return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
10
|
+
}
|
|
11
|
+
/** Defers only a valid incomplete suffix (at most 3 bytes), never malformed data. */
|
|
12
|
+
export function trimStorageUtf8Chunk(bytes, options) {
|
|
13
|
+
let end = bytes.byteLength;
|
|
14
|
+
if (!options.final && end > 0) {
|
|
15
|
+
let start = end - 1;
|
|
16
|
+
while (start >= 0 && (bytes[start] & 0xc0) === 0x80)
|
|
17
|
+
start--;
|
|
18
|
+
if (start >= 0) {
|
|
19
|
+
const lead = bytes[start];
|
|
20
|
+
const width = lead >= 0xc2 && lead <= 0xdf
|
|
21
|
+
? 2
|
|
22
|
+
: lead >= 0xe0 && lead <= 0xef
|
|
23
|
+
? 3
|
|
24
|
+
: lead >= 0xf0 && lead <= 0xf4
|
|
25
|
+
? 4
|
|
26
|
+
: 1;
|
|
27
|
+
if (end - start < width) {
|
|
28
|
+
new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes, { stream: true });
|
|
29
|
+
end = start;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const result = bytes.subarray(0, end);
|
|
34
|
+
new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(result);
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
export function encodeStorageBase64(bytes, options) {
|
|
38
|
+
budget(options.maxBytes);
|
|
39
|
+
if (bytes.byteLength > options.maxBytes)
|
|
40
|
+
throw new RangeError('Chunk exceeds the byte budget.');
|
|
41
|
+
let text = '';
|
|
42
|
+
for (let offset = 0; offset < bytes.byteLength; offset += 8192)
|
|
43
|
+
text += String.fromCharCode(...bytes.subarray(offset, offset + 8192));
|
|
44
|
+
return btoa(text);
|
|
45
|
+
}
|
|
46
|
+
/** Verify receipt bounds, ordering and actual local bytes before skipping a chunk. */
|
|
47
|
+
export async function verifyStorageChunkReceipt(blob, receipt, options) {
|
|
48
|
+
budget(options.maxBytes);
|
|
49
|
+
options.signal?.throwIfAborted();
|
|
50
|
+
if (!Number.isSafeInteger(options.offset) ||
|
|
51
|
+
options.offset < 0 ||
|
|
52
|
+
receipt.offset !== options.offset ||
|
|
53
|
+
!Number.isSafeInteger(receipt.size) ||
|
|
54
|
+
receipt.size < 1 ||
|
|
55
|
+
receipt.size > options.maxBytes ||
|
|
56
|
+
!Number.isSafeInteger(receipt.offset + receipt.size) ||
|
|
57
|
+
receipt.offset + receipt.size > blob.size ||
|
|
58
|
+
!/^[0-9a-f]{64}$/u.test(receipt.sha256))
|
|
59
|
+
throw new TypeError('Invalid or out-of-order chunk receipt.');
|
|
60
|
+
const bytes = new Uint8Array(await blob
|
|
61
|
+
.slice(receipt.offset, receipt.offset + receipt.size)
|
|
62
|
+
.arrayBuffer());
|
|
63
|
+
if ((await sha256StorageBytes(bytes, options)) !== receipt.sha256)
|
|
64
|
+
throw new Error('The selected bytes differ from the accepted chunk.');
|
|
65
|
+
return receipt.offset + receipt.size;
|
|
66
|
+
}
|
|
67
|
+
/** Bounded UTF-8 validation; filename/MIME classification remains host policy. */
|
|
68
|
+
export async function isStorageUtf8Blob(blob, options) {
|
|
69
|
+
budget(options.chunkBytes);
|
|
70
|
+
const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
71
|
+
try {
|
|
72
|
+
options.signal?.throwIfAborted();
|
|
73
|
+
for (let offset = 0; offset < blob.size; offset += options.chunkBytes) {
|
|
74
|
+
options.signal?.throwIfAborted();
|
|
75
|
+
const bytes = await blob
|
|
76
|
+
.slice(offset, offset + options.chunkBytes)
|
|
77
|
+
.arrayBuffer();
|
|
78
|
+
options.signal?.throwIfAborted();
|
|
79
|
+
const text = decoder.decode(bytes, { stream: true });
|
|
80
|
+
if (options.rejectNul && text.includes('\0'))
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
decoder.decode();
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (options.signal?.aborted)
|
|
88
|
+
throw error;
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function budget(value) {
|
|
93
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
94
|
+
throw new RangeError('Byte budget must be a positive safe integer.');
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bytes/index.ts"],"names":[],"mappings":"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","sourcesContent":["/** Browser-safe bounded byte helpers. No Node, framework, provider or AI imports. */\nexport async function sha256StorageBytes(\n bytes: Uint8Array,\n options: {\n readonly maxBytes: number;\n readonly signal?: AbortSignal | undefined;\n },\n): Promise<string> {\n budget(options.maxBytes);\n options.signal?.throwIfAborted();\n if (bytes.byteLength > options.maxBytes)\n throw new RangeError('Chunk exceeds the byte budget.');\n const hash = await crypto.subtle.digest('SHA-256', bytes.slice());\n options.signal?.throwIfAborted();\n return Array.from(new Uint8Array(hash), (byte) =>\n byte.toString(16).padStart(2, '0'),\n ).join('');\n}\n\n/** Defers only a valid incomplete suffix (at most 3 bytes), never malformed data. */\nexport function trimStorageUtf8Chunk(\n bytes: Uint8Array,\n options: { readonly final: boolean },\n): Uint8Array {\n let end = bytes.byteLength;\n if (!options.final && end > 0) {\n let start = end - 1;\n while (start >= 0 && (bytes[start]! & 0xc0) === 0x80) start--;\n if (start >= 0) {\n const lead = bytes[start]!;\n const width =\n lead >= 0xc2 && lead <= 0xdf\n ? 2\n : lead >= 0xe0 && lead <= 0xef\n ? 3\n : lead >= 0xf0 && lead <= 0xf4\n ? 4\n : 1;\n if (end - start < width) {\n new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(\n bytes,\n { stream: true },\n );\n end = start;\n }\n }\n }\n const result = bytes.subarray(0, end);\n new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(result);\n return result;\n}\n\nexport function encodeStorageBase64(\n bytes: Uint8Array,\n options: { readonly maxBytes: number },\n): string {\n budget(options.maxBytes);\n if (bytes.byteLength > options.maxBytes)\n throw new RangeError('Chunk exceeds the byte budget.');\n let text = '';\n for (let offset = 0; offset < bytes.byteLength; offset += 8192)\n text += String.fromCharCode(...bytes.subarray(offset, offset + 8192));\n return btoa(text);\n}\n\nexport interface StorageChunkIntegrityReceipt {\n readonly offset: number;\n readonly size: number;\n readonly sha256: string;\n}\n/** Verify receipt bounds, ordering and actual local bytes before skipping a chunk. */\nexport async function verifyStorageChunkReceipt(\n blob: Blob,\n receipt: StorageChunkIntegrityReceipt,\n options: {\n readonly offset: number;\n readonly maxBytes: number;\n readonly signal?: AbortSignal | undefined;\n },\n): Promise<number> {\n budget(options.maxBytes);\n options.signal?.throwIfAborted();\n if (\n !Number.isSafeInteger(options.offset) ||\n options.offset < 0 ||\n receipt.offset !== options.offset ||\n !Number.isSafeInteger(receipt.size) ||\n receipt.size < 1 ||\n receipt.size > options.maxBytes ||\n !Number.isSafeInteger(receipt.offset + receipt.size) ||\n receipt.offset + receipt.size > blob.size ||\n !/^[0-9a-f]{64}$/u.test(receipt.sha256)\n )\n throw new TypeError('Invalid or out-of-order chunk receipt.');\n const bytes = new Uint8Array(\n await blob\n .slice(receipt.offset, receipt.offset + receipt.size)\n .arrayBuffer(),\n );\n if ((await sha256StorageBytes(bytes, options)) !== receipt.sha256)\n throw new Error('The selected bytes differ from the accepted chunk.');\n return receipt.offset + receipt.size;\n}\n\n/** Bounded UTF-8 validation; filename/MIME classification remains host policy. */\nexport async function isStorageUtf8Blob(\n blob: Blob,\n options: {\n readonly chunkBytes: number;\n readonly rejectNul?: boolean;\n readonly signal?: AbortSignal | undefined;\n },\n): Promise<boolean> {\n budget(options.chunkBytes);\n const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });\n try {\n options.signal?.throwIfAborted();\n for (let offset = 0; offset < blob.size; offset += options.chunkBytes) {\n options.signal?.throwIfAborted();\n const bytes = await blob\n .slice(offset, offset + options.chunkBytes)\n .arrayBuffer();\n options.signal?.throwIfAborted();\n const text = decoder.decode(bytes, { stream: true });\n if (options.rejectNul && text.includes('\\0')) return false;\n }\n decoder.decode();\n return true;\n } catch (error) {\n if (options.signal?.aborted) throw error;\n return false;\n }\n}\nfunction budget(value: number) {\n if (!Number.isSafeInteger(value) || value < 1)\n throw new RangeError('Byte budget must be a positive safe integer.');\n}\n"]}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -3,4 +3,9 @@ export type { StorageDriver } from '../storage.driver.js';
|
|
|
3
3
|
export { StorageError, StorageErrorCode, isStorageError, normalizeStorageError, type StorageErrorOptions, } from '../storage.error.js';
|
|
4
4
|
export { StorageUploadControl, type StorageResumableToken, type StorageUploadStatus, } from '../storage-upload-control.js';
|
|
5
5
|
export type * from '../storage.types.js';
|
|
6
|
+
export { searchStorageText, applyStorageTextEdit, type StorageTextSearchOptions, type StorageTextSearchResult, type StorageTextEdit, } from './storage-text.js';
|
|
7
|
+
export { collectStorageBytes, storageBytesStream, readStorageTextWindow, type StorageTextWindow, type StorageTextWindowOptions, type StorageRangeReader, } from './storage-streams.js';
|
|
8
|
+
export { StorageStagedContentStore, type StorageStagedBody, type StorageStagedContent, type StorageStagedContentStoreOptions, type StorageStagedReadOptions, type StorageStagedWriteOptions, } from './storage-staged-content.js';
|
|
9
|
+
export { StorageTextEditConflict, storageTextContext, type StorageTextChange, type StorageTextContext, type StorageTextEditDiagnostic, } from './storage-text-edit.js';
|
|
10
|
+
export { editStorageTextStream } from './storage-text-stream-edit.js';
|
|
6
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,KAAK,iBAAiB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,8BAA8B,CAAC;AACtC,mBAAmB,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,KAAK,iBAAiB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,8BAA8B,CAAC;AACtC,mBAAmB,qBAAqB,CAAC;AACzC,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,gCAAgC,EACrC,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export { DEFAULT_BUFFER_LIMIT, StorageClient, } from '../storage.client.js';
|
|
2
2
|
export { StorageError, StorageErrorCode, isStorageError, normalizeStorageError, } from '../storage.error.js';
|
|
3
3
|
export { StorageUploadControl, } from '../storage-upload-control.js';
|
|
4
|
+
export { searchStorageText, applyStorageTextEdit, } from './storage-text.js';
|
|
5
|
+
export { collectStorageBytes, storageBytesStream, readStorageTextWindow, } from './storage-streams.js';
|
|
6
|
+
export { StorageStagedContentStore, } from './storage-staged-content.js';
|
|
7
|
+
export { StorageTextEditConflict, storageTextContext, } from './storage-text-edit.js';
|
|
8
|
+
export { editStorageTextStream } from './storage-text-stream-edit.js';
|
|
4
9
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,aAAa,GAEd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,GAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,GAGrB,MAAM,8BAA8B,CAAC","sourcesContent":["export {\n DEFAULT_BUFFER_LIMIT,\n StorageClient,\n type StorageFileHandle,\n} from '../storage.client.js';\nexport type { StorageDriver } from '../storage.driver.js';\nexport {\n StorageError,\n StorageErrorCode,\n isStorageError,\n normalizeStorageError,\n type StorageErrorOptions,\n} from '../storage.error.js';\nexport {\n StorageUploadControl,\n type StorageResumableToken,\n type StorageUploadStatus,\n} from '../storage-upload-control.js';\nexport type * from '../storage.types.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,aAAa,GAEd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,qBAAqB,GAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,GAGrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,iBAAiB,EACjB,oBAAoB,GAIrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,GAItB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,GAM1B,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,uBAAuB,EACvB,kBAAkB,GAInB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC","sourcesContent":["export {\n DEFAULT_BUFFER_LIMIT,\n StorageClient,\n type StorageFileHandle,\n} from '../storage.client.js';\nexport type { StorageDriver } from '../storage.driver.js';\nexport {\n StorageError,\n StorageErrorCode,\n isStorageError,\n normalizeStorageError,\n type StorageErrorOptions,\n} from '../storage.error.js';\nexport {\n StorageUploadControl,\n type StorageResumableToken,\n type StorageUploadStatus,\n} from '../storage-upload-control.js';\nexport type * from '../storage.types.js';\nexport {\n searchStorageText,\n applyStorageTextEdit,\n type StorageTextSearchOptions,\n type StorageTextSearchResult,\n type StorageTextEdit,\n} from './storage-text.js';\nexport {\n collectStorageBytes,\n storageBytesStream,\n readStorageTextWindow,\n type StorageTextWindow,\n type StorageTextWindowOptions,\n type StorageRangeReader,\n} from './storage-streams.js';\nexport {\n StorageStagedContentStore,\n type StorageStagedBody,\n type StorageStagedContent,\n type StorageStagedContentStoreOptions,\n type StorageStagedReadOptions,\n type StorageStagedWriteOptions,\n} from './storage-staged-content.js';\n\nexport {\n StorageTextEditConflict,\n storageTextContext,\n type StorageTextChange,\n type StorageTextContext,\n type StorageTextEditDiagnostic,\n} from './storage-text-edit.js';\n\nexport { editStorageTextStream } from './storage-text-stream-edit.js';\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { StorageClient } from '../storage.client.js';
|
|
2
|
+
import type { StorageByteRange } from '../storage.types.js';
|
|
3
|
+
export interface StorageStagedBody {
|
|
4
|
+
readonly payloadId: string;
|
|
5
|
+
readonly size: number;
|
|
6
|
+
readonly sha256: string;
|
|
7
|
+
readonly etag: string;
|
|
8
|
+
}
|
|
9
|
+
export interface StorageStagedWriteOptions {
|
|
10
|
+
readonly signal?: AbortSignal | undefined;
|
|
11
|
+
readonly maxBytes?: number | undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface StorageStagedReadOptions {
|
|
14
|
+
readonly signal?: AbortSignal | undefined;
|
|
15
|
+
readonly range?: StorageByteRange | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface StorageStagedContent<Scope> {
|
|
18
|
+
write(scope: Scope, body: ReadableStream<Uint8Array>, options?: StorageStagedWriteOptions): Promise<StorageStagedBody>;
|
|
19
|
+
read(scope: Scope, body: StorageStagedBody, options?: StorageStagedReadOptions): Promise<ReadableStream<Uint8Array>>;
|
|
20
|
+
}
|
|
21
|
+
export interface StorageStagedContentStoreOptions<Scope> {
|
|
22
|
+
readonly client: StorageClient;
|
|
23
|
+
/** Trusted, injective scope mapping; never accept this function from a model. */
|
|
24
|
+
readonly key: (scope: Scope, payloadId: string) => string;
|
|
25
|
+
}
|
|
26
|
+
/** Immutable create-only bodies. Retention eligibility and references remain host-owned. */
|
|
27
|
+
export declare class StorageStagedContentStore<Scope> implements StorageStagedContent<Scope> {
|
|
28
|
+
#private;
|
|
29
|
+
constructor(options: StorageStagedContentStoreOptions<Scope>);
|
|
30
|
+
write(scope: Scope, body: ReadableStream<Uint8Array>, options?: StorageStagedWriteOptions): Promise<StorageStagedBody>;
|
|
31
|
+
/** Trusted callers reserve a fresh identity before preparing detached metadata. */
|
|
32
|
+
writeReserved(scope: Scope, payloadId: string, body: ReadableStream<Uint8Array>, options?: StorageStagedWriteOptions): Promise<StorageStagedBody>;
|
|
33
|
+
read(scope: Scope, body: StorageStagedBody, options?: StorageStagedReadOptions): Promise<ReadableStream<Uint8Array>>;
|
|
34
|
+
/** Host must prove no durable/in-flight reference can be created before removal. */
|
|
35
|
+
remove(scope: Scope, body: StorageStagedBody, options?: {
|
|
36
|
+
readonly signal?: AbortSignal;
|
|
37
|
+
}): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=storage-staged-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-staged-content.d.ts","sourceRoot":"","sources":["../../src/core/storage-staged-content.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AACD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AACD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;CAC/C;AACD,MAAM,WAAW,oBAAoB,CAAC,KAAK;IACzC,KAAK,CACH,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9B,IAAI,CACF,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,iBAAiB,EACvB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;CACxC;AACD,MAAM,WAAW,gCAAgC,CAAC,KAAK;IACrD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3D;AAED,4FAA4F;AAC5F,qBAAa,yBAAyB,CACpC,KAAK,CACL,YAAW,oBAAoB,CAAC,KAAK,CAAC;;IAGtC,YAAY,OAAO,EAAE,gCAAgC,CAAC,KAAK,CAAC,EAG3D;IACK,KAAK,CACT,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,iBAAiB,CAAC,CAE5B;IACD,mFAAmF;IAC7E,aAAa,CACjB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,iBAAiB,CAAC,CAqE5B;IACK,IAAI,CACR,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAgBrC;IACD,oFAAoF;IAC9E,MAAM,CACV,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GAC9C,OAAO,CAAC,IAAI,CAAC,CAMf;CACF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { StorageError } from '../storage.error.js';
|
|
3
|
+
import { storageInteger } from './storage-streams.js';
|
|
4
|
+
/** Immutable create-only bodies. Retention eligibility and references remain host-owned. */
|
|
5
|
+
export class StorageStagedContentStore {
|
|
6
|
+
#client;
|
|
7
|
+
#key;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.#client = options.client;
|
|
10
|
+
this.#key = options.key;
|
|
11
|
+
}
|
|
12
|
+
async write(scope, body, options = {}) {
|
|
13
|
+
return this.writeReserved(scope, randomUUID(), body, options);
|
|
14
|
+
}
|
|
15
|
+
/** Trusted callers reserve a fresh identity before preparing detached metadata. */
|
|
16
|
+
async writeReserved(scope, payloadId, body, options = {}) {
|
|
17
|
+
validatePayloadId(payloadId);
|
|
18
|
+
const { signal } = options;
|
|
19
|
+
const maxBytes = options.maxBytes ?? Number.MAX_SAFE_INTEGER;
|
|
20
|
+
storageInteger(maxBytes, 'maxBytes');
|
|
21
|
+
const capabilities = this.#client.capabilities;
|
|
22
|
+
if (!capabilities.conditionalCreate?.resultEtag ||
|
|
23
|
+
!capabilities.conditionalRead?.etag) {
|
|
24
|
+
await body.cancel().catch(() => { });
|
|
25
|
+
throw new StorageError('Staged content requires native create-only writes and exact ETag reads.', { code: 'NOT_SUPPORTED' });
|
|
26
|
+
}
|
|
27
|
+
const hash = createHash('sha256');
|
|
28
|
+
let size = 0;
|
|
29
|
+
let completed = false;
|
|
30
|
+
const measured = body.pipeThrough(new TransformStream({
|
|
31
|
+
transform(chunk, controller) {
|
|
32
|
+
signal?.throwIfAborted();
|
|
33
|
+
size += chunk.byteLength;
|
|
34
|
+
if (!Number.isSafeInteger(size) || size > maxBytes)
|
|
35
|
+
throw new StorageError('Staged body exceeds its byte budget.', {
|
|
36
|
+
code: 'LIMIT_EXCEEDED',
|
|
37
|
+
});
|
|
38
|
+
hash.update(chunk);
|
|
39
|
+
controller.enqueue(chunk);
|
|
40
|
+
},
|
|
41
|
+
flush() {
|
|
42
|
+
completed = true;
|
|
43
|
+
},
|
|
44
|
+
}), signal === undefined ? {} : { signal });
|
|
45
|
+
try {
|
|
46
|
+
signal?.throwIfAborted();
|
|
47
|
+
const result = await this.#client.uploadConditional(this.#key(scope, payloadId), measured, {
|
|
48
|
+
condition: { type: 'create' },
|
|
49
|
+
contentType: 'application/octet-stream',
|
|
50
|
+
// Unknown-length streams need bounded parts on providers such as S3.
|
|
51
|
+
// Only opt in when the provider can enforce create at completion.
|
|
52
|
+
...(capabilities.conditionalMultipartCompletion?.create === true && {
|
|
53
|
+
multipart: true,
|
|
54
|
+
}),
|
|
55
|
+
retries: 0,
|
|
56
|
+
...(signal === undefined ? {} : { signal }),
|
|
57
|
+
});
|
|
58
|
+
if (!completed || result.size !== size || result.etag === undefined)
|
|
59
|
+
throw new StorageError('Provider did not acknowledge the complete staged body.', { code: 'PROVIDER', applied: true });
|
|
60
|
+
return Object.freeze({
|
|
61
|
+
payloadId,
|
|
62
|
+
size,
|
|
63
|
+
sha256: hash.digest('hex'),
|
|
64
|
+
etag: result.etag,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
await measured.cancel(error).catch(() => { });
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async read(scope, body, options = {}) {
|
|
73
|
+
validateBody(body);
|
|
74
|
+
options.signal?.throwIfAborted();
|
|
75
|
+
if (options.range !== undefined && !this.#client.capabilities.rangeRead)
|
|
76
|
+
throw new StorageError('Provider does not support byte ranges.', {
|
|
77
|
+
code: 'NOT_SUPPORTED',
|
|
78
|
+
});
|
|
79
|
+
const result = await this.#client.downloadConditional(this.#key(scope, body.payloadId), {
|
|
80
|
+
condition: { etag: body.etag },
|
|
81
|
+
...(options.range === undefined ? {} : { range: options.range }),
|
|
82
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
83
|
+
});
|
|
84
|
+
return result.body;
|
|
85
|
+
}
|
|
86
|
+
/** Host must prove no durable/in-flight reference can be created before removal. */
|
|
87
|
+
async remove(scope, body, options = {}) {
|
|
88
|
+
validateBody(body);
|
|
89
|
+
await this.#client.deleteConditional(this.#key(scope, body.payloadId), {
|
|
90
|
+
condition: { etag: body.etag },
|
|
91
|
+
...options,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function validateBody(body) {
|
|
96
|
+
validatePayloadId(body.payloadId);
|
|
97
|
+
if (!/^[0-9a-f]{64}$/u.test(body.sha256))
|
|
98
|
+
throw new StorageError('Invalid staged body receipt.', {
|
|
99
|
+
code: 'INVALID_ARGUMENT',
|
|
100
|
+
});
|
|
101
|
+
storageInteger(body.size, 'size');
|
|
102
|
+
}
|
|
103
|
+
function validatePayloadId(payloadId) {
|
|
104
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(payloadId))
|
|
105
|
+
throw new StorageError('Invalid staged payload identity.', {
|
|
106
|
+
code: 'INVALID_ARGUMENT',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=storage-staged-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-staged-content.js","sourceRoot":"","sources":["../../src/core/storage-staged-content.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport { StorageError } from '../storage.error.js';\nimport type { StorageClient } from '../storage.client.js';\nimport type { StorageByteRange } from '../storage.types.js';\nimport { storageInteger } from './storage-streams.js';\n\nexport interface StorageStagedBody {\n readonly payloadId: string;\n readonly size: number;\n readonly sha256: string;\n readonly etag: string;\n}\nexport interface StorageStagedWriteOptions {\n readonly signal?: AbortSignal | undefined;\n readonly maxBytes?: number | undefined;\n}\nexport interface StorageStagedReadOptions {\n readonly signal?: AbortSignal | undefined;\n readonly range?: StorageByteRange | undefined;\n}\nexport interface StorageStagedContent<Scope> {\n write(\n scope: Scope,\n body: ReadableStream<Uint8Array>,\n options?: StorageStagedWriteOptions,\n ): Promise<StorageStagedBody>;\n read(\n scope: Scope,\n body: StorageStagedBody,\n options?: StorageStagedReadOptions,\n ): Promise<ReadableStream<Uint8Array>>;\n}\nexport interface StorageStagedContentStoreOptions<Scope> {\n readonly client: StorageClient;\n /** Trusted, injective scope mapping; never accept this function from a model. */\n readonly key: (scope: Scope, payloadId: string) => string;\n}\n\n/** Immutable create-only bodies. Retention eligibility and references remain host-owned. */\nexport class StorageStagedContentStore<\n Scope,\n> implements StorageStagedContent<Scope> {\n readonly #client: StorageClient;\n readonly #key: (scope: Scope, payloadId: string) => string;\n constructor(options: StorageStagedContentStoreOptions<Scope>) {\n this.#client = options.client;\n this.#key = options.key;\n }\n async write(\n scope: Scope,\n body: ReadableStream<Uint8Array>,\n options: StorageStagedWriteOptions = {},\n ): Promise<StorageStagedBody> {\n return this.writeReserved(scope, randomUUID(), body, options);\n }\n /** Trusted callers reserve a fresh identity before preparing detached metadata. */\n async writeReserved(\n scope: Scope,\n payloadId: string,\n body: ReadableStream<Uint8Array>,\n options: StorageStagedWriteOptions = {},\n ): Promise<StorageStagedBody> {\n validatePayloadId(payloadId);\n const { signal } = options;\n const maxBytes = options.maxBytes ?? Number.MAX_SAFE_INTEGER;\n storageInteger(maxBytes, 'maxBytes');\n const capabilities = this.#client.capabilities;\n if (\n !capabilities.conditionalCreate?.resultEtag ||\n !capabilities.conditionalRead?.etag\n ) {\n await body.cancel().catch(() => {});\n throw new StorageError(\n 'Staged content requires native create-only writes and exact ETag reads.',\n { code: 'NOT_SUPPORTED' },\n );\n }\n const hash = createHash('sha256');\n let size = 0;\n let completed = false;\n const measured = body.pipeThrough(\n new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n signal?.throwIfAborted();\n size += chunk.byteLength;\n if (!Number.isSafeInteger(size) || size > maxBytes)\n throw new StorageError('Staged body exceeds its byte budget.', {\n code: 'LIMIT_EXCEEDED',\n });\n hash.update(chunk);\n controller.enqueue(chunk);\n },\n flush() {\n completed = true;\n },\n }),\n signal === undefined ? {} : { signal },\n );\n try {\n signal?.throwIfAborted();\n const result = await this.#client.uploadConditional(\n this.#key(scope, payloadId),\n measured,\n {\n condition: { type: 'create' },\n contentType: 'application/octet-stream',\n // Unknown-length streams need bounded parts on providers such as S3.\n // Only opt in when the provider can enforce create at completion.\n ...(capabilities.conditionalMultipartCompletion?.create === true && {\n multipart: true,\n }),\n retries: 0,\n ...(signal === undefined ? {} : { signal }),\n },\n );\n if (!completed || result.size !== size || result.etag === undefined)\n throw new StorageError(\n 'Provider did not acknowledge the complete staged body.',\n { code: 'PROVIDER', applied: true },\n );\n return Object.freeze({\n payloadId,\n size,\n sha256: hash.digest('hex'),\n etag: result.etag,\n });\n } catch (error) {\n await measured.cancel(error).catch(() => {});\n throw error;\n }\n }\n async read(\n scope: Scope,\n body: StorageStagedBody,\n options: StorageStagedReadOptions = {},\n ): Promise<ReadableStream<Uint8Array>> {\n validateBody(body);\n options.signal?.throwIfAborted();\n if (options.range !== undefined && !this.#client.capabilities.rangeRead)\n throw new StorageError('Provider does not support byte ranges.', {\n code: 'NOT_SUPPORTED',\n });\n const result = await this.#client.downloadConditional(\n this.#key(scope, body.payloadId),\n {\n condition: { etag: body.etag },\n ...(options.range === undefined ? {} : { range: options.range }),\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n },\n );\n return result.body;\n }\n /** Host must prove no durable/in-flight reference can be created before removal. */\n async remove(\n scope: Scope,\n body: StorageStagedBody,\n options: { readonly signal?: AbortSignal } = {},\n ): Promise<void> {\n validateBody(body);\n await this.#client.deleteConditional(this.#key(scope, body.payloadId), {\n condition: { etag: body.etag },\n ...options,\n });\n }\n}\nfunction validateBody(body: StorageStagedBody): void {\n validatePayloadId(body.payloadId);\n if (!/^[0-9a-f]{64}$/u.test(body.sha256))\n throw new StorageError('Invalid staged body receipt.', {\n code: 'INVALID_ARGUMENT',\n });\n storageInteger(body.size, 'size');\n}\n\nfunction validatePayloadId(payloadId: string): void {\n if (\n !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(\n payloadId,\n )\n )\n throw new StorageError('Invalid staged payload identity.', {\n code: 'INVALID_ARGUMENT',\n });\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { StorageByteRange } from '../storage.types.js';
|
|
2
|
+
export declare function storageBytesStream(bytes: Uint8Array): ReadableStream<Uint8Array>;
|
|
3
|
+
/** Explicitly buffers no more than maxBytes and cancels the source on failure/abort. */
|
|
4
|
+
export declare function collectStorageBytes(stream: ReadableStream<Uint8Array>, maxBytes: number, signal?: AbortSignal): Promise<Uint8Array>;
|
|
5
|
+
export interface StorageTextWindow {
|
|
6
|
+
readonly content: string | null;
|
|
7
|
+
readonly offset: number;
|
|
8
|
+
readonly nextOffset: number | null;
|
|
9
|
+
}
|
|
10
|
+
export interface StorageTextWindowOptions {
|
|
11
|
+
readonly size: number;
|
|
12
|
+
readonly offset?: number | undefined;
|
|
13
|
+
readonly maxBytes: number;
|
|
14
|
+
readonly signal?: AbortSignal | undefined;
|
|
15
|
+
}
|
|
16
|
+
export type StorageRangeReader = (range: Required<StorageByteRange>, signal?: AbortSignal) => Promise<ReadableStream<Uint8Array>>;
|
|
17
|
+
/** Byte offsets; inclusive provider ranges. Never trims malformed UTF-8 at EOF. */
|
|
18
|
+
export declare function readStorageTextWindow(read: StorageRangeReader, options: StorageTextWindowOptions): Promise<StorageTextWindow>;
|
|
19
|
+
//# sourceMappingURL=storage-streams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-streams.d.ts","sourceRoot":"","sources":["../../src/core/storage-streams.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,UAAU,GAChB,cAAc,CAAC,UAAU,CAAC,CAO5B;AAED,wFAAwF;AACxF,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAkCrB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AACD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C;AACD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACjC,MAAM,CAAC,EAAE,WAAW,KACjB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;AAEzC,mFAAmF;AACnF,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CA0C5B"}
|