@whittlelabs/trivet 0.1.9 → 0.1.10
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/bin.js +125 -63
- package/bin.js.map +3 -3
- package/package.json +1 -1
package/bin.js
CHANGED
|
@@ -67941,6 +67941,10 @@ var require_store = __commonJS({
|
|
|
67941
67941
|
await fsp.rename(tmp, this.path);
|
|
67942
67942
|
await fsp.chmod(this.path, 384);
|
|
67943
67943
|
}
|
|
67944
|
+
/** Forget the pairing: `revoke` of this machine, whose credential is dead. */
|
|
67945
|
+
async remove() {
|
|
67946
|
+
await fsp.rm(this.path, { force: true });
|
|
67947
|
+
}
|
|
67944
67948
|
};
|
|
67945
67949
|
exports2.PairingConfigStore = PairingConfigStore;
|
|
67946
67950
|
}
|
|
@@ -75761,38 +75765,55 @@ var require_pairings = __commonJS({
|
|
|
75761
75765
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
75762
75766
|
exports2.listPairings = listPairings;
|
|
75763
75767
|
exports2.revokePairing = revokePairing;
|
|
75768
|
+
var keep_1 = require_keep();
|
|
75769
|
+
var keep_2 = require_dist4();
|
|
75770
|
+
var version_check_1 = require_version_check();
|
|
75771
|
+
var PAGE_LIMIT = 100;
|
|
75764
75772
|
async function listPairings(opts) {
|
|
75765
|
-
const
|
|
75766
|
-
|
|
75767
|
-
|
|
75768
|
-
|
|
75769
|
-
|
|
75770
|
-
|
|
75771
|
-
|
|
75773
|
+
const machines = [];
|
|
75774
|
+
for (let offset = 0; ; offset += PAGE_LIMIT) {
|
|
75775
|
+
const { pairings, total } = await ask(opts, (keep) => keep.get("/api/pairings", {
|
|
75776
|
+
query: { limit: PAGE_LIMIT, offset },
|
|
75777
|
+
headers: { Authorization: `Bearer ${opts.accessToken}` }
|
|
75778
|
+
}));
|
|
75779
|
+
machines.push(...pairings);
|
|
75780
|
+
if (pairings.length < PAGE_LIMIT || offset + pairings.length >= total)
|
|
75781
|
+
return machines;
|
|
75782
|
+
}
|
|
75772
75783
|
}
|
|
75773
75784
|
async function revokePairing(opts) {
|
|
75774
|
-
|
|
75775
|
-
|
|
75776
|
-
const response = await fetcher(url, {
|
|
75777
|
-
method: "DELETE",
|
|
75785
|
+
await ask(opts, (keep) => keep.delete("/api/pairings/{pairingId}", {
|
|
75786
|
+
path: { pairingId: opts.pairingId },
|
|
75778
75787
|
headers: { Authorization: `Bearer ${opts.accessToken}` }
|
|
75779
|
-
});
|
|
75780
|
-
if (!response.ok) {
|
|
75781
|
-
throw new Error(`Revoke failed with status ${response.status}`);
|
|
75782
|
-
}
|
|
75788
|
+
}));
|
|
75783
75789
|
}
|
|
75784
|
-
async function
|
|
75785
|
-
|
|
75786
|
-
|
|
75787
|
-
|
|
75788
|
-
|
|
75789
|
-
|
|
75790
|
-
|
|
75791
|
-
|
|
75792
|
-
|
|
75793
|
-
|
|
75790
|
+
async function ask(opts, send) {
|
|
75791
|
+
const fetcher = opts.fetcher ?? globalThis.fetch;
|
|
75792
|
+
let belowFloor;
|
|
75793
|
+
const transport = async (url, init2) => {
|
|
75794
|
+
const response = await fetcher(url, init2);
|
|
75795
|
+
try {
|
|
75796
|
+
(0, version_check_1.checkResponseMinVersion)({
|
|
75797
|
+
response,
|
|
75798
|
+
productId: opts.brand.product.id,
|
|
75799
|
+
currentVersion: opts.brand.product.version,
|
|
75800
|
+
packageName: opts.brand.product.packageName
|
|
75801
|
+
});
|
|
75802
|
+
} catch (err2) {
|
|
75803
|
+
belowFloor = err2;
|
|
75804
|
+
throw err2;
|
|
75805
|
+
}
|
|
75806
|
+
return response;
|
|
75807
|
+
};
|
|
75808
|
+
const result = await send((0, keep_1.createClient)({ baseUrl: opts.keepApiUrl.replace(/\/$/, ""), transport }));
|
|
75809
|
+
if (belowFloor !== void 0)
|
|
75810
|
+
throw belowFloor;
|
|
75811
|
+
if (result.success)
|
|
75812
|
+
return result.data;
|
|
75813
|
+
if (result.error.status === 401) {
|
|
75814
|
+
throw new keep_2.AgentCredentialRevokedError(`Keep refused this machine's token (401): ${result.error.message}`);
|
|
75794
75815
|
}
|
|
75795
|
-
|
|
75816
|
+
throw new Error(result.error.message || `Keep answered ${result.error.status ?? "nothing"}.`);
|
|
75796
75817
|
}
|
|
75797
75818
|
}
|
|
75798
75819
|
});
|
|
@@ -75803,42 +75824,75 @@ var require_list = __commonJS({
|
|
|
75803
75824
|
"use strict";
|
|
75804
75825
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
75805
75826
|
exports2.buildListCommand = buildListCommand;
|
|
75827
|
+
exports2.mintAgentToken = mintAgentToken;
|
|
75828
|
+
exports2.renderPairings = renderPairings;
|
|
75806
75829
|
var commander_1 = require_commander();
|
|
75807
75830
|
var keep_1 = require_dist4();
|
|
75808
75831
|
var apply_1 = require_apply();
|
|
75809
75832
|
var store_1 = require_store();
|
|
75810
75833
|
var pairings_1 = require_pairings();
|
|
75834
|
+
var version_check_1 = require_version_check();
|
|
75835
|
+
var typed_exit_1 = require_typed_exit();
|
|
75811
75836
|
function buildListCommand(brand) {
|
|
75812
|
-
return new commander_1.Command("list").description(`List paired ${brand.product.title}
|
|
75837
|
+
return new commander_1.Command("list").description(`List the machines paired to your account as a ${brand.product.title}`).option("-p, --profile <name>", 'Config profile whose pairing credentials to use (default "default")').option("--json", "Print the pairings as JSON and nothing else").action(async (options) => {
|
|
75813
75838
|
try {
|
|
75814
75839
|
const paths = (0, apply_1.resolvePaths)(brand, (0, apply_1.resolveProfile)(brand, options.profile));
|
|
75815
|
-
const
|
|
75816
|
-
const
|
|
75817
|
-
|
|
75840
|
+
const pairing = new store_1.PairingConfigStore(paths.configFile).read();
|
|
75841
|
+
const machines = await (0, pairings_1.listPairings)({
|
|
75842
|
+
brand,
|
|
75818
75843
|
keepApiUrl: pairing.keepApiUrl,
|
|
75819
|
-
|
|
75820
|
-
clientSecret: pairing.credentials.clientSecret
|
|
75844
|
+
accessToken: await mintAgentToken(pairing, brand)
|
|
75821
75845
|
});
|
|
75822
|
-
|
|
75823
|
-
|
|
75824
|
-
throw new Error("Failed to mint service token from stored credentials.");
|
|
75825
|
-
}
|
|
75826
|
-
const machines = await (0, pairings_1.listPairings)({ brand, accessToken });
|
|
75827
|
-
if (machines.length === 0) {
|
|
75828
|
-
console.log("No paired machines.");
|
|
75846
|
+
if (options.json) {
|
|
75847
|
+
console.log(JSON.stringify(machines, null, 2));
|
|
75829
75848
|
return;
|
|
75830
75849
|
}
|
|
75831
|
-
|
|
75832
|
-
|
|
75833
|
-
console.log([m.id, m.name, m.hostname ?? "-", m.pairedAt ?? "-", m.lastSeenAt ?? "-", m.active].join(" "));
|
|
75834
|
-
}
|
|
75850
|
+
for (const line of renderPairings(machines, pairing.serviceIdentity.id))
|
|
75851
|
+
console.log(line);
|
|
75835
75852
|
} catch (err2) {
|
|
75853
|
+
if ((0, typed_exit_1.isTypedExit)(err2))
|
|
75854
|
+
throw err2;
|
|
75836
75855
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
75837
75856
|
console.error(`list failed: ${message}`);
|
|
75838
75857
|
process.exit(1);
|
|
75839
75858
|
}
|
|
75840
75859
|
});
|
|
75841
75860
|
}
|
|
75861
|
+
async function mintAgentToken(pairing, brand) {
|
|
75862
|
+
const token = await new keep_1.AgentTokenManager({
|
|
75863
|
+
keepApiUrl: pairing.keepApiUrl,
|
|
75864
|
+
clientId: pairing.credentials.clientId,
|
|
75865
|
+
clientSecret: pairing.credentials.clientSecret,
|
|
75866
|
+
onResponse: (response) => (0, version_check_1.checkResponseMinVersion)({
|
|
75867
|
+
response,
|
|
75868
|
+
productId: brand.product.id,
|
|
75869
|
+
currentVersion: brand.product.version,
|
|
75870
|
+
packageName: brand.product.packageName
|
|
75871
|
+
})
|
|
75872
|
+
}).getToken();
|
|
75873
|
+
if (!token)
|
|
75874
|
+
throw new Error("This pairing holds no credentials to mint a token with. Run `init` again.");
|
|
75875
|
+
return token;
|
|
75876
|
+
}
|
|
75877
|
+
function renderPairings(machines, self2) {
|
|
75878
|
+
if (machines.length === 0)
|
|
75879
|
+
return ["No paired machines."];
|
|
75880
|
+
const header = ["", "ID", "NAME", "HOST", "PAIRED", "LAST USED"];
|
|
75881
|
+
const rows = machines.map((m) => [
|
|
75882
|
+
m.id === self2 ? "*" : "",
|
|
75883
|
+
m.id,
|
|
75884
|
+
m.displayName,
|
|
75885
|
+
m.hostname ?? "-",
|
|
75886
|
+
m.pairedAt.slice(0, 10),
|
|
75887
|
+
m.lastUsedAt ? m.lastUsedAt.slice(0, 16).replace("T", " ") : "never"
|
|
75888
|
+
]);
|
|
75889
|
+
const widths = header.map((h, i2) => Math.max(h.length, ...rows.map((r) => r[i2].length)));
|
|
75890
|
+
const line = (cells) => cells.map((cell, i2) => cell.padEnd(widths[i2])).join(" ").trimEnd();
|
|
75891
|
+
const lines = [line(header), ...rows.map(line)];
|
|
75892
|
+
if (machines.some((m) => m.id === self2))
|
|
75893
|
+
lines.push("", "* this machine");
|
|
75894
|
+
return lines;
|
|
75895
|
+
}
|
|
75842
75896
|
}
|
|
75843
75897
|
});
|
|
75844
75898
|
|
|
@@ -75848,43 +75902,51 @@ var require_revoke = __commonJS({
|
|
|
75848
75902
|
"use strict";
|
|
75849
75903
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
75850
75904
|
exports2.buildRevokeCommand = buildRevokeCommand;
|
|
75905
|
+
exports2.pickMachine = pickMachine;
|
|
75851
75906
|
var commander_1 = require_commander();
|
|
75852
|
-
var keep_1 = require_dist4();
|
|
75853
75907
|
var apply_1 = require_apply();
|
|
75854
75908
|
var store_1 = require_store();
|
|
75855
75909
|
var pairings_1 = require_pairings();
|
|
75910
|
+
var list_1 = require_list();
|
|
75911
|
+
var typed_exit_1 = require_typed_exit();
|
|
75856
75912
|
function buildRevokeCommand(brand) {
|
|
75857
|
-
return new commander_1.Command("revoke").description(`Revoke a paired ${brand.product.title}`).argument("<
|
|
75913
|
+
return new commander_1.Command("revoke").description(`Revoke a machine paired to your account as a ${brand.product.title} (this one included)`).argument("<machine>", "The machine to revoke: its id, the start of its id, its name, or its host, as `list` shows them").option("-p, --profile <name>", 'Config profile whose pairing credentials to use (default "default")').action(async (machine, options) => {
|
|
75858
75914
|
try {
|
|
75859
75915
|
const paths = (0, apply_1.resolvePaths)(brand, (0, apply_1.resolveProfile)(brand, options.profile));
|
|
75860
75916
|
const store = new store_1.PairingConfigStore(paths.configFile);
|
|
75861
75917
|
const pairing = store.read();
|
|
75862
|
-
const
|
|
75863
|
-
|
|
75864
|
-
|
|
75865
|
-
clientSecret: pairing.credentials.clientSecret
|
|
75866
|
-
});
|
|
75867
|
-
const accessToken = await tokens.getToken();
|
|
75868
|
-
if (!accessToken) {
|
|
75869
|
-
throw new Error("Failed to mint service token from stored credentials.");
|
|
75870
|
-
}
|
|
75871
|
-
const machines = await (0, pairings_1.listPairings)({ brand, accessToken });
|
|
75872
|
-
const target = machines.find((m) => m.id === nameOrId || m.name === nameOrId || m.displayName === nameOrId);
|
|
75873
|
-
if (!target) {
|
|
75874
|
-
throw new Error(`No paired machine matches "${nameOrId}".`);
|
|
75875
|
-
}
|
|
75918
|
+
const api = { brand, keepApiUrl: pairing.keepApiUrl, accessToken: await (0, list_1.mintAgentToken)(pairing, brand) };
|
|
75919
|
+
const target = pickMachine(await (0, pairings_1.listPairings)(api), machine);
|
|
75920
|
+
await (0, pairings_1.revokePairing)({ ...api, pairingId: target.id });
|
|
75876
75921
|
if (target.id === pairing.serviceIdentity.id) {
|
|
75877
|
-
|
|
75922
|
+
await store.remove();
|
|
75923
|
+
console.log(`Revoked this machine, "${target.displayName}" (${target.id}).`);
|
|
75924
|
+
console.log(`Its pairing is removed from ${paths.configFile}; run \`${brand.product.cliBinary} init\` to pair it again.`);
|
|
75925
|
+
return;
|
|
75878
75926
|
}
|
|
75879
|
-
|
|
75880
|
-
console.log(`Revoked ${target.name} (${target.id}).`);
|
|
75927
|
+
console.log(`Revoked "${target.displayName}" (${target.id}). It can take no more work.`);
|
|
75881
75928
|
} catch (err2) {
|
|
75929
|
+
if ((0, typed_exit_1.isTypedExit)(err2))
|
|
75930
|
+
throw err2;
|
|
75882
75931
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
75883
75932
|
console.error(`revoke failed: ${message}`);
|
|
75884
75933
|
process.exit(1);
|
|
75885
75934
|
}
|
|
75886
75935
|
});
|
|
75887
75936
|
}
|
|
75937
|
+
function pickMachine(machines, query) {
|
|
75938
|
+
const exact = machines.find((m) => m.id === query);
|
|
75939
|
+
if (exact)
|
|
75940
|
+
return exact;
|
|
75941
|
+
const candidates = machines.filter((m) => m.id.startsWith(query) || m.name === query || m.displayName === query || m.hostname === query);
|
|
75942
|
+
if (candidates.length === 1)
|
|
75943
|
+
return candidates[0];
|
|
75944
|
+
if (candidates.length === 0) {
|
|
75945
|
+
throw new Error(`No paired machine matches "${query}". Run \`list\` to see them.`);
|
|
75946
|
+
}
|
|
75947
|
+
const named = candidates.map((m) => ` ${m.id} ${m.displayName}${m.hostname ? ` (${m.hostname})` : ""}`);
|
|
75948
|
+
throw new Error([`"${query}" matches ${candidates.length} machines; name one by its id:`, ...named].join("\n"));
|
|
75949
|
+
}
|
|
75888
75950
|
}
|
|
75889
75951
|
});
|
|
75890
75952
|
|
|
@@ -76390,7 +76452,7 @@ var import_shuttle2 = __toESM(require_dist8());
|
|
|
76390
76452
|
|
|
76391
76453
|
// src/brand.ts
|
|
76392
76454
|
var import_shuttle = __toESM(require_dist8());
|
|
76393
|
-
var buildVersion = true ? "0.1.
|
|
76455
|
+
var buildVersion = true ? "0.1.10" : pkg.version;
|
|
76394
76456
|
var EXECUTORS = ["claude-code"];
|
|
76395
76457
|
var trivetBrand = {
|
|
76396
76458
|
product: {
|