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,193 @@
1
+ /**
2
+ * Harness service — the one engine behind both setup front ends.
3
+ *
4
+ * The REST API (`/api/harness`, used by the web setup page) and the `crewly`
5
+ * CLI (`crewly onboard`, `crewly login`, `crewly harness`) both call this
6
+ * facade, so detection, install, orc choice and login behave identically.
7
+ * The backend uses the process-wide {@link getHarnessService}; the CLI builds
8
+ * its own instance with {@link createHarnessService} (silent logger, no
9
+ * backend running required).
10
+ *
11
+ * @module services/harness/harness.service
12
+ */
13
+ import { LoggerService } from '../core/logger.service.js';
14
+ import { HarnessApiKeyService } from './harness-api-key.service.js';
15
+ import { HarnessInstallService } from './harness-install.service.js';
16
+ import { getHarnessDefinition } from './harness-registry.js';
17
+ import { HarnessStatusService } from './harness-status.service.js';
18
+ import { SILENT_HARNESS_LOGGER, isHarnessId, } from './harness.types.js';
19
+ import { LoginBrokerService } from './login-broker.service.js';
20
+ import { OrcHarnessStore } from './orc-harness.store.js';
21
+ /** Error for an id that is not a harness (REST: 404). */
22
+ export class UnknownHarnessError extends Error {
23
+ id;
24
+ /**
25
+ * @param id - The id that was asked for
26
+ */
27
+ constructor(id) {
28
+ super(`Unknown harness: ${id}`);
29
+ this.id = id;
30
+ this.name = 'UnknownHarnessError';
31
+ }
32
+ }
33
+ /** Facade over status, install, orc choice, broker login and API-key login. */
34
+ export class HarnessService {
35
+ status;
36
+ install;
37
+ broker;
38
+ apiKeys;
39
+ orc;
40
+ /**
41
+ * @param parts - Service parts
42
+ */
43
+ constructor(parts) {
44
+ this.status = parts.status;
45
+ this.install = parts.install;
46
+ this.broker = parts.broker;
47
+ this.apiKeys = parts.apiKeys;
48
+ this.orc = parts.orc;
49
+ }
50
+ /**
51
+ * Validate a harness id.
52
+ *
53
+ * @param id - Candidate
54
+ * @returns The id, typed
55
+ * @throws UnknownHarnessError for an unknown id
56
+ */
57
+ requireHarnessId(id) {
58
+ if (!isHarnessId(id))
59
+ throw new UnknownHarnessError(id);
60
+ return id;
61
+ }
62
+ /**
63
+ * Everything the setup screen needs.
64
+ *
65
+ * @returns Harness statuses, the orc harness and system tools
66
+ */
67
+ async getOverview() {
68
+ const [harnesses, orcHarness] = await Promise.all([this.status.listStatuses(), this.orc.get()]);
69
+ return { harnesses, orcHarness, systemTools: this.status.getSystemTools() };
70
+ }
71
+ /**
72
+ * Status of one harness.
73
+ *
74
+ * @param id - Harness id
75
+ * @returns The status
76
+ * @throws UnknownHarnessError for an unknown id
77
+ */
78
+ async getStatus(id) {
79
+ return this.status.getStatus(this.requireHarnessId(id));
80
+ }
81
+ /**
82
+ * Start installing (or updating) a harness.
83
+ *
84
+ * @param id - Harness id
85
+ * @returns The install job
86
+ * @throws UnknownHarnessError for an unknown id
87
+ */
88
+ startInstall(id) {
89
+ return this.install.startInstall(this.requireHarnessId(id));
90
+ }
91
+ /**
92
+ * Read an install job.
93
+ *
94
+ * @param jobId - Job id
95
+ * @returns The job
96
+ * @throws HarnessInstallError job_not_found
97
+ */
98
+ getInstallJob(jobId) {
99
+ return this.install.getJob(jobId);
100
+ }
101
+ /**
102
+ * Set the orchestrator's harness.
103
+ *
104
+ * @param id - Harness id
105
+ * @returns The recorded harness id
106
+ * @throws UnknownHarnessError for an unknown id
107
+ */
108
+ async setOrcHarness(id) {
109
+ return this.orc.set(this.requireHarnessId(id));
110
+ }
111
+ /**
112
+ * Start a broker login.
113
+ *
114
+ * @param id - Harness id
115
+ * @param method - Broker login method
116
+ * @returns The login session
117
+ * @throws UnknownHarnessError | LoginBrokerError
118
+ */
119
+ startLogin(id, method) {
120
+ return this.broker.start(this.requireHarnessId(id), method);
121
+ }
122
+ /**
123
+ * Store an API key for a harness and return its fresh status.
124
+ *
125
+ * @param id - Harness id
126
+ * @param key - The key (never echoed)
127
+ * @returns The harness status after login
128
+ * @throws UnknownHarnessError | HarnessApiKeyError
129
+ */
130
+ async submitApiKey(id, key) {
131
+ const harnessId = this.requireHarnessId(id);
132
+ await this.apiKeys.submit(harnessId, key);
133
+ return this.status.getStatus(harnessId);
134
+ }
135
+ }
136
+ /**
137
+ * Build a harness service with real dependencies.
138
+ *
139
+ * Codex broker logins are confirmed with `codex login status` through the
140
+ * status service.
141
+ *
142
+ * @param options - Logger, settings updater, env
143
+ * @returns A new service
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * const harness = createHarnessService({ logger: SILENT_HARNESS_LOGGER });
148
+ * const overview = await harness.getOverview();
149
+ * ```
150
+ */
151
+ export function createHarnessService(options = {}) {
152
+ const logger = options.logger ?? SILENT_HARNESS_LOGGER;
153
+ const env = options.env ?? process.env;
154
+ const status = new HarnessStatusService({ logger, env });
155
+ const install = new HarnessInstallService({ logger, env });
156
+ const broker = new LoginBrokerService({
157
+ logger,
158
+ env,
159
+ verify: async (harnessId) => {
160
+ const def = getHarnessDefinition(harnessId);
161
+ if (!def)
162
+ return false;
163
+ const installed = await status.getInstalledInfo(def);
164
+ const login = await status.getLoginInfo(def, installed.path);
165
+ return login.loginState === 'logged_in';
166
+ },
167
+ });
168
+ const apiKeys = new HarnessApiKeyService({ logger, env });
169
+ const orc = new OrcHarnessStore(options.updateDefaultRuntime ? { updateDefaultRuntime: options.updateDefaultRuntime } : {});
170
+ return new HarnessService({ status, install, broker, apiKeys, orc });
171
+ }
172
+ /** Backend singleton. */
173
+ let backendInstance = null;
174
+ /**
175
+ * The backend's harness service (logs through LoggerService).
176
+ *
177
+ * @returns The singleton
178
+ */
179
+ export function getHarnessService() {
180
+ if (!backendInstance) {
181
+ backendInstance = createHarnessService({ logger: LoggerService.getInstance().createComponentLogger('Harness') });
182
+ }
183
+ return backendInstance;
184
+ }
185
+ /**
186
+ * Replace or clear the backend singleton (tests).
187
+ *
188
+ * @param service - Service to use, or null to clear
189
+ */
190
+ export function setHarnessServiceForTesting(service) {
191
+ backendInstance = service;
192
+ }
193
+ //# sourceMappingURL=harness.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Harness onboarding types — the shapes shared by the backend REST API
3
+ * (`/api/harness`), the `crewly` CLI and the web setup page.
4
+ *
5
+ * A "harness" is an agent CLI Crewly drives in a PTY: Claude Code, Codex or
6
+ * Gemini CLI. See specs/onboarding-harness-login.md for the contract.
7
+ *
8
+ * @module services/harness/harness.types
9
+ */
10
+ import { HARNESS_CONSTANTS } from '../../constants.js';
11
+ /** Harness id — equal to the matching `RuntimeType` value. */
12
+ export type HarnessId = (typeof HARNESS_CONSTANTS.IDS)[keyof typeof HARNESS_CONSTANTS.IDS];
13
+ /** Every harness id, in display order. */
14
+ export declare const HARNESS_IDS: readonly HarnessId[];
15
+ /** How the owner can log in to a harness. */
16
+ export type LoginMethodId = 'subscription' | 'api_key' | 'device';
17
+ /** Every login method id. */
18
+ export declare const LOGIN_METHOD_IDS: readonly LoginMethodId[];
19
+ /**
20
+ * How a front end drives a login method.
21
+ * - `broker`: Crewly runs the harness's login command in a PTY (login broker)
22
+ * - `api_key`: the owner pastes a key
23
+ */
24
+ export type LoginMethodKind = 'broker' | 'api_key';
25
+ /** A login method as exposed over the API. */
26
+ export interface HarnessLoginMethod {
27
+ id: LoginMethodId;
28
+ label: string;
29
+ kind: LoginMethodKind;
30
+ }
31
+ /** Login state reported for a harness. */
32
+ export type LoginState = 'logged_in' | 'logged_out' | 'unknown';
33
+ /** Status of one harness (`GET /api/harness`). */
34
+ export interface HarnessStatus {
35
+ id: HarnessId;
36
+ displayName: string;
37
+ installed: boolean;
38
+ version: string | null;
39
+ latestVersion: string | null;
40
+ updateAvailable: boolean;
41
+ loginState: LoginState;
42
+ /** Where the login was found (never a secret), e.g. `crewly-subscription`, `macos-keychain` */
43
+ loginSource: string | null;
44
+ loginMethods: HarnessLoginMethod[];
45
+ }
46
+ /** A required system tool (only jq today). */
47
+ export interface SystemToolStatus {
48
+ id: string;
49
+ installed: boolean;
50
+ installHint: string;
51
+ }
52
+ /** Body of `GET /api/harness`. */
53
+ export interface HarnessOverview {
54
+ harnesses: HarnessStatus[];
55
+ orcHarness: string | null;
56
+ systemTools: SystemToolStatus[];
57
+ }
58
+ /** State of an install job. */
59
+ export type InstallJobState = 'running' | 'succeeded' | 'failed';
60
+ /** An install job (`GET /api/harness/install/:jobId`). */
61
+ export interface InstallJob {
62
+ jobId: string;
63
+ harnessId: HarnessId;
64
+ state: InstallJobState;
65
+ log: string;
66
+ usedUserPrefix: boolean;
67
+ }
68
+ /** State of a login broker session. */
69
+ export type LoginSessionState = 'starting' | 'awaiting_user' | 'verifying' | 'succeeded' | 'failed' | 'timed_out' | 'cancelled';
70
+ /** Terminal login states: the PTY is gone and the session no longer changes. */
71
+ export declare const TERMINAL_LOGIN_STATES: readonly LoginSessionState[];
72
+ /** A login broker session as exposed to front ends. Never contains a secret. */
73
+ export interface LoginSession {
74
+ id: string;
75
+ harnessId: HarnessId;
76
+ method: LoginMethodId;
77
+ state: LoginSessionState;
78
+ url: string | null;
79
+ userCode: string | null;
80
+ /** True when the harness waits for the user to type/paste something (e.g. Claude's code) */
81
+ needsInput: boolean;
82
+ message: string | null;
83
+ /** Tail of the normalized terminal text, secrets redacted */
84
+ screen: string;
85
+ startedAt: string;
86
+ updatedAt: string;
87
+ }
88
+ /**
89
+ * Whether a value is a known harness id.
90
+ *
91
+ * @param value - Candidate
92
+ * @returns True for `claude-code`, `codex-cli` or `gemini-cli`
93
+ */
94
+ export declare function isHarnessId(value: unknown): value is HarnessId;
95
+ /**
96
+ * Whether a value is a known login method id.
97
+ *
98
+ * @param value - Candidate
99
+ * @returns True for `subscription`, `api_key` or `device`
100
+ */
101
+ export declare function isLoginMethodId(value: unknown): value is LoginMethodId;
102
+ /**
103
+ * Whether a login state is terminal (the session will not change again).
104
+ *
105
+ * @param state - Login session state
106
+ * @returns True for succeeded / failed / timed_out / cancelled
107
+ */
108
+ export declare function isTerminalLoginState(state: LoginSessionState): boolean;
109
+ /** Minimal logger the harness services accept (the CLI passes a silent one). */
110
+ export interface HarnessLogger {
111
+ info(message: string, context?: Record<string, unknown>): void;
112
+ warn(message: string, context?: Record<string, unknown>): void;
113
+ error(message: string, context?: Record<string, unknown>): void;
114
+ debug(message: string, context?: Record<string, unknown>): void;
115
+ }
116
+ /** A logger that drops everything (CLI default, tests). */
117
+ export declare const SILENT_HARNESS_LOGGER: HarnessLogger;
118
+ /** Result of running a command to completion. */
119
+ export interface CommandResult {
120
+ /** Exit code; null when the process could not be started or was killed */
121
+ code: number | null;
122
+ stdout: string;
123
+ stderr: string;
124
+ /** Spawn error message (ENOENT, timeout), when there was one */
125
+ error?: string;
126
+ }
127
+ /** Options for {@link RunCommand}. */
128
+ export interface RunCommandOptions {
129
+ env?: NodeJS.ProcessEnv;
130
+ timeoutMs?: number;
131
+ /** Written to the child's stdin, then stdin is closed (used for API keys; never argv) */
132
+ stdin?: string;
133
+ /** Streaming output callback (install log) */
134
+ onOutput?: (chunk: string) => void;
135
+ }
136
+ /** Runs a command without a shell and resolves when it exits. Never rejects. */
137
+ export type RunCommand = (command: string, args: readonly string[], options?: RunCommandOptions) => Promise<CommandResult>;
138
+ //# sourceMappingURL=harness.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.types.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Harness onboarding types — the shapes shared by the backend REST API
3
+ * (`/api/harness`), the `crewly` CLI and the web setup page.
4
+ *
5
+ * A "harness" is an agent CLI Crewly drives in a PTY: Claude Code, Codex or
6
+ * Gemini CLI. See specs/onboarding-harness-login.md for the contract.
7
+ *
8
+ * @module services/harness/harness.types
9
+ */
10
+ import { HARNESS_CONSTANTS } from '../../constants.js';
11
+ /** Every harness id, in display order. */
12
+ export const HARNESS_IDS = Object.values(HARNESS_CONSTANTS.IDS);
13
+ /** Every login method id. */
14
+ export const LOGIN_METHOD_IDS = ['subscription', 'api_key', 'device'];
15
+ /** Terminal login states: the PTY is gone and the session no longer changes. */
16
+ export const TERMINAL_LOGIN_STATES = ['succeeded', 'failed', 'timed_out', 'cancelled'];
17
+ /**
18
+ * Whether a value is a known harness id.
19
+ *
20
+ * @param value - Candidate
21
+ * @returns True for `claude-code`, `codex-cli` or `gemini-cli`
22
+ */
23
+ export function isHarnessId(value) {
24
+ return typeof value === 'string' && HARNESS_IDS.includes(value);
25
+ }
26
+ /**
27
+ * Whether a value is a known login method id.
28
+ *
29
+ * @param value - Candidate
30
+ * @returns True for `subscription`, `api_key` or `device`
31
+ */
32
+ export function isLoginMethodId(value) {
33
+ return typeof value === 'string' && LOGIN_METHOD_IDS.includes(value);
34
+ }
35
+ /**
36
+ * Whether a login state is terminal (the session will not change again).
37
+ *
38
+ * @param state - Login session state
39
+ * @returns True for succeeded / failed / timed_out / cancelled
40
+ */
41
+ export function isTerminalLoginState(state) {
42
+ return TERMINAL_LOGIN_STATES.includes(state);
43
+ }
44
+ /** A logger that drops everything (CLI default, tests). */
45
+ export const SILENT_HARNESS_LOGGER = {
46
+ info: () => undefined,
47
+ warn: () => undefined,
48
+ error: () => undefined,
49
+ debug: () => undefined,
50
+ };
51
+ //# sourceMappingURL=harness.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.types.js","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/harness.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAKvD,0CAA0C;AAC1C,MAAM,CAAC,MAAM,WAAW,GAAyB,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAKtF,6BAA6B;AAC7B,MAAM,CAAC,MAAM,gBAAgB,GAA6B,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAqEhG,gFAAgF;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAiC,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AAmBrH;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,WAAiC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,gBAAsC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAwB;IAC5D,OAAO,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC9C,CAAC;AAUD,2DAA2D;AAC3D,MAAM,CAAC,MAAM,qBAAqB,GAAkB;IACnD,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;IACtB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;CACtB,CAAC"}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Login broker — runs a harness's own login command in a PTY and relays it.
3
+ *
4
+ * The broker knows nothing about harness APIs. It spawns the login command
5
+ * (`claude setup-token`, `codex login --device-auth`) in a very wide PTY,
6
+ * normalizes the screen and applies the harness's rule set (login-rules.ts)
7
+ * to find the sign-in URL, a one-time code, a "paste the code" prompt,
8
+ * success and failure. Front ends read the resulting {@link LoginSession}
9
+ * and send the user's reply back with {@link LoginBrokerService.input}.
10
+ *
11
+ * Front ends are consumers of the same events: the REST API polls
12
+ * {@link LoginBrokerService.get}, the CLI awaits
13
+ * {@link LoginBrokerService.waitForCompletion}, and Phase 2 (re-login over
14
+ * Slack DM) subscribes to the `update` / `finished` events.
15
+ *
16
+ * Secrets: Claude's long-lived token is captured from the screen, stored with
17
+ * {@link HarnessCredentialsStore.setClaudeOauthToken}, redacted from every
18
+ * exposed screen and scrubbed from the raw buffer. It is never logged or
19
+ * emitted.
20
+ *
21
+ * State machine:
22
+ * `starting` → `awaiting_user` (URL / code / prompt seen) → `verifying`
23
+ * (input sent, or the command reported success and is being confirmed) →
24
+ * `succeeded` | `failed`; any live state → `timed_out` (15 min) | `cancelled`.
25
+ * A prompt that reappears after input returns the session to `awaiting_user`.
26
+ *
27
+ * @module services/harness/login-broker.service
28
+ */
29
+ import { EventEmitter } from 'events';
30
+ import { HarnessCredentialsStore } from './harness-credentials.store.js';
31
+ import { type HarnessId, type HarnessLogger, type LoginSession } from './harness.types.js';
32
+ /** The slice of a PTY the broker uses (node-pty's IPty satisfies it). */
33
+ export interface BrokerPty {
34
+ onData(listener: (data: string) => void): unknown;
35
+ onExit(listener: (event: {
36
+ exitCode: number;
37
+ signal?: number;
38
+ }) => void): unknown;
39
+ write(data: string): void;
40
+ kill(signal?: string): void;
41
+ }
42
+ /** Spawns a PTY. */
43
+ export type BrokerPtySpawner = (file: string, args: string[], options: {
44
+ cols: number;
45
+ rows: number;
46
+ cwd: string;
47
+ env: Record<string, string>;
48
+ }) => BrokerPty;
49
+ /** Events emitted by the broker. Listeners receive a {@link LoginSession} (never a secret). */
50
+ export declare const LOGIN_BROKER_EVENTS: {
51
+ /** Any change to a session */
52
+ readonly UPDATE: "update";
53
+ /** A session reached a terminal state */
54
+ readonly FINISHED: "finished";
55
+ };
56
+ /** Error codes the REST layer maps to HTTP statuses. */
57
+ export type LoginBrokerErrorCode = 'unknown_harness' | 'unsupported_method' | 'not_installed' | 'spawn_failed' | 'not_found' | 'not_active';
58
+ /** Broker error with a machine-readable code. */
59
+ export declare class LoginBrokerError extends Error {
60
+ readonly code: LoginBrokerErrorCode;
61
+ /**
62
+ * @param code - Machine-readable code
63
+ * @param message - Human-readable message (never contains a secret)
64
+ */
65
+ constructor(code: LoginBrokerErrorCode, message: string);
66
+ }
67
+ /** Injectable dependencies. */
68
+ export interface LoginBrokerDeps {
69
+ spawnPty?: BrokerPtySpawner;
70
+ /** PATH lookup for the login command */
71
+ resolveCommand?: (command: string, envPath: string) => string | null;
72
+ env?: NodeJS.ProcessEnv;
73
+ homeDir?: string;
74
+ credentials?: HarnessCredentialsStore;
75
+ /** Confirms a login with the harness's own status command (Codex) */
76
+ verify?: (harnessId: HarnessId) => Promise<boolean>;
77
+ /** Records Claude's first-run answers after a Claude login */
78
+ prepareClaudeConfig?: () => void;
79
+ now?: () => number;
80
+ idFactory?: () => string;
81
+ logger?: HarnessLogger;
82
+ timeoutMs?: number;
83
+ }
84
+ /** Runs harness login commands in PTYs and tracks their sessions. */
85
+ export declare class LoginBrokerService extends EventEmitter {
86
+ private readonly spawnPty;
87
+ private readonly resolveCommand;
88
+ private readonly env;
89
+ private readonly homeDir;
90
+ private readonly credentials;
91
+ private readonly verify;
92
+ private readonly prepareClaudeConfig;
93
+ private readonly now;
94
+ private readonly idFactory;
95
+ private readonly logger;
96
+ private readonly timeoutMs;
97
+ private readonly sessions;
98
+ /** Sessions whose verification is in flight. */
99
+ private readonly verifying;
100
+ /**
101
+ * @param deps - Injectable dependencies (all optional)
102
+ */
103
+ constructor(deps?: LoginBrokerDeps);
104
+ /**
105
+ * Environment for the login PTY: the harness PATH, no owner API token, no
106
+ * nested-Claude-session markers, and a no-op BROWSER so the harness does
107
+ * not try to open a browser on the server.
108
+ *
109
+ * @returns String-only env map
110
+ */
111
+ buildEnv(): Record<string, string>;
112
+ /**
113
+ * Start a login session, or return the live one for this harness.
114
+ *
115
+ * @param harnessId - Harness id
116
+ * @param method - Broker login method (`subscription`, `device`)
117
+ * @returns The session
118
+ * @throws LoginBrokerError unknown_harness | unsupported_method | not_installed | spawn_failed
119
+ */
120
+ start(harnessId: string, method: string): LoginSession;
121
+ /**
122
+ * Read a session.
123
+ *
124
+ * @param sessionId - Session id
125
+ * @returns The session
126
+ * @throws LoginBrokerError not_found
127
+ */
128
+ get(sessionId: string): LoginSession;
129
+ /**
130
+ * The live (non-terminal) session for a harness, if any.
131
+ *
132
+ * @param harnessId - Harness id
133
+ * @returns The session, or null
134
+ */
135
+ getActiveSession(harnessId: string): LoginSession | null;
136
+ /**
137
+ * Type the user's reply into the PTY, followed by Enter.
138
+ *
139
+ * @param sessionId - Session id
140
+ * @param text - What the user typed (e.g. the code from platform.claude.com)
141
+ * @returns The session
142
+ * @throws LoginBrokerError not_found | not_active
143
+ */
144
+ input(sessionId: string, text: string): LoginSession;
145
+ /**
146
+ * Cancel a session (kills the PTY). Cancelling a finished session is a no-op.
147
+ *
148
+ * @param sessionId - Session id
149
+ * @returns The session
150
+ * @throws LoginBrokerError not_found
151
+ */
152
+ cancel(sessionId: string): LoginSession;
153
+ /**
154
+ * Resolve when the session reaches a terminal state.
155
+ *
156
+ * @param sessionId - Session id
157
+ * @returns The final session
158
+ * @throws LoginBrokerError not_found
159
+ */
160
+ waitForCompletion(sessionId: string): Promise<LoginSession>;
161
+ /** Cancel every live session (backend shutdown, CLI exit). */
162
+ shutdown(): void;
163
+ /**
164
+ * Session record or a not_found error.
165
+ *
166
+ * @param sessionId - Session id
167
+ * @returns The record
168
+ * @throws LoginBrokerError not_found
169
+ */
170
+ private requireRecord;
171
+ /**
172
+ * Append PTY output and re-evaluate the rules.
173
+ *
174
+ * @param record - Session record
175
+ * @param data - Output chunk
176
+ */
177
+ private handleData;
178
+ /**
179
+ * Apply the rule set to the current screen and move the state machine.
180
+ *
181
+ * @param record - Session record
182
+ * @param final - The process has exited
183
+ */
184
+ private evaluate;
185
+ /**
186
+ * Handle a reported success: store the secret (Claude) or confirm (Codex).
187
+ *
188
+ * @param record - Session record
189
+ * @param secret - Captured credential, when the rule set has one
190
+ */
191
+ private complete;
192
+ /**
193
+ * Confirm a login with the harness's status command.
194
+ *
195
+ * @param record - Session record
196
+ */
197
+ private confirm;
198
+ /**
199
+ * Save a captured credential. Never logs it.
200
+ *
201
+ * @param record - Session record
202
+ * @param secret - The credential
203
+ */
204
+ private storeSecret;
205
+ /**
206
+ * The login command exited.
207
+ *
208
+ * @param record - Session record
209
+ * @param exitCode - Process exit code
210
+ */
211
+ private handleExit;
212
+ /**
213
+ * Move a session to a terminal state and release the PTY.
214
+ *
215
+ * @param record - Session record
216
+ * @param state - Terminal state
217
+ * @param message - Message for the user
218
+ */
219
+ private finish;
220
+ /**
221
+ * Apply a patch, bump `updatedAt` and emit `update`.
222
+ *
223
+ * @param record - Session record
224
+ * @param patch - Fields to change
225
+ */
226
+ private update;
227
+ /**
228
+ * Tail of the screen, secrets redacted.
229
+ *
230
+ * @param record - Session record
231
+ * @param text - Normalized text
232
+ * @returns Exposed screen text
233
+ */
234
+ private exposedScreen;
235
+ /** Forget finished sessions older than the retention window. */
236
+ private prune;
237
+ }
238
+ //# sourceMappingURL=login-broker.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-broker.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/login-broker.service.ts"],"names":[],"mappings":"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"}