crewly 1.20.123 → 1.20.124
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/backend/backend/src/constants.d.ts +118 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +118 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/harness/harness.controller.d.ts +54 -0
- package/dist/backend/backend/src/controllers/harness/harness.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/harness/harness.controller.js +204 -0
- package/dist/backend/backend/src/controllers/harness/harness.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/harness/harness.routes.d.ts +27 -0
- package/dist/backend/backend/src/controllers/harness/harness.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/harness/harness.routes.js +43 -0
- package/dist/backend/backend/src/controllers/harness/harness.routes.js.map +1 -0
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +4 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +5 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +7 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +2 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js +4 -3
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +14 -0
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/claude-config.utils.d.ts +67 -0
- package/dist/backend/backend/src/services/harness/claude-config.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/claude-config.utils.js +118 -0
- package/dist/backend/backend/src/services/harness/claude-config.utils.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-api-key.service.d.ts +99 -0
- package/dist/backend/backend/src/services/harness/harness-api-key.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-api-key.service.js +157 -0
- package/dist/backend/backend/src/services/harness/harness-api-key.service.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts +135 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.js +208 -0
- package/dist/backend/backend/src/services/harness/harness-credentials.store.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-exec.utils.d.ts +85 -0
- package/dist/backend/backend/src/services/harness/harness-exec.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-exec.utils.js +183 -0
- package/dist/backend/backend/src/services/harness/harness-exec.utils.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-install.service.d.ts +106 -0
- package/dist/backend/backend/src/services/harness/harness-install.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-install.service.js +205 -0
- package/dist/backend/backend/src/services/harness/harness-install.service.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-registry.d.ts +86 -0
- package/dist/backend/backend/src/services/harness/harness-registry.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-registry.js +121 -0
- package/dist/backend/backend/src/services/harness/harness-registry.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-status.service.d.ts +173 -0
- package/dist/backend/backend/src/services/harness/harness-status.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness-status.service.js +324 -0
- package/dist/backend/backend/src/services/harness/harness-status.service.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness.service.d.ts +146 -0
- package/dist/backend/backend/src/services/harness/harness.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness.service.js +193 -0
- package/dist/backend/backend/src/services/harness/harness.service.js.map +1 -0
- package/dist/backend/backend/src/services/harness/harness.types.d.ts +138 -0
- package/dist/backend/backend/src/services/harness/harness.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/harness.types.js +51 -0
- package/dist/backend/backend/src/services/harness/harness.types.js.map +1 -0
- package/dist/backend/backend/src/services/harness/login-broker.service.d.ts +238 -0
- package/dist/backend/backend/src/services/harness/login-broker.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/login-broker.service.js +495 -0
- package/dist/backend/backend/src/services/harness/login-broker.service.js.map +1 -0
- package/dist/backend/backend/src/services/harness/login-rules.d.ts +162 -0
- package/dist/backend/backend/src/services/harness/login-rules.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/login-rules.js +344 -0
- package/dist/backend/backend/src/services/harness/login-rules.js.map +1 -0
- package/dist/backend/backend/src/services/harness/orc-harness.store.d.ts +59 -0
- package/dist/backend/backend/src/services/harness/orc-harness.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/orc-harness.store.js +108 -0
- package/dist/backend/backend/src/services/harness/orc-harness.store.js.map +1 -0
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +118 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +118 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +5 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +7 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts +2 -1
- package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-client.service.js +4 -3
- package/dist/cli/backend/src/services/cloud/cloud-client.service.js.map +1 -1
- package/dist/cli/backend/src/services/harness/claude-config.utils.d.ts +67 -0
- package/dist/cli/backend/src/services/harness/claude-config.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/claude-config.utils.js +118 -0
- package/dist/cli/backend/src/services/harness/claude-config.utils.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-api-key.service.d.ts +99 -0
- package/dist/cli/backend/src/services/harness/harness-api-key.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-api-key.service.js +157 -0
- package/dist/cli/backend/src/services/harness/harness-api-key.service.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts +135 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.js +208 -0
- package/dist/cli/backend/src/services/harness/harness-credentials.store.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-exec.utils.d.ts +85 -0
- package/dist/cli/backend/src/services/harness/harness-exec.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-exec.utils.js +183 -0
- package/dist/cli/backend/src/services/harness/harness-exec.utils.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-install.service.d.ts +106 -0
- package/dist/cli/backend/src/services/harness/harness-install.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-install.service.js +205 -0
- package/dist/cli/backend/src/services/harness/harness-install.service.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-registry.d.ts +86 -0
- package/dist/cli/backend/src/services/harness/harness-registry.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-registry.js +121 -0
- package/dist/cli/backend/src/services/harness/harness-registry.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-status.service.d.ts +173 -0
- package/dist/cli/backend/src/services/harness/harness-status.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness-status.service.js +324 -0
- package/dist/cli/backend/src/services/harness/harness-status.service.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness.service.d.ts +146 -0
- package/dist/cli/backend/src/services/harness/harness.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness.service.js +193 -0
- package/dist/cli/backend/src/services/harness/harness.service.js.map +1 -0
- package/dist/cli/backend/src/services/harness/harness.types.d.ts +138 -0
- package/dist/cli/backend/src/services/harness/harness.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/harness.types.js +51 -0
- package/dist/cli/backend/src/services/harness/harness.types.js.map +1 -0
- package/dist/cli/backend/src/services/harness/login-broker.service.d.ts +238 -0
- package/dist/cli/backend/src/services/harness/login-broker.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/login-broker.service.js +495 -0
- package/dist/cli/backend/src/services/harness/login-broker.service.js.map +1 -0
- package/dist/cli/backend/src/services/harness/login-rules.d.ts +162 -0
- package/dist/cli/backend/src/services/harness/login-rules.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/login-rules.js +344 -0
- package/dist/cli/backend/src/services/harness/login-rules.js.map +1 -0
- package/dist/cli/backend/src/services/harness/orc-harness.store.d.ts +59 -0
- package/dist/cli/backend/src/services/harness/orc-harness.store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/orc-harness.store.js +108 -0
- package/dist/cli/backend/src/services/harness/orc-harness.store.js.map +1 -0
- package/dist/cli/cli/src/commands/harness-setup.d.ts +159 -0
- package/dist/cli/cli/src/commands/harness-setup.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/harness-setup.js +377 -0
- package/dist/cli/cli/src/commands/harness-setup.js.map +1 -0
- package/dist/cli/cli/src/commands/harness.d.ts +56 -0
- package/dist/cli/cli/src/commands/harness.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/harness.js +97 -0
- package/dist/cli/cli/src/commands/harness.js.map +1 -0
- package/dist/cli/cli/src/commands/onboard.d.ts +108 -50
- package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/onboard.js +200 -191
- package/dist/cli/cli/src/commands/onboard.js.map +1 -1
- package/dist/cli/cli/src/constants.d.ts +18 -0
- package/dist/cli/cli/src/constants.d.ts.map +1 -1
- package/dist/cli/cli/src/constants.js +18 -0
- package/dist/cli/cli/src/constants.js.map +1 -1
- package/dist/cli/cli/src/index.js +22 -3
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/harness-engine.d.ts +99 -0
- package/dist/cli/cli/src/utils/harness-engine.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/harness-engine.js +143 -0
- package/dist/cli/cli/src/utils/harness-engine.js.map +1 -0
- package/dist/cli/cli/src/utils/prompt-io.d.ts +25 -0
- package/dist/cli/cli/src/utils/prompt-io.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/prompt-io.js +47 -0
- package/dist/cli/cli/src/utils/prompt-io.js.map +1 -0
- package/frontend/dist/assets/{index-8327e63e.css → index-0a2f783c.css} +1 -1
- package/frontend/dist/assets/{index-daf43f1a.js → index-aaf65055.js} +309 -309
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness install — `npm install -g <pkg>@latest` as an async job.
|
|
3
|
+
*
|
|
4
|
+
* When the global prefix is not writable (EACCES / EPERM), the install is
|
|
5
|
+
* retried once under the user-owned prefix `<crewlyHome>/npm-global`
|
|
6
|
+
* (`npm install -g --prefix …`); its `bin` dir is on the PATH of everything
|
|
7
|
+
* Crewly spawns (harness-exec.utils). No sudo, no shell profile edits.
|
|
8
|
+
*
|
|
9
|
+
* One install runs per harness at a time: starting a second one while the
|
|
10
|
+
* first is running returns the running job.
|
|
11
|
+
*
|
|
12
|
+
* @module services/harness/harness-install.service
|
|
13
|
+
*/
|
|
14
|
+
import { type HarnessId, type HarnessLogger, type InstallJob, type RunCommand } from './harness.types.js';
|
|
15
|
+
/** Injectable dependencies. */
|
|
16
|
+
export interface HarnessInstallDeps {
|
|
17
|
+
run?: RunCommand;
|
|
18
|
+
env?: NodeJS.ProcessEnv;
|
|
19
|
+
/** Creates the user prefix dir */
|
|
20
|
+
mkdirp?: (dir: string) => void;
|
|
21
|
+
now?: () => number;
|
|
22
|
+
idFactory?: () => string;
|
|
23
|
+
logger?: HarnessLogger;
|
|
24
|
+
/** Called after a successful install (e.g. to refresh status caches) */
|
|
25
|
+
onInstalled?: (harnessId: HarnessId) => void;
|
|
26
|
+
}
|
|
27
|
+
/** Error with a machine-readable code, for the REST layer. */
|
|
28
|
+
export declare class HarnessInstallError extends Error {
|
|
29
|
+
readonly code: 'unknown_harness' | 'job_not_found';
|
|
30
|
+
/**
|
|
31
|
+
* @param code - `unknown_harness` or `job_not_found`
|
|
32
|
+
* @param message - Human-readable message
|
|
33
|
+
*/
|
|
34
|
+
constructor(code: 'unknown_harness' | 'job_not_found', message: string);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether npm output says the global prefix is not writable.
|
|
38
|
+
*
|
|
39
|
+
* @param output - npm stdout + stderr
|
|
40
|
+
* @returns True for EACCES / EPERM / permission denied
|
|
41
|
+
*/
|
|
42
|
+
export declare function isPermissionError(output: string): boolean;
|
|
43
|
+
/** Runs and tracks harness install jobs. */
|
|
44
|
+
export declare class HarnessInstallService {
|
|
45
|
+
private readonly run;
|
|
46
|
+
private readonly env;
|
|
47
|
+
private readonly mkdirp;
|
|
48
|
+
private readonly now;
|
|
49
|
+
private readonly idFactory;
|
|
50
|
+
private readonly logger;
|
|
51
|
+
private readonly onInstalled?;
|
|
52
|
+
private readonly jobs;
|
|
53
|
+
/**
|
|
54
|
+
* @param deps - Injectable dependencies (all optional)
|
|
55
|
+
*/
|
|
56
|
+
constructor(deps?: HarnessInstallDeps);
|
|
57
|
+
/**
|
|
58
|
+
* Start installing (or updating) a harness.
|
|
59
|
+
*
|
|
60
|
+
* @param harnessId - Harness id
|
|
61
|
+
* @returns The new job, or the job already running for this harness
|
|
62
|
+
* @throws HarnessInstallError `unknown_harness`
|
|
63
|
+
*/
|
|
64
|
+
startInstall(harnessId: string): InstallJob;
|
|
65
|
+
/**
|
|
66
|
+
* Look up a job.
|
|
67
|
+
*
|
|
68
|
+
* @param jobId - Job id
|
|
69
|
+
* @returns The job
|
|
70
|
+
* @throws HarnessInstallError `job_not_found`
|
|
71
|
+
*/
|
|
72
|
+
getJob(jobId: string): InstallJob;
|
|
73
|
+
/**
|
|
74
|
+
* Wait for a job to finish (CLI).
|
|
75
|
+
*
|
|
76
|
+
* @param jobId - Job id
|
|
77
|
+
* @returns The finished job
|
|
78
|
+
* @throws HarnessInstallError `job_not_found`
|
|
79
|
+
*/
|
|
80
|
+
waitForJob(jobId: string): Promise<InstallJob>;
|
|
81
|
+
/**
|
|
82
|
+
* Run npm, falling back to the user prefix on a permission error.
|
|
83
|
+
*
|
|
84
|
+
* @param record - Job record (mutated)
|
|
85
|
+
* @param npmPackage - Package to install
|
|
86
|
+
* @returns The finished job
|
|
87
|
+
*/
|
|
88
|
+
private execute;
|
|
89
|
+
/**
|
|
90
|
+
* Append to a job log, keeping only the tail.
|
|
91
|
+
*
|
|
92
|
+
* @param record - Job record
|
|
93
|
+
* @param text - Text to append
|
|
94
|
+
*/
|
|
95
|
+
private append;
|
|
96
|
+
/** Forget finished jobs older than the retention window. */
|
|
97
|
+
private pruneFinished;
|
|
98
|
+
/**
|
|
99
|
+
* Public view of a job.
|
|
100
|
+
*
|
|
101
|
+
* @param record - Job record
|
|
102
|
+
* @returns Contract shape
|
|
103
|
+
*/
|
|
104
|
+
private toPublic;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=harness-install.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness-install.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAAyB,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEjI,+BAA+B;AAC/B,MAAM,WAAW,kBAAkB;IAClC,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,kCAAkC;IAClC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,wEAAwE;IACxE,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;CAC7C;AAED,8DAA8D;AAC9D,qBAAa,mBAAoB,SAAQ,KAAK;aAM5B,IAAI,EAAE,iBAAiB,GAAG,eAAe;IAL1D;;;OAGG;gBAEc,IAAI,EAAE,iBAAiB,GAAG,eAAe,EACzD,OAAO,EAAE,MAAM;CAKhB;AASD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGzD;AAED,4CAA4C;AAC5C,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAiC;IAC9D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgC;IAErD;;OAEG;gBACS,IAAI,GAAE,kBAAuB;IAUzC;;;;;;OAMG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU;IAqB3C;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAMjC;;;;;;OAMG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAOpD;;;;;;OAMG;YACW,OAAO;IAuCrB;;;;;OAKG;IACH,OAAO,CAAC,MAAM;IAMd,4DAA4D;IAC5D,OAAO,CAAC,aAAa;IAOrB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;CAShB"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness install — `npm install -g <pkg>@latest` as an async job.
|
|
3
|
+
*
|
|
4
|
+
* When the global prefix is not writable (EACCES / EPERM), the install is
|
|
5
|
+
* retried once under the user-owned prefix `<crewlyHome>/npm-global`
|
|
6
|
+
* (`npm install -g --prefix …`); its `bin` dir is on the PATH of everything
|
|
7
|
+
* Crewly spawns (harness-exec.utils). No sudo, no shell profile edits.
|
|
8
|
+
*
|
|
9
|
+
* One install runs per harness at a time: starting a second one while the
|
|
10
|
+
* first is running returns the running job.
|
|
11
|
+
*
|
|
12
|
+
* @module services/harness/harness-install.service
|
|
13
|
+
*/
|
|
14
|
+
import { randomUUID } from 'crypto';
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import { HARNESS_CONSTANTS } from '../../constants.js';
|
|
17
|
+
import { buildNpmPath, getUserNpmPrefix, runCommand } from './harness-exec.utils.js';
|
|
18
|
+
import { getHarnessDefinition } from './harness-registry.js';
|
|
19
|
+
import { SILENT_HARNESS_LOGGER } from './harness.types.js';
|
|
20
|
+
/** Error with a machine-readable code, for the REST layer. */
|
|
21
|
+
export class HarnessInstallError extends Error {
|
|
22
|
+
code;
|
|
23
|
+
/**
|
|
24
|
+
* @param code - `unknown_harness` or `job_not_found`
|
|
25
|
+
* @param message - Human-readable message
|
|
26
|
+
*/
|
|
27
|
+
constructor(code, message) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.name = 'HarnessInstallError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether npm output says the global prefix is not writable.
|
|
35
|
+
*
|
|
36
|
+
* @param output - npm stdout + stderr
|
|
37
|
+
* @returns True for EACCES / EPERM / permission denied
|
|
38
|
+
*/
|
|
39
|
+
export function isPermissionError(output) {
|
|
40
|
+
const lower = output.toLowerCase();
|
|
41
|
+
return HARNESS_CONSTANTS.PERMISSION_ERROR_PATTERNS.some((pattern) => lower.includes(pattern.toLowerCase()));
|
|
42
|
+
}
|
|
43
|
+
/** Runs and tracks harness install jobs. */
|
|
44
|
+
export class HarnessInstallService {
|
|
45
|
+
run;
|
|
46
|
+
env;
|
|
47
|
+
mkdirp;
|
|
48
|
+
now;
|
|
49
|
+
idFactory;
|
|
50
|
+
logger;
|
|
51
|
+
onInstalled;
|
|
52
|
+
jobs = new Map();
|
|
53
|
+
/**
|
|
54
|
+
* @param deps - Injectable dependencies (all optional)
|
|
55
|
+
*/
|
|
56
|
+
constructor(deps = {}) {
|
|
57
|
+
this.run = deps.run ?? runCommand;
|
|
58
|
+
this.env = deps.env ?? process.env;
|
|
59
|
+
this.mkdirp = deps.mkdirp ?? ((dir) => fs.mkdirSync(dir, { recursive: true }));
|
|
60
|
+
this.now = deps.now ?? Date.now;
|
|
61
|
+
this.idFactory = deps.idFactory ?? randomUUID;
|
|
62
|
+
this.logger = deps.logger ?? SILENT_HARNESS_LOGGER;
|
|
63
|
+
this.onInstalled = deps.onInstalled;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Start installing (or updating) a harness.
|
|
67
|
+
*
|
|
68
|
+
* @param harnessId - Harness id
|
|
69
|
+
* @returns The new job, or the job already running for this harness
|
|
70
|
+
* @throws HarnessInstallError `unknown_harness`
|
|
71
|
+
*/
|
|
72
|
+
startInstall(harnessId) {
|
|
73
|
+
const def = getHarnessDefinition(harnessId);
|
|
74
|
+
if (!def)
|
|
75
|
+
throw new HarnessInstallError('unknown_harness', `Unknown harness: ${harnessId}`);
|
|
76
|
+
this.pruneFinished();
|
|
77
|
+
const running = [...this.jobs.values()].find((job) => job.harnessId === def.id && job.state === 'running');
|
|
78
|
+
if (running)
|
|
79
|
+
return this.toPublic(running);
|
|
80
|
+
const record = {
|
|
81
|
+
jobId: this.idFactory(),
|
|
82
|
+
harnessId: def.id,
|
|
83
|
+
state: 'running',
|
|
84
|
+
log: '',
|
|
85
|
+
usedUserPrefix: false,
|
|
86
|
+
finishedAt: null,
|
|
87
|
+
done: null,
|
|
88
|
+
};
|
|
89
|
+
this.jobs.set(record.jobId, record);
|
|
90
|
+
record.done = this.execute(record, def.npmPackage);
|
|
91
|
+
return this.toPublic(record);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Look up a job.
|
|
95
|
+
*
|
|
96
|
+
* @param jobId - Job id
|
|
97
|
+
* @returns The job
|
|
98
|
+
* @throws HarnessInstallError `job_not_found`
|
|
99
|
+
*/
|
|
100
|
+
getJob(jobId) {
|
|
101
|
+
const record = this.jobs.get(jobId);
|
|
102
|
+
if (!record)
|
|
103
|
+
throw new HarnessInstallError('job_not_found', `Install job not found: ${jobId}`);
|
|
104
|
+
return this.toPublic(record);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Wait for a job to finish (CLI).
|
|
108
|
+
*
|
|
109
|
+
* @param jobId - Job id
|
|
110
|
+
* @returns The finished job
|
|
111
|
+
* @throws HarnessInstallError `job_not_found`
|
|
112
|
+
*/
|
|
113
|
+
async waitForJob(jobId) {
|
|
114
|
+
const record = this.jobs.get(jobId);
|
|
115
|
+
if (!record)
|
|
116
|
+
throw new HarnessInstallError('job_not_found', `Install job not found: ${jobId}`);
|
|
117
|
+
if (record.done)
|
|
118
|
+
await record.done;
|
|
119
|
+
return this.toPublic(record);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Run npm, falling back to the user prefix on a permission error.
|
|
123
|
+
*
|
|
124
|
+
* @param record - Job record (mutated)
|
|
125
|
+
* @param npmPackage - Package to install
|
|
126
|
+
* @returns The finished job
|
|
127
|
+
*/
|
|
128
|
+
async execute(record, npmPackage) {
|
|
129
|
+
const spec = `${npmPackage}@latest`;
|
|
130
|
+
const env = { ...this.env, PATH: buildNpmPath(this.env.PATH) };
|
|
131
|
+
try {
|
|
132
|
+
this.append(record, `$ npm install -g ${spec}\n`);
|
|
133
|
+
const first = await this.run('npm', ['install', '-g', spec], {
|
|
134
|
+
env,
|
|
135
|
+
timeoutMs: HARNESS_CONSTANTS.INSTALL_TIMEOUT_MS,
|
|
136
|
+
onOutput: (chunk) => this.append(record, chunk),
|
|
137
|
+
});
|
|
138
|
+
let ok = first.code === 0;
|
|
139
|
+
if (!ok && isPermissionError(`${first.stdout}\n${first.stderr}\n${first.error ?? ''}`)) {
|
|
140
|
+
const prefix = getUserNpmPrefix();
|
|
141
|
+
this.mkdirp(prefix);
|
|
142
|
+
record.usedUserPrefix = true;
|
|
143
|
+
this.append(record, `\nNo permission to write the global npm prefix; installing under ${prefix} instead.\n`);
|
|
144
|
+
this.append(record, `$ npm install -g --prefix ${prefix} ${spec}\n`);
|
|
145
|
+
const second = await this.run('npm', ['install', '-g', '--prefix', prefix, spec], {
|
|
146
|
+
env,
|
|
147
|
+
timeoutMs: HARNESS_CONSTANTS.INSTALL_TIMEOUT_MS,
|
|
148
|
+
onOutput: (chunk) => this.append(record, chunk),
|
|
149
|
+
});
|
|
150
|
+
ok = second.code === 0;
|
|
151
|
+
if (!ok && second.error)
|
|
152
|
+
this.append(record, `\n${second.error}\n`);
|
|
153
|
+
}
|
|
154
|
+
else if (!ok && first.error) {
|
|
155
|
+
this.append(record, `\n${first.error}\n`);
|
|
156
|
+
}
|
|
157
|
+
record.state = ok ? 'succeeded' : 'failed';
|
|
158
|
+
this.append(record, ok ? '\nInstalled.\n' : '\nInstall failed.\n');
|
|
159
|
+
if (ok)
|
|
160
|
+
this.onInstalled?.(record.harnessId);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
record.state = 'failed';
|
|
164
|
+
this.append(record, `\n${error instanceof Error ? error.message : String(error)}\n`);
|
|
165
|
+
}
|
|
166
|
+
record.finishedAt = this.now();
|
|
167
|
+
this.logger.info('Harness install finished', { harnessId: record.harnessId, state: record.state, usedUserPrefix: record.usedUserPrefix });
|
|
168
|
+
return this.toPublic(record);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Append to a job log, keeping only the tail.
|
|
172
|
+
*
|
|
173
|
+
* @param record - Job record
|
|
174
|
+
* @param text - Text to append
|
|
175
|
+
*/
|
|
176
|
+
append(record, text) {
|
|
177
|
+
const next = record.log + text;
|
|
178
|
+
const max = HARNESS_CONSTANTS.INSTALL_LOG_MAX_CHARS;
|
|
179
|
+
record.log = next.length > max ? next.slice(next.length - max) : next;
|
|
180
|
+
}
|
|
181
|
+
/** Forget finished jobs older than the retention window. */
|
|
182
|
+
pruneFinished() {
|
|
183
|
+
const cutoff = this.now() - HARNESS_CONSTANTS.INSTALL_JOB_RETENTION_MS;
|
|
184
|
+
for (const [id, job] of this.jobs) {
|
|
185
|
+
if (job.finishedAt !== null && job.finishedAt < cutoff)
|
|
186
|
+
this.jobs.delete(id);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Public view of a job.
|
|
191
|
+
*
|
|
192
|
+
* @param record - Job record
|
|
193
|
+
* @returns Contract shape
|
|
194
|
+
*/
|
|
195
|
+
toPublic(record) {
|
|
196
|
+
return {
|
|
197
|
+
jobId: record.jobId,
|
|
198
|
+
harnessId: record.harnessId,
|
|
199
|
+
state: record.state,
|
|
200
|
+
log: record.log,
|
|
201
|
+
usedUserPrefix: record.usedUserPrefix,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=harness-install.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness-install.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness registry — static definitions of the agent CLIs Crewly can set up.
|
|
3
|
+
*
|
|
4
|
+
* One entry per harness: display name, binary, npm package, how to print the
|
|
5
|
+
* version, and the login methods Crewly offers. A `broker` method names the
|
|
6
|
+
* harness's own login command, which the login broker runs in a PTY; an
|
|
7
|
+
* `api_key` method is a pasted key. Gemini CLI is detect-only (no methods).
|
|
8
|
+
*
|
|
9
|
+
* @module services/harness/harness-registry
|
|
10
|
+
*/
|
|
11
|
+
import type { HarnessId, HarnessLoginMethod, LoginMethodId, LoginMethodKind } from './harness.types.js';
|
|
12
|
+
/** The command a broker login method runs. */
|
|
13
|
+
export interface BrokerCommand {
|
|
14
|
+
/** Binary (resolved on the harness PATH) */
|
|
15
|
+
command: string;
|
|
16
|
+
args: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
/** A login method definition (internal: includes the broker command). */
|
|
19
|
+
export interface LoginMethodDefinition {
|
|
20
|
+
id: LoginMethodId;
|
|
21
|
+
label: string;
|
|
22
|
+
kind: LoginMethodKind;
|
|
23
|
+
/** Command run by the login broker (kind `broker` only) */
|
|
24
|
+
broker?: BrokerCommand;
|
|
25
|
+
}
|
|
26
|
+
/** Static facts about one harness. */
|
|
27
|
+
export interface HarnessDefinition {
|
|
28
|
+
id: HarnessId;
|
|
29
|
+
displayName: string;
|
|
30
|
+
/** Binary name on PATH */
|
|
31
|
+
command: string;
|
|
32
|
+
npmPackage: string;
|
|
33
|
+
/** Arguments that print the version */
|
|
34
|
+
versionArgs: readonly string[];
|
|
35
|
+
loginMethods: readonly LoginMethodDefinition[];
|
|
36
|
+
}
|
|
37
|
+
/** Every harness Crewly knows, in display order (default first). */
|
|
38
|
+
export declare const HARNESS_DEFINITIONS: readonly HarnessDefinition[];
|
|
39
|
+
/**
|
|
40
|
+
* All harness definitions.
|
|
41
|
+
*
|
|
42
|
+
* @returns The registry, in display order
|
|
43
|
+
*/
|
|
44
|
+
export declare function listHarnessDefinitions(): readonly HarnessDefinition[];
|
|
45
|
+
/**
|
|
46
|
+
* Look up a harness definition.
|
|
47
|
+
*
|
|
48
|
+
* @param id - Harness id
|
|
49
|
+
* @returns The definition, or undefined for an unknown id
|
|
50
|
+
*/
|
|
51
|
+
export declare function getHarnessDefinition(id: string): HarnessDefinition | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Look up one login method of a harness.
|
|
54
|
+
*
|
|
55
|
+
* @param harnessId - Harness id
|
|
56
|
+
* @param methodId - Login method id
|
|
57
|
+
* @returns The method, or undefined when the harness does not offer it
|
|
58
|
+
*/
|
|
59
|
+
export declare function getLoginMethod(harnessId: string, methodId: string): LoginMethodDefinition | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* The broker login method of a harness (the first one), if any.
|
|
62
|
+
*
|
|
63
|
+
* @param harnessId - Harness id
|
|
64
|
+
* @returns The method, or undefined when the harness has no broker login
|
|
65
|
+
*/
|
|
66
|
+
export declare function getBrokerLoginMethod(harnessId: string): LoginMethodDefinition | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Public view of a harness's login methods (no commands).
|
|
69
|
+
*
|
|
70
|
+
* @param def - Harness definition
|
|
71
|
+
* @returns `{ id, label, kind }` per method
|
|
72
|
+
*/
|
|
73
|
+
export declare function toPublicLoginMethods(def: HarnessDefinition): HarnessLoginMethod[];
|
|
74
|
+
/**
|
|
75
|
+
* Resolve a harness id from a full id or a short CLI alias.
|
|
76
|
+
*
|
|
77
|
+
* @param value - `claude-code`, `claude`, `codex-cli`, `codex`, `gemini-cli` or `gemini` (case-insensitive)
|
|
78
|
+
* @returns The harness id, or null when unknown
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* resolveHarnessAlias('codex'); // 'codex-cli'
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function resolveHarnessAlias(value: string | undefined | null): HarnessId | null;
|
|
86
|
+
//# sourceMappingURL=harness-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-registry.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGxG,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC7B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACxB;AAED,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACrC,EAAE,EAAE,aAAa,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;IACtB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,SAAS,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,YAAY,EAAE,SAAS,qBAAqB,EAAE,CAAC;CAC/C;AAED,oEAAoE;AACpE,eAAO,MAAM,mBAAmB,EAAE,SAAS,iBAAiB,EAyC3D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,SAAS,iBAAiB,EAAE,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAErG;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAEzF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,iBAAiB,GAAG,kBAAkB,EAAE,CAEjF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAMtF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness registry — static definitions of the agent CLIs Crewly can set up.
|
|
3
|
+
*
|
|
4
|
+
* One entry per harness: display name, binary, npm package, how to print the
|
|
5
|
+
* version, and the login methods Crewly offers. A `broker` method names the
|
|
6
|
+
* harness's own login command, which the login broker runs in a PTY; an
|
|
7
|
+
* `api_key` method is a pasted key. Gemini CLI is detect-only (no methods).
|
|
8
|
+
*
|
|
9
|
+
* @module services/harness/harness-registry
|
|
10
|
+
*/
|
|
11
|
+
import { HARNESS_CONSTANTS } from '../../constants.js';
|
|
12
|
+
import { isHarnessId } from './harness.types.js';
|
|
13
|
+
/** Every harness Crewly knows, in display order (default first). */
|
|
14
|
+
export const HARNESS_DEFINITIONS = [
|
|
15
|
+
{
|
|
16
|
+
id: HARNESS_CONSTANTS.IDS.CLAUDE_CODE,
|
|
17
|
+
displayName: 'Claude Code',
|
|
18
|
+
command: 'claude',
|
|
19
|
+
npmPackage: '@anthropic-ai/claude-code',
|
|
20
|
+
versionArgs: ['--version'],
|
|
21
|
+
loginMethods: [
|
|
22
|
+
{
|
|
23
|
+
id: 'subscription',
|
|
24
|
+
label: 'Claude subscription (Pro / Max)',
|
|
25
|
+
kind: 'broker',
|
|
26
|
+
broker: { command: 'claude', args: ['setup-token'] },
|
|
27
|
+
},
|
|
28
|
+
{ id: 'api_key', label: 'Anthropic API key', kind: 'api_key' },
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: HARNESS_CONSTANTS.IDS.CODEX_CLI,
|
|
33
|
+
displayName: 'Codex',
|
|
34
|
+
command: 'codex',
|
|
35
|
+
npmPackage: '@openai/codex',
|
|
36
|
+
versionArgs: ['--version'],
|
|
37
|
+
loginMethods: [
|
|
38
|
+
{
|
|
39
|
+
id: 'device',
|
|
40
|
+
label: 'ChatGPT account (device code)',
|
|
41
|
+
kind: 'broker',
|
|
42
|
+
broker: { command: 'codex', args: ['login', '--device-auth'] },
|
|
43
|
+
},
|
|
44
|
+
{ id: 'api_key', label: 'OpenAI API key', kind: 'api_key' },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: HARNESS_CONSTANTS.IDS.GEMINI_CLI,
|
|
49
|
+
displayName: 'Gemini CLI',
|
|
50
|
+
command: 'gemini',
|
|
51
|
+
npmPackage: '@google/gemini-cli',
|
|
52
|
+
versionArgs: ['--version'],
|
|
53
|
+
loginMethods: [],
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* All harness definitions.
|
|
58
|
+
*
|
|
59
|
+
* @returns The registry, in display order
|
|
60
|
+
*/
|
|
61
|
+
export function listHarnessDefinitions() {
|
|
62
|
+
return HARNESS_DEFINITIONS;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Look up a harness definition.
|
|
66
|
+
*
|
|
67
|
+
* @param id - Harness id
|
|
68
|
+
* @returns The definition, or undefined for an unknown id
|
|
69
|
+
*/
|
|
70
|
+
export function getHarnessDefinition(id) {
|
|
71
|
+
return HARNESS_DEFINITIONS.find((def) => def.id === id);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Look up one login method of a harness.
|
|
75
|
+
*
|
|
76
|
+
* @param harnessId - Harness id
|
|
77
|
+
* @param methodId - Login method id
|
|
78
|
+
* @returns The method, or undefined when the harness does not offer it
|
|
79
|
+
*/
|
|
80
|
+
export function getLoginMethod(harnessId, methodId) {
|
|
81
|
+
return getHarnessDefinition(harnessId)?.loginMethods.find((method) => method.id === methodId);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The broker login method of a harness (the first one), if any.
|
|
85
|
+
*
|
|
86
|
+
* @param harnessId - Harness id
|
|
87
|
+
* @returns The method, or undefined when the harness has no broker login
|
|
88
|
+
*/
|
|
89
|
+
export function getBrokerLoginMethod(harnessId) {
|
|
90
|
+
return getHarnessDefinition(harnessId)?.loginMethods.find((method) => method.kind === 'broker');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Public view of a harness's login methods (no commands).
|
|
94
|
+
*
|
|
95
|
+
* @param def - Harness definition
|
|
96
|
+
* @returns `{ id, label, kind }` per method
|
|
97
|
+
*/
|
|
98
|
+
export function toPublicLoginMethods(def) {
|
|
99
|
+
return def.loginMethods.map(({ id, label, kind }) => ({ id, label, kind }));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve a harness id from a full id or a short CLI alias.
|
|
103
|
+
*
|
|
104
|
+
* @param value - `claude-code`, `claude`, `codex-cli`, `codex`, `gemini-cli` or `gemini` (case-insensitive)
|
|
105
|
+
* @returns The harness id, or null when unknown
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* resolveHarnessAlias('codex'); // 'codex-cli'
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function resolveHarnessAlias(value) {
|
|
113
|
+
if (!value)
|
|
114
|
+
return null;
|
|
115
|
+
const key = value.trim().toLowerCase();
|
|
116
|
+
if (isHarnessId(key))
|
|
117
|
+
return key;
|
|
118
|
+
const aliases = HARNESS_CONSTANTS.CLI_ALIASES;
|
|
119
|
+
return aliases[key] ?? null;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=harness-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-registry.js","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness-registry.ts"],"names":[],"mappings":"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"}
|