crewly 1.20.180 → 1.20.182
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/config/skills/agent/remote-browser/SKILL.md +28 -8
- package/dist/backend/backend/src/constants.d.ts +89 -1
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +99 -2
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts +2 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js +15 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.d.ts +11 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js +44 -9
- package/dist/backend/backend/src/controllers/system/runtime-fallback.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/runtime-terms.controller.d.ts +31 -0
- package/dist/backend/backend/src/controllers/system/runtime-terms.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/system/runtime-terms.controller.js +99 -0
- package/dist/backend/backend/src/controllers/system/runtime-terms.controller.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +51 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/system.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/system.routes.js +3 -0
- package/dist/backend/backend/src/routes/modules/system.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/antigravity-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/antigravity-runtime.service.js +5 -0
- package/dist/backend/backend/src/services/agent/antigravity-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-approval.service.d.ts +202 -0
- package/dist/backend/backend/src/services/browser/browser-approval.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-approval.service.js +533 -0
- package/dist/backend/backend/src/services/browser/browser-approval.service.js.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +24 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js +55 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-session.service.d.ts +51 -0
- package/dist/backend/backend/src/services/browser/browser-session.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-session.service.js +82 -3
- package/dist/backend/backend/src/services/browser/browser-session.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/held-action-store.d.ts +125 -0
- package/dist/backend/backend/src/services/browser/held-action-store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/browser/held-action-store.js +141 -0
- package/dist/backend/backend/src/services/browser/held-action-store.js.map +1 -0
- package/dist/backend/backend/src/services/decisions/decision-card.d.ts +23 -5
- package/dist/backend/backend/src/services/decisions/decision-card.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision-card.js +56 -9
- package/dist/backend/backend/src/services/decisions/decision-card.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts +96 -1
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.js +190 -8
- package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.wiring.js +7 -0
- package/dist/backend/backend/src/services/decisions/decision.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.d.ts +8 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js +5 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-availability.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts +2 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js +4 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +2 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.types.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js +3 -0
- package/dist/backend/backend/src/services/runtime-fallback/runtime-fallback.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-smoke-test.service.d.ts +15 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-smoke-test.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/runtime-fallback/runtime-smoke-test.service.js +13 -2
- package/dist/backend/backend/src/services/runtime-fallback/runtime-smoke-test.service.js.map +1 -1
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-driver.d.ts +92 -0
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-driver.d.ts.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-driver.js +199 -0
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-driver.js.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-screens.d.ts +79 -0
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-screens.d.ts.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-screens.js +145 -0
- package/dist/backend/backend/src/services/runtime-terms/antigravity-terms-screens.js.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/fake-agy-tui.fixture.d.ts +75 -0
- package/dist/backend/backend/src/services/runtime-terms/fake-agy-tui.fixture.d.ts.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/fake-agy-tui.fixture.js +218 -0
- package/dist/backend/backend/src/services/runtime-terms/fake-agy-tui.fixture.js.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms-consent.service.d.ts +245 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms-consent.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms-consent.service.js +428 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms-consent.service.js.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.store.d.ts +67 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.store.js +78 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.store.js.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.wiring.d.ts +39 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.wiring.js +161 -0
- package/dist/backend/backend/src/services/runtime-terms/runtime-terms.wiring.js.map +1 -0
- package/dist/backend/backend/src/types/decision.types.d.ts +55 -2
- package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +89 -1
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +99 -2
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/antigravity-runtime.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/antigravity-runtime.service.js +5 -0
- package/dist/cli/backend/src/services/agent/antigravity-runtime.service.js.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision-card.d.ts +165 -0
- package/dist/cli/backend/src/services/decisions/decision-card.d.ts.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision-card.js +358 -0
- package/dist/cli/backend/src/services/decisions/decision-card.js.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision-contract.d.ts +83 -0
- package/dist/cli/backend/src/services/decisions/decision-contract.d.ts.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision-contract.js +226 -0
- package/dist/cli/backend/src/services/decisions/decision-contract.js.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision-store.d.ts +80 -0
- package/dist/cli/backend/src/services/decisions/decision-store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision-store.js +151 -0
- package/dist/cli/backend/src/services/decisions/decision-store.js.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts +376 -0
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/decisions/decision.service.js +821 -0
- package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -0
- package/dist/cli/backend/src/services/decisions/ticket-thread-store.d.ts +97 -0
- package/dist/cli/backend/src/services/decisions/ticket-thread-store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/decisions/ticket-thread-store.js +137 -0
- package/dist/cli/backend/src/services/decisions/ticket-thread-store.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts +136 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.js +152 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-fallback.types.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-smoke-test.service.d.ts +217 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-smoke-test.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-smoke-test.service.js +430 -0
- package/dist/cli/backend/src/services/runtime-fallback/runtime-smoke-test.service.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-driver.d.ts +92 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-driver.d.ts.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-driver.js +199 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-driver.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-screens.d.ts +79 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-screens.d.ts.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-screens.js +145 -0
- package/dist/cli/backend/src/services/runtime-terms/antigravity-terms-screens.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms-consent.service.d.ts +245 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms-consent.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms-consent.service.js +428 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms-consent.service.js.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms.store.d.ts +67 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms.store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms.store.js +78 -0
- package/dist/cli/backend/src/services/runtime-terms/runtime-terms.store.js.map +1 -0
- package/dist/cli/backend/src/types/decision.types.d.ts +192 -0
- package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -0
- package/dist/cli/backend/src/types/decision.types.js +13 -0
- package/dist/cli/backend/src/types/decision.types.js.map +1 -0
- package/dist/cli/cli/src/commands/harness-setup.js +2 -2
- package/frontend/dist/assets/{index-4271e95e.js → index-9c91de50.js} +138 -138
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owner consent for a runtime's first-run Terms of Service.
|
|
3
|
+
*
|
|
4
|
+
* The harness never accepts third-party terms on its own. When a runtime's
|
|
5
|
+
* Terms screen is seen (on launch, by the smoke test, or on a probe), ONE
|
|
6
|
+
* decision card per runtime per machine goes to the owner's DM with this
|
|
7
|
+
* machine's orc bot: "Agree, no data sharing" / "Agree + share data" /
|
|
8
|
+
* "Don't agree", 24 h, default Don't agree. On the answer:
|
|
9
|
+
*
|
|
10
|
+
* - agree: launch the runtime in a dedicated PTY session, drive its setup
|
|
11
|
+
* screens to the choice (data box verified on screen before Done), check
|
|
12
|
+
* the prompt appears, close the session, run the runtime smoke test and
|
|
13
|
+
* report both in the card's thread;
|
|
14
|
+
* - don't agree (or no answer): mark the runtime "terms not accepted" so the
|
|
15
|
+
* fallback order skips it (reason shown in Settings → Runtimes); asked
|
|
16
|
+
* again only when the owner presses Test, re-adds it, or Accept terms….
|
|
17
|
+
*
|
|
18
|
+
* specs/2026-10-01-runtime-terms-consent.md
|
|
19
|
+
*
|
|
20
|
+
* @module services/runtime-terms/runtime-terms-consent.service
|
|
21
|
+
*/
|
|
22
|
+
import { RUNTIME_TERMS_CONSTANTS } from '../../constants.js';
|
|
23
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
24
|
+
import { PENDING_DECISION_STATUSES } from '../decisions/decision-store.js';
|
|
25
|
+
import { redactSecrets } from '../harness/login-rules.js';
|
|
26
|
+
const C = RUNTIME_TERMS_CONSTANTS;
|
|
27
|
+
/** Choice ↔ button label. */
|
|
28
|
+
export const TERMS_CHOICE_LABELS = {
|
|
29
|
+
agree_no_data: C.OPTIONS.AGREE_NO_DATA,
|
|
30
|
+
agree_share_data: C.OPTIONS.AGREE_SHARE_DATA,
|
|
31
|
+
decline: C.OPTIONS.DECLINE,
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The choice an option label means.
|
|
35
|
+
*
|
|
36
|
+
* @param label - Button label
|
|
37
|
+
* @returns Choice, or null
|
|
38
|
+
*/
|
|
39
|
+
export function choiceOfLabel(label) {
|
|
40
|
+
const entry = Object.entries(TERMS_CHOICE_LABELS).find(([, l]) => l === label);
|
|
41
|
+
return entry ? entry[0] : null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Screen text for a Slack code block: secrets redacted, last lines only, no
|
|
45
|
+
* fence breakers.
|
|
46
|
+
*
|
|
47
|
+
* @param screen - Screen text
|
|
48
|
+
* @returns Block text
|
|
49
|
+
*/
|
|
50
|
+
export function screenForThread(screen) {
|
|
51
|
+
const lines = redactSecrets(screen)
|
|
52
|
+
.split('\n')
|
|
53
|
+
.map((l) => l.replace(/\s+$/, ''));
|
|
54
|
+
while (lines.length && !lines[lines.length - 1])
|
|
55
|
+
lines.pop();
|
|
56
|
+
const tail = lines.slice(-C.DRIVE.SCREEN_LINES_IN_THREAD).join('\n').replace(/```/g, "'''");
|
|
57
|
+
return '```\n' + (tail || '(empty screen)') + '\n```';
|
|
58
|
+
}
|
|
59
|
+
/** The service. */
|
|
60
|
+
export class RuntimeTermsConsentService {
|
|
61
|
+
deps;
|
|
62
|
+
logger;
|
|
63
|
+
now;
|
|
64
|
+
/** Serialises asks per runtime (launch + smoke test can report at once) */
|
|
65
|
+
asking = new Map();
|
|
66
|
+
/** Running accept / decline per runtime */
|
|
67
|
+
running = new Map();
|
|
68
|
+
/**
|
|
69
|
+
* @param deps - Dependencies
|
|
70
|
+
*/
|
|
71
|
+
constructor(deps) {
|
|
72
|
+
this.deps = deps;
|
|
73
|
+
this.logger = deps.logger ?? LoggerService.getInstance().createComponentLogger('RuntimeTerms');
|
|
74
|
+
this.now = deps.now ?? (() => new Date());
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether the service handles a runtime.
|
|
78
|
+
*
|
|
79
|
+
* @param runtime - Runtime id
|
|
80
|
+
* @returns True when it has a profile
|
|
81
|
+
*/
|
|
82
|
+
supports(runtime) {
|
|
83
|
+
return Boolean(this.deps.profiles[runtime]);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A runtime's Terms screen was seen: ask the owner, once.
|
|
87
|
+
*
|
|
88
|
+
* No new card while one is open or the harness is accepting; none after
|
|
89
|
+
* Don't agree / a failed attempt unless the owner asked
|
|
90
|
+
* (`ownerInitiated`).
|
|
91
|
+
*
|
|
92
|
+
* @param runtime - Runtime id
|
|
93
|
+
* @param report - Source
|
|
94
|
+
* @returns The record, or null for a runtime without a profile
|
|
95
|
+
*/
|
|
96
|
+
reportTermsScreen(runtime, report) {
|
|
97
|
+
if (!this.supports(runtime))
|
|
98
|
+
return Promise.resolve(null);
|
|
99
|
+
const prev = this.asking.get(runtime) ?? Promise.resolve(null);
|
|
100
|
+
const next = prev.catch(() => null).then(() => this.askOnce(runtime, report));
|
|
101
|
+
this.asking.set(runtime, next);
|
|
102
|
+
return next;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Settings → Runtimes → Accept terms…: post the card (or return the open one).
|
|
106
|
+
*
|
|
107
|
+
* @param runtime - Runtime id
|
|
108
|
+
* @returns The record
|
|
109
|
+
* @throws Error for a runtime without Terms handling
|
|
110
|
+
*/
|
|
111
|
+
async requestConsent(runtime) {
|
|
112
|
+
if (!this.supports(runtime))
|
|
113
|
+
throw new Error(`Crewly has no Terms flow for ${runtime}`);
|
|
114
|
+
return (await this.reportTermsScreen(runtime, { source: 'settings', ownerInitiated: true }));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Probe: launch the runtime in the dedicated session, read (never press
|
|
118
|
+
* anything) until the screen is recognisable, close it. A Terms screen
|
|
119
|
+
* asks the owner (the owner asked for the check); a ready prompt means
|
|
120
|
+
* the Terms were accepted here already (e.g. in a terminal).
|
|
121
|
+
*
|
|
122
|
+
* @param runtime - Runtime id
|
|
123
|
+
* @returns What was on screen and the record after
|
|
124
|
+
* @throws Error while an answer is being applied, or for a runtime without a profile
|
|
125
|
+
*/
|
|
126
|
+
async probe(runtime) {
|
|
127
|
+
const profile = this.deps.profiles[runtime];
|
|
128
|
+
if (!profile)
|
|
129
|
+
throw new Error(`Crewly has no Terms flow for ${runtime}`);
|
|
130
|
+
if (this.running.has(runtime) || this.deps.store.get(runtime)?.status === 'accepting') {
|
|
131
|
+
throw new Error('Crewly is already accepting these Terms; wait for it to finish');
|
|
132
|
+
}
|
|
133
|
+
const sleep = this.deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
134
|
+
const timeout = this.deps.probeTimeoutMs ?? C.DRIVE.LAUNCH_TIMEOUT_MS;
|
|
135
|
+
let screen = '';
|
|
136
|
+
let outcome = 'unknown';
|
|
137
|
+
const session = await this.deps.launch(runtime);
|
|
138
|
+
try {
|
|
139
|
+
for (let waited = 0; waited <= timeout; waited += C.DRIVE.POLL_MS) {
|
|
140
|
+
screen = String(await session.terminal.capture());
|
|
141
|
+
outcome = profile.classify(screen);
|
|
142
|
+
if (outcome !== 'unknown')
|
|
143
|
+
break;
|
|
144
|
+
await sleep(C.DRIVE.POLL_MS);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
await session.close().catch(() => undefined);
|
|
149
|
+
}
|
|
150
|
+
if (outcome === 'terms') {
|
|
151
|
+
const record = await this.reportTermsScreen(runtime, { source: 'probe', ownerInitiated: true });
|
|
152
|
+
return { outcome, record, screen: redactSecrets(screen) };
|
|
153
|
+
}
|
|
154
|
+
if (outcome === 'ready') {
|
|
155
|
+
const prev = this.deps.store.get(runtime);
|
|
156
|
+
const record = this.save({ runtime, status: 'accepted', detectedBy: 'probe', ...(prev?.dataSharing !== undefined ? { dataSharing: prev.dataSharing } : {}) });
|
|
157
|
+
return { outcome, record, screen: redactSecrets(screen) };
|
|
158
|
+
}
|
|
159
|
+
return { outcome, record: this.deps.store.get(runtime), screen: redactSecrets(screen) };
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Answer inline from Settings: through the open card when there is one
|
|
163
|
+
* (so the card updates), else directly.
|
|
164
|
+
*
|
|
165
|
+
* @param runtime - Runtime id
|
|
166
|
+
* @param choice - Owner's choice
|
|
167
|
+
* @returns The record after the answer was taken (driving continues in the background)
|
|
168
|
+
*/
|
|
169
|
+
async answer(runtime, choice) {
|
|
170
|
+
if (!this.supports(runtime))
|
|
171
|
+
throw new Error(`Crewly has no Terms flow for ${runtime}`);
|
|
172
|
+
const rec = this.deps.store.get(runtime);
|
|
173
|
+
if (rec?.status === 'accepting')
|
|
174
|
+
throw new Error('Crewly is already accepting these Terms; wait for it to finish');
|
|
175
|
+
const decisions = this.deps.decisions();
|
|
176
|
+
if (rec?.decisionId && decisions) {
|
|
177
|
+
const d = await decisions.get(rec.decisionId);
|
|
178
|
+
const opt = d?.options.find((o) => o.label === TERMS_CHOICE_LABELS[choice]);
|
|
179
|
+
if (d && opt && PENDING_DECISION_STATUSES.has(d.status)) {
|
|
180
|
+
await decisions.chooseFromDashboard(d.id, opt.key);
|
|
181
|
+
return this.deps.store.get(runtime) ?? rec;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
this.start(runtime, choice, undefined, 'owner');
|
|
185
|
+
return this.deps.store.get(runtime) ?? rec;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The `runtime_terms` decision-kind handler
|
|
189
|
+
* (`DecisionService.registerKindHandler`): acts on the answer. No agent
|
|
190
|
+
* asked, so there is no note for one.
|
|
191
|
+
*
|
|
192
|
+
* @param d - Settled decision
|
|
193
|
+
* @returns null (nothing to deliver)
|
|
194
|
+
*/
|
|
195
|
+
async onSettled(d) {
|
|
196
|
+
this.handleSettled(d);
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* A decision was settled: act on runtime-terms ones.
|
|
201
|
+
*
|
|
202
|
+
* @param d - Settled decision
|
|
203
|
+
*/
|
|
204
|
+
handleSettled(d) {
|
|
205
|
+
if (d.kind !== 'runtime_terms' || !d.system)
|
|
206
|
+
return;
|
|
207
|
+
const runtime = d.system.key;
|
|
208
|
+
const rec = this.deps.store.get(runtime);
|
|
209
|
+
if (!rec || rec.decisionId !== d.id) {
|
|
210
|
+
this.logger.info('Ignoring an old Terms decision', { decisionId: d.id, runtime });
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (d.status === 'resolved') {
|
|
214
|
+
const choice = choiceOfLabel(d.options.find((o) => o.key === d.chosenKey)?.label);
|
|
215
|
+
if (choice)
|
|
216
|
+
this.start(runtime, choice, d.id, 'owner');
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (d.status === 'defaulted') {
|
|
220
|
+
this.start(runtime, 'decline', d.id, 'deadline');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
// Withdrawn / parked: nothing was agreed.
|
|
224
|
+
this.start(runtime, 'decline', d.id, 'withdrawn');
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Why a runtime cannot be used because of its Terms (null = it can).
|
|
228
|
+
*
|
|
229
|
+
* @param runtime - Runtime id
|
|
230
|
+
* @returns Owner-facing reason, or null
|
|
231
|
+
*/
|
|
232
|
+
blockedReason(runtime) {
|
|
233
|
+
const rec = this.deps.store.get(runtime);
|
|
234
|
+
if (!rec)
|
|
235
|
+
return null;
|
|
236
|
+
switch (rec.status) {
|
|
237
|
+
case 'pending':
|
|
238
|
+
return C.MESSAGES.PENDING;
|
|
239
|
+
case 'accepting':
|
|
240
|
+
return 'Accepting its Terms of Service…';
|
|
241
|
+
case 'declined':
|
|
242
|
+
return `${C.MESSAGES.DECLINED_SUFFIX}: ${rec.reason ?? C.MESSAGES.DECLINED_BY_OWNER}`;
|
|
243
|
+
case 'failed':
|
|
244
|
+
return `${C.MESSAGES.DECLINED_SUFFIX}: the setup stopped (${rec.reason ?? 'unknown reason'})`;
|
|
245
|
+
default:
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/** @returns Every runtime with a Terms flow, with its record */
|
|
250
|
+
list() {
|
|
251
|
+
const all = this.deps.store.all();
|
|
252
|
+
return Object.values(this.deps.profiles).map((p) => ({
|
|
253
|
+
...(all[p.runtime] ?? { runtime: p.runtime, status: 'none' }),
|
|
254
|
+
label: p.label,
|
|
255
|
+
info: p.info,
|
|
256
|
+
blockedReason: this.blockedReason(p.runtime),
|
|
257
|
+
choices: Object.keys(TERMS_CHOICE_LABELS).map((choice) => ({ choice, label: TERMS_CHOICE_LABELS[choice] })),
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Wait for a running accept / decline (tests, the API's `?wait=1`).
|
|
262
|
+
*
|
|
263
|
+
* @param runtime - Runtime id
|
|
264
|
+
*/
|
|
265
|
+
async whenIdle(runtime) {
|
|
266
|
+
await (this.asking.get(runtime) ?? Promise.resolve()).catch(() => undefined);
|
|
267
|
+
await (this.running.get(runtime) ?? Promise.resolve());
|
|
268
|
+
}
|
|
269
|
+
// ------------------------------------------------------------------ internals
|
|
270
|
+
async askOnce(runtime, report) {
|
|
271
|
+
const profile = this.deps.profiles[runtime];
|
|
272
|
+
const rec = this.deps.store.get(runtime);
|
|
273
|
+
if (rec?.status === 'accepting')
|
|
274
|
+
return rec;
|
|
275
|
+
const decisions = this.deps.decisions();
|
|
276
|
+
if (rec?.status === 'pending' && rec.decisionId && decisions) {
|
|
277
|
+
const open = await decisions.get(rec.decisionId).catch(() => null);
|
|
278
|
+
if (open && PENDING_DECISION_STATUSES.has(open.status))
|
|
279
|
+
return rec;
|
|
280
|
+
}
|
|
281
|
+
if ((rec?.status === 'declined' || rec?.status === 'failed') && !report.ownerInitiated)
|
|
282
|
+
return rec;
|
|
283
|
+
const machine = this.deps.machineName();
|
|
284
|
+
let decisionId;
|
|
285
|
+
if (decisions) {
|
|
286
|
+
const text = profile.card(machine);
|
|
287
|
+
try {
|
|
288
|
+
const d = await decisions.askSystem({
|
|
289
|
+
kind: 'runtime_terms',
|
|
290
|
+
system: { key: runtime, defaultIsDecline: true },
|
|
291
|
+
title: text.title,
|
|
292
|
+
question: text.question,
|
|
293
|
+
body: text.body,
|
|
294
|
+
options: [C.OPTIONS.AGREE_NO_DATA, C.OPTIONS.AGREE_SHARE_DATA, C.OPTIONS.DECLINE],
|
|
295
|
+
default: C.OPTIONS.DECLINE,
|
|
296
|
+
deadline: new Date(this.now().getTime() + C.DEADLINE_MS),
|
|
297
|
+
sensitive: 'runtime_terms',
|
|
298
|
+
});
|
|
299
|
+
decisionId = d.id;
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
this.logger.warn('Could not create the Terms decision card', { runtime, error: err instanceof Error ? err.message : String(err) });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const saved = this.save({
|
|
306
|
+
runtime,
|
|
307
|
+
status: 'pending',
|
|
308
|
+
...(decisionId ? { decisionId } : {}),
|
|
309
|
+
detectedBy: report.source,
|
|
310
|
+
});
|
|
311
|
+
this.logger.info('Runtime Terms consent asked', { runtime, source: report.source, decisionId });
|
|
312
|
+
return saved;
|
|
313
|
+
}
|
|
314
|
+
start(runtime, choice, decisionId, why) {
|
|
315
|
+
if (this.running.has(runtime)) {
|
|
316
|
+
this.logger.warn('A Terms answer is already being applied; ignoring another', { runtime, choice });
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const run = (choice === 'decline' ? this.decline(runtime, decisionId, why) : this.accept(runtime, choice === 'agree_share_data', decisionId))
|
|
320
|
+
.catch((err) => this.logger.error('Applying the Terms answer failed', { runtime, error: err instanceof Error ? err.message : String(err) }))
|
|
321
|
+
.finally(() => this.running.delete(runtime));
|
|
322
|
+
this.running.set(runtime, run);
|
|
323
|
+
}
|
|
324
|
+
async decline(runtime, decisionId, why) {
|
|
325
|
+
const profile = this.deps.profiles[runtime];
|
|
326
|
+
await this.deps.closeSession?.(runtime).catch(() => undefined);
|
|
327
|
+
const reason = why === 'deadline' ? C.MESSAGES.DECLINED_BY_DEADLINE : why === 'withdrawn' ? 'The question was withdrawn without an answer' : C.MESSAGES.DECLINED_BY_OWNER;
|
|
328
|
+
this.save({ runtime, status: 'declined', reason, ...(decisionId ? { decisionId } : {}) });
|
|
329
|
+
const machine = this.deps.machineName();
|
|
330
|
+
const lead = why === 'deadline' ? 'No answer within 24 h, so nothing was accepted (the default).' : 'OK, not accepted.';
|
|
331
|
+
await this.reply(decisionId, `${lead} ${profile.label} is marked "terms not accepted" on ${machine}, and the fallback order skips it. ` +
|
|
332
|
+
`To change your mind: Settings → Runtimes → ${profile.label} → Accept terms…, or press Test.`);
|
|
333
|
+
}
|
|
334
|
+
async accept(runtime, shareData, decisionId) {
|
|
335
|
+
const profile = this.deps.profiles[runtime];
|
|
336
|
+
const machine = this.deps.machineName();
|
|
337
|
+
this.save({ runtime, status: 'accepting', ...(decisionId ? { decisionId } : {}), dataSharing: shareData });
|
|
338
|
+
let drive;
|
|
339
|
+
let session = null;
|
|
340
|
+
try {
|
|
341
|
+
session = await this.deps.launch(runtime);
|
|
342
|
+
drive = await profile.drive(session.terminal, shareData);
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
drive = { ok: false, donePressed: false, alreadyAccepted: false, error: `Could not start ${profile.label}: ${err instanceof Error ? err.message : String(err)}`, keys: [], screen: '' };
|
|
346
|
+
}
|
|
347
|
+
finally {
|
|
348
|
+
await session?.close().catch(() => undefined);
|
|
349
|
+
}
|
|
350
|
+
this.logger.info('Runtime Terms screens driven', { runtime, ok: drive.ok, donePressed: drive.donePressed, alreadyAccepted: drive.alreadyAccepted, keys: drive.keys.length });
|
|
351
|
+
if (!drive.ok) {
|
|
352
|
+
this.save({
|
|
353
|
+
runtime,
|
|
354
|
+
status: 'failed',
|
|
355
|
+
reason: drive.error ?? 'unknown',
|
|
356
|
+
...(decisionId ? { decisionId } : {}),
|
|
357
|
+
...(drive.donePressed ? { dataSharing: drive.dataSharing } : {}),
|
|
358
|
+
});
|
|
359
|
+
const head = drive.donePressed
|
|
360
|
+
? `:warning: Done was pressed on ${machine} (Terms accepted, data sharing ${drive.dataSharing ? 'on' : 'off'}), but then: ${drive.error}.`
|
|
361
|
+
: `:warning: Stopped on ${machine}; nothing was accepted (Done was not pressed): ${drive.error}.`;
|
|
362
|
+
await this.reply(decisionId, `${head}\nScreen:\n${screenForThread(drive.screen)}\nTo try again: Settings → Runtimes → ${profile.label} → Accept terms….`);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
this.save({
|
|
366
|
+
runtime,
|
|
367
|
+
status: 'accepted',
|
|
368
|
+
...(decisionId ? { decisionId } : {}),
|
|
369
|
+
...(drive.alreadyAccepted ? {} : { dataSharing: drive.dataSharing ?? shareData }),
|
|
370
|
+
});
|
|
371
|
+
await this.reply(decisionId, drive.alreadyAccepted
|
|
372
|
+
? `${profile.label} on ${machine} was already set up (it opened straight to its prompt), so nothing was pressed. Running the runtime test…`
|
|
373
|
+
: `:white_check_mark: Accepted on ${machine}: ${profile.label}'s Terms, data sharing ${drive.dataSharing ? 'on' : 'off'} (checked on screen before Done). It opened to its prompt. Running the runtime test…`);
|
|
374
|
+
let smoke;
|
|
375
|
+
try {
|
|
376
|
+
smoke = await this.deps.runSmokeTest(runtime);
|
|
377
|
+
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
await this.reply(decisionId, `Runtime test could not start: ${err instanceof Error ? err.message : String(err)}`);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
await this.reply(decisionId, smoke.passed
|
|
383
|
+
? `Runtime test passed in ${Math.round(smoke.durationMs / 1000)}s: ${profile.label} ran bash and replied.`
|
|
384
|
+
: `Runtime test failed at "${(smoke.failedStep ?? 'unknown').replace(/_/g, ' ')}": ${smoke.error ?? 'no reason given'}` +
|
|
385
|
+
(smoke.screen ? `\nScreen:\n${screenForThread(smoke.screen)}` : ''));
|
|
386
|
+
}
|
|
387
|
+
async reply(decisionId, text) {
|
|
388
|
+
if (!decisionId)
|
|
389
|
+
return;
|
|
390
|
+
const decisions = this.deps.decisions();
|
|
391
|
+
if (!decisions)
|
|
392
|
+
return;
|
|
393
|
+
await decisions.replyInThread(decisionId, text).catch((err) => this.logger.warn('Could not reply in the Terms card thread', { decisionId, error: String(err) }));
|
|
394
|
+
}
|
|
395
|
+
save(fields) {
|
|
396
|
+
const saved = this.deps.store.set({ ...fields, updatedAt: this.now().toISOString() });
|
|
397
|
+
try {
|
|
398
|
+
this.deps.onChange?.(fields.runtime);
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
// cache invalidation only
|
|
402
|
+
}
|
|
403
|
+
return saved;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// ----------------------------------------------------------------- singleton
|
|
407
|
+
let instance = null;
|
|
408
|
+
/** @returns The backend's instance, or null before wiring (and in tests) */
|
|
409
|
+
export function getRuntimeTermsConsentService() {
|
|
410
|
+
return instance;
|
|
411
|
+
}
|
|
412
|
+
/** @param service - Instance to install (null clears) */
|
|
413
|
+
export function setRuntimeTermsConsentService(service) {
|
|
414
|
+
instance = service;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Report a Terms screen to the backend's service, when wired (fire and forget).
|
|
418
|
+
*
|
|
419
|
+
* @param runtime - Runtime id
|
|
420
|
+
* @param report - Source
|
|
421
|
+
*/
|
|
422
|
+
export function reportRuntimeTermsScreen(runtime, report) {
|
|
423
|
+
const svc = instance;
|
|
424
|
+
if (!svc)
|
|
425
|
+
return;
|
|
426
|
+
void svc.reportTermsScreen(runtime, report).catch(() => undefined);
|
|
427
|
+
}
|
|
428
|
+
//# sourceMappingURL=runtime-terms-consent.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-terms-consent.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/runtime-terms/runtime-terms-consent.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-machine Terms consent state (`<CREWLY_HOME>/runtime-terms-consent.json`).
|
|
3
|
+
*
|
|
4
|
+
* One record per runtime. Writes are atomic (temp file + rename); an
|
|
5
|
+
* unreadable file reads as empty. specs/2026-10-01-runtime-terms-consent.md
|
|
6
|
+
*
|
|
7
|
+
* @module services/runtime-terms/runtime-terms.store
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Where a runtime's Terms stand on this machine.
|
|
11
|
+
*
|
|
12
|
+
* - `pending`: the first-run Terms screen was seen; a card is waiting for the owner
|
|
13
|
+
* - `accepting`: the owner agreed; the harness is driving the screens
|
|
14
|
+
* - `accepted`: the screens were completed (or were already done)
|
|
15
|
+
* - `declined`: the owner chose Don't agree (or the deadline applied it)
|
|
16
|
+
* - `failed`: the harness stopped before (or after) Done because the screen did not match
|
|
17
|
+
*/
|
|
18
|
+
export type RuntimeTermsStatus = 'pending' | 'accepting' | 'accepted' | 'declined' | 'failed';
|
|
19
|
+
/** One runtime's record. */
|
|
20
|
+
export interface RuntimeTermsRecord {
|
|
21
|
+
runtime: string;
|
|
22
|
+
status: RuntimeTermsStatus;
|
|
23
|
+
/** ISO time of the last change */
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
/** Decision card of the current / last ask */
|
|
26
|
+
decisionId?: string;
|
|
27
|
+
/** Owner's choice for the data-sharing item, once agreed */
|
|
28
|
+
dataSharing?: boolean;
|
|
29
|
+
/** Why it is declined / failed (English, shown in Settings) */
|
|
30
|
+
reason?: string;
|
|
31
|
+
/** What found the Terms screen (launch, smoke_test, settings, probe) */
|
|
32
|
+
detectedBy?: string;
|
|
33
|
+
}
|
|
34
|
+
/** Reads and writes the records. */
|
|
35
|
+
export declare class RuntimeTermsStore {
|
|
36
|
+
private readonly file;
|
|
37
|
+
/**
|
|
38
|
+
* @param file - JSON file path
|
|
39
|
+
*/
|
|
40
|
+
constructor(file: string);
|
|
41
|
+
/**
|
|
42
|
+
* Store in a Crewly home.
|
|
43
|
+
*
|
|
44
|
+
* @param crewlyHome - CREWLY_HOME
|
|
45
|
+
* @returns Store
|
|
46
|
+
*/
|
|
47
|
+
static inHome(crewlyHome: string): RuntimeTermsStore;
|
|
48
|
+
/** @returns Every record, keyed by runtime */
|
|
49
|
+
all(): Record<string, RuntimeTermsRecord>;
|
|
50
|
+
/**
|
|
51
|
+
* One record.
|
|
52
|
+
*
|
|
53
|
+
* @param runtime - Runtime id
|
|
54
|
+
* @returns Record, or null
|
|
55
|
+
*/
|
|
56
|
+
get(runtime: string): RuntimeTermsRecord | null;
|
|
57
|
+
/**
|
|
58
|
+
* Replace a record.
|
|
59
|
+
*
|
|
60
|
+
* @param record - Record
|
|
61
|
+
* @returns The record
|
|
62
|
+
*/
|
|
63
|
+
set(record: RuntimeTermsRecord): RuntimeTermsRecord;
|
|
64
|
+
private read;
|
|
65
|
+
private write;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=runtime-terms.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-terms.store.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/runtime-terms/runtime-terms.store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE9F,4BAA4B;AAC5B,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,oCAAoC;AACpC,qBAAa,iBAAiB;IAIjB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC;;OAEG;gBAC0B,IAAI,EAAE,MAAM;IAEzC;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB;IAIpD,8CAA8C;IAC9C,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAIzC;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAI/C;;;;;OAKG;IACH,GAAG,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB;IAOnD,OAAO,CAAC,IAAI;IAcZ,OAAO,CAAC,KAAK;CAMb"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-machine Terms consent state (`<CREWLY_HOME>/runtime-terms-consent.json`).
|
|
3
|
+
*
|
|
4
|
+
* One record per runtime. Writes are atomic (temp file + rename); an
|
|
5
|
+
* unreadable file reads as empty. specs/2026-10-01-runtime-terms-consent.md
|
|
6
|
+
*
|
|
7
|
+
* @module services/runtime-terms/runtime-terms.store
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { RUNTIME_TERMS_CONSTANTS } from '../../constants.js';
|
|
12
|
+
const STATUSES = ['pending', 'accepting', 'accepted', 'declined', 'failed'];
|
|
13
|
+
/** Reads and writes the records. */
|
|
14
|
+
export class RuntimeTermsStore {
|
|
15
|
+
file;
|
|
16
|
+
/**
|
|
17
|
+
* @param file - JSON file path
|
|
18
|
+
*/
|
|
19
|
+
constructor(file) {
|
|
20
|
+
this.file = file;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Store in a Crewly home.
|
|
24
|
+
*
|
|
25
|
+
* @param crewlyHome - CREWLY_HOME
|
|
26
|
+
* @returns Store
|
|
27
|
+
*/
|
|
28
|
+
static inHome(crewlyHome) {
|
|
29
|
+
return new RuntimeTermsStore(path.join(crewlyHome, RUNTIME_TERMS_CONSTANTS.STORE_FILENAME));
|
|
30
|
+
}
|
|
31
|
+
/** @returns Every record, keyed by runtime */
|
|
32
|
+
all() {
|
|
33
|
+
return this.read().runtimes;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* One record.
|
|
37
|
+
*
|
|
38
|
+
* @param runtime - Runtime id
|
|
39
|
+
* @returns Record, or null
|
|
40
|
+
*/
|
|
41
|
+
get(runtime) {
|
|
42
|
+
return this.read().runtimes[runtime] ?? null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Replace a record.
|
|
46
|
+
*
|
|
47
|
+
* @param record - Record
|
|
48
|
+
* @returns The record
|
|
49
|
+
*/
|
|
50
|
+
set(record) {
|
|
51
|
+
const data = this.read();
|
|
52
|
+
data.runtimes[record.runtime] = record;
|
|
53
|
+
this.write(data);
|
|
54
|
+
return record;
|
|
55
|
+
}
|
|
56
|
+
read() {
|
|
57
|
+
try {
|
|
58
|
+
const raw = JSON.parse(fs.readFileSync(this.file, 'utf-8'));
|
|
59
|
+
const runtimes = {};
|
|
60
|
+
for (const [runtime, r] of Object.entries(raw.runtimes ?? {})) {
|
|
61
|
+
if (!r || !STATUSES.includes(r.status) || typeof r.updatedAt !== 'string')
|
|
62
|
+
continue;
|
|
63
|
+
runtimes[runtime] = { ...r, runtime };
|
|
64
|
+
}
|
|
65
|
+
return { version: 1, runtimes };
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return { version: 1, runtimes: {} };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
write(data) {
|
|
72
|
+
fs.mkdirSync(path.dirname(this.file), { recursive: true });
|
|
73
|
+
const tmp = `${this.file}.${process.pid}.tmp`;
|
|
74
|
+
fs.writeFileSync(tmp, JSON.stringify(data, null, 2));
|
|
75
|
+
fs.renameSync(tmp, this.file);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=runtime-terms.store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-terms.store.js","sourceRoot":"","sources":["../../../../../../backend/src/services/runtime-terms/runtime-terms.store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAmC7D,MAAM,QAAQ,GAAkC,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE3G,oCAAoC;AACpC,MAAM,OAAO,iBAAiB;IAIA;IAH7B;;OAEG;IACH,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAE7C;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,UAAkB;QAC/B,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,uBAAuB,CAAC,cAAc,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,8CAA8C;IAC9C,GAAG;QACF,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC;IAC7B,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,OAAe;QAClB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IAC9C,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,MAA0B;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO,MAAM,CAAC;IACf,CAAC;IAEO,IAAI;QACX,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAuB,CAAC;YAClF,MAAM,QAAQ,GAAuC,EAAE,CAAC;YACxD,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC/D,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;oBAAE,SAAS;gBACpF,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;YACvC,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACrC,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,IAAe;QAC5B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;QAC9C,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrD,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;CACD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Terms consent — the Antigravity CLI profile and the wiring with
|
|
3
|
+
* the real decision cards, PTY sessions and smoke test.
|
|
4
|
+
* specs/2026-10-01-runtime-terms-consent.md
|
|
5
|
+
*
|
|
6
|
+
* @module services/runtime-terms/runtime-terms.wiring
|
|
7
|
+
*/
|
|
8
|
+
import { DecisionService } from '../decisions/decision.service.js';
|
|
9
|
+
import { RuntimeTermsConsentService, type RuntimeTermsProfile, type TermsCardText } from './runtime-terms-consent.service.js';
|
|
10
|
+
/**
|
|
11
|
+
* The card for Antigravity CLI's Terms.
|
|
12
|
+
*
|
|
13
|
+
* @param machine - This machine's name
|
|
14
|
+
* @returns Title, question and body sections (English, Slack mrkdwn)
|
|
15
|
+
*/
|
|
16
|
+
export declare function antigravityTermsCard(machine: string): TermsCardText;
|
|
17
|
+
/** Antigravity CLI's profile. */
|
|
18
|
+
export declare const ANTIGRAVITY_TERMS_PROFILE: RuntimeTermsProfile;
|
|
19
|
+
/**
|
|
20
|
+
* Name of the harness's dedicated session for a runtime.
|
|
21
|
+
*
|
|
22
|
+
* @param runtime - Runtime id
|
|
23
|
+
* @returns Session name
|
|
24
|
+
*/
|
|
25
|
+
export declare function termsSessionName(runtime: string): string;
|
|
26
|
+
/** What the composition root provides. */
|
|
27
|
+
export interface RuntimeTermsWiringInput {
|
|
28
|
+
crewlyHome: string;
|
|
29
|
+
decisions: DecisionService;
|
|
30
|
+
machineName: () => string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build the service, install it and subscribe it to decision cards.
|
|
34
|
+
*
|
|
35
|
+
* @param input - Composition-root hooks
|
|
36
|
+
* @returns The service
|
|
37
|
+
*/
|
|
38
|
+
export declare function startRuntimeTerms(input: RuntimeTermsWiringInput): RuntimeTermsConsentService;
|
|
39
|
+
//# sourceMappingURL=runtime-terms.wiring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-terms.wiring.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/runtime-terms/runtime-terms.wiring.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGnE,OAAO,EACN,0BAA0B,EAE1B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAElB,MAAM,oCAAoC,CAAC;AAK5C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAYnE;AAED,iCAAiC;AACjC,eAAO,MAAM,yBAAyB,EAAE,mBAoBvC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AA6DD,0CAA0C;AAC1C,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,eAAe,CAAC;IAC3B,WAAW,EAAE,MAAM,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,GAAG,0BAA0B,CAuB5F"}
|