@remotedraw/cli 0.1.3 → 0.2.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/LICENSE +21 -0
- package/README.md +56 -1
- package/dist/cli.d.ts +11 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1020 -749
- package/dist/cloud.d.ts +13 -0
- package/dist/cloud.d.ts.map +1 -1
- package/dist/cloud.js +61 -14
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +13 -0
- package/dist/generated/agent-skill.d.ts +2 -0
- package/dist/generated/agent-skill.d.ts.map +1 -0
- package/dist/generated/agent-skill.js +4 -0
- package/dist/i18n.d.ts +74 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +178 -0
- package/dist/index.js +17 -1
- package/dist/locales/catalog.d.ts +21 -0
- package/dist/locales/catalog.d.ts.map +1 -0
- package/dist/locales/catalog.js +1 -0
- package/dist/locales/en.d.ts +420 -0
- package/dist/locales/en.d.ts.map +1 -0
- package/dist/locales/en.js +446 -0
- package/dist/locales/index.d.ts +436 -0
- package/dist/locales/index.d.ts.map +1 -0
- package/dist/locales/index.js +27 -0
- package/dist/locales/nl.d.ts +10 -0
- package/dist/locales/nl.d.ts.map +1 -0
- package/dist/locales/nl.js +438 -0
- package/dist/setup-wizard.d.ts +1 -1
- package/dist/setup-wizard.d.ts.map +1 -1
- package/dist/setup-wizard.js +50 -36
- package/dist/telemetry.d.ts +73 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +145 -0
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +8 -3
- package/package.json +11 -4
package/dist/setup-wizard.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { emitKeypressEvents } from "node:readline";
|
|
3
|
+
import { t } from "./i18n.js";
|
|
3
4
|
export function initialWizardState(definition) {
|
|
4
5
|
return {
|
|
5
6
|
screen: "field",
|
|
@@ -136,7 +137,7 @@ export function wizardSemanticView(state, definition) {
|
|
|
136
137
|
const selectedChoice = choices?.find((choice) => choice.value === state.values[field.key]);
|
|
137
138
|
return {
|
|
138
139
|
screen: state.screen,
|
|
139
|
-
title: "
|
|
140
|
+
title: t("wizard.title.setup"),
|
|
140
141
|
progress: {
|
|
141
142
|
current: state.fieldIndex + 1,
|
|
142
143
|
total: definition.fields.length,
|
|
@@ -153,55 +154,63 @@ export function wizardSemanticView(state, definition) {
|
|
|
153
154
|
controls: field.kind === "text"
|
|
154
155
|
? [
|
|
155
156
|
!state.editedFields.includes(field.key)
|
|
156
|
-
? "
|
|
157
|
-
: "
|
|
158
|
-
"
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
"
|
|
157
|
+
? t("wizard.hint.replaceDefault")
|
|
158
|
+
: t("wizard.hint.edit"),
|
|
159
|
+
t("wizard.control.steps"),
|
|
160
|
+
t("wizard.control.next"),
|
|
161
|
+
t("wizard.control.back"),
|
|
162
|
+
t("wizard.control.quitCtrlC"),
|
|
162
163
|
]
|
|
163
164
|
: [
|
|
164
|
-
"
|
|
165
|
-
...(selectedChoice?.details ? ["
|
|
166
|
-
"
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
"
|
|
165
|
+
t("wizard.control.choose"),
|
|
166
|
+
...(selectedChoice?.details ? [t("wizard.control.docs")] : []),
|
|
167
|
+
t("wizard.control.steps"),
|
|
168
|
+
t("wizard.control.next"),
|
|
169
|
+
t("wizard.control.back"),
|
|
170
|
+
t("wizard.control.quitQ"),
|
|
170
171
|
],
|
|
171
172
|
};
|
|
172
173
|
}
|
|
173
174
|
if (state.screen === "review") {
|
|
174
175
|
return {
|
|
175
176
|
screen: state.screen,
|
|
176
|
-
title: "
|
|
177
|
+
title: t("wizard.title.review"),
|
|
177
178
|
review: definition.review(state.values),
|
|
178
|
-
controls: [
|
|
179
|
+
controls: [
|
|
180
|
+
t("wizard.control.forward"),
|
|
181
|
+
t("wizard.control.backArrow"),
|
|
182
|
+
t("wizard.control.quitQ"),
|
|
183
|
+
],
|
|
179
184
|
};
|
|
180
185
|
}
|
|
181
186
|
if (state.screen === "confirm") {
|
|
182
187
|
return {
|
|
183
188
|
screen: state.screen,
|
|
184
|
-
title: "
|
|
189
|
+
title: t("wizard.title.confirm"),
|
|
185
190
|
review: definition.review(state.values),
|
|
186
191
|
choices: [
|
|
187
|
-
{ value: "no", label: "
|
|
188
|
-
{ value: "yes", label: "
|
|
192
|
+
{ value: "no", label: t("wizard.confirm.no") },
|
|
193
|
+
{ value: "yes", label: t("wizard.confirm.yes") },
|
|
189
194
|
],
|
|
190
195
|
selectedChoice: state.confirmCreate ? "yes" : "no",
|
|
191
|
-
controls: [
|
|
196
|
+
controls: [
|
|
197
|
+
t("wizard.control.choose"),
|
|
198
|
+
t("wizard.control.confirm"),
|
|
199
|
+
t("wizard.control.backArrow"),
|
|
200
|
+
],
|
|
192
201
|
};
|
|
193
202
|
}
|
|
194
203
|
return {
|
|
195
204
|
screen: state.screen,
|
|
196
205
|
title: state.screen === "executing"
|
|
197
|
-
? "
|
|
206
|
+
? t("wizard.title.executing")
|
|
198
207
|
: state.screen === "success"
|
|
199
|
-
? "
|
|
208
|
+
? t("wizard.title.success")
|
|
200
209
|
: state.screen === "error"
|
|
201
|
-
? "
|
|
210
|
+
? t("wizard.title.error")
|
|
202
211
|
: state.screen === "interrupted"
|
|
203
|
-
? "
|
|
204
|
-
: "
|
|
212
|
+
? t("wizard.title.interrupted")
|
|
213
|
+
: t("wizard.title.cancelled"),
|
|
205
214
|
controls: [],
|
|
206
215
|
createdPath: state.createdPath,
|
|
207
216
|
nextCommand: state.nextCommand,
|
|
@@ -305,7 +314,7 @@ export async function runSetupWizard(options) {
|
|
|
305
314
|
catch {
|
|
306
315
|
state = {
|
|
307
316
|
...state,
|
|
308
|
-
error:
|
|
317
|
+
error: t("wizard.docs.openFailed", { url: selectedDetails.docsUrl }),
|
|
309
318
|
};
|
|
310
319
|
}
|
|
311
320
|
continue;
|
|
@@ -378,7 +387,7 @@ function hyperlink(enabled, url, label) {
|
|
|
378
387
|
async function openExternalUrl(url) {
|
|
379
388
|
const parsed = new URL(url);
|
|
380
389
|
if (parsed.protocol !== "https:") {
|
|
381
|
-
throw new Error("
|
|
390
|
+
throw new Error(t("error.httpsDocsOnly"));
|
|
382
391
|
}
|
|
383
392
|
const [command, args] = process.platform === "darwin"
|
|
384
393
|
? ["open", [url]]
|
|
@@ -465,7 +474,7 @@ function renderChoiceDetails(details, terminal) {
|
|
|
465
474
|
rendered: ink(terminal, "muted", line),
|
|
466
475
|
})));
|
|
467
476
|
}
|
|
468
|
-
return cardLines(terminal, "
|
|
477
|
+
return cardLines(terminal, t("wizard.card.help"), rows, width);
|
|
469
478
|
}
|
|
470
479
|
const BANNER_COLORS = ["36", "96", "94", "34"];
|
|
471
480
|
const BANNER_GRADIENT = [
|
|
@@ -779,12 +788,15 @@ function composeWizard(view, terminal, frame, narrow, rule, density) {
|
|
|
779
788
|
const lines = [
|
|
780
789
|
...bannerLines(terminal, frame, density.banner),
|
|
781
790
|
ink(terminal, "muted", density.banner > 0
|
|
782
|
-
? "
|
|
783
|
-
: "
|
|
791
|
+
? t("wizard.tagline.setup")
|
|
792
|
+
: t("wizard.tagline")),
|
|
784
793
|
"",
|
|
785
794
|
];
|
|
786
795
|
if (view.progress) {
|
|
787
|
-
const step =
|
|
796
|
+
const step = t("wizard.progress.step", {
|
|
797
|
+
current: view.progress.current,
|
|
798
|
+
total: view.progress.total,
|
|
799
|
+
});
|
|
788
800
|
lines.push(narrow
|
|
789
801
|
? `${ink(terminal, "muted", step)} · ${strong(terminal, view.title)}`
|
|
790
802
|
: `${stepRail(terminal, view.progress.current, view.progress.total, frame)} ${ink(terminal, "muted", step)} ${strong(terminal, view.title)}`, "");
|
|
@@ -805,7 +817,9 @@ function composeWizard(view, terminal, frame, narrow, rule, density) {
|
|
|
805
817
|
lines.push(...choiceLines(terminal, view.choices, view.selectedChoice, density.hints));
|
|
806
818
|
}
|
|
807
819
|
else {
|
|
808
|
-
lines.push(`${ink(terminal, "accent", "│")} ${ink(terminal, view.valueIsDefault ? "muted" : "glow", view.value || "_", !view.valueIsDefault)}${ink(terminal, "glow", caretGlyph(frame))}${view.valueIsDefault
|
|
820
|
+
lines.push(`${ink(terminal, "accent", "│")} ${ink(terminal, view.valueIsDefault ? "muted" : "glow", view.value || "_", !view.valueIsDefault)}${ink(terminal, "glow", caretGlyph(frame))}${view.valueIsDefault
|
|
821
|
+
? ` ${ink(terminal, "muted", t("wizard.value.default"))}`
|
|
822
|
+
: ""}`);
|
|
809
823
|
if (view.valuePreview) {
|
|
810
824
|
lines.push(`${ink(terminal, "muted", "└")} ${ink(terminal, "muted", view.valuePreview)}`);
|
|
811
825
|
}
|
|
@@ -831,23 +845,23 @@ function composeWizard(view, terminal, frame, narrow, rule, density) {
|
|
|
831
845
|
rendered: `${ink(terminal, "muted", label.padEnd(column))} ${strong(terminal, value)}`,
|
|
832
846
|
}));
|
|
833
847
|
const width = Math.max(24, Math.min(Math.max(20, terminal.columns - 4), rows.reduce((widest, row) => Math.max(widest, row.text.length), 0)));
|
|
834
|
-
lines.push(...cardLines(terminal, "
|
|
848
|
+
lines.push(...cardLines(terminal, t("wizard.card.summary"), rows, width));
|
|
835
849
|
}
|
|
836
850
|
}
|
|
837
851
|
if (view.choices && !view.activeLabel) {
|
|
838
852
|
lines.push(...choiceLines(terminal, view.choices, view.selectedChoice, false));
|
|
839
853
|
}
|
|
840
854
|
if (view.screen === "executing") {
|
|
841
|
-
lines.push(progressBar(terminal, frame, narrow ? 12 : 24), "", ink(terminal, "muted", "
|
|
855
|
+
lines.push(progressBar(terminal, frame, narrow ? 12 : 24), "", ink(terminal, "muted", t("wizard.executing.detail")));
|
|
842
856
|
}
|
|
843
857
|
if (view.createdPath) {
|
|
844
|
-
lines.push(`${ink(terminal, "muted", "
|
|
858
|
+
lines.push(`${ink(terminal, "muted", t("wizard.created.at"))} ${view.createdPath}`);
|
|
845
859
|
}
|
|
846
860
|
if (view.nextCommand) {
|
|
847
|
-
lines.push("", ink(terminal, "muted", "
|
|
861
|
+
lines.push("", ink(terminal, "muted", t("wizard.next.command")), ` ${ink(terminal, "glow", view.nextCommand, true)}`);
|
|
848
862
|
}
|
|
849
863
|
if (view.screen === "success") {
|
|
850
|
-
lines.push("", `${ink(terminal, "success", SPARKLES[frame % SPARKLES.length])} ${ink(terminal, "muted", "
|
|
864
|
+
lines.push("", `${ink(terminal, "success", SPARKLES[frame % SPARKLES.length])} ${ink(terminal, "muted", t("wizard.docs.line"))}`);
|
|
851
865
|
}
|
|
852
866
|
if (view.error) {
|
|
853
867
|
for (const line of view.error.split("\n")) {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crash reporting for the published CLI.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately dependency-free: `remotedraw` is installed globally by customers,
|
|
5
|
+
* and pulling `@sentry/node` into it would add tens of megabytes and a native
|
|
6
|
+
* OpenTelemetry stack to what is otherwise a small package. Sentry's envelope
|
|
7
|
+
* endpoint is a plain POST, so the whole client is the function below.
|
|
8
|
+
*
|
|
9
|
+
* It only ever sends a crash — never a command's arguments, never file
|
|
10
|
+
* contents, never a project name. Anything that could carry a credential is
|
|
11
|
+
* scrubbed before it leaves the machine, and the whole path is opt-out.
|
|
12
|
+
*/
|
|
13
|
+
export type TelemetryEnvironment = {
|
|
14
|
+
env: Record<string, string | undefined>;
|
|
15
|
+
version: string;
|
|
16
|
+
platform: string;
|
|
17
|
+
nodeVersion: string;
|
|
18
|
+
/** Injected by the test suite so no suite run can reach the network. */
|
|
19
|
+
fetch?: typeof fetch | undefined;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Off whenever the user says so, and off in CI, where a crash report has no
|
|
23
|
+
* human behind it and the environment is usually a fresh container.
|
|
24
|
+
* DO_NOT_TRACK is the cross-vendor convention; we honor it without a flag.
|
|
25
|
+
*/
|
|
26
|
+
export declare function telemetryDisabled(env: Record<string, string | undefined>): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Removes the two things a CLI error message realistically leaks: credentials
|
|
29
|
+
* pasted into a flag or read from the environment, and the absolute path of the
|
|
30
|
+
* user's home directory, which usually contains their name.
|
|
31
|
+
*/
|
|
32
|
+
export declare function scrubTelemetryText(value: string, env?: Record<string, string | undefined>): string;
|
|
33
|
+
/**
|
|
34
|
+
* Builds the Sentry event for a crash. Exported so tests can assert exactly
|
|
35
|
+
* what would go over the wire without one leaving the machine.
|
|
36
|
+
*/
|
|
37
|
+
export declare function crashEvent(error: unknown, command: string, environment: TelemetryEnvironment): {
|
|
38
|
+
event_id: string;
|
|
39
|
+
timestamp: number;
|
|
40
|
+
platform: string;
|
|
41
|
+
level: string;
|
|
42
|
+
logger: string;
|
|
43
|
+
release: string;
|
|
44
|
+
environment: string;
|
|
45
|
+
transaction: string;
|
|
46
|
+
tags: {
|
|
47
|
+
command: string;
|
|
48
|
+
cli_version: string;
|
|
49
|
+
node_version: string;
|
|
50
|
+
os: string;
|
|
51
|
+
};
|
|
52
|
+
exception: {
|
|
53
|
+
values: {
|
|
54
|
+
type: string;
|
|
55
|
+
value: string;
|
|
56
|
+
mechanism: {
|
|
57
|
+
handled: boolean;
|
|
58
|
+
};
|
|
59
|
+
}[];
|
|
60
|
+
};
|
|
61
|
+
extra: {
|
|
62
|
+
stack: string;
|
|
63
|
+
} | undefined;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Reports a CLI crash. Never throws, never rejects, and never delays the exit
|
|
67
|
+
* by more than the timeout: a command's outcome must be identical whether or
|
|
68
|
+
* not Sentry is reachable.
|
|
69
|
+
*/
|
|
70
|
+
export declare function reportCliCrash(error: unknown, command: string, environment: TelemetryEnvironment): Promise<void>;
|
|
71
|
+
/** The environment description used by the real CLI process. */
|
|
72
|
+
export declare function nodeTelemetryEnvironment(version: string): TelemetryEnvironment;
|
|
73
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,WAOxE;AAMD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAM,UAW7C;AAmBD;;;GAGG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsClC;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,oBAAoB,iBA+BlC;AAED,gEAAgE;AAChE,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GACd,oBAAoB,CAOtB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crash reporting for the published CLI.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately dependency-free: `remotedraw` is installed globally by customers,
|
|
5
|
+
* and pulling `@sentry/node` into it would add tens of megabytes and a native
|
|
6
|
+
* OpenTelemetry stack to what is otherwise a small package. Sentry's envelope
|
|
7
|
+
* endpoint is a plain POST, so the whole client is the function below.
|
|
8
|
+
*
|
|
9
|
+
* It only ever sends a crash — never a command's arguments, never file
|
|
10
|
+
* contents, never a project name. Anything that could carry a credential is
|
|
11
|
+
* scrubbed before it leaves the machine, and the whole path is opt-out.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Filled in at release time. Sentry DSNs are public by design (browser bundles
|
|
15
|
+
* ship them), so a value here is not a secret; it only identifies the project
|
|
16
|
+
* that receives crashes. Override at runtime with REMOTEDRAW_SENTRY_DSN.
|
|
17
|
+
*/
|
|
18
|
+
const RELEASE_DSN = "";
|
|
19
|
+
/**
|
|
20
|
+
* Off whenever the user says so, and off in CI, where a crash report has no
|
|
21
|
+
* human behind it and the environment is usually a fresh container.
|
|
22
|
+
* DO_NOT_TRACK is the cross-vendor convention; we honor it without a flag.
|
|
23
|
+
*/
|
|
24
|
+
export function telemetryDisabled(env) {
|
|
25
|
+
return Boolean(env.REMOTEDRAW_TELEMETRY_DISABLED?.trim() ||
|
|
26
|
+
env.REMOTEDRAW_CLI_OFFLINE?.trim() ||
|
|
27
|
+
env.DO_NOT_TRACK?.trim() ||
|
|
28
|
+
env.CI?.trim());
|
|
29
|
+
}
|
|
30
|
+
function dsnFor(env) {
|
|
31
|
+
return env.REMOTEDRAW_SENTRY_DSN?.trim() || RELEASE_DSN;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Removes the two things a CLI error message realistically leaks: credentials
|
|
35
|
+
* pasted into a flag or read from the environment, and the absolute path of the
|
|
36
|
+
* user's home directory, which usually contains their name.
|
|
37
|
+
*/
|
|
38
|
+
export function scrubTelemetryText(value, env = {}) {
|
|
39
|
+
let scrubbed = value
|
|
40
|
+
.replace(/\brd_[a-z]+_[A-Za-z0-9_-]+/g, "rd_***")
|
|
41
|
+
.replace(/\bsk_[A-Za-z0-9_-]{8,}/g, "sk_***")
|
|
42
|
+
.replace(/\b(Bearer)\s+\S+/gi, "$1 ***");
|
|
43
|
+
const home = env.HOME ?? env.USERPROFILE;
|
|
44
|
+
if (home && home.length > 1) {
|
|
45
|
+
scrubbed = scrubbed.split(home).join("~");
|
|
46
|
+
}
|
|
47
|
+
return scrubbed;
|
|
48
|
+
}
|
|
49
|
+
function parseDsn(value) {
|
|
50
|
+
try {
|
|
51
|
+
const url = new URL(value);
|
|
52
|
+
const projectId = url.pathname.replace(/^\//, "");
|
|
53
|
+
if (!url.username || !projectId)
|
|
54
|
+
return null;
|
|
55
|
+
return {
|
|
56
|
+
envelopeUrl: `${url.protocol}//${url.host}/api/${projectId}/envelope/`,
|
|
57
|
+
publicKey: url.username,
|
|
58
|
+
dsn: value,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Builds the Sentry event for a crash. Exported so tests can assert exactly
|
|
67
|
+
* what would go over the wire without one leaving the machine.
|
|
68
|
+
*/
|
|
69
|
+
export function crashEvent(error, command, environment) {
|
|
70
|
+
const isError = error instanceof Error;
|
|
71
|
+
const eventId = crypto.randomUUID().replace(/-/g, "");
|
|
72
|
+
return {
|
|
73
|
+
event_id: eventId,
|
|
74
|
+
timestamp: Date.now() / 1000,
|
|
75
|
+
platform: "node",
|
|
76
|
+
level: "error",
|
|
77
|
+
logger: "remotedraw.cli",
|
|
78
|
+
release: `remotedraw-cli@${environment.version}`,
|
|
79
|
+
environment: "production",
|
|
80
|
+
// The command name only; flags and values never leave the machine because
|
|
81
|
+
// any of them may be a key, a path, or a customer's project name.
|
|
82
|
+
transaction: command,
|
|
83
|
+
tags: {
|
|
84
|
+
command,
|
|
85
|
+
cli_version: environment.version,
|
|
86
|
+
node_version: environment.nodeVersion,
|
|
87
|
+
os: environment.platform,
|
|
88
|
+
},
|
|
89
|
+
exception: {
|
|
90
|
+
values: [
|
|
91
|
+
{
|
|
92
|
+
type: isError ? error.name || "Error" : "UnknownError",
|
|
93
|
+
value: scrubTelemetryText(isError ? error.message : String(error), environment.env),
|
|
94
|
+
mechanism: { handled: true },
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
extra: isError && error.stack
|
|
99
|
+
? { stack: scrubTelemetryText(error.stack, environment.env) }
|
|
100
|
+
: undefined,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Reports a CLI crash. Never throws, never rejects, and never delays the exit
|
|
105
|
+
* by more than the timeout: a command's outcome must be identical whether or
|
|
106
|
+
* not Sentry is reachable.
|
|
107
|
+
*/
|
|
108
|
+
export async function reportCliCrash(error, command, environment) {
|
|
109
|
+
if (telemetryDisabled(environment.env))
|
|
110
|
+
return;
|
|
111
|
+
const target = parseDsn(dsnFor(environment.env));
|
|
112
|
+
if (!target)
|
|
113
|
+
return;
|
|
114
|
+
const event = crashEvent(error, command, environment);
|
|
115
|
+
const envelope = [
|
|
116
|
+
JSON.stringify({
|
|
117
|
+
event_id: event.event_id,
|
|
118
|
+
sent_at: new Date().toISOString(),
|
|
119
|
+
dsn: target.dsn,
|
|
120
|
+
}),
|
|
121
|
+
JSON.stringify({ type: "event" }),
|
|
122
|
+
JSON.stringify(event),
|
|
123
|
+
].join("\n");
|
|
124
|
+
const send = environment.fetch ?? fetch;
|
|
125
|
+
try {
|
|
126
|
+
await send(`${target.envelopeUrl}?sentry_key=${target.publicKey}&sentry_version=7`, {
|
|
127
|
+
method: "POST",
|
|
128
|
+
headers: { "Content-Type": "application/x-sentry-envelope" },
|
|
129
|
+
body: envelope,
|
|
130
|
+
signal: AbortSignal.timeout(2000),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// A crash report that fails to send is not itself worth reporting.
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** The environment description used by the real CLI process. */
|
|
138
|
+
export function nodeTelemetryEnvironment(version) {
|
|
139
|
+
return {
|
|
140
|
+
env: process.env,
|
|
141
|
+
version,
|
|
142
|
+
platform: process.platform,
|
|
143
|
+
nodeVersion: process.versions.node,
|
|
144
|
+
};
|
|
145
|
+
}
|
package/dist/update.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGjE,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAOlD,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG;IACzC;;;;OAIG;IACH,YAAY,CAAC,EAAE,CACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,KACX,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,sEAAsE;IACtE,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IACzC,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAiBF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM;;;EAczC;AA2BD,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,cASnD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAoClE;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,UAEzD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,UAErD;AAgDD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,aAAa,EACtB,SAAS,SAAmB,+BAoC7B;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,WAO3E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9C,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CA2BlC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,UAWrE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa;;;;;;GAM7E"}
|
package/dist/update.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { globalConfigPath } from "./cloud.js";
|
|
3
|
+
import { t } from "./i18n.js";
|
|
3
4
|
export const CLI_PACKAGE_NAME = "@remotedraw/cli";
|
|
4
5
|
const DEFAULT_REGISTRY_URL = "https://registry.npmjs.org";
|
|
5
6
|
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -220,10 +221,14 @@ export async function checkForUpdate(runtime, currentVersion, options = {}) {
|
|
|
220
221
|
}
|
|
221
222
|
export function updateNotice(check, method) {
|
|
222
223
|
return [
|
|
223
|
-
|
|
224
|
+
t("notice.update.available", {
|
|
225
|
+
package: CLI_PACKAGE_NAME,
|
|
226
|
+
current: check.current,
|
|
227
|
+
latest: check.latest,
|
|
228
|
+
}),
|
|
224
229
|
method.ephemeral
|
|
225
|
-
?
|
|
226
|
-
:
|
|
230
|
+
? t("notice.update.ephemeral", { package: CLI_PACKAGE_NAME })
|
|
231
|
+
: t("notice.update.install", { command: installMethodDisplay(method) }),
|
|
227
232
|
].join("\n");
|
|
228
233
|
}
|
|
229
234
|
export async function runInstall(runtime, method) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotedraw/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Command-line tools for creating and inspecting RemoteDraw integrations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=20"
|
|
15
15
|
},
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/AxioSOzo/RemoteDraw.git",
|
|
20
|
+
"directory": "packages/cli"
|
|
21
|
+
},
|
|
16
22
|
"bugs": {
|
|
17
23
|
"email": "support@remotedraw.com"
|
|
18
24
|
},
|
|
@@ -27,12 +33,13 @@
|
|
|
27
33
|
"registry": "https://registry.npmjs.org/"
|
|
28
34
|
},
|
|
29
35
|
"scripts": {
|
|
30
|
-
"build": "tsc -p tsconfig.json",
|
|
36
|
+
"build": "bun run generate:skill && tsc -p tsconfig.json",
|
|
31
37
|
"dev": "bun run src/index.ts",
|
|
32
38
|
"test": "bun test tests/*.test.ts",
|
|
33
39
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
34
|
-
"verify:publish": "bun run build && bun run typecheck && bun run test && node dist/index.js --help && node dist/index.js --version",
|
|
35
|
-
"prepack": "bun run verify:publish"
|
|
40
|
+
"verify:publish": "bun run generate:skill && bun run build && bun run typecheck && bun run test && node dist/index.js --help && node dist/index.js --version",
|
|
41
|
+
"prepack": "bun run verify:publish",
|
|
42
|
+
"generate:skill": "bun run scripts/generate-agent-skill.ts"
|
|
36
43
|
},
|
|
37
44
|
"devDependencies": {
|
|
38
45
|
"@types/node": "25.6.2",
|