@cursor/july 0.1.3 → 0.1.4
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/agent-serve.d.ts +1 -1
- package/dist/bin/agent-serve.js +40 -16
- package/dist/channels/slack/log.d.ts +1 -1
- package/dist/channels/slack/log.d.ts.map +1 -1
- package/dist/channels/slack/log.js +4 -5
- package/dist/channels/slack/setup.js +1 -1
- package/dist/channels/slack/socket-mode.d.ts.map +1 -1
- package/dist/channels/slack/socket-mode.js +10 -9
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.BR0RbIdx.js → app.DF-Yx4OP.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.0XrheBv2.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.qjsVTneI.js → VPLocalSearchBox.DSeJSudL.js} +1 -1
- package/dist/docs/assets/chunks/{theme.2Kg8jIp_.js → theme.DZVLTXOC.js} +2 -2
- package/dist/docs/assets/{index.md.m81y7TY7.js → index.md.Cylk70gg.js} +1 -1
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +5 -5
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +3 -3
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/internal/ab-collector.js +3 -3
- package/dist/internal/ab-fold.js +1 -1
- package/dist/internal/cli-ax.d.ts +13 -5
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +41 -15
- package/dist/internal/cli-github.js +13 -13
- package/dist/internal/cursor/account-mcp.js +3 -3
- package/dist/internal/cursor/backend-client.js +1 -1
- package/dist/internal/cursor/credentials.d.ts +5 -3
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +9 -6
- package/dist/internal/cursor/github-credentials.js +3 -3
- package/dist/internal/cursor-event-relay.js +1 -1
- package/dist/internal/cursor-relay-core.d.ts +1 -1
- package/dist/internal/cursor-relay-core.d.ts.map +1 -1
- package/dist/internal/cursor-relay-core.js +2 -1
- package/dist/internal/cursor-slack-relay.js +1 -1
- package/dist/internal/distribution.d.ts +7 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +7 -0
- package/dist/internal/docs-site.js +3 -3
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +8 -8
- package/dist/internal/github-fanout.js +2 -2
- package/dist/internal/host-platforms.js +5 -5
- package/dist/internal/mcp-endpoint.d.ts.map +1 -1
- package/dist/internal/mcp-endpoint.js +1 -1
- package/dist/internal/playground/toolchain.js +6 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +11 -11
- package/dist/internal/resolve-prod-target.d.ts +2 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -1
- package/dist/internal/resolve-prod-target.js +44 -21
- package/dist/internal/resolved-connections.js +5 -5
- package/dist/internal/schedule-runner.js +1 -1
- package/dist/internal/server.js +14 -14
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +13 -13
- package/dist/internal/sessions-client.d.ts +13 -0
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +25 -0
- package/dist/internal/storage-coordinator.js +6 -6
- package/dist/internal/update-check.d.ts +93 -0
- package/dist/internal/update-check.d.ts.map +1 -0
- package/dist/internal/update-check.js +431 -0
- package/dist/playground/assets/{index-D-vo2lV_.css → index-Ct_Usdm8.css} +1 -1
- package/dist/playground/assets/index-Dsyb-Vaj.js +319 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +0 -1
- package/package.json +2 -1
- package/skills/setup-slack/SKILL.md +1 -1
- package/src/bin/agent-serve.ts +42 -16
- package/src/channels/slack/log.ts +5 -5
- package/src/channels/slack/setup.ts +1 -1
- package/src/channels/slack/socket-mode.ts +11 -9
- package/src/internal/ab-collector.ts +3 -3
- package/src/internal/ab-fold.ts +1 -1
- package/src/internal/cli-ax.ts +55 -16
- package/src/internal/cli-github.ts +13 -15
- package/src/internal/cursor/account-mcp.ts +3 -3
- package/src/internal/cursor/backend-client.ts +1 -1
- package/src/internal/cursor/credentials.ts +12 -7
- package/src/internal/cursor/github-credentials.ts +3 -3
- package/src/internal/cursor-event-relay.ts +1 -1
- package/src/internal/cursor-relay-core.ts +4 -2
- package/src/internal/cursor-slack-relay.ts +1 -1
- package/src/internal/distribution.ts +8 -0
- package/src/internal/docs-site.ts +3 -3
- package/src/internal/eval-run-store.ts +8 -10
- package/src/internal/github-fanout.ts +2 -2
- package/src/internal/host-platforms.ts +5 -5
- package/src/internal/mcp-endpoint.ts +1 -3
- package/src/internal/playground/toolchain.ts +6 -6
- package/src/internal/reminder-runner.ts +11 -17
- package/src/internal/resolve-prod-target.ts +55 -23
- package/src/internal/resolved-connections.ts +5 -5
- package/src/internal/schedule-runner.ts +1 -1
- package/src/internal/server.ts +14 -14
- package/src/internal/session-engine.ts +13 -15
- package/src/internal/sessions-client.ts +34 -0
- package/src/internal/storage-coordinator.ts +6 -6
- package/src/internal/update-check.ts +552 -0
- package/src/types.ts +3 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DtIOQzGj.js +0 -1
- package/dist/playground/assets/index-x60b9q2j.js +0 -312
- /package/dist/docs/assets/{index.md.m81y7TY7.lean.js → index.md.Cylk70gg.lean.js} +0 -0
|
@@ -252,7 +252,7 @@ export class StorageCoordinator {
|
|
|
252
252
|
// Index entry without its record (e.g. the record write was shed
|
|
253
253
|
// under at-most-once). The session is unrecoverable; treat as a miss
|
|
254
254
|
// so the conversation can continue rather than failing forever.
|
|
255
|
-
this.logger(`[
|
|
255
|
+
this.logger(`[agentkit] storage continuation entry points at missing session ${sessionId}; treating as a miss`);
|
|
256
256
|
return undefined;
|
|
257
257
|
}
|
|
258
258
|
// The sink must answer for the exact key it was asked about — a
|
|
@@ -383,7 +383,7 @@ export class StorageCoordinator {
|
|
|
383
383
|
return value == null ? undefined : value;
|
|
384
384
|
}
|
|
385
385
|
catch (error) {
|
|
386
|
-
this.logger(`[
|
|
386
|
+
this.logger(`[agentkit] storage get(ab-snapshot) failed: ${describeError(error)}`);
|
|
387
387
|
return undefined;
|
|
388
388
|
}
|
|
389
389
|
});
|
|
@@ -415,7 +415,7 @@ export class StorageCoordinator {
|
|
|
415
415
|
]);
|
|
416
416
|
clearTimeout(timer);
|
|
417
417
|
if (!drained) {
|
|
418
|
-
this.logger(`[
|
|
418
|
+
this.logger(`[agentkit] storage shutdown drain timed out after ${CLOSE_DRAIN_TIMEOUT_MS}ms with ${this.pending} write(s) undelivered`);
|
|
419
419
|
}
|
|
420
420
|
});
|
|
421
421
|
}
|
|
@@ -455,7 +455,7 @@ export class StorageCoordinator {
|
|
|
455
455
|
return Array.isArray(entries) ? entries : [];
|
|
456
456
|
}
|
|
457
457
|
catch (error) {
|
|
458
|
-
this.logger(`[
|
|
458
|
+
this.logger(`[agentkit] storage list(${prefix}) failed: ${describeError(error)}`);
|
|
459
459
|
return [];
|
|
460
460
|
}
|
|
461
461
|
});
|
|
@@ -467,7 +467,7 @@ export class StorageCoordinator {
|
|
|
467
467
|
if (this.pending + ops.length > MAX_PENDING_OPS) {
|
|
468
468
|
this.dropped += ops.length;
|
|
469
469
|
if (this.dropped <= ops.length || this.dropped % 1000 < ops.length) {
|
|
470
|
-
this.logger(`[
|
|
470
|
+
this.logger(`[agentkit] storage queue full (${MAX_PENDING_OPS} pending writes); dropped ${this.dropped} write(s) so far — the sink is too slow for the traffic`);
|
|
471
471
|
}
|
|
472
472
|
return;
|
|
473
473
|
}
|
|
@@ -485,7 +485,7 @@ export class StorageCoordinator {
|
|
|
485
485
|
}
|
|
486
486
|
}
|
|
487
487
|
catch (error) {
|
|
488
|
-
this.logger(`[
|
|
488
|
+
this.logger(`[agentkit] storage ${op.op}(${op.key}) failed: ${describeError(error)}`);
|
|
489
489
|
}
|
|
490
490
|
finally {
|
|
491
491
|
this.pending -= 1;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outdated-version warning + `agentkit update`.
|
|
3
|
+
*
|
|
4
|
+
* Every CLI run of a published install compares its own version against the
|
|
5
|
+
* npm registry's `latest` dist-tag and warns on stderr when behind. The
|
|
6
|
+
* registry lookup is cached under the config dir
|
|
7
|
+
* (`~/.config/agent-serve/update-check.json`) so most runs never touch the
|
|
8
|
+
* network; a stale cache refreshes inline under a short timeout, and any
|
|
9
|
+
* network failure is silent (the warning is best-effort, never a blocker).
|
|
10
|
+
*
|
|
11
|
+
* `agentkit update` re-runs the lookup fresh, figures out how this copy was
|
|
12
|
+
* installed (global npm/pnpm/yarn/bun, or a project dependency), and runs the
|
|
13
|
+
* matching install command.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
/**
|
|
17
|
+
* Semver-style ordering: negative when `a < b`, 0 when equal, positive when
|
|
18
|
+
* `a > b`. Unparseable versions compare equal (never warn on garbage).
|
|
19
|
+
*/
|
|
20
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
21
|
+
/**
|
|
22
|
+
* Latest published version of the package, from the registry's `latest`
|
|
23
|
+
* dist-tag. Returns undefined on any failure (offline, 404 pre-publish, …).
|
|
24
|
+
*/
|
|
25
|
+
export declare function fetchLatestPublishedVersion(options?: {
|
|
26
|
+
fetchImpl?: typeof fetch;
|
|
27
|
+
timeoutMs?: number;
|
|
28
|
+
packageName?: string;
|
|
29
|
+
}): Promise<string | undefined>;
|
|
30
|
+
declare const cacheSchema: z.ZodObject<{
|
|
31
|
+
checkedAt: z.ZodNumber;
|
|
32
|
+
latestVersion: z.ZodOptional<z.ZodString>;
|
|
33
|
+
}, "strip">;
|
|
34
|
+
export type UpdateCheckCache = z.infer<typeof cacheSchema>;
|
|
35
|
+
export declare function updateCheckCachePath(configDir?: string): string;
|
|
36
|
+
export declare function readUpdateCheckCache(configDir?: string): Promise<UpdateCheckCache | undefined>;
|
|
37
|
+
export declare function writeUpdateCheckCache(cache: UpdateCheckCache, configDir?: string): Promise<void>;
|
|
38
|
+
export interface WarnIfOutdatedOptions {
|
|
39
|
+
/** Defaults to the running package's own version. */
|
|
40
|
+
currentVersion?: string;
|
|
41
|
+
/** Test seam; defaults to the shared config dir. */
|
|
42
|
+
configDir?: string;
|
|
43
|
+
fetchImpl?: typeof fetch;
|
|
44
|
+
/** Test seam; defaults to Date.now(). */
|
|
45
|
+
now?: number;
|
|
46
|
+
env?: NodeJS.ProcessEnv;
|
|
47
|
+
/** Defaults to process.stderr.write. */
|
|
48
|
+
err?: (text: string) => void;
|
|
49
|
+
/** Skip the source-checkout guard (tests exercise the full path). */
|
|
50
|
+
force?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Print an outdated-version warning to stderr when a newer release exists.
|
|
54
|
+
*
|
|
55
|
+
* Never throws and never blocks longer than {@link WARN_FETCH_TIMEOUT_MS}.
|
|
56
|
+
* Suppressed on source-checkout runs (there is no installed copy to update),
|
|
57
|
+
* in CI, and via NO_UPDATE_NOTIFIER / AGENT_SERVE_NO_UPDATE_CHECK.
|
|
58
|
+
*/
|
|
59
|
+
export declare function warnIfOutdated(options?: WarnIfOutdatedOptions): Promise<void>;
|
|
60
|
+
export interface UpdateCommand {
|
|
61
|
+
cmd: string;
|
|
62
|
+
args: string[];
|
|
63
|
+
/** Working directory for local project installs. */
|
|
64
|
+
cwd?: string;
|
|
65
|
+
/** One-line human description of what will run and why. */
|
|
66
|
+
reason: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Figure out how the running copy was installed and which command upgrades
|
|
70
|
+
* it. Detection is path-shape based (global stores have recognizable
|
|
71
|
+
* layouts), then falls back to walking up to the project that declares the
|
|
72
|
+
* dependency. Returns undefined for layouts we cannot safely upgrade
|
|
73
|
+
* (npx cache, unrecognized stores).
|
|
74
|
+
*/
|
|
75
|
+
export declare function detectUpdateCommand(args: {
|
|
76
|
+
packageRoot: string;
|
|
77
|
+
packageName?: string;
|
|
78
|
+
}): Promise<UpdateCommand | undefined>;
|
|
79
|
+
export interface UpdateCliOptions {
|
|
80
|
+
/** Test seams. */
|
|
81
|
+
fetchImpl?: typeof fetch;
|
|
82
|
+
currentVersion?: string;
|
|
83
|
+
packageRoot?: string;
|
|
84
|
+
configDir?: string;
|
|
85
|
+
runCommand?: (command: UpdateCommand) => Promise<number>;
|
|
86
|
+
compiled?: boolean;
|
|
87
|
+
out?: (text: string) => void;
|
|
88
|
+
err?: (text: string) => void;
|
|
89
|
+
}
|
|
90
|
+
/** `agentkit update` — upgrade this install to the latest published version. */
|
|
91
|
+
export declare function cmdUpdate(options?: UpdateCliOptions): Promise<number>;
|
|
92
|
+
export {};
|
|
93
|
+
//# sourceMappingURL=update-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../../src/internal/update-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6CxB;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA0C5D;AAQD;;;GAGG;AACH,wBAAsB,2BAA2B,CAAC,OAAO,CAAC,EAAE;IAC1D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAqB9B;AAMD,QAAA,MAAM,WAAW,EAAE,CAAC,CAAC,SAAS,CAC5B;IAAE,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC;IAAC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;CAAE,EACrE,OAAO,CAMP,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAE3D,wBAAgB,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAsB,oBAAoB,CACxC,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAavC;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,gBAAgB,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAQf;AAMD,MAAM,WAAW,qBAAqB;IACpC,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,wCAAwC;IACxC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAUD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAoErC;AA+ED,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB;IAClB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,gFAAgF;AAChF,wBAAsB,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwE3E"}
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outdated-version warning + `agentkit update`.
|
|
3
|
+
*
|
|
4
|
+
* Every CLI run of a published install compares its own version against the
|
|
5
|
+
* npm registry's `latest` dist-tag and warns on stderr when behind. The
|
|
6
|
+
* registry lookup is cached under the config dir
|
|
7
|
+
* (`~/.config/agent-serve/update-check.json`) so most runs never touch the
|
|
8
|
+
* network; a stale cache refreshes inline under a short timeout, and any
|
|
9
|
+
* network failure is silent (the warning is best-effort, never a blocker).
|
|
10
|
+
*
|
|
11
|
+
* `agentkit update` re-runs the lookup fresh, figures out how this copy was
|
|
12
|
+
* installed (global npm/pnpm/yarn/bun, or a project dependency), and runs the
|
|
13
|
+
* matching install command.
|
|
14
|
+
*/
|
|
15
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
16
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
17
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
18
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
19
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
20
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
21
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
import { spawn } from "node:child_process";
|
|
25
|
+
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
26
|
+
import { dirname, join, sep } from "node:path";
|
|
27
|
+
import { z } from "zod";
|
|
28
|
+
import { configDirPath } from "./cursor/credentials.js";
|
|
29
|
+
import { describeError } from "./describe-error.js";
|
|
30
|
+
import { CLI_COMMAND_NAME, isCompiledDistribution, PACKAGE_NAME, packageRootDir, packageVersion, } from "./distribution.js";
|
|
31
|
+
import { stderrPalette } from "./terminal-style.js";
|
|
32
|
+
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
33
|
+
/** Refresh the registry lookup at most this often. */
|
|
34
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
35
|
+
/** Inline refresh budget; a slow registry must not stall the command. */
|
|
36
|
+
const WARN_FETCH_TIMEOUT_MS = 1500;
|
|
37
|
+
/** `agentkit update` runs interactively, so it can afford a real timeout. */
|
|
38
|
+
const UPDATE_FETCH_TIMEOUT_MS = 10000;
|
|
39
|
+
function parseVersion(version) {
|
|
40
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+.*)?$/.exec(version.trim());
|
|
41
|
+
if (match === null) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
release: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
46
|
+
prerelease: match[4] === undefined ? [] : match[4].split("."),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Semver-style ordering: negative when `a < b`, 0 when equal, positive when
|
|
51
|
+
* `a > b`. Unparseable versions compare equal (never warn on garbage).
|
|
52
|
+
*/
|
|
53
|
+
export function compareVersions(a, b) {
|
|
54
|
+
const pa = parseVersion(a);
|
|
55
|
+
const pb = parseVersion(b);
|
|
56
|
+
if (pa === undefined || pb === undefined) {
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
for (let i = 0; i < 3; i++) {
|
|
60
|
+
const diff = pa.release[i] - pb.release[i];
|
|
61
|
+
if (diff !== 0) {
|
|
62
|
+
return diff;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// A release outranks any prerelease of the same triple.
|
|
66
|
+
if (pa.prerelease.length === 0 || pb.prerelease.length === 0) {
|
|
67
|
+
return pb.prerelease.length - pa.prerelease.length;
|
|
68
|
+
}
|
|
69
|
+
const len = Math.max(pa.prerelease.length, pb.prerelease.length);
|
|
70
|
+
for (let i = 0; i < len; i++) {
|
|
71
|
+
const ia = pa.prerelease[i];
|
|
72
|
+
const ib = pb.prerelease[i];
|
|
73
|
+
// A longer prerelease list outranks its prefix (1.0.0-a.1 > 1.0.0-a).
|
|
74
|
+
if (ia === undefined) {
|
|
75
|
+
return -1;
|
|
76
|
+
}
|
|
77
|
+
if (ib === undefined) {
|
|
78
|
+
return 1;
|
|
79
|
+
}
|
|
80
|
+
const na = /^\d+$/.test(ia) ? Number(ia) : undefined;
|
|
81
|
+
const nb = /^\d+$/.test(ib) ? Number(ib) : undefined;
|
|
82
|
+
if (na !== undefined && nb !== undefined) {
|
|
83
|
+
if (na !== nb) {
|
|
84
|
+
return na - nb;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (na !== undefined) {
|
|
88
|
+
return -1; // numeric identifiers sort before alphanumeric ones
|
|
89
|
+
}
|
|
90
|
+
else if (nb !== undefined) {
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
else if (ia !== ib) {
|
|
94
|
+
return ia < ib ? -1 : 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Registry lookup
|
|
101
|
+
// ============================================================================
|
|
102
|
+
const distTagResponseSchema = z.object({ version: z.string() });
|
|
103
|
+
/**
|
|
104
|
+
* Latest published version of the package, from the registry's `latest`
|
|
105
|
+
* dist-tag. Returns undefined on any failure (offline, 404 pre-publish, …).
|
|
106
|
+
*/
|
|
107
|
+
export function fetchLatestPublishedVersion(options) {
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
109
|
+
var _a, _b, _c;
|
|
110
|
+
const fetchImpl = (_a = options === null || options === void 0 ? void 0 : options.fetchImpl) !== null && _a !== void 0 ? _a : fetch;
|
|
111
|
+
const packageName = (_b = options === null || options === void 0 ? void 0 : options.packageName) !== null && _b !== void 0 ? _b : PACKAGE_NAME;
|
|
112
|
+
// Scoped names keep the `@` but encode the `/` for the registry path.
|
|
113
|
+
const url = `${NPM_REGISTRY_URL}/${packageName.replace("/", "%2F")}/latest`;
|
|
114
|
+
try {
|
|
115
|
+
const response = yield fetchImpl(url, {
|
|
116
|
+
headers: { accept: "application/json" },
|
|
117
|
+
signal: AbortSignal.timeout((_c = options === null || options === void 0 ? void 0 : options.timeoutMs) !== null && _c !== void 0 ? _c : WARN_FETCH_TIMEOUT_MS),
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
const body = distTagResponseSchema.safeParse(yield response.json());
|
|
123
|
+
if (!body.success || parseVersion(body.data.version) === undefined) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
return body.data.version;
|
|
127
|
+
}
|
|
128
|
+
catch (_d) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// Cache (one JSON file next to credentials.json)
|
|
135
|
+
// ============================================================================
|
|
136
|
+
const cacheSchema = z.object({
|
|
137
|
+
/** Epoch ms of the last registry lookup attempt (success or not). */
|
|
138
|
+
checkedAt: z.number(),
|
|
139
|
+
/** Last version the registry reported; absent when lookups keep failing. */
|
|
140
|
+
latestVersion: z.string().optional(),
|
|
141
|
+
});
|
|
142
|
+
export function updateCheckCachePath(configDir) {
|
|
143
|
+
return join(configDir !== null && configDir !== void 0 ? configDir : configDirPath(), "update-check.json");
|
|
144
|
+
}
|
|
145
|
+
export function readUpdateCheckCache(configDir) {
|
|
146
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
+
let raw;
|
|
148
|
+
try {
|
|
149
|
+
raw = yield readFile(updateCheckCachePath(configDir), "utf8");
|
|
150
|
+
}
|
|
151
|
+
catch (_a) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const parsed = cacheSchema.safeParse(JSON.parse(raw));
|
|
156
|
+
return parsed.success ? parsed.data : undefined;
|
|
157
|
+
}
|
|
158
|
+
catch (_b) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
export function writeUpdateCheckCache(cache, configDir) {
|
|
164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
const path = updateCheckCachePath(configDir);
|
|
166
|
+
try {
|
|
167
|
+
yield mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
168
|
+
yield writeFile(path, `${JSON.stringify(cache, null, 2)}\n`);
|
|
169
|
+
}
|
|
170
|
+
catch (_a) {
|
|
171
|
+
// Best-effort; a read-only config dir just means re-checking next run.
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Print an outdated-version warning to stderr when a newer release exists.
|
|
177
|
+
*
|
|
178
|
+
* Never throws and never blocks longer than {@link WARN_FETCH_TIMEOUT_MS}.
|
|
179
|
+
* Suppressed on source-checkout runs (there is no installed copy to update),
|
|
180
|
+
* in CI, and via NO_UPDATE_NOTIFIER / AGENT_SERVE_NO_UPDATE_CHECK.
|
|
181
|
+
*/
|
|
182
|
+
export function warnIfOutdated(options) {
|
|
183
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
184
|
+
var _a, _b, _c, _d;
|
|
185
|
+
const env = (_a = options === null || options === void 0 ? void 0 : options.env) !== null && _a !== void 0 ? _a : process.env;
|
|
186
|
+
if (isTruthyEnv(env.AGENT_SERVE_NO_UPDATE_CHECK) ||
|
|
187
|
+
isTruthyEnv(env.NO_UPDATE_NOTIFIER) ||
|
|
188
|
+
isTruthyEnv(env.CI)) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if ((options === null || options === void 0 ? void 0 : options.force) !== true && !isCompiledDistribution()) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const now = (_b = options === null || options === void 0 ? void 0 : options.now) !== null && _b !== void 0 ? _b : Date.now();
|
|
195
|
+
const currentVersion = (_c = options === null || options === void 0 ? void 0 : options.currentVersion) !== null && _c !== void 0 ? _c : packageVersion();
|
|
196
|
+
const cached = yield readUpdateCheckCache(options === null || options === void 0 ? void 0 : options.configDir);
|
|
197
|
+
let latestVersion = cached === null || cached === void 0 ? void 0 : cached.latestVersion;
|
|
198
|
+
const fresh = cached !== undefined && now - cached.checkedAt < CHECK_INTERVAL_MS;
|
|
199
|
+
if (!fresh) {
|
|
200
|
+
const fetched = yield fetchLatestPublishedVersion({
|
|
201
|
+
fetchImpl: options === null || options === void 0 ? void 0 : options.fetchImpl,
|
|
202
|
+
timeoutMs: WARN_FETCH_TIMEOUT_MS,
|
|
203
|
+
});
|
|
204
|
+
latestVersion = fetched !== null && fetched !== void 0 ? fetched : latestVersion;
|
|
205
|
+
// checkedAt always advances so a flaky registry backs off to one
|
|
206
|
+
// attempt per interval instead of one per command.
|
|
207
|
+
yield writeUpdateCheckCache({ checkedAt: now, latestVersion }, options === null || options === void 0 ? void 0 : options.configDir);
|
|
208
|
+
}
|
|
209
|
+
if (latestVersion === undefined ||
|
|
210
|
+
compareVersions(currentVersion, latestVersion) >= 0) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const c = stderrPalette();
|
|
214
|
+
const err = (_d = options === null || options === void 0 ? void 0 : options.err) !== null && _d !== void 0 ? _d : ((text) => void process.stderr.write(text));
|
|
215
|
+
err(`${c.yellow("warning:")} ${CLI_COMMAND_NAME} ${currentVersion} is outdated (latest is ${latestVersion}). Run \`${CLI_COMMAND_NAME} update\` to upgrade.\n`);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function isTruthyEnv(value) {
|
|
219
|
+
return value !== undefined && value !== "" && value !== "0";
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Figure out how the running copy was installed and which command upgrades
|
|
223
|
+
* it. Detection is path-shape based (global stores have recognizable
|
|
224
|
+
* layouts), then falls back to walking up to the project that declares the
|
|
225
|
+
* dependency. Returns undefined for layouts we cannot safely upgrade
|
|
226
|
+
* (npx cache, unrecognized stores).
|
|
227
|
+
*/
|
|
228
|
+
export function detectUpdateCommand(args) {
|
|
229
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
230
|
+
var _a;
|
|
231
|
+
const packageName = (_a = args.packageName) !== null && _a !== void 0 ? _a : PACKAGE_NAME;
|
|
232
|
+
const spec = `${packageName}@latest`;
|
|
233
|
+
const posixRoot = args.packageRoot.split(sep).join("/");
|
|
234
|
+
// npx / pnpm dlx caches are ephemeral; a fresh `npx agentkit` already
|
|
235
|
+
// resolves latest, and upgrading the cache entry in place helps nobody.
|
|
236
|
+
if (posixRoot.includes("/_npx/") || posixRoot.includes("/.pnpm-store/")) {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
if (posixRoot.includes("/pnpm/global/")) {
|
|
240
|
+
return {
|
|
241
|
+
cmd: "pnpm",
|
|
242
|
+
args: ["add", "-g", spec],
|
|
243
|
+
reason: "installed with pnpm --global",
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
if (posixRoot.includes("/.bun/install/global/")) {
|
|
247
|
+
return {
|
|
248
|
+
cmd: "bun",
|
|
249
|
+
args: ["add", "-g", spec],
|
|
250
|
+
reason: "installed with bun --global",
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
if (posixRoot.includes("/yarn/global/") ||
|
|
254
|
+
posixRoot.includes("/.config/yarn/global/")) {
|
|
255
|
+
return {
|
|
256
|
+
cmd: "yarn",
|
|
257
|
+
args: ["global", "add", spec],
|
|
258
|
+
reason: "installed with yarn global",
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
// A project that depends on the package: upgrade the dependency there,
|
|
262
|
+
// with whichever package manager the lockfile says the project uses.
|
|
263
|
+
const projectDir = yield findDependingProjectDir(args.packageRoot, packageName);
|
|
264
|
+
if (projectDir !== undefined) {
|
|
265
|
+
const pm = yield detectProjectPackageManager(projectDir);
|
|
266
|
+
const command = pm === "pnpm"
|
|
267
|
+
? { cmd: "pnpm", args: ["add", spec] }
|
|
268
|
+
: pm === "yarn"
|
|
269
|
+
? { cmd: "yarn", args: ["add", spec] }
|
|
270
|
+
: pm === "bun"
|
|
271
|
+
? { cmd: "bun", args: ["add", spec] }
|
|
272
|
+
: { cmd: "npm", args: ["install", spec] };
|
|
273
|
+
return Object.assign(Object.assign({}, command), { cwd: projectDir, reason: `project dependency in ${projectDir}` });
|
|
274
|
+
}
|
|
275
|
+
// Global npm layout: <prefix>/lib/node_modules/<name> (or <prefix>\
|
|
276
|
+
// node_modules\<name> on Windows), with no depending project above it.
|
|
277
|
+
if (posixRoot.includes("/node_modules/")) {
|
|
278
|
+
return {
|
|
279
|
+
cmd: "npm",
|
|
280
|
+
args: ["install", "-g", spec],
|
|
281
|
+
reason: "installed with npm --global",
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
return undefined;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Nearest ancestor with a package.json that declares `packageName` as a
|
|
289
|
+
* dependency. Skips directories inside node_modules (pnpm's virtual store
|
|
290
|
+
* nests package.json files that are not the user's project).
|
|
291
|
+
*/
|
|
292
|
+
function findDependingProjectDir(packageRoot, packageName) {
|
|
293
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
294
|
+
let dir = dirname(packageRoot);
|
|
295
|
+
for (let depth = 0; depth < 30; depth++) {
|
|
296
|
+
const parent = dirname(dir);
|
|
297
|
+
if (parent === dir) {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
const inNodeModules = dir
|
|
301
|
+
.split(sep)
|
|
302
|
+
.some((part) => part === "node_modules" || part === ".pnpm");
|
|
303
|
+
if (!inNodeModules && (yield declaresDependency(dir, packageName))) {
|
|
304
|
+
return dir;
|
|
305
|
+
}
|
|
306
|
+
dir = parent;
|
|
307
|
+
}
|
|
308
|
+
return undefined;
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
function declaresDependency(dir, packageName) {
|
|
312
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
313
|
+
var _a, _b;
|
|
314
|
+
let raw;
|
|
315
|
+
try {
|
|
316
|
+
raw = yield readFile(join(dir, "package.json"), "utf8");
|
|
317
|
+
}
|
|
318
|
+
catch (_c) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
const manifestSchema = z.object({
|
|
322
|
+
dependencies: z.record(z.string()).optional(),
|
|
323
|
+
devDependencies: z.record(z.string()).optional(),
|
|
324
|
+
});
|
|
325
|
+
try {
|
|
326
|
+
const parsed = manifestSchema.safeParse(JSON.parse(raw));
|
|
327
|
+
if (!parsed.success) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
return (((_a = parsed.data.dependencies) === null || _a === void 0 ? void 0 : _a[packageName]) !== undefined ||
|
|
331
|
+
((_b = parsed.data.devDependencies) === null || _b === void 0 ? void 0 : _b[packageName]) !== undefined);
|
|
332
|
+
}
|
|
333
|
+
catch (_d) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
function detectProjectPackageManager(projectDir) {
|
|
339
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
340
|
+
const exists = (file) => __awaiter(this, void 0, void 0, function* () {
|
|
341
|
+
try {
|
|
342
|
+
yield stat(join(projectDir, file));
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
catch (_a) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
if (yield exists("pnpm-lock.yaml")) {
|
|
350
|
+
return "pnpm";
|
|
351
|
+
}
|
|
352
|
+
if (yield exists("yarn.lock")) {
|
|
353
|
+
return "yarn";
|
|
354
|
+
}
|
|
355
|
+
if ((yield exists("bun.lock")) || (yield exists("bun.lockb"))) {
|
|
356
|
+
return "bun";
|
|
357
|
+
}
|
|
358
|
+
return "npm";
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
/** `agentkit update` — upgrade this install to the latest published version. */
|
|
362
|
+
export function cmdUpdate(options) {
|
|
363
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
364
|
+
var _a, _b, _c, _d, _e, _f;
|
|
365
|
+
const c = stderrPalette();
|
|
366
|
+
const out = (_a = options === null || options === void 0 ? void 0 : options.out) !== null && _a !== void 0 ? _a : ((text) => void process.stdout.write(text));
|
|
367
|
+
const err = (_b = options === null || options === void 0 ? void 0 : options.err) !== null && _b !== void 0 ? _b : ((text) => void process.stderr.write(text));
|
|
368
|
+
const compiled = (_c = options === null || options === void 0 ? void 0 : options.compiled) !== null && _c !== void 0 ? _c : isCompiledDistribution();
|
|
369
|
+
if (!compiled) {
|
|
370
|
+
err(`${CLI_COMMAND_NAME} is running from a source checkout, not an installed package; update it with git instead.\n`);
|
|
371
|
+
return 1;
|
|
372
|
+
}
|
|
373
|
+
const currentVersion = (_d = options === null || options === void 0 ? void 0 : options.currentVersion) !== null && _d !== void 0 ? _d : packageVersion();
|
|
374
|
+
const latestVersion = yield fetchLatestPublishedVersion({
|
|
375
|
+
fetchImpl: options === null || options === void 0 ? void 0 : options.fetchImpl,
|
|
376
|
+
timeoutMs: UPDATE_FETCH_TIMEOUT_MS,
|
|
377
|
+
});
|
|
378
|
+
if (latestVersion === undefined) {
|
|
379
|
+
err(`Could not reach the npm registry to look up the latest ${PACKAGE_NAME} version. Check your network and retry.\n`);
|
|
380
|
+
return 1;
|
|
381
|
+
}
|
|
382
|
+
if (compareVersions(currentVersion, latestVersion) >= 0) {
|
|
383
|
+
out(`${CLI_COMMAND_NAME} ${currentVersion} is already the latest version.\n`);
|
|
384
|
+
yield writeUpdateCheckCache({ checkedAt: Date.now(), latestVersion }, options === null || options === void 0 ? void 0 : options.configDir);
|
|
385
|
+
return 0;
|
|
386
|
+
}
|
|
387
|
+
const command = yield detectUpdateCommand({
|
|
388
|
+
packageRoot: (_e = options === null || options === void 0 ? void 0 : options.packageRoot) !== null && _e !== void 0 ? _e : packageRootDir(),
|
|
389
|
+
});
|
|
390
|
+
if (command === undefined) {
|
|
391
|
+
err(`${CLI_COMMAND_NAME} ${currentVersion} is outdated (latest is ${latestVersion}), but this install's layout was not recognized.\nUpgrade it yourself, e.g. \`npm install -g ${PACKAGE_NAME}@latest\` for a global install, or bump the ${PACKAGE_NAME} dependency in your project.\n`);
|
|
392
|
+
return 1;
|
|
393
|
+
}
|
|
394
|
+
const rendered = [command.cmd, ...command.args].join(" ");
|
|
395
|
+
err(c.dim(`Updating ${CLI_COMMAND_NAME} ${currentVersion} → ${latestVersion} (${command.reason}):\n ${rendered}\n`));
|
|
396
|
+
const run = (_f = options === null || options === void 0 ? void 0 : options.runCommand) !== null && _f !== void 0 ? _f : runUpdateCommand;
|
|
397
|
+
let code;
|
|
398
|
+
try {
|
|
399
|
+
code = yield run(command);
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
err(`\`${rendered}\` failed: ${describeError(error)}\n`);
|
|
403
|
+
return 1;
|
|
404
|
+
}
|
|
405
|
+
if (code !== 0) {
|
|
406
|
+
err(`\`${rendered}\` exited with code ${code}.\n`);
|
|
407
|
+
return code;
|
|
408
|
+
}
|
|
409
|
+
yield writeUpdateCheckCache({ checkedAt: Date.now(), latestVersion }, options === null || options === void 0 ? void 0 : options.configDir);
|
|
410
|
+
out(`Updated ${CLI_COMMAND_NAME} to ${latestVersion}. New commands run the new version.\n`);
|
|
411
|
+
return 0;
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
function runUpdateCommand(command) {
|
|
415
|
+
return new Promise((resolve, reject) => {
|
|
416
|
+
// Windows-only shell: npm/pnpm/yarn/bun are .cmd shims there, and Node
|
|
417
|
+
// refuses to spawn .cmd files without a shell (EINVAL, CVE-2024-27980
|
|
418
|
+
// hardening). Injection-safe: cmd and args are module-level constants
|
|
419
|
+
// from detectUpdateCommand (never user or registry input).
|
|
420
|
+
// nosemgrep: javascript.lang.security.audit.spawn-shell-true.spawn-shell-true
|
|
421
|
+
const child = spawn(command.cmd, command.args, {
|
|
422
|
+
stdio: "inherit",
|
|
423
|
+
cwd: command.cwd,
|
|
424
|
+
shell: process.platform === "win32",
|
|
425
|
+
});
|
|
426
|
+
child.on("error", reject);
|
|
427
|
+
child.on("close", (code) => {
|
|
428
|
+
resolve(code !== null && code !== void 0 ? code : 1);
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
}
|