@buildinternet/uploads 0.42.2 → 0.44.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/cli-help.js +1 -1
- package/dist/client.d.ts +36 -1
- package/dist/client.js +15 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/hook.d.ts +6 -2
- package/dist/commands/hook.js +31 -9
- package/dist/commands/screenshot.js +96 -20
- package/dist/commands.d.ts +76 -0
- package/dist/commands.js +326 -78
- package/dist/comment-config.generated.d.ts +6 -0
- package/dist/comment-config.generated.js +27 -1
- package/dist/comment-render.generated.d.ts +4 -1
- package/dist/comment-render.generated.js +15 -2
- package/dist/config-file.d.ts +4 -1
- package/dist/config-file.js +10 -0
- package/dist/mcp/output-schemas.js +24 -1
- package/dist/mcp/tools.js +154 -49
- package/dist/project-context-nudge.d.ts +9 -0
- package/dist/project-context-nudge.js +39 -0
- package/package.json +1 -1
|
@@ -12,6 +12,8 @@ export interface RepoCommentConfig {
|
|
|
12
12
|
linkToFilePage?: boolean;
|
|
13
13
|
note?: string;
|
|
14
14
|
ingestGithubAttachments?: boolean;
|
|
15
|
+
ingestBotAttachments?: boolean;
|
|
16
|
+
adoptLinkedFiles?: boolean;
|
|
15
17
|
}
|
|
16
18
|
export interface WorkspaceCommentDefaults {
|
|
17
19
|
imageWidth?: "full" | number;
|
|
@@ -20,6 +22,8 @@ export interface WorkspaceCommentDefaults {
|
|
|
20
22
|
linkToFilePage?: boolean;
|
|
21
23
|
note?: string;
|
|
22
24
|
ingestGithubAttachments?: boolean;
|
|
25
|
+
ingestBotAttachments?: boolean;
|
|
26
|
+
adoptLinkedFiles?: boolean;
|
|
23
27
|
}
|
|
24
28
|
export interface ResolvedCommentOptions {
|
|
25
29
|
imageWidth: "auto" | "full" | number;
|
|
@@ -29,6 +33,8 @@ export interface ResolvedCommentOptions {
|
|
|
29
33
|
linkToFilePage: boolean;
|
|
30
34
|
note: string | null;
|
|
31
35
|
ingestGithubAttachments: boolean;
|
|
36
|
+
ingestBotAttachments: boolean;
|
|
37
|
+
adoptLinkedFiles: boolean;
|
|
32
38
|
}
|
|
33
39
|
export type OptionSource = "repo" | "workspace" | "auto";
|
|
34
40
|
export declare const AUTO_COMMENT_OPTIONS: ResolvedCommentOptions;
|
|
@@ -12,7 +12,11 @@ export const AUTO_COMMENT_OPTIONS = {
|
|
|
12
12
|
metaState: true,
|
|
13
13
|
linkToFilePage: true,
|
|
14
14
|
note: null,
|
|
15
|
-
ingestGithubAttachments:
|
|
15
|
+
ingestGithubAttachments: true,
|
|
16
|
+
ingestBotAttachments: false,
|
|
17
|
+
// Default ON for bound repos (issue #701) — binding is already an
|
|
18
|
+
// explicit opt-in relationship, same posture as ingestGithubAttachments.
|
|
19
|
+
adoptLinkedFiles: true,
|
|
16
20
|
};
|
|
17
21
|
export const NOTE_MAX_CHARS = 500;
|
|
18
22
|
const WIDTH_MIN = 160;
|
|
@@ -72,6 +76,22 @@ export function parseRepoCommentConfig(text, format) {
|
|
|
72
76
|
else
|
|
73
77
|
warnings.push(`ingestGithubAttachments: expected a boolean; dropped`);
|
|
74
78
|
}
|
|
79
|
+
// ingestBotAttachments: boolean
|
|
80
|
+
if ("ingestBotAttachments" in c) {
|
|
81
|
+
const v = c.ingestBotAttachments;
|
|
82
|
+
if (typeof v === "boolean")
|
|
83
|
+
config.ingestBotAttachments = v;
|
|
84
|
+
else
|
|
85
|
+
warnings.push(`ingestBotAttachments: expected a boolean; dropped`);
|
|
86
|
+
}
|
|
87
|
+
// adoptLinkedFiles: boolean
|
|
88
|
+
if ("adoptLinkedFiles" in c) {
|
|
89
|
+
const v = c.adoptLinkedFiles;
|
|
90
|
+
if (typeof v === "boolean")
|
|
91
|
+
config.adoptLinkedFiles = v;
|
|
92
|
+
else
|
|
93
|
+
warnings.push(`adoptLinkedFiles: expected a boolean; dropped`);
|
|
94
|
+
}
|
|
75
95
|
// meta.path / meta.state: booleans nested under `meta`
|
|
76
96
|
if ("meta" in c) {
|
|
77
97
|
const v = c.meta;
|
|
@@ -127,6 +147,10 @@ export function resolveCommentOptions(repo, ws) {
|
|
|
127
147
|
...(ws?.ingestGithubAttachments !== undefined
|
|
128
148
|
? { ingestGithubAttachments: ws.ingestGithubAttachments }
|
|
129
149
|
: {}),
|
|
150
|
+
...(ws?.ingestBotAttachments !== undefined
|
|
151
|
+
? { ingestBotAttachments: ws.ingestBotAttachments }
|
|
152
|
+
: {}),
|
|
153
|
+
...(ws?.adoptLinkedFiles !== undefined ? { adoptLinkedFiles: ws.adoptLinkedFiles } : {}),
|
|
130
154
|
};
|
|
131
155
|
const options = { ...AUTO_COMMENT_OPTIONS };
|
|
132
156
|
const source = Object.fromEntries(Object.keys(AUTO_COMMENT_OPTIONS).map((k) => [k, "auto"]));
|
|
@@ -138,6 +162,8 @@ export function resolveCommentOptions(repo, ws) {
|
|
|
138
162
|
"metaState",
|
|
139
163
|
"linkToFilePage",
|
|
140
164
|
"ingestGithubAttachments",
|
|
165
|
+
"ingestBotAttachments",
|
|
166
|
+
"adoptLinkedFiles",
|
|
141
167
|
]) {
|
|
142
168
|
if (cfg[key] !== undefined && source[key] === "auto") {
|
|
143
169
|
options[key] = cfg[key];
|
|
@@ -147,5 +147,8 @@ export declare function attachmentImageWidth(filename: string, density?: Attachm
|
|
|
147
147
|
/**
|
|
148
148
|
* Render the one marker-owned GitHub comment. When there are no galleries this
|
|
149
149
|
* intentionally preserves the legacy attachment-only body byte-for-byte.
|
|
150
|
+
*
|
|
151
|
+
* `target` is optional so goldens, the settings preview, and other callers
|
|
152
|
+
* without a PR/issue stay on the generic `--pr <N>` hint.
|
|
150
153
|
*/
|
|
151
|
-
export declare function attachmentsCommentBody(items: AttachmentItem[], galleries?: GalleryCommentItem[], marker?: string, options?: CommentRenderOptions): string;
|
|
154
|
+
export declare function attachmentsCommentBody(items: AttachmentItem[], galleries?: GalleryCommentItem[], marker?: string, options?: CommentRenderOptions, target?: Pick<GhTarget, "kind" | "num">): string;
|
|
@@ -390,11 +390,24 @@ function countInlinableMedia(sorted, maxInlineImages) {
|
|
|
390
390
|
}
|
|
391
391
|
return count;
|
|
392
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Quiet add-media footer. When `target` is a real PR/issue, the command
|
|
395
|
+
* uses that number (`--pr 12` / `--issue 45`) so anyone reading the comment
|
|
396
|
+
* can copy it. Without a target the generic `--pr <N>` placeholder stays.
|
|
397
|
+
*/
|
|
398
|
+
function addMediaFooter(target) {
|
|
399
|
+
const flag = target?.kind === "issues" ? "--issue" : "--pr";
|
|
400
|
+
const n = target && Number.isInteger(target.num) && target.num > 0 ? String(target.num) : "<N>";
|
|
401
|
+
return `<sub>Maintained by <a href="https://uploads.sh">uploads.sh</a> · add media: <code>uploads put <file> ${flag} ${n}</code> · <a href="https://uploads.sh/docs/github-app">docs</a></sub>`;
|
|
402
|
+
}
|
|
393
403
|
/**
|
|
394
404
|
* Render the one marker-owned GitHub comment. When there are no galleries this
|
|
395
405
|
* intentionally preserves the legacy attachment-only body byte-for-byte.
|
|
406
|
+
*
|
|
407
|
+
* `target` is optional so goldens, the settings preview, and other callers
|
|
408
|
+
* without a PR/issue stay on the generic `--pr <N>` hint.
|
|
396
409
|
*/
|
|
397
|
-
export function attachmentsCommentBody(items, galleries = [], marker = ATTACHMENTS_MARKER, options = AUTO_RENDER_OPTIONS) {
|
|
410
|
+
export function attachmentsCommentBody(items, galleries = [], marker = ATTACHMENTS_MARKER, options = AUTO_RENDER_OPTIONS, target) {
|
|
398
411
|
// Non-mutating sort (equivalent to Array#toSorted) — the api worker's
|
|
399
412
|
// tsconfig targets lib ES2022, which predates Array#toSorted (ES2023);
|
|
400
413
|
// packages/uploads/src/github.ts uses toSorted directly.
|
|
@@ -529,6 +542,6 @@ export function attachmentsCommentBody(items, galleries = [], marker = ATTACHMEN
|
|
|
529
542
|
// Footer condensed to a single quiet line — the old two-line explainer
|
|
530
543
|
// ("re-uploading updates everywhere", full add-media flags) repeats on
|
|
531
544
|
// every PR and lost value with each appearance; details live in the docs.
|
|
532
|
-
lines.push(
|
|
545
|
+
lines.push(addMediaFooter(target));
|
|
533
546
|
return lines.join("\n");
|
|
534
547
|
}
|
package/dist/config-file.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { UploadsClientConfig } from "./config.js";
|
|
2
2
|
export declare const UPLOADS_CONFIG_KEYS: readonly ["UPLOADS_API_URL", "UPLOADS_WORKSPACE", "UPLOADS_TOKEN",
|
|
3
3
|
/** Better Auth device-flow session bearer — keeps session.cliVersion fresh. */
|
|
4
|
-
"UPLOADS_SESSION_TOKEN", "UPLOADS_DEFAULT_PREFIX", "UPLOADS_DEFAULT_REPO", "UPLOADS_DEFAULT_REF", "UPLOADS_DEFAULT_WIDTH", "UPLOADS_NO_GIT", "UPLOADS_NO_OPTIMIZE", "UPLOADS_KEEP_EXIF", "UPLOADS_NO_AUTO_META", "UPLOADS_SCREENSHOT_VIA", "UPLOADS_NO_NUDGE"];
|
|
4
|
+
"UPLOADS_SESSION_TOKEN", "UPLOADS_DEFAULT_PREFIX", "UPLOADS_DEFAULT_REPO", "UPLOADS_DEFAULT_REF", "UPLOADS_DEFAULT_WIDTH", "UPLOADS_NO_GIT", "UPLOADS_NO_OPTIMIZE", "UPLOADS_KEEP_EXIF", "UPLOADS_NO_AUTO_META", "UPLOADS_SCREENSHOT_VIA", "UPLOADS_NO_NUDGE", "UPLOADS_NO_AUTO_PR"];
|
|
5
5
|
export type UploadsConfigKey = (typeof UPLOADS_CONFIG_KEYS)[number];
|
|
6
6
|
export type UploadsConfigValues = Partial<Record<UploadsConfigKey, string>>;
|
|
7
7
|
export interface PutDefaults {
|
|
@@ -18,6 +18,9 @@ export interface PutDefaults {
|
|
|
18
18
|
noAutoMeta?: boolean;
|
|
19
19
|
/** When true, `put` never prints the bare-put --pr/attach nudge (issue #393). */
|
|
20
20
|
noNudge?: boolean;
|
|
21
|
+
/** When true, a bare put/screenshot never auto-assumes an unambiguous open
|
|
22
|
+
* PR's context (issue #700) — falls back to the #403/#469 staging default. */
|
|
23
|
+
noAutoPr?: boolean;
|
|
21
24
|
}
|
|
22
25
|
declare const PUT_DEFAULT_KEY_MAP: Record<keyof PutDefaults, UploadsConfigKey>;
|
|
23
26
|
export declare function putDefaultsToConfigValues(defaults: PutDefaults): UploadsConfigValues;
|
package/dist/config-file.js
CHANGED
|
@@ -17,6 +17,7 @@ export const UPLOADS_CONFIG_KEYS = [
|
|
|
17
17
|
"UPLOADS_NO_AUTO_META",
|
|
18
18
|
"UPLOADS_SCREENSHOT_VIA",
|
|
19
19
|
"UPLOADS_NO_NUDGE",
|
|
20
|
+
"UPLOADS_NO_AUTO_PR",
|
|
20
21
|
];
|
|
21
22
|
const PUT_DEFAULT_KEY_MAP = {
|
|
22
23
|
prefix: "UPLOADS_DEFAULT_PREFIX",
|
|
@@ -28,6 +29,7 @@ const PUT_DEFAULT_KEY_MAP = {
|
|
|
28
29
|
keepExif: "UPLOADS_KEEP_EXIF",
|
|
29
30
|
noAutoMeta: "UPLOADS_NO_AUTO_META",
|
|
30
31
|
noNudge: "UPLOADS_NO_NUDGE",
|
|
32
|
+
noAutoPr: "UPLOADS_NO_AUTO_PR",
|
|
31
33
|
};
|
|
32
34
|
function isTruthyConfigFlag(value) {
|
|
33
35
|
if (!value)
|
|
@@ -55,6 +57,8 @@ export function putDefaultsToConfigValues(defaults) {
|
|
|
55
57
|
out.UPLOADS_NO_AUTO_META = "1";
|
|
56
58
|
if (defaults.noNudge)
|
|
57
59
|
out.UPLOADS_NO_NUDGE = "1";
|
|
60
|
+
if (defaults.noAutoPr)
|
|
61
|
+
out.UPLOADS_NO_AUTO_PR = "1";
|
|
58
62
|
return out;
|
|
59
63
|
}
|
|
60
64
|
function parsePutDefaultsFromRaw(raw) {
|
|
@@ -80,6 +84,8 @@ function parsePutDefaultsFromRaw(raw) {
|
|
|
80
84
|
out.noAutoMeta = true;
|
|
81
85
|
if (isTruthyConfigFlag(raw.UPLOADS_NO_NUDGE))
|
|
82
86
|
out.noNudge = true;
|
|
87
|
+
if (isTruthyConfigFlag(raw.UPLOADS_NO_AUTO_PR))
|
|
88
|
+
out.noAutoPr = true;
|
|
83
89
|
return out;
|
|
84
90
|
}
|
|
85
91
|
function parsePutDefaultsFromEnv() {
|
|
@@ -102,6 +108,8 @@ function parsePutDefaultsFromEnv() {
|
|
|
102
108
|
raw.UPLOADS_NO_AUTO_META = process.env.UPLOADS_NO_AUTO_META;
|
|
103
109
|
if (process.env.UPLOADS_NO_NUDGE)
|
|
104
110
|
raw.UPLOADS_NO_NUDGE = process.env.UPLOADS_NO_NUDGE;
|
|
111
|
+
if (process.env.UPLOADS_NO_AUTO_PR)
|
|
112
|
+
raw.UPLOADS_NO_AUTO_PR = process.env.UPLOADS_NO_AUTO_PR;
|
|
105
113
|
return parsePutDefaultsFromRaw(raw);
|
|
106
114
|
}
|
|
107
115
|
/** XDG default shared across buildinternet skills (github-screenshots, uploads, …). */
|
|
@@ -175,6 +183,8 @@ export function mergePutDefaults(...layers) {
|
|
|
175
183
|
out.noAutoMeta = layer.noAutoMeta;
|
|
176
184
|
if (layer.noNudge != null)
|
|
177
185
|
out.noNudge = layer.noNudge;
|
|
186
|
+
if (layer.noAutoPr != null)
|
|
187
|
+
out.noAutoPr = layer.noAutoPr;
|
|
178
188
|
}
|
|
179
189
|
return out;
|
|
180
190
|
}
|
|
@@ -43,6 +43,25 @@ const promoteResultSchema = objectSchema({
|
|
|
43
43
|
]),
|
|
44
44
|
},
|
|
45
45
|
}, ["promoted", "skipped"]);
|
|
46
|
+
/** Hosted `promote` tool's `attached[]` entry (issue #702, `AttachExistingResponse`). */
|
|
47
|
+
const attachExistingResultSchema = objectSchema({
|
|
48
|
+
key: { type: "string" },
|
|
49
|
+
url: nullableString,
|
|
50
|
+
embedUrl: nullableString,
|
|
51
|
+
pageUrl: { type: "string" },
|
|
52
|
+
moved: { type: "boolean" },
|
|
53
|
+
source: objectSchema({ key: { type: "string" } }, ["key"]),
|
|
54
|
+
comment: commentResultSchema,
|
|
55
|
+
}, ["key", "url", "embedUrl", "moved", "source", "comment"]);
|
|
56
|
+
/** Hosted `promote` tool's `attachFailures[]` entry — one per bad `keys` source. */
|
|
57
|
+
const attachFailureSchema = objectSchema({
|
|
58
|
+
key: { type: "string" },
|
|
59
|
+
error: objectSchema({
|
|
60
|
+
message: { type: "string" },
|
|
61
|
+
code: { type: "string" },
|
|
62
|
+
status: { type: "number" },
|
|
63
|
+
}, ["message"]),
|
|
64
|
+
}, ["key", "error"]);
|
|
46
65
|
const putObjectFields = {
|
|
47
66
|
key: { type: "string" },
|
|
48
67
|
url: nullableString,
|
|
@@ -209,10 +228,14 @@ export const healthResultSchema = objectSchema({
|
|
|
209
228
|
apiUrl: { type: "string" },
|
|
210
229
|
});
|
|
211
230
|
export const promoteToolResultSchema = objectSchema({
|
|
231
|
+
// `promotion` is optional (issue #702): a `keys`-only call (no `branch`)
|
|
232
|
+
// never runs the branch sweep, so there's nothing to report under it.
|
|
212
233
|
promotion: promoteResultSchema,
|
|
234
|
+
attached: { type: "array", items: attachExistingResultSchema },
|
|
235
|
+
attachFailures: { type: "array", items: attachFailureSchema },
|
|
213
236
|
comment: commentResultSchema,
|
|
214
237
|
commentError: { type: "string" },
|
|
215
|
-
}
|
|
238
|
+
});
|
|
216
239
|
const galleryItemSchema = objectSchema({
|
|
217
240
|
id: { type: "string" },
|
|
218
241
|
objectKey: { type: "string" },
|