@lazehq/cli 0.1.26 → 0.1.28
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 +274 -50
- package/package.json +1 -1
package/dist/laze.mjs
CHANGED
|
@@ -30997,6 +30997,41 @@ function isBasicAuthPayload(value) {
|
|
|
30997
30997
|
}
|
|
30998
30998
|
var CREDENTIAL_QUALIFIERS = "master|encryption|signing|private|access|api|auth|secret|refresh|session|bearer|verification|webhook|client|service|personal|root|admin";
|
|
30999
30999
|
var CREDENTIAL_KEYWORD = `(?:x[_.\\- ]?)?(?:(?:${CREDENTIAL_QUALIFIERS})[_.\\- ]?(?:api[_.\\- ]?)?key|(?:${CREDENTIAL_QUALIFIERS})?[_.\\- ]?(?:api[_.\\- ]?)?(?:token|secret|password|passwd|pwd|credentials?|authorization|cookie))`;
|
|
31000
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31001
|
+
var GIT_SHA = /^[0-9a-f]{40}$/;
|
|
31002
|
+
var DOMAIN_PATH = /^[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}\//;
|
|
31003
|
+
var NAMED_KEY_MIN = 24;
|
|
31004
|
+
var NAMED_KEY_MAX = 256;
|
|
31005
|
+
function isSlug(value) {
|
|
31006
|
+
const parts = value.split(/[-_.]/);
|
|
31007
|
+
if (parts.length < 3) return false;
|
|
31008
|
+
const short = parts.every((part) => /^(?:[a-z0-9]{1,10}|[A-Z0-9]{1,10})$/.test(part));
|
|
31009
|
+
return short && parts.some((part) => /^[A-Za-z]{3,}$/.test(part));
|
|
31010
|
+
}
|
|
31011
|
+
var NOT_A_NAMED_KEY = [
|
|
31012
|
+
/^\/|\/\//,
|
|
31013
|
+
GIT_SHA,
|
|
31014
|
+
DOMAIN_PATH,
|
|
31015
|
+
PATH_LIKE,
|
|
31016
|
+
CODE_EXPRESSION,
|
|
31017
|
+
ENV_REFERENCE,
|
|
31018
|
+
VERSION_LIKE
|
|
31019
|
+
];
|
|
31020
|
+
function isNamedKeyValue(value) {
|
|
31021
|
+
if (value.length < NAMED_KEY_MIN || value.length > NAMED_KEY_MAX) return false;
|
|
31022
|
+
if (UUID.test(value)) return true;
|
|
31023
|
+
if (isSlug(value)) return false;
|
|
31024
|
+
if (NOT_A_NAMED_KEY.some((shape) => shape.test(value))) return false;
|
|
31025
|
+
const prefix = /^([A-Za-z][A-Za-z0-9]{1,11})[_-]/.exec(value)?.[1];
|
|
31026
|
+
if (prefix && isNonCredentialPrefix(prefix)) return false;
|
|
31027
|
+
if (HEX.test(value)) return true;
|
|
31028
|
+
if (shannonEntropyBits(value) < 3.5) return false;
|
|
31029
|
+
const c = charClasses(value);
|
|
31030
|
+
return c.digit >= 2 && c.lower + c.upper >= 8 && (c.lower >= 2 || c.upper >= 2);
|
|
31031
|
+
}
|
|
31032
|
+
var KEY_WORD = String.raw`(?:api[_.\- ]?key|apikey|access[_.\- ]?key|key|token|secret|password|passwd|pwd)`;
|
|
31033
|
+
var QUOTE = "[\"'`]";
|
|
31034
|
+
var KEY_WORD_GAP = String.raw`(?:[ \t]{0,3}(?:is|was|here|it's|its|below|:|=|->|=>|-{1,2}))`;
|
|
31000
31035
|
var TOKEN_START = "(?<![A-Za-z0-9_-])";
|
|
31001
31036
|
var TOKEN_END = "(?![A-Za-z0-9_-])";
|
|
31002
31037
|
var VENDOR_KEY_PATTERNS = [
|
|
@@ -31125,11 +31160,21 @@ var RULES = [
|
|
|
31125
31160
|
"i"
|
|
31126
31161
|
),
|
|
31127
31162
|
value: { kind: "group", group: 2 },
|
|
31163
|
+
dropsFullStop: true,
|
|
31128
31164
|
accept: (match) => {
|
|
31129
31165
|
const introduction = groupOf(match, 1);
|
|
31130
31166
|
const value = groupOf(match, 2);
|
|
31131
31167
|
return STRICT_INTRODUCTION.test(introduction) ? isCredentialValue(value) : isKeyMaterial(value);
|
|
31132
31168
|
}
|
|
31169
|
+
},
|
|
31170
|
+
{
|
|
31171
|
+
id: "named_key",
|
|
31172
|
+
regex: rx(
|
|
31173
|
+
String.raw`\b(${KEY_WORD})\b(${KEY_WORD_GAP}{0,3}[ \t]*(?:\r?\n[ \t]*)?${QUOTE}?)` + String.raw`([A-Za-z0-9+/=_.-]{${NAMED_KEY_MIN - 1},${NAMED_KEY_MAX - 1}}[A-Za-z0-9+/=_-])` + String.raw`(?![A-Za-z0-9+/=_-]|\.[A-Za-z0-9])`,
|
|
31174
|
+
"i"
|
|
31175
|
+
),
|
|
31176
|
+
value: { kind: "group", group: 3 },
|
|
31177
|
+
accept: (match) => /[\s:="'`]/.test(groupOf(match, 2)) && isNamedKeyValue(groupOf(match, 3))
|
|
31133
31178
|
}
|
|
31134
31179
|
];
|
|
31135
31180
|
var SECRET_RULE_IDS = RULES.map((rule) => rule.id);
|
|
@@ -31157,12 +31202,21 @@ function spanStartOf({ rule, text: text2, fullStart }) {
|
|
|
31157
31202
|
const before = rule.precededBy.exec(text2.slice(from, fullStart));
|
|
31158
31203
|
return before ? fullStart - before[0].length : fullStart;
|
|
31159
31204
|
}
|
|
31205
|
+
function withoutFullStop({
|
|
31206
|
+
text: text2,
|
|
31207
|
+
span
|
|
31208
|
+
}) {
|
|
31209
|
+
let end = span.end;
|
|
31210
|
+
while (end > span.start && text2[end - 1] === "." && !/\S/.test(text2[end] ?? "")) end--;
|
|
31211
|
+
return end === span.end ? span : { start: span.start, end, spanEnd: Math.min(span.spanEnd, end) };
|
|
31212
|
+
}
|
|
31160
31213
|
function rawMatches(rule, text2) {
|
|
31161
31214
|
const out = [];
|
|
31162
31215
|
rule.regex.lastIndex = 0;
|
|
31163
31216
|
for (const match of text2.matchAll(rule.regex)) {
|
|
31164
31217
|
if (rule.accept && !rule.accept(match)) continue;
|
|
31165
|
-
const
|
|
31218
|
+
const found = valueSpan(rule, match);
|
|
31219
|
+
const span = found && rule.dropsFullStop ? withoutFullStop({ text: text2, span: found }) : found;
|
|
31166
31220
|
if (!span || span.end <= span.start) continue;
|
|
31167
31221
|
const spanStart = spanStartOf({ rule, text: text2, fullStart: match.index });
|
|
31168
31222
|
out.push({ ruleId: rule.id, spanStart, ...span });
|
|
@@ -31322,7 +31376,33 @@ function suggestedName({
|
|
|
31322
31376
|
const line = lineBreak === -1 ? before : before.slice(lineBreak + 1);
|
|
31323
31377
|
const assigned = ASSIGNMENT.exec(line)?.[1]?.toUpperCase();
|
|
31324
31378
|
if (assigned && isValidSecretName(assigned)) return assigned;
|
|
31325
|
-
|
|
31379
|
+
const lead = before.replace(/\s+$/, "");
|
|
31380
|
+
const lastLine = lead.slice(lead.search(/[^\r\n]*$/));
|
|
31381
|
+
const named = KEY_WORD_KINDS.has(kind) ? keyWordName({ line: lastLine }) : null;
|
|
31382
|
+
return named ?? defaultName({ kind, value, before });
|
|
31383
|
+
}
|
|
31384
|
+
var KEY_WORD_KINDS = /* @__PURE__ */ new Set(["named_key", "sensitive_assignment"]);
|
|
31385
|
+
var VENDOR_KEY_WORD = /([A-Za-z][A-Za-z0-9]{1,30})[ _.-]+(?:(?:api|access)[ _.-]?)?(key|token|secret|password|passwd|pwd)\b/gi;
|
|
31386
|
+
var NOT_VENDOR_WORDS = new Set(
|
|
31387
|
+
"a an the my your our their his her its this that these new old here is of for with and or to my api access secret private public personal prod production live test dev staging master admin root bearer auth client service session refresh read write full main default".split(
|
|
31388
|
+
" "
|
|
31389
|
+
)
|
|
31390
|
+
);
|
|
31391
|
+
var KEY_WORD_SUFFIXES = {
|
|
31392
|
+
key: "_API_KEY",
|
|
31393
|
+
token: "_TOKEN",
|
|
31394
|
+
secret: "_SECRET",
|
|
31395
|
+
password: "_PASSWORD",
|
|
31396
|
+
passwd: "_PASSWORD",
|
|
31397
|
+
pwd: "_PASSWORD"
|
|
31398
|
+
};
|
|
31399
|
+
function keyWordName({ line }) {
|
|
31400
|
+
const last = [...line.slice(-80).matchAll(VENDOR_KEY_WORD)].at(-1);
|
|
31401
|
+
const vendor = last?.[1]?.toLowerCase();
|
|
31402
|
+
const word3 = last?.[2]?.toLowerCase();
|
|
31403
|
+
if (!vendor || !word3 || NOT_VENDOR_WORDS.has(vendor)) return null;
|
|
31404
|
+
const name2 = `${vendor.toUpperCase()}${KEY_WORD_SUFFIXES[word3] ?? "_KEY"}`;
|
|
31405
|
+
return isValidSecretName(name2) ? name2 : null;
|
|
31326
31406
|
}
|
|
31327
31407
|
var SAFE_CUT_LOOKAHEAD = 4096;
|
|
31328
31408
|
var PEM_BEGIN = "-----BEGIN";
|
|
@@ -35426,6 +35506,8 @@ function cliEnvironment({
|
|
|
35426
35506
|
} = {}) {
|
|
35427
35507
|
return {
|
|
35428
35508
|
configPath: env.LAZE_CLI_CONFIG || join(homedir(), ".laze", "config.json"),
|
|
35509
|
+
// Claude Code names a subagent's commands `claude-code_<version>_agent`.
|
|
35510
|
+
subagent: /^claude-code_.+_agent$/.test(env.AI_AGENT ?? ""),
|
|
35429
35511
|
profile: env.LAZE_PROFILE || void 0,
|
|
35430
35512
|
url: env.LAZE_URL || void 0,
|
|
35431
35513
|
opsToken: env.LAZE_OPS_TOKEN || void 0,
|
|
@@ -35625,7 +35707,7 @@ function flagText({
|
|
|
35625
35707
|
}
|
|
35626
35708
|
|
|
35627
35709
|
// src/rules/cli-version.rules.ts
|
|
35628
|
-
var STAMPED = "0.1.
|
|
35710
|
+
var STAMPED = "0.1.28";
|
|
35629
35711
|
function cliVersionOf({ stamped = STAMPED } = {}) {
|
|
35630
35712
|
return stamped.startsWith("__") ? "dev" : stamped;
|
|
35631
35713
|
}
|
|
@@ -57848,6 +57930,17 @@ var chatScrubReportSchemaDefinition = external_exports.object({
|
|
|
57848
57930
|
channels: external_exports.array(chatScrubChannelSchemaDefinition)
|
|
57849
57931
|
});
|
|
57850
57932
|
var chatScrubReportSchema = chatScrubReportSchemaDefinition;
|
|
57933
|
+
var saveMessageSecretBodySchemaDefinition = external_exports.object({
|
|
57934
|
+
/** One token, as keys are: a value with spaces is text, not a key. */
|
|
57935
|
+
value: external_exports.string().min(8).max(4096).regex(/^\S+$/),
|
|
57936
|
+
name: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),
|
|
57937
|
+
description: external_exports.string().trim().min(1).max(120)
|
|
57938
|
+
});
|
|
57939
|
+
var messageSecretSavedSchemaDefinition = external_exports.object({
|
|
57940
|
+
outcome: external_exports.enum(["named", "already_named"]),
|
|
57941
|
+
name: external_exports.string(),
|
|
57942
|
+
connectionId: external_exports.string()
|
|
57943
|
+
});
|
|
57851
57944
|
|
|
57852
57945
|
// ../../modules/chat/contract/src/chat.sent.ts
|
|
57853
57946
|
var SENT_PAGE_MAX = 50;
|
|
@@ -62603,6 +62696,16 @@ var savePendingSecretBodySchemaDefinition = external_exports.object({
|
|
|
62603
62696
|
name: connectionName2,
|
|
62604
62697
|
description: external_exports.string().trim().min(1).max(120)
|
|
62605
62698
|
});
|
|
62699
|
+
var saveMessageSecretInputSchemaDefinition = external_exports.object({
|
|
62700
|
+
workspaceId: external_exports.string().min(1),
|
|
62701
|
+
channelId: external_exports.string().min(1),
|
|
62702
|
+
messageId: external_exports.string().min(1),
|
|
62703
|
+
/** The message's author, a person: the keychain the value goes to. */
|
|
62704
|
+
ownerUserId: external_exports.string().min(1),
|
|
62705
|
+
value: external_exports.string().min(8).max(4096).regex(/^\S+$/),
|
|
62706
|
+
name: connectionName2,
|
|
62707
|
+
description: external_exports.string().trim().min(1).max(120)
|
|
62708
|
+
});
|
|
62606
62709
|
var vaultPendingSecretSavedSchemaDefinition = external_exports.object({
|
|
62607
62710
|
outcome: external_exports.enum(["named", "already_named"]),
|
|
62608
62711
|
name: connectionName2,
|
|
@@ -66817,14 +66920,26 @@ async function liveElsewhere({
|
|
|
66817
66920
|
}
|
|
66818
66921
|
return false;
|
|
66819
66922
|
}
|
|
66820
|
-
function
|
|
66821
|
-
|
|
66923
|
+
function refuseInSubagent({ context, args }) {
|
|
66924
|
+
if (!context.environment.subagent || flagText({ args, name: "session" })) return;
|
|
66925
|
+
throw new CliUsageError(
|
|
66926
|
+
"This runs inside a Claude Code subagent, which shares its parent's session: it would take that session. Run it in the session itself, or pass --session <id>."
|
|
66927
|
+
);
|
|
66928
|
+
}
|
|
66929
|
+
function notBoundText({
|
|
66930
|
+
meta: meta3,
|
|
66931
|
+
agent: agent2,
|
|
66932
|
+
configPath
|
|
66933
|
+
}) {
|
|
66934
|
+
const who = `${agent2 ? `"${agent2}"` : "this agent"} (config ${configPath})`;
|
|
66935
|
+
return `Laze: ${who} listens in another session${meta3.bound ? `: ${meta3.bound}` : ""}. Create a new Laze agent with this session: laze agent request. Or move this agent here: laze agent bind.`;
|
|
66822
66936
|
}
|
|
66823
66937
|
async function notBoundNotice({
|
|
66824
66938
|
context,
|
|
66825
66939
|
client,
|
|
66826
66940
|
session,
|
|
66827
|
-
error: error62
|
|
66941
|
+
error: error62,
|
|
66942
|
+
profile
|
|
66828
66943
|
}) {
|
|
66829
66944
|
if (!(error62 instanceof LazeApiError) || error62.code !== "session_not_bound") return void 0;
|
|
66830
66945
|
const meta3 = error62.meta ?? {};
|
|
@@ -66844,7 +66959,10 @@ async function notBoundNotice({
|
|
|
66844
66959
|
if (told) return { notice: void 0 };
|
|
66845
66960
|
await mkdir3(dirname3(path), { recursive: true, mode: 448 });
|
|
66846
66961
|
await writeFile3(path, String(context.nowMs()), { mode: 384 });
|
|
66847
|
-
|
|
66962
|
+
const agent2 = (await context.store.read()).profiles[profile]?.name;
|
|
66963
|
+
return {
|
|
66964
|
+
notice: notBoundText({ meta: meta3, agent: agent2, configPath: context.environment.configPath })
|
|
66965
|
+
};
|
|
66848
66966
|
}
|
|
66849
66967
|
|
|
66850
66968
|
// src/services/plugin-hook.service.ts
|
|
@@ -67676,7 +67794,8 @@ async function settleRound(round) {
|
|
|
67676
67794
|
context,
|
|
67677
67795
|
client: forSession({ client, session }),
|
|
67678
67796
|
session,
|
|
67679
|
-
error: error62
|
|
67797
|
+
error: error62,
|
|
67798
|
+
profile: name2
|
|
67680
67799
|
});
|
|
67681
67800
|
if (!refused) throw error62;
|
|
67682
67801
|
return refused;
|
|
@@ -69321,6 +69440,7 @@ async function linkCodexSession({
|
|
|
69321
69440
|
|
|
69322
69441
|
// src/services/laze-plugin.service.ts
|
|
69323
69442
|
import { mkdir as mkdir11, readFile as readFile11, writeFile as writeFile11 } from "node:fs/promises";
|
|
69443
|
+
import { homedir as homedir3 } from "node:os";
|
|
69324
69444
|
import { dirname as dirname11, join as join13 } from "node:path";
|
|
69325
69445
|
|
|
69326
69446
|
// src/rules/laze-plugin.rules.ts
|
|
@@ -69461,15 +69581,7 @@ async function writeLazePlugin({ context }) {
|
|
|
69461
69581
|
}
|
|
69462
69582
|
return folder;
|
|
69463
69583
|
}
|
|
69464
|
-
async function
|
|
69465
|
-
const quiet = ">/dev/null 2>&1 </dev/null";
|
|
69466
|
-
const script = [
|
|
69467
|
-
`claude plugin marketplace add ${quote2(folder)} --scope user ${quiet}`,
|
|
69468
|
-
`claude plugin marketplace update ${LAZE_PLUGIN} ${quiet}`,
|
|
69469
|
-
// install is a no-op for a plugin Claude Code already has; update refreshes its cached copy.
|
|
69470
|
-
`{ claude plugin install ${LAZE_PLUGIN}@${LAZE_PLUGIN} --scope user ${quiet} || true; }`,
|
|
69471
|
-
`claude plugin update ${LAZE_PLUGIN}@${LAZE_PLUGIN} ${quiet}`
|
|
69472
|
-
].join("; ");
|
|
69584
|
+
async function claudeScript({ context, script }) {
|
|
69473
69585
|
const stop3 = new AbortController();
|
|
69474
69586
|
const command = ["sh", "-c", script];
|
|
69475
69587
|
const run4 = context.runCommand({ command, env: {}, signal: stop3.signal }).catch(() => 1);
|
|
@@ -69480,6 +69592,44 @@ async function registerWithClaude({ context, folder }) {
|
|
|
69480
69592
|
stop3.abort();
|
|
69481
69593
|
return code === 0;
|
|
69482
69594
|
}
|
|
69595
|
+
var QUIET = ">/dev/null 2>&1 </dev/null";
|
|
69596
|
+
async function registerWithClaude({ context, folder }) {
|
|
69597
|
+
const script = [
|
|
69598
|
+
`claude plugin marketplace add ${quote2(folder)} --scope user ${QUIET}`,
|
|
69599
|
+
`claude plugin marketplace update ${LAZE_PLUGIN} ${QUIET}`,
|
|
69600
|
+
// install is a no-op for a plugin Claude Code already has; update refreshes its cached copy.
|
|
69601
|
+
`{ claude plugin install ${LAZE_PLUGIN}@${LAZE_PLUGIN} --scope user ${QUIET} || true; }`,
|
|
69602
|
+
`claude plugin update ${LAZE_PLUGIN}@${LAZE_PLUGIN} ${QUIET}`
|
|
69603
|
+
].join("; ");
|
|
69604
|
+
return claudeScript({ context, script });
|
|
69605
|
+
}
|
|
69606
|
+
var RUN_FILES = ["hooks/hooks.json", "monitors/monitors.json"];
|
|
69607
|
+
async function cachedPluginOf({ context }) {
|
|
69608
|
+
const inherited = context.environment.inherited;
|
|
69609
|
+
const home = inherited.HOME || homedir3();
|
|
69610
|
+
const claude = inherited.CLAUDE_CONFIG_DIR || join13(home, ".claude");
|
|
69611
|
+
const listed = await readFile11(join13(claude, "plugins", "installed_plugins.json"), "utf8").then(
|
|
69612
|
+
(text2) => JSON.parse(text2),
|
|
69613
|
+
() => void 0
|
|
69614
|
+
);
|
|
69615
|
+
return listed?.plugins?.[`${LAZE_PLUGIN}@${LAZE_PLUGIN}`]?.[0]?.installPath;
|
|
69616
|
+
}
|
|
69617
|
+
async function refreshStaleCache({ context, folder }) {
|
|
69618
|
+
const cached2 = await cachedPluginOf({ context });
|
|
69619
|
+
if (!cached2) return true;
|
|
69620
|
+
const read3 = (path) => readFile11(path, "utf8").catch(() => "");
|
|
69621
|
+
for (const file3 of RUN_FILES) {
|
|
69622
|
+
const ours = await read3(join13(folder, LAZE_PLUGIN, file3));
|
|
69623
|
+
if (ours === await read3(join13(cached2, file3))) continue;
|
|
69624
|
+
const plugin2 = `${LAZE_PLUGIN}@${LAZE_PLUGIN}`;
|
|
69625
|
+
const script = [
|
|
69626
|
+
`claude plugin uninstall ${plugin2} --scope user ${QUIET}`,
|
|
69627
|
+
`claude plugin install ${plugin2} --scope user ${QUIET}`
|
|
69628
|
+
].join("; ");
|
|
69629
|
+
return claudeScript({ context, script });
|
|
69630
|
+
}
|
|
69631
|
+
return true;
|
|
69632
|
+
}
|
|
69483
69633
|
function registeredMarkOf({ context }) {
|
|
69484
69634
|
return join13(pluginFolderOf({ context }), "registered");
|
|
69485
69635
|
}
|
|
@@ -69491,7 +69641,7 @@ async function pluginRegistered({ context }) {
|
|
|
69491
69641
|
}
|
|
69492
69642
|
async function installLazePlugin({ context }) {
|
|
69493
69643
|
const folder = await writeLazePlugin({ context });
|
|
69494
|
-
const registered = await registerWithClaude({ context, folder });
|
|
69644
|
+
const registered = await registerWithClaude({ context, folder }) && await refreshStaleCache({ context, folder });
|
|
69495
69645
|
if (registered) await writeFile11(registeredMarkOf({ context }), cliVersionOf());
|
|
69496
69646
|
return { folder, registered };
|
|
69497
69647
|
}
|
|
@@ -69840,6 +69990,7 @@ function sandboxed({ context, error: error62 }) {
|
|
|
69840
69990
|
async function linkAgent({ context, args }) {
|
|
69841
69991
|
const token2 = flagText({ args, name: "token" });
|
|
69842
69992
|
if (!token2) throw new CliUsageError("Usage: laze agent link --token <token>");
|
|
69993
|
+
refuseInSubagent({ context, args });
|
|
69843
69994
|
const url2 = serverUrlOf({ context, args });
|
|
69844
69995
|
const { harness, pid } = await harnessOf2({ context, args });
|
|
69845
69996
|
const client = LazeClient.create({ baseUrl: url2, fetcher: context.fetcher });
|
|
@@ -69989,7 +70140,13 @@ async function handOver({ context, args }) {
|
|
|
69989
70140
|
try {
|
|
69990
70141
|
fresh = await receiveMessages({ context, client: claim3, waitSeconds: 0 });
|
|
69991
70142
|
} catch (error62) {
|
|
69992
|
-
const refused = await notBoundNotice({
|
|
70143
|
+
const refused = await notBoundNotice({
|
|
70144
|
+
context,
|
|
70145
|
+
client: claim3,
|
|
70146
|
+
session,
|
|
70147
|
+
error: error62,
|
|
70148
|
+
profile: agent2
|
|
70149
|
+
});
|
|
69993
70150
|
if (!refused) throw error62;
|
|
69994
70151
|
if (refused.notice) stopContext({ context, text: refused.notice });
|
|
69995
70152
|
return;
|
|
@@ -70723,17 +70880,30 @@ async function setAgentPool({
|
|
|
70723
70880
|
|
|
70724
70881
|
// src/services/agent-session-commands.service.ts
|
|
70725
70882
|
var NO_SESSION = "Run this inside the Claude Code or Codex session the agent should listen in, or pass --session <id>.";
|
|
70883
|
+
var NO_AGENT = "This session and its folder have no agent: name one with `laze agent bind --profile <name>`.";
|
|
70726
70884
|
var DEFAULT_WAIT_SECONDS = 300;
|
|
70727
70885
|
async function bindAgentSession({
|
|
70728
70886
|
context,
|
|
70729
70887
|
args
|
|
70730
70888
|
}) {
|
|
70889
|
+
refuseInSubagent({ context, args });
|
|
70731
70890
|
const session = await currentSessionOf({ context, args });
|
|
70732
70891
|
if (!session) throw new CliUsageError(NO_SESSION);
|
|
70733
|
-
const
|
|
70892
|
+
const key = sessionKeyOf({ session });
|
|
70893
|
+
const config2 = await context.store.read();
|
|
70894
|
+
const held = config2.sessions?.[key];
|
|
70895
|
+
const own2 = held && config2.profiles[held] ? held : void 0;
|
|
70896
|
+
const explicit = flagText({ args, name: "profile" }) || void 0;
|
|
70897
|
+
const target = explicit ?? own2 ?? boundProfileOf({ bindings: config2.bindings, cwd: context.cwd });
|
|
70898
|
+
if (!target) throw new CliUsageError(NO_AGENT);
|
|
70899
|
+
const named = { ...args, flags: { ...args.flags, profile: target } };
|
|
70900
|
+
const { client, name: name2, profile } = await signedIn({ context, args: named });
|
|
70734
70901
|
await forSession({ client, session }).post("/api/agents/me/bind", {});
|
|
70735
|
-
await context.store.bindSession({ session:
|
|
70736
|
-
|
|
70902
|
+
await context.store.bindSession({ session: key, profile: name2 });
|
|
70903
|
+
const where = `profile ${name2}, config ${context.environment.configPath}`;
|
|
70904
|
+
const from = own2 && own2 !== name2 ? ` It moved from "${config2.profiles[own2]?.name}".` : "";
|
|
70905
|
+
context.out(`"${profile.name}" now listens in this session (${where}).${from}
|
|
70906
|
+
`);
|
|
70737
70907
|
}
|
|
70738
70908
|
async function mintedRequestProfile({
|
|
70739
70909
|
context,
|
|
@@ -71898,7 +72068,9 @@ var appPinSchemaDefinition = external_exports.object({
|
|
|
71898
72068
|
pinnedByName: external_exports.string().nullable(),
|
|
71899
72069
|
pinnedAt: external_exports.iso.datetime(),
|
|
71900
72070
|
/** Set for a browser tab, null for an app. */
|
|
71901
|
-
browser: browserPinSchemaDefinition.nullable()
|
|
72071
|
+
browser: browserPinSchemaDefinition.nullable(),
|
|
72072
|
+
/** Whether the reader may unpin it; a browser tab only its owner, their agents or an Admin. */
|
|
72073
|
+
canUnpin: external_exports.boolean().default(true)
|
|
71902
72074
|
});
|
|
71903
72075
|
var appPinViewSchemaDefinition = external_exports.object({
|
|
71904
72076
|
activeAppId: external_exports.string().nullable(),
|
|
@@ -72404,6 +72576,7 @@ var AppNavSlot = appUi.component("nav");
|
|
|
72404
72576
|
var AppPanelSlot = appUi.component("panel");
|
|
72405
72577
|
var AppCardSlot = appUi.component("card");
|
|
72406
72578
|
var AppPinStripSlot = appUi.component("pin-strip");
|
|
72579
|
+
var AppPinListSlot = appUi.component("pin-list");
|
|
72407
72580
|
|
|
72408
72581
|
// ../../modules/app/contract/src/app.config.ts
|
|
72409
72582
|
var appConfig = Config.define((c) => ({
|
|
@@ -76347,7 +76520,13 @@ async function monitorRound(turn) {
|
|
|
76347
76520
|
const named = { ...turn.args, flags: { ...turn.args.flags, profile: turn.profile } };
|
|
76348
76521
|
const { client } = await signedIn({ context, args: named });
|
|
76349
76522
|
const claim3 = forSession({ client, session });
|
|
76350
|
-
const refused = await notBoundNotice({
|
|
76523
|
+
const refused = await notBoundNotice({
|
|
76524
|
+
context,
|
|
76525
|
+
client: claim3,
|
|
76526
|
+
session,
|
|
76527
|
+
error: error62,
|
|
76528
|
+
profile: turn.profile
|
|
76529
|
+
});
|
|
76351
76530
|
if (refused?.rebound) return true;
|
|
76352
76531
|
if (refused?.notice) context.out(`${refused.notice}
|
|
76353
76532
|
`);
|
|
@@ -81431,6 +81610,7 @@ var MCP_REFUSED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
81431
81610
|
"vault add",
|
|
81432
81611
|
"vault replace",
|
|
81433
81612
|
"vault compare",
|
|
81613
|
+
"vault save-from-message",
|
|
81434
81614
|
"connect mcp-key",
|
|
81435
81615
|
"connect card-key"
|
|
81436
81616
|
]);
|
|
@@ -83502,15 +83682,20 @@ async function update2({
|
|
|
83502
83682
|
return 0;
|
|
83503
83683
|
}
|
|
83504
83684
|
|
|
83505
|
-
// src/services/vault-save-commands.service.ts
|
|
83506
|
-
var
|
|
83507
|
-
Names a key Laze held from a message you received, in the sender's vault
|
|
83685
|
+
// src/services/vault-save-message-commands.service.ts
|
|
83686
|
+
var SAVE_USAGE = `Usage: laze vault save <pending> --name <name> --description "<what it is for>"
|
|
83687
|
+
Names a key Laze held from a message you received, in the sender's vault.
|
|
83688
|
+
or: laze vault save --from-message <message-id> --name <name> --description "<what>" <<'EOF'
|
|
83689
|
+
Saves a key a person sent in that message, which Laze did not hold, to their own vault: the key
|
|
83690
|
+
on stdin, exactly as it is in the message. The message then shows {{vault:<name>}}. Run it in
|
|
83691
|
+
your turn in the message's conversation; it needs no vault access. MCP cannot send stdin.`;
|
|
83508
83692
|
var KEPT_IN_LAZE = "The key never left Laze: the chat, its history and your session hold only a reference, so there is nothing to rotate. Tell the person that.";
|
|
83509
|
-
async function
|
|
83510
|
-
|
|
83511
|
-
|
|
83512
|
-
|
|
83513
|
-
|
|
83693
|
+
async function postInTurn({
|
|
83694
|
+
context,
|
|
83695
|
+
args,
|
|
83696
|
+
path,
|
|
83697
|
+
body
|
|
83698
|
+
}) {
|
|
83514
83699
|
const env = context.environment.inherited;
|
|
83515
83700
|
const turn = await turnTokenOf4({
|
|
83516
83701
|
env,
|
|
@@ -83518,11 +83703,13 @@ async function vaultSave({ context, args }) {
|
|
|
83518
83703
|
command: "laze vault save"
|
|
83519
83704
|
});
|
|
83520
83705
|
const { client } = await signedIn({ context, args });
|
|
83521
|
-
|
|
83522
|
-
|
|
83523
|
-
|
|
83524
|
-
|
|
83525
|
-
|
|
83706
|
+
return client.withHeaders({ "x-laze-turn": turn }).post(path, body);
|
|
83707
|
+
}
|
|
83708
|
+
function printSaved({
|
|
83709
|
+
context,
|
|
83710
|
+
args,
|
|
83711
|
+
saved: saved3
|
|
83712
|
+
}) {
|
|
83526
83713
|
if (args.flags.json) return context.out(`${JSON.stringify(saved3, null, 2)}
|
|
83527
83714
|
`);
|
|
83528
83715
|
const done = saved3.outcome === "named" ? "Saved as" : "Already named";
|
|
@@ -83532,6 +83719,40 @@ ${KEPT_IN_LAZE}
|
|
|
83532
83719
|
`
|
|
83533
83720
|
);
|
|
83534
83721
|
}
|
|
83722
|
+
async function vaultSaveFromMessage({
|
|
83723
|
+
context,
|
|
83724
|
+
args
|
|
83725
|
+
}) {
|
|
83726
|
+
const messageId = flagText({ args, name: "from-message" });
|
|
83727
|
+
const name2 = flagText({ args, name: "name" });
|
|
83728
|
+
const description = flagText({ args, name: "description" });
|
|
83729
|
+
if (!messageId || !name2 || !description) throw new CliUsageError(SAVE_USAGE);
|
|
83730
|
+
const value = (await context.readStdin()).trim();
|
|
83731
|
+
if (!value) throw new CliUsageError(SAVE_USAGE);
|
|
83732
|
+
const saved3 = await postInTurn({
|
|
83733
|
+
context,
|
|
83734
|
+
args,
|
|
83735
|
+
path: `/api/chat/messages/${encodeURIComponent(messageId)}/save-secret`,
|
|
83736
|
+
body: { value, name: name2, description }
|
|
83737
|
+
});
|
|
83738
|
+
printSaved({ context, args, saved: saved3 });
|
|
83739
|
+
}
|
|
83740
|
+
|
|
83741
|
+
// src/services/vault-save-commands.service.ts
|
|
83742
|
+
async function vaultSave({ context, args }) {
|
|
83743
|
+
if (flagText({ args, name: "from-message" })) return vaultSaveFromMessage({ context, args });
|
|
83744
|
+
const pending = args.words[2];
|
|
83745
|
+
const name2 = flagText({ args, name: "name" });
|
|
83746
|
+
const description = flagText({ args, name: "description" });
|
|
83747
|
+
if (!pending || !name2 || !description) throw new CliUsageError(SAVE_USAGE);
|
|
83748
|
+
const saved3 = await postInTurn({
|
|
83749
|
+
context,
|
|
83750
|
+
args,
|
|
83751
|
+
path: "/api/vault/pending-secrets/save",
|
|
83752
|
+
body: { pending, name: name2, description }
|
|
83753
|
+
});
|
|
83754
|
+
printSaved({ context, args, saved: saved3 });
|
|
83755
|
+
}
|
|
83535
83756
|
|
|
83536
83757
|
// src/services/vault-scrub-commands.service.ts
|
|
83537
83758
|
function lineOf3(channel) {
|
|
@@ -84265,7 +84486,7 @@ var PATHS3 = {
|
|
|
84265
84486
|
var STATUS_WAIT_SECONDS2 = 50;
|
|
84266
84487
|
var STATUS_CALLS2 = 2;
|
|
84267
84488
|
var SETTLED = /* @__PURE__ */ new Set(["sent", "denied", "expired", "failed"]);
|
|
84268
|
-
var
|
|
84489
|
+
var USAGE18 = [
|
|
84269
84490
|
"Usage: laze whatsapp chats <machine> [--limit <n>] the chats on the machine, newest first",
|
|
84270
84491
|
" laze whatsapp read <machine> <chat> [--limit <n>] a chat's last messages, oldest first",
|
|
84271
84492
|
' laze whatsapp send <machine> <chat> "<text>" send as the owner; an agent waits for their approval',
|
|
@@ -84275,14 +84496,14 @@ var USAGE19 = [
|
|
|
84275
84496
|
].join("\n");
|
|
84276
84497
|
function word2({ args, at }) {
|
|
84277
84498
|
const value = args.words[at];
|
|
84278
|
-
if (!value) throw new CliUsageError(
|
|
84499
|
+
if (!value) throw new CliUsageError(USAGE18);
|
|
84279
84500
|
return value;
|
|
84280
84501
|
}
|
|
84281
84502
|
function limitOf5({ args }) {
|
|
84282
84503
|
const text2 = flagText({ args, name: "limit" });
|
|
84283
84504
|
if (!text2) return {};
|
|
84284
84505
|
const limit = Number(text2);
|
|
84285
|
-
if (!Number.isInteger(limit) || limit < 1) throw new CliUsageError(
|
|
84506
|
+
if (!Number.isInteger(limit) || limit < 1) throw new CliUsageError(USAGE18);
|
|
84286
84507
|
return { limit };
|
|
84287
84508
|
}
|
|
84288
84509
|
async function chats({ context, args }) {
|
|
@@ -84344,7 +84565,7 @@ Still waiting. Run \`laze whatsapp status ${send4.id}\` later to see the answer.
|
|
|
84344
84565
|
}
|
|
84345
84566
|
async function send3({ context, args }) {
|
|
84346
84567
|
const text2 = args.words.slice(4).join(" ") || args.rest.join(" ");
|
|
84347
|
-
if (!text2) throw new CliUsageError(
|
|
84568
|
+
if (!text2) throw new CliUsageError(USAGE18);
|
|
84348
84569
|
const client = await computeClient({ context, args });
|
|
84349
84570
|
const asked = await client.post(PATHS3.send, {
|
|
84350
84571
|
machine: word2({ args, at: 2 }),
|
|
@@ -84374,11 +84595,11 @@ async function whatsapp({
|
|
|
84374
84595
|
if (command === "status") return status7({ context, args });
|
|
84375
84596
|
const linking = whatsappPairingCommand(command);
|
|
84376
84597
|
if (linking) return linking({ context, args });
|
|
84377
|
-
throw new CliUsageError(
|
|
84598
|
+
throw new CliUsageError(USAGE18);
|
|
84378
84599
|
}
|
|
84379
84600
|
|
|
84380
84601
|
// src/services/wiki-commands.service.ts
|
|
84381
|
-
var
|
|
84602
|
+
var USAGE19 = `Usage:
|
|
84382
84603
|
laze wiki list
|
|
84383
84604
|
laze wiki get <path>
|
|
84384
84605
|
laze wiki put <path> <markdown|@file|-> [--title <title>] [--channel <channel>] [--base <version>]
|
|
@@ -84398,7 +84619,7 @@ async function wikiList({ context, args }) {
|
|
|
84398
84619
|
}
|
|
84399
84620
|
async function wikiGet({ context, args }) {
|
|
84400
84621
|
const path = args.words[2];
|
|
84401
|
-
if (!path) throw new CliUsageError(
|
|
84622
|
+
if (!path) throw new CliUsageError(USAGE19);
|
|
84402
84623
|
const { client } = await signedIn({ context, args });
|
|
84403
84624
|
const page = await client.post("/api/wiki/get", { path });
|
|
84404
84625
|
if (args.flags.json) return context.out(`${JSON.stringify(page, null, 2)}
|
|
@@ -84415,7 +84636,7 @@ Linked from: ${page.backlinks.map((link) => link.path).join(", ")}
|
|
|
84415
84636
|
async function wikiPut({ context, args }) {
|
|
84416
84637
|
const path = args.words[2];
|
|
84417
84638
|
const value = args.words.slice(3).join(" ");
|
|
84418
|
-
if (!path || !value) throw new CliUsageError(
|
|
84639
|
+
if (!path || !value) throw new CliUsageError(USAGE19);
|
|
84419
84640
|
const body = await textArgument({ context, value });
|
|
84420
84641
|
const title = flagText({ args, name: "title" });
|
|
84421
84642
|
const channel = flagText({ args, name: "channel" });
|
|
@@ -84435,7 +84656,7 @@ async function wikiPut({ context, args }) {
|
|
|
84435
84656
|
}
|
|
84436
84657
|
async function wikiSearch({ context, args }) {
|
|
84437
84658
|
const query = args.words.slice(2).join(" ").trim();
|
|
84438
|
-
if (!query) throw new CliUsageError(
|
|
84659
|
+
if (!query) throw new CliUsageError(USAGE19);
|
|
84439
84660
|
const { client } = await signedIn({ context, args });
|
|
84440
84661
|
const hits = await client.post("/api/wiki/search", { query });
|
|
84441
84662
|
if (args.flags.json) return context.out(`${JSON.stringify(hits, null, 2)}
|
|
@@ -84445,7 +84666,7 @@ async function wikiSearch({ context, args }) {
|
|
|
84445
84666
|
}
|
|
84446
84667
|
async function wikiHistory({ context, args }) {
|
|
84447
84668
|
const path = args.words[2];
|
|
84448
|
-
if (!path) throw new CliUsageError(
|
|
84669
|
+
if (!path) throw new CliUsageError(USAGE19);
|
|
84449
84670
|
const { client } = await signedIn({ context, args });
|
|
84450
84671
|
const revisions = await client.post("/api/wiki/history", { path });
|
|
84451
84672
|
if (args.flags.json) return context.out(`${JSON.stringify(revisions, null, 2)}
|
|
@@ -84459,7 +84680,7 @@ async function wikiHistory({ context, args }) {
|
|
|
84459
84680
|
}
|
|
84460
84681
|
async function wikiMove({ context, args }) {
|
|
84461
84682
|
const [, , path, to] = args.words;
|
|
84462
|
-
if (!path || !to) throw new CliUsageError(
|
|
84683
|
+
if (!path || !to) throw new CliUsageError(USAGE19);
|
|
84463
84684
|
const { client } = await signedIn({ context, args });
|
|
84464
84685
|
const page = await client.post("/api/wiki/move", { path, to });
|
|
84465
84686
|
if (args.flags.json) return context.out(`${JSON.stringify(page, null, 2)}
|
|
@@ -84469,7 +84690,7 @@ async function wikiMove({ context, args }) {
|
|
|
84469
84690
|
}
|
|
84470
84691
|
async function wikiRemove({ context, args }) {
|
|
84471
84692
|
const path = args.words[2];
|
|
84472
|
-
if (!path) throw new CliUsageError(
|
|
84693
|
+
if (!path) throw new CliUsageError(USAGE19);
|
|
84473
84694
|
const { client } = await signedIn({ context, args });
|
|
84474
84695
|
const removed = await client.post("/api/wiki/remove", { path });
|
|
84475
84696
|
if (args.flags.json) return context.out(`${JSON.stringify(removed)}
|
|
@@ -84489,7 +84710,7 @@ var WIKI_COMMANDS = {
|
|
|
84489
84710
|
async function wiki({ context, args }) {
|
|
84490
84711
|
const name2 = args.words[1] ?? "";
|
|
84491
84712
|
const command = Object.hasOwn(WIKI_COMMANDS, name2) ? WIKI_COMMANDS[name2] : void 0;
|
|
84492
|
-
if (!command) throw new CliUsageError(
|
|
84713
|
+
if (!command) throw new CliUsageError(USAGE19);
|
|
84493
84714
|
await command({ context, args });
|
|
84494
84715
|
}
|
|
84495
84716
|
|
|
@@ -85107,6 +85328,8 @@ var HELP = `laze: work in a Laze workspace from your terminal or your agent.
|
|
|
85107
85328
|
laze adopt codex --status | --stop the background adopt that laze agent link started
|
|
85108
85329
|
laze vault run <name> --reason "<why>" -- <cmd> run a command with a vault connection (agents)
|
|
85109
85330
|
laze vault save <pending> --name <name> --description "<text>" name a key Laze held from a message (agents)
|
|
85331
|
+
laze vault save --from-message <id> --name <name> --description "<text>" save a key a person sent,
|
|
85332
|
+
read from stdin, to their own vault; the message keeps {{vault:<name>}} (agents, no vault access)
|
|
85110
85333
|
laze vault scrub [--dry-run] move secrets found in messages to the vault now (admins)
|
|
85111
85334
|
laze vault list|add|update|replace|compare|rm|revoke|uses your keychains with your own key
|
|
85112
85335
|
a value comes from stdin or --from-file, never a flag; no command prints a value
|
|
@@ -85262,6 +85485,7 @@ var COMMANDS3 = {
|
|
|
85262
85485
|
app,
|
|
85263
85486
|
"vault run": vaultRun,
|
|
85264
85487
|
"vault save": vaultSave,
|
|
85488
|
+
"vault save-from-message": vaultSaveFromMessage,
|
|
85265
85489
|
connect,
|
|
85266
85490
|
slack,
|
|
85267
85491
|
"connect providers": connectAsPerson,
|
package/package.json
CHANGED