@buildinternet/uploads 0.38.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/github.js CHANGED
@@ -57,14 +57,78 @@ export function normalizeGithubCoordinate(value) {
57
57
  * Inverse of `ghKeyPrefix`: parse the PR/issue coordinate back out of a
58
58
  * stable attachment key (`gh/<owner>/<name>/<kind>/<num>/<filename>`), or
59
59
  * undefined for any other key shape.
60
+ *
61
+ * A real GitHub owner CAN be named `private`, so the strict private-repo
62
+ * shape (`gh/private/<32-hex-id>/...`, see `parseGhPrivateKey`) is checked
63
+ * first and rejected here — otherwise a private-prefixed key would
64
+ * misparse as an ordinary key with owner "private". The accepted ambiguity:
65
+ * a key whose second segment is NOT 32-lowercase-hex (e.g.
66
+ * `gh/private/realrepo/pull/5/x.png`) still parses here as owner "private",
67
+ * repo "private/realrepo" — that's an ordinary public-repo key for a repo
68
+ * actually named "private", not a private-prefix key.
60
69
  */
61
70
  export function parseGhKey(key) {
71
+ if (parseGhPrivateKey(key))
72
+ return undefined;
62
73
  const match = /^gh\/([^/]+)\/([^/]+)\/(pull|issues)\/([1-9][0-9]*)\/./.exec(key);
63
74
  if (!match)
64
75
  return undefined;
65
76
  const [, owner, name, kind, num] = match;
66
77
  return { repo: `${owner}/${name}`, kind: kind, num: Number(num) };
67
78
  }
79
+ /** Literal root under which every private-repo attachment key lives. */
80
+ export const GH_PRIVATE_ROOT = "gh/private/";
81
+ /** Strict shape for a randomized private-repo prefix id: 32 lowercase hex chars. */
82
+ const PRIVATE_PREFIX_ID_RE = /^[0-9a-f]{32}$/;
83
+ /**
84
+ * Guard every private-key builder against a malformed `prefixId` — a
85
+ * caller bug here must never silently produce a guessable-ish key.
86
+ */
87
+ function assertPrivatePrefixId(prefixId) {
88
+ if (!PRIVATE_PREFIX_ID_RE.test(prefixId)) {
89
+ throw new Error(`invalid private prefix id: "${prefixId}" must be 32 lowercase hex characters`);
90
+ }
91
+ }
92
+ /**
93
+ * Private-repo key prefix: `gh/private/<32-hex-id>/<kind>/<num>/`.
94
+ * Deliberately omits the repo (unlike `ghKeyPrefix`) — the id is a random,
95
+ * unguessable per-repo prefix rather than an owner/name path, so callers
96
+ * that need the repo back must read `gh.repo` metadata (see
97
+ * `parseGhPrivateKey`, which cannot recover it from the key alone).
98
+ */
99
+ export function ghPrivateKeyPrefix(prefixId, target) {
100
+ assertPrivatePrefixId(prefixId);
101
+ return `${GH_PRIVATE_ROOT}${prefixId}/${target.kind}/${target.num}/`;
102
+ }
103
+ /** Private-repo attachment key: `ghPrivateKeyPrefix` + the sanitized filename. */
104
+ export function ghPrivateAttachmentKey(prefixId, target, filename) {
105
+ return `${ghPrivateKeyPrefix(prefixId, target)}${sanitizeKeySegment(filename)}`;
106
+ }
107
+ /**
108
+ * Private-repo branch-staged key prefix: `gh/private/<32-hex-id>/branch/`.
109
+ * Unlike `ghBranchKeyPrefix`, there is deliberately NO branch-name segment —
110
+ * the branch name itself is not embedded in a private-repo key.
111
+ */
112
+ export function ghPrivateBranchKeyPrefix(prefixId) {
113
+ assertPrivatePrefixId(prefixId);
114
+ return `${GH_PRIVATE_ROOT}${prefixId}/branch/`;
115
+ }
116
+ /** Private-repo branch-staged attachment key: `ghPrivateBranchKeyPrefix` + the sanitized filename. */
117
+ export function ghPrivateBranchAttachmentKey(prefixId, filename) {
118
+ return `${ghPrivateBranchKeyPrefix(prefixId)}${sanitizeKeySegment(filename)}`;
119
+ }
120
+ /**
121
+ * Inverse of `ghPrivateKeyPrefix`: parse the prefix id/kind/number back out
122
+ * of a private-repo attachment key, or undefined for any other key shape.
123
+ * Cannot recover the repo — callers that need it read `gh.repo` metadata.
124
+ */
125
+ export function parseGhPrivateKey(key) {
126
+ const match = /^gh\/private\/([0-9a-f]{32})\/(pull|issues)\/([1-9][0-9]*)\/./.exec(key);
127
+ if (!match)
128
+ return undefined;
129
+ const [, prefixId, kind, num] = match;
130
+ return { prefixId, kind: kind, num: Number(num) };
131
+ }
68
132
  export function ghKeyPrefix(target) {
69
133
  const [owner, name] = target.repo.split("/");
70
134
  return `gh/${sanitizeKeySegment(owner)}/${sanitizeKeySegment(name)}/${target.kind}/${target.num}/`;
@@ -91,6 +155,26 @@ export function ghBranchKeyPrefix(repo, branch) {
91
155
  export function ghBranchAttachmentKey(repo, branch, filename) {
92
156
  return `${ghBranchKeyPrefix(repo, branch)}${sanitizeKeySegment(filename)}`;
93
157
  }
158
+ /**
159
+ * Mode-owning attachment key builder: collapses the
160
+ * `mode === "private" ? ghPrivateAttachmentKey(...) : ghAttachmentKey(...)`
161
+ * ternary repeated across call sites into one place.
162
+ */
163
+ export function ghAttachmentKeyForMode(mode, target, filename) {
164
+ return mode.mode === "private"
165
+ ? ghPrivateAttachmentKey(mode.prefixId, target, filename)
166
+ : ghAttachmentKey(target, filename);
167
+ }
168
+ /**
169
+ * Mode-owning branch-staged attachment key builder. The private form
170
+ * ignores `repo`/`branch` (a private-repo key has no branch-name segment,
171
+ * see `ghPrivateBranchKeyPrefix`) and uses the prefix id instead.
172
+ */
173
+ export function ghBranchAttachmentKeyForMode(mode, repo, branch, filename) {
174
+ return mode.mode === "private"
175
+ ? ghPrivateBranchAttachmentKey(mode.prefixId, filename)
176
+ : ghBranchAttachmentKey(repo, branch, filename);
177
+ }
94
178
  /**
95
179
  * `gh.*` metadata for a branch-staged attach: `gh.repo`, `gh.kind=branch`,
96
180
  * `gh.branch` (lowercased), and `gh.staged-at` (ISO 8601 UTC, no fractional
package/dist/index.d.ts CHANGED
@@ -4,10 +4,10 @@ export { sanitizeKeySegment, sha256Short, deriveRepoFromGit, buildScreenshotKey
4
4
  export { BUILTIN_DESTINATIONS, isBuiltinDestination, keyMatchesDestination, resolveDestinationRoot, resolvePutPrefix, type BuiltinDestinationId, } from "./destinations.js";
5
5
  export { DEFAULT_API_URL, DEFAULT_WORKSPACE, UPLOADS_CONFIG_KEYS, defaultConfigPath, resolveConfigPath, loadConfigFile, loadEnvFile, resolveApiUrl, resolveConfig, describeConfigSources, redactToken, writeConfigKeys, configValuesFromClient, putDefaultsToConfigValues, resolvePutDefaults, mergePutDefaults, workspaceFromToken, workspaceMismatch, type UploadsClientConfig, type ResolvedConfig, type WorkspaceSource, type ConfigValueSource, type ConfigSources, type UploadsConfigKey, type UploadsConfigValues, type PutDefaults, } from "./config.js";
6
6
  export { UploadsError, type UploadsErrorCode } from "./errors.js";
7
- export { createUploadsClient, type UploadsClient, type PutOptions, type ProvenanceInput, type ListOptions, type PutResult, type ListItem, type ListResult, type HeadResult, type DeleteResult, type GalleryItem, type Gallery, type GallerySummary, type GalleryListOptions, type GalleryListResult, type CreateGalleryOptions, type AddGalleryItemOptions, type DeleteGalleryOptions, type HealthResult, type UsageResult, type ReconcileResult, type PurgeExpiredResult, type PurgeExpiredResponse, type FindFilesOptions, type FindFilesItem, type FindFilesResult, type MetadataKeysResult, type MetadataValuesResult, type GetMetadataResult, type PatchMetadataOptions, } from "./client.js";
7
+ export { createUploadsClient, type UploadsClient, type PutOptions, type ProvenanceInput, type ListOptions, type PutResult, type ListItem, type ListResult, type HeadResult, type DeleteResult, type GalleryItem, type Gallery, type GallerySummary, type GalleryListOptions, type GalleryListResult, type CreateGalleryOptions, type AddGalleryItemOptions, type DeleteGalleryOptions, type HealthResult, type UsageResult, type ReconcileResult, type PurgeExpiredResult, type PurgeExpiredResponse, type FindFilesOptions, type FindFilesItem, type FindFilesResult, type MetadataKeysResult, type MetadataValuesResult, type GetMetadataResult, type PatchMetadataOptions, type ResolveGhPrefixOptions, type ResolveGhPrefixResult, } from "./client.js";
8
8
  export { buildCliProvenance } from "./provenance.js";
9
9
  export { META_KEY_RE, META_VALUE_MAX, META_MAX_KEYS, META_MAX_TOTAL_BYTES, validateMetaEntry, parseMetaPair, parseMetaFlags, } from "./metadata.js";
10
- export { ATTACHMENTS_MARKER, attachmentsCommentBody, GH_FALLBACK_AUTHOR_NOTE, ghAttachmentKey, ghKeyPrefix, ghMetadataFromTarget, ghBranchAttachmentKey, ghBranchKeyPrefix, ghMetadataForBranch, isValidRepo, parseRepoFromRemoteUrl, type AttachmentItem, type GhTarget, type GhTargetKind, } from "./github.js";
10
+ export { ATTACHMENTS_MARKER, attachmentsCommentBody, GH_FALLBACK_AUTHOR_NOTE, ghAttachmentKey, ghKeyPrefix, ghMetadataFromTarget, ghBranchAttachmentKey, ghBranchKeyPrefix, ghMetadataForBranch, isValidRepo, parseRepoFromRemoteUrl, GH_PRIVATE_ROOT, ghPrivateKeyPrefix, ghPrivateAttachmentKey, ghPrivateBranchKeyPrefix, ghPrivateBranchAttachmentKey, ghAttachmentKeyForMode, ghBranchAttachmentKeyForMode, parseGhKey, parseGhPrivateKey, type AttachmentItem, type GhTarget, type GhTargetKind, type GhKeyMode, } from "./github.js";
11
11
  export { DEFAULT_OPTIMIZE_MAX_EDGE, DEFAULT_OPTIMIZE_QUALITY, optimizeImageForUpload, rewriteKeyExtension, withImageExtension, type OptimizeImageOptions, type OptimizeImageResult, type OptimizeOutputFormat, } from "./optimize.js";
12
12
  export { FRAME_PRESETS, applyFrame, listFramePresets, resolveFrameId, type FrameFit, type FrameOptions, type FrameResult, } from "./frame.js";
13
13
  export { execRunner, resolveRepo, upsertAttachmentsComment, type CommandRunner, } from "./github-gh.js";
package/dist/index.js CHANGED
@@ -7,7 +7,11 @@ export { UploadsError } from "./errors.js";
7
7
  export { createUploadsClient, } from "./client.js";
8
8
  export { buildCliProvenance } from "./provenance.js";
9
9
  export { META_KEY_RE, META_VALUE_MAX, META_MAX_KEYS, META_MAX_TOTAL_BYTES, validateMetaEntry, parseMetaPair, parseMetaFlags, } from "./metadata.js";
10
- export { ATTACHMENTS_MARKER, attachmentsCommentBody, GH_FALLBACK_AUTHOR_NOTE, ghAttachmentKey, ghKeyPrefix, ghMetadataFromTarget, ghBranchAttachmentKey, ghBranchKeyPrefix, ghMetadataForBranch, isValidRepo, parseRepoFromRemoteUrl, } from "./github.js";
10
+ export { ATTACHMENTS_MARKER, attachmentsCommentBody, GH_FALLBACK_AUTHOR_NOTE, ghAttachmentKey, ghKeyPrefix, ghMetadataFromTarget, ghBranchAttachmentKey, ghBranchKeyPrefix, ghMetadataForBranch, isValidRepo, parseRepoFromRemoteUrl,
11
+ // Private-repo randomized-prefix builders (issue #631) — needed by the
12
+ // hosted MCP (apps/mcp), which builds keys in-process rather than via
13
+ // the CLI's own commands.ts.
14
+ GH_PRIVATE_ROOT, ghPrivateKeyPrefix, ghPrivateAttachmentKey, ghPrivateBranchKeyPrefix, ghPrivateBranchAttachmentKey, ghAttachmentKeyForMode, ghBranchAttachmentKeyForMode, parseGhKey, parseGhPrivateKey, } from "./github.js";
11
15
  export { DEFAULT_OPTIMIZE_MAX_EDGE, DEFAULT_OPTIMIZE_QUALITY, optimizeImageForUpload, rewriteKeyExtension, withImageExtension, } from "./optimize.js";
12
16
  export { FRAME_PRESETS, applyFrame, listFramePresets, resolveFrameId, } from "./frame.js";
13
17
  export { execRunner, resolveRepo, upsertAttachmentsComment, } from "./github-gh.js";
package/dist/keys.d.ts CHANGED
@@ -8,6 +8,12 @@ export declare function sha256Short(bytes: Uint8Array): Promise<string>;
8
8
  * every existing caller.
9
9
  */
10
10
  export declare function deriveRepoFromGit(run?: (cmd: string, args: string[], input?: string) => string): string | undefined;
11
+ /**
12
+ * Full `owner/name` slug (lowercase, matching the `gh.repo` convention) from
13
+ * the cwd's git remote — the derived `repo` metadata value. Unlike
14
+ * `deriveRepoFromGit` above (key-segment name only), this keeps the owner.
15
+ */
16
+ export declare function deriveRepoSlugFromGit(run?: (cmd: string, args: string[], input?: string) => string): string | undefined;
11
17
  export declare function buildScreenshotKey(opts: {
12
18
  filename: string;
13
19
  fileBytes: Uint8Array;
package/dist/keys.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { execSync } from "node:child_process";
2
+ import { parseRepoFromRemoteUrl } from "./github.js";
2
3
  export function sanitizeKeySegment(s) {
3
4
  return s.replace(/[^A-Za-z0-9._-]/g, "-");
4
5
  }
@@ -28,6 +29,22 @@ export function deriveRepoFromGit(run) {
28
29
  return undefined;
29
30
  }
30
31
  }
32
+ /**
33
+ * Full `owner/name` slug (lowercase, matching the `gh.repo` convention) from
34
+ * the cwd's git remote — the derived `repo` metadata value. Unlike
35
+ * `deriveRepoFromGit` above (key-segment name only), this keeps the owner.
36
+ */
37
+ export function deriveRepoSlugFromGit(run) {
38
+ try {
39
+ const url = run
40
+ ? run("git", ["config", "--get", "remote.origin.url"])
41
+ : execSync("git config --get remote.origin.url", { encoding: "utf8" });
42
+ return parseRepoFromRemoteUrl(url)?.toLowerCase();
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
31
48
  export async function buildScreenshotKey(opts) {
32
49
  const dot = opts.filename.lastIndexOf(".");
33
50
  const ext = dot >= 0 ? opts.filename.slice(dot + 1) : "";
package/dist/mcp/tools.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { createUploadsClient } from "../client.js";
2
- import { buildDoctorReport, makeGhTarget, mergeStagingMeta, resolvePutStagingTarget, resolveStaged, syncAttachmentsComment, uploadAttachments, uploadPreparedImage, uploadPuts, } from "../commands.js";
2
+ import { buildDoctorReport, ghListPrefixes, ghMergedList, makeGhTarget, mergeStagingMeta, resolveGhPrefixSafe, resolvePutStagingTarget, resolveStaged, syncAttachmentsComment, uploadAttachments, uploadPreparedImage, uploadPuts, } from "../commands.js";
3
3
  import { resolveFrameId } from "../frame.js";
4
4
  import { resolveConfig, resolvePutDefaults, } from "../config.js";
5
5
  import { resolvePutPrefix } from "../destinations.js";
6
- import { ghBranchAttachmentKey, ghKeyPrefix } from "../github.js";
6
+ import { ghKeyPrefix, ghPrivateKeyPrefix } from "../github.js";
7
7
  import { safeCaptureFacts } from "../capture-facts.js";
8
+ import { deriveRepoSlugFromGit } from "../keys.js";
8
9
  import { validateMetaMap } from "../metadata.js";
9
10
  import { mergeDerivedMeta } from "../metadata-vocab.js";
10
11
  import { execRunner, ghMetadataFromTargetWithTitle, resolveCurrentBranch, resolveCurrentPullRequest, resolveRepo, } from "../github-gh.js";
@@ -430,7 +431,23 @@ export function createUploadsMcpTools(opts) {
430
431
  repoArg: optString(args, "repo") ?? defaults.repo,
431
432
  run,
432
433
  });
433
- const putMetadata = stagingTarget ? mergeStagingMeta(metadata, stagingTarget) : metadata;
434
+ // Derived `repo` metadata (spec: 2026-08-11-screenshots-project-grouping-design.md).
435
+ // Same derivation the CLI does; MCP always derives (no --no-auto), so
436
+ // this is only suppressed by noGit. metadataProp's contract: omitting
437
+ // `metadata` means "leave what's already stored for this key
438
+ // untouched" — an object (even {}) triggers a full replace. So only
439
+ // fold the derived repo into a defined object when the caller already
440
+ // supplied metadata, or branch staging is building one below anyway
441
+ // (mergeStagingMeta always returns a defined object); never
442
+ // synthesize metadata on a bare re-upload just to add repo, or a
443
+ // no-metadata put would silently wipe everything already stored.
444
+ const repoSlug = !noGit ? deriveRepoSlugFromGit(run) : undefined;
445
+ const metadataWithRepo = repoSlug !== undefined && (metadata !== undefined || stagingTarget !== undefined)
446
+ ? mergeDerivedMeta(metadata ?? {}, { repo: repoSlug })
447
+ : metadata;
448
+ const putMetadata = stagingTarget
449
+ ? mergeStagingMeta(metadataWithRepo, stagingTarget)
450
+ : metadataWithRepo;
434
451
  const putShared = {
435
452
  client,
436
453
  ghTarget: target,
@@ -737,9 +754,15 @@ export function createUploadsMcpTools(opts) {
737
754
  // Keep undefined when nothing at all was supplied or derived, so the
738
755
  // "omit to leave stored metadata untouched" contract still holds.
739
756
  const captureDerived = safeCaptureFacts(targetArg, viewport, colorSchemeArg);
740
- const metadataBase = metadata === undefined && Object.keys(captureDerived).length === 0
757
+ // Derived `repo` metadata (spec: 2026-08-11-screenshots-project-grouping-design.md).
758
+ // Same derivation the CLI does, suppressed by noGit.
759
+ const repoSlug = !noGit ? deriveRepoSlugFromGit(run) : undefined;
760
+ const captureDerivedWithRepo = repoSlug
761
+ ? { ...captureDerived, repo: repoSlug }
762
+ : captureDerived;
763
+ const metadataBase = metadata === undefined && Object.keys(captureDerivedWithRepo).length === 0
741
764
  ? undefined
742
- : mergeDerivedMeta(metadata ?? {}, captureDerived);
765
+ : mergeDerivedMeta(metadata ?? {}, captureDerivedWithRepo);
743
766
  // gh.* metadata: explicit pr/issue target wins; staging wins the same
744
767
  // way (matches attach --branch/bare put); otherwise capture-derived +
745
768
  // explicit only.
@@ -778,14 +801,26 @@ export function createUploadsMcpTools(opts) {
778
801
  }
779
802
  throw err;
780
803
  }
781
- const branchKey = stagingTarget
782
- ? ghBranchAttachmentKey(stagingTarget.repo, stagingTarget.branch, captured.filename)
783
- : undefined;
804
+ // Resolved once (issue #631), only now that upload is actually
805
+ // about to happen — never per file (screenshot uploads exactly one).
806
+ const ghPrefix = target
807
+ ? await resolveGhPrefixSafe(client, {
808
+ repo: target.repo,
809
+ target: { kind: target.kind, num: target.num },
810
+ })
811
+ : stagingTarget
812
+ ? await resolveGhPrefixSafe(client, {
813
+ repo: stagingTarget.repo,
814
+ branch: stagingTarget.branch,
815
+ })
816
+ : undefined;
784
817
  const { result, prepared, markdown } = await uploadPreparedImage(client, captured.png, captured.filename, {
785
818
  frame: frameOpts,
786
819
  optimize: optimizeOpts,
787
820
  ghTarget: target,
788
- key: keyArg ?? branchKey,
821
+ ghBranchTarget: stagingTarget,
822
+ ghPrefix,
823
+ key: keyArg,
789
824
  prefix: resolvedPrefix ?? defaults.prefix,
790
825
  repo: optString(args, "repo") ?? defaults.repo,
791
826
  ref: refArg ?? defaults.ref,
@@ -957,16 +992,35 @@ export function createUploadsMcpTools(opts) {
957
992
  const prefixArg = optString(args, "prefix");
958
993
  let prefix = prefixArg ?? (defaults.prefix ? `${defaults.prefix}/` : undefined);
959
994
  const target = ghTargetFromArgs(args, run);
995
+ const { client } = clientFor(args);
996
+ // Also list every active private prefix, if any (issue #631) —
997
+ // mirrors syncAttachmentsComment's gh-fallback gather: a repo's
998
+ // attachment history can be split across the plain shape and
999
+ // MULTIPLE private prefixes, not just the currently-resolved one.
1000
+ // `prefixes` stays undefined outside pr/issue (unchanged behavior);
1001
+ // collapses to `[prefix]` in plain mode, so the single-request path
1002
+ // below is byte-identical to pre-#631.
1003
+ let prefixes;
960
1004
  if (target) {
961
1005
  if (prefixArg)
962
1006
  usage("prefix cannot be combined with pr/issue");
963
1007
  prefix = ghKeyPrefix(target);
1008
+ const ghPrefix = await resolveGhPrefixSafe(client, {
1009
+ repo: target.repo,
1010
+ target: { kind: target.kind, num: target.num },
1011
+ });
1012
+ prefixes = ghListPrefixes(prefix, ghPrefix, (id) => ghPrivateKeyPrefix(id, target));
964
1013
  }
965
1014
  const limit = optPosInt(args, "limit");
966
1015
  const cursor = optString(args, "cursor");
967
- const { client } = clientFor(args);
968
1016
  if (optBool(args, "all")) {
969
- const items = await client.listAll({ prefix, limit, cursor });
1017
+ const items = prefixes && prefixes.length > 1
1018
+ ? await ghMergedList(prefixes, cursor, (p, c) => client.listAll({ prefix: p, limit, cursor: c }))
1019
+ : await client.listAll({ prefix, limit, cursor });
1020
+ return { items, cursor: null };
1021
+ }
1022
+ if (prefixes && prefixes.length > 1) {
1023
+ const items = await ghMergedList(prefixes, cursor, async (p, c) => (await client.list({ prefix: p, limit, cursor: c })).items);
970
1024
  return { items, cursor: null };
971
1025
  }
972
1026
  return client.list({ prefix, limit, cursor });
@@ -1,4 +1,4 @@
1
- export declare const CANONICAL_META_KEYS: readonly ["url", "path", "env", "theme", "viewport", "device", "software", "captured", "state", "app"];
1
+ export declare const CANONICAL_META_KEYS: readonly ["url", "path", "env", "theme", "viewport", "device", "software", "captured", "state", "app", "repo"];
2
2
  export type CanonicalMetaKey = (typeof CANONICAL_META_KEYS)[number];
3
3
  /** Closed enum for `state` — the highest-value hand-supplied search facet. */
4
4
  export declare const META_STATE_VALUES: readonly ["before", "after", "empty", "error", "loading"];
@@ -18,6 +18,7 @@ export const CANONICAL_META_KEYS = [
18
18
  "captured",
19
19
  "state",
20
20
  "app",
21
+ "repo",
21
22
  ];
22
23
  const CANONICAL_KEY_SET = new Set(CANONICAL_META_KEYS);
23
24
  /** Closed enum for `state` — the highest-value hand-supplied search facet. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildinternet/uploads",
3
- "version": "0.38.0",
3
+ "version": "0.41.0",
4
4
  "description": "CLI and client for uploads.sh — workspace-scoped image hosting for GitHub embeds",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -38,7 +38,7 @@
38
38
  "node": ">=22"
39
39
  },
40
40
  "peerDependencies": {
41
- "files-sdk": "^2.1.0"
41
+ "files-sdk": "^2.2.3"
42
42
  },
43
43
  "peerDependenciesMeta": {
44
44
  "files-sdk": {
@@ -48,7 +48,7 @@
48
48
  "devDependencies": {
49
49
  "@types/node": "^26.1.0",
50
50
  "ai": "^6.0.0",
51
- "files-sdk": "^2.1.0",
51
+ "files-sdk": "^2.2.3",
52
52
  "typescript": "^7.0.2",
53
53
  "vitest": "^4.1.10"
54
54
  },