@apilift/cli 1.5.13 → 1.5.14
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.
|
@@ -20067,7 +20067,6 @@ var CaptureStore = class {
|
|
|
20067
20067
|
const rows = this.db.prepare("SELECT id,owner_pid,owner_started_at,expires_at FROM scopes WHERE retained_at IS NULL").all();
|
|
20068
20068
|
const stale = rows.filter((row) => row.expires_at <= now || !this.alive(row.owner_pid, row.owner_started_at));
|
|
20069
20069
|
for (const row of stale) this.releaseStaleScope(row.id);
|
|
20070
|
-
this.db.prepare("DELETE FROM jobs WHERE status='delivered' AND delivered_at < ?").run(now - 6e5);
|
|
20071
20070
|
this.db.prepare("DELETE FROM bridge_demands WHERE expires_at <= ?").run(now);
|
|
20072
20071
|
}
|
|
20073
20072
|
releaseStaleScope(id2) {
|
package/dist/apilift.js
CHANGED
|
@@ -42340,11 +42340,31 @@ async function releaseCapture(state, draftId, row, root2) {
|
|
|
42340
42340
|
await (await captureClient(root2, false)).retainScope(row.scope_id);
|
|
42341
42341
|
state.db.prepare("UPDATE discovery_capture SET evidence_scope_id=COALESCE(evidence_scope_id,scope_id),scope_id=NULL WHERE draft_id=?").run(draftId);
|
|
42342
42342
|
}
|
|
42343
|
+
async function captureJobResult(client, id2) {
|
|
42344
|
+
try {
|
|
42345
|
+
return await client.jobResult(id2);
|
|
42346
|
+
} catch (error62) {
|
|
42347
|
+
if (error62.code === "job-missing") return { status: "missing" };
|
|
42348
|
+
throw error62;
|
|
42349
|
+
}
|
|
42350
|
+
}
|
|
42351
|
+
async function releaseUnconfirmedCapture(client, state, draftId, scopeId, root2) {
|
|
42352
|
+
try {
|
|
42353
|
+
await client.retainScope(scopeId);
|
|
42354
|
+
} catch (error62) {
|
|
42355
|
+
if (error62.code === "boundary-unconfirmed") return false;
|
|
42356
|
+
throw error62;
|
|
42357
|
+
}
|
|
42358
|
+
const entries = await retainedCaptureEntries(client, scopeId);
|
|
42359
|
+
state.db.prepare("UPDATE discovery_capture SET evidence_scope_id=COALESCE(evidence_scope_id,scope_id),scope_id=NULL,job_id=NULL,phase='lost',entries_json=? WHERE draft_id=?").run(JSON.stringify(entries), draftId);
|
|
42360
|
+
withBaselines(root2, (baselines) => baselines.closeObservation(draftId, "capture-lost"));
|
|
42361
|
+
return true;
|
|
42362
|
+
}
|
|
42343
42363
|
async function awaitCaptureJob(client, id2) {
|
|
42344
42364
|
const deadline = Date.now() + 3e4;
|
|
42345
42365
|
do {
|
|
42346
|
-
const job = await client
|
|
42347
|
-
if (
|
|
42366
|
+
const job = await captureJobResult(client, id2);
|
|
42367
|
+
if (["delivered", "uncertain", "missing"].includes(job.status)) return job;
|
|
42348
42368
|
await new Promise((resolve10) => setTimeout(resolve10, 200));
|
|
42349
42369
|
} while (Date.now() < deadline);
|
|
42350
42370
|
return { status: "pending" };
|
|
@@ -42620,8 +42640,8 @@ ${detail}
|
|
|
42620
42640
|
const job = await awaitCaptureJob(client, id2);
|
|
42621
42641
|
if (job.status !== "delivered" || job.result?.state !== "recording") return fail5(`Recording start is unconfirmed (${job.status}). Do not operate the app. Retry ${command4(invocation, "discover capture start")} after inspecting ${command4(invocation, "discover status")}.
|
|
42622
42642
|
`, 12);
|
|
42623
|
-
await client.acknowledgeJob(id2);
|
|
42624
42643
|
state.db.prepare("UPDATE discovery_capture SET phase='recording',job_id=NULL WHERE draft_id=?").run(draft.id);
|
|
42644
|
+
await client.acknowledgeJob(id2);
|
|
42625
42645
|
withBaselines(root2, (baselines) => baselines.startCapture(draft.id, draft.appId, session.id));
|
|
42626
42646
|
withBaselines(root2, (baselines) => baselines.finishPreparation(session.id, draft.appSlug, draft.appId, "browser"));
|
|
42627
42647
|
return ok4(`Recording ${draft.name} in the configured tab. Declared effect: ${effect2}. Explicit inputs: ${Object.keys(envelope.verification.inputs).join(", ") || "none"}.
|
|
@@ -42663,14 +42683,15 @@ Review: ${command4(invocation, "discover status")}
|
|
|
42663
42683
|
return fail5(`capture-scope-lost \u2014 The recorder exited before it confirmed the recording boundary. Admission is closed, but the app operation may have happened. Do not repeat a mutation. Inspect app state and the retained draft: ${draft.filePath}
|
|
42664
42684
|
`, 12);
|
|
42665
42685
|
}
|
|
42686
|
+
const previous = row.phase === "stopping" && row.job_id ? await captureJobResult(client, row.job_id) : null;
|
|
42687
|
+
if (previous?.status === "missing" && await releaseUnconfirmedCapture(client, state, draft.id, row.scope_id, root2)) return ok4(lostCaptureMessage);
|
|
42666
42688
|
client = await captureClient(root2);
|
|
42667
42689
|
let stopId = row.phase === "stopping" && row.job_id ? row.job_id : randomUUID9();
|
|
42668
42690
|
if (row.phase !== "stopping") {
|
|
42669
42691
|
state.db.prepare("UPDATE discovery_capture SET phase='stopping',job_id=? WHERE draft_id=?").run(stopId, draft.id);
|
|
42670
42692
|
await client.enqueueJob(row.scope_id, { job: { id: stopId, kind: "stop" } });
|
|
42671
42693
|
} else if (row.job_id) {
|
|
42672
|
-
|
|
42673
|
-
if (previous.status === "delivered" && previous.result?.boundaryConfirmed !== true) {
|
|
42694
|
+
if (previous?.status === "missing" || previous?.status === "delivered" && previous.result?.boundaryConfirmed !== true) {
|
|
42674
42695
|
const failedId = stopId;
|
|
42675
42696
|
stopId = randomUUID9();
|
|
42676
42697
|
state.db.prepare("UPDATE discovery_capture SET job_id=? WHERE draft_id=?").run(stopId, draft.id);
|
|
@@ -42679,11 +42700,12 @@ Review: ${command4(invocation, "discover status")}
|
|
|
42679
42700
|
}
|
|
42680
42701
|
}
|
|
42681
42702
|
const job = await awaitCaptureJob(client, stopId);
|
|
42703
|
+
if (job.result?.boundaryConfirmed !== true && key === "discoverCaptureCancel" && await releaseUnconfirmedCapture(client, state, draft.id, row.scope_id, root2)) return ok4(lostCaptureMessage);
|
|
42682
42704
|
if (job.status !== "delivered" || job.result?.boundaryConfirmed !== true) return fail5(`Recording closure is unconfirmed. Do not repeat the app operation. Retry the same ${command4(invocation, key === "discoverCaptureCancel" ? "discover capture cancel" : "discover capture stop")}.
|
|
42683
42705
|
`, 12);
|
|
42684
42706
|
const entries2 = await retainedCaptureEntries(client, row.scope_id);
|
|
42685
|
-
await client.acknowledgeJob(stopId);
|
|
42686
42707
|
state.db.prepare("UPDATE discovery_capture SET job_id=NULL,phase='closed',entries_json=? WHERE draft_id=?").run(JSON.stringify(entries2), draft.id);
|
|
42708
|
+
await client.acknowledgeJob(stopId);
|
|
42687
42709
|
if (key === "discoverCaptureCancel") {
|
|
42688
42710
|
withBaselines(root2, (baselines) => baselines.cancelCapture(draft.id));
|
|
42689
42711
|
await releaseCapture(state, draft.id, row, root2);
|
|
@@ -42790,7 +42812,7 @@ Defer this action with ${command4(invocation, "discover defer")} to release its
|
|
|
42790
42812
|
return fail5(`Unknown capture command ${key}.
|
|
42791
42813
|
`);
|
|
42792
42814
|
}
|
|
42793
|
-
var import__4, ok4, fail5, backendKind, label, command4, actionNameHelp, issueLines, ajv4, sessionRequired, CaptureEvidenceUnavailable, implicitOrStaticHeader, authHeader, sensitiveName;
|
|
42815
|
+
var import__4, ok4, fail5, backendKind, label, command4, actionNameHelp, issueLines, ajv4, sessionRequired, CaptureEvidenceUnavailable, lostCaptureMessage, implicitOrStaticHeader, authHeader, sensitiveName;
|
|
42794
42816
|
var init_discover = __esm({
|
|
42795
42817
|
"src/commands/discover.ts"() {
|
|
42796
42818
|
"use strict";
|
|
@@ -42822,6 +42844,7 @@ var init_discover = __esm({
|
|
|
42822
42844
|
`);
|
|
42823
42845
|
CaptureEvidenceUnavailable = class extends Error {
|
|
42824
42846
|
};
|
|
42847
|
+
lostCaptureMessage = "Recording admission is closed. Its stop boundary was not confirmed. Inspect app state before any mutation; retained evidence and drafts remain available. No app operation was repeated.\n";
|
|
42825
42848
|
implicitOrStaticHeader = /^(accept(?:-.*)?|accept-encoding|connection|content-length|content-type|cookie|host|origin|referer|user-agent|sec-.*)$/i;
|
|
42826
42849
|
authHeader = /^(?:authorization|proxy-authorization|(?:x-|x_)?[a-z0-9_-]*(?:auth|token|key)[a-z0-9_-]*)$/i;
|
|
42827
42850
|
sensitiveName = /token|secret|password|cookie|authorization|api[_-]?key|session/i;
|
|
@@ -46403,6 +46426,10 @@ ${next2}
|
|
|
46403
46426
|
Fix the local Chrome registration and retry:
|
|
46404
46427
|
${prefix} setup continue
|
|
46405
46428
|
`);
|
|
46429
|
+
}
|
|
46430
|
+
if (state.db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='discovery_capture'").get() && state.db.prepare("SELECT 1 FROM discovery_capture c JOIN selected_discovery_draft s ON s.draft_id=c.draft_id JOIN discovery_draft d ON d.id=c.draft_id WHERE s.session_id=? AND d.owner_session_id=? AND c.scope_id IS NOT NULL AND c.phase IN ('starting','stopping')").get(session.id, session.id)) {
|
|
46431
|
+
return { ...result2(`${JSON.stringify({ action: "agent", instruction: "Settle this session's pending recording with repairCommand, then run resumeCommand. This preserves drafts and captured evidence. Do not repeat an app operation or ask the user to toggle the extension.", repairCommand: `${prefix} discover capture cancel`, resumeCommand: `${prefix} setup continue` })}
|
|
46432
|
+
`), stdoutJson: true };
|
|
46406
46433
|
}
|
|
46407
46434
|
let bridgeError, connected = false;
|
|
46408
46435
|
try {
|
|
@@ -7,7 +7,9 @@ description: Link Apilift to this agent and check installation readiness.
|
|
|
7
7
|
|
|
8
8
|
Run `apilift` and follow the commands it prints. If it reports that linking is needed, run `apilift setup` and follow its returned step. Only a person can sign in, enter a one-time link code, provision a credential, or complete browser login. Use `apilift doctor` when setup or a selected app reports an installation problem.
|
|
9
9
|
|
|
10
|
-
Only a person installs or enables browser extensions and configures the agent’s Chrome connection. Never attempt those actions through browser tools. When setup returns `action: "user"`, send its `userMessage` unchanged as your entire response and wait. Resume with its `resumeCommand` when the user returns. For `action: "agent"`, perform the browser check yourself
|
|
10
|
+
Only a person installs or enables browser extensions and configures the agent’s Chrome connection. Never attempt those actions through browser tools. When setup returns `action: "user"`, send its `userMessage` unchanged as your entire response and wait. Resume with its `resumeCommand` when the user returns. For `action: "agent"`, run its `repairCommand` when present, then its `resumeCommand`; otherwise perform the returned browser check yourself. If that check requires Chrome tools and they are unavailable, send `onBrowserUnavailable.userMessage` unchanged and wait.
|
|
11
|
+
|
|
12
|
+
Recover an existing connection through the supported CLI yourself. A queued browser job or recorder error does not establish that the extension is missing or disabled. Settle this session’s pending recording with the returned stop/cancel command, preserve its drafts and evidence, and follow the live setup check. Do not ask a person to toggle or reinstall an extension merely because a recorder command failed. Never operate another session’s tab or repeat a possibly dispatched app mutation to repair the connection.
|
|
11
13
|
|
|
12
14
|
When setup returns `action: "complete"`, installation is finished. For a setup-only request, send its `userMessage` unchanged as your entire response and wait for the user to name an app and task. Do not append verification details or connection-preservation status. If setup unblocked app work the user already requested, continue that work instead of asking them to choose again.
|
|
13
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apilift/cli",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.14",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": ">=24.16.0 <27"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "74f177d77f68a31b81741e277ce3d6e6add05622",
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|
|
43
43
|
"url": "git+https://github.com/egor-sergeev/apilift.git",
|