@lazehq/cli 0.1.34 → 0.1.35
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/laze.mjs +400 -288
- package/package.json +1 -1
package/dist/laze.mjs
CHANGED
|
@@ -35708,7 +35708,7 @@ function flagText({
|
|
|
35708
35708
|
}
|
|
35709
35709
|
|
|
35710
35710
|
// src/rules/cli-version.rules.ts
|
|
35711
|
-
var STAMPED = "0.1.
|
|
35711
|
+
var STAMPED = "0.1.35";
|
|
35712
35712
|
function cliVersionOf({ stamped = STAMPED } = {}) {
|
|
35713
35713
|
return stamped.startsWith("__") ? "dev" : stamped;
|
|
35714
35714
|
}
|
|
@@ -62006,7 +62006,9 @@ var updateVaultConnectionInputSchemaDefinition = external_exports.object({
|
|
|
62006
62006
|
maxLeaseSeconds: external_exports.number().int().positive().max(VAULT_MAX_LEASE_SECONDS).nullable().optional(),
|
|
62007
62007
|
everyUseAsks: external_exports.boolean().optional(),
|
|
62008
62008
|
secret: vaultSecretBundleSchema.optional(),
|
|
62009
|
-
egress: vaultEgressTargetSchema.nullable().optional()
|
|
62009
|
+
egress: vaultEgressTargetSchema.nullable().optional(),
|
|
62010
|
+
/** A fresh passkey or Face ID proof, needed to lower a key from Always ask or Human only. */
|
|
62011
|
+
reauthToken: external_exports.string().min(1).optional()
|
|
62010
62012
|
});
|
|
62011
62013
|
var updateVaultConnectionInputSchema = updateVaultConnectionInputSchemaDefinition;
|
|
62012
62014
|
var vaultGrantSubjectSchemaDefinition = external_exports.object({
|
|
@@ -62023,7 +62025,9 @@ var vaultGrantSchemaDefinition = external_exports.object({
|
|
|
62023
62025
|
lend: external_exports.boolean(),
|
|
62024
62026
|
grantedByUserId: external_exports.string(),
|
|
62025
62027
|
expiresAt: external_exports.iso.datetime().nullable(),
|
|
62026
|
-
createdAt: external_exports.iso.datetime()
|
|
62028
|
+
createdAt: external_exports.iso.datetime(),
|
|
62029
|
+
/** A share asked from the CLI or by an agent: nothing reaches it until the owner's passkey. */
|
|
62030
|
+
awaitingOwner: external_exports.boolean().optional()
|
|
62027
62031
|
});
|
|
62028
62032
|
var vaultGrantSchema = vaultGrantSchemaDefinition;
|
|
62029
62033
|
var grantVaultConnectionInputSchemaDefinition = external_exports.object({
|
|
@@ -62041,6 +62045,33 @@ var lendVaultConnectionInputSchemaDefinition = external_exports.object({
|
|
|
62041
62045
|
durationSeconds: external_exports.number().int().positive().nullable().default(null)
|
|
62042
62046
|
});
|
|
62043
62047
|
var lendVaultConnectionInputSchema = lendVaultConnectionInputSchemaDefinition;
|
|
62048
|
+
var shareVaultConnectionInputSchemaDefinition = external_exports.object({
|
|
62049
|
+
workspaceId: external_exports.string().min(1),
|
|
62050
|
+
connectionId: external_exports.string().min(1),
|
|
62051
|
+
/** The teammate whose own agents may use the key; they never see its value. */
|
|
62052
|
+
userId: external_exports.string().min(1),
|
|
62053
|
+
durationSeconds: external_exports.number().int().positive().nullable().default(null),
|
|
62054
|
+
/** A fresh passkey or Face ID proof makes the share live; without one it waits for the owner. */
|
|
62055
|
+
reauthToken: external_exports.string().min(1).optional()
|
|
62056
|
+
});
|
|
62057
|
+
var shareVaultConnectionInputSchema = shareVaultConnectionInputSchemaDefinition;
|
|
62058
|
+
var approveVaultShareInputSchemaDefinition = external_exports.object({
|
|
62059
|
+
workspaceId: external_exports.string().min(1),
|
|
62060
|
+
grantId: external_exports.string().min(1),
|
|
62061
|
+
reauthToken: external_exports.string().min(1)
|
|
62062
|
+
});
|
|
62063
|
+
var approveVaultShareInputSchema = approveVaultShareInputSchemaDefinition;
|
|
62064
|
+
var requestVaultShareInputSchemaDefinition = external_exports.object({
|
|
62065
|
+
turnToken: external_exports.string().min(1),
|
|
62066
|
+
connection: external_exports.string().min(1),
|
|
62067
|
+
userId: external_exports.string().min(1),
|
|
62068
|
+
durationSeconds: external_exports.number().int().positive().nullable().default(null)
|
|
62069
|
+
});
|
|
62070
|
+
var setVaultLevelInTurnInputSchemaDefinition = external_exports.object({
|
|
62071
|
+
turnToken: external_exports.string().min(1),
|
|
62072
|
+
connection: external_exports.string().min(1),
|
|
62073
|
+
sensitivity: vaultSensitivitySchema
|
|
62074
|
+
});
|
|
62044
62075
|
var vaultAgentKindSchema = external_exports.enum(["personal", "team"]);
|
|
62045
62076
|
var openVaultTurnInputSchemaDefinition = external_exports.object({
|
|
62046
62077
|
workspaceId: external_exports.string().min(1),
|
|
@@ -62298,7 +62329,14 @@ var vaultConnectionUseSchemaDefinition = external_exports.object({
|
|
|
62298
62329
|
leaseId: external_exports.string().nullable().default(null),
|
|
62299
62330
|
origin: vaultUseOriginSchema.nullable().default(null),
|
|
62300
62331
|
/** How a person's read happened: `page` (Reveal) or `own_secret` (the CLI or Laze for them). */
|
|
62301
|
-
via: external_exports.string().nullable().default(null)
|
|
62332
|
+
via: external_exports.string().nullable().default(null),
|
|
62333
|
+
/** On a share or a tier change: the person it named, the new tier, and the proof used. */
|
|
62334
|
+
change: external_exports.object({
|
|
62335
|
+
subjectUserId: external_exports.string().nullable(),
|
|
62336
|
+
to: vaultSensitivitySchema.nullable(),
|
|
62337
|
+
direction: external_exports.enum(["raised", "lowered"]).nullable(),
|
|
62338
|
+
method: external_exports.string().nullable()
|
|
62339
|
+
}).nullable().optional()
|
|
62302
62340
|
});
|
|
62303
62341
|
var vaultConnectionUseSchema = vaultConnectionUseSchemaDefinition;
|
|
62304
62342
|
var vaultRevokeAtProviderSchema = external_exports.enum(["revoked", "failed", "not_supported"]);
|
|
@@ -62395,7 +62433,7 @@ var vaultTrpc = defineTrpcContract("vault").mutation("createConnection").withInp
|
|
|
62395
62433
|
reason: external_exports.string().trim().min(1).max(200),
|
|
62396
62434
|
reauthToken: external_exports.string().min(1).max(200).optional()
|
|
62397
62435
|
})
|
|
62398
|
-
).withOutput(external_exports.object({ fields: external_exports.record(external_exports.string(), external_exports.string()) })).mutation("beginReauth").withInput(workspaceInput).withOutput(vaultReauthChallengeSchema).mutation("confirmReauth").withInput(confirmVaultReauthInputSchema).withOutput(vaultReauthProofSchema).mutation("grantConnection").withInput(grantVaultConnectionInputSchema).withOutput(vaultGrantSchema).mutation("lendToChannel").withInput(lendVaultConnectionInputSchema).withOutput(vaultGrantSchema).mutation("revokeGrant").withInput(external_exports.object({ workspaceId: external_exports.string().min(1), grantId: external_exports.string().min(1) })).withOutput(external_exports.object({ revoked: external_exports.literal(true) })).query("listGrants").withInput(connectionInput).withOutput(external_exports.array(vaultGrantSchema)).query("listApprovals").withInput(external_exports.object({ ...workspaceInput.shape, state: vaultApprovalStateSchema.optional() })).withOutput(external_exports.array(vaultApprovalRequestSchema)).mutation("answerApproval").withInput(answerVaultApprovalInputSchema).withOutput(vaultApprovalRequestSchema).query("listAudit").withInput(vaultAuditReadInputSchema).withOutput(vaultAuditPageSchema).query("listActivity").withInput(vaultAuditReadInputSchema).withOutput(external_exports.array(vaultAuditEntrySchema)).query("listLeases").withInput(workspaceInput).withOutput(external_exports.array(vaultLeaseSchema)).mutation("endLease").withInput(endVaultLeaseInputSchema).withOutput(external_exports.object({ ended: external_exports.literal(true) })).query("mostAsked").withInput(vaultMostAskedInputSchema).withOutput(vaultMostAskedSchema).query("judgeStatus").withInput(workspaceInput).withOutput(vaultJudgeStatusSchema).query("listLevelLimits").withInput(workspaceInput).withOutput(external_exports.array(vaultLevelLimitSchema)).mutation("setLevelLimit").withInput(setVaultLevelLimitInputSchema).withOutput(external_exports.array(vaultLevelLimitSchema)).query("listDevices").withInput(workspaceInput).withOutput(external_exports.array(vaultDeviceSchema)).mutation("beginDeviceEnrolment").withInput(workspaceInput).withOutput(vaultDeviceEnrolmentSchema).mutation("finishDeviceEnrolment").withInput(finishVaultDeviceEnrolmentInputSchema).withOutput(vaultDeviceSchema).mutation("beginDeviceApproval").withInput(external_exports.object({ ...workspaceInput.shape, deviceId: external_exports.string().min(1) })).withOutput(external_exports.object({ challenge: external_exports.string(), sealed: external_exports.array(vaultSealedMaterialSchema) })).mutation("approveDevice").withInput(approveVaultDeviceInputSchema).withOutput(vaultDeviceSchema).mutation("removeDevice").withInput(external_exports.object({ ...workspaceInput.shape, deviceId: external_exports.string().min(1) })).withOutput(external_exports.object({ removed: external_exports.literal(true) })).mutation("createSealedConnection").withInput(createSealedConnectionInputSchema).withOutput(vaultConnectionSchema).mutation("resealConnection").withInput(resealConnectionInputSchema).withOutput(vaultConnectionSchema).mutation("openSealedConnection").withInput(
|
|
62436
|
+
).withOutput(external_exports.object({ fields: external_exports.record(external_exports.string(), external_exports.string()) })).mutation("beginReauth").withInput(workspaceInput).withOutput(vaultReauthChallengeSchema).mutation("confirmReauth").withInput(confirmVaultReauthInputSchema).withOutput(vaultReauthProofSchema).mutation("grantConnection").withInput(grantVaultConnectionInputSchema).withOutput(vaultGrantSchema).mutation("lendToChannel").withInput(lendVaultConnectionInputSchema).withOutput(vaultGrantSchema).mutation("revokeGrant").withInput(external_exports.object({ workspaceId: external_exports.string().min(1), grantId: external_exports.string().min(1) })).withOutput(external_exports.object({ revoked: external_exports.literal(true) })).query("listGrants").withInput(connectionInput).withOutput(external_exports.array(vaultGrantSchema)).mutation("shareConnection").withInput(shareVaultConnectionInputSchema).withOutput(vaultGrantSchema).mutation("approveShare").withInput(approveVaultShareInputSchema).withOutput(vaultGrantSchema).query("listApprovals").withInput(external_exports.object({ ...workspaceInput.shape, state: vaultApprovalStateSchema.optional() })).withOutput(external_exports.array(vaultApprovalRequestSchema)).mutation("answerApproval").withInput(answerVaultApprovalInputSchema).withOutput(vaultApprovalRequestSchema).query("listAudit").withInput(vaultAuditReadInputSchema).withOutput(vaultAuditPageSchema).query("listActivity").withInput(vaultAuditReadInputSchema).withOutput(external_exports.array(vaultAuditEntrySchema)).query("listLeases").withInput(workspaceInput).withOutput(external_exports.array(vaultLeaseSchema)).mutation("endLease").withInput(endVaultLeaseInputSchema).withOutput(external_exports.object({ ended: external_exports.literal(true) })).query("mostAsked").withInput(vaultMostAskedInputSchema).withOutput(vaultMostAskedSchema).query("judgeStatus").withInput(workspaceInput).withOutput(vaultJudgeStatusSchema).query("listLevelLimits").withInput(workspaceInput).withOutput(external_exports.array(vaultLevelLimitSchema)).mutation("setLevelLimit").withInput(setVaultLevelLimitInputSchema).withOutput(external_exports.array(vaultLevelLimitSchema)).query("listDevices").withInput(workspaceInput).withOutput(external_exports.array(vaultDeviceSchema)).mutation("beginDeviceEnrolment").withInput(workspaceInput).withOutput(vaultDeviceEnrolmentSchema).mutation("finishDeviceEnrolment").withInput(finishVaultDeviceEnrolmentInputSchema).withOutput(vaultDeviceSchema).mutation("beginDeviceApproval").withInput(external_exports.object({ ...workspaceInput.shape, deviceId: external_exports.string().min(1) })).withOutput(external_exports.object({ challenge: external_exports.string(), sealed: external_exports.array(vaultSealedMaterialSchema) })).mutation("approveDevice").withInput(approveVaultDeviceInputSchema).withOutput(vaultDeviceSchema).mutation("removeDevice").withInput(external_exports.object({ ...workspaceInput.shape, deviceId: external_exports.string().min(1) })).withOutput(external_exports.object({ removed: external_exports.literal(true) })).mutation("createSealedConnection").withInput(createSealedConnectionInputSchema).withOutput(vaultConnectionSchema).mutation("resealConnection").withInput(resealConnectionInputSchema).withOutput(vaultConnectionSchema).mutation("openSealedConnection").withInput(
|
|
62399
62437
|
external_exports.object({
|
|
62400
62438
|
...connectionInput.shape,
|
|
62401
62439
|
reason: external_exports.string().trim().min(1).max(200),
|
|
@@ -74504,10 +74542,15 @@ var appPull = async ({ context, args }) => {
|
|
|
74504
74542
|
args,
|
|
74505
74543
|
value: { ...pulled, folder },
|
|
74506
74544
|
text: `Pulled ${pulled.files.length} files of ${pulled.app.name} (${site} version ${pulled.version.slice(0, 7)}) into ${where}
|
|
74507
|
-
` + (names
|
|
74508
|
-
` : "It keeps no records.\n")
|
|
74545
|
+
` + recordsHint({ names, slug: pulled.app.slug })
|
|
74509
74546
|
});
|
|
74510
74547
|
};
|
|
74548
|
+
function recordsHint({ names, slug }) {
|
|
74549
|
+
if (names.length === 0) return "It keeps no records.\n";
|
|
74550
|
+
const which = names.length === 1 ? names[0] : `<${names.join("|")}>`;
|
|
74551
|
+
return `Its data: laze app records list ${which} --app ${slug}
|
|
74552
|
+
`;
|
|
74553
|
+
}
|
|
74511
74554
|
var appPublish = async ({ context, args }) => {
|
|
74512
74555
|
const client = await appClient({ context, args });
|
|
74513
74556
|
const appId = await appIdOf({ client, args, folder: folderOf({ context, word: void 0 }) });
|
|
@@ -79169,11 +79212,11 @@ async function connect({
|
|
|
79169
79212
|
}
|
|
79170
79213
|
|
|
79171
79214
|
// src/services/connector-commands.service.ts
|
|
79172
|
-
import { readFile as
|
|
79215
|
+
import { readFile as readFile24 } from "node:fs/promises";
|
|
79173
79216
|
import { resolve as resolve8 } from "node:path";
|
|
79174
79217
|
|
|
79175
79218
|
// src/services/vault-keychain-commands.service.ts
|
|
79176
|
-
import { readFile as
|
|
79219
|
+
import { readFile as readFile23 } from "node:fs/promises";
|
|
79177
79220
|
|
|
79178
79221
|
// src/rules/vault-input.rules.ts
|
|
79179
79222
|
function secondsOf(text2) {
|
|
@@ -79444,6 +79487,298 @@ var listDevices = async ({ context, args }) => {
|
|
|
79444
79487
|
}
|
|
79445
79488
|
};
|
|
79446
79489
|
|
|
79490
|
+
// src/services/vault-commands.service.ts
|
|
79491
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
79492
|
+
import { mkdir as mkdir17, readFile as readFile22, rm as rm10, writeFile as writeFile18 } from "node:fs/promises";
|
|
79493
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
79494
|
+
import { dirname as dirname17, join as join19 } from "node:path";
|
|
79495
|
+
var USAGE8 = `Usage: laze vault run <connection> --reason "<one plain sentence>" [--wait <s>] -- <command> [args...]
|
|
79496
|
+
Runs the command with the connection's values in its environment, on a Laze agent's computer
|
|
79497
|
+
or on a machine it runs on.`;
|
|
79498
|
+
var POLL_MS2 = 3e3;
|
|
79499
|
+
var RESTART_WAIT_MS = 12e4;
|
|
79500
|
+
var RESTART_BACKOFF_MS = [1e3, 2e3, 4e3, 8e3, 1e4];
|
|
79501
|
+
var P2562 = { name: "ECDH", namedCurve: "P-256" };
|
|
79502
|
+
var ServerGoneError = class extends Error {
|
|
79503
|
+
};
|
|
79504
|
+
function proxyOf({ env }) {
|
|
79505
|
+
const raw = env.LAZE_VAULT_PROXY || env.HTTP_PROXY || env.http_proxy;
|
|
79506
|
+
if (!raw) {
|
|
79507
|
+
throw new CliUsageError(
|
|
79508
|
+
"laze vault run works only on a Laze agent's computer or on a machine it runs on"
|
|
79509
|
+
);
|
|
79510
|
+
}
|
|
79511
|
+
const url2 = new URL(raw);
|
|
79512
|
+
const user = decodeURIComponent(url2.username);
|
|
79513
|
+
const password = decodeURIComponent(url2.password);
|
|
79514
|
+
return {
|
|
79515
|
+
origin: url2.origin,
|
|
79516
|
+
authorization: `Basic ${Buffer.from(`${user}:${password}`).toString("base64")}`
|
|
79517
|
+
};
|
|
79518
|
+
}
|
|
79519
|
+
function turnFileOf({
|
|
79520
|
+
env
|
|
79521
|
+
}) {
|
|
79522
|
+
return env.LAZE_TURN_FILE || void 0;
|
|
79523
|
+
}
|
|
79524
|
+
async function turnTokenOf3({
|
|
79525
|
+
env,
|
|
79526
|
+
turnFile,
|
|
79527
|
+
command = "laze vault run"
|
|
79528
|
+
}) {
|
|
79529
|
+
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
79530
|
+
if (pinned) return pinned;
|
|
79531
|
+
if (!turnFile) throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
79532
|
+
try {
|
|
79533
|
+
return (await readFile22(turnFile, "utf8")).trim();
|
|
79534
|
+
} catch {
|
|
79535
|
+
throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
79536
|
+
}
|
|
79537
|
+
}
|
|
79538
|
+
function runKeyPathOf({
|
|
79539
|
+
turnFile,
|
|
79540
|
+
connection
|
|
79541
|
+
}) {
|
|
79542
|
+
const name2 = createHash2("sha256").update(connection).digest("hex");
|
|
79543
|
+
const base = turnFile ? dirname17(turnFile) : join19(tmpdir2(), "laze-vault");
|
|
79544
|
+
return join19(base, "vault-run-keys", `${name2}.json`);
|
|
79545
|
+
}
|
|
79546
|
+
async function runKeyAt({ path }) {
|
|
79547
|
+
const saved3 = await readFile22(path, "utf8").then(
|
|
79548
|
+
(text2) => JSON.parse(text2),
|
|
79549
|
+
() => void 0
|
|
79550
|
+
);
|
|
79551
|
+
if (saved3 && typeof saved3.publicKey === "string" && saved3.privateKey) {
|
|
79552
|
+
const privateKey = await globalThis.crypto.subtle.importKey("jwk", saved3.privateKey, P2562, false, ["deriveBits"]).catch(() => void 0);
|
|
79553
|
+
if (privateKey) return { privateKey, publicKey: saved3.publicKey };
|
|
79554
|
+
}
|
|
79555
|
+
const fresh = await generateEcdhKeys();
|
|
79556
|
+
const jwk = await globalThis.crypto.subtle.exportKey("jwk", fresh.privateKey);
|
|
79557
|
+
await mkdir17(dirname17(path), { recursive: true, mode: 448 });
|
|
79558
|
+
await writeFile18(path, JSON.stringify({ publicKey: fresh.publicKey, privateKey: jwk }), {
|
|
79559
|
+
mode: 384
|
|
79560
|
+
});
|
|
79561
|
+
return fresh;
|
|
79562
|
+
}
|
|
79563
|
+
function connectionRefused(error62) {
|
|
79564
|
+
const cause = error62.cause;
|
|
79565
|
+
if (cause?.code === "ECONNREFUSED") return true;
|
|
79566
|
+
return cause?.errors?.some((inner) => inner.code === "ECONNREFUSED") ?? false;
|
|
79567
|
+
}
|
|
79568
|
+
async function sendOnce({
|
|
79569
|
+
context,
|
|
79570
|
+
url: url2,
|
|
79571
|
+
init
|
|
79572
|
+
}) {
|
|
79573
|
+
let response;
|
|
79574
|
+
try {
|
|
79575
|
+
response = await context.fetcher(url2, init);
|
|
79576
|
+
} catch (error62) {
|
|
79577
|
+
const wasRefused = connectionRefused(error62);
|
|
79578
|
+
if (init.method === "POST" && !wasRefused) throw error62;
|
|
79579
|
+
return { restarting: wasRefused ? "connection refused" : String(error62) };
|
|
79580
|
+
}
|
|
79581
|
+
if (response.status !== 502 && response.status !== 503) return { response };
|
|
79582
|
+
const code = codeOf(await response.clone().text());
|
|
79583
|
+
const neverReached = response.status === 503 && code === "vault_not_answering";
|
|
79584
|
+
if (init.method === "POST" && !neverReached) return { response };
|
|
79585
|
+
return { restarting: `status ${response.status}${code ? ` ${code}` : ""}` };
|
|
79586
|
+
}
|
|
79587
|
+
async function reach(input2) {
|
|
79588
|
+
const { context } = input2;
|
|
79589
|
+
const started = context.nowMs();
|
|
79590
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
79591
|
+
const sent = await sendOnce(input2);
|
|
79592
|
+
if ("response" in sent) return sent.response;
|
|
79593
|
+
if (context.nowMs() - started >= RESTART_WAIT_MS) {
|
|
79594
|
+
throw new ServerGoneError(
|
|
79595
|
+
`laze vault: the Laze server did not come back (${sent.restarting})`
|
|
79596
|
+
);
|
|
79597
|
+
}
|
|
79598
|
+
if (attempt === 0) {
|
|
79599
|
+
context.err(
|
|
79600
|
+
`laze vault: the Laze server is not answering (${sent.restarting}), probably restarting; waiting up to 2 min...
|
|
79601
|
+
`
|
|
79602
|
+
);
|
|
79603
|
+
}
|
|
79604
|
+
await context.sleep(RESTART_BACKOFF_MS[Math.min(attempt, RESTART_BACKOFF_MS.length - 1)] ?? 0);
|
|
79605
|
+
}
|
|
79606
|
+
}
|
|
79607
|
+
function codeOf(text2) {
|
|
79608
|
+
return /"code"\s*:\s*"([^"]+)"/.exec(text2)?.[1];
|
|
79609
|
+
}
|
|
79610
|
+
async function releaseOf({ response }) {
|
|
79611
|
+
const text2 = await response.text();
|
|
79612
|
+
if (!response.ok) {
|
|
79613
|
+
return {
|
|
79614
|
+
outcome: "deny",
|
|
79615
|
+
exitCode: 1,
|
|
79616
|
+
message: `laze vault: the release was refused (${codeOf(text2) ?? `status ${response.status}`})`
|
|
79617
|
+
};
|
|
79618
|
+
}
|
|
79619
|
+
return JSON.parse(text2);
|
|
79620
|
+
}
|
|
79621
|
+
async function envOf({
|
|
79622
|
+
release: release2,
|
|
79623
|
+
run: run4
|
|
79624
|
+
}) {
|
|
79625
|
+
if (!release2.sealed) return release2.env;
|
|
79626
|
+
const sealed = await openRunRelease({
|
|
79627
|
+
release: release2.sealed,
|
|
79628
|
+
runPrivateKey: run4.privateKey,
|
|
79629
|
+
runPublicKey: run4.publicKey,
|
|
79630
|
+
requestId: release2.sealed.requestId
|
|
79631
|
+
});
|
|
79632
|
+
return { ...release2.env, ...sealed };
|
|
79633
|
+
}
|
|
79634
|
+
function deadlineOf({ args, nowMs }) {
|
|
79635
|
+
const wait = flagText({ args, name: "wait" }) || (args.flags.wait === true ? args.words[3] : "");
|
|
79636
|
+
if (!wait) return Infinity;
|
|
79637
|
+
if (!(Number(wait) >= 0)) throw new CliUsageError(`--wait takes a number of seconds
|
|
79638
|
+
${USAGE8}`);
|
|
79639
|
+
return nowMs + Number(wait) * 1e3;
|
|
79640
|
+
}
|
|
79641
|
+
async function untilAnswered({
|
|
79642
|
+
context,
|
|
79643
|
+
first,
|
|
79644
|
+
origin,
|
|
79645
|
+
headers,
|
|
79646
|
+
deadline
|
|
79647
|
+
}) {
|
|
79648
|
+
let release2 = first;
|
|
79649
|
+
while (release2.outcome === "ask") {
|
|
79650
|
+
if (context.nowMs() + POLL_MS2 > deadline) {
|
|
79651
|
+
context.err(`${release2.message}. Not approved yet; ask again later.
|
|
79652
|
+
`);
|
|
79653
|
+
return "capped";
|
|
79654
|
+
}
|
|
79655
|
+
if (release2 === first) {
|
|
79656
|
+
context.err(`${release2.message}. Waiting for an answer (cards expire after 12 hours)...
|
|
79657
|
+
`);
|
|
79658
|
+
}
|
|
79659
|
+
await context.sleep(POLL_MS2);
|
|
79660
|
+
const url2 = `${origin}/vault/release/${encodeURIComponent(release2.requestId)}`;
|
|
79661
|
+
release2 = await releaseOf({
|
|
79662
|
+
response: await reach({ context, url: url2, init: { method: "GET", headers } })
|
|
79663
|
+
});
|
|
79664
|
+
}
|
|
79665
|
+
return release2;
|
|
79666
|
+
}
|
|
79667
|
+
async function vaultRelease({
|
|
79668
|
+
context,
|
|
79669
|
+
args,
|
|
79670
|
+
connection,
|
|
79671
|
+
reason,
|
|
79672
|
+
command
|
|
79673
|
+
}) {
|
|
79674
|
+
const deadline = deadlineOf({ args, nowMs: context.nowMs() });
|
|
79675
|
+
const env = context.environment.inherited;
|
|
79676
|
+
const proxy = proxyOf({ env });
|
|
79677
|
+
const turnFile = turnFileOf({ env });
|
|
79678
|
+
const headers = {
|
|
79679
|
+
"proxy-authorization": proxy.authorization,
|
|
79680
|
+
"x-laze-turn": await turnTokenOf3({ env, turnFile })
|
|
79681
|
+
};
|
|
79682
|
+
const keyPath = runKeyPathOf({ turnFile, connection });
|
|
79683
|
+
const run4 = await runKeyAt({ path: keyPath });
|
|
79684
|
+
const body = JSON.stringify({ connection, reason, command, recipient: run4.publicKey });
|
|
79685
|
+
let release2;
|
|
79686
|
+
try {
|
|
79687
|
+
const first = await releaseOf({
|
|
79688
|
+
response: await reach({
|
|
79689
|
+
context,
|
|
79690
|
+
url: `${proxy.origin}/vault/release`,
|
|
79691
|
+
init: { method: "POST", headers: { ...headers, "content-type": "application/json" }, body }
|
|
79692
|
+
})
|
|
79693
|
+
});
|
|
79694
|
+
release2 = await untilAnswered({ context, first, origin: proxy.origin, headers, deadline });
|
|
79695
|
+
} catch (error62) {
|
|
79696
|
+
if (!(error62 instanceof ServerGoneError)) throw error62;
|
|
79697
|
+
context.err(`${error62.message}. Run the command again to keep waiting.
|
|
79698
|
+
`);
|
|
79699
|
+
return { exitCode: 75 };
|
|
79700
|
+
}
|
|
79701
|
+
if (release2 === "capped") return { exitCode: 75 };
|
|
79702
|
+
if (release2.outcome === "deny") {
|
|
79703
|
+
await rm10(keyPath, { force: true });
|
|
79704
|
+
context.err(`${release2.message}
|
|
79705
|
+
`);
|
|
79706
|
+
return { exitCode: release2.exitCode || 1 };
|
|
79707
|
+
}
|
|
79708
|
+
const values = await envOf({ release: release2, run: run4 });
|
|
79709
|
+
await rm10(keyPath, { force: true });
|
|
79710
|
+
if (release2.message) context.err(`${release2.message}
|
|
79711
|
+
`);
|
|
79712
|
+
return { env: values };
|
|
79713
|
+
}
|
|
79714
|
+
async function vaultRun({
|
|
79715
|
+
context,
|
|
79716
|
+
args
|
|
79717
|
+
}) {
|
|
79718
|
+
const connection = args.words[2];
|
|
79719
|
+
const reason = flagText({ args, name: "reason" });
|
|
79720
|
+
if (!connection || args.rest.length === 0) throw new CliUsageError(USAGE8);
|
|
79721
|
+
if (!reason) throw new CliUsageError(`Say why with --reason "<one plain sentence>"
|
|
79722
|
+
${USAGE8}`);
|
|
79723
|
+
const released = await vaultRelease({ context, args, connection, reason, command: args.rest });
|
|
79724
|
+
if ("exitCode" in released) return released.exitCode;
|
|
79725
|
+
return context.runCommand({ command: args.rest, env: released.env });
|
|
79726
|
+
}
|
|
79727
|
+
|
|
79728
|
+
// src/services/vault-share-commands.service.ts
|
|
79729
|
+
var SHARE_USAGE2 = "Usage: laze vault share <connection> --with <email|userId> [--for 1h]";
|
|
79730
|
+
var WAITING_LINE = "It waits for the owner's approval with a passkey or Face ID, in Settings > Vault.";
|
|
79731
|
+
async function personOf({ client, who }) {
|
|
79732
|
+
const members3 = await client.get("/api/workspaces/current/members");
|
|
79733
|
+
const wanted = who.toLowerCase();
|
|
79734
|
+
const found = members3.find(
|
|
79735
|
+
(member) => member.userId === who || member.email.toLowerCase() === wanted
|
|
79736
|
+
);
|
|
79737
|
+
if (!found) throw new CliUsageError(`No one in this workspace is ${who}.`);
|
|
79738
|
+
return found.userId;
|
|
79739
|
+
}
|
|
79740
|
+
async function inTurn({
|
|
79741
|
+
context,
|
|
79742
|
+
client,
|
|
79743
|
+
command
|
|
79744
|
+
}) {
|
|
79745
|
+
const env = context.environment.inherited;
|
|
79746
|
+
const turn = await turnTokenOf3({ env, turnFile: turnFileOf({ env }), command });
|
|
79747
|
+
return client.withHeaders({ "x-laze-turn": turn });
|
|
79748
|
+
}
|
|
79749
|
+
function printShare({ context, grant }) {
|
|
79750
|
+
printGrant({ context, grant });
|
|
79751
|
+
if (grant.awaitingOwner) context.out(`${WAITING_LINE}
|
|
79752
|
+
`);
|
|
79753
|
+
}
|
|
79754
|
+
var shareWith = async ({ context, args }) => {
|
|
79755
|
+
const word3 = args.words[2];
|
|
79756
|
+
const who = flagText({ args, name: "with" });
|
|
79757
|
+
if (!word3 || !who) throw new CliUsageError(SHARE_USAGE2);
|
|
79758
|
+
const { client, profile } = await signedIn({ context, args });
|
|
79759
|
+
const userId = await personOf({ client, who });
|
|
79760
|
+
const grant = profile.kind === "agent" ? await (await inTurn({ context, client, command: "laze vault share" })).post("/api/vault/turn/share", {
|
|
79761
|
+
connection: word3,
|
|
79762
|
+
userId,
|
|
79763
|
+
...durationOf(args)
|
|
79764
|
+
}) : await client.post("/api/vault/shares", {
|
|
79765
|
+
connectionId: (await connectionOf({ client, args, word: word3 })).id,
|
|
79766
|
+
userId,
|
|
79767
|
+
...durationOf(args)
|
|
79768
|
+
});
|
|
79769
|
+
if (args.flags.json) return printJson4({ context, data: grant });
|
|
79770
|
+
printShare({ context, grant });
|
|
79771
|
+
};
|
|
79772
|
+
async function setLevelInTurn({
|
|
79773
|
+
context,
|
|
79774
|
+
client,
|
|
79775
|
+
connection,
|
|
79776
|
+
sensitivity
|
|
79777
|
+
}) {
|
|
79778
|
+
const turned = await inTurn({ context, client, command: "laze vault update --level" });
|
|
79779
|
+
return turned.post("/api/vault/turn/level", { connection, sensitivity });
|
|
79780
|
+
}
|
|
79781
|
+
|
|
79447
79782
|
// src/services/vault-keychain-commands.service.ts
|
|
79448
79783
|
var VAULT_USAGE = `Usage (your own key; an agent's key is refused, values are never printed):
|
|
79449
79784
|
laze vault list [--json] connections you manage or see: names, fields, levels
|
|
@@ -79462,6 +79797,9 @@ var VAULT_USAGE = `Usage (your own key; an agent's key is refused, values are ne
|
|
|
79462
79797
|
laze vault rm|revoke <connection> delete it; revoke also takes it back at the provider
|
|
79463
79798
|
laze vault uses <connection> [--limit <n>] who used it, how, where, under which approval
|
|
79464
79799
|
laze vault grant <connection> --to person|group|channel|agent:<id> [--for 1h]
|
|
79800
|
+
laze vault share <connection> --with <email|userId> [--for 1h] your own key, with one teammate:
|
|
79801
|
+
it waits for your passkey in Settings > Vault; Always ask and Human only keys are shared
|
|
79802
|
+
only from there. Lowering a key's level is done only there too; raising works anywhere
|
|
79465
79803
|
laze vault lend <connection> --channel <channelId> [--for 1h]
|
|
79466
79804
|
laze vault grants <connection> | laze vault ungrant <grantId>
|
|
79467
79805
|
laze vault leases | laze vault end-lease <leaseId>
|
|
@@ -79495,7 +79833,7 @@ async function secretText({ context, args }) {
|
|
|
79495
79833
|
);
|
|
79496
79834
|
}
|
|
79497
79835
|
const file3 = flagText({ args, name: "from-file" });
|
|
79498
|
-
const text2 = file3 ? await
|
|
79836
|
+
const text2 = file3 ? await readFile23(file3, "utf8") : await context.readStdin();
|
|
79499
79837
|
const trimmed = text2.replace(/\r?\n$/, "");
|
|
79500
79838
|
if (!trimmed.trim()) throw new CliUsageError("No value: pipe it on stdin or use --from-file.");
|
|
79501
79839
|
return trimmed;
|
|
@@ -79554,10 +79892,21 @@ var add3 = async ({ context, args }) => {
|
|
|
79554
79892
|
);
|
|
79555
79893
|
};
|
|
79556
79894
|
var update = async ({ context, args }) => {
|
|
79557
|
-
const { client } = await signedIn({ context, args });
|
|
79558
|
-
const target = await connectionOf({ client, args, word: args.words[2] });
|
|
79895
|
+
const { client, profile } = await signedIn({ context, args });
|
|
79559
79896
|
const settings2 = settingsOf(args);
|
|
79560
79897
|
if (Object.keys(settings2).length === 0) throw new CliUsageError(VAULT_USAGE);
|
|
79898
|
+
const word3 = args.words[2];
|
|
79899
|
+
if (profile.kind === "agent" && word3 && settings2.sensitivity && Object.keys(settings2).length === 1) {
|
|
79900
|
+
const raised = await setLevelInTurn({
|
|
79901
|
+
context,
|
|
79902
|
+
client,
|
|
79903
|
+
connection: word3,
|
|
79904
|
+
sensitivity: settings2.sensitivity
|
|
79905
|
+
});
|
|
79906
|
+
if (args.flags.json) return printJson4({ context, data: raised });
|
|
79907
|
+
return printConnection({ context, row: raised });
|
|
79908
|
+
}
|
|
79909
|
+
const target = await connectionOf({ client, args, word: word3 });
|
|
79561
79910
|
const updated = await client.post("/api/vault/connections/update", {
|
|
79562
79911
|
connectionId: target.id,
|
|
79563
79912
|
...settings2
|
|
@@ -79649,6 +79998,7 @@ var VAULT_COMMANDS = {
|
|
|
79649
79998
|
revoke: removal("revoke"),
|
|
79650
79999
|
uses,
|
|
79651
80000
|
grant: grantTo,
|
|
80001
|
+
share: shareWith,
|
|
79652
80002
|
lend: lendTo,
|
|
79653
80003
|
grants: grantsOf,
|
|
79654
80004
|
ungrant: revokeGrant,
|
|
@@ -79705,7 +80055,7 @@ async function keyText({ context, args }) {
|
|
|
79705
80055
|
throw new CliUsageError("A key never goes in a flag: pipe it on stdin or use --from-file.");
|
|
79706
80056
|
}
|
|
79707
80057
|
const file3 = flagText({ args, name: "from-file" });
|
|
79708
|
-
const text2 = file3 ? await
|
|
80058
|
+
const text2 = file3 ? await readFile24(resolve8(context.cwd, file3), "utf8") : await context.readStdin();
|
|
79709
80059
|
const trimmed = text2.trim();
|
|
79710
80060
|
if (!trimmed) throw new CliUsageError("No key: pipe it on stdin or use --from-file.");
|
|
79711
80061
|
return trimmed;
|
|
@@ -80069,16 +80419,16 @@ function dndLine({ pausedUntil }) {
|
|
|
80069
80419
|
}
|
|
80070
80420
|
|
|
80071
80421
|
// src/services/dnd-commands.service.ts
|
|
80072
|
-
var
|
|
80422
|
+
var USAGE9 = "Usage: laze dnd 30m|1h|2h|until <HH:mm|ISO time> [--tz <zone>], laze dnd off";
|
|
80073
80423
|
async function dnd({ context, args }) {
|
|
80074
80424
|
const timeZone = flagText({ args, name: "tz" }) || Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
80075
80425
|
let input2;
|
|
80076
80426
|
try {
|
|
80077
80427
|
input2 = dndInputOf({ words: args.words.slice(1), now: nowInstant(), timeZone });
|
|
80078
80428
|
} catch {
|
|
80079
|
-
throw new CliUsageError(
|
|
80429
|
+
throw new CliUsageError(USAGE9);
|
|
80080
80430
|
}
|
|
80081
|
-
if (!input2) throw new CliUsageError(
|
|
80431
|
+
if (!input2) throw new CliUsageError(USAGE9);
|
|
80082
80432
|
const { client } = await signedIn({ context, args });
|
|
80083
80433
|
const settings2 = await client.post(
|
|
80084
80434
|
"/api/agents/me/notifications/snooze",
|
|
@@ -80130,7 +80480,7 @@ async function domains({ context, args }) {
|
|
|
80130
80480
|
}
|
|
80131
80481
|
|
|
80132
80482
|
// src/services/feed-commands.service.ts
|
|
80133
|
-
import { readFile as
|
|
80483
|
+
import { readFile as readFile26 } from "node:fs/promises";
|
|
80134
80484
|
import { resolve as resolve10 } from "node:path";
|
|
80135
80485
|
|
|
80136
80486
|
// src/rules/feed-input.rules.ts
|
|
@@ -80255,7 +80605,7 @@ function feedFlagsOf({ args }) {
|
|
|
80255
80605
|
}
|
|
80256
80606
|
|
|
80257
80607
|
// src/services/feed-files.service.ts
|
|
80258
|
-
import { readFile as
|
|
80608
|
+
import { readFile as readFile25 } from "node:fs/promises";
|
|
80259
80609
|
import { basename as basename4, resolve as resolve9 } from "node:path";
|
|
80260
80610
|
|
|
80261
80611
|
// ../../modules/feed/contract/src/feed.ts
|
|
@@ -80830,7 +81180,7 @@ async function local({ context, path }) {
|
|
|
80830
81180
|
return {
|
|
80831
81181
|
fileName,
|
|
80832
81182
|
contentType: contentTypeOf(fileName),
|
|
80833
|
-
bytes: new Uint8Array(await
|
|
81183
|
+
bytes: new Uint8Array(await readFile25(full))
|
|
80834
81184
|
};
|
|
80835
81185
|
}
|
|
80836
81186
|
async function directWith({ client, to }) {
|
|
@@ -80868,7 +81218,7 @@ async function feedAttachmentIdsOf({
|
|
|
80868
81218
|
}
|
|
80869
81219
|
|
|
80870
81220
|
// src/services/feed-commands.service.ts
|
|
80871
|
-
var
|
|
81221
|
+
var USAGE10 = `Usage:
|
|
80872
81222
|
laze feed post <title> [--channel <channel>] [--tag <tag>] [--summary <line>]
|
|
80873
81223
|
[--draft <text|@file>] [--draft-header "To: ...\\nRe: ..."]
|
|
80874
81224
|
[--metric <json|@file.json> | --table <csv|@file.csv>]
|
|
@@ -80908,7 +81258,7 @@ async function bodyOf2({
|
|
|
80908
81258
|
flags: flags2
|
|
80909
81259
|
}) {
|
|
80910
81260
|
const body = { ...flags2.fields };
|
|
80911
|
-
const read3 = (source) => "file" in source ?
|
|
81261
|
+
const read3 = (source) => "file" in source ? readFile26(resolve10(context.cwd, source.file), "utf8") : source.text;
|
|
80912
81262
|
for (const [field, source] of Object.entries(flags2.texts)) body[field] = await read3(source);
|
|
80913
81263
|
if (flags2.rich) {
|
|
80914
81264
|
const text2 = await read3(flags2.rich.source);
|
|
@@ -80937,7 +81287,7 @@ function printItem({
|
|
|
80937
81287
|
}
|
|
80938
81288
|
async function feedPost({ context, args }) {
|
|
80939
81289
|
const title = args.words.slice(2).join(" ").trim();
|
|
80940
|
-
if (!title) throw new CliUsageError(
|
|
81290
|
+
if (!title) throw new CliUsageError(USAGE10);
|
|
80941
81291
|
const flags2 = flagsOf(args);
|
|
80942
81292
|
const { client } = await signedIn({ context, args });
|
|
80943
81293
|
const channel = flagText({ args, name: "channel" });
|
|
@@ -80959,7 +81309,7 @@ async function feedPost({ context, args }) {
|
|
|
80959
81309
|
}
|
|
80960
81310
|
async function feedUpdate({ context, args }) {
|
|
80961
81311
|
const itemId = args.words[2];
|
|
80962
|
-
if (!itemId) throw new CliUsageError(
|
|
81312
|
+
if (!itemId) throw new CliUsageError(USAGE10);
|
|
80963
81313
|
const flags2 = flagsOf(args);
|
|
80964
81314
|
const { client } = await signedIn({ context, args });
|
|
80965
81315
|
const body = await bodyOf2({ context, flags: flags2 });
|
|
@@ -80975,7 +81325,7 @@ async function feedUpdate({ context, args }) {
|
|
|
80975
81325
|
async function feedReply({ context, args }) {
|
|
80976
81326
|
const itemId = args.words[2];
|
|
80977
81327
|
const text2 = args.words.slice(3).join(" ").trim();
|
|
80978
|
-
if (!itemId || !text2) throw new CliUsageError(
|
|
81328
|
+
if (!itemId || !text2) throw new CliUsageError(USAGE10);
|
|
80979
81329
|
const { client } = await signedIn({ context, args });
|
|
80980
81330
|
const replied = await client.post("/api/feed/items/reply", {
|
|
80981
81331
|
itemId,
|
|
@@ -80987,7 +81337,7 @@ async function feedReply({ context, args }) {
|
|
|
80987
81337
|
}
|
|
80988
81338
|
async function feedRead({ context, args }) {
|
|
80989
81339
|
const itemId = args.words[2];
|
|
80990
|
-
if (!itemId) throw new CliUsageError(
|
|
81340
|
+
if (!itemId) throw new CliUsageError(USAGE10);
|
|
80991
81341
|
const { client } = await signedIn({ context, args });
|
|
80992
81342
|
const read3 = await client.post("/api/feed/items/read", { itemId });
|
|
80993
81343
|
printItem({ context, args, item: read3 });
|
|
@@ -81006,7 +81356,7 @@ async function feedClose({ context, args }) {
|
|
|
81006
81356
|
const itemId = args.words[2];
|
|
81007
81357
|
const loop = flagText({ args, name: "loop" });
|
|
81008
81358
|
const note = flagText({ args, name: "note" });
|
|
81009
|
-
if (!note || Boolean(itemId) === Boolean(loop)) throw new CliUsageError(
|
|
81359
|
+
if (!note || Boolean(itemId) === Boolean(loop)) throw new CliUsageError(USAGE10);
|
|
81010
81360
|
const { client } = await signedIn({ context, args });
|
|
81011
81361
|
const closed = await client.post("/api/feed/items/close", {
|
|
81012
81362
|
...itemId ? { itemId } : { loop },
|
|
@@ -81032,7 +81382,7 @@ async function feedLoops({ context, args }) {
|
|
|
81032
81382
|
}
|
|
81033
81383
|
async function feedGroupSummary({ context, args }) {
|
|
81034
81384
|
const group = args.words.slice(2).join(" ").trim();
|
|
81035
|
-
if (!group) throw new CliUsageError(
|
|
81385
|
+
if (!group) throw new CliUsageError(USAGE10);
|
|
81036
81386
|
const { client } = await signedIn({ context, args });
|
|
81037
81387
|
const pointer = await client.post("/api/feed/group-summary", { group });
|
|
81038
81388
|
if (args.flags.json) return context.out(`${JSON.stringify(pointer, null, 2)}
|
|
@@ -81070,7 +81420,7 @@ async function textFlag({
|
|
|
81070
81420
|
}) {
|
|
81071
81421
|
const value = flagText({ args, name: name2 });
|
|
81072
81422
|
if (!value.startsWith("@")) return value;
|
|
81073
|
-
return
|
|
81423
|
+
return readFile26(resolve10(context.cwd, value.slice(1)), "utf8");
|
|
81074
81424
|
}
|
|
81075
81425
|
async function feedList({ context, args }) {
|
|
81076
81426
|
const { client } = await signedIn({ context, args });
|
|
@@ -81102,7 +81452,7 @@ async function feedCount({ context, args }) {
|
|
|
81102
81452
|
}
|
|
81103
81453
|
async function feedAct({ context, args }) {
|
|
81104
81454
|
const [itemId, actionId] = [args.words[2], args.words[3]];
|
|
81105
|
-
if (!itemId || !actionId) throw new CliUsageError(
|
|
81455
|
+
if (!itemId || !actionId) throw new CliUsageError(USAGE10);
|
|
81106
81456
|
const draft = await textFlag({ context, args, name: "draft" });
|
|
81107
81457
|
const { client } = await signedIn({ context, args });
|
|
81108
81458
|
const item = await client.post("/api/feed/mine/act", {
|
|
@@ -81115,7 +81465,7 @@ async function feedAct({ context, args }) {
|
|
|
81115
81465
|
async function feedComment({ context, args }) {
|
|
81116
81466
|
const itemId = args.words[2];
|
|
81117
81467
|
const text2 = args.words.slice(3).join(" ").trim();
|
|
81118
|
-
if (!itemId || !text2) throw new CliUsageError(
|
|
81468
|
+
if (!itemId || !text2) throw new CliUsageError(USAGE10);
|
|
81119
81469
|
const draft = await textFlag({ context, args, name: "draft" });
|
|
81120
81470
|
const { client } = await signedIn({ context, args });
|
|
81121
81471
|
const item = await client.post("/api/feed/mine/comment", {
|
|
@@ -81129,7 +81479,7 @@ async function feedComment({ context, args }) {
|
|
|
81129
81479
|
function moveItem(path) {
|
|
81130
81480
|
return async ({ context, args }) => {
|
|
81131
81481
|
const itemId = args.words[2];
|
|
81132
|
-
if (!itemId) throw new CliUsageError(
|
|
81482
|
+
if (!itemId) throw new CliUsageError(USAGE10);
|
|
81133
81483
|
const { client } = await signedIn({ context, args });
|
|
81134
81484
|
const item = await client.post(`/api/feed/mine/${path}`, { itemId });
|
|
81135
81485
|
printMoved({ context, args, item });
|
|
@@ -81138,14 +81488,14 @@ function moveItem(path) {
|
|
|
81138
81488
|
async function feedSnooze({ context, args }) {
|
|
81139
81489
|
const itemId = args.words[2];
|
|
81140
81490
|
const until = flagText({ args, name: "until" });
|
|
81141
|
-
if (!itemId || !until) throw new CliUsageError(
|
|
81491
|
+
if (!itemId || !until) throw new CliUsageError(USAGE10);
|
|
81142
81492
|
const { client } = await signedIn({ context, args });
|
|
81143
81493
|
const item = await client.post("/api/feed/mine/snooze", { itemId, until });
|
|
81144
81494
|
printMoved({ context, args, item });
|
|
81145
81495
|
}
|
|
81146
81496
|
async function feedChannel({ context, args }) {
|
|
81147
81497
|
const channelId = args.words[2];
|
|
81148
|
-
if (!channelId) throw new CliUsageError(
|
|
81498
|
+
if (!channelId) throw new CliUsageError(USAGE10);
|
|
81149
81499
|
const { client } = await signedIn({ context, args });
|
|
81150
81500
|
const items = await client.post("/api/feed/channel", { channelId });
|
|
81151
81501
|
if (args.flags.json) return context.out(`${JSON.stringify(items, null, 2)}
|
|
@@ -81175,12 +81525,12 @@ var FEED_COMMANDS = {
|
|
|
81175
81525
|
async function feed({ context, args }) {
|
|
81176
81526
|
const name2 = args.words[1] ?? "";
|
|
81177
81527
|
const command = Object.hasOwn(FEED_COMMANDS, name2) ? FEED_COMMANDS[name2] : void 0;
|
|
81178
|
-
if (!command) throw new CliUsageError(
|
|
81528
|
+
if (!command) throw new CliUsageError(USAGE10);
|
|
81179
81529
|
await command({ context, args });
|
|
81180
81530
|
}
|
|
81181
81531
|
|
|
81182
81532
|
// src/services/github-commands.service.ts
|
|
81183
|
-
import { readFile as
|
|
81533
|
+
import { readFile as readFile27 } from "node:fs/promises";
|
|
81184
81534
|
|
|
81185
81535
|
// src/rules/github-signature.rules.ts
|
|
81186
81536
|
var TURN_SEPARATOR = "~";
|
|
@@ -81250,7 +81600,7 @@ var REAL_GH = "/usr/bin/gh";
|
|
|
81250
81600
|
var NOT_SET = "laze: agent_github_not_set: this agent has no GitHub connection. Its owner sets one on the agent's settings page or with `laze agent set-github <agent> <connection>`.";
|
|
81251
81601
|
async function turnFileToken({ env }) {
|
|
81252
81602
|
if (!env.LAZE_TURN_FILE) return "";
|
|
81253
|
-
return
|
|
81603
|
+
return readFile27(env.LAZE_TURN_FILE, "utf8").then(
|
|
81254
81604
|
(text2) => text2.trim(),
|
|
81255
81605
|
() => ""
|
|
81256
81606
|
);
|
|
@@ -81284,7 +81634,7 @@ async function githubGh({
|
|
|
81284
81634
|
args: args.rest,
|
|
81285
81635
|
agentName: profile.name ?? "An agent",
|
|
81286
81636
|
threadUrl: threadUrlOf({ env, workspaceId: profile.workspaceId }),
|
|
81287
|
-
readBodyFile: (path) => path === "-" ? context.readStdin() :
|
|
81637
|
+
readBodyFile: (path) => path === "-" ? context.readStdin() : readFile27(path, "utf8")
|
|
81288
81638
|
});
|
|
81289
81639
|
return context.runCommand({
|
|
81290
81640
|
command: [REAL_GH, ...ghArgs],
|
|
@@ -81383,7 +81733,7 @@ async function setAgentGithub({
|
|
|
81383
81733
|
}
|
|
81384
81734
|
|
|
81385
81735
|
// src/services/history-commands.service.ts
|
|
81386
|
-
import { readFile as
|
|
81736
|
+
import { readFile as readFile28 } from "node:fs/promises";
|
|
81387
81737
|
|
|
81388
81738
|
// src/rules/history-format.rules.ts
|
|
81389
81739
|
function timeOf2(iso) {
|
|
@@ -81474,12 +81824,12 @@ function beforeOf({ args }) {
|
|
|
81474
81824
|
throw new CliUsageError(HISTORY_USAGE);
|
|
81475
81825
|
}
|
|
81476
81826
|
}
|
|
81477
|
-
async function
|
|
81827
|
+
async function turnTokenOf4({ context }) {
|
|
81478
81828
|
const env = context.environment.inherited;
|
|
81479
81829
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
81480
81830
|
if (pinned) return pinned;
|
|
81481
81831
|
if (!env.LAZE_TURN_FILE) return "";
|
|
81482
|
-
return
|
|
81832
|
+
return readFile28(env.LAZE_TURN_FILE, "utf8").then(
|
|
81483
81833
|
(text2) => text2.trim(),
|
|
81484
81834
|
() => ""
|
|
81485
81835
|
);
|
|
@@ -81493,7 +81843,7 @@ async function history({
|
|
|
81493
81843
|
const limit = limitOf3({ args });
|
|
81494
81844
|
const before = beforeOf({ args });
|
|
81495
81845
|
const { client: signed2 } = await signedIn({ context, args });
|
|
81496
|
-
const turn = await
|
|
81846
|
+
const turn = await turnTokenOf4({ context });
|
|
81497
81847
|
const client = turn ? signed2.withHeaders({ "x-laze-turn": turn }) : signed2;
|
|
81498
81848
|
const laze = await client.post("/api/agents/me/history", {
|
|
81499
81849
|
channel,
|
|
@@ -81671,19 +82021,19 @@ async function ip({ context, args }) {
|
|
|
81671
82021
|
}
|
|
81672
82022
|
|
|
81673
82023
|
// src/services/join-commands.service.ts
|
|
81674
|
-
import { mkdir as
|
|
81675
|
-
import { dirname as
|
|
82024
|
+
import { mkdir as mkdir18, readFile as readFile29, rename as rename5, rm as rm11, writeFile as writeFile19 } from "node:fs/promises";
|
|
82025
|
+
import { dirname as dirname18, join as join20 } from "node:path";
|
|
81676
82026
|
var DEFAULT_WAIT_SECONDS2 = 100;
|
|
81677
82027
|
var JOIN_USAGE = "Usage: laze join [--workspace <name|id|invite link>] [--for <email>] [--name <name>] [--note <text>] [--timeout <seconds>] [--project <folder>]";
|
|
81678
82028
|
function pendingPathOf({ context }) {
|
|
81679
|
-
return
|
|
82029
|
+
return join20(dirname18(context.environment.configPath), "join", "pending.json");
|
|
81680
82030
|
}
|
|
81681
82031
|
async function readPending({
|
|
81682
82032
|
context,
|
|
81683
82033
|
url: url2,
|
|
81684
82034
|
args
|
|
81685
82035
|
}) {
|
|
81686
|
-
const pending = await
|
|
82036
|
+
const pending = await readFile29(pendingPathOf({ context }), "utf8").then(
|
|
81687
82037
|
(text2) => JSON.parse(text2),
|
|
81688
82038
|
() => void 0
|
|
81689
82039
|
);
|
|
@@ -81693,13 +82043,13 @@ async function readPending({
|
|
|
81693
82043
|
}
|
|
81694
82044
|
async function keepPending({ context, pending }) {
|
|
81695
82045
|
const path = pendingPathOf({ context });
|
|
81696
|
-
await
|
|
82046
|
+
await mkdir18(dirname18(path), { recursive: true, mode: 448 });
|
|
81697
82047
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
81698
|
-
await
|
|
82048
|
+
await writeFile19(temporary, JSON.stringify(pending), { mode: 384 });
|
|
81699
82049
|
await rename5(temporary, path);
|
|
81700
82050
|
}
|
|
81701
82051
|
async function dropPending({ context }) {
|
|
81702
|
-
await
|
|
82052
|
+
await rm11(pendingPathOf({ context }), { force: true });
|
|
81703
82053
|
}
|
|
81704
82054
|
function waitSecondsOf3({ args }) {
|
|
81705
82055
|
const raw = flagText({ args, name: "timeout" });
|
|
@@ -82011,244 +82361,6 @@ function machineAccessCommand(name2) {
|
|
|
82011
82361
|
return name2 && Object.hasOwn(COMMANDS, name2) ? COMMANDS[name2] : void 0;
|
|
82012
82362
|
}
|
|
82013
82363
|
|
|
82014
|
-
// src/services/vault-commands.service.ts
|
|
82015
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
82016
|
-
import { mkdir as mkdir18, readFile as readFile29, rm as rm11, writeFile as writeFile19 } from "node:fs/promises";
|
|
82017
|
-
import { tmpdir as tmpdir2 } from "node:os";
|
|
82018
|
-
import { dirname as dirname18, join as join20 } from "node:path";
|
|
82019
|
-
var USAGE10 = `Usage: laze vault run <connection> --reason "<one plain sentence>" [--wait <s>] -- <command> [args...]
|
|
82020
|
-
Runs the command with the connection's values in its environment, on a Laze agent's computer
|
|
82021
|
-
or on a machine it runs on.`;
|
|
82022
|
-
var POLL_MS2 = 3e3;
|
|
82023
|
-
var RESTART_WAIT_MS = 12e4;
|
|
82024
|
-
var RESTART_BACKOFF_MS = [1e3, 2e3, 4e3, 8e3, 1e4];
|
|
82025
|
-
var P2562 = { name: "ECDH", namedCurve: "P-256" };
|
|
82026
|
-
var ServerGoneError = class extends Error {
|
|
82027
|
-
};
|
|
82028
|
-
function proxyOf({ env }) {
|
|
82029
|
-
const raw = env.LAZE_VAULT_PROXY || env.HTTP_PROXY || env.http_proxy;
|
|
82030
|
-
if (!raw) {
|
|
82031
|
-
throw new CliUsageError(
|
|
82032
|
-
"laze vault run works only on a Laze agent's computer or on a machine it runs on"
|
|
82033
|
-
);
|
|
82034
|
-
}
|
|
82035
|
-
const url2 = new URL(raw);
|
|
82036
|
-
const user = decodeURIComponent(url2.username);
|
|
82037
|
-
const password = decodeURIComponent(url2.password);
|
|
82038
|
-
return {
|
|
82039
|
-
origin: url2.origin,
|
|
82040
|
-
authorization: `Basic ${Buffer.from(`${user}:${password}`).toString("base64")}`
|
|
82041
|
-
};
|
|
82042
|
-
}
|
|
82043
|
-
function turnFileOf({
|
|
82044
|
-
env
|
|
82045
|
-
}) {
|
|
82046
|
-
return env.LAZE_TURN_FILE || void 0;
|
|
82047
|
-
}
|
|
82048
|
-
async function turnTokenOf4({
|
|
82049
|
-
env,
|
|
82050
|
-
turnFile,
|
|
82051
|
-
command = "laze vault run"
|
|
82052
|
-
}) {
|
|
82053
|
-
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
82054
|
-
if (pinned) return pinned;
|
|
82055
|
-
if (!turnFile) throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
82056
|
-
try {
|
|
82057
|
-
return (await readFile29(turnFile, "utf8")).trim();
|
|
82058
|
-
} catch {
|
|
82059
|
-
throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
82060
|
-
}
|
|
82061
|
-
}
|
|
82062
|
-
function runKeyPathOf({
|
|
82063
|
-
turnFile,
|
|
82064
|
-
connection
|
|
82065
|
-
}) {
|
|
82066
|
-
const name2 = createHash2("sha256").update(connection).digest("hex");
|
|
82067
|
-
const base = turnFile ? dirname18(turnFile) : join20(tmpdir2(), "laze-vault");
|
|
82068
|
-
return join20(base, "vault-run-keys", `${name2}.json`);
|
|
82069
|
-
}
|
|
82070
|
-
async function runKeyAt({ path }) {
|
|
82071
|
-
const saved3 = await readFile29(path, "utf8").then(
|
|
82072
|
-
(text2) => JSON.parse(text2),
|
|
82073
|
-
() => void 0
|
|
82074
|
-
);
|
|
82075
|
-
if (saved3 && typeof saved3.publicKey === "string" && saved3.privateKey) {
|
|
82076
|
-
const privateKey = await globalThis.crypto.subtle.importKey("jwk", saved3.privateKey, P2562, false, ["deriveBits"]).catch(() => void 0);
|
|
82077
|
-
if (privateKey) return { privateKey, publicKey: saved3.publicKey };
|
|
82078
|
-
}
|
|
82079
|
-
const fresh = await generateEcdhKeys();
|
|
82080
|
-
const jwk = await globalThis.crypto.subtle.exportKey("jwk", fresh.privateKey);
|
|
82081
|
-
await mkdir18(dirname18(path), { recursive: true, mode: 448 });
|
|
82082
|
-
await writeFile19(path, JSON.stringify({ publicKey: fresh.publicKey, privateKey: jwk }), {
|
|
82083
|
-
mode: 384
|
|
82084
|
-
});
|
|
82085
|
-
return fresh;
|
|
82086
|
-
}
|
|
82087
|
-
function connectionRefused(error62) {
|
|
82088
|
-
const cause = error62.cause;
|
|
82089
|
-
if (cause?.code === "ECONNREFUSED") return true;
|
|
82090
|
-
return cause?.errors?.some((inner) => inner.code === "ECONNREFUSED") ?? false;
|
|
82091
|
-
}
|
|
82092
|
-
async function sendOnce({
|
|
82093
|
-
context,
|
|
82094
|
-
url: url2,
|
|
82095
|
-
init
|
|
82096
|
-
}) {
|
|
82097
|
-
let response;
|
|
82098
|
-
try {
|
|
82099
|
-
response = await context.fetcher(url2, init);
|
|
82100
|
-
} catch (error62) {
|
|
82101
|
-
const wasRefused = connectionRefused(error62);
|
|
82102
|
-
if (init.method === "POST" && !wasRefused) throw error62;
|
|
82103
|
-
return { restarting: wasRefused ? "connection refused" : String(error62) };
|
|
82104
|
-
}
|
|
82105
|
-
if (response.status !== 502 && response.status !== 503) return { response };
|
|
82106
|
-
const code = codeOf(await response.clone().text());
|
|
82107
|
-
const neverReached = response.status === 503 && code === "vault_not_answering";
|
|
82108
|
-
if (init.method === "POST" && !neverReached) return { response };
|
|
82109
|
-
return { restarting: `status ${response.status}${code ? ` ${code}` : ""}` };
|
|
82110
|
-
}
|
|
82111
|
-
async function reach(input2) {
|
|
82112
|
-
const { context } = input2;
|
|
82113
|
-
const started = context.nowMs();
|
|
82114
|
-
for (let attempt = 0; ; attempt += 1) {
|
|
82115
|
-
const sent = await sendOnce(input2);
|
|
82116
|
-
if ("response" in sent) return sent.response;
|
|
82117
|
-
if (context.nowMs() - started >= RESTART_WAIT_MS) {
|
|
82118
|
-
throw new ServerGoneError(
|
|
82119
|
-
`laze vault: the Laze server did not come back (${sent.restarting})`
|
|
82120
|
-
);
|
|
82121
|
-
}
|
|
82122
|
-
if (attempt === 0) {
|
|
82123
|
-
context.err(
|
|
82124
|
-
`laze vault: the Laze server is not answering (${sent.restarting}), probably restarting; waiting up to 2 min...
|
|
82125
|
-
`
|
|
82126
|
-
);
|
|
82127
|
-
}
|
|
82128
|
-
await context.sleep(RESTART_BACKOFF_MS[Math.min(attempt, RESTART_BACKOFF_MS.length - 1)] ?? 0);
|
|
82129
|
-
}
|
|
82130
|
-
}
|
|
82131
|
-
function codeOf(text2) {
|
|
82132
|
-
return /"code"\s*:\s*"([^"]+)"/.exec(text2)?.[1];
|
|
82133
|
-
}
|
|
82134
|
-
async function releaseOf({ response }) {
|
|
82135
|
-
const text2 = await response.text();
|
|
82136
|
-
if (!response.ok) {
|
|
82137
|
-
return {
|
|
82138
|
-
outcome: "deny",
|
|
82139
|
-
exitCode: 1,
|
|
82140
|
-
message: `laze vault: the release was refused (${codeOf(text2) ?? `status ${response.status}`})`
|
|
82141
|
-
};
|
|
82142
|
-
}
|
|
82143
|
-
return JSON.parse(text2);
|
|
82144
|
-
}
|
|
82145
|
-
async function envOf({
|
|
82146
|
-
release: release2,
|
|
82147
|
-
run: run4
|
|
82148
|
-
}) {
|
|
82149
|
-
if (!release2.sealed) return release2.env;
|
|
82150
|
-
const sealed = await openRunRelease({
|
|
82151
|
-
release: release2.sealed,
|
|
82152
|
-
runPrivateKey: run4.privateKey,
|
|
82153
|
-
runPublicKey: run4.publicKey,
|
|
82154
|
-
requestId: release2.sealed.requestId
|
|
82155
|
-
});
|
|
82156
|
-
return { ...release2.env, ...sealed };
|
|
82157
|
-
}
|
|
82158
|
-
function deadlineOf({ args, nowMs }) {
|
|
82159
|
-
const wait = flagText({ args, name: "wait" }) || (args.flags.wait === true ? args.words[3] : "");
|
|
82160
|
-
if (!wait) return Infinity;
|
|
82161
|
-
if (!(Number(wait) >= 0)) throw new CliUsageError(`--wait takes a number of seconds
|
|
82162
|
-
${USAGE10}`);
|
|
82163
|
-
return nowMs + Number(wait) * 1e3;
|
|
82164
|
-
}
|
|
82165
|
-
async function untilAnswered({
|
|
82166
|
-
context,
|
|
82167
|
-
first,
|
|
82168
|
-
origin,
|
|
82169
|
-
headers,
|
|
82170
|
-
deadline
|
|
82171
|
-
}) {
|
|
82172
|
-
let release2 = first;
|
|
82173
|
-
while (release2.outcome === "ask") {
|
|
82174
|
-
if (context.nowMs() + POLL_MS2 > deadline) {
|
|
82175
|
-
context.err(`${release2.message}. Not approved yet; ask again later.
|
|
82176
|
-
`);
|
|
82177
|
-
return "capped";
|
|
82178
|
-
}
|
|
82179
|
-
if (release2 === first) {
|
|
82180
|
-
context.err(`${release2.message}. Waiting for an answer (cards expire after 12 hours)...
|
|
82181
|
-
`);
|
|
82182
|
-
}
|
|
82183
|
-
await context.sleep(POLL_MS2);
|
|
82184
|
-
const url2 = `${origin}/vault/release/${encodeURIComponent(release2.requestId)}`;
|
|
82185
|
-
release2 = await releaseOf({
|
|
82186
|
-
response: await reach({ context, url: url2, init: { method: "GET", headers } })
|
|
82187
|
-
});
|
|
82188
|
-
}
|
|
82189
|
-
return release2;
|
|
82190
|
-
}
|
|
82191
|
-
async function vaultRelease({
|
|
82192
|
-
context,
|
|
82193
|
-
args,
|
|
82194
|
-
connection,
|
|
82195
|
-
reason,
|
|
82196
|
-
command
|
|
82197
|
-
}) {
|
|
82198
|
-
const deadline = deadlineOf({ args, nowMs: context.nowMs() });
|
|
82199
|
-
const env = context.environment.inherited;
|
|
82200
|
-
const proxy = proxyOf({ env });
|
|
82201
|
-
const turnFile = turnFileOf({ env });
|
|
82202
|
-
const headers = {
|
|
82203
|
-
"proxy-authorization": proxy.authorization,
|
|
82204
|
-
"x-laze-turn": await turnTokenOf4({ env, turnFile })
|
|
82205
|
-
};
|
|
82206
|
-
const keyPath = runKeyPathOf({ turnFile, connection });
|
|
82207
|
-
const run4 = await runKeyAt({ path: keyPath });
|
|
82208
|
-
const body = JSON.stringify({ connection, reason, command, recipient: run4.publicKey });
|
|
82209
|
-
let release2;
|
|
82210
|
-
try {
|
|
82211
|
-
const first = await releaseOf({
|
|
82212
|
-
response: await reach({
|
|
82213
|
-
context,
|
|
82214
|
-
url: `${proxy.origin}/vault/release`,
|
|
82215
|
-
init: { method: "POST", headers: { ...headers, "content-type": "application/json" }, body }
|
|
82216
|
-
})
|
|
82217
|
-
});
|
|
82218
|
-
release2 = await untilAnswered({ context, first, origin: proxy.origin, headers, deadline });
|
|
82219
|
-
} catch (error62) {
|
|
82220
|
-
if (!(error62 instanceof ServerGoneError)) throw error62;
|
|
82221
|
-
context.err(`${error62.message}. Run the command again to keep waiting.
|
|
82222
|
-
`);
|
|
82223
|
-
return { exitCode: 75 };
|
|
82224
|
-
}
|
|
82225
|
-
if (release2 === "capped") return { exitCode: 75 };
|
|
82226
|
-
if (release2.outcome === "deny") {
|
|
82227
|
-
await rm11(keyPath, { force: true });
|
|
82228
|
-
context.err(`${release2.message}
|
|
82229
|
-
`);
|
|
82230
|
-
return { exitCode: release2.exitCode || 1 };
|
|
82231
|
-
}
|
|
82232
|
-
const values = await envOf({ release: release2, run: run4 });
|
|
82233
|
-
await rm11(keyPath, { force: true });
|
|
82234
|
-
if (release2.message) context.err(`${release2.message}
|
|
82235
|
-
`);
|
|
82236
|
-
return { env: values };
|
|
82237
|
-
}
|
|
82238
|
-
async function vaultRun({
|
|
82239
|
-
context,
|
|
82240
|
-
args
|
|
82241
|
-
}) {
|
|
82242
|
-
const connection = args.words[2];
|
|
82243
|
-
const reason = flagText({ args, name: "reason" });
|
|
82244
|
-
if (!connection || args.rest.length === 0) throw new CliUsageError(USAGE10);
|
|
82245
|
-
if (!reason) throw new CliUsageError(`Say why with --reason "<one plain sentence>"
|
|
82246
|
-
${USAGE10}`);
|
|
82247
|
-
const released = await vaultRelease({ context, args, connection, reason, command: args.rest });
|
|
82248
|
-
if ("exitCode" in released) return released.exitCode;
|
|
82249
|
-
return context.runCommand({ command: args.rest, env: released.env });
|
|
82250
|
-
}
|
|
82251
|
-
|
|
82252
82364
|
// src/services/machine-commands.service.ts
|
|
82253
82365
|
var USAGE11 = [
|
|
82254
82366
|
"Usage: laze machine connect <name> the command to run on your own machine (people)",
|
|
@@ -84665,7 +84777,7 @@ async function postInTurn({
|
|
|
84665
84777
|
body
|
|
84666
84778
|
}) {
|
|
84667
84779
|
const env = context.environment.inherited;
|
|
84668
|
-
const turn = await
|
|
84780
|
+
const turn = await turnTokenOf3({
|
|
84669
84781
|
env,
|
|
84670
84782
|
turnFile: turnFileOf({ env }),
|
|
84671
84783
|
command: "laze vault save"
|
|
@@ -86301,7 +86413,7 @@ var HELP = `laze: work in a Laze workspace from your terminal or your agent.
|
|
|
86301
86413
|
laze vault scrub [--dry-run] move secrets found in messages to the vault now (admins)
|
|
86302
86414
|
laze vault list|add|update|replace|compare|rm|revoke|uses your keychains with your own key
|
|
86303
86415
|
a value comes from stdin or --from-file, never a flag; no command prints a value
|
|
86304
|
-
laze vault grant|lend|grants|ungrant|leases|end-lease|limits|set-limit sharing, leases, limits
|
|
86416
|
+
laze vault grant|share|lend|grants|ungrant|leases|end-lease|limits|set-limit sharing, leases, limits
|
|
86305
86417
|
laze vault audit|activity|most-asked|approvals|judge|devices what happened (audit: admins)
|
|
86306
86418
|
laze vault every laze vault command, with its flags
|
|
86307
86419
|
laze connect suggest <service> --reason "<why>" a connect card for whoever asked (agents)
|
package/package.json
CHANGED