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,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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"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness status — is each harness installed, which version, is a newer one
|
|
3
|
+
* published, and is it logged in?
|
|
4
|
+
*
|
|
5
|
+
* Detection reads files, env var names and the exit codes of probe commands;
|
|
6
|
+
* it never prints or returns a secret. Login sources are labels such as
|
|
7
|
+
* `crewly-subscription` or `macos-keychain`.
|
|
8
|
+
*
|
|
9
|
+
* - Claude Code: a credential Crewly stores, `CLAUDE_CODE_OAUTH_TOKEN` /
|
|
10
|
+
* `ANTHROPIC_API_KEY` in the env, `~/.claude/.credentials.json`, or the macOS
|
|
11
|
+
* keychain item "Claude Code-credentials" (existence only: `security
|
|
12
|
+
* find-generic-password -s …` without `-w`/`-g`, so no secret is printed).
|
|
13
|
+
* - Codex: `codex login status`; falls back to `$CODEX_HOME/auth.json`.
|
|
14
|
+
* - Gemini CLI (detect only): Google-login credentials file or an API key env var.
|
|
15
|
+
*
|
|
16
|
+
* @module services/harness/harness-status.service
|
|
17
|
+
*/
|
|
18
|
+
import { HarnessCredentialsStore } from './harness-credentials.store.js';
|
|
19
|
+
import { type HarnessDefinition } from './harness-registry.js';
|
|
20
|
+
import { type HarnessId, type HarnessLogger, type HarnessStatus, type LoginState, type RunCommand, type SystemToolStatus } from './harness.types.js';
|
|
21
|
+
/** Injectable dependencies. */
|
|
22
|
+
export interface HarnessStatusDeps {
|
|
23
|
+
run?: RunCommand;
|
|
24
|
+
env?: NodeJS.ProcessEnv;
|
|
25
|
+
homeDir?: string;
|
|
26
|
+
platform?: NodeJS.Platform;
|
|
27
|
+
fileExists?: (file: string) => boolean;
|
|
28
|
+
/** PATH lookup; defaults to {@link resolveExecutable} on the harness PATH */
|
|
29
|
+
resolveCommand?: (command: string) => string | null;
|
|
30
|
+
credentials?: HarnessCredentialsStore;
|
|
31
|
+
now?: () => number;
|
|
32
|
+
logger?: HarnessLogger;
|
|
33
|
+
}
|
|
34
|
+
/** Installed binary facts. */
|
|
35
|
+
export interface InstalledInfo {
|
|
36
|
+
installed: boolean;
|
|
37
|
+
/** Absolute path of the binary */
|
|
38
|
+
path: string | null;
|
|
39
|
+
version: string | null;
|
|
40
|
+
}
|
|
41
|
+
/** Login facts. */
|
|
42
|
+
export interface LoginInfo {
|
|
43
|
+
loginState: LoginState;
|
|
44
|
+
loginSource: string | null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Pull a version number out of `--version` output.
|
|
48
|
+
*
|
|
49
|
+
* @param output - Command output, e.g. `2.1.282 (Claude Code)` or `codex-cli 0.156.1`
|
|
50
|
+
* @returns The version, or null
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseVersion(output: string): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Compare two dotted versions numerically (pre-release suffixes ignored).
|
|
55
|
+
*
|
|
56
|
+
* @param a - Version
|
|
57
|
+
* @param b - Version
|
|
58
|
+
* @returns Positive when a > b, negative when a < b, 0 when equal
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* compareVersions('2.1.282', '2.1.99'); // > 0
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
66
|
+
/**
|
|
67
|
+
* Classify `codex login status` output.
|
|
68
|
+
*
|
|
69
|
+
* @param output - stdout + stderr (may mention a masked key; never returned)
|
|
70
|
+
* @returns `chatgpt`, `api_key` or `codex`
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseCodexLoginSource(output: string): string;
|
|
73
|
+
/** Detects install, version and login state of each harness. */
|
|
74
|
+
export declare class HarnessStatusService {
|
|
75
|
+
private readonly run;
|
|
76
|
+
private readonly env;
|
|
77
|
+
private readonly homeDir;
|
|
78
|
+
private readonly platform;
|
|
79
|
+
private readonly fileExists;
|
|
80
|
+
private readonly resolveCommand;
|
|
81
|
+
private readonly credentials;
|
|
82
|
+
private readonly now;
|
|
83
|
+
private readonly logger;
|
|
84
|
+
private readonly latestCache;
|
|
85
|
+
/**
|
|
86
|
+
* @param deps - Injectable dependencies (all optional)
|
|
87
|
+
*/
|
|
88
|
+
constructor(deps?: HarnessStatusDeps);
|
|
89
|
+
/**
|
|
90
|
+
* Environment for probe commands (harness PATH).
|
|
91
|
+
*
|
|
92
|
+
* @returns Env copy
|
|
93
|
+
*/
|
|
94
|
+
private probeEnv;
|
|
95
|
+
/**
|
|
96
|
+
* Whether the binary is on PATH and which version it reports.
|
|
97
|
+
*
|
|
98
|
+
* @param def - Harness definition
|
|
99
|
+
* @returns Installed facts
|
|
100
|
+
*/
|
|
101
|
+
getInstalledInfo(def: HarnessDefinition): Promise<InstalledInfo>;
|
|
102
|
+
/**
|
|
103
|
+
* Latest published version (`npm view <pkg> version`), cached.
|
|
104
|
+
*
|
|
105
|
+
* @param def - Harness definition
|
|
106
|
+
* @returns The version, or null when npm could not be asked
|
|
107
|
+
*/
|
|
108
|
+
getLatestVersion(def: HarnessDefinition): Promise<string | null>;
|
|
109
|
+
/** Forget cached latest versions. */
|
|
110
|
+
clearLatestVersionCache(): void;
|
|
111
|
+
/**
|
|
112
|
+
* First env var (by name) that has a value.
|
|
113
|
+
*
|
|
114
|
+
* @param names - Candidates
|
|
115
|
+
* @returns The name, or null
|
|
116
|
+
*/
|
|
117
|
+
private firstSetEnv;
|
|
118
|
+
/**
|
|
119
|
+
* Claude Code login detection.
|
|
120
|
+
*
|
|
121
|
+
* @returns Login facts
|
|
122
|
+
*/
|
|
123
|
+
private getClaudeLogin;
|
|
124
|
+
/**
|
|
125
|
+
* Whether `~/.claude.json` records an OAuth account or a primary API key.
|
|
126
|
+
*
|
|
127
|
+
* @param file - Config path
|
|
128
|
+
* @returns True when an account is recorded
|
|
129
|
+
*/
|
|
130
|
+
private claudeConfigHasAccount;
|
|
131
|
+
/**
|
|
132
|
+
* Codex login detection.
|
|
133
|
+
*
|
|
134
|
+
* @param binary - Codex binary path, when installed
|
|
135
|
+
* @returns Login facts
|
|
136
|
+
*/
|
|
137
|
+
private getCodexLogin;
|
|
138
|
+
/**
|
|
139
|
+
* Gemini CLI login detection (detect only).
|
|
140
|
+
*
|
|
141
|
+
* @returns Login facts
|
|
142
|
+
*/
|
|
143
|
+
private getGeminiLogin;
|
|
144
|
+
/**
|
|
145
|
+
* Login state of a harness.
|
|
146
|
+
*
|
|
147
|
+
* @param def - Harness definition
|
|
148
|
+
* @param binary - Binary path when installed (Codex asks the binary itself)
|
|
149
|
+
* @returns Login facts
|
|
150
|
+
*/
|
|
151
|
+
getLoginInfo(def: HarnessDefinition, binary: string | null): Promise<LoginInfo>;
|
|
152
|
+
/**
|
|
153
|
+
* Full status of one harness.
|
|
154
|
+
*
|
|
155
|
+
* @param id - Harness id
|
|
156
|
+
* @returns The status
|
|
157
|
+
* @throws Error for an unknown harness id
|
|
158
|
+
*/
|
|
159
|
+
getStatus(id: HarnessId): Promise<HarnessStatus>;
|
|
160
|
+
/**
|
|
161
|
+
* Status of every harness, in registry order.
|
|
162
|
+
*
|
|
163
|
+
* @returns Statuses
|
|
164
|
+
*/
|
|
165
|
+
listStatuses(): Promise<HarnessStatus[]>;
|
|
166
|
+
/**
|
|
167
|
+
* Required system tools (jq).
|
|
168
|
+
*
|
|
169
|
+
* @returns One entry per tool
|
|
170
|
+
*/
|
|
171
|
+
getSystemTools(): SystemToolStatus[];
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=harness-status.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-status.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness-status.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness status — is each harness installed, which version, is a newer one
|
|
3
|
+
* published, and is it logged in?
|
|
4
|
+
*
|
|
5
|
+
* Detection reads files, env var names and the exit codes of probe commands;
|
|
6
|
+
* it never prints or returns a secret. Login sources are labels such as
|
|
7
|
+
* `crewly-subscription` or `macos-keychain`.
|
|
8
|
+
*
|
|
9
|
+
* - Claude Code: a credential Crewly stores, `CLAUDE_CODE_OAUTH_TOKEN` /
|
|
10
|
+
* `ANTHROPIC_API_KEY` in the env, `~/.claude/.credentials.json`, or the macOS
|
|
11
|
+
* keychain item "Claude Code-credentials" (existence only: `security
|
|
12
|
+
* find-generic-password -s …` without `-w`/`-g`, so no secret is printed).
|
|
13
|
+
* - Codex: `codex login status`; falls back to `$CODEX_HOME/auth.json`.
|
|
14
|
+
* - Gemini CLI (detect only): Google-login credentials file or an API key env var.
|
|
15
|
+
*
|
|
16
|
+
* @module services/harness/harness-status.service
|
|
17
|
+
*/
|
|
18
|
+
import * as fs from 'fs';
|
|
19
|
+
import * as os from 'os';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { HARNESS_CONSTANTS } from '../../constants.js';
|
|
22
|
+
import { getClaudeConfigFile, getClaudeCredentialsFile } from './claude-config.utils.js';
|
|
23
|
+
import { getHarnessCredentialsStore } from './harness-credentials.store.js';
|
|
24
|
+
import { buildHarnessPath, buildNpmPath, resolveExecutable, runCommand } from './harness-exec.utils.js';
|
|
25
|
+
import { getHarnessDefinition, listHarnessDefinitions, toPublicLoginMethods } from './harness-registry.js';
|
|
26
|
+
import { SILENT_HARNESS_LOGGER, } from './harness.types.js';
|
|
27
|
+
/** Exit code of `security find-generic-password` when the item does not exist. */
|
|
28
|
+
const KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE = 44;
|
|
29
|
+
/**
|
|
30
|
+
* Pull a version number out of `--version` output.
|
|
31
|
+
*
|
|
32
|
+
* @param output - Command output, e.g. `2.1.282 (Claude Code)` or `codex-cli 0.156.1`
|
|
33
|
+
* @returns The version, or null
|
|
34
|
+
*/
|
|
35
|
+
export function parseVersion(output) {
|
|
36
|
+
const match = HARNESS_CONSTANTS.VERSION_PATTERN.exec(output);
|
|
37
|
+
return match ? match[0] : null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compare two dotted versions numerically (pre-release suffixes ignored).
|
|
41
|
+
*
|
|
42
|
+
* @param a - Version
|
|
43
|
+
* @param b - Version
|
|
44
|
+
* @returns Positive when a > b, negative when a < b, 0 when equal
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* compareVersions('2.1.282', '2.1.99'); // > 0
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export function compareVersions(a, b) {
|
|
52
|
+
const parts = (value) => value
|
|
53
|
+
.split(/[-+]/)[0]
|
|
54
|
+
.split('.')
|
|
55
|
+
.map((part) => Number.parseInt(part, 10) || 0);
|
|
56
|
+
const left = parts(a);
|
|
57
|
+
const right = parts(b);
|
|
58
|
+
for (let i = 0; i < Math.max(left.length, right.length); i++) {
|
|
59
|
+
const diff = (left[i] ?? 0) - (right[i] ?? 0);
|
|
60
|
+
if (diff !== 0)
|
|
61
|
+
return diff;
|
|
62
|
+
}
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Classify `codex login status` output.
|
|
67
|
+
*
|
|
68
|
+
* @param output - stdout + stderr (may mention a masked key; never returned)
|
|
69
|
+
* @returns `chatgpt`, `api_key` or `codex`
|
|
70
|
+
*/
|
|
71
|
+
export function parseCodexLoginSource(output) {
|
|
72
|
+
if (/chatgpt/i.test(output))
|
|
73
|
+
return 'chatgpt';
|
|
74
|
+
if (/api\s*key/i.test(output))
|
|
75
|
+
return 'api_key';
|
|
76
|
+
return 'codex';
|
|
77
|
+
}
|
|
78
|
+
/** Detects install, version and login state of each harness. */
|
|
79
|
+
export class HarnessStatusService {
|
|
80
|
+
run;
|
|
81
|
+
env;
|
|
82
|
+
homeDir;
|
|
83
|
+
platform;
|
|
84
|
+
fileExists;
|
|
85
|
+
resolveCommand;
|
|
86
|
+
credentials;
|
|
87
|
+
now;
|
|
88
|
+
logger;
|
|
89
|
+
latestCache = new Map();
|
|
90
|
+
/**
|
|
91
|
+
* @param deps - Injectable dependencies (all optional)
|
|
92
|
+
*/
|
|
93
|
+
constructor(deps = {}) {
|
|
94
|
+
this.run = deps.run ?? runCommand;
|
|
95
|
+
this.env = deps.env ?? process.env;
|
|
96
|
+
this.homeDir = deps.homeDir ?? os.homedir();
|
|
97
|
+
this.platform = deps.platform ?? process.platform;
|
|
98
|
+
this.fileExists = deps.fileExists ?? ((file) => fs.existsSync(file));
|
|
99
|
+
this.resolveCommand = deps.resolveCommand ?? ((command) => resolveExecutable(command, buildHarnessPath(this.env.PATH, this.homeDir)));
|
|
100
|
+
this.credentials = deps.credentials ?? getHarnessCredentialsStore();
|
|
101
|
+
this.now = deps.now ?? Date.now;
|
|
102
|
+
this.logger = deps.logger ?? SILENT_HARNESS_LOGGER;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Environment for probe commands (harness PATH).
|
|
106
|
+
*
|
|
107
|
+
* @returns Env copy
|
|
108
|
+
*/
|
|
109
|
+
probeEnv() {
|
|
110
|
+
return { ...this.env, PATH: buildHarnessPath(this.env.PATH, this.homeDir) };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Whether the binary is on PATH and which version it reports.
|
|
114
|
+
*
|
|
115
|
+
* @param def - Harness definition
|
|
116
|
+
* @returns Installed facts
|
|
117
|
+
*/
|
|
118
|
+
async getInstalledInfo(def) {
|
|
119
|
+
const binary = this.resolveCommand(def.command);
|
|
120
|
+
if (!binary)
|
|
121
|
+
return { installed: false, path: null, version: null };
|
|
122
|
+
const result = await this.run(binary, def.versionArgs, { env: this.probeEnv(), timeoutMs: HARNESS_CONSTANTS.PROBE_TIMEOUT_MS });
|
|
123
|
+
// Only a clean exit reports a version: a broken install's crash output
|
|
124
|
+
// ("Node.js v22.14.0") must not pass for the harness's version.
|
|
125
|
+
const version = result.code === 0 ? parseVersion(`${result.stdout}\n${result.stderr}`) : null;
|
|
126
|
+
return { installed: true, path: binary, version };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Latest published version (`npm view <pkg> version`), cached.
|
|
130
|
+
*
|
|
131
|
+
* @param def - Harness definition
|
|
132
|
+
* @returns The version, or null when npm could not be asked
|
|
133
|
+
*/
|
|
134
|
+
async getLatestVersion(def) {
|
|
135
|
+
const cached = this.latestCache.get(def.npmPackage);
|
|
136
|
+
if (cached && cached.expiresAt > this.now())
|
|
137
|
+
return cached.value;
|
|
138
|
+
const result = await this.run('npm', ['view', def.npmPackage, 'version'], {
|
|
139
|
+
env: { ...this.env, PATH: buildNpmPath(this.env.PATH, this.homeDir) },
|
|
140
|
+
timeoutMs: HARNESS_CONSTANTS.NPM_VIEW_TIMEOUT_MS,
|
|
141
|
+
});
|
|
142
|
+
const value = result.code === 0 ? parseVersion(result.stdout) : null;
|
|
143
|
+
if (value === null) {
|
|
144
|
+
this.logger.debug('npm view failed', { pkg: def.npmPackage, code: result.code, error: result.error });
|
|
145
|
+
}
|
|
146
|
+
this.latestCache.set(def.npmPackage, {
|
|
147
|
+
value,
|
|
148
|
+
expiresAt: this.now() + (value ? HARNESS_CONSTANTS.LATEST_VERSION_CACHE_TTL_MS : HARNESS_CONSTANTS.LATEST_VERSION_FAILURE_TTL_MS),
|
|
149
|
+
});
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
/** Forget cached latest versions. */
|
|
153
|
+
clearLatestVersionCache() {
|
|
154
|
+
this.latestCache.clear();
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* First env var (by name) that has a value.
|
|
158
|
+
*
|
|
159
|
+
* @param names - Candidates
|
|
160
|
+
* @returns The name, or null
|
|
161
|
+
*/
|
|
162
|
+
firstSetEnv(names) {
|
|
163
|
+
return names.find((name) => (this.env[name] ?? '').trim().length > 0) ?? null;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Claude Code login detection.
|
|
167
|
+
*
|
|
168
|
+
* @returns Login facts
|
|
169
|
+
*/
|
|
170
|
+
async getClaudeLogin() {
|
|
171
|
+
const stored = this.credentials.getClaudeCredentialKind();
|
|
172
|
+
if (stored === 'oauth_token')
|
|
173
|
+
return { loginState: 'logged_in', loginSource: 'crewly-subscription' };
|
|
174
|
+
if (stored === 'api_key')
|
|
175
|
+
return { loginState: 'logged_in', loginSource: 'crewly-api-key' };
|
|
176
|
+
const envName = this.firstSetEnv([HARNESS_CONSTANTS.CLAUDE.OAUTH_TOKEN_ENV, HARNESS_CONSTANTS.CLAUDE.API_KEY_ENV]);
|
|
177
|
+
if (envName)
|
|
178
|
+
return { loginState: 'logged_in', loginSource: `env:${envName}` };
|
|
179
|
+
const location = { env: this.env, homeDir: this.homeDir };
|
|
180
|
+
if (this.fileExists(getClaudeCredentialsFile(location))) {
|
|
181
|
+
return { loginState: 'logged_in', loginSource: 'claude-credentials-file' };
|
|
182
|
+
}
|
|
183
|
+
if (this.platform === 'darwin') {
|
|
184
|
+
// Existence only: no -w / -g, so the secret is never printed.
|
|
185
|
+
const result = await this.run('security', ['find-generic-password', '-s', HARNESS_CONSTANTS.CLAUDE.KEYCHAIN_SERVICE], {
|
|
186
|
+
env: this.probeEnv(),
|
|
187
|
+
timeoutMs: HARNESS_CONSTANTS.PROBE_TIMEOUT_MS,
|
|
188
|
+
});
|
|
189
|
+
if (result.code === 0)
|
|
190
|
+
return { loginState: 'logged_in', loginSource: 'macos-keychain' };
|
|
191
|
+
if (result.code !== KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE) {
|
|
192
|
+
return { loginState: 'unknown', loginSource: null };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// A config file naming an account is a weaker signal than a credential;
|
|
196
|
+
// report it as unknown rather than claiming a working login.
|
|
197
|
+
if (this.fileExists(getClaudeConfigFile(location)) && this.claudeConfigHasAccount(getClaudeConfigFile(location))) {
|
|
198
|
+
return { loginState: 'unknown', loginSource: 'claude-config' };
|
|
199
|
+
}
|
|
200
|
+
return { loginState: 'logged_out', loginSource: null };
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Whether `~/.claude.json` records an OAuth account or a primary API key.
|
|
204
|
+
*
|
|
205
|
+
* @param file - Config path
|
|
206
|
+
* @returns True when an account is recorded
|
|
207
|
+
*/
|
|
208
|
+
claudeConfigHasAccount(file) {
|
|
209
|
+
try {
|
|
210
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
211
|
+
return Boolean(parsed.oauthAccount) || Boolean(parsed.primaryApiKey);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Codex login detection.
|
|
219
|
+
*
|
|
220
|
+
* @param binary - Codex binary path, when installed
|
|
221
|
+
* @returns Login facts
|
|
222
|
+
*/
|
|
223
|
+
async getCodexLogin(binary) {
|
|
224
|
+
const codexHome = this.env[HARNESS_CONSTANTS.CODEX.HOME_ENV] || path.join(this.homeDir, HARNESS_CONSTANTS.CODEX.HOME_DIR);
|
|
225
|
+
const authFileExists = this.fileExists(path.join(codexHome, HARNESS_CONSTANTS.CODEX.AUTH_FILE));
|
|
226
|
+
if (binary) {
|
|
227
|
+
const result = await this.run(binary, ['login', 'status'], { env: this.probeEnv(), timeoutMs: HARNESS_CONSTANTS.PROBE_TIMEOUT_MS });
|
|
228
|
+
if (result.code === 0) {
|
|
229
|
+
return { loginState: 'logged_in', loginSource: parseCodexLoginSource(`${result.stdout}\n${result.stderr}`) };
|
|
230
|
+
}
|
|
231
|
+
if (result.code !== null)
|
|
232
|
+
return { loginState: 'logged_out', loginSource: null };
|
|
233
|
+
this.logger.debug('codex login status could not run', { error: result.error });
|
|
234
|
+
}
|
|
235
|
+
return authFileExists ? { loginState: 'logged_in', loginSource: 'codex-auth-file' } : { loginState: binary ? 'unknown' : 'logged_out', loginSource: null };
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Gemini CLI login detection (detect only).
|
|
239
|
+
*
|
|
240
|
+
* @returns Login facts
|
|
241
|
+
*/
|
|
242
|
+
getGeminiLogin() {
|
|
243
|
+
if (this.fileExists(path.join(this.homeDir, HARNESS_CONSTANTS.GEMINI.OAUTH_CREDS_FILE))) {
|
|
244
|
+
return { loginState: 'logged_in', loginSource: 'gemini-google-login' };
|
|
245
|
+
}
|
|
246
|
+
const envName = this.firstSetEnv(HARNESS_CONSTANTS.GEMINI.KEY_ENV);
|
|
247
|
+
if (envName)
|
|
248
|
+
return { loginState: 'logged_in', loginSource: `env:${envName}` };
|
|
249
|
+
return { loginState: 'unknown', loginSource: null };
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Login state of a harness.
|
|
253
|
+
*
|
|
254
|
+
* @param def - Harness definition
|
|
255
|
+
* @param binary - Binary path when installed (Codex asks the binary itself)
|
|
256
|
+
* @returns Login facts
|
|
257
|
+
*/
|
|
258
|
+
async getLoginInfo(def, binary) {
|
|
259
|
+
try {
|
|
260
|
+
switch (def.id) {
|
|
261
|
+
case HARNESS_CONSTANTS.IDS.CLAUDE_CODE:
|
|
262
|
+
return await this.getClaudeLogin();
|
|
263
|
+
case HARNESS_CONSTANTS.IDS.CODEX_CLI:
|
|
264
|
+
return await this.getCodexLogin(binary);
|
|
265
|
+
default:
|
|
266
|
+
return this.getGeminiLogin();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
this.logger.warn('Harness login detection failed', { harnessId: def.id, error: error instanceof Error ? error.message : String(error) });
|
|
271
|
+
return { loginState: 'unknown', loginSource: null };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Full status of one harness.
|
|
276
|
+
*
|
|
277
|
+
* @param id - Harness id
|
|
278
|
+
* @returns The status
|
|
279
|
+
* @throws Error for an unknown harness id
|
|
280
|
+
*/
|
|
281
|
+
async getStatus(id) {
|
|
282
|
+
const def = getHarnessDefinition(id);
|
|
283
|
+
if (!def)
|
|
284
|
+
throw new Error(`Unknown harness: ${id}`);
|
|
285
|
+
const [installedInfo, latestVersion] = await Promise.all([this.getInstalledInfo(def), this.getLatestVersion(def)]);
|
|
286
|
+
const login = await this.getLoginInfo(def, installedInfo.path);
|
|
287
|
+
const updateAvailable = Boolean(installedInfo.installed && installedInfo.version && latestVersion && compareVersions(latestVersion, installedInfo.version) > 0);
|
|
288
|
+
return {
|
|
289
|
+
id: def.id,
|
|
290
|
+
displayName: def.displayName,
|
|
291
|
+
installed: installedInfo.installed,
|
|
292
|
+
version: installedInfo.version,
|
|
293
|
+
latestVersion,
|
|
294
|
+
updateAvailable,
|
|
295
|
+
loginState: login.loginState,
|
|
296
|
+
loginSource: login.loginSource,
|
|
297
|
+
loginMethods: toPublicLoginMethods(def),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Status of every harness, in registry order.
|
|
302
|
+
*
|
|
303
|
+
* @returns Statuses
|
|
304
|
+
*/
|
|
305
|
+
async listStatuses() {
|
|
306
|
+
return Promise.all(listHarnessDefinitions().map((def) => this.getStatus(def.id)));
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Required system tools (jq).
|
|
310
|
+
*
|
|
311
|
+
* @returns One entry per tool
|
|
312
|
+
*/
|
|
313
|
+
getSystemTools() {
|
|
314
|
+
const jq = HARNESS_CONSTANTS.SYSTEM_TOOLS.JQ;
|
|
315
|
+
return [
|
|
316
|
+
{
|
|
317
|
+
id: jq.ID,
|
|
318
|
+
installed: this.resolveCommand(jq.ID) !== null,
|
|
319
|
+
installHint: this.platform === 'darwin' ? jq.INSTALL_HINT_MACOS : jq.INSTALL_HINT_LINUX,
|
|
320
|
+
},
|
|
321
|
+
];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=harness-status.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-status.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness-status.service.ts"],"names":[],"mappings":"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"}
|