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.
Files changed (165) hide show
  1. package/dist/backend/backend/src/constants.d.ts +118 -0
  2. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  3. package/dist/backend/backend/src/constants.js +118 -0
  4. package/dist/backend/backend/src/constants.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/harness/harness.controller.d.ts +54 -0
  6. package/dist/backend/backend/src/controllers/harness/harness.controller.d.ts.map +1 -0
  7. package/dist/backend/backend/src/controllers/harness/harness.controller.js +204 -0
  8. package/dist/backend/backend/src/controllers/harness/harness.controller.js.map +1 -0
  9. package/dist/backend/backend/src/controllers/harness/harness.routes.d.ts +27 -0
  10. package/dist/backend/backend/src/controllers/harness/harness.routes.d.ts.map +1 -0
  11. package/dist/backend/backend/src/controllers/harness/harness.routes.js +43 -0
  12. package/dist/backend/backend/src/controllers/harness/harness.routes.js.map +1 -0
  13. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  14. package/dist/backend/backend/src/routes/api.routes.js +4 -0
  15. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  16. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +5 -0
  17. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  18. package/dist/backend/backend/src/services/agent/agent-registration.service.js +7 -0
  19. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  20. package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +2 -1
  21. package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
  22. package/dist/backend/backend/src/services/cloud/cloud-client.service.js +4 -3
  23. package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
  24. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
  25. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +14 -0
  26. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
  27. package/dist/backend/backend/src/services/harness/claude-config.utils.d.ts +67 -0
  28. package/dist/backend/backend/src/services/harness/claude-config.utils.d.ts.map +1 -0
  29. package/dist/backend/backend/src/services/harness/claude-config.utils.js +118 -0
  30. package/dist/backend/backend/src/services/harness/claude-config.utils.js.map +1 -0
  31. package/dist/backend/backend/src/services/harness/harness-api-key.service.d.ts +99 -0
  32. package/dist/backend/backend/src/services/harness/harness-api-key.service.d.ts.map +1 -0
  33. package/dist/backend/backend/src/services/harness/harness-api-key.service.js +157 -0
  34. package/dist/backend/backend/src/services/harness/harness-api-key.service.js.map +1 -0
  35. package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts +135 -0
  36. package/dist/backend/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -0
  37. package/dist/backend/backend/src/services/harness/harness-credentials.store.js +208 -0
  38. package/dist/backend/backend/src/services/harness/harness-credentials.store.js.map +1 -0
  39. package/dist/backend/backend/src/services/harness/harness-exec.utils.d.ts +85 -0
  40. package/dist/backend/backend/src/services/harness/harness-exec.utils.d.ts.map +1 -0
  41. package/dist/backend/backend/src/services/harness/harness-exec.utils.js +183 -0
  42. package/dist/backend/backend/src/services/harness/harness-exec.utils.js.map +1 -0
  43. package/dist/backend/backend/src/services/harness/harness-install.service.d.ts +106 -0
  44. package/dist/backend/backend/src/services/harness/harness-install.service.d.ts.map +1 -0
  45. package/dist/backend/backend/src/services/harness/harness-install.service.js +205 -0
  46. package/dist/backend/backend/src/services/harness/harness-install.service.js.map +1 -0
  47. package/dist/backend/backend/src/services/harness/harness-registry.d.ts +86 -0
  48. package/dist/backend/backend/src/services/harness/harness-registry.d.ts.map +1 -0
  49. package/dist/backend/backend/src/services/harness/harness-registry.js +121 -0
  50. package/dist/backend/backend/src/services/harness/harness-registry.js.map +1 -0
  51. package/dist/backend/backend/src/services/harness/harness-status.service.d.ts +173 -0
  52. package/dist/backend/backend/src/services/harness/harness-status.service.d.ts.map +1 -0
  53. package/dist/backend/backend/src/services/harness/harness-status.service.js +324 -0
  54. package/dist/backend/backend/src/services/harness/harness-status.service.js.map +1 -0
  55. package/dist/backend/backend/src/services/harness/harness.service.d.ts +146 -0
  56. package/dist/backend/backend/src/services/harness/harness.service.d.ts.map +1 -0
  57. package/dist/backend/backend/src/services/harness/harness.service.js +193 -0
  58. package/dist/backend/backend/src/services/harness/harness.service.js.map +1 -0
  59. package/dist/backend/backend/src/services/harness/harness.types.d.ts +138 -0
  60. package/dist/backend/backend/src/services/harness/harness.types.d.ts.map +1 -0
  61. package/dist/backend/backend/src/services/harness/harness.types.js +51 -0
  62. package/dist/backend/backend/src/services/harness/harness.types.js.map +1 -0
  63. package/dist/backend/backend/src/services/harness/login-broker.service.d.ts +238 -0
  64. package/dist/backend/backend/src/services/harness/login-broker.service.d.ts.map +1 -0
  65. package/dist/backend/backend/src/services/harness/login-broker.service.js +495 -0
  66. package/dist/backend/backend/src/services/harness/login-broker.service.js.map +1 -0
  67. package/dist/backend/backend/src/services/harness/login-rules.d.ts +162 -0
  68. package/dist/backend/backend/src/services/harness/login-rules.d.ts.map +1 -0
  69. package/dist/backend/backend/src/services/harness/login-rules.js +344 -0
  70. package/dist/backend/backend/src/services/harness/login-rules.js.map +1 -0
  71. package/dist/backend/backend/src/services/harness/orc-harness.store.d.ts +59 -0
  72. package/dist/backend/backend/src/services/harness/orc-harness.store.d.ts.map +1 -0
  73. package/dist/backend/backend/src/services/harness/orc-harness.store.js +108 -0
  74. package/dist/backend/backend/src/services/harness/orc-harness.store.js.map +1 -0
  75. package/dist/backend/build-info.json +2 -2
  76. package/dist/cli/backend/src/constants.d.ts +118 -0
  77. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  78. package/dist/cli/backend/src/constants.js +118 -0
  79. package/dist/cli/backend/src/constants.js.map +1 -1
  80. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +5 -0
  81. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  82. package/dist/cli/backend/src/services/agent/agent-registration.service.js +7 -0
  83. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  84. package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts +2 -1
  85. package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
  86. package/dist/cli/backend/src/services/cloud/cloud-client.service.js +4 -3
  87. package/dist/cli/backend/src/services/cloud/cloud-client.service.js.map +1 -1
  88. package/dist/cli/backend/src/services/harness/claude-config.utils.d.ts +67 -0
  89. package/dist/cli/backend/src/services/harness/claude-config.utils.d.ts.map +1 -0
  90. package/dist/cli/backend/src/services/harness/claude-config.utils.js +118 -0
  91. package/dist/cli/backend/src/services/harness/claude-config.utils.js.map +1 -0
  92. package/dist/cli/backend/src/services/harness/harness-api-key.service.d.ts +99 -0
  93. package/dist/cli/backend/src/services/harness/harness-api-key.service.d.ts.map +1 -0
  94. package/dist/cli/backend/src/services/harness/harness-api-key.service.js +157 -0
  95. package/dist/cli/backend/src/services/harness/harness-api-key.service.js.map +1 -0
  96. package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts +135 -0
  97. package/dist/cli/backend/src/services/harness/harness-credentials.store.d.ts.map +1 -0
  98. package/dist/cli/backend/src/services/harness/harness-credentials.store.js +208 -0
  99. package/dist/cli/backend/src/services/harness/harness-credentials.store.js.map +1 -0
  100. package/dist/cli/backend/src/services/harness/harness-exec.utils.d.ts +85 -0
  101. package/dist/cli/backend/src/services/harness/harness-exec.utils.d.ts.map +1 -0
  102. package/dist/cli/backend/src/services/harness/harness-exec.utils.js +183 -0
  103. package/dist/cli/backend/src/services/harness/harness-exec.utils.js.map +1 -0
  104. package/dist/cli/backend/src/services/harness/harness-install.service.d.ts +106 -0
  105. package/dist/cli/backend/src/services/harness/harness-install.service.d.ts.map +1 -0
  106. package/dist/cli/backend/src/services/harness/harness-install.service.js +205 -0
  107. package/dist/cli/backend/src/services/harness/harness-install.service.js.map +1 -0
  108. package/dist/cli/backend/src/services/harness/harness-registry.d.ts +86 -0
  109. package/dist/cli/backend/src/services/harness/harness-registry.d.ts.map +1 -0
  110. package/dist/cli/backend/src/services/harness/harness-registry.js +121 -0
  111. package/dist/cli/backend/src/services/harness/harness-registry.js.map +1 -0
  112. package/dist/cli/backend/src/services/harness/harness-status.service.d.ts +173 -0
  113. package/dist/cli/backend/src/services/harness/harness-status.service.d.ts.map +1 -0
  114. package/dist/cli/backend/src/services/harness/harness-status.service.js +324 -0
  115. package/dist/cli/backend/src/services/harness/harness-status.service.js.map +1 -0
  116. package/dist/cli/backend/src/services/harness/harness.service.d.ts +146 -0
  117. package/dist/cli/backend/src/services/harness/harness.service.d.ts.map +1 -0
  118. package/dist/cli/backend/src/services/harness/harness.service.js +193 -0
  119. package/dist/cli/backend/src/services/harness/harness.service.js.map +1 -0
  120. package/dist/cli/backend/src/services/harness/harness.types.d.ts +138 -0
  121. package/dist/cli/backend/src/services/harness/harness.types.d.ts.map +1 -0
  122. package/dist/cli/backend/src/services/harness/harness.types.js +51 -0
  123. package/dist/cli/backend/src/services/harness/harness.types.js.map +1 -0
  124. package/dist/cli/backend/src/services/harness/login-broker.service.d.ts +238 -0
  125. package/dist/cli/backend/src/services/harness/login-broker.service.d.ts.map +1 -0
  126. package/dist/cli/backend/src/services/harness/login-broker.service.js +495 -0
  127. package/dist/cli/backend/src/services/harness/login-broker.service.js.map +1 -0
  128. package/dist/cli/backend/src/services/harness/login-rules.d.ts +162 -0
  129. package/dist/cli/backend/src/services/harness/login-rules.d.ts.map +1 -0
  130. package/dist/cli/backend/src/services/harness/login-rules.js +344 -0
  131. package/dist/cli/backend/src/services/harness/login-rules.js.map +1 -0
  132. package/dist/cli/backend/src/services/harness/orc-harness.store.d.ts +59 -0
  133. package/dist/cli/backend/src/services/harness/orc-harness.store.d.ts.map +1 -0
  134. package/dist/cli/backend/src/services/harness/orc-harness.store.js +108 -0
  135. package/dist/cli/backend/src/services/harness/orc-harness.store.js.map +1 -0
  136. package/dist/cli/cli/src/commands/harness-setup.d.ts +159 -0
  137. package/dist/cli/cli/src/commands/harness-setup.d.ts.map +1 -0
  138. package/dist/cli/cli/src/commands/harness-setup.js +377 -0
  139. package/dist/cli/cli/src/commands/harness-setup.js.map +1 -0
  140. package/dist/cli/cli/src/commands/harness.d.ts +56 -0
  141. package/dist/cli/cli/src/commands/harness.d.ts.map +1 -0
  142. package/dist/cli/cli/src/commands/harness.js +97 -0
  143. package/dist/cli/cli/src/commands/harness.js.map +1 -0
  144. package/dist/cli/cli/src/commands/onboard.d.ts +108 -50
  145. package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
  146. package/dist/cli/cli/src/commands/onboard.js +200 -191
  147. package/dist/cli/cli/src/commands/onboard.js.map +1 -1
  148. package/dist/cli/cli/src/constants.d.ts +18 -0
  149. package/dist/cli/cli/src/constants.d.ts.map +1 -1
  150. package/dist/cli/cli/src/constants.js +18 -0
  151. package/dist/cli/cli/src/constants.js.map +1 -1
  152. package/dist/cli/cli/src/index.js +22 -3
  153. package/dist/cli/cli/src/index.js.map +1 -1
  154. package/dist/cli/cli/src/utils/harness-engine.d.ts +99 -0
  155. package/dist/cli/cli/src/utils/harness-engine.d.ts.map +1 -0
  156. package/dist/cli/cli/src/utils/harness-engine.js +143 -0
  157. package/dist/cli/cli/src/utils/harness-engine.js.map +1 -0
  158. package/dist/cli/cli/src/utils/prompt-io.d.ts +25 -0
  159. package/dist/cli/cli/src/utils/prompt-io.d.ts.map +1 -0
  160. package/dist/cli/cli/src/utils/prompt-io.js +47 -0
  161. package/dist/cli/cli/src/utils/prompt-io.js.map +1 -0
  162. package/frontend/dist/assets/{index-8327e63e.css → index-0a2f783c.css} +1 -1
  163. package/frontend/dist/assets/{index-daf43f1a.js → index-aaf65055.js} +309 -309
  164. package/frontend/dist/index.html +2 -2
  165. 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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"}