ai-spend-agent 0.9.10 → 0.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +15 -7
- package/dist/workspaceConnect.d.ts +4 -3
- package/dist/workspaceConnect.js +7 -5
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1098,14 +1098,17 @@ async function workspaceCommand(args, runtime) {
|
|
|
1098
1098
|
: fail("Pairing outcome is unknown. Do not replay this response bundle; inspect and revoke the enrollment in Settings before starting another.");
|
|
1099
1099
|
}
|
|
1100
1100
|
if (action === "disconnect") {
|
|
1101
|
-
const result = await disconnectWorkspace({ home: runtime.homeDirectory, transport: runtime.workspaceDisconnectTransport,
|
|
1101
|
+
const result = await disconnectWorkspace({ home: runtime.homeDirectory, retry: args.workspaceDisconnectRetry, transport: runtime.workspaceDisconnectTransport,
|
|
1102
1102
|
confirm: action => consent(action === "abandon_unexchanged"
|
|
1103
1103
|
? "This native request has never attempted exchange. Destroy its unused private pairing key so it can no longer complete enrollment? Cancel any browser challenge in Settings as well. [y/N] "
|
|
1104
|
-
:
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1104
|
+
: action === "retry_revoke"
|
|
1105
|
+
? "Repeat the identical retained disconnect request once? If already revoked, Tilden returns that outcome; otherwise this revokes the same grant. No session facts are sent. Local pairing is removed only after a matching receipt. [y/N] "
|
|
1106
|
+
: "Revoke this machine's Workspace grant and remove its local pairing after the accepted receipt? [y/N] ") });
|
|
1107
|
+
return result.state === "retry_not_pending" ? fail("No uncertain disconnect is retained. Run workspace disconnect without --retry to start a new disconnect.")
|
|
1108
|
+
: result.state === "revoked" ? ok("Workspace revoked this machine grant. Local pairing was removed.")
|
|
1109
|
+
: result.state === "abandoned" ? ok("Unused native pairing key removed. No remote revocation was claimed. Run npx aibill workspace connect to start a new request.")
|
|
1110
|
+
: result.state === "cancelled" ? fail("Pairing kept. Disconnect was not confirmed; no request or key was removed.") : result.state === "not_paired" ? ok("No completed local pairing exists.")
|
|
1111
|
+
: fail(`Disconnect outcome is unknown. Local keys remain and uploads are blocked. Run npx aibill@latest workspace disconnect --retry to review and explicitly repeat the identical retained request once, or inspect this machine at ${WORKSPACE_ORIGIN}/settings/machines.`);
|
|
1109
1112
|
}
|
|
1110
1113
|
const status = await workspaceStatus(runtime.homeDirectory);
|
|
1111
1114
|
if (status.state !== "connected")
|
|
@@ -6756,8 +6759,12 @@ function parseArgs(argv) {
|
|
|
6756
6759
|
parsed.workspaceRestart = true;
|
|
6757
6760
|
rest.shift();
|
|
6758
6761
|
}
|
|
6762
|
+
if (parsed.workspaceAction === "disconnect" && rest.length === 1 && rest[0] === "--retry") {
|
|
6763
|
+
parsed.workspaceDisconnectRetry = true;
|
|
6764
|
+
rest.shift();
|
|
6765
|
+
}
|
|
6759
6766
|
if (rest.length)
|
|
6760
|
-
parsed.parseErrors.push("workspace accepts only connect [response-bundle], connect --restart, push, status, or disconnect");
|
|
6767
|
+
parsed.parseErrors.push("workspace accepts only connect [response-bundle], connect --restart, push, status, or disconnect [--retry]");
|
|
6761
6768
|
}
|
|
6762
6769
|
if (command === "statusline" && rest[0] && !rest[0].startsWith("--")) {
|
|
6763
6770
|
parsed.statuslineAction = rest.shift();
|
|
@@ -7429,6 +7436,7 @@ function helpText(telemetryDisclosure) {
|
|
|
7429
7436
|
" npx aibill workspace push Preview and send local session facts",
|
|
7430
7437
|
" npx aibill workspace status Read local pairing/pending status only",
|
|
7431
7438
|
" npx aibill workspace disconnect Revoke the grant or abandon an unused pairing key",
|
|
7439
|
+
" npx aibill workspace disconnect --retry Confirm one identical uncertain disconnect attempt",
|
|
7432
7440
|
"",
|
|
7433
7441
|
"Add official provider-reported cost (ADMIN/owner-gated):",
|
|
7434
7442
|
" npx aibill connect openai Requires an org-owner Admin credential reference",
|
|
@@ -227,13 +227,14 @@ export declare function finishWorkspaceEnrollment(options: {
|
|
|
227
227
|
}): Promise<{
|
|
228
228
|
state: "connected" | "cancelled" | "unconfirmed";
|
|
229
229
|
}>;
|
|
230
|
-
/**
|
|
230
|
+
/** One native attempt per confirmation. Explicit recovery repeats the retained proof; unknown outcomes keep writes blocked. */
|
|
231
231
|
export declare function disconnectWorkspace(options: {
|
|
232
232
|
home?: string;
|
|
233
|
-
|
|
233
|
+
retry?: boolean;
|
|
234
|
+
confirm: (action: "revoke" | "retry_revoke" | "abandon_unexchanged") => Promise<boolean>;
|
|
234
235
|
transport?: WorkspaceDisconnectTransport;
|
|
235
236
|
}): Promise<{
|
|
236
|
-
state: "revoked" | "abandoned" | "cancelled" | "unconfirmed" | "not_paired";
|
|
237
|
+
state: "revoked" | "abandoned" | "cancelled" | "unconfirmed" | "not_paired" | "retry_not_pending";
|
|
237
238
|
}>;
|
|
238
239
|
export {};
|
|
239
240
|
//# sourceMappingURL=workspaceConnect.d.ts.map
|
package/dist/workspaceConnect.js
CHANGED
|
@@ -668,9 +668,11 @@ export async function finishWorkspaceEnrollment(options) {
|
|
|
668
668
|
}
|
|
669
669
|
});
|
|
670
670
|
}
|
|
671
|
-
/**
|
|
671
|
+
/** One native attempt per confirmation. Explicit recovery repeats the retained proof; unknown outcomes keep writes blocked. */
|
|
672
672
|
export async function disconnectWorkspace(options) {
|
|
673
673
|
return withState(options.home ?? homedir(), async (state, save, path) => {
|
|
674
|
+
if (options.retry && state?.disconnect?.state !== "uncertain")
|
|
675
|
+
return { state: "retry_not_pending" };
|
|
674
676
|
if (!state) {
|
|
675
677
|
const enrollment = await readEnrollment(path);
|
|
676
678
|
if (!enrollment)
|
|
@@ -692,14 +694,14 @@ export async function disconnectWorkspace(options) {
|
|
|
692
694
|
}
|
|
693
695
|
return { state: "abandoned" };
|
|
694
696
|
}
|
|
695
|
-
if (state.disconnect?.state === "uncertain")
|
|
697
|
+
if (state.disconnect?.state === "uncertain" && !options.retry)
|
|
696
698
|
return { state: "unconfirmed" };
|
|
697
|
-
if (!await options.confirm("revoke"))
|
|
699
|
+
if (!await options.confirm(state.disconnect?.state === "uncertain" ? "retry_revoke" : "revoke"))
|
|
698
700
|
return { state: "cancelled" };
|
|
699
|
-
if (
|
|
701
|
+
if (state.disconnect?.state !== "revoked") {
|
|
700
702
|
const proof = { purpose: "machine_disconnect_v1", grantId: state.device.grantId,
|
|
701
703
|
grantRevision: state.device.grantRevision, connectionEpoch: state.device.connectionEpoch,
|
|
702
|
-
requestId: `oref_${randomBytes(32).toString("base64url")}` };
|
|
704
|
+
requestId: state.disconnect?.requestId ?? `oref_${randomBytes(32).toString("base64url")}` };
|
|
703
705
|
const body = { ...proof, publicKey: createPublicKey(state.device.privateKeyPem).export({ format: "jwk" }).x,
|
|
704
706
|
signature: sign(null, Buffer.from(workspaceCanonicalJson(proof)), state.device.privateKeyPem).toString("base64url") };
|
|
705
707
|
const uncertain = { ...state, disconnect: { state: "uncertain", requestId: proof.requestId, revokedAt: null } };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-spend-agent",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.11",
|
|
4
4
|
"funding": "https://asktilden.com",
|
|
5
5
|
"description": "Local-first financial accountability CLI: Claude Code/Codex attribution, provenance, and next actions, plus experimental Gemini CLI cost evidence.",
|
|
6
6
|
"type": "module",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"prepack": "npm run build"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@agent-finops/core": "0.9.
|
|
59
|
-
"@agent-finops/report": "0.9.
|
|
58
|
+
"@agent-finops/core": "0.9.11",
|
|
59
|
+
"@agent-finops/report": "0.9.11",
|
|
60
60
|
"yocto-spinner": "^1.2.0"
|
|
61
61
|
}
|
|
62
62
|
}
|