alink-cli 0.12.5 → 0.12.7

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/bin.mjs CHANGED
@@ -13862,25 +13862,39 @@ const ProviderApprovalDecision = Literals([
13862
13862
  ]);
13863
13863
  const ProviderUserInputAnswers = Record(String$1, Unknown);
13864
13864
  const PROVIDER_SEND_TURN_MAX_INPUT_CHARS = 12e4;
13865
- const PROVIDER_SEND_TURN_MAX_IMAGE_BYTES = 10 * 1024 * 1024;
13866
- const PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS = 14e6;
13865
+ const PROVIDER_SEND_TURN_MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;
13866
+ const PROVIDER_SEND_TURN_MAX_ATTACHMENT_DATA_URL_CHARS = 14e6;
13867
13867
  const ChatAttachmentId = TrimmedNonEmptyString.check(isMaxLength(128), isPattern(/^[a-z0-9_-]+$/i));
13868
13868
  const ChatImageAttachment = Struct({
13869
13869
  type: Literal("image"),
13870
13870
  id: ChatAttachmentId,
13871
13871
  name: TrimmedNonEmptyString.check(isMaxLength(255)),
13872
13872
  mimeType: TrimmedNonEmptyString.check(isMaxLength(100), isPattern(/^image\//i)),
13873
- sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES))
13873
+ sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_ATTACHMENT_BYTES))
13874
13874
  });
13875
13875
  const UploadChatImageAttachment = Struct({
13876
13876
  type: Literal("image"),
13877
13877
  name: TrimmedNonEmptyString.check(isMaxLength(255)),
13878
13878
  mimeType: TrimmedNonEmptyString.check(isMaxLength(100), isPattern(/^image\//i)),
13879
- sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_IMAGE_BYTES)),
13880
- dataUrl: TrimmedNonEmptyString.check(isMaxLength(PROVIDER_SEND_TURN_MAX_IMAGE_DATA_URL_CHARS))
13879
+ sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_ATTACHMENT_BYTES)),
13880
+ dataUrl: TrimmedNonEmptyString.check(isMaxLength(PROVIDER_SEND_TURN_MAX_ATTACHMENT_DATA_URL_CHARS))
13881
13881
  });
13882
- const ChatAttachment = Union([ChatImageAttachment]);
13883
- const UploadChatAttachment = Union([UploadChatImageAttachment]);
13882
+ const ChatFileAttachment = Struct({
13883
+ type: Literal("file"),
13884
+ id: ChatAttachmentId,
13885
+ name: TrimmedNonEmptyString.check(isMaxLength(255)),
13886
+ mimeType: TrimmedNonEmptyString.check(isMaxLength(100)),
13887
+ sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_ATTACHMENT_BYTES))
13888
+ });
13889
+ const UploadChatFileAttachment = Struct({
13890
+ type: Literal("file"),
13891
+ name: TrimmedNonEmptyString.check(isMaxLength(255)),
13892
+ mimeType: TrimmedNonEmptyString.check(isMaxLength(100)),
13893
+ sizeBytes: NonNegativeInt.check(isLessThanOrEqualTo(PROVIDER_SEND_TURN_MAX_ATTACHMENT_BYTES)),
13894
+ dataUrl: TrimmedNonEmptyString.check(isMaxLength(PROVIDER_SEND_TURN_MAX_ATTACHMENT_DATA_URL_CHARS))
13895
+ });
13896
+ const ChatAttachment = Union([ChatImageAttachment, ChatFileAttachment]);
13897
+ const UploadChatAttachment = Union([UploadChatImageAttachment, UploadChatFileAttachment]);
13884
13898
  const ProjectScriptIcon = Literals([
13885
13899
  "play",
13886
13900
  "test",
@@ -22491,7 +22505,7 @@ var AssetWorkspacePathValidationError = class extends TaggedErrorClass()("AssetW
22491
22505
  };
22492
22506
  var AssetPreviewTypeValidationError = class extends TaggedErrorClass()("AssetPreviewTypeValidationError", { resource: AssetResource }) {
22493
22507
  get message() {
22494
- return "Only browser documents and images can be previewed.";
22508
+ return "Only browser documents, media, and images can be previewed.";
22495
22509
  }
22496
22510
  };
22497
22511
  var AssetWorkspaceAssetInspectionError = class extends TaggedErrorClass()("AssetWorkspaceAssetInspectionError", {
@@ -37795,7 +37809,29 @@ function attachmentRelativePath(attachment) {
37795
37809
  });
37796
37810
  return `${attachment.id}${extension}`;
37797
37811
  }
37812
+ case "file": return `${attachment.id}.bin`;
37813
+ }
37814
+ }
37815
+ function prepareProviderAttachmentInput(input) {
37816
+ const imageAttachments = [];
37817
+ const fileLines = [];
37818
+ for (const attachment of input.attachments) {
37819
+ if (attachment.type === "image") {
37820
+ imageAttachments.push(attachment);
37821
+ continue;
37822
+ }
37823
+ const filePath = resolveAttachmentPath({
37824
+ attachmentsDir: input.attachmentsDir,
37825
+ attachment
37826
+ });
37827
+ if (!filePath || !NodeFS.existsSync(filePath)) return null;
37828
+ fileLines.push(`- ${JSON.stringify(attachment.name)}: ${filePath}`);
37798
37829
  }
37830
+ const text = input.text?.trim();
37831
+ return {
37832
+ text: fileLines.length === 0 ? text : [text, ["Attached files (local paths):", ...fileLines].join("\n")].filter(Boolean).join("\n\n"),
37833
+ imageAttachments
37834
+ };
37799
37835
  }
37800
37836
  function resolveAttachmentPath(input) {
37801
37837
  return resolveAttachmentRelativePath({
@@ -37939,7 +37975,6 @@ function collectThreadAttachmentRelativePaths(threadId, messages) {
37939
37975
  if (!threadSegment) return /* @__PURE__ */ new Set();
37940
37976
  const relativePaths = /* @__PURE__ */ new Set();
37941
37977
  for (const message of messages) for (const attachment of message.attachments ?? []) {
37942
- if (attachment.type !== "image") continue;
37943
37978
  const attachmentThreadSegment = parseThreadSegmentFromAttachmentId(attachment.id);
37944
37979
  if (!attachmentThreadSegment || attachmentThreadSegment !== threadSegment) continue;
37945
37980
  relativePaths.add(attachmentRelativePath(attachment));
@@ -45657,11 +45692,6 @@ function parseBigInt(input) {
45657
45692
  }
45658
45693
  //#endregion
45659
45694
  //#region ../t3-shared/src/filePreview.ts
45660
- const WORKSPACE_BROWSER_PREVIEW_EXTENSIONS = [
45661
- ".htm",
45662
- ".html",
45663
- ".pdf"
45664
- ];
45665
45695
  const WORKSPACE_IMAGE_PREVIEW_EXTENSIONS = [
45666
45696
  ".avif",
45667
45697
  ".gif",
@@ -45676,15 +45706,9 @@ function hasPreviewExtension(path, extensions) {
45676
45706
  const pathWithoutQuery = path.split(/[?#]/, 1)[0]?.toLowerCase() ?? "";
45677
45707
  return extensions.some((extension) => pathWithoutQuery.endsWith(extension));
45678
45708
  }
45679
- function isWorkspaceBrowserPreviewPath(path) {
45680
- return hasPreviewExtension(path, WORKSPACE_BROWSER_PREVIEW_EXTENSIONS);
45681
- }
45682
45709
  function isWorkspaceImagePreviewPath(path) {
45683
45710
  return hasPreviewExtension(path, WORKSPACE_IMAGE_PREVIEW_EXTENSIONS);
45684
45711
  }
45685
- function isWorkspacePreviewEntryPath(path) {
45686
- return isWorkspaceBrowserPreviewPath(path) || isWorkspaceImagePreviewPath(path);
45687
- }
45688
45712
  //#endregion
45689
45713
  //#region ../t3-shared/src/projectFavicon.ts
45690
45714
  const PROJECT_FAVICON_FALLBACK_MARKER = "project-favicon-missing";
@@ -45886,17 +45910,6 @@ const SIGNING_SECRET_NAME = "asset-access-signing-key";
45886
45910
  const ASSET_TOKEN_TTL_MS = 3600 * 1e3;
45887
45911
  const PROJECT_FAVICON_TOKEN_BUCKET_MS = 1800 * 1e3;
45888
45912
  const PROJECT_FAVICON_VERSION_PREFIX = "v";
45889
- const PREVIEW_ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
45890
- ...WORKSPACE_BROWSER_PREVIEW_EXTENSIONS,
45891
- ...WORKSPACE_IMAGE_PREVIEW_EXTENSIONS,
45892
- ".css",
45893
- ".js",
45894
- ".mjs",
45895
- ".otf",
45896
- ".ttf",
45897
- ".woff",
45898
- ".woff2"
45899
- ]);
45900
45913
  const AssetClaimsJson = fromJsonString(Union([
45901
45914
  Struct({
45902
45915
  version: Literal(1),
@@ -45970,11 +45983,21 @@ const issueAssetUrl = fn("AssetAccess.issueAssetUrl")(function* (input) {
45970
45983
  switch (input.resource._tag) {
45971
45984
  case "workspace-file": {
45972
45985
  if (!input.workspaceRoot) return yield* new AssetWorkspaceContextNotFoundError({ resource: input.resource });
45973
- const workspaceRoot = yield* workspacePaths.normalizeWorkspaceRoot(input.workspaceRoot).pipe(mapError((cause) => new AssetWorkspaceRootNormalizationError({
45986
+ let workspaceRoot = yield* workspacePaths.normalizeWorkspaceRoot(input.workspaceRoot).pipe(mapError((cause) => new AssetWorkspaceRootNormalizationError({
45974
45987
  resource: input.resource,
45975
45988
  cause
45976
45989
  })));
45977
- const relativePath = path.isAbsolute(input.resource.path) ? path.relative(workspaceRoot, input.resource.path) : input.resource.path;
45990
+ let relativePath = path.isAbsolute(input.resource.path) ? path.relative(workspaceRoot, input.resource.path) : input.resource.path;
45991
+ const isImage = isWorkspaceImagePreviewPath(input.resource.path);
45992
+ if (isImage) {
45993
+ const imagePath = yield* optionOnNotFound(fileSystem.realPath(path.resolve(workspaceRoot, input.resource.path))).pipe(mapError((cause) => new AssetWorkspaceAssetInspectionError({
45994
+ resource: input.resource,
45995
+ cause
45996
+ })));
45997
+ if (isNone(imagePath)) return yield* new AssetWorkspaceAssetNotFoundError({ resource: input.resource });
45998
+ workspaceRoot = path.dirname(imagePath.value);
45999
+ relativePath = path.basename(imagePath.value);
46000
+ }
45978
46001
  const resolved = yield* workspacePaths.resolveRelativePathWithinRoot({
45979
46002
  workspaceRoot,
45980
46003
  relativePath
@@ -45982,7 +46005,6 @@ const issueAssetUrl = fn("AssetAccess.issueAssetUrl")(function* (input) {
45982
46005
  resource: input.resource,
45983
46006
  cause
45984
46007
  })));
45985
- if (!isWorkspacePreviewEntryPath(resolved.relativePath)) return yield* new AssetPreviewTypeValidationError({ resource: input.resource });
45986
46008
  if (!(yield* resolveCanonicalWorkspaceFile({
45987
46009
  workspaceRoot,
45988
46010
  relativePath: resolved.relativePath
@@ -45994,7 +46016,7 @@ const issueAssetUrl = fn("AssetAccess.issueAssetUrl")(function* (input) {
45994
46016
  resource: input.resource,
45995
46017
  cause
45996
46018
  })));
45997
- claims = isWorkspaceImagePreviewPath(resolved.relativePath) ? {
46019
+ claims = isImage ? {
45998
46020
  version: 1,
45999
46021
  kind: "workspace-file-exact",
46000
46022
  workspaceRoot: canonicalWorkspaceRoot,
@@ -46138,7 +46160,7 @@ const resolveAsset = fn("AssetAccess.resolveAsset")(function* (token, relativePa
46138
46160
  } : null;
46139
46161
  }
46140
46162
  const segments = decodedPath.split(/[\\/]/);
46141
- if (decodedPath.length === 0 || decodedPath.includes("\0") || segments.some((segment) => segment === "." || segment === ".." || segment.startsWith(".")) || !PREVIEW_ASSET_EXTENSIONS.has(path.extname(decodedPath).toLowerCase())) return null;
46163
+ if (decodedPath.length === 0 || decodedPath.includes("\0") || segments.some((segment) => segment === "." || segment === ".." || segment.startsWith("."))) return null;
46142
46164
  const joinedRelativePath = claims.baseRelativePath === "." ? decodedPath : path.join(claims.baseRelativePath, decodedPath);
46143
46165
  const workspaceFile = yield* resolveCanonicalWorkspaceFileForRequest({
46144
46166
  workspaceRoot: claims.workspaceRoot,
@@ -51168,13 +51190,13 @@ const normalizeDispatchCommand = (command) => gen(function* () {
51168
51190
  if (canonicalCommand.type !== "thread.turn.start") return canonicalCommand;
51169
51191
  const normalizedAttachments = yield* forEach(canonicalCommand.message.attachments, (attachment) => gen(function* () {
51170
51192
  const parsed = parseBase64DataUrl(attachment.dataUrl);
51171
- if (!parsed || !parsed.mimeType.startsWith("image/")) return yield* new OrchestrationDispatchCommandError({ message: `Invalid image attachment payload for '${attachment.name}'.` });
51193
+ if (!parsed || attachment.type === "image" && !parsed.mimeType.startsWith("image/")) return yield* new OrchestrationDispatchCommandError({ message: `Invalid attachment payload for '${attachment.name}'.` });
51172
51194
  const bytes = Buffer.from(parsed.base64, "base64");
51173
- if (bytes.byteLength === 0 || bytes.byteLength > 10485760) return yield* new OrchestrationDispatchCommandError({ message: `Image attachment '${attachment.name}' is empty or too large.` });
51195
+ if (bytes.byteLength === 0 || bytes.byteLength > 10485760) return yield* new OrchestrationDispatchCommandError({ message: `Attachment '${attachment.name}' is empty or too large.` });
51174
51196
  const attachmentId = createAttachmentId(canonicalCommand.threadId);
51175
51197
  if (!attachmentId) return yield* new OrchestrationDispatchCommandError({ message: "Failed to create a safe attachment id." });
51176
51198
  const persistedAttachment = {
51177
- type: "image",
51199
+ type: attachment.type,
51178
51200
  id: attachmentId,
51179
51201
  name: attachment.name,
51180
51202
  mimeType: parsed.mimeType.toLowerCase(),
@@ -51343,12 +51365,12 @@ function normalizeSearchQuery(input, options) {
51343
51365
  //#endregion
51344
51366
  //#region src/workspace/WorkspaceSearchIndex.ts
51345
51367
  const WORKSPACE_INDEX_MAX_ENTRIES = 25e3;
51346
- const WORKSPACE_INDEX_PAGE_SIZE = 25002;
51347
51368
  const WORKSPACE_INDEX_SCAN_TIMEOUT = "15 seconds";
51348
51369
  const WORKSPACE_INDEX_SCAN_TIMEOUT_MS = 15e3;
51349
51370
  const WORKSPACE_INDEX_IDLE_TTL = "15 minutes";
51350
51371
  const CONTENT_SEARCH_TIME_BUDGET_MS = 250;
51351
51372
  const CONTENT_SEARCH_MAX_MATCHES_PER_FILE = 100;
51373
+ const WORKSPACE_LIST_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
51352
51374
  var WorkspaceSearchIndexCreateFailed = class extends TaggedErrorClass()("WorkspaceSearchIndexCreateFailed", {
51353
51375
  cwd: String$1,
51354
51376
  reason: String$1,
@@ -51401,10 +51423,6 @@ function toPosixPath(input) {
51401
51423
  function trimDirectorySeparator(input) {
51402
51424
  return input.endsWith("/") ? input.slice(0, -1) : input;
51403
51425
  }
51404
- function parentPathOf(input) {
51405
- const separatorIndex = input.lastIndexOf("/");
51406
- return separatorIndex === -1 ? void 0 : input.slice(0, separatorIndex);
51407
- }
51408
51426
  function toProjectEntry(item) {
51409
51427
  const normalizedPath = trimDirectorySeparator(toPosixPath(item.item.relativePath));
51410
51428
  if (!normalizedPath) return null;
@@ -51507,19 +51525,41 @@ function isWholeWordRange(line, range) {
51507
51525
  const rightIsBoundary = range.end >= line.length || !isWord(codePointAt(line, range.end)) || !isWord(codePointBefore(line, range.end));
51508
51526
  return leftIsBoundary && rightIsBoundary;
51509
51527
  }
51510
- function withDirectoryAncestors(entries) {
51511
- const entryByPath = new Map(entries.map((entry) => [entry.path, entry]));
51512
- for (const entry of entries) {
51513
- let parentPath = parentPathOf(entry.path);
51514
- while (parentPath) {
51515
- if (!entryByPath.has(parentPath)) entryByPath.set(parentPath, {
51516
- path: parentPath,
51517
- kind: "directory"
51528
+ async function listWorkspaceFilesystemEntries(cwd, maxEntries) {
51529
+ const entries = [];
51530
+ const directories = [{
51531
+ absolutePath: cwd,
51532
+ relativePath: ""
51533
+ }];
51534
+ let truncated = false;
51535
+ while (directories.length > 0 && entries.length < maxEntries) {
51536
+ const current = directories.pop();
51537
+ if (!current) break;
51538
+ const dirents = await NodeFSP.readdir(current.absolutePath, { withFileTypes: true });
51539
+ dirents.sort((left, right) => left.name.localeCompare(right.name));
51540
+ for (const dirent of dirents) {
51541
+ if (entries.length >= maxEntries) {
51542
+ truncated = true;
51543
+ break;
51544
+ }
51545
+ if (dirent.isDirectory() && WORKSPACE_LIST_SKIPPED_DIRECTORIES.has(dirent.name)) continue;
51546
+ const relativePath = current.relativePath ? `${current.relativePath}/${dirent.name}` : dirent.name;
51547
+ const entry = {
51548
+ path: relativePath,
51549
+ kind: dirent.isDirectory() ? "directory" : "file"
51550
+ };
51551
+ entries.push(entry);
51552
+ if (entry.kind === "directory") directories.push({
51553
+ absolutePath: NodePath.join(current.absolutePath, dirent.name),
51554
+ relativePath
51518
51555
  });
51519
- parentPath = parentPathOf(parentPath);
51520
51556
  }
51521
51557
  }
51522
- return [...entryByPath.values()];
51558
+ if (directories.length > 0) truncated = true;
51559
+ return {
51560
+ entries: entries.toSorted((left, right) => left.path.localeCompare(right.path)),
51561
+ truncated
51562
+ };
51523
51563
  }
51524
51564
  const createFinder = fn("WorkspaceSearchIndex.createFinder")(function* (cwd, variant) {
51525
51565
  const result = yield* try_({
@@ -51609,13 +51649,16 @@ const make$16 = fn("WorkspaceSearchIndex.make")(function* (cwd, variant = "paths
51609
51649
  }));
51610
51650
  });
51611
51651
  const list = fn("WorkspaceSearchIndex.list")(function* () {
51612
- const mapped = mapMixedSearchResult(yield* runSearch("", WORKSPACE_INDEX_PAGE_SIZE, "mixedSearch", () => finder.mixedSearch("", { pageSize: WORKSPACE_INDEX_PAGE_SIZE })), WORKSPACE_INDEX_MAX_ENTRIES);
51613
- const sortedEntries = withDirectoryAncestors(mapped.entries).toSorted((left, right) => left.path.localeCompare(right.path));
51614
- const entries = sortedEntries.slice(0, WORKSPACE_INDEX_MAX_ENTRIES);
51615
- return {
51616
- entries,
51617
- truncated: mapped.truncated || entries.length < sortedEntries.length
51618
- };
51652
+ return yield* tryPromise({
51653
+ try: () => listWorkspaceFilesystemEntries(cwd, WORKSPACE_INDEX_MAX_ENTRIES),
51654
+ catch: (cause) => new WorkspaceSearchIndexSearchFailed({
51655
+ cwd,
51656
+ queryLength: 0,
51657
+ pageSize: WORKSPACE_INDEX_MAX_ENTRIES,
51658
+ reason: "Workspace filesystem listing failed.",
51659
+ cause
51660
+ })
51661
+ });
51619
51662
  });
51620
51663
  const search = fn("WorkspaceSearchIndex.search")(function* (query, limit, kind) {
51621
51664
  const pageSize = Math.max(1, limit + 1);
@@ -59143,14 +59186,23 @@ function buildClaudeImageContentBlock(input) {
59143
59186
  };
59144
59187
  }
59145
59188
  const buildUserMessageEffect = fn("buildUserMessageEffect")(function* (input, dependencies) {
59146
- const text = buildPromptText(input, dependencies.boundInstanceId);
59189
+ const prepared = prepareProviderAttachmentInput({
59190
+ text: buildPromptText(input, dependencies.boundInstanceId),
59191
+ attachmentsDir: dependencies.attachmentsDir,
59192
+ attachments: input.attachments ?? []
59193
+ });
59194
+ if (!prepared) return yield* new ProviderAdapterRequestError({
59195
+ provider: PROVIDER$2,
59196
+ method: "turn/start",
59197
+ detail: "Invalid file attachment id."
59198
+ });
59199
+ const text = prepared.text ?? "";
59147
59200
  const sdkContent = [];
59148
59201
  if (text.length > 0) sdkContent.push({
59149
59202
  type: "text",
59150
59203
  text
59151
59204
  });
59152
- for (const attachment of input.attachments ?? []) {
59153
- if (attachment.type !== "image") continue;
59205
+ for (const attachment of prepared.imageAttachments) {
59154
59206
  if (!SUPPORTED_CLAUDE_IMAGE_MIME_TYPES.has(attachment.mimeType)) return yield* new ProviderAdapterRequestError({
59155
59207
  provider: PROVIDER$2,
59156
59208
  method: "turn/start",
@@ -82608,12 +82660,22 @@ const makeCodexAdapter = fn("makeCodexAdapter")(function* (codexConfig, options)
82608
82660
  };
82609
82661
  });
82610
82662
  const sendTurn = fn("sendTurn")(function* (input) {
82611
- const codexAttachments = yield* forEach(input.attachments ?? [], (attachment) => resolveAttachment(input, attachment), { concurrency: 1 });
82663
+ const prepared = prepareProviderAttachmentInput({
82664
+ text: input.input,
82665
+ attachmentsDir: serverConfig.attachmentsDir,
82666
+ attachments: input.attachments ?? []
82667
+ });
82668
+ if (!prepared) return yield* new ProviderAdapterRequestError({
82669
+ provider: PROVIDER,
82670
+ method: "turn/start",
82671
+ detail: "Invalid file attachment id."
82672
+ });
82673
+ const codexAttachments = yield* forEach(prepared.imageAttachments, (attachment) => resolveAttachment(input, attachment), { concurrency: 1 });
82612
82674
  const session = yield* requireSession(input.threadId);
82613
82675
  const reasoningEffort = input.modelSelection?.instanceId === boundInstanceId ? getModelSelectionStringOptionValue(input.modelSelection, "reasoningEffort") : void 0;
82614
82676
  const serviceTier = input.modelSelection?.instanceId === boundInstanceId ? getCodexServiceTierOptionValue(input.modelSelection) : void 0;
82615
82677
  return yield* session.runtime.sendTurn({
82616
- ...input.input !== void 0 ? { input: input.input } : {},
82678
+ ...prepared.text !== void 0 ? { input: prepared.text } : {},
82617
82679
  ...input.modelSelection?.instanceId === boundInstanceId ? { model: input.modelSelection.model } : {},
82618
82680
  ...reasoningEffort ? { effort: reasoningEffort } : {},
82619
82681
  ...serviceTier ? { serviceTier } : {},
@@ -88885,8 +88947,18 @@ function makeAcpAgentAdapter(descriptor, settings, options) {
88885
88947
  requestedModelId: requestedTurnModelId,
88886
88948
  mapError: (cause) => mapAcpToAdapterError(PROVIDER, input.threadId, "session/set_model", cause)
88887
88949
  });
88888
- const text = input.input?.trim();
88889
- const imagePromptParts = yield* forEach(input.attachments ?? [], (attachment) => gen(function* () {
88950
+ const preparedAttachments = prepareProviderAttachmentInput({
88951
+ text: input.input,
88952
+ attachmentsDir: serverConfig.attachmentsDir,
88953
+ attachments: input.attachments ?? []
88954
+ });
88955
+ if (!preparedAttachments) return yield* new ProviderAdapterRequestError({
88956
+ provider: PROVIDER,
88957
+ method: "session/prompt",
88958
+ detail: "Invalid file attachment id."
88959
+ });
88960
+ const text = preparedAttachments.text;
88961
+ const imagePromptParts = yield* forEach(preparedAttachments.imageAttachments, (attachment) => gen(function* () {
88890
88962
  const attachmentPath = resolveAttachmentPath({
88891
88963
  attachmentsDir: serverConfig.attachmentsDir,
88892
88964
  attachment