@lazehq/cli 0.1.30 → 0.1.32
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 +1112 -816
- package/package.json +1 -1
package/dist/laze.mjs
CHANGED
|
@@ -18733,8 +18733,8 @@ var require_snapshot_utils = __commonJS({
|
|
|
18733
18733
|
var require_snapshot_recorder = __commonJS({
|
|
18734
18734
|
"../../node_modules/.pnpm/undici@8.10.0/node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
|
|
18735
18735
|
"use strict";
|
|
18736
|
-
var { writeFile: writeFile23, readFile:
|
|
18737
|
-
var { dirname:
|
|
18736
|
+
var { writeFile: writeFile23, readFile: readFile39, mkdir: mkdir21 } = __require("node:fs/promises");
|
|
18737
|
+
var { dirname: dirname22, resolve: resolve17 } = __require("node:path");
|
|
18738
18738
|
var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
|
|
18739
18739
|
var { InvalidArgumentError, UndiciError } = require_errors();
|
|
18740
18740
|
var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
|
|
@@ -18950,7 +18950,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
18950
18950
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
18951
18951
|
}
|
|
18952
18952
|
try {
|
|
18953
|
-
const data = await
|
|
18953
|
+
const data = await readFile39(resolve17(path), "utf8");
|
|
18954
18954
|
const parsed = JSON.parse(data);
|
|
18955
18955
|
if (Array.isArray(parsed)) {
|
|
18956
18956
|
this.#snapshots.clear();
|
|
@@ -18980,7 +18980,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
18980
18980
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
18981
18981
|
}
|
|
18982
18982
|
const resolvedPath = resolve17(path);
|
|
18983
|
-
await mkdir21(
|
|
18983
|
+
await mkdir21(dirname22(resolvedPath), { recursive: true });
|
|
18984
18984
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
18985
18985
|
hash: hash2,
|
|
18986
18986
|
snapshot
|
|
@@ -35645,6 +35645,7 @@ function boundProfileOf({
|
|
|
35645
35645
|
// src/rules/args.rules.ts
|
|
35646
35646
|
var SWITCHES = /* @__PURE__ */ new Set([
|
|
35647
35647
|
"wait",
|
|
35648
|
+
"take",
|
|
35648
35649
|
"json",
|
|
35649
35650
|
"no-hook",
|
|
35650
35651
|
"help",
|
|
@@ -35707,7 +35708,7 @@ function flagText({
|
|
|
35707
35708
|
}
|
|
35708
35709
|
|
|
35709
35710
|
// src/rules/cli-version.rules.ts
|
|
35710
|
-
var STAMPED = "0.1.
|
|
35711
|
+
var STAMPED = "0.1.32";
|
|
35711
35712
|
function cliVersionOf({ stamped = STAMPED } = {}) {
|
|
35712
35713
|
return stamped.startsWith("__") ? "dev" : stamped;
|
|
35713
35714
|
}
|
|
@@ -57981,6 +57982,7 @@ var deleteDraftInputSchema = deleteDraftInputSchemaDefinition;
|
|
|
57981
57982
|
var GROUP_DM_MAX_MEMBERS = 8;
|
|
57982
57983
|
var MESSAGE_BODY_MAX = 4e4;
|
|
57983
57984
|
var HISTORY_PAGE_MAX = 100;
|
|
57985
|
+
var NOTICE_DETAILS_MAX = 2e3;
|
|
57984
57986
|
var workspaceIdSchema = external_exports.string().min(1);
|
|
57985
57987
|
var idSchema4 = external_exports.string().min(1).max(64);
|
|
57986
57988
|
var chatActorKindSchema = external_exports.enum(["person", "agent"]);
|
|
@@ -58275,6 +58277,10 @@ var feedCardSchemaDefinition = external_exports.object({
|
|
|
58275
58277
|
itemId: idSchema4,
|
|
58276
58278
|
changeId: idSchema4
|
|
58277
58279
|
});
|
|
58280
|
+
var failureCardSchemaDefinition = external_exports.object({
|
|
58281
|
+
type: external_exports.literal("failure"),
|
|
58282
|
+
details: external_exports.string().min(1).max(NOTICE_DETAILS_MAX)
|
|
58283
|
+
});
|
|
58278
58284
|
var messageCardSchemaDefinition = external_exports.discriminatedUnion("type", [
|
|
58279
58285
|
attentionCardSchemaDefinition,
|
|
58280
58286
|
connectCardSchemaDefinition,
|
|
@@ -58285,7 +58291,8 @@ var messageCardSchemaDefinition = external_exports.discriminatedUnion("type", [
|
|
|
58285
58291
|
heldCardSchemaDefinition,
|
|
58286
58292
|
hopLimitCardSchemaDefinition,
|
|
58287
58293
|
budgetCardSchemaDefinition,
|
|
58288
|
-
feedCardSchemaDefinition
|
|
58294
|
+
feedCardSchemaDefinition,
|
|
58295
|
+
failureCardSchemaDefinition
|
|
58289
58296
|
]);
|
|
58290
58297
|
var messageRefSchemaDefinition = external_exports.object({
|
|
58291
58298
|
/** `conversation` points at a conversation with the agent, by its channel. */
|
|
@@ -58680,6 +58687,8 @@ var postNoticeInputSchemaDefinition = external_exports.object({
|
|
|
58680
58687
|
ref: messageRefSchemaDefinition.optional(),
|
|
58681
58688
|
/** Set on the notice a compaction leaves, so it draws as a divider. */
|
|
58682
58689
|
compaction: messageCompactionSchemaDefinition.optional(),
|
|
58690
|
+
/** The raw reason behind the line, such as a provider's error, shown only under Details. */
|
|
58691
|
+
details: external_exports.string().trim().min(1).max(NOTICE_DETAILS_MAX).optional(),
|
|
58683
58692
|
/** One notice per key: a second post with it answers the first. */
|
|
58684
58693
|
clientKey: external_exports.string().regex(/^[A-Za-z0-9_-]{8,64}$/).optional()
|
|
58685
58694
|
});
|
|
@@ -60342,6 +60351,25 @@ var attentionClosedReasonSchema = external_exports.enum([
|
|
|
60342
60351
|
]);
|
|
60343
60352
|
var permissionDecisionSchema2 = external_exports.enum(["allowed", "skipped"]);
|
|
60344
60353
|
var permissionSkipReasonSchema = external_exports.enum(["question", "plan", "plan_mode"]);
|
|
60354
|
+
var liveStepKindSchema = external_exports.enum(["tool", "subagent", "shell"]);
|
|
60355
|
+
var liveStepStatusSchema = external_exports.enum(["running", "done", "failed"]);
|
|
60356
|
+
var LIVE_STEP_LABEL_MAX = 160;
|
|
60357
|
+
var LIVE_STEPS_BATCH_MAX = 100;
|
|
60358
|
+
var liveStepSchemaDefinition = external_exports.object({
|
|
60359
|
+
id: external_exports.string().min(1).max(200),
|
|
60360
|
+
kind: liveStepKindSchema,
|
|
60361
|
+
/** `Bash(Run the tests)` for a tool; the task for a subagent; what a shell runs. */
|
|
60362
|
+
label: external_exports.string().max(LIVE_STEP_LABEL_MAX),
|
|
60363
|
+
status: liveStepStatusSchema,
|
|
60364
|
+
/** Epoch ms. */
|
|
60365
|
+
startedAt: external_exports.number().int().nonnegative(),
|
|
60366
|
+
endedAt: external_exports.number().int().nonnegative().optional(),
|
|
60367
|
+
/** A subagent's type or model, such as `Explore` or `claude-haiku-4-5`. */
|
|
60368
|
+
agent: external_exports.string().max(80).optional(),
|
|
60369
|
+
/** A subagent's tool calls so far. */
|
|
60370
|
+
steps: external_exports.number().int().nonnegative().optional()
|
|
60371
|
+
});
|
|
60372
|
+
var liveStepSchema = liveStepSchemaDefinition;
|
|
60345
60373
|
var lazeAgentEventSchemaDefinition = external_exports.discriminatedUnion("type", [
|
|
60346
60374
|
external_exports.object({
|
|
60347
60375
|
type: external_exports.literal("harness_started"),
|
|
@@ -60375,6 +60403,12 @@ var lazeAgentEventSchemaDefinition = external_exports.discriminatedUnion("type",
|
|
|
60375
60403
|
failure: external_exports.object({ code: external_exports.string().min(1), message: external_exports.string() }).optional()
|
|
60376
60404
|
}),
|
|
60377
60405
|
external_exports.object({ type: external_exports.literal("text_delta"), messageId: external_exports.string().optional(), text: external_exports.string() }),
|
|
60406
|
+
/** Steps that changed since the last batch, coalesced on the computer; streamed, never stored. */
|
|
60407
|
+
external_exports.object({
|
|
60408
|
+
type: external_exports.literal("steps"),
|
|
60409
|
+
turnId: external_exports.string().min(1),
|
|
60410
|
+
steps: external_exports.array(liveStepSchemaDefinition).max(LIVE_STEPS_BATCH_MAX)
|
|
60411
|
+
}),
|
|
60378
60412
|
external_exports.object({
|
|
60379
60413
|
type: external_exports.literal("message"),
|
|
60380
60414
|
role: external_exports.enum(["user", "assistant"]),
|
|
@@ -60750,7 +60784,9 @@ var hostFrameSchemaDefinition = external_exports.discriminatedUnion("type", [
|
|
|
60750
60784
|
external_exports.object({
|
|
60751
60785
|
type: external_exports.literal("hello"),
|
|
60752
60786
|
agentToken: external_exports.string().min(1),
|
|
60753
|
-
lastAckedSeq: external_exports.number().int()
|
|
60787
|
+
lastAckedSeq: external_exports.number().int(),
|
|
60788
|
+
/** This host takes `steps` events; a supervisor sends none to a host that does not say so. */
|
|
60789
|
+
liveSteps: external_exports.boolean().optional()
|
|
60754
60790
|
}),
|
|
60755
60791
|
external_exports.object({
|
|
60756
60792
|
type: external_exports.literal("deliver"),
|
|
@@ -63619,6 +63655,66 @@ var linkRedemptionSchemaDefinition = external_exports.discriminatedUnion("status
|
|
|
63619
63655
|
]);
|
|
63620
63656
|
var linkRedemptionSchema = linkRedemptionSchemaDefinition;
|
|
63621
63657
|
|
|
63658
|
+
// ../../modules/agent/contract/src/agent-live-steps.ts
|
|
63659
|
+
var liveTurnStateSchema = external_exports.enum(["working", "done", "stopped", "failed"]);
|
|
63660
|
+
var sequencedStepSchemaDefinition = external_exports.object({
|
|
63661
|
+
...liveStepSchema.shape,
|
|
63662
|
+
seq: external_exports.number().int().positive()
|
|
63663
|
+
});
|
|
63664
|
+
var liveTurnSchemaDefinition = external_exports.object({
|
|
63665
|
+
turnKey: external_exports.string().min(1),
|
|
63666
|
+
state: liveTurnStateSchema,
|
|
63667
|
+
startedAt: external_exports.number().int().nonnegative(),
|
|
63668
|
+
endedAt: external_exports.number().int().nonnegative().nullable(),
|
|
63669
|
+
/** Every tool call of the turn, also those past the kept lines. */
|
|
63670
|
+
tools: external_exports.number().int().nonnegative()
|
|
63671
|
+
});
|
|
63672
|
+
var liveStepsPublicationSchemaDefinition = external_exports.discriminatedUnion("type", [
|
|
63673
|
+
external_exports.object({
|
|
63674
|
+
type: external_exports.literal("step"),
|
|
63675
|
+
turnKey: external_exports.string().min(1),
|
|
63676
|
+
step: sequencedStepSchemaDefinition
|
|
63677
|
+
}),
|
|
63678
|
+
external_exports.object({
|
|
63679
|
+
type: external_exports.literal("turn"),
|
|
63680
|
+
turnKey: external_exports.string().min(1),
|
|
63681
|
+
seq: external_exports.number().int().positive(),
|
|
63682
|
+
turn: liveTurnSchemaDefinition
|
|
63683
|
+
})
|
|
63684
|
+
]);
|
|
63685
|
+
var liveStepsInputSchemaDefinition = external_exports.object({
|
|
63686
|
+
workspaceId: external_exports.string().min(1),
|
|
63687
|
+
agentId: external_exports.string().min(1),
|
|
63688
|
+
channelId: external_exports.string().min(1),
|
|
63689
|
+
/** A finished turn's key, as a reply names it; the running turn when left out. */
|
|
63690
|
+
turnKey: external_exports.string().min(1).optional()
|
|
63691
|
+
});
|
|
63692
|
+
var liveStepsInputSchema = liveStepsInputSchemaDefinition;
|
|
63693
|
+
var liveStepsSchemaDefinition = external_exports.object({
|
|
63694
|
+
turn: liveTurnSchemaDefinition.nullable(),
|
|
63695
|
+
steps: external_exports.array(sequencedStepSchemaDefinition),
|
|
63696
|
+
lastSeq: external_exports.number().int().nonnegative(),
|
|
63697
|
+
/** Null where the realtime edge is not configured: the panel says live steps are unavailable. */
|
|
63698
|
+
stream: realtimeTokenSchema.nullable()
|
|
63699
|
+
});
|
|
63700
|
+
var liveStepsSchema = liveStepsSchemaDefinition;
|
|
63701
|
+
var replyStepsInputSchemaDefinition = external_exports.object({
|
|
63702
|
+
workspaceId: external_exports.string().min(1),
|
|
63703
|
+
channelId: external_exports.string().min(1),
|
|
63704
|
+
messageIds: external_exports.array(external_exports.string().min(1)).max(200)
|
|
63705
|
+
});
|
|
63706
|
+
var replyStepsInputSchema = replyStepsInputSchemaDefinition;
|
|
63707
|
+
var replyStepsSchemaDefinition = external_exports.array(
|
|
63708
|
+
external_exports.object({
|
|
63709
|
+
messageId: external_exports.string().min(1),
|
|
63710
|
+
agentId: external_exports.string().min(1),
|
|
63711
|
+
turnKey: external_exports.string().min(1),
|
|
63712
|
+
state: liveTurnStateSchema,
|
|
63713
|
+
tools: external_exports.number().int().nonnegative()
|
|
63714
|
+
})
|
|
63715
|
+
);
|
|
63716
|
+
var replyStepsSchema = replyStepsSchemaDefinition;
|
|
63717
|
+
|
|
63622
63718
|
// ../../modules/agent/contract/src/agent-login-trouble.ts
|
|
63623
63719
|
var loginCardActionInputSchemaDefinition = external_exports.object({
|
|
63624
63720
|
workspaceId: external_exports.string().min(1),
|
|
@@ -64268,6 +64364,8 @@ var harnessLoginsSchemaDefinition = external_exports.object({
|
|
|
64268
64364
|
codex: external_exports.boolean()
|
|
64269
64365
|
});
|
|
64270
64366
|
var harnessLoginsSchema = harnessLoginsSchemaDefinition;
|
|
64367
|
+
var lastRuntimeSchemaDefinition = external_exports.object({ harness: hostedHarnessSchema.nullable() });
|
|
64368
|
+
var lastRuntimeSchema = lastRuntimeSchemaDefinition;
|
|
64271
64369
|
var mintLinkInputSchemaDefinition = external_exports.object({
|
|
64272
64370
|
workspaceId: workspaceIdSchema10,
|
|
64273
64371
|
/** Left out, the agent names itself when it joins, else it takes its harness's name. */
|
|
@@ -64555,11 +64653,12 @@ var codexLoginRefreshInputSchemaDefinition = external_exports.object({
|
|
|
64555
64653
|
});
|
|
64556
64654
|
var AgentApi = moduleApi()("agent");
|
|
64557
64655
|
var agentCoreTrpc = defineTrpcContract("agents").query("list").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(external_exports.array(agentListEntrySchema)).mutation("create").withInput(createAgentInputSchema).withOutput(agentSchema).mutation("update").withInput(updateAgentInputSchema).withOutput(agentSchema).mutation("remove").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(external_exports.object({ removed: external_exports.literal(true) })).mutation("transfer").withInput(transferAgentInputSchema).withOutput(agentSchema).mutation("resetSession").withInput(resetAgentSessionInputSchema).withOutput(agentSchema).query("faces").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(external_exports.array(agentFaceSchema)).query("presence").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(external_exports.array(agentPresenceSchema)).mutation("uploadAvatar").withInput(uploadAgentAvatarInputSchema).withOutput(uploadedAgentAvatarSchema).query("access").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(agentAccessSchema).query("loginActivity").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(loginActivitySchema).mutation("raiseBudget").withInput(raiseBudgetInputSchema).withOutput(external_exports.object({ limitUsd: external_exports.number() })).query("permissionPrompts").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(external_exports.array(agentPermissionPromptSchema)).mutation("share").withInput(shareAgentInputSchema).withOutput(agentAccessSchema).mutation("unshare").withInput(shareAgentInputSchema).withOutput(agentAccessSchema).query("harnessLogins").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(harnessLoginsSchema).mutation("saveHarnessLogin").withInput(saveHarnessLoginInputSchema).withOutput(harnessLoginsSchema).mutation("removeHarnessLogin").withInput(removeHarnessLoginInputSchema).withOutput(harnessLoginsSchema).query("listHarnessLogins").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(harnessLoginListSchema).mutation("addHarnessLogin").withInput(addHarnessLoginInputSchema).withOutput(harnessLoginListSchema).mutation("renameHarnessLogin").withInput(renameHarnessLoginInputSchema).withOutput(harnessLoginListSchema).mutation("deleteHarnessLogin").withInput(deleteHarnessLoginInputSchema).withOutput(harnessLoginListSchema).mutation("checkLoginUsage").withInput(checkLoginUsageInputSchema).withOutput(loginUsageCheckSchema).query("loginPools").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(loginPoolsSchema).mutation("createLoginPool").withInput(createLoginPoolInputSchema).withOutput(loginPoolsSchema).mutation("renameLoginPool").withInput(renameLoginPoolInputSchema).withOutput(loginPoolsSchema).mutation("deleteLoginPool").withInput(loginPoolRefInputSchema).withOutput(loginPoolsSchema).mutation("addPoolLogin").withInput(addPoolLoginInputSchema).withOutput(loginPoolsSchema).mutation("removePoolLogin").withInput(removePoolLoginInputSchema).withOutput(loginPoolsSchema).mutation("setPoolMember").withInput(setPoolMemberInputSchema).withOutput(loginPoolsSchema).mutation("removePoolMember").withInput(removePoolMemberInputSchema).withOutput(loginPoolsSchema).mutation("setAgentPool").withInput(setAgentPoolInputSchema).withOutput(agentSchema).mutation("openDirect").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(external_exports.object({ channelId: idSchema14 })).mutation("startConversation").withInput(startConversationInputSchema).withOutput(startedConversationSchema).query("conversations").withInput(listConversationsInputSchema).withOutput(external_exports.array(conversationSummarySchema2)).mutation("joinConversation").withInput(conversationInputSchema).withOutput(conversationSummarySchema2).mutation("renameConversation").withInput(renameConversationInputSchema).withOutput(conversationSummarySchema2).mutation("leaveConversation").withInput(conversationInputSchema).withOutput(external_exports.object({ left: external_exports.literal(true) })).mutation("deleteConversation").withInput(conversationInputSchema).withOutput(external_exports.object({ deleted: external_exports.literal(true) })).mutation("mintLink").withInput(mintLinkInputSchema).withOutput(mintedLinkSchema).query("linkRedemption").withInput(linkRedemptionInputSchema).withOutput(linkRedemptionSchema).query("oauthRequest").withInput(oauthRequestInputSchema).withOutput(oauthRequestViewSchema).mutation("oauthApprove").withInput(approveOAuthInputSchema).withOutput(oauthRedirectSchema).mutation("oauthDeny").withInput(oauthRequestInputSchema).withOutput(oauthRedirectSchema).mutation("disconnect").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(external_exports.object({ disconnected: external_exports.literal(true) })).mutation("setGithub").withInput(setAgentGithubInputSchema).withOutput(agentSchema).query("githubWatches").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(external_exports.array(agentGithubWatchSchema)).mutation("watchGithub").withInput(watchGithubInputSchema).withOutput(agentGithubWatchSchema).mutation("unwatchGithub").withInput(unwatchGithubInputSchema).withOutput(external_exports.object({ removed: external_exports.literal(true) })).build();
|
|
64558
|
-
var agentTurnTrpc = defineTrpcContract("agents").mutation("answerAttention").withInput(answerAttentionInputSchema).withOutput(external_exports.object({ answered: external_exports.literal(true) })).mutation("stopTurn").withInput(stopAgentTurnInputSchema).withOutput(external_exports.object({ stopped: external_exports.literal(true) })).query("mayStopTurn").withInput(stopAgentTurnInputSchema).withOutput(external_exports.object({ allowed: external_exports.boolean() })).mutation("compactSession").withInput(compactAgentSessionInputSchema).withOutput(external_exports.object({ requested: external_exports.literal(true) })).mutation("restartComputer").withInput(restartAgentComputerInputSchema).withOutput(external_exports.object({ restarted: external_exports.boolean() })).build();
|
|
64656
|
+
var agentTurnTrpc = defineTrpcContract("agents").mutation("answerAttention").withInput(answerAttentionInputSchema).withOutput(external_exports.object({ answered: external_exports.literal(true) })).mutation("stopTurn").withInput(stopAgentTurnInputSchema).withOutput(external_exports.object({ stopped: external_exports.literal(true) })).query("mayStopTurn").withInput(stopAgentTurnInputSchema).withOutput(external_exports.object({ allowed: external_exports.boolean() })).query("liveSteps").withInput(liveStepsInputSchema).withOutput(liveStepsSchema).query("replySteps").withInput(replyStepsInputSchema).withOutput(replyStepsSchema).mutation("compactSession").withInput(compactAgentSessionInputSchema).withOutput(external_exports.object({ requested: external_exports.literal(true) })).mutation("restartComputer").withInput(restartAgentComputerInputSchema).withOutput(external_exports.object({ restarted: external_exports.boolean() })).build();
|
|
64559
64657
|
var agentChannelSettingsTrpc = defineTrpcContract("agents").query("monitors").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14 })).withOutput(external_exports.array(agentMonitorSchema)).query("channelLevel").withInput(external_exports.object({ workspaceId: workspaceIdSchema10, agentId: idSchema14, channelId: idSchema14 })).withOutput(channelLevelSchema).mutation("setChannelLevel").withInput(setChannelLevelInputSchema).withOutput(channelLevelSchema).mutation("unmuteChannel").withInput(unmuteAgentChannelInputSchema).withOutput(channelLevelSchema).mutation("cancelHeld").withInput(cancelHeldInputSchema).withOutput(cancelHeldResultSchema).build();
|
|
64560
64658
|
var agentJoinTrpc = defineTrpcContract("agents").query("joinRequest").withInput(joinRequestInputSchema).withOutput(joinRequestViewSchema).mutation("approveJoinRequest").withInput(approveJoinRequestInputSchema).withOutput(joinRequestViewSchema).mutation("denyJoinRequest").withInput(joinRequestInputSchema).withOutput(joinRequestViewSchema).build();
|
|
64561
64659
|
var agentLoginTroubleTrpc = defineTrpcContract("agents").mutation("replaceHarnessLogin").withInput(replaceHarnessLoginInputSchema).withOutput(harnessLoginListSchema).mutation("startHarnessSignIn").withInput(startHarnessSignInInputSchema).withOutput(harnessSignInSchema).mutation("pollHarnessSignIn").withInput(pollHarnessSignInInputSchema).withOutput(harnessSignInPollSchema).mutation("waitForLogins").withInput(loginCardActionInputSchema).withOutput(external_exports.object({ waiting: external_exports.boolean() })).mutation("useAnotherLogin").withInput(loginCardActionInputSchema).withOutput(external_exports.object({ loginName: external_exports.string() })).build();
|
|
64562
64660
|
var agentWorkspaceDefaultTrpc = defineTrpcContract("agents").query("workspaceDefault").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(workspaceDefaultAgentSchema).mutation("setWorkspaceDefault").withInput(setWorkspaceDefaultAgentInputSchema).withOutput(workspaceDefaultAgentSchema).build();
|
|
64661
|
+
var agentRuntimeChoiceTrpc = defineTrpcContract("agents").query("lastRuntime").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(lastRuntimeSchema).build();
|
|
64563
64662
|
var agentArchiveTrpc = defineTrpcContract("agents").query("archived").withInput(external_exports.object({ workspaceId: workspaceIdSchema10 })).withOutput(external_exports.array(archivedAgentSchema)).mutation("restore").withInput(restoreAgentInputSchema).withOutput(agentSchema).mutation("copy").withInput(copyAgentInputSchema).withOutput(agentSchema).mutation("deleteArchived").withInput(restoreAgentInputSchema).withOutput(external_exports.object({ deleted: external_exports.literal(true) })).build();
|
|
64564
64663
|
var agentTrpc = joinTrpcContracts(
|
|
64565
64664
|
"agents",
|
|
@@ -64569,6 +64668,7 @@ var agentTrpc = joinTrpcContracts(
|
|
|
64569
64668
|
agentJoinTrpc,
|
|
64570
64669
|
agentLoginTroubleTrpc,
|
|
64571
64670
|
agentWorkspaceDefaultTrpc,
|
|
64671
|
+
agentRuntimeChoiceTrpc,
|
|
64572
64672
|
agentArchiveTrpc
|
|
64573
64673
|
);
|
|
64574
64674
|
var agentUi = uiTokens("agent");
|
|
@@ -64578,6 +64678,8 @@ var AgentComputerCardSlot = agentUi.component("computerCard");
|
|
|
64578
64678
|
var AgentLoginCardSlot = agentUi.component("loginCard");
|
|
64579
64679
|
var AgentBudgetCardSlot = agentUi.component("budgetCard");
|
|
64580
64680
|
var AgentStopTurnSlot = agentUi.component("stopTurn");
|
|
64681
|
+
var AgentLiveStepsSlot = agentUi.component("liveSteps");
|
|
64682
|
+
var AgentReplyStepsSlot = agentUi.component("replySteps");
|
|
64581
64683
|
var AgentSessionHooksToken = agentUi.hooks("session");
|
|
64582
64684
|
var AgentCreateDialogSlot = agentUi.component("createDialog");
|
|
64583
64685
|
var AgentEditDialogSlot = agentUi.component("editDialog");
|
|
@@ -64616,8 +64718,6 @@ var agentConfig = Config.define((c) => ({
|
|
|
64616
64718
|
"AGENT_CLAUDE_GATEWAY_THINKING",
|
|
64617
64719
|
external_exports.enum(["on", "off"]).default("on")
|
|
64618
64720
|
),
|
|
64619
|
-
claudeModel: c.env("AGENT_CLAUDE_MODEL", external_exports.string().min(1).default("sonnet")),
|
|
64620
|
-
codexModel: c.env("AGENT_CODEX_MODEL", external_exports.string().min(1).default("gpt-5.5")),
|
|
64621
64721
|
/** The Codex model's window, which caps a Codex agent's context window setting. */
|
|
64622
64722
|
codexContextWindow: c.env("AGENT_CODEX_CONTEXT", positiveInt3.default(4e5)),
|
|
64623
64723
|
/** A harness prompt or question no one answers is denied or dismissed after this long. */
|
|
@@ -65572,8 +65672,8 @@ async function copyAgent({
|
|
|
65572
65672
|
}
|
|
65573
65673
|
|
|
65574
65674
|
// src/services/agent-commands.service.ts
|
|
65575
|
-
import { mkdir as mkdir14, readFile as
|
|
65576
|
-
import { join as
|
|
65675
|
+
import { mkdir as mkdir14, readFile as readFile14, writeFile as writeFile14 } from "node:fs/promises";
|
|
65676
|
+
import { join as join15, resolve as resolve4 } from "node:path";
|
|
65577
65677
|
|
|
65578
65678
|
// src/rules/agent-profile.rules.ts
|
|
65579
65679
|
var LEVELS = { fast: "Laze Fast", frontier: "Laze Frontier" };
|
|
@@ -66748,14 +66848,32 @@ function rushSessionOf({
|
|
|
66748
66848
|
function rushSendCommand({ program, id }) {
|
|
66749
66849
|
return ["sh", "-c", 'printf "%s\\n" "$LAZE_WAKE_TEXT" | "$0" session send "$1"', program, id];
|
|
66750
66850
|
}
|
|
66751
|
-
function
|
|
66851
|
+
function rushListedOf({ listed }) {
|
|
66752
66852
|
try {
|
|
66753
66853
|
const sessions = JSON.parse(listed);
|
|
66754
|
-
return
|
|
66854
|
+
return Array.isArray(sessions) ? sessions : [];
|
|
66755
66855
|
} catch {
|
|
66756
|
-
return
|
|
66856
|
+
return [];
|
|
66757
66857
|
}
|
|
66758
66858
|
}
|
|
66859
|
+
function rushListsLive({ listed, sessionId }) {
|
|
66860
|
+
return rushListedOf({ listed }).some(
|
|
66861
|
+
(one) => one.sessionId === sessionId && one.state !== "stopped"
|
|
66862
|
+
);
|
|
66863
|
+
}
|
|
66864
|
+
function rushRunsElsewhere({
|
|
66865
|
+
listed,
|
|
66866
|
+
sessionId,
|
|
66867
|
+
claudePid
|
|
66868
|
+
}) {
|
|
66869
|
+
return rushListedOf({ listed }).some(
|
|
66870
|
+
(one) => one.sessionId === sessionId && one.state !== "stopped" && one.alive === true && one.claudePid !== claudePid
|
|
66871
|
+
);
|
|
66872
|
+
}
|
|
66873
|
+
function rushStandingOf({ one }) {
|
|
66874
|
+
if (!one || one.state === "stopped") return "stopped";
|
|
66875
|
+
return one.alive === false ? "asleep" : "awake";
|
|
66876
|
+
}
|
|
66759
66877
|
|
|
66760
66878
|
// src/services/claude-project.service.ts
|
|
66761
66879
|
import { basename as basename2, isAbsolute, relative as relative2, resolve as resolve2 } from "node:path";
|
|
@@ -66949,8 +67067,7 @@ async function sessionProfileArgs({
|
|
|
66949
67067
|
}
|
|
66950
67068
|
return args;
|
|
66951
67069
|
}
|
|
66952
|
-
async function
|
|
66953
|
-
const sessionId = key.slice(key.indexOf(":") + 1);
|
|
67070
|
+
async function rushListingOf({ context }) {
|
|
66954
67071
|
let listed = "";
|
|
66955
67072
|
const code = await context.runCommand({
|
|
66956
67073
|
command: ["sh", "-c", "command -v rush >/dev/null && rush session list --json"],
|
|
@@ -66958,15 +67075,27 @@ async function rushKeeps({ context, key }) {
|
|
|
66958
67075
|
stdout: { write: (chunk) => listed += chunk },
|
|
66959
67076
|
stderr: { write: () => true }
|
|
66960
67077
|
}).catch(() => 1);
|
|
66961
|
-
|
|
66962
|
-
|
|
67078
|
+
return code === 0 ? listed : void 0;
|
|
67079
|
+
}
|
|
67080
|
+
async function rushKeeps({
|
|
67081
|
+
context,
|
|
67082
|
+
key,
|
|
67083
|
+
claudePid,
|
|
67084
|
+
asleepCounts
|
|
67085
|
+
}) {
|
|
67086
|
+
const sessionId = key.slice(key.indexOf(":") + 1);
|
|
67087
|
+
const listed = await rushListingOf({ context });
|
|
67088
|
+
if (listed === void 0) return false;
|
|
67089
|
+
if (asleepCounts) return rushListsLive({ listed, sessionId });
|
|
67090
|
+
return rushRunsElsewhere({ listed, sessionId, claudePid });
|
|
66963
67091
|
}
|
|
66964
67092
|
async function liveElsewhere({
|
|
66965
67093
|
context,
|
|
66966
67094
|
key,
|
|
66967
|
-
claudePid
|
|
67095
|
+
claudePid,
|
|
67096
|
+
asleepCounts = true
|
|
66968
67097
|
}) {
|
|
66969
|
-
if (await rushKeeps({ context, key })) return true;
|
|
67098
|
+
if (await rushKeeps({ context, key, claudePid, asleepCounts })) return true;
|
|
66970
67099
|
const folder = dirname3(statePathOf({ context, kind: "sessions", profile: "x" }));
|
|
66971
67100
|
for (const file3 of await readdir(folder).catch(() => [])) {
|
|
66972
67101
|
const pid = Number(file3.replace(/\.json$/, ""));
|
|
@@ -67612,8 +67741,23 @@ function waitSecondsOf({ args }) {
|
|
|
67612
67741
|
const timeout = Number(flagText({ args, name: "timeout", fallback: "0" }));
|
|
67613
67742
|
return timeout > 0 ? timeout : Infinity;
|
|
67614
67743
|
}
|
|
67744
|
+
async function refuseOtherSessionsInbox({
|
|
67745
|
+
context,
|
|
67746
|
+
args,
|
|
67747
|
+
name: name2
|
|
67748
|
+
}) {
|
|
67749
|
+
if (args.flags.take) return;
|
|
67750
|
+
const bound = Object.entries((await context.store.read()).sessions ?? {}).filter(([, profile]) => profile === name2).map(([key]) => key);
|
|
67751
|
+
if (bound.length === 0) return;
|
|
67752
|
+
const here = await currentSessionOf({ context, args });
|
|
67753
|
+
if (here && bound.includes(sessionKeyOf({ session: here }))) return;
|
|
67754
|
+
throw new CliUsageError(
|
|
67755
|
+
`${name2} is bound to the session ${bound.join(", ")}, and reading its inbox here would take those messages away from it. Read the channel with \`laze history <channel>\` instead, or pass --take to take them anyway.`
|
|
67756
|
+
);
|
|
67757
|
+
}
|
|
67615
67758
|
async function inbox({ context, args }) {
|
|
67616
67759
|
const { client, name: name2, profile } = await signedIn({ context, args });
|
|
67760
|
+
if (profile.kind === "agent") await refuseOtherSessionsInbox({ context, args, name: name2 });
|
|
67617
67761
|
const waitSeconds = waitSecondsOf({ args });
|
|
67618
67762
|
const messages = await receiveMessages({ context, client, waitSeconds });
|
|
67619
67763
|
if (profile.kind === "agent" && context.environment.harness === "claude-code") {
|
|
@@ -67697,238 +67841,13 @@ function channelLabelIn(channel) {
|
|
|
67697
67841
|
}
|
|
67698
67842
|
|
|
67699
67843
|
// src/services/claude-wait.service.ts
|
|
67700
|
-
import { readFile as
|
|
67701
|
-
import { dirname as
|
|
67702
|
-
|
|
67703
|
-
// src/services/rush-host.service.ts
|
|
67704
|
-
import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
|
|
67705
|
-
import { dirname as dirname5, join as join6 } from "node:path";
|
|
67706
|
-
async function rushAboveOf({
|
|
67707
|
-
context,
|
|
67708
|
-
from = context.processes.pid
|
|
67709
|
-
}) {
|
|
67710
|
-
let pid = await context.processes.parentOf(from);
|
|
67711
|
-
for (let depth = 0; pid !== void 0 && pid > 1 && depth < 16; depth += 1) {
|
|
67712
|
-
const rush = rushSessionOf({ parentArgs: await context.processes.argsOf(pid) });
|
|
67713
|
-
if (rush) return rush;
|
|
67714
|
-
pid = await context.processes.parentOf(pid);
|
|
67715
|
-
}
|
|
67716
|
-
return void 0;
|
|
67717
|
-
}
|
|
67718
|
-
function guardPathOf({ context, claudePid }) {
|
|
67719
|
-
return join6(dirname5(context.environment.configPath), "rush-guards", `${claudePid}.json`);
|
|
67720
|
-
}
|
|
67721
|
-
async function startRushGuard({
|
|
67722
|
-
context,
|
|
67723
|
-
profile,
|
|
67724
|
-
claudePid,
|
|
67725
|
-
rush
|
|
67726
|
-
}) {
|
|
67727
|
-
const path = guardPathOf({ context, claudePid });
|
|
67728
|
-
const holder = await guardHolderOf({ path });
|
|
67729
|
-
if (holder && context.processes.alive(holder.pid)) return;
|
|
67730
|
-
const flags2 = ["--profile", profile, "--claude-pid", String(claudePid), "--rush-id", rush.id];
|
|
67731
|
-
const argv = [...context.program, "hook", "rush-wake", ...flags2, "--rush-program", rush.program];
|
|
67732
|
-
const logPath = join6(dirname5(context.environment.configPath), "rush-guards", "guard.log");
|
|
67733
|
-
context.processes.spawnDetached({ argv: ["sh", "-c", '"$@" &', "sh", ...argv], logPath });
|
|
67734
|
-
}
|
|
67735
|
-
async function claimRushGuard({
|
|
67736
|
-
context,
|
|
67737
|
-
claudePid
|
|
67738
|
-
}) {
|
|
67739
|
-
const path = guardPathOf({ context, claudePid });
|
|
67740
|
-
const holder = await guardHolderOf({ path });
|
|
67741
|
-
const self2 = context.processes.pid;
|
|
67742
|
-
if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) return false;
|
|
67743
|
-
await mkdir5(dirname5(path), { recursive: true, mode: 448 });
|
|
67744
|
-
await writeFile5(path, JSON.stringify({ pid: self2, claudePid }), { mode: 384 });
|
|
67745
|
-
return true;
|
|
67746
|
-
}
|
|
67747
|
-
function guardHolderOf({ path }) {
|
|
67748
|
-
return readFile6(path, "utf8").then(
|
|
67749
|
-
(text2) => JSON.parse(text2),
|
|
67750
|
-
() => void 0
|
|
67751
|
-
);
|
|
67752
|
-
}
|
|
67753
|
-
|
|
67754
|
-
// src/services/claude-wait.service.ts
|
|
67755
|
-
var ROUND_SECONDS = 50;
|
|
67756
|
-
var WATCH_MS = 2e3;
|
|
67757
|
-
var CHANNEL_CHECK_MS = 5e3;
|
|
67758
|
-
async function holderOf({ path }) {
|
|
67759
|
-
return readFile7(path, "utf8").then(
|
|
67760
|
-
(text2) => JSON.parse(text2),
|
|
67761
|
-
() => void 0
|
|
67762
|
-
);
|
|
67763
|
-
}
|
|
67764
|
-
async function holderClaudeOf({ context, holder }) {
|
|
67765
|
-
if (holder.claudePid) return holder.claudePid;
|
|
67766
|
-
return (await nearestHarnessOf({ context, from: holder.pid }))?.pid;
|
|
67767
|
-
}
|
|
67768
|
-
async function takeLock({
|
|
67769
|
-
context,
|
|
67770
|
-
path,
|
|
67771
|
-
sessionId,
|
|
67772
|
-
claudePid,
|
|
67773
|
-
preempt = false
|
|
67774
|
-
}) {
|
|
67775
|
-
const holder = await holderOf({ path });
|
|
67776
|
-
const self2 = context.processes.pid;
|
|
67777
|
-
if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) {
|
|
67778
|
-
const served = await holderClaudeOf({ context, holder });
|
|
67779
|
-
const mine4 = preempt && served === claudePid && !holder.monitor;
|
|
67780
|
-
if (served && context.processes.alive(served) && !mine4) return false;
|
|
67781
|
-
context.processes.stop(holder.pid);
|
|
67782
|
-
}
|
|
67783
|
-
await mkdir6(dirname6(path), { recursive: true, mode: 448 });
|
|
67784
|
-
await writeFile6(
|
|
67785
|
-
path,
|
|
67786
|
-
JSON.stringify({
|
|
67787
|
-
pid: self2,
|
|
67788
|
-
claudePid,
|
|
67789
|
-
...sessionId ? { sessionId } : {},
|
|
67790
|
-
...preempt ? { monitor: true } : {}
|
|
67791
|
-
})
|
|
67792
|
-
);
|
|
67793
|
-
return true;
|
|
67794
|
-
}
|
|
67795
|
-
async function channelLive({ context, profile }) {
|
|
67796
|
-
const holder = await holderOf({ path: statePathOf({ context, kind: "channels", profile }) });
|
|
67797
|
-
return holder !== void 0 && context.processes.alive(holder.pid);
|
|
67798
|
-
}
|
|
67799
|
-
async function takeRound({
|
|
67800
|
-
context,
|
|
67801
|
-
client,
|
|
67802
|
-
claudePid,
|
|
67803
|
-
session
|
|
67804
|
-
}) {
|
|
67805
|
-
const controller = new AbortController();
|
|
67806
|
-
const { signal } = controller;
|
|
67807
|
-
const watch = (async () => {
|
|
67808
|
-
while (!signal.aborted) {
|
|
67809
|
-
await context.sleep(WATCH_MS, signal);
|
|
67810
|
-
if (claudePid && !context.processes.alive(claudePid)) controller.abort();
|
|
67811
|
-
}
|
|
67812
|
-
})();
|
|
67813
|
-
try {
|
|
67814
|
-
return await forSession({ client, session }).post(
|
|
67815
|
-
"/api/agents/me/inbox",
|
|
67816
|
-
{ waitSeconds: ROUND_SECONDS },
|
|
67817
|
-
{ signal }
|
|
67818
|
-
);
|
|
67819
|
-
} catch (error62) {
|
|
67820
|
-
if (signal.aborted) return [];
|
|
67821
|
-
throw error62;
|
|
67822
|
-
} finally {
|
|
67823
|
-
controller.abort();
|
|
67824
|
-
await watch;
|
|
67825
|
-
}
|
|
67826
|
-
}
|
|
67827
|
-
async function roundOf({ context, client, name: name2, lock, claudePid, session, seen }) {
|
|
67828
|
-
if ((await holderOf({ path: lock }))?.pid !== context.processes.pid) return void 0;
|
|
67829
|
-
if (claudePid && !context.processes.alive(claudePid)) return void 0;
|
|
67830
|
-
const due = await dueFromSpool({ context, profile: name2, seen, pushedToo: true });
|
|
67831
|
-
if (due.length > 0) return due;
|
|
67832
|
-
if (await channelLive({ context, profile: name2 })) {
|
|
67833
|
-
await context.sleep(CHANNEL_CHECK_MS);
|
|
67834
|
-
return [];
|
|
67835
|
-
}
|
|
67836
|
-
const taken = await takeRound({ context, client, claudePid, session });
|
|
67837
|
-
if (taken.length === 0) {
|
|
67838
|
-
await context.sleep(1e3);
|
|
67839
|
-
return [];
|
|
67840
|
-
}
|
|
67841
|
-
await keepTaken({ context, profile: name2, messages: taken });
|
|
67842
|
-
return taken;
|
|
67843
|
-
}
|
|
67844
|
-
async function claudePidOf({ context }) {
|
|
67845
|
-
const harness = await nearestHarnessOf({ context });
|
|
67846
|
-
if (harness?.harness === "claude-code") return harness.pid;
|
|
67847
|
-
return await context.processes.parentOf(context.processes.pid) ?? 0;
|
|
67848
|
-
}
|
|
67849
|
-
async function settleRound(round) {
|
|
67850
|
-
const { context, client, name: name2, session } = round;
|
|
67851
|
-
const messages = await roundOf(round).catch(async (error62) => {
|
|
67852
|
-
const refused = await notBoundNotice({
|
|
67853
|
-
context,
|
|
67854
|
-
client: forSession({ client, session }),
|
|
67855
|
-
session,
|
|
67856
|
-
error: error62,
|
|
67857
|
-
profile: name2
|
|
67858
|
-
});
|
|
67859
|
-
if (!refused) throw error62;
|
|
67860
|
-
return refused;
|
|
67861
|
-
});
|
|
67862
|
-
if (messages === void 0) return 0;
|
|
67863
|
-
if (!Array.isArray(messages)) {
|
|
67864
|
-
if (messages.rebound) return "again";
|
|
67865
|
-
if (!messages.notice) return 0;
|
|
67866
|
-
context.err(`${messages.notice}
|
|
67867
|
-
`);
|
|
67868
|
-
return 2;
|
|
67869
|
-
}
|
|
67870
|
-
if (messages.length === 0) return "again";
|
|
67871
|
-
await turnStarted({ context, client, agent: name2, messages }).catch(() => void 0);
|
|
67872
|
-
const self2 = await currentNameOf({ context, client, profile: name2 });
|
|
67873
|
-
context.err(`${hookContextOf({ messages, self: self2 })}
|
|
67874
|
-
`);
|
|
67875
|
-
const messageIds = messages.map((message2) => message2.messageId);
|
|
67876
|
-
await dropFromSpool({ context, profile: name2, messageIds });
|
|
67877
|
-
return 2;
|
|
67878
|
-
}
|
|
67879
|
-
async function waitForMessages({ context, args }) {
|
|
67880
|
-
const raw = await context.readStdin();
|
|
67881
|
-
const input2 = raw.trim() ? JSON.parse(raw) : {};
|
|
67882
|
-
const session = sessionOf({ context, harness: "claude-code", sessionId: input2.session_id });
|
|
67883
|
-
const claudePid = await claudePidOf({ context });
|
|
67884
|
-
const asked = await pluginHookArgs({ context, args, session, claudePid });
|
|
67885
|
-
if (!asked) return 0;
|
|
67886
|
-
const named = await sessionProfileArgs({ context, args: asked, session });
|
|
67887
|
-
const { client, name: name2 } = await signedIn({ context, args: named });
|
|
67888
|
-
await rememberSession({ context, claudePid, session });
|
|
67889
|
-
const rush = rushSessionOf({
|
|
67890
|
-
parentArgs: await context.processes.argsOf(await context.processes.parentOf(claudePid) ?? 0)
|
|
67891
|
-
});
|
|
67892
|
-
if (rush) await startRushGuard({ context, profile: name2, claudePid, rush });
|
|
67893
|
-
const lock = statePathOf({ context, kind: "waiters", profile: name2 });
|
|
67894
|
-
if (!await takeLock({ context, path: lock, sessionId: input2.session_id, claudePid })) return 0;
|
|
67895
|
-
const seen = () => input2.transcript_path ? readFile7(input2.transcript_path, "utf8") : Promise.resolve("");
|
|
67896
|
-
const deadline = context.nowMs() + (WAIT_HOOK_TIMEOUT_SECONDS - 60) * 1e3;
|
|
67897
|
-
try {
|
|
67898
|
-
while (context.nowMs() < deadline) {
|
|
67899
|
-
const code = await settleRound({ context, client, name: name2, lock, claudePid, session, seen });
|
|
67900
|
-
if (code !== "again") return code;
|
|
67901
|
-
}
|
|
67902
|
-
return 0;
|
|
67903
|
-
} finally {
|
|
67904
|
-
if ((await holderOf({ path: lock }))?.pid === context.processes.pid)
|
|
67905
|
-
await rm2(lock, { force: true });
|
|
67906
|
-
}
|
|
67907
|
-
}
|
|
67908
|
-
async function waitHook({ context, args }) {
|
|
67909
|
-
try {
|
|
67910
|
-
return await waitForMessages({ context, args });
|
|
67911
|
-
} catch (error62) {
|
|
67912
|
-
context.err(`laze: the background waiter stopped: ${String(error62)}
|
|
67913
|
-
`);
|
|
67914
|
-
return 0;
|
|
67915
|
-
}
|
|
67916
|
-
}
|
|
67917
|
-
async function monitorServes({
|
|
67918
|
-
context,
|
|
67919
|
-
profile,
|
|
67920
|
-
claudePid
|
|
67921
|
-
}) {
|
|
67922
|
-
const holder = await holderOf({ path: statePathOf({ context, kind: "waiters", profile }) });
|
|
67923
|
-
if (!holder?.monitor || !context.processes.alive(holder.pid)) return false;
|
|
67924
|
-
return await holderClaudeOf({ context, holder }) === claudePid;
|
|
67925
|
-
}
|
|
67844
|
+
import { readFile as readFile10, rm as rm4, writeFile as writeFile9, mkdir as mkdir9 } from "node:fs/promises";
|
|
67845
|
+
import { dirname as dirname10 } from "node:path";
|
|
67926
67846
|
|
|
67927
|
-
// src/services/
|
|
67928
|
-
import {
|
|
67929
|
-
import {
|
|
67930
|
-
import {
|
|
67931
|
-
import { createInterface as createInterface2 } from "node:readline";
|
|
67847
|
+
// src/services/connect-service.service.ts
|
|
67848
|
+
import { createHash } from "node:crypto";
|
|
67849
|
+
import { mkdir as mkdir8, rm as rm3, writeFile as writeFile8 } from "node:fs/promises";
|
|
67850
|
+
import { dirname as dirname9, join as join11 } from "node:path";
|
|
67932
67851
|
|
|
67933
67852
|
// src/rules/connect-service.rules.ts
|
|
67934
67853
|
function systemdWordOf(word3) {
|
|
@@ -67952,6 +67871,8 @@ function systemdUnitOf({
|
|
|
67952
67871
|
...environment,
|
|
67953
67872
|
"Restart=on-failure",
|
|
67954
67873
|
"RestartSec=5",
|
|
67874
|
+
// The rush guards it starts outlive a restart, such as the one after a CLI update.
|
|
67875
|
+
"KillMode=process",
|
|
67955
67876
|
"",
|
|
67956
67877
|
"[Install]",
|
|
67957
67878
|
"WantedBy=default.target",
|
|
@@ -67991,6 +67912,8 @@ function launchAgentOf({
|
|
|
67991
67912
|
" <true/>",
|
|
67992
67913
|
" <key>KeepAlive</key>",
|
|
67993
67914
|
" <true/>",
|
|
67915
|
+
" <key>AbandonProcessGroup</key>",
|
|
67916
|
+
" <true/>",
|
|
67994
67917
|
" <key>StandardOutPath</key>",
|
|
67995
67918
|
` <string>${xmlOf(logPath)}</string>`,
|
|
67996
67919
|
" <key>StandardErrorPath</key>",
|
|
@@ -68045,396 +67968,21 @@ function rolloutEventOf({
|
|
|
68045
67968
|
return held.length > 0 ? { kind: "holds", messageIds: held } : void 0;
|
|
68046
67969
|
}
|
|
68047
67970
|
|
|
68048
|
-
// src/services/codex-adopt.service.ts
|
|
68049
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
68050
|
-
import { mkdir as mkdir7, readdir as readdir2, readFile as readFile8, rm as rm3, stat, writeFile as writeFile7 } from "node:fs/promises";
|
|
68051
|
-
import { dirname as dirname7, join as join7 } from "node:path";
|
|
68052
|
-
import { createInterface } from "node:readline";
|
|
68053
|
-
|
|
68054
|
-
// src/rules/codex-requests.rules.ts
|
|
68055
|
-
var DECLINED_DECISION = {
|
|
68056
|
-
"item/commandExecution/requestApproval": "decline",
|
|
68057
|
-
"item/fileChange/requestApproval": "decline",
|
|
68058
|
-
execCommandApproval: "denied",
|
|
68059
|
-
applyPatchApproval: "denied"
|
|
68060
|
-
};
|
|
68061
|
-
function codexRequestReplyOf({ method }) {
|
|
68062
|
-
const decision = DECLINED_DECISION[method];
|
|
68063
|
-
if (decision) return { result: { decision } };
|
|
68064
|
-
if (method === "item/permissions/requestApproval") {
|
|
68065
|
-
return { result: { permissions: {}, scope: "turn" } };
|
|
68066
|
-
}
|
|
68067
|
-
if (method === "mcpServer/elicitation/request") {
|
|
68068
|
-
return { result: { action: "decline", content: null } };
|
|
68069
|
-
}
|
|
68070
|
-
return { error: { code: -32601, message: `${method} is not supported here` } };
|
|
68071
|
-
}
|
|
68072
|
-
|
|
68073
|
-
// src/services/codex-adopt.service.ts
|
|
68074
|
-
function record3(value) {
|
|
68075
|
-
return typeof value === "object" && value !== null ? value : {};
|
|
68076
|
-
}
|
|
68077
|
-
function absorbTurnEvent({ result, message: message2 }) {
|
|
68078
|
-
const params = record3(message2.params);
|
|
68079
|
-
if (message2.method === "item/completed") {
|
|
68080
|
-
const item = record3(params.item);
|
|
68081
|
-
if (item.type === "agentMessage" && typeof item.text === "string") result.answer = item.text;
|
|
68082
|
-
return;
|
|
68083
|
-
}
|
|
68084
|
-
if (message2.method !== "thread/tokenUsage/updated") return;
|
|
68085
|
-
const usage = record3(params.tokenUsage);
|
|
68086
|
-
const total = record3(usage.last).totalTokens;
|
|
68087
|
-
if (typeof total === "number") result.contextTokens = total;
|
|
68088
|
-
const window2 = usage.modelContextWindow;
|
|
68089
|
-
if (typeof window2 === "number" && window2 > 0) result.contextWindow = window2;
|
|
68090
|
-
}
|
|
68091
|
-
var TURN_HEARTBEAT_MS = 1e4;
|
|
68092
|
-
var CodexAppServer = class _CodexAppServer {
|
|
68093
|
-
constructor(child) {
|
|
68094
|
-
this.child = child;
|
|
68095
|
-
createInterface({ input: child.stdout }).on("line", (line) => this.receive(line));
|
|
68096
|
-
}
|
|
68097
|
-
child;
|
|
68098
|
-
#nextId = 0;
|
|
68099
|
-
#pending = /* @__PURE__ */ new Map();
|
|
68100
|
-
#listeners = /* @__PURE__ */ new Set();
|
|
68101
|
-
static start({
|
|
68102
|
-
codexHome,
|
|
68103
|
-
inherited
|
|
68104
|
-
}) {
|
|
68105
|
-
const env = { ...inherited, CODEX_HOME: codexHome };
|
|
68106
|
-
return new _CodexAppServer(spawn2("codex", ["app-server"], { env, stdio: "pipe" }));
|
|
68107
|
-
}
|
|
68108
|
-
async call(method, params) {
|
|
68109
|
-
const id = ++this.#nextId;
|
|
68110
|
-
const reply2 = await new Promise((resolve17) => {
|
|
68111
|
-
this.#pending.set(id, resolve17);
|
|
68112
|
-
this.write({ id, method, params });
|
|
68113
|
-
});
|
|
68114
|
-
if (reply2.error !== void 0) throw new Error(`${method}: ${JSON.stringify(reply2.error)}`);
|
|
68115
|
-
return record3(reply2.result);
|
|
68116
|
-
}
|
|
68117
|
-
notify(method) {
|
|
68118
|
-
this.write({ method });
|
|
68119
|
-
}
|
|
68120
|
-
/** Starts one turn; `done` settles when it completes, keeping its last agent message. */
|
|
68121
|
-
async startTurn({ threadId, text: text2 }) {
|
|
68122
|
-
const result = { answer: "" };
|
|
68123
|
-
const done = new Promise((resolve17) => {
|
|
68124
|
-
const listen = (message2) => {
|
|
68125
|
-
absorbTurnEvent({ result, message: message2 });
|
|
68126
|
-
if (message2.method !== "turn/completed") return;
|
|
68127
|
-
this.#listeners.delete(listen);
|
|
68128
|
-
resolve17(result);
|
|
68129
|
-
};
|
|
68130
|
-
this.#listeners.add(listen);
|
|
68131
|
-
});
|
|
68132
|
-
const started = await this.call("turn/start", {
|
|
68133
|
-
threadId,
|
|
68134
|
-
input: [{ type: "text", text: text2, text_elements: [] }]
|
|
68135
|
-
});
|
|
68136
|
-
const turnId = record3(started.turn).id;
|
|
68137
|
-
return { turnId: typeof turnId === "string" ? turnId : null, done };
|
|
68138
|
-
}
|
|
68139
|
-
stop() {
|
|
68140
|
-
this.child.kill("SIGTERM");
|
|
68141
|
-
}
|
|
68142
|
-
write(message2) {
|
|
68143
|
-
this.child.stdin.write(`${JSON.stringify(message2)}
|
|
68144
|
-
`);
|
|
68145
|
-
}
|
|
68146
|
-
receive(line) {
|
|
68147
|
-
let message2;
|
|
68148
|
-
try {
|
|
68149
|
-
message2 = record3(JSON.parse(line));
|
|
68150
|
-
} catch {
|
|
68151
|
-
return;
|
|
68152
|
-
}
|
|
68153
|
-
if (typeof message2.id === "number" && message2.method === void 0) {
|
|
68154
|
-
this.#pending.get(message2.id)?.(message2);
|
|
68155
|
-
this.#pending.delete(message2.id);
|
|
68156
|
-
return;
|
|
68157
|
-
}
|
|
68158
|
-
if (message2.method !== void 0 && message2.id !== void 0) {
|
|
68159
|
-
this.write({
|
|
68160
|
-
id: message2.id,
|
|
68161
|
-
...codexRequestReplyOf({
|
|
68162
|
-
method: typeof message2.method === "string" ? message2.method : ""
|
|
68163
|
-
})
|
|
68164
|
-
});
|
|
68165
|
-
return;
|
|
68166
|
-
}
|
|
68167
|
-
for (const listen of this.#listeners) listen(message2);
|
|
68168
|
-
}
|
|
68169
|
-
};
|
|
68170
|
-
async function newestThreadId({ codexHome }) {
|
|
68171
|
-
const root = join7(codexHome, "sessions");
|
|
68172
|
-
const files2 = await readdir2(root, { recursive: true }).catch(() => []);
|
|
68173
|
-
const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
|
|
68174
|
-
const dated = await Promise.all(
|
|
68175
|
-
rollouts.map(async (file3) => ({ file: file3, at: (await stat(join7(root, file3))).mtimeMs }))
|
|
68176
|
-
);
|
|
68177
|
-
const newest = dated.toSorted((a, b) => b.at - a.at)[0]?.file ?? "";
|
|
68178
|
-
const id = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/.exec(newest);
|
|
68179
|
-
if (!id?.[1]) throw new CliUsageError("No Codex session found: pass --thread <id>.");
|
|
68180
|
-
return id[1];
|
|
68181
|
-
}
|
|
68182
|
-
function promptOf({ message: message2, self: self2 }) {
|
|
68183
|
-
return [
|
|
68184
|
-
`A message reached you in the Laze workspace${selfClauseOf({ self: self2 })}. Answer it; your final`,
|
|
68185
|
-
"message is posted as your reply in its thread.",
|
|
68186
|
-
"",
|
|
68187
|
-
formatInboxMessage({ message: message2 }).split("\n").slice(0, -1).join("\n")
|
|
68188
|
-
].join("\n");
|
|
68189
|
-
}
|
|
68190
|
-
async function heartbeat({
|
|
68191
|
-
client,
|
|
68192
|
-
message: message2,
|
|
68193
|
-
state
|
|
68194
|
-
}) {
|
|
68195
|
-
return client.post("/api/agents/me/turn", {
|
|
68196
|
-
channelId: message2.channelId,
|
|
68197
|
-
threadRootId: message2.threadRootId,
|
|
68198
|
-
state,
|
|
68199
|
-
...state === "working" ? { messageId: message2.messageId } : {}
|
|
68200
|
-
}).catch(() => void 0);
|
|
68201
|
-
}
|
|
68202
|
-
async function watchTurn({
|
|
68203
|
-
context,
|
|
68204
|
-
client,
|
|
68205
|
-
codex,
|
|
68206
|
-
threadId,
|
|
68207
|
-
turn,
|
|
68208
|
-
message: message2
|
|
68209
|
-
}) {
|
|
68210
|
-
const finished = new AbortController();
|
|
68211
|
-
void turn.done.then(() => finished.abort());
|
|
68212
|
-
while (!finished.signal.aborted) {
|
|
68213
|
-
const beat2 = await heartbeat({ client, message: message2, state: "working" });
|
|
68214
|
-
if (beat2?.stop && turn.turnId) {
|
|
68215
|
-
await codex.call("turn/interrupt", { threadId, turnId: turn.turnId }).catch(() => void 0);
|
|
68216
|
-
return beat2.stoppedBy ?? "someone";
|
|
68217
|
-
}
|
|
68218
|
-
await context.sleep(TURN_HEARTBEAT_MS, finished.signal);
|
|
68219
|
-
}
|
|
68220
|
-
return void 0;
|
|
68221
|
-
}
|
|
68222
|
-
async function answer({
|
|
68223
|
-
context,
|
|
68224
|
-
codex,
|
|
68225
|
-
client,
|
|
68226
|
-
threadId,
|
|
68227
|
-
message: message2,
|
|
68228
|
-
profile
|
|
68229
|
-
}) {
|
|
68230
|
-
const self2 = await currentNameOf({ context, client, profile });
|
|
68231
|
-
const running = await codex.startTurn({ threadId, text: promptOf({ message: message2, self: self2 }) });
|
|
68232
|
-
const stoppedBy = await watchTurn({ context, client, codex, threadId, turn: running, message: message2 });
|
|
68233
|
-
const turn = await running.done;
|
|
68234
|
-
await heartbeat({ client, message: message2, state: "idle" });
|
|
68235
|
-
if (stoppedBy !== void 0) return `(stopped by ${stoppedBy})`;
|
|
68236
|
-
const body = turn.answer.trim() || "(no answer)";
|
|
68237
|
-
await client.post("/api/agents/me/replies", { messageId: message2.messageId, body });
|
|
68238
|
-
if (turn.contextTokens !== void 0) {
|
|
68239
|
-
await client.post("/api/agents/me/activity", {
|
|
68240
|
-
sessionId: threadId,
|
|
68241
|
-
contextTokens: turn.contextTokens,
|
|
68242
|
-
...turn.contextWindow ? { contextWindow: turn.contextWindow } : {}
|
|
68243
|
-
});
|
|
68244
|
-
}
|
|
68245
|
-
return body;
|
|
68246
|
-
}
|
|
68247
|
-
var MAX_RESTART_WAIT_SECONDS = 60;
|
|
68248
|
-
var HEALTHY_RUN_MS = 6e4;
|
|
68249
|
-
async function recordOf({ path }) {
|
|
68250
|
-
return readFile8(path, "utf8").then(
|
|
68251
|
-
(text2) => JSON.parse(text2),
|
|
68252
|
-
() => void 0
|
|
68253
|
-
);
|
|
68254
|
-
}
|
|
68255
|
-
function threadFlag({ thread: thread2 }) {
|
|
68256
|
-
return thread2 ? ["--thread", thread2] : [];
|
|
68257
|
-
}
|
|
68258
|
-
async function startAdoptInBackground({
|
|
68259
|
-
context,
|
|
68260
|
-
args,
|
|
68261
|
-
profile,
|
|
68262
|
-
laze
|
|
68263
|
-
}) {
|
|
68264
|
-
const thread2 = flagText({ args, name: "thread" }) || context.environment.inherited.CODEX_THREAD_ID || null;
|
|
68265
|
-
const path = statePathOf({ context, kind: "adopt", profile });
|
|
68266
|
-
const log = statePathOf({ context, kind: "adopt", profile, extension: "log" });
|
|
68267
|
-
const running = await recordOf({ path });
|
|
68268
|
-
if (running) context.processes.stop(running.pid);
|
|
68269
|
-
const adopt = ["adopt", "codex", "--profile", profile, ...threadFlag({ thread: thread2 })];
|
|
68270
|
-
const argv = [...context.program, ...adopt, "--supervise"];
|
|
68271
|
-
const pid = context.processes.spawnDetached({ argv, logPath: log });
|
|
68272
|
-
await mkdir7(dirname7(path), { recursive: true, mode: 448 });
|
|
68273
|
-
await writeFile7(path, JSON.stringify({ pid, thread: thread2, log, startedAt: context.nowMs() }));
|
|
68274
|
-
return [
|
|
68275
|
-
`Started \`${laze} adopt codex\` in the background (pid ${pid}). It answers each Laze message`,
|
|
68276
|
-
`as a turn in ${thread2 ? `this Codex thread (${thread2})` : "the newest Codex thread"}, and starts again if it stops.`,
|
|
68277
|
-
`Log: ${log}`,
|
|
68278
|
-
` ${laze} adopt codex --status --profile ${profile} shows whether it runs`,
|
|
68279
|
-
` ${laze} adopt codex --stop --profile ${profile} stops it`,
|
|
68280
|
-
"Nothing else needs to run. While this Codex window stays open, Codex lets only it write the",
|
|
68281
|
-
"thread, so adopt answers in a fork of it (the same history so far; `codex resume <fork id>`",
|
|
68282
|
-
"from the log opens it). Started again with this window closed, it answers in the thread itself."
|
|
68283
|
-
].join("\n");
|
|
68284
|
-
}
|
|
68285
|
-
async function supervise({
|
|
68286
|
-
context,
|
|
68287
|
-
args,
|
|
68288
|
-
profile
|
|
68289
|
-
}) {
|
|
68290
|
-
const path = statePathOf({ context, kind: "adopt", profile });
|
|
68291
|
-
const thread2 = flagText({ args, name: "thread" });
|
|
68292
|
-
const adopt = ["adopt", "codex", "--profile", profile, ...threadFlag({ thread: thread2 })];
|
|
68293
|
-
const command = [...context.program, ...adopt];
|
|
68294
|
-
let wait = 1;
|
|
68295
|
-
while ((await recordOf({ path }))?.pid === context.processes.pid) {
|
|
68296
|
-
const started = context.nowMs();
|
|
68297
|
-
context.out(
|
|
68298
|
-
`${Temporal3.Instant.fromEpochMilliseconds(started).toString()} starting laze adopt codex
|
|
68299
|
-
`
|
|
68300
|
-
);
|
|
68301
|
-
const code = await context.runCommand({ command, env: {} }).catch(() => 1);
|
|
68302
|
-
if (context.nowMs() - started > HEALTHY_RUN_MS) wait = 1;
|
|
68303
|
-
if ((await recordOf({ path }))?.pid !== context.processes.pid) break;
|
|
68304
|
-
context.out(`laze adopt codex exited ${code}; starting it again in ${wait}s
|
|
68305
|
-
`);
|
|
68306
|
-
await context.sleep(wait * 1e3);
|
|
68307
|
-
wait = Math.min(MAX_RESTART_WAIT_SECONDS, wait * 2);
|
|
68308
|
-
}
|
|
68309
|
-
return 0;
|
|
68310
|
-
}
|
|
68311
|
-
async function adoptStatus({ context, profile }) {
|
|
68312
|
-
const record4 = await recordOf({ path: statePathOf({ context, kind: "adopt", profile }) });
|
|
68313
|
-
if (!record4 || !context.processes.alive(record4.pid)) {
|
|
68314
|
-
context.out(`laze adopt codex does not run in the background for profile "${profile}".
|
|
68315
|
-
`);
|
|
68316
|
-
return;
|
|
68317
|
-
}
|
|
68318
|
-
const thread2 = record4.thread ?? "the newest thread";
|
|
68319
|
-
context.out(
|
|
68320
|
-
`laze adopt codex runs in the background for profile "${profile}" (pid ${record4.pid}), thread ${thread2}.
|
|
68321
|
-
Log: ${record4.log}
|
|
68322
|
-
`
|
|
68323
|
-
);
|
|
68324
|
-
}
|
|
68325
|
-
async function adoptStop({ context, profile }) {
|
|
68326
|
-
const path = statePathOf({ context, kind: "adopt", profile });
|
|
68327
|
-
const record4 = await recordOf({ path });
|
|
68328
|
-
await rm3(path, { force: true });
|
|
68329
|
-
if (!record4 || !context.processes.stop(record4.pid)) {
|
|
68330
|
-
context.out(`laze adopt codex was not running in the background for profile "${profile}".
|
|
68331
|
-
`);
|
|
68332
|
-
return;
|
|
68333
|
-
}
|
|
68334
|
-
context.out(`Stopped laze adopt codex (pid ${record4.pid}) for profile "${profile}".
|
|
68335
|
-
`);
|
|
68336
|
-
}
|
|
68337
|
-
var HELD_THREAD = /active writer/;
|
|
68338
|
-
async function adoptedThreadOf({
|
|
68339
|
-
context,
|
|
68340
|
-
codex,
|
|
68341
|
-
threadId,
|
|
68342
|
-
profile
|
|
68343
|
-
}) {
|
|
68344
|
-
const held = await codex.call("thread/resume", { threadId }).then(
|
|
68345
|
-
() => false,
|
|
68346
|
-
(error62) => {
|
|
68347
|
-
if (HELD_THREAD.test(String(error62))) return true;
|
|
68348
|
-
throw error62;
|
|
68349
|
-
}
|
|
68350
|
-
);
|
|
68351
|
-
if (!held) return threadId;
|
|
68352
|
-
const path = statePathOf({ context, kind: "adopt", profile, extension: "forks.json" });
|
|
68353
|
-
const forks = await readFile8(path, "utf8").then(
|
|
68354
|
-
(text2) => JSON.parse(text2),
|
|
68355
|
-
() => ({})
|
|
68356
|
-
);
|
|
68357
|
-
const known = forks[threadId];
|
|
68358
|
-
if (known && await codex.call("thread/resume", { threadId: known }).then(
|
|
68359
|
-
() => true,
|
|
68360
|
-
() => false
|
|
68361
|
-
)) {
|
|
68362
|
-
context.out(`Codex holds thread ${threadId} open elsewhere; answering in its fork ${known}.
|
|
68363
|
-
`);
|
|
68364
|
-
return known;
|
|
68365
|
-
}
|
|
68366
|
-
const forked = record3((await codex.call("thread/fork", { threadId })).thread).id;
|
|
68367
|
-
if (typeof forked !== "string") throw new Error("thread/fork answered no thread id");
|
|
68368
|
-
await mkdir7(dirname7(path), { recursive: true, mode: 448 });
|
|
68369
|
-
await writeFile7(path, JSON.stringify({ ...forks, [threadId]: forked }));
|
|
68370
|
-
context.out(
|
|
68371
|
-
`Codex holds thread ${threadId} open elsewhere; answering in its new fork ${forked}.
|
|
68372
|
-
`
|
|
68373
|
-
);
|
|
68374
|
-
return forked;
|
|
68375
|
-
}
|
|
68376
|
-
async function adoptCodex({ context, args }) {
|
|
68377
|
-
if (args.words[1] !== "codex") {
|
|
68378
|
-
throw new CliUsageError("Usage: laze adopt codex [--thread <id>] | --status | --stop");
|
|
68379
|
-
}
|
|
68380
|
-
const { client, name: name2 } = await signedIn({ context, args });
|
|
68381
|
-
if (args.flags.status) return adoptStatus({ context, profile: name2 });
|
|
68382
|
-
if (args.flags.stop) return adoptStop({ context, profile: name2 });
|
|
68383
|
-
if (args.flags.supervise) return supervise({ context, args, profile: name2 });
|
|
68384
|
-
const { codexHome } = context.environment;
|
|
68385
|
-
const threadId = flagText({ args, name: "thread" }) || context.environment.inherited.CODEX_THREAD_ID || await newestThreadId({ codexHome });
|
|
68386
|
-
const once = Boolean(args.flags.once);
|
|
68387
|
-
const codex = CodexAppServer.start({ codexHome, inherited: context.environment.inherited });
|
|
68388
|
-
try {
|
|
68389
|
-
await codex.call("initialize", {
|
|
68390
|
-
clientInfo: { name: "laze", title: "Laze", version: "1" },
|
|
68391
|
-
capabilities: null
|
|
68392
|
-
});
|
|
68393
|
-
codex.notify("initialized");
|
|
68394
|
-
const adopted = await adoptedThreadOf({ context, codex, threadId, profile: name2 });
|
|
68395
|
-
context.out(`Adopted Codex thread ${adopted}; answering Laze messages.
|
|
68396
|
-
`);
|
|
68397
|
-
const timeout = Number(flagText({ args, name: "timeout", fallback: "0" }));
|
|
68398
|
-
do {
|
|
68399
|
-
const messages = await receiveMessages({
|
|
68400
|
-
context,
|
|
68401
|
-
client,
|
|
68402
|
-
waitSeconds: timeout > 0 ? timeout : Infinity
|
|
68403
|
-
});
|
|
68404
|
-
for (const message2 of messages) {
|
|
68405
|
-
const body = await answer({
|
|
68406
|
-
context,
|
|
68407
|
-
codex,
|
|
68408
|
-
client,
|
|
68409
|
-
threadId: adopted,
|
|
68410
|
-
message: message2,
|
|
68411
|
-
profile: name2
|
|
68412
|
-
});
|
|
68413
|
-
context.out(`Answered ${message2.messageId}: ${body.slice(0, 120)}
|
|
68414
|
-
`);
|
|
68415
|
-
}
|
|
68416
|
-
if (messages.length === 0 && timeout > 0) break;
|
|
68417
|
-
} while (!once);
|
|
68418
|
-
} finally {
|
|
68419
|
-
codex.stop();
|
|
68420
|
-
}
|
|
68421
|
-
}
|
|
68422
|
-
|
|
68423
67971
|
// src/services/connect-delivery.service.ts
|
|
68424
|
-
import { mkdir as
|
|
67972
|
+
import { mkdir as mkdir7, readFile as readFile9, rename as rename3, rm as rm2, stat as stat2, writeFile as writeFile7 } from "node:fs/promises";
|
|
68425
67973
|
import { homedir as homedir2, hostname as hostname4 } from "node:os";
|
|
68426
|
-
import { dirname as
|
|
67974
|
+
import { dirname as dirname8, join as join10 } from "node:path";
|
|
68427
67975
|
|
|
68428
67976
|
// src/services/codex-turn-watch.service.ts
|
|
68429
|
-
import { open as open2, readdir as
|
|
68430
|
-
import { join as
|
|
67977
|
+
import { open as open2, readdir as readdir2 } from "node:fs/promises";
|
|
67978
|
+
import { join as join6 } from "node:path";
|
|
68431
67979
|
var READ_MS = 1500;
|
|
68432
67980
|
var KEEP_WORKING_MS = 3e4;
|
|
68433
67981
|
async function rolloutPathOf({ delivery }) {
|
|
68434
|
-
const root =
|
|
68435
|
-
const files2 = await
|
|
67982
|
+
const root = join6(delivery.codexHome, "sessions");
|
|
67983
|
+
const files2 = await readdir2(root, { recursive: true }).catch(() => []);
|
|
68436
67984
|
const file3 = files2.find((name2) => name2.endsWith(`-${delivery.threadId}.jsonl`));
|
|
68437
|
-
return file3 ?
|
|
67985
|
+
return file3 ? join6(root, file3) : void 0;
|
|
68438
67986
|
}
|
|
68439
67987
|
async function readFrom({ path, offset }) {
|
|
68440
67988
|
const handle = await open2(path, "r");
|
|
@@ -68520,8 +68068,8 @@ var CodexTurnWatch = class _CodexTurnWatch {
|
|
|
68520
68068
|
};
|
|
68521
68069
|
|
|
68522
68070
|
// src/services/openclaw-relay.service.ts
|
|
68523
|
-
import { chmod as chmod2, mkdir as
|
|
68524
|
-
import { dirname as
|
|
68071
|
+
import { chmod as chmod2, mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
|
|
68072
|
+
import { dirname as dirname5, join as join7 } from "node:path";
|
|
68525
68073
|
|
|
68526
68074
|
// ../../modules/openclaw/contract/src/openclaw.ts
|
|
68527
68075
|
var workspaceIdSchema14 = external_exports.string().min(1);
|
|
@@ -68749,11 +68297,11 @@ var STOPS = /* @__PURE__ */ new Map([
|
|
|
68749
68297
|
[OPENCLAW_RELAY_CLOSE.replaced.code, "another relay for this gateway took over"]
|
|
68750
68298
|
]);
|
|
68751
68299
|
function relaysPathOf({ context }) {
|
|
68752
|
-
return
|
|
68300
|
+
return join7(dirname5(context.environment.configPath), "connect", "openclaw-relays.json");
|
|
68753
68301
|
}
|
|
68754
68302
|
async function readRelays({ context }) {
|
|
68755
68303
|
try {
|
|
68756
|
-
return JSON.parse(await
|
|
68304
|
+
return JSON.parse(await readFile6(relaysPathOf({ context }), "utf8"));
|
|
68757
68305
|
} catch {
|
|
68758
68306
|
return {};
|
|
68759
68307
|
}
|
|
@@ -68763,8 +68311,8 @@ async function saveRelays({
|
|
|
68763
68311
|
relays
|
|
68764
68312
|
}) {
|
|
68765
68313
|
const path = relaysPathOf({ context });
|
|
68766
|
-
await
|
|
68767
|
-
await
|
|
68314
|
+
await mkdir5(dirname5(path), { recursive: true, mode: 448 });
|
|
68315
|
+
await writeFile5(path, `${JSON.stringify(relays, null, 2)}
|
|
68768
68316
|
`, { mode: 384 });
|
|
68769
68317
|
await chmod2(path, 384);
|
|
68770
68318
|
}
|
|
@@ -68948,16 +68496,148 @@ var RelayLoops = class _RelayLoops {
|
|
|
68948
68496
|
}
|
|
68949
68497
|
};
|
|
68950
68498
|
|
|
68499
|
+
// src/services/rush-listeners.service.ts
|
|
68500
|
+
import { readFile as readFile8, readdir as readdir3, stat } from "node:fs/promises";
|
|
68501
|
+
import { dirname as dirname7, join as join9 } from "node:path";
|
|
68502
|
+
|
|
68503
|
+
// src/services/rush-host.service.ts
|
|
68504
|
+
import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
68505
|
+
import { dirname as dirname6, join as join8 } from "node:path";
|
|
68506
|
+
async function rushAboveOf({
|
|
68507
|
+
context,
|
|
68508
|
+
from = context.processes.pid
|
|
68509
|
+
}) {
|
|
68510
|
+
let pid = await context.processes.parentOf(from);
|
|
68511
|
+
for (let depth = 0; pid !== void 0 && pid > 1 && depth < 16; depth += 1) {
|
|
68512
|
+
const rush = rushSessionOf({ parentArgs: await context.processes.argsOf(pid) });
|
|
68513
|
+
if (rush) return rush;
|
|
68514
|
+
pid = await context.processes.parentOf(pid);
|
|
68515
|
+
}
|
|
68516
|
+
return void 0;
|
|
68517
|
+
}
|
|
68518
|
+
function guardPathOf({ context, claudePid }) {
|
|
68519
|
+
return join8(dirname6(context.environment.configPath), "rush-guards", `${claudePid}.json`);
|
|
68520
|
+
}
|
|
68521
|
+
async function startRushGuard({
|
|
68522
|
+
context,
|
|
68523
|
+
profile,
|
|
68524
|
+
claudePid,
|
|
68525
|
+
rush
|
|
68526
|
+
}) {
|
|
68527
|
+
const path = guardPathOf({ context, claudePid });
|
|
68528
|
+
const holder = await guardHolderOf({ path });
|
|
68529
|
+
if (holder && context.processes.alive(holder.pid)) return;
|
|
68530
|
+
const flags2 = ["--profile", profile, "--claude-pid", String(claudePid), "--rush-id", rush.id];
|
|
68531
|
+
const argv = [...context.program, "hook", "rush-wake", ...flags2, "--rush-program", rush.program];
|
|
68532
|
+
const logPath = join8(dirname6(context.environment.configPath), "rush-guards", "guard.log");
|
|
68533
|
+
context.processes.spawnDetached({ argv: ["sh", "-c", '"$@" &', "sh", ...argv], logPath });
|
|
68534
|
+
}
|
|
68535
|
+
async function claimRushGuard({
|
|
68536
|
+
context,
|
|
68537
|
+
claudePid
|
|
68538
|
+
}) {
|
|
68539
|
+
const path = guardPathOf({ context, claudePid });
|
|
68540
|
+
const holder = await guardHolderOf({ path });
|
|
68541
|
+
const self2 = context.processes.pid;
|
|
68542
|
+
if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) return false;
|
|
68543
|
+
await mkdir6(dirname6(path), { recursive: true, mode: 448 });
|
|
68544
|
+
await writeFile6(path, JSON.stringify({ pid: self2, claudePid }), { mode: 384 });
|
|
68545
|
+
return true;
|
|
68546
|
+
}
|
|
68547
|
+
function guardHolderOf({ path }) {
|
|
68548
|
+
return readFile7(path, "utf8").then(
|
|
68549
|
+
(text2) => JSON.parse(text2),
|
|
68550
|
+
() => void 0
|
|
68551
|
+
);
|
|
68552
|
+
}
|
|
68553
|
+
|
|
68554
|
+
// src/services/rush-listeners.service.ts
|
|
68555
|
+
async function jsonOf(path) {
|
|
68556
|
+
return readFile8(path, "utf8").then(
|
|
68557
|
+
(text2) => JSON.parse(text2),
|
|
68558
|
+
() => void 0
|
|
68559
|
+
);
|
|
68560
|
+
}
|
|
68561
|
+
async function notesOf({ context }) {
|
|
68562
|
+
const folder = dirname7(statePathOf({ context, kind: "sessions", profile: "x" }));
|
|
68563
|
+
const files2 = await readdir3(folder).catch(() => []);
|
|
68564
|
+
const notes = await Promise.all(
|
|
68565
|
+
files2.map(async (file3) => {
|
|
68566
|
+
const pid = Number(file3.replace(/\.json$/, ""));
|
|
68567
|
+
const session = await jsonOf(join9(folder, file3));
|
|
68568
|
+
const at = await stat(join9(folder, file3)).then(
|
|
68569
|
+
(info) => info.mtimeMs,
|
|
68570
|
+
() => 0
|
|
68571
|
+
);
|
|
68572
|
+
return pid && session ? [{ pid, key: sessionKeyOf({ session }), at }] : [];
|
|
68573
|
+
})
|
|
68574
|
+
);
|
|
68575
|
+
return notes.flat().toSorted((a, b) => b.at - a.at);
|
|
68576
|
+
}
|
|
68577
|
+
async function rushListenersOf({
|
|
68578
|
+
context
|
|
68579
|
+
}) {
|
|
68580
|
+
const bound = Object.entries((await context.store.read()).sessions ?? {}).filter(
|
|
68581
|
+
([key]) => key.startsWith("claude-code:")
|
|
68582
|
+
);
|
|
68583
|
+
if (bound.length === 0) return [];
|
|
68584
|
+
const listed = await rushListingOf({ context });
|
|
68585
|
+
if (listed === void 0) return [];
|
|
68586
|
+
const sessions = rushListedOf({ listed });
|
|
68587
|
+
const notes = await notesOf({ context });
|
|
68588
|
+
const rows = [];
|
|
68589
|
+
for (const [key, profile] of bound) {
|
|
68590
|
+
const one = sessions.find((each) => `claude-code:${each.sessionId}` === key);
|
|
68591
|
+
if (!one?.id) continue;
|
|
68592
|
+
const pids = notes.filter((note) => note.key === key).map((note) => note.pid);
|
|
68593
|
+
const listenerPid = await listenerOf({ context, key, profile, pids });
|
|
68594
|
+
const lastClaudePid = pids.find((pid) => !context.processes.alive(pid));
|
|
68595
|
+
rows.push({
|
|
68596
|
+
profile,
|
|
68597
|
+
rushId: one.id,
|
|
68598
|
+
standing: rushStandingOf({ one }),
|
|
68599
|
+
...listenerPid ? { listenerPid } : {},
|
|
68600
|
+
...lastClaudePid ? { lastClaudePid } : {}
|
|
68601
|
+
});
|
|
68602
|
+
}
|
|
68603
|
+
return rows;
|
|
68604
|
+
}
|
|
68605
|
+
async function listenerOf({
|
|
68606
|
+
context,
|
|
68607
|
+
key,
|
|
68608
|
+
profile,
|
|
68609
|
+
pids
|
|
68610
|
+
}) {
|
|
68611
|
+
for (const claudePid of pids) {
|
|
68612
|
+
const guard = await jsonOf(guardPathOf({ context, claudePid }));
|
|
68613
|
+
if (guard && context.processes.alive(guard.pid)) return guard.pid;
|
|
68614
|
+
}
|
|
68615
|
+
const lock = statePathOf({ context, kind: "waiters", profile });
|
|
68616
|
+
const waiter = await jsonOf(lock);
|
|
68617
|
+
const mine4 = waiter?.sessionId === key.slice(key.indexOf(":") + 1);
|
|
68618
|
+
return waiter && mine4 && context.processes.alive(waiter.pid) ? waiter.pid : void 0;
|
|
68619
|
+
}
|
|
68620
|
+
async function rearmRushGuards({ context }) {
|
|
68621
|
+
let started = 0;
|
|
68622
|
+
for (const row of await rushListenersOf({ context })) {
|
|
68623
|
+
if (row.standing !== "asleep" || row.listenerPid || !row.lastClaudePid) continue;
|
|
68624
|
+
const rush = { id: row.rushId, program: "rush" };
|
|
68625
|
+
await startRushGuard({ context, profile: row.profile, claudePid: row.lastClaudePid, rush });
|
|
68626
|
+
started += 1;
|
|
68627
|
+
}
|
|
68628
|
+
return started;
|
|
68629
|
+
}
|
|
68630
|
+
|
|
68951
68631
|
// src/services/connect-delivery.service.ts
|
|
68952
68632
|
function connectFolderOf({ context }) {
|
|
68953
|
-
return join10(
|
|
68633
|
+
return join10(dirname8(context.environment.configPath), "connect");
|
|
68954
68634
|
}
|
|
68955
68635
|
function runStatePathOf({ context }) {
|
|
68956
68636
|
return join10(connectFolderOf({ context }), "run.json");
|
|
68957
68637
|
}
|
|
68958
68638
|
async function readJson({ path }) {
|
|
68959
68639
|
try {
|
|
68960
|
-
return JSON.parse(await
|
|
68640
|
+
return JSON.parse(await readFile9(path, "utf8"));
|
|
68961
68641
|
} catch {
|
|
68962
68642
|
return void 0;
|
|
68963
68643
|
}
|
|
@@ -68965,9 +68645,18 @@ async function readJson({ path }) {
|
|
|
68965
68645
|
async function runStateOf({ context }) {
|
|
68966
68646
|
return readJson({ path: runStatePathOf({ context }) });
|
|
68967
68647
|
}
|
|
68968
|
-
var
|
|
68648
|
+
var ROUND_SECONDS = 50;
|
|
68969
68649
|
var REFRESH_MS = 3e4;
|
|
68970
68650
|
var MAX_RETRY_SECONDS2 = 60;
|
|
68651
|
+
var CLI_CHANGED_EXIT = 75;
|
|
68652
|
+
async function cliStampOf({ context }) {
|
|
68653
|
+
const file3 = context.program.at(-1);
|
|
68654
|
+
if (!file3) return "";
|
|
68655
|
+
return stat2(file3).then(
|
|
68656
|
+
(info) => `${info.mtimeMs}:${info.size}`,
|
|
68657
|
+
() => ""
|
|
68658
|
+
);
|
|
68659
|
+
}
|
|
68971
68660
|
var CodexQueueError = class extends Error {
|
|
68972
68661
|
constructor(reason, detail) {
|
|
68973
68662
|
super(detail);
|
|
@@ -68998,7 +68687,7 @@ async function queueInCodex({
|
|
|
68998
68687
|
throw new CodexQueueError(codexQueueFailureOf({ stderr: stderr2 }), stderr2.trim() || `exit ${code}`);
|
|
68999
68688
|
}
|
|
69000
68689
|
}
|
|
69001
|
-
async function
|
|
68690
|
+
async function takeRound({
|
|
69002
68691
|
client,
|
|
69003
68692
|
signal,
|
|
69004
68693
|
delivery
|
|
@@ -69010,7 +68699,7 @@ async function takeRound2({
|
|
|
69010
68699
|
host: hostname4()
|
|
69011
68700
|
};
|
|
69012
68701
|
try {
|
|
69013
|
-
return await client.withHeaders(sessionHeadersOf({ session })).post("/api/agents/me/inbox", { waitSeconds:
|
|
68702
|
+
return await client.withHeaders(sessionHeadersOf({ session })).post("/api/agents/me/inbox", { waitSeconds: ROUND_SECONDS }, { signal });
|
|
69014
68703
|
} catch (error62) {
|
|
69015
68704
|
if (signal.aborted) return [];
|
|
69016
68705
|
throw error62;
|
|
@@ -69025,7 +68714,7 @@ async function deliverRound({
|
|
|
69025
68714
|
watch
|
|
69026
68715
|
}) {
|
|
69027
68716
|
const kept = await dueFromSpool({ context, profile, seen: async () => "", pushedToo: true });
|
|
69028
|
-
const messages = kept.length > 0 ? kept : await
|
|
68717
|
+
const messages = kept.length > 0 ? kept : await takeRound({ client, signal, delivery });
|
|
69029
68718
|
if (messages.length === 0) return 0;
|
|
69030
68719
|
if (kept.length === 0) await keepTaken({ context, profile, messages });
|
|
69031
68720
|
const self2 = await currentNameOf({ context, client, profile });
|
|
@@ -69108,9 +68797,9 @@ async function serveRounds({
|
|
|
69108
68797
|
}
|
|
69109
68798
|
var saves = 0;
|
|
69110
68799
|
async function save(run4) {
|
|
69111
|
-
await
|
|
68800
|
+
await mkdir7(dirname8(run4.path), { recursive: true, mode: 448 });
|
|
69112
68801
|
const temporary = `${run4.path}.${run4.self}.${saves += 1}.tmp`;
|
|
69113
|
-
await
|
|
68802
|
+
await writeFile7(temporary, JSON.stringify(run4.state));
|
|
69114
68803
|
await rename3(temporary, run4.path);
|
|
69115
68804
|
}
|
|
69116
68805
|
async function holdsLock(run4) {
|
|
@@ -69165,6 +68854,7 @@ async function runConnectLoop({ context }) {
|
|
|
69165
68854
|
await save(run4);
|
|
69166
68855
|
context.out(`laze connect run: pid ${self2}
|
|
69167
68856
|
`);
|
|
68857
|
+
const startedFrom = await cliStampOf({ context });
|
|
69168
68858
|
const relays = RelayLoops.create({
|
|
69169
68859
|
context,
|
|
69170
68860
|
report: async (connectionId, relay2) => {
|
|
@@ -69177,26 +68867,31 @@ async function runConnectLoop({ context }) {
|
|
|
69177
68867
|
while (await holdsLock(run4)) {
|
|
69178
68868
|
await syncLoops(run4);
|
|
69179
68869
|
await relays.sync();
|
|
68870
|
+
await rearmRushGuards({ context }).catch((error62) => {
|
|
68871
|
+
context.err(`laze connect: no rush guard check this round: ${String(error62)}
|
|
68872
|
+
`);
|
|
68873
|
+
});
|
|
69180
68874
|
await save(run4);
|
|
69181
68875
|
await context.sleep(REFRESH_MS);
|
|
68876
|
+
if (await cliStampOf({ context }) !== startedFrom) {
|
|
68877
|
+
context.out("laze connect run: the CLI changed on disk, exiting so the new one starts\n");
|
|
68878
|
+
return CLI_CHANGED_EXIT;
|
|
68879
|
+
}
|
|
69182
68880
|
}
|
|
69183
68881
|
} finally {
|
|
69184
68882
|
await relays.stopAll();
|
|
69185
68883
|
for (const current2 of run4.served.values()) current2.stop.abort();
|
|
69186
68884
|
await Promise.all([...run4.served.values()].map((current2) => current2.done));
|
|
69187
|
-
if (await holdsLock(run4)) await
|
|
68885
|
+
if (await holdsLock(run4)) await rm2(run4.path, { force: true });
|
|
69188
68886
|
}
|
|
69189
68887
|
return 0;
|
|
69190
68888
|
}
|
|
69191
68889
|
|
|
69192
68890
|
// src/services/connect-service.service.ts
|
|
69193
|
-
|
|
69194
|
-
import { mkdir as mkdir10, rm as rm5, writeFile as writeFile10 } from "node:fs/promises";
|
|
69195
|
-
import { dirname as dirname10, join as join11 } from "node:path";
|
|
69196
|
-
var CONNECT_SERVICE_USAGE = `laze connect install|status|stop|uninstall|run: the service that delivers to linked Codex sessions.
|
|
68891
|
+
var CONNECT_SERVICE_USAGE = `laze connect install|status|stop|uninstall|run: the service that delivers to linked Codex sessions and keeps a guard on every Claude Code session rush put to sleep.
|
|
69197
68892
|
|
|
69198
68893
|
laze connect install install and start it (systemd --user, a LaunchAgent, or detached)
|
|
69199
|
-
laze connect status whether it runs
|
|
68894
|
+
laze connect status whether it runs, which agents it serves, who listens per rush session
|
|
69200
68895
|
laze connect stop stop it until the next login or install
|
|
69201
68896
|
laze connect uninstall stop it and remove it
|
|
69202
68897
|
laze connect run the service itself, in the foreground
|
|
@@ -69211,7 +68906,7 @@ function logPathOf({ context }) {
|
|
|
69211
68906
|
return join11(connectFolderOf({ context }), "connect.log");
|
|
69212
68907
|
}
|
|
69213
68908
|
function homeOf({ context }) {
|
|
69214
|
-
return context.environment.inherited.HOME ??
|
|
68909
|
+
return context.environment.inherited.HOME ?? dirname9(dirname9(context.environment.configPath));
|
|
69215
68910
|
}
|
|
69216
68911
|
function serviceNameOf({ context }) {
|
|
69217
68912
|
const { configPath } = context.environment;
|
|
@@ -69240,8 +68935,8 @@ async function installSystemd({ context }) {
|
|
|
69240
68935
|
const env = context.environment.inherited;
|
|
69241
68936
|
const base = env.XDG_CONFIG_HOME || join11(homeOf({ context }), ".config");
|
|
69242
68937
|
const file3 = join11(base, "systemd", "user", `${name2}.service`);
|
|
69243
|
-
await
|
|
69244
|
-
await
|
|
68938
|
+
await mkdir8(dirname9(file3), { recursive: true });
|
|
68939
|
+
await writeFile8(
|
|
69245
68940
|
file3,
|
|
69246
68941
|
systemdUnitOf({ argv: runArgvOf({ context }), env: serviceEnvOf({ context }) })
|
|
69247
68942
|
);
|
|
@@ -69256,8 +68951,8 @@ async function installLaunchd({ context }) {
|
|
|
69256
68951
|
const label2 = `ai.laze.${name2}`;
|
|
69257
68952
|
const file3 = join11(homeOf({ context }), "Library", "LaunchAgents", `${label2}.plist`);
|
|
69258
68953
|
const log = logPathOf({ context });
|
|
69259
|
-
await
|
|
69260
|
-
await
|
|
68954
|
+
await mkdir8(dirname9(file3), { recursive: true });
|
|
68955
|
+
await writeFile8(
|
|
69261
68956
|
file3,
|
|
69262
68957
|
launchAgentOf({
|
|
69263
68958
|
label: label2,
|
|
@@ -69309,10 +69004,16 @@ async function installConnectService({ context }) {
|
|
|
69309
69004
|
const manager = await managerOf({ context });
|
|
69310
69005
|
const install = { systemd: installSystemd, launchd: installLaunchd, detached: installDetached };
|
|
69311
69006
|
const installed = await install[manager]({ context });
|
|
69312
|
-
await
|
|
69313
|
-
await
|
|
69007
|
+
await mkdir8(dirname9(path), { recursive: true, mode: 448 });
|
|
69008
|
+
await writeFile8(path, JSON.stringify(installed));
|
|
69314
69009
|
return describeInstalled({ installed });
|
|
69315
69010
|
}
|
|
69011
|
+
async function ensureConnectService({ context }) {
|
|
69012
|
+
const running = await runStateOf({ context });
|
|
69013
|
+
if (running && context.processes.alive(running.pid)) return false;
|
|
69014
|
+
await installConnectService({ context });
|
|
69015
|
+
return true;
|
|
69016
|
+
}
|
|
69316
69017
|
function describeInstalled({ installed }) {
|
|
69317
69018
|
switch (installed.manager) {
|
|
69318
69019
|
case "systemd":
|
|
@@ -69340,6 +69041,8 @@ async function status({ context }) {
|
|
|
69340
69041
|
`
|
|
69341
69042
|
);
|
|
69342
69043
|
}
|
|
69044
|
+
for (const row of await rushListenersOf({ context })) context.out(`${rushLineOf({ row })}
|
|
69045
|
+
`);
|
|
69343
69046
|
const config2 = await context.store.read();
|
|
69344
69047
|
const linked = Object.entries(config2.profiles).filter(([, profile]) => profile.delivery);
|
|
69345
69048
|
if (linked.length === 0) {
|
|
@@ -69352,6 +69055,13 @@ async function status({ context }) {
|
|
|
69352
69055
|
`);
|
|
69353
69056
|
}
|
|
69354
69057
|
}
|
|
69058
|
+
function rushLineOf({ row }) {
|
|
69059
|
+
const head = `${row.profile} Claude Code in rush ${row.rushId} ${row.standing}`;
|
|
69060
|
+
if (row.standing === "awake") return `${head}, its Claude Code delivers`;
|
|
69061
|
+
if (row.standing === "stopped") return `${head}, gets messages when rush starts it again`;
|
|
69062
|
+
if (row.listenerPid) return `${head}, guard pid ${row.listenerPid}`;
|
|
69063
|
+
return `${head}, NO LISTENER: messages wait in Laze; \`laze connect install\` brings a guard back`;
|
|
69064
|
+
}
|
|
69355
69065
|
async function stop({ context }) {
|
|
69356
69066
|
const installed = await readJson({ path: installedPathOf({ context }) });
|
|
69357
69067
|
if (!installed) {
|
|
@@ -69376,11 +69086,11 @@ async function uninstall({ context }) {
|
|
|
69376
69086
|
command: ["systemctl", "--user", "disable", `${installed.name}.service`]
|
|
69377
69087
|
});
|
|
69378
69088
|
}
|
|
69379
|
-
if (installed.file) await
|
|
69089
|
+
if (installed.file) await rm3(installed.file, { force: true });
|
|
69380
69090
|
if (installed.manager === "systemd") {
|
|
69381
69091
|
await run({ context, command: ["systemctl", "--user", "daemon-reload"] });
|
|
69382
69092
|
}
|
|
69383
|
-
await
|
|
69093
|
+
await rm3(path, { force: true });
|
|
69384
69094
|
context.out(
|
|
69385
69095
|
`Removed the connect service (${installed.manager}, ${installed.name}). Linked Codex agents get no messages until \`laze connect install\`.
|
|
69386
69096
|
`
|
|
@@ -69405,6 +69115,571 @@ async function connectService({ context, args }) {
|
|
|
69405
69115
|
}
|
|
69406
69116
|
}
|
|
69407
69117
|
|
|
69118
|
+
// src/services/claude-wait.service.ts
|
|
69119
|
+
var ROUND_SECONDS2 = 50;
|
|
69120
|
+
var WATCH_MS = 2e3;
|
|
69121
|
+
var CHANNEL_CHECK_MS = 5e3;
|
|
69122
|
+
async function holderOf({ path }) {
|
|
69123
|
+
return readFile10(path, "utf8").then(
|
|
69124
|
+
(text2) => JSON.parse(text2),
|
|
69125
|
+
() => void 0
|
|
69126
|
+
);
|
|
69127
|
+
}
|
|
69128
|
+
async function holderClaudeOf({ context, holder }) {
|
|
69129
|
+
if (holder.claudePid) return holder.claudePid;
|
|
69130
|
+
return (await nearestHarnessOf({ context, from: holder.pid }))?.pid;
|
|
69131
|
+
}
|
|
69132
|
+
async function takeLock({
|
|
69133
|
+
context,
|
|
69134
|
+
path,
|
|
69135
|
+
sessionId,
|
|
69136
|
+
claudePid,
|
|
69137
|
+
preempt = false
|
|
69138
|
+
}) {
|
|
69139
|
+
const holder = await holderOf({ path });
|
|
69140
|
+
const self2 = context.processes.pid;
|
|
69141
|
+
if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) {
|
|
69142
|
+
const served = await holderClaudeOf({ context, holder });
|
|
69143
|
+
const mine4 = preempt && served === claudePid && !holder.monitor;
|
|
69144
|
+
if (served && context.processes.alive(served) && !mine4) return false;
|
|
69145
|
+
context.processes.stop(holder.pid);
|
|
69146
|
+
}
|
|
69147
|
+
await mkdir9(dirname10(path), { recursive: true, mode: 448 });
|
|
69148
|
+
await writeFile9(
|
|
69149
|
+
path,
|
|
69150
|
+
JSON.stringify({
|
|
69151
|
+
pid: self2,
|
|
69152
|
+
claudePid,
|
|
69153
|
+
...sessionId ? { sessionId } : {},
|
|
69154
|
+
...preempt ? { monitor: true } : {}
|
|
69155
|
+
})
|
|
69156
|
+
);
|
|
69157
|
+
return true;
|
|
69158
|
+
}
|
|
69159
|
+
async function channelLive({ context, profile }) {
|
|
69160
|
+
const holder = await holderOf({ path: statePathOf({ context, kind: "channels", profile }) });
|
|
69161
|
+
return holder !== void 0 && context.processes.alive(holder.pid);
|
|
69162
|
+
}
|
|
69163
|
+
async function takeRound2({
|
|
69164
|
+
context,
|
|
69165
|
+
client,
|
|
69166
|
+
claudePid,
|
|
69167
|
+
session
|
|
69168
|
+
}) {
|
|
69169
|
+
const controller = new AbortController();
|
|
69170
|
+
const { signal } = controller;
|
|
69171
|
+
const watch = (async () => {
|
|
69172
|
+
while (!signal.aborted) {
|
|
69173
|
+
await context.sleep(WATCH_MS, signal);
|
|
69174
|
+
if (claudePid && !context.processes.alive(claudePid)) controller.abort();
|
|
69175
|
+
}
|
|
69176
|
+
})();
|
|
69177
|
+
try {
|
|
69178
|
+
return await forSession({ client, session }).post(
|
|
69179
|
+
"/api/agents/me/inbox",
|
|
69180
|
+
{ waitSeconds: ROUND_SECONDS2 },
|
|
69181
|
+
{ signal }
|
|
69182
|
+
);
|
|
69183
|
+
} catch (error62) {
|
|
69184
|
+
if (signal.aborted) return [];
|
|
69185
|
+
throw error62;
|
|
69186
|
+
} finally {
|
|
69187
|
+
controller.abort();
|
|
69188
|
+
await watch;
|
|
69189
|
+
}
|
|
69190
|
+
}
|
|
69191
|
+
async function roundOf({ context, client, name: name2, lock, claudePid, session, seen }) {
|
|
69192
|
+
if ((await holderOf({ path: lock }))?.pid !== context.processes.pid) return void 0;
|
|
69193
|
+
if (claudePid && !context.processes.alive(claudePid)) return void 0;
|
|
69194
|
+
const due = await dueFromSpool({ context, profile: name2, seen, pushedToo: true });
|
|
69195
|
+
if (due.length > 0) return due;
|
|
69196
|
+
if (await channelLive({ context, profile: name2 })) {
|
|
69197
|
+
await context.sleep(CHANNEL_CHECK_MS);
|
|
69198
|
+
return [];
|
|
69199
|
+
}
|
|
69200
|
+
const taken = await takeRound2({ context, client, claudePid, session });
|
|
69201
|
+
if (taken.length === 0) {
|
|
69202
|
+
await context.sleep(1e3);
|
|
69203
|
+
return [];
|
|
69204
|
+
}
|
|
69205
|
+
await keepTaken({ context, profile: name2, messages: taken });
|
|
69206
|
+
return taken;
|
|
69207
|
+
}
|
|
69208
|
+
async function claudePidOf({ context }) {
|
|
69209
|
+
const harness = await nearestHarnessOf({ context });
|
|
69210
|
+
if (harness?.harness === "claude-code") return harness.pid;
|
|
69211
|
+
return await context.processes.parentOf(context.processes.pid) ?? 0;
|
|
69212
|
+
}
|
|
69213
|
+
async function settleRound(round) {
|
|
69214
|
+
const { context, client, name: name2, session } = round;
|
|
69215
|
+
const messages = await roundOf(round).catch(async (error62) => {
|
|
69216
|
+
const refused = await notBoundNotice({
|
|
69217
|
+
context,
|
|
69218
|
+
client: forSession({ client, session }),
|
|
69219
|
+
session,
|
|
69220
|
+
error: error62,
|
|
69221
|
+
profile: name2
|
|
69222
|
+
});
|
|
69223
|
+
if (!refused) throw error62;
|
|
69224
|
+
return refused;
|
|
69225
|
+
});
|
|
69226
|
+
if (messages === void 0) return 0;
|
|
69227
|
+
if (!Array.isArray(messages)) {
|
|
69228
|
+
if (messages.rebound) return "again";
|
|
69229
|
+
if (!messages.notice) return 0;
|
|
69230
|
+
context.err(`${messages.notice}
|
|
69231
|
+
`);
|
|
69232
|
+
return 2;
|
|
69233
|
+
}
|
|
69234
|
+
if (messages.length === 0) return "again";
|
|
69235
|
+
await turnStarted({ context, client, agent: name2, messages }).catch(() => void 0);
|
|
69236
|
+
const self2 = await currentNameOf({ context, client, profile: name2 });
|
|
69237
|
+
context.err(`${hookContextOf({ messages, self: self2 })}
|
|
69238
|
+
`);
|
|
69239
|
+
const messageIds = messages.map((message2) => message2.messageId);
|
|
69240
|
+
await dropFromSpool({ context, profile: name2, messageIds });
|
|
69241
|
+
return 2;
|
|
69242
|
+
}
|
|
69243
|
+
async function waitForMessages({ context, args }) {
|
|
69244
|
+
const raw = await context.readStdin();
|
|
69245
|
+
const input2 = raw.trim() ? JSON.parse(raw) : {};
|
|
69246
|
+
const session = sessionOf({ context, harness: "claude-code", sessionId: input2.session_id });
|
|
69247
|
+
const claudePid = await claudePidOf({ context });
|
|
69248
|
+
const asked = await pluginHookArgs({ context, args, session, claudePid });
|
|
69249
|
+
if (!asked) return 0;
|
|
69250
|
+
const named = await sessionProfileArgs({ context, args: asked, session });
|
|
69251
|
+
const { client, name: name2 } = await signedIn({ context, args: named });
|
|
69252
|
+
await rememberSession({ context, claudePid, session });
|
|
69253
|
+
const rush = rushSessionOf({
|
|
69254
|
+
parentArgs: await context.processes.argsOf(await context.processes.parentOf(claudePid) ?? 0)
|
|
69255
|
+
});
|
|
69256
|
+
if (rush) await startRushGuard({ context, profile: name2, claudePid, rush });
|
|
69257
|
+
if (rush) await healRushDelivery({ context });
|
|
69258
|
+
const lock = statePathOf({ context, kind: "waiters", profile: name2 });
|
|
69259
|
+
if (!await takeLock({ context, path: lock, sessionId: input2.session_id, claudePid })) return 0;
|
|
69260
|
+
const seen = () => input2.transcript_path ? readFile10(input2.transcript_path, "utf8") : Promise.resolve("");
|
|
69261
|
+
const deadline = context.nowMs() + (WAIT_HOOK_TIMEOUT_SECONDS - 60) * 1e3;
|
|
69262
|
+
try {
|
|
69263
|
+
while (context.nowMs() < deadline) {
|
|
69264
|
+
const code = await settleRound({ context, client, name: name2, lock, claudePid, session, seen });
|
|
69265
|
+
if (code !== "again") return code;
|
|
69266
|
+
}
|
|
69267
|
+
return 0;
|
|
69268
|
+
} finally {
|
|
69269
|
+
if ((await holderOf({ path: lock }))?.pid === context.processes.pid)
|
|
69270
|
+
await rm4(lock, { force: true });
|
|
69271
|
+
}
|
|
69272
|
+
}
|
|
69273
|
+
async function healRushDelivery({ context }) {
|
|
69274
|
+
await rearmRushGuards({ context }).catch((error62) => {
|
|
69275
|
+
context.err(`laze: could not check the other rush sessions: ${String(error62)}
|
|
69276
|
+
`);
|
|
69277
|
+
});
|
|
69278
|
+
await ensureConnectService({ context }).catch((error62) => {
|
|
69279
|
+
context.err(`laze: could not start the connect service: ${String(error62)}
|
|
69280
|
+
`);
|
|
69281
|
+
});
|
|
69282
|
+
}
|
|
69283
|
+
async function waitHook({ context, args }) {
|
|
69284
|
+
try {
|
|
69285
|
+
return await waitForMessages({ context, args });
|
|
69286
|
+
} catch (error62) {
|
|
69287
|
+
context.err(`laze: the background waiter stopped: ${String(error62)}
|
|
69288
|
+
`);
|
|
69289
|
+
return 0;
|
|
69290
|
+
}
|
|
69291
|
+
}
|
|
69292
|
+
async function monitorServes({
|
|
69293
|
+
context,
|
|
69294
|
+
profile,
|
|
69295
|
+
claudePid
|
|
69296
|
+
}) {
|
|
69297
|
+
const holder = await holderOf({ path: statePathOf({ context, kind: "waiters", profile }) });
|
|
69298
|
+
if (!holder?.monitor || !context.processes.alive(holder.pid)) return false;
|
|
69299
|
+
return await holderClaudeOf({ context, holder }) === claudePid;
|
|
69300
|
+
}
|
|
69301
|
+
|
|
69302
|
+
// src/services/codex-link.service.ts
|
|
69303
|
+
import { createReadStream } from "node:fs";
|
|
69304
|
+
import { readdir as readdir5, rm as rm6, stat as stat4 } from "node:fs/promises";
|
|
69305
|
+
import { join as join13, resolve as resolve3 } from "node:path";
|
|
69306
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
69307
|
+
|
|
69308
|
+
// src/services/codex-adopt.service.ts
|
|
69309
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
69310
|
+
import { mkdir as mkdir10, readdir as readdir4, readFile as readFile11, rm as rm5, stat as stat3, writeFile as writeFile10 } from "node:fs/promises";
|
|
69311
|
+
import { dirname as dirname11, join as join12 } from "node:path";
|
|
69312
|
+
import { createInterface } from "node:readline";
|
|
69313
|
+
|
|
69314
|
+
// src/rules/codex-requests.rules.ts
|
|
69315
|
+
var DECLINED_DECISION = {
|
|
69316
|
+
"item/commandExecution/requestApproval": "decline",
|
|
69317
|
+
"item/fileChange/requestApproval": "decline",
|
|
69318
|
+
execCommandApproval: "denied",
|
|
69319
|
+
applyPatchApproval: "denied"
|
|
69320
|
+
};
|
|
69321
|
+
function codexRequestReplyOf({ method }) {
|
|
69322
|
+
const decision = DECLINED_DECISION[method];
|
|
69323
|
+
if (decision) return { result: { decision } };
|
|
69324
|
+
if (method === "item/permissions/requestApproval") {
|
|
69325
|
+
return { result: { permissions: {}, scope: "turn" } };
|
|
69326
|
+
}
|
|
69327
|
+
if (method === "mcpServer/elicitation/request") {
|
|
69328
|
+
return { result: { action: "decline", content: null } };
|
|
69329
|
+
}
|
|
69330
|
+
return { error: { code: -32601, message: `${method} is not supported here` } };
|
|
69331
|
+
}
|
|
69332
|
+
|
|
69333
|
+
// src/services/codex-adopt.service.ts
|
|
69334
|
+
function record3(value) {
|
|
69335
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
69336
|
+
}
|
|
69337
|
+
function absorbTurnEvent({ result, message: message2 }) {
|
|
69338
|
+
const params = record3(message2.params);
|
|
69339
|
+
if (message2.method === "item/completed") {
|
|
69340
|
+
const item = record3(params.item);
|
|
69341
|
+
if (item.type === "agentMessage" && typeof item.text === "string") result.answer = item.text;
|
|
69342
|
+
return;
|
|
69343
|
+
}
|
|
69344
|
+
if (message2.method !== "thread/tokenUsage/updated") return;
|
|
69345
|
+
const usage = record3(params.tokenUsage);
|
|
69346
|
+
const total = record3(usage.last).totalTokens;
|
|
69347
|
+
if (typeof total === "number") result.contextTokens = total;
|
|
69348
|
+
const window2 = usage.modelContextWindow;
|
|
69349
|
+
if (typeof window2 === "number" && window2 > 0) result.contextWindow = window2;
|
|
69350
|
+
}
|
|
69351
|
+
var TURN_HEARTBEAT_MS = 1e4;
|
|
69352
|
+
var CodexAppServer = class _CodexAppServer {
|
|
69353
|
+
constructor(child) {
|
|
69354
|
+
this.child = child;
|
|
69355
|
+
createInterface({ input: child.stdout }).on("line", (line) => this.receive(line));
|
|
69356
|
+
}
|
|
69357
|
+
child;
|
|
69358
|
+
#nextId = 0;
|
|
69359
|
+
#pending = /* @__PURE__ */ new Map();
|
|
69360
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
69361
|
+
static start({
|
|
69362
|
+
codexHome,
|
|
69363
|
+
inherited
|
|
69364
|
+
}) {
|
|
69365
|
+
const env = { ...inherited, CODEX_HOME: codexHome };
|
|
69366
|
+
return new _CodexAppServer(spawn2("codex", ["app-server"], { env, stdio: "pipe" }));
|
|
69367
|
+
}
|
|
69368
|
+
async call(method, params) {
|
|
69369
|
+
const id = ++this.#nextId;
|
|
69370
|
+
const reply2 = await new Promise((resolve17) => {
|
|
69371
|
+
this.#pending.set(id, resolve17);
|
|
69372
|
+
this.write({ id, method, params });
|
|
69373
|
+
});
|
|
69374
|
+
if (reply2.error !== void 0) throw new Error(`${method}: ${JSON.stringify(reply2.error)}`);
|
|
69375
|
+
return record3(reply2.result);
|
|
69376
|
+
}
|
|
69377
|
+
notify(method) {
|
|
69378
|
+
this.write({ method });
|
|
69379
|
+
}
|
|
69380
|
+
/** Starts one turn; `done` settles when it completes, keeping its last agent message. */
|
|
69381
|
+
async startTurn({ threadId, text: text2 }) {
|
|
69382
|
+
const result = { answer: "" };
|
|
69383
|
+
const done = new Promise((resolve17) => {
|
|
69384
|
+
const listen = (message2) => {
|
|
69385
|
+
absorbTurnEvent({ result, message: message2 });
|
|
69386
|
+
if (message2.method !== "turn/completed") return;
|
|
69387
|
+
this.#listeners.delete(listen);
|
|
69388
|
+
resolve17(result);
|
|
69389
|
+
};
|
|
69390
|
+
this.#listeners.add(listen);
|
|
69391
|
+
});
|
|
69392
|
+
const started = await this.call("turn/start", {
|
|
69393
|
+
threadId,
|
|
69394
|
+
input: [{ type: "text", text: text2, text_elements: [] }]
|
|
69395
|
+
});
|
|
69396
|
+
const turnId = record3(started.turn).id;
|
|
69397
|
+
return { turnId: typeof turnId === "string" ? turnId : null, done };
|
|
69398
|
+
}
|
|
69399
|
+
stop() {
|
|
69400
|
+
this.child.kill("SIGTERM");
|
|
69401
|
+
}
|
|
69402
|
+
write(message2) {
|
|
69403
|
+
this.child.stdin.write(`${JSON.stringify(message2)}
|
|
69404
|
+
`);
|
|
69405
|
+
}
|
|
69406
|
+
receive(line) {
|
|
69407
|
+
let message2;
|
|
69408
|
+
try {
|
|
69409
|
+
message2 = record3(JSON.parse(line));
|
|
69410
|
+
} catch {
|
|
69411
|
+
return;
|
|
69412
|
+
}
|
|
69413
|
+
if (typeof message2.id === "number" && message2.method === void 0) {
|
|
69414
|
+
this.#pending.get(message2.id)?.(message2);
|
|
69415
|
+
this.#pending.delete(message2.id);
|
|
69416
|
+
return;
|
|
69417
|
+
}
|
|
69418
|
+
if (message2.method !== void 0 && message2.id !== void 0) {
|
|
69419
|
+
this.write({
|
|
69420
|
+
id: message2.id,
|
|
69421
|
+
...codexRequestReplyOf({
|
|
69422
|
+
method: typeof message2.method === "string" ? message2.method : ""
|
|
69423
|
+
})
|
|
69424
|
+
});
|
|
69425
|
+
return;
|
|
69426
|
+
}
|
|
69427
|
+
for (const listen of this.#listeners) listen(message2);
|
|
69428
|
+
}
|
|
69429
|
+
};
|
|
69430
|
+
async function newestThreadId({ codexHome }) {
|
|
69431
|
+
const root = join12(codexHome, "sessions");
|
|
69432
|
+
const files2 = await readdir4(root, { recursive: true }).catch(() => []);
|
|
69433
|
+
const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
|
|
69434
|
+
const dated = await Promise.all(
|
|
69435
|
+
rollouts.map(async (file3) => ({ file: file3, at: (await stat3(join12(root, file3))).mtimeMs }))
|
|
69436
|
+
);
|
|
69437
|
+
const newest = dated.toSorted((a, b) => b.at - a.at)[0]?.file ?? "";
|
|
69438
|
+
const id = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/.exec(newest);
|
|
69439
|
+
if (!id?.[1]) throw new CliUsageError("No Codex session found: pass --thread <id>.");
|
|
69440
|
+
return id[1];
|
|
69441
|
+
}
|
|
69442
|
+
function promptOf({ message: message2, self: self2 }) {
|
|
69443
|
+
return [
|
|
69444
|
+
`A message reached you in the Laze workspace${selfClauseOf({ self: self2 })}. Answer it; your final`,
|
|
69445
|
+
"message is posted as your reply in its thread.",
|
|
69446
|
+
"",
|
|
69447
|
+
formatInboxMessage({ message: message2 }).split("\n").slice(0, -1).join("\n")
|
|
69448
|
+
].join("\n");
|
|
69449
|
+
}
|
|
69450
|
+
async function heartbeat({
|
|
69451
|
+
client,
|
|
69452
|
+
message: message2,
|
|
69453
|
+
state
|
|
69454
|
+
}) {
|
|
69455
|
+
return client.post("/api/agents/me/turn", {
|
|
69456
|
+
channelId: message2.channelId,
|
|
69457
|
+
threadRootId: message2.threadRootId,
|
|
69458
|
+
state,
|
|
69459
|
+
...state === "working" ? { messageId: message2.messageId } : {}
|
|
69460
|
+
}).catch(() => void 0);
|
|
69461
|
+
}
|
|
69462
|
+
async function watchTurn({
|
|
69463
|
+
context,
|
|
69464
|
+
client,
|
|
69465
|
+
codex,
|
|
69466
|
+
threadId,
|
|
69467
|
+
turn,
|
|
69468
|
+
message: message2
|
|
69469
|
+
}) {
|
|
69470
|
+
const finished = new AbortController();
|
|
69471
|
+
void turn.done.then(() => finished.abort());
|
|
69472
|
+
while (!finished.signal.aborted) {
|
|
69473
|
+
const beat2 = await heartbeat({ client, message: message2, state: "working" });
|
|
69474
|
+
if (beat2?.stop && turn.turnId) {
|
|
69475
|
+
await codex.call("turn/interrupt", { threadId, turnId: turn.turnId }).catch(() => void 0);
|
|
69476
|
+
return beat2.stoppedBy ?? "someone";
|
|
69477
|
+
}
|
|
69478
|
+
await context.sleep(TURN_HEARTBEAT_MS, finished.signal);
|
|
69479
|
+
}
|
|
69480
|
+
return void 0;
|
|
69481
|
+
}
|
|
69482
|
+
async function answer({
|
|
69483
|
+
context,
|
|
69484
|
+
codex,
|
|
69485
|
+
client,
|
|
69486
|
+
threadId,
|
|
69487
|
+
message: message2,
|
|
69488
|
+
profile
|
|
69489
|
+
}) {
|
|
69490
|
+
const self2 = await currentNameOf({ context, client, profile });
|
|
69491
|
+
const running = await codex.startTurn({ threadId, text: promptOf({ message: message2, self: self2 }) });
|
|
69492
|
+
const stoppedBy = await watchTurn({ context, client, codex, threadId, turn: running, message: message2 });
|
|
69493
|
+
const turn = await running.done;
|
|
69494
|
+
await heartbeat({ client, message: message2, state: "idle" });
|
|
69495
|
+
if (stoppedBy !== void 0) return `(stopped by ${stoppedBy})`;
|
|
69496
|
+
const body = turn.answer.trim() || "(no answer)";
|
|
69497
|
+
await client.post("/api/agents/me/replies", { messageId: message2.messageId, body });
|
|
69498
|
+
if (turn.contextTokens !== void 0) {
|
|
69499
|
+
await client.post("/api/agents/me/activity", {
|
|
69500
|
+
sessionId: threadId,
|
|
69501
|
+
contextTokens: turn.contextTokens,
|
|
69502
|
+
...turn.contextWindow ? { contextWindow: turn.contextWindow } : {}
|
|
69503
|
+
});
|
|
69504
|
+
}
|
|
69505
|
+
return body;
|
|
69506
|
+
}
|
|
69507
|
+
var MAX_RESTART_WAIT_SECONDS = 60;
|
|
69508
|
+
var HEALTHY_RUN_MS = 6e4;
|
|
69509
|
+
async function recordOf({ path }) {
|
|
69510
|
+
return readFile11(path, "utf8").then(
|
|
69511
|
+
(text2) => JSON.parse(text2),
|
|
69512
|
+
() => void 0
|
|
69513
|
+
);
|
|
69514
|
+
}
|
|
69515
|
+
function threadFlag({ thread: thread2 }) {
|
|
69516
|
+
return thread2 ? ["--thread", thread2] : [];
|
|
69517
|
+
}
|
|
69518
|
+
async function startAdoptInBackground({
|
|
69519
|
+
context,
|
|
69520
|
+
args,
|
|
69521
|
+
profile,
|
|
69522
|
+
laze
|
|
69523
|
+
}) {
|
|
69524
|
+
const thread2 = flagText({ args, name: "thread" }) || context.environment.inherited.CODEX_THREAD_ID || null;
|
|
69525
|
+
const path = statePathOf({ context, kind: "adopt", profile });
|
|
69526
|
+
const log = statePathOf({ context, kind: "adopt", profile, extension: "log" });
|
|
69527
|
+
const running = await recordOf({ path });
|
|
69528
|
+
if (running) context.processes.stop(running.pid);
|
|
69529
|
+
const adopt = ["adopt", "codex", "--profile", profile, ...threadFlag({ thread: thread2 })];
|
|
69530
|
+
const argv = [...context.program, ...adopt, "--supervise"];
|
|
69531
|
+
const pid = context.processes.spawnDetached({ argv, logPath: log });
|
|
69532
|
+
await mkdir10(dirname11(path), { recursive: true, mode: 448 });
|
|
69533
|
+
await writeFile10(path, JSON.stringify({ pid, thread: thread2, log, startedAt: context.nowMs() }));
|
|
69534
|
+
return [
|
|
69535
|
+
`Started \`${laze} adopt codex\` in the background (pid ${pid}). It answers each Laze message`,
|
|
69536
|
+
`as a turn in ${thread2 ? `this Codex thread (${thread2})` : "the newest Codex thread"}, and starts again if it stops.`,
|
|
69537
|
+
`Log: ${log}`,
|
|
69538
|
+
` ${laze} adopt codex --status --profile ${profile} shows whether it runs`,
|
|
69539
|
+
` ${laze} adopt codex --stop --profile ${profile} stops it`,
|
|
69540
|
+
"Nothing else needs to run. While this Codex window stays open, Codex lets only it write the",
|
|
69541
|
+
"thread, so adopt answers in a fork of it (the same history so far; `codex resume <fork id>`",
|
|
69542
|
+
"from the log opens it). Started again with this window closed, it answers in the thread itself."
|
|
69543
|
+
].join("\n");
|
|
69544
|
+
}
|
|
69545
|
+
async function supervise({
|
|
69546
|
+
context,
|
|
69547
|
+
args,
|
|
69548
|
+
profile
|
|
69549
|
+
}) {
|
|
69550
|
+
const path = statePathOf({ context, kind: "adopt", profile });
|
|
69551
|
+
const thread2 = flagText({ args, name: "thread" });
|
|
69552
|
+
const adopt = ["adopt", "codex", "--profile", profile, ...threadFlag({ thread: thread2 })];
|
|
69553
|
+
const command = [...context.program, ...adopt];
|
|
69554
|
+
let wait = 1;
|
|
69555
|
+
while ((await recordOf({ path }))?.pid === context.processes.pid) {
|
|
69556
|
+
const started = context.nowMs();
|
|
69557
|
+
context.out(
|
|
69558
|
+
`${Temporal3.Instant.fromEpochMilliseconds(started).toString()} starting laze adopt codex
|
|
69559
|
+
`
|
|
69560
|
+
);
|
|
69561
|
+
const code = await context.runCommand({ command, env: {} }).catch(() => 1);
|
|
69562
|
+
if (context.nowMs() - started > HEALTHY_RUN_MS) wait = 1;
|
|
69563
|
+
if ((await recordOf({ path }))?.pid !== context.processes.pid) break;
|
|
69564
|
+
context.out(`laze adopt codex exited ${code}; starting it again in ${wait}s
|
|
69565
|
+
`);
|
|
69566
|
+
await context.sleep(wait * 1e3);
|
|
69567
|
+
wait = Math.min(MAX_RESTART_WAIT_SECONDS, wait * 2);
|
|
69568
|
+
}
|
|
69569
|
+
return 0;
|
|
69570
|
+
}
|
|
69571
|
+
async function adoptStatus({ context, profile }) {
|
|
69572
|
+
const record4 = await recordOf({ path: statePathOf({ context, kind: "adopt", profile }) });
|
|
69573
|
+
if (!record4 || !context.processes.alive(record4.pid)) {
|
|
69574
|
+
context.out(`laze adopt codex does not run in the background for profile "${profile}".
|
|
69575
|
+
`);
|
|
69576
|
+
return;
|
|
69577
|
+
}
|
|
69578
|
+
const thread2 = record4.thread ?? "the newest thread";
|
|
69579
|
+
context.out(
|
|
69580
|
+
`laze adopt codex runs in the background for profile "${profile}" (pid ${record4.pid}), thread ${thread2}.
|
|
69581
|
+
Log: ${record4.log}
|
|
69582
|
+
`
|
|
69583
|
+
);
|
|
69584
|
+
}
|
|
69585
|
+
async function adoptStop({ context, profile }) {
|
|
69586
|
+
const path = statePathOf({ context, kind: "adopt", profile });
|
|
69587
|
+
const record4 = await recordOf({ path });
|
|
69588
|
+
await rm5(path, { force: true });
|
|
69589
|
+
if (!record4 || !context.processes.stop(record4.pid)) {
|
|
69590
|
+
context.out(`laze adopt codex was not running in the background for profile "${profile}".
|
|
69591
|
+
`);
|
|
69592
|
+
return;
|
|
69593
|
+
}
|
|
69594
|
+
context.out(`Stopped laze adopt codex (pid ${record4.pid}) for profile "${profile}".
|
|
69595
|
+
`);
|
|
69596
|
+
}
|
|
69597
|
+
var HELD_THREAD = /active writer/;
|
|
69598
|
+
async function adoptedThreadOf({
|
|
69599
|
+
context,
|
|
69600
|
+
codex,
|
|
69601
|
+
threadId,
|
|
69602
|
+
profile
|
|
69603
|
+
}) {
|
|
69604
|
+
const held = await codex.call("thread/resume", { threadId }).then(
|
|
69605
|
+
() => false,
|
|
69606
|
+
(error62) => {
|
|
69607
|
+
if (HELD_THREAD.test(String(error62))) return true;
|
|
69608
|
+
throw error62;
|
|
69609
|
+
}
|
|
69610
|
+
);
|
|
69611
|
+
if (!held) return threadId;
|
|
69612
|
+
const path = statePathOf({ context, kind: "adopt", profile, extension: "forks.json" });
|
|
69613
|
+
const forks = await readFile11(path, "utf8").then(
|
|
69614
|
+
(text2) => JSON.parse(text2),
|
|
69615
|
+
() => ({})
|
|
69616
|
+
);
|
|
69617
|
+
const known = forks[threadId];
|
|
69618
|
+
if (known && await codex.call("thread/resume", { threadId: known }).then(
|
|
69619
|
+
() => true,
|
|
69620
|
+
() => false
|
|
69621
|
+
)) {
|
|
69622
|
+
context.out(`Codex holds thread ${threadId} open elsewhere; answering in its fork ${known}.
|
|
69623
|
+
`);
|
|
69624
|
+
return known;
|
|
69625
|
+
}
|
|
69626
|
+
const forked = record3((await codex.call("thread/fork", { threadId })).thread).id;
|
|
69627
|
+
if (typeof forked !== "string") throw new Error("thread/fork answered no thread id");
|
|
69628
|
+
await mkdir10(dirname11(path), { recursive: true, mode: 448 });
|
|
69629
|
+
await writeFile10(path, JSON.stringify({ ...forks, [threadId]: forked }));
|
|
69630
|
+
context.out(
|
|
69631
|
+
`Codex holds thread ${threadId} open elsewhere; answering in its new fork ${forked}.
|
|
69632
|
+
`
|
|
69633
|
+
);
|
|
69634
|
+
return forked;
|
|
69635
|
+
}
|
|
69636
|
+
async function adoptCodex({ context, args }) {
|
|
69637
|
+
if (args.words[1] !== "codex") {
|
|
69638
|
+
throw new CliUsageError("Usage: laze adopt codex [--thread <id>] | --status | --stop");
|
|
69639
|
+
}
|
|
69640
|
+
const { client, name: name2 } = await signedIn({ context, args });
|
|
69641
|
+
if (args.flags.status) return adoptStatus({ context, profile: name2 });
|
|
69642
|
+
if (args.flags.stop) return adoptStop({ context, profile: name2 });
|
|
69643
|
+
if (args.flags.supervise) return supervise({ context, args, profile: name2 });
|
|
69644
|
+
const { codexHome } = context.environment;
|
|
69645
|
+
const threadId = flagText({ args, name: "thread" }) || context.environment.inherited.CODEX_THREAD_ID || await newestThreadId({ codexHome });
|
|
69646
|
+
const once = Boolean(args.flags.once);
|
|
69647
|
+
const codex = CodexAppServer.start({ codexHome, inherited: context.environment.inherited });
|
|
69648
|
+
try {
|
|
69649
|
+
await codex.call("initialize", {
|
|
69650
|
+
clientInfo: { name: "laze", title: "Laze", version: "1" },
|
|
69651
|
+
capabilities: null
|
|
69652
|
+
});
|
|
69653
|
+
codex.notify("initialized");
|
|
69654
|
+
const adopted = await adoptedThreadOf({ context, codex, threadId, profile: name2 });
|
|
69655
|
+
context.out(`Adopted Codex thread ${adopted}; answering Laze messages.
|
|
69656
|
+
`);
|
|
69657
|
+
const timeout = Number(flagText({ args, name: "timeout", fallback: "0" }));
|
|
69658
|
+
do {
|
|
69659
|
+
const messages = await receiveMessages({
|
|
69660
|
+
context,
|
|
69661
|
+
client,
|
|
69662
|
+
waitSeconds: timeout > 0 ? timeout : Infinity
|
|
69663
|
+
});
|
|
69664
|
+
for (const message2 of messages) {
|
|
69665
|
+
const body = await answer({
|
|
69666
|
+
context,
|
|
69667
|
+
codex,
|
|
69668
|
+
client,
|
|
69669
|
+
threadId: adopted,
|
|
69670
|
+
message: message2,
|
|
69671
|
+
profile: name2
|
|
69672
|
+
});
|
|
69673
|
+
context.out(`Answered ${message2.messageId}: ${body.slice(0, 120)}
|
|
69674
|
+
`);
|
|
69675
|
+
}
|
|
69676
|
+
if (messages.length === 0 && timeout > 0) break;
|
|
69677
|
+
} while (!once);
|
|
69678
|
+
} finally {
|
|
69679
|
+
codex.stop();
|
|
69680
|
+
}
|
|
69681
|
+
}
|
|
69682
|
+
|
|
69408
69683
|
// src/services/codex-link.service.ts
|
|
69409
69684
|
var ROLLOUTS_READ = 200;
|
|
69410
69685
|
async function firstLineOf({ path }) {
|
|
@@ -69422,13 +69697,13 @@ async function newestThreadIn({
|
|
|
69422
69697
|
codexHome,
|
|
69423
69698
|
directory
|
|
69424
69699
|
}) {
|
|
69425
|
-
const root =
|
|
69426
|
-
const files2 = await
|
|
69700
|
+
const root = join13(codexHome, "sessions");
|
|
69701
|
+
const files2 = await readdir5(root, { recursive: true }).catch(() => []);
|
|
69427
69702
|
const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
|
|
69428
69703
|
const dated = await Promise.all(
|
|
69429
69704
|
rollouts.map(async (file3) => ({
|
|
69430
|
-
path:
|
|
69431
|
-
at: await
|
|
69705
|
+
path: join13(root, file3),
|
|
69706
|
+
at: await stat4(join13(root, file3)).then(
|
|
69432
69707
|
(info) => info.mtimeMs,
|
|
69433
69708
|
() => 0
|
|
69434
69709
|
)
|
|
@@ -69498,9 +69773,9 @@ async function linkCodexSession({
|
|
|
69498
69773
|
}
|
|
69499
69774
|
|
|
69500
69775
|
// src/services/laze-plugin.service.ts
|
|
69501
|
-
import { mkdir as mkdir11, readFile as
|
|
69776
|
+
import { mkdir as mkdir11, readFile as readFile12, writeFile as writeFile11 } from "node:fs/promises";
|
|
69502
69777
|
import { homedir as homedir3 } from "node:os";
|
|
69503
|
-
import { dirname as
|
|
69778
|
+
import { dirname as dirname12, join as join14 } from "node:path";
|
|
69504
69779
|
|
|
69505
69780
|
// src/rules/laze-plugin.rules.ts
|
|
69506
69781
|
var LAZE_PLUGIN = "laze";
|
|
@@ -69616,11 +69891,11 @@ function lazePluginFiles({
|
|
|
69616
69891
|
var REGISTER_LIMIT_MS = 6e4;
|
|
69617
69892
|
var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
69618
69893
|
function pluginFolderOf({ context }) {
|
|
69619
|
-
return
|
|
69894
|
+
return join14(dirname12(context.environment.configPath), "plugins");
|
|
69620
69895
|
}
|
|
69621
69896
|
async function pluginIsCurrent({ context }) {
|
|
69622
|
-
const manifest =
|
|
69623
|
-
const written = await
|
|
69897
|
+
const manifest = join14(pluginFolderOf({ context }), LAZE_PLUGIN, ".claude-plugin", "plugin.json");
|
|
69898
|
+
const written = await readFile12(manifest, "utf8").then(
|
|
69624
69899
|
(text2) => JSON.parse(text2).version,
|
|
69625
69900
|
() => void 0
|
|
69626
69901
|
);
|
|
@@ -69634,8 +69909,8 @@ async function writeLazePlugin({ context }) {
|
|
|
69634
69909
|
configPath: context.environment.configPath
|
|
69635
69910
|
});
|
|
69636
69911
|
for (const [path, text2] of Object.entries(files2)) {
|
|
69637
|
-
const target =
|
|
69638
|
-
await mkdir11(
|
|
69912
|
+
const target = join14(folder, path);
|
|
69913
|
+
await mkdir11(dirname12(target), { recursive: true });
|
|
69639
69914
|
await writeFile11(target, text2);
|
|
69640
69915
|
}
|
|
69641
69916
|
return folder;
|
|
@@ -69666,8 +69941,8 @@ var RUN_FILES = ["hooks/hooks.json", "monitors/monitors.json"];
|
|
|
69666
69941
|
async function cachedPluginOf({ context }) {
|
|
69667
69942
|
const inherited = context.environment.inherited;
|
|
69668
69943
|
const home = inherited.HOME || homedir3();
|
|
69669
|
-
const claude = inherited.CLAUDE_CONFIG_DIR ||
|
|
69670
|
-
const listed = await
|
|
69944
|
+
const claude = inherited.CLAUDE_CONFIG_DIR || join14(home, ".claude");
|
|
69945
|
+
const listed = await readFile12(join14(claude, "plugins", "installed_plugins.json"), "utf8").then(
|
|
69671
69946
|
(text2) => JSON.parse(text2),
|
|
69672
69947
|
() => void 0
|
|
69673
69948
|
);
|
|
@@ -69676,10 +69951,10 @@ async function cachedPluginOf({ context }) {
|
|
|
69676
69951
|
async function refreshStaleCache({ context, folder }) {
|
|
69677
69952
|
const cached2 = await cachedPluginOf({ context });
|
|
69678
69953
|
if (!cached2) return true;
|
|
69679
|
-
const read3 = (path) =>
|
|
69954
|
+
const read3 = (path) => readFile12(path, "utf8").catch(() => "");
|
|
69680
69955
|
for (const file3 of RUN_FILES) {
|
|
69681
|
-
const ours = await read3(
|
|
69682
|
-
if (ours === await read3(
|
|
69956
|
+
const ours = await read3(join14(folder, LAZE_PLUGIN, file3));
|
|
69957
|
+
if (ours === await read3(join14(cached2, file3))) continue;
|
|
69683
69958
|
const plugin2 = `${LAZE_PLUGIN}@${LAZE_PLUGIN}`;
|
|
69684
69959
|
const script = [
|
|
69685
69960
|
`claude plugin uninstall ${plugin2} --scope user ${QUIET}`,
|
|
@@ -69690,10 +69965,10 @@ async function refreshStaleCache({ context, folder }) {
|
|
|
69690
69965
|
return true;
|
|
69691
69966
|
}
|
|
69692
69967
|
function registeredMarkOf({ context }) {
|
|
69693
|
-
return
|
|
69968
|
+
return join14(pluginFolderOf({ context }), "registered");
|
|
69694
69969
|
}
|
|
69695
69970
|
async function pluginRegistered({ context }) {
|
|
69696
|
-
return
|
|
69971
|
+
return readFile12(registeredMarkOf({ context }), "utf8").then(
|
|
69697
69972
|
() => true,
|
|
69698
69973
|
() => false
|
|
69699
69974
|
);
|
|
@@ -69707,7 +69982,7 @@ async function installLazePlugin({ context }) {
|
|
|
69707
69982
|
async function plugin({ context, args }) {
|
|
69708
69983
|
const action = args.words[1] ?? "install";
|
|
69709
69984
|
if (action === "path") {
|
|
69710
|
-
context.out(`${
|
|
69985
|
+
context.out(`${join14(pluginFolderOf({ context }), LAZE_PLUGIN)}
|
|
69711
69986
|
`);
|
|
69712
69987
|
return 0;
|
|
69713
69988
|
}
|
|
@@ -69726,7 +70001,7 @@ async function plugin({ context, args }) {
|
|
|
69726
70001
|
|
|
69727
70002
|
// src/services/mcp-channel.service.ts
|
|
69728
70003
|
import { mkdir as mkdir12, rm as rm7, writeFile as writeFile12 } from "node:fs/promises";
|
|
69729
|
-
import { dirname as
|
|
70004
|
+
import { dirname as dirname13 } from "node:path";
|
|
69730
70005
|
var LAZE_MCP_SERVER = "laze";
|
|
69731
70006
|
var DEV_CHANNELS_FLAG = "--dangerously-load-development-channels";
|
|
69732
70007
|
var ROUND_SECONDS3 = 50;
|
|
@@ -69816,7 +70091,7 @@ async function pushInbox({
|
|
|
69816
70091
|
signal
|
|
69817
70092
|
}) {
|
|
69818
70093
|
const marker = statePathOf({ context, kind: "channels", profile });
|
|
69819
|
-
await mkdir12(
|
|
70094
|
+
await mkdir12(dirname13(marker), { recursive: true, mode: 448 });
|
|
69820
70095
|
await writeFile12(marker, JSON.stringify({ pid: context.processes.pid }));
|
|
69821
70096
|
try {
|
|
69822
70097
|
while (!signal.aborted) {
|
|
@@ -69844,8 +70119,8 @@ async function pushInbox({
|
|
|
69844
70119
|
}
|
|
69845
70120
|
|
|
69846
70121
|
// src/services/plugin-tip.service.ts
|
|
69847
|
-
import { mkdir as mkdir13, readFile as
|
|
69848
|
-
import { dirname as
|
|
70122
|
+
import { mkdir as mkdir13, readFile as readFile13, writeFile as writeFile13 } from "node:fs/promises";
|
|
70123
|
+
import { dirname as dirname14 } from "node:path";
|
|
69849
70124
|
var RELOAD_TIP = "Laze: the Laze plugin is installed in Claude Code, and this session has not loaded it yet. Tell the user once, in one plain line, that it is optional: typing /reload-plugins makes Laze messages arrive right away; until then they still arrive through the hooks.";
|
|
69850
70125
|
var LINK_RELOAD_TIP = "Tell the user once, in one plain line, that it is optional: typing /reload-plugins makes Laze messages arrive right away; until then they still arrive through the hooks.";
|
|
69851
70126
|
function monitorsRunHere({ context }) {
|
|
@@ -69879,7 +70154,7 @@ async function markReloadTipTold({
|
|
|
69879
70154
|
}) {
|
|
69880
70155
|
if (!session) return;
|
|
69881
70156
|
const path = toldPathOf({ context, session });
|
|
69882
|
-
await mkdir13(
|
|
70157
|
+
await mkdir13(dirname14(path), { recursive: true, mode: 448 });
|
|
69883
70158
|
await writeFile13(path, String(context.nowMs()), { mode: 384 });
|
|
69884
70159
|
}
|
|
69885
70160
|
async function reloadTipOnce({
|
|
@@ -69888,7 +70163,7 @@ async function reloadTipOnce({
|
|
|
69888
70163
|
}) {
|
|
69889
70164
|
if (!session || !monitorsRunHere({ context })) return void 0;
|
|
69890
70165
|
if (!await pluginRegistered({ context })) return void 0;
|
|
69891
|
-
const told = await
|
|
70166
|
+
const told = await readFile13(toldPathOf({ context, session }), "utf8").then(
|
|
69892
70167
|
() => true,
|
|
69893
70168
|
() => false
|
|
69894
70169
|
);
|
|
@@ -69954,9 +70229,9 @@ async function installHooks({
|
|
|
69954
70229
|
directory,
|
|
69955
70230
|
profile
|
|
69956
70231
|
}) {
|
|
69957
|
-
const folder =
|
|
69958
|
-
const path =
|
|
69959
|
-
const current2 = await
|
|
70232
|
+
const folder = join15(directory, ".claude");
|
|
70233
|
+
const path = join15(folder, "settings.local.json");
|
|
70234
|
+
const current2 = await readFile14(path, "utf8").then(
|
|
69960
70235
|
(text2) => JSON.parse(text2),
|
|
69961
70236
|
() => ({})
|
|
69962
70237
|
);
|
|
@@ -70158,7 +70433,7 @@ async function reportTranscript({
|
|
|
70158
70433
|
input: input2
|
|
70159
70434
|
}) {
|
|
70160
70435
|
if (!input2.transcript_path || !input2.session_id) return;
|
|
70161
|
-
const lines = (await
|
|
70436
|
+
const lines = (await readFile14(input2.transcript_path, "utf8")).split("\n");
|
|
70162
70437
|
const context = readTranscript({ lines });
|
|
70163
70438
|
await client.post("/api/agents/me/activity", {
|
|
70164
70439
|
sessionId: input2.session_id,
|
|
@@ -70191,7 +70466,7 @@ async function handOver({ context, args }) {
|
|
|
70191
70466
|
const kept = await dueFromSpool({
|
|
70192
70467
|
context,
|
|
70193
70468
|
profile: agent2,
|
|
70194
|
-
seen: () => input2.transcript_path ?
|
|
70469
|
+
seen: () => input2.transcript_path ? readFile14(input2.transcript_path, "utf8") : Promise.resolve(""),
|
|
70195
70470
|
pushedToo: false
|
|
70196
70471
|
});
|
|
70197
70472
|
const claim3 = forSession({ client, session });
|
|
@@ -70231,8 +70506,8 @@ async function addSessionStartWaiter({ context, args }) {
|
|
|
70231
70506
|
const directory = context.environment.inherited.CLAUDE_PROJECT_DIR;
|
|
70232
70507
|
const profile = flagText({ args, name: "profile" });
|
|
70233
70508
|
if (!directory || !profile) return;
|
|
70234
|
-
const path =
|
|
70235
|
-
const settings2 = await
|
|
70509
|
+
const path = join15(directory, ".claude", "settings.local.json");
|
|
70510
|
+
const settings2 = await readFile14(path, "utf8").then(
|
|
70236
70511
|
(text2) => JSON.parse(text2),
|
|
70237
70512
|
() => void 0
|
|
70238
70513
|
);
|
|
@@ -70241,7 +70516,7 @@ async function addSessionStartWaiter({ context, args }) {
|
|
|
70241
70516
|
}
|
|
70242
70517
|
async function refreshPlugin({ context }) {
|
|
70243
70518
|
if (await pluginIsCurrent({ context })) return;
|
|
70244
|
-
const logPath =
|
|
70519
|
+
const logPath = join15(pluginFolderOf({ context }), "install.log");
|
|
70245
70520
|
context.processes.spawnDetached({ argv: [...context.program, "plugin", "install"], logPath });
|
|
70246
70521
|
}
|
|
70247
70522
|
async function stopHook({ context, args }) {
|
|
@@ -70259,7 +70534,7 @@ async function stopHook({ context, args }) {
|
|
|
70259
70534
|
}
|
|
70260
70535
|
|
|
70261
70536
|
// src/services/agent-manage-commands.service.ts
|
|
70262
|
-
import { readFile as
|
|
70537
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
70263
70538
|
import { extname, resolve as resolve5 } from "node:path";
|
|
70264
70539
|
|
|
70265
70540
|
// src/rules/login-format.rules.ts
|
|
@@ -70388,7 +70663,7 @@ async function avatarOf({
|
|
|
70388
70663
|
}) {
|
|
70389
70664
|
const path = flagText({ args, name: "avatar" });
|
|
70390
70665
|
if (!path) return void 0;
|
|
70391
|
-
const bytes = await
|
|
70666
|
+
const bytes = await readFile15(resolve5(context.cwd, path)).catch(() => {
|
|
70392
70667
|
throw new CliUsageError(`laze: cannot read the avatar file ${path}.`);
|
|
70393
70668
|
});
|
|
70394
70669
|
const uploaded = await client.post("/api/agents/avatars", {
|
|
@@ -71091,8 +71366,8 @@ async function requestAgent({ context, args }) {
|
|
|
71091
71366
|
}
|
|
71092
71367
|
|
|
71093
71368
|
// src/services/app-commands.service.ts
|
|
71094
|
-
import { mkdir as mkdir15, readdir as
|
|
71095
|
-
import { dirname as
|
|
71369
|
+
import { mkdir as mkdir15, readdir as readdir6, readFile as readFile16, writeFile as writeFile16 } from "node:fs/promises";
|
|
71370
|
+
import { dirname as dirname15, join as join17, relative as relative3, resolve as resolve6, sep as sep2 } from "node:path";
|
|
71096
71371
|
|
|
71097
71372
|
// ../../modules/app/contract/src/app.connections.ts
|
|
71098
71373
|
var appFunctionNameSchema = external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/);
|
|
@@ -73487,7 +73762,7 @@ async function appPinsCommand({
|
|
|
73487
73762
|
import { execFile } from "node:child_process";
|
|
73488
73763
|
import { mkdtemp, rm as rm8, writeFile as writeFile15 } from "node:fs/promises";
|
|
73489
73764
|
import { tmpdir } from "node:os";
|
|
73490
|
-
import { join as
|
|
73765
|
+
import { join as join16 } from "node:path";
|
|
73491
73766
|
import { promisify } from "node:util";
|
|
73492
73767
|
var run2 = promisify(execFile);
|
|
73493
73768
|
var MODULE_SYNTAX = /^\s*(import|export)\s/m;
|
|
@@ -73516,11 +73791,11 @@ async function scriptErrorsOf({
|
|
|
73516
73791
|
const unknown2 = unknownCollectionsOf({ files: files2, collections });
|
|
73517
73792
|
const scripts = files2.flatMap(scriptsOf);
|
|
73518
73793
|
if (scripts.length === 0) return unknown2;
|
|
73519
|
-
const dir = await mkdtemp(
|
|
73794
|
+
const dir = await mkdtemp(join16(tmpdir(), "laze-app-check-"));
|
|
73520
73795
|
try {
|
|
73521
73796
|
const errors = await Promise.all(
|
|
73522
73797
|
scripts.map(async (script, index) => {
|
|
73523
|
-
const file3 =
|
|
73798
|
+
const file3 = join16(dir, `${index}.${script.module ? "mjs" : "cjs"}`);
|
|
73524
73799
|
await writeFile15(file3, script.code);
|
|
73525
73800
|
try {
|
|
73526
73801
|
await run2(process.execPath, ["--check", file3]);
|
|
@@ -73670,7 +73945,7 @@ async function turnTokenOf({
|
|
|
73670
73945
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
73671
73946
|
if (pinned) return pinned;
|
|
73672
73947
|
if (env.LAZE_TURN_FILE) {
|
|
73673
|
-
return
|
|
73948
|
+
return readFile16(env.LAZE_TURN_FILE, "utf8").then(
|
|
73674
73949
|
(text2) => text2.trim(),
|
|
73675
73950
|
() => ""
|
|
73676
73951
|
);
|
|
@@ -73696,7 +73971,7 @@ function folderOf({ context, word: word3 }) {
|
|
|
73696
73971
|
return resolve6(context.cwd, word3 ?? ".");
|
|
73697
73972
|
}
|
|
73698
73973
|
async function readManifest(folder) {
|
|
73699
|
-
const text2 = await
|
|
73974
|
+
const text2 = await readFile16(join17(folder, APP_MANIFEST_FILE), "utf8").catch(() => void 0);
|
|
73700
73975
|
if (text2 === void 0) return void 0;
|
|
73701
73976
|
const parsed = appManifestSchema.safeParse(JSON.parse(text2));
|
|
73702
73977
|
if (!parsed.success) {
|
|
@@ -73731,7 +74006,7 @@ async function jsonFlag({
|
|
|
73731
74006
|
}) {
|
|
73732
74007
|
const raw = flagText({ args, name: name2 });
|
|
73733
74008
|
if (!raw) return void 0;
|
|
73734
|
-
const text2 = raw.startsWith("@") ? await
|
|
74009
|
+
const text2 = raw.startsWith("@") ? await readFile16(resolve6(context.cwd, raw.slice(1)), "utf8") : raw;
|
|
73735
74010
|
try {
|
|
73736
74011
|
return JSON.parse(text2);
|
|
73737
74012
|
} catch {
|
|
@@ -73743,8 +74018,8 @@ async function listFiles(folder) {
|
|
|
73743
74018
|
const pending = [folder];
|
|
73744
74019
|
while (pending.length > 0 && found.length <= MAX_FILES) {
|
|
73745
74020
|
const current2 = pending.pop() ?? folder;
|
|
73746
|
-
for (const entry of await
|
|
73747
|
-
const path =
|
|
74021
|
+
for (const entry of await readdir6(current2, { withFileTypes: true })) {
|
|
74022
|
+
const path = join17(current2, entry.name);
|
|
73748
74023
|
const rel = relative3(folder, path).split(sep2).join("/");
|
|
73749
74024
|
if (isSkippedPath({ path: rel })) continue;
|
|
73750
74025
|
if (entry.isDirectory()) pending.push(path);
|
|
@@ -73788,8 +74063,8 @@ var appCreate = async ({ context, args }) => {
|
|
|
73788
74063
|
await mkdir15(folder, { recursive: true });
|
|
73789
74064
|
const files2 = template ? templateFiles({ template, name: name2 }) : {};
|
|
73790
74065
|
for (const [path, content] of Object.entries(files2)) {
|
|
73791
|
-
await mkdir15(
|
|
73792
|
-
await writeFile16(
|
|
74066
|
+
await mkdir15(dirname15(join17(folder, path)), { recursive: true });
|
|
74067
|
+
await writeFile16(join17(folder, path), content);
|
|
73793
74068
|
}
|
|
73794
74069
|
const manifest = {
|
|
73795
74070
|
app: { id: app2.id, name: app2.name, slug: app2.slug },
|
|
@@ -73797,7 +74072,7 @@ var appCreate = async ({ context, args }) => {
|
|
|
73797
74072
|
views: template?.views ? [...template.views] : [],
|
|
73798
74073
|
seed: template ? { ...template.seed } : {}
|
|
73799
74074
|
};
|
|
73800
|
-
await writeFile16(
|
|
74075
|
+
await writeFile16(join17(folder, APP_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
|
|
73801
74076
|
`);
|
|
73802
74077
|
print5({
|
|
73803
74078
|
context,
|
|
@@ -73834,7 +74109,7 @@ var appPush = async ({ context, args }) => {
|
|
|
73834
74109
|
paths.map(
|
|
73835
74110
|
async (path) => buildFileOf({
|
|
73836
74111
|
path: relative3(folder, path).split(sep2).join("/"),
|
|
73837
|
-
bytes: await
|
|
74112
|
+
bytes: await readFile16(path)
|
|
73838
74113
|
})
|
|
73839
74114
|
)
|
|
73840
74115
|
);
|
|
@@ -74217,7 +74492,7 @@ var appImport = async ({ context, args }) => {
|
|
|
74217
74492
|
const words = args.words.slice(2);
|
|
74218
74493
|
const [named, collection, file3] = words.length >= 3 ? words : [void 0, ...words];
|
|
74219
74494
|
if (!collection || !file3) throw new CliUsageError(USAGE5);
|
|
74220
|
-
const csv = await
|
|
74495
|
+
const csv = await readFile16(resolve6(context.cwd, file3), "utf8").catch(() => {
|
|
74221
74496
|
throw new CliUsageError(`Cannot read ${file3}`);
|
|
74222
74497
|
});
|
|
74223
74498
|
const scoped = named ? { ...args, flags: { ...args.flags, app: named } } : args;
|
|
@@ -74783,8 +75058,8 @@ async function billing({ context, args }) {
|
|
|
74783
75058
|
|
|
74784
75059
|
// src/services/browser-commands.service.ts
|
|
74785
75060
|
import { randomBytes } from "node:crypto";
|
|
74786
|
-
import { mkdir as mkdir16, readFile as
|
|
74787
|
-
import { dirname as
|
|
75061
|
+
import { mkdir as mkdir16, readFile as readFile17, writeFile as writeFile17 } from "node:fs/promises";
|
|
75062
|
+
import { dirname as dirname16, join as join18 } from "node:path";
|
|
74788
75063
|
|
|
74789
75064
|
// src/services/browser-tab-commands.service.ts
|
|
74790
75065
|
var BROWSER_TAB_PATHS = {
|
|
@@ -75330,7 +75605,7 @@ async function turnTokenOf2({ context }) {
|
|
|
75330
75605
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
75331
75606
|
if (pinned) return pinned;
|
|
75332
75607
|
if (!env.LAZE_TURN_FILE) return "";
|
|
75333
|
-
return
|
|
75608
|
+
return readFile17(env.LAZE_TURN_FILE, "utf8").then(
|
|
75334
75609
|
(text2) => text2.trim(),
|
|
75335
75610
|
() => ""
|
|
75336
75611
|
);
|
|
@@ -75404,7 +75679,7 @@ async function cdp({ context, args }) {
|
|
|
75404
75679
|
}
|
|
75405
75680
|
function bridgeStatePath({ context, machine: machine2 }) {
|
|
75406
75681
|
const safe = machine2.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
75407
|
-
return
|
|
75682
|
+
return join18(dirname16(context.environment.configPath), "bridges", `${safe}.json`);
|
|
75408
75683
|
}
|
|
75409
75684
|
async function bridgePort({
|
|
75410
75685
|
context,
|
|
@@ -75412,7 +75687,7 @@ async function bridgePort({
|
|
|
75412
75687
|
access
|
|
75413
75688
|
}) {
|
|
75414
75689
|
const path = bridgeStatePath({ context, machine: machine2 });
|
|
75415
|
-
const live = await
|
|
75690
|
+
const live = await readFile17(path, "utf8").then(
|
|
75416
75691
|
(text2) => JSON.parse(text2),
|
|
75417
75692
|
() => void 0
|
|
75418
75693
|
);
|
|
@@ -75425,7 +75700,7 @@ async function bridgePort({
|
|
|
75425
75700
|
key,
|
|
75426
75701
|
...target
|
|
75427
75702
|
});
|
|
75428
|
-
await mkdir16(
|
|
75703
|
+
await mkdir16(dirname16(path), { recursive: true, mode: 448 });
|
|
75429
75704
|
await writeFile17(path, JSON.stringify({ port, key }), { mode: 384 });
|
|
75430
75705
|
return port;
|
|
75431
75706
|
}
|
|
@@ -76070,9 +76345,42 @@ async function channelSettings({ context, args }) {
|
|
|
76070
76345
|
}
|
|
76071
76346
|
|
|
76072
76347
|
// src/services/chat-actions-commands.service.ts
|
|
76073
|
-
import { readFile as
|
|
76348
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
76074
76349
|
import { basename as basename3, isAbsolute as isAbsolute2, relative as relative4, resolve as resolve7 } from "node:path";
|
|
76075
76350
|
|
|
76351
|
+
// src/rules/file-types.rules.ts
|
|
76352
|
+
var TYPES = {
|
|
76353
|
+
png: "image/png",
|
|
76354
|
+
jpg: "image/jpeg",
|
|
76355
|
+
jpeg: "image/jpeg",
|
|
76356
|
+
webp: "image/webp",
|
|
76357
|
+
gif: "image/gif",
|
|
76358
|
+
svg: "image/svg+xml",
|
|
76359
|
+
pdf: "application/pdf",
|
|
76360
|
+
txt: "text/plain",
|
|
76361
|
+
md: "text/markdown",
|
|
76362
|
+
csv: "text/csv",
|
|
76363
|
+
json: "application/json",
|
|
76364
|
+
zip: "application/zip"
|
|
76365
|
+
};
|
|
76366
|
+
function contentTypeOf(fileName) {
|
|
76367
|
+
const extension2 = fileName.toLowerCase().split(".").pop() ?? "";
|
|
76368
|
+
return TYPES[extension2] ?? "application/octet-stream";
|
|
76369
|
+
}
|
|
76370
|
+
var MACHINE_NAME = /^(?:[a-z]{1,8}[_-])?[0-9a-f][0-9a-f_-]{11,}$/i;
|
|
76371
|
+
function readableUploadName({ name: name2, asked }) {
|
|
76372
|
+
const slash = name2.lastIndexOf("/");
|
|
76373
|
+
const base = name2.slice(slash + 1);
|
|
76374
|
+
const dot = base.lastIndexOf(".");
|
|
76375
|
+
const extension2 = dot > 0 ? base.slice(dot) : "";
|
|
76376
|
+
const wanted = asked?.trim();
|
|
76377
|
+
if (wanted) return /\.[A-Za-z0-9]{1,8}$/.test(wanted) ? wanted : `${wanted}${extension2}`;
|
|
76378
|
+
const stem = dot > 0 ? base.slice(0, dot) : base;
|
|
76379
|
+
if (!MACHINE_NAME.test(stem)) return name2;
|
|
76380
|
+
const image = contentTypeOf(base).startsWith("image/");
|
|
76381
|
+
return `${image ? "image" : "file"}${extension2}`;
|
|
76382
|
+
}
|
|
76383
|
+
|
|
76076
76384
|
// src/services/file-upload.service.ts
|
|
76077
76385
|
async function sendParts({
|
|
76078
76386
|
context,
|
|
@@ -76171,7 +76479,7 @@ var CHAT_ACTIONS_USAGE = `Usage:
|
|
|
76171
76479
|
laze files <channel> [--before <fileId>] [--limit <n>] its files, newest first
|
|
76172
76480
|
laze file link <fileId> [--variant original|thumbnail|poster|preview] [--download]
|
|
76173
76481
|
laze file rename <fileId> <name> rename a file you posted
|
|
76174
|
-
laze file upload <channel> <path> [--type <content-type>] upload a file; post it with its id
|
|
76482
|
+
laze file upload <channel> <path> [--name <name>] [--type <content-type>] upload a file; post it with its id
|
|
76175
76483
|
laze saved [--done] [--limit <n>] | laze saved marks your saved messages (people)
|
|
76176
76484
|
laze save <messageId> [--off] save a message for later, or take it out
|
|
76177
76485
|
laze saved done <messageId> [--undo] mark a saved message done, or open again
|
|
@@ -76375,19 +76683,27 @@ function uploadNameOf({ cwd, path }) {
|
|
|
76375
76683
|
}
|
|
76376
76684
|
var fileUpload = async ({ context, args, client }) => {
|
|
76377
76685
|
const path = resolve7(context.cwd, wordAt(args, 3));
|
|
76378
|
-
const bytes = new Uint8Array(await
|
|
76686
|
+
const bytes = new Uint8Array(await readFile18(path));
|
|
76379
76687
|
const answer4 = await uploadFile({
|
|
76380
76688
|
context,
|
|
76381
76689
|
client,
|
|
76382
76690
|
file: {
|
|
76383
76691
|
channel: wordAt(args, 2),
|
|
76384
|
-
fileName:
|
|
76385
|
-
|
|
76692
|
+
fileName: readableUploadName({
|
|
76693
|
+
name: uploadNameOf({ cwd: context.cwd, path }),
|
|
76694
|
+
...flagText({ args, name: "name" }) && { asked: flagText({ args, name: "name" }) }
|
|
76695
|
+
}),
|
|
76696
|
+
contentType: flagText({ args, name: "type", fallback: contentTypeOf(path) }),
|
|
76386
76697
|
bytes
|
|
76387
76698
|
}
|
|
76388
76699
|
});
|
|
76389
|
-
print6({
|
|
76390
|
-
|
|
76700
|
+
print6({
|
|
76701
|
+
context,
|
|
76702
|
+
args,
|
|
76703
|
+
answer: answer4,
|
|
76704
|
+
text: (it) => `Uploaded ${it.fileName} as ${it.id}. Put <file:${it.id}> in a message to share it.
|
|
76705
|
+
`
|
|
76706
|
+
});
|
|
76391
76707
|
};
|
|
76392
76708
|
var FILE_VERBS = {
|
|
76393
76709
|
link: async ({ context, args, client }) => {
|
|
@@ -76540,7 +76856,7 @@ async function chatActions({
|
|
|
76540
76856
|
}
|
|
76541
76857
|
|
|
76542
76858
|
// src/services/claude-monitor.service.ts
|
|
76543
|
-
import { readFile as
|
|
76859
|
+
import { readFile as readFile19, rm as rm9 } from "node:fs/promises";
|
|
76544
76860
|
var MONITOR_IDLE_MS = 3e4;
|
|
76545
76861
|
var MONITOR_OUTRANKED_MS = 3e3;
|
|
76546
76862
|
async function deliverOnce({
|
|
@@ -76558,7 +76874,7 @@ async function deliverOnce({
|
|
|
76558
76874
|
const named = { ...args, flags: { ...args.flags, profile } };
|
|
76559
76875
|
const { client } = await signedIn({ context, args: named });
|
|
76560
76876
|
const due = await dueFromSpool({ context, profile, seen: async () => "", pushedToo: true });
|
|
76561
|
-
const taken = due.length > 0 ? [] : await
|
|
76877
|
+
const taken = due.length > 0 ? [] : await takeRound2({ context, client, claudePid, session });
|
|
76562
76878
|
const messages = [...due, ...taken];
|
|
76563
76879
|
if (messages.length === 0) {
|
|
76564
76880
|
await context.sleep(1e3);
|
|
@@ -76635,7 +76951,7 @@ async function monitorSessionOf({
|
|
|
76635
76951
|
const fromEnv = sessionOf({ context, harness: "claude-code", sessionId });
|
|
76636
76952
|
if (fromEnv || !claudePid) return fromEnv;
|
|
76637
76953
|
const path = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
|
|
76638
|
-
return
|
|
76954
|
+
return readFile19(path, "utf8").then(
|
|
76639
76955
|
(text2) => JSON.parse(text2),
|
|
76640
76956
|
() => void 0
|
|
76641
76957
|
);
|
|
@@ -78310,10 +78626,10 @@ async function computer({ context, args }) {
|
|
|
78310
78626
|
}
|
|
78311
78627
|
|
|
78312
78628
|
// src/services/connect-commands.service.ts
|
|
78313
|
-
import { readFile as
|
|
78629
|
+
import { readFile as readFile21 } from "node:fs/promises";
|
|
78314
78630
|
|
|
78315
78631
|
// src/services/mcp-gateway.service.ts
|
|
78316
|
-
import { readFile as
|
|
78632
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
78317
78633
|
import { createInterface as createInterface3 } from "node:readline";
|
|
78318
78634
|
var TURN_HEADER = "x-laze-turn";
|
|
78319
78635
|
function serveMcpGateway({
|
|
@@ -78356,7 +78672,7 @@ async function relayMcpLines({
|
|
|
78356
78672
|
const github3 = env.LAZE_GITHUB_CONNECTION;
|
|
78357
78673
|
const url2 = `${profile.url.replace(/\/+$/, "")}/api/connectors/mcp/${encodeURIComponent(profile.agentId)}${github3 ? `?github=${encodeURIComponent(github3)}` : ""}`;
|
|
78358
78674
|
const turnFile = env.LAZE_TURN_FILE;
|
|
78359
|
-
const readTurn = () =>
|
|
78675
|
+
const readTurn = () => readFile20(turnFile, "utf8").then(
|
|
78360
78676
|
(text2) => text2.trim(),
|
|
78361
78677
|
() => ""
|
|
78362
78678
|
);
|
|
@@ -78446,7 +78762,7 @@ async function turnOf({ context }) {
|
|
|
78446
78762
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
78447
78763
|
if (pinned) return pinned;
|
|
78448
78764
|
const file3 = env.LAZE_TURN_FILE;
|
|
78449
|
-
const turn = file3 ? await
|
|
78765
|
+
const turn = file3 ? await readFile21(file3, "utf8").then(
|
|
78450
78766
|
(text2) => text2.trim(),
|
|
78451
78767
|
() => ""
|
|
78452
78768
|
) : "";
|
|
@@ -78504,11 +78820,11 @@ async function connect({
|
|
|
78504
78820
|
}
|
|
78505
78821
|
|
|
78506
78822
|
// src/services/connector-commands.service.ts
|
|
78507
|
-
import { readFile as
|
|
78823
|
+
import { readFile as readFile23 } from "node:fs/promises";
|
|
78508
78824
|
import { resolve as resolve8 } from "node:path";
|
|
78509
78825
|
|
|
78510
78826
|
// src/services/vault-keychain-commands.service.ts
|
|
78511
|
-
import { readFile as
|
|
78827
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
78512
78828
|
|
|
78513
78829
|
// src/rules/vault-input.rules.ts
|
|
78514
78830
|
function secondsOf(text2) {
|
|
@@ -78830,7 +79146,7 @@ async function secretText({ context, args }) {
|
|
|
78830
79146
|
);
|
|
78831
79147
|
}
|
|
78832
79148
|
const file3 = flagText({ args, name: "from-file" });
|
|
78833
|
-
const text2 = file3 ? await
|
|
79149
|
+
const text2 = file3 ? await readFile22(file3, "utf8") : await context.readStdin();
|
|
78834
79150
|
const trimmed = text2.replace(/\r?\n$/, "");
|
|
78835
79151
|
if (!trimmed.trim()) throw new CliUsageError("No value: pipe it on stdin or use --from-file.");
|
|
78836
79152
|
return trimmed;
|
|
@@ -79040,7 +79356,7 @@ async function keyText({ context, args }) {
|
|
|
79040
79356
|
throw new CliUsageError("A key never goes in a flag: pipe it on stdin or use --from-file.");
|
|
79041
79357
|
}
|
|
79042
79358
|
const file3 = flagText({ args, name: "from-file" });
|
|
79043
|
-
const text2 = file3 ? await
|
|
79359
|
+
const text2 = file3 ? await readFile23(resolve8(context.cwd, file3), "utf8") : await context.readStdin();
|
|
79044
79360
|
const trimmed = text2.trim();
|
|
79045
79361
|
if (!trimmed) throw new CliUsageError("No key: pipe it on stdin or use --from-file.");
|
|
79046
79362
|
return trimmed;
|
|
@@ -79432,8 +79748,8 @@ var DOMAINS_USAGE = `Usage:
|
|
|
79432
79748
|
var printJson5 = (context, data) => context.out(`${JSON.stringify(data, null, 2)}
|
|
79433
79749
|
`);
|
|
79434
79750
|
function printDomain(context, row) {
|
|
79435
|
-
const
|
|
79436
|
-
context.out(`${row.domain} ${
|
|
79751
|
+
const join23 = row.autoJoin ? "auto-join on" : "auto-join off";
|
|
79752
|
+
context.out(`${row.domain} ${join23}${row.enforced ? " single sign-on enforced" : ""}
|
|
79437
79753
|
`);
|
|
79438
79754
|
}
|
|
79439
79755
|
async function list4({ context, args }) {
|
|
@@ -79465,7 +79781,7 @@ async function domains({ context, args }) {
|
|
|
79465
79781
|
}
|
|
79466
79782
|
|
|
79467
79783
|
// src/services/feed-commands.service.ts
|
|
79468
|
-
import { readFile as
|
|
79784
|
+
import { readFile as readFile25 } from "node:fs/promises";
|
|
79469
79785
|
import { resolve as resolve10 } from "node:path";
|
|
79470
79786
|
|
|
79471
79787
|
// src/rules/feed-input.rules.ts
|
|
@@ -79590,7 +79906,7 @@ function feedFlagsOf({ args }) {
|
|
|
79590
79906
|
}
|
|
79591
79907
|
|
|
79592
79908
|
// src/services/feed-files.service.ts
|
|
79593
|
-
import { readFile as
|
|
79909
|
+
import { readFile as readFile24 } from "node:fs/promises";
|
|
79594
79910
|
import { basename as basename4, resolve as resolve9 } from "node:path";
|
|
79595
79911
|
|
|
79596
79912
|
// ../../modules/feed/contract/src/feed.ts
|
|
@@ -80135,26 +80451,6 @@ var feedWakeIntentSchemaDefinition = external_exports.object({
|
|
|
80135
80451
|
// ../../modules/feed/contract/src/feed.config.ts
|
|
80136
80452
|
var feedConfig = Config.define(() => ({ publicBaseUrl }));
|
|
80137
80453
|
|
|
80138
|
-
// src/rules/file-types.rules.ts
|
|
80139
|
-
var TYPES = {
|
|
80140
|
-
png: "image/png",
|
|
80141
|
-
jpg: "image/jpeg",
|
|
80142
|
-
jpeg: "image/jpeg",
|
|
80143
|
-
webp: "image/webp",
|
|
80144
|
-
gif: "image/gif",
|
|
80145
|
-
svg: "image/svg+xml",
|
|
80146
|
-
pdf: "application/pdf",
|
|
80147
|
-
txt: "text/plain",
|
|
80148
|
-
md: "text/markdown",
|
|
80149
|
-
csv: "text/csv",
|
|
80150
|
-
json: "application/json",
|
|
80151
|
-
zip: "application/zip"
|
|
80152
|
-
};
|
|
80153
|
-
function contentTypeOf(fileName) {
|
|
80154
|
-
const extension2 = fileName.toLowerCase().split(".").pop() ?? "";
|
|
80155
|
-
return TYPES[extension2] ?? "application/octet-stream";
|
|
80156
|
-
}
|
|
80157
|
-
|
|
80158
80454
|
// src/services/feed-files.service.ts
|
|
80159
80455
|
async function bytesOf2({
|
|
80160
80456
|
context,
|
|
@@ -80185,7 +80481,7 @@ async function local({ context, path }) {
|
|
|
80185
80481
|
return {
|
|
80186
80482
|
fileName,
|
|
80187
80483
|
contentType: contentTypeOf(fileName),
|
|
80188
|
-
bytes: new Uint8Array(await
|
|
80484
|
+
bytes: new Uint8Array(await readFile24(full))
|
|
80189
80485
|
};
|
|
80190
80486
|
}
|
|
80191
80487
|
async function directWith({ client, to }) {
|
|
@@ -80263,7 +80559,7 @@ async function bodyOf2({
|
|
|
80263
80559
|
flags: flags2
|
|
80264
80560
|
}) {
|
|
80265
80561
|
const body = { ...flags2.fields };
|
|
80266
|
-
const read3 = (source) => "file" in source ?
|
|
80562
|
+
const read3 = (source) => "file" in source ? readFile25(resolve10(context.cwd, source.file), "utf8") : source.text;
|
|
80267
80563
|
for (const [field, source] of Object.entries(flags2.texts)) body[field] = await read3(source);
|
|
80268
80564
|
if (flags2.rich) {
|
|
80269
80565
|
const text2 = await read3(flags2.rich.source);
|
|
@@ -80425,7 +80721,7 @@ async function textFlag({
|
|
|
80425
80721
|
}) {
|
|
80426
80722
|
const value = flagText({ args, name: name2 });
|
|
80427
80723
|
if (!value.startsWith("@")) return value;
|
|
80428
|
-
return
|
|
80724
|
+
return readFile25(resolve10(context.cwd, value.slice(1)), "utf8");
|
|
80429
80725
|
}
|
|
80430
80726
|
async function feedList({ context, args }) {
|
|
80431
80727
|
const { client } = await signedIn({ context, args });
|
|
@@ -80535,7 +80831,7 @@ async function feed({ context, args }) {
|
|
|
80535
80831
|
}
|
|
80536
80832
|
|
|
80537
80833
|
// src/services/github-commands.service.ts
|
|
80538
|
-
import { readFile as
|
|
80834
|
+
import { readFile as readFile26 } from "node:fs/promises";
|
|
80539
80835
|
|
|
80540
80836
|
// src/rules/github-signature.rules.ts
|
|
80541
80837
|
var TURN_SEPARATOR = "~";
|
|
@@ -80605,7 +80901,7 @@ var REAL_GH = "/usr/bin/gh";
|
|
|
80605
80901
|
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>`.";
|
|
80606
80902
|
async function turnFileToken({ env }) {
|
|
80607
80903
|
if (!env.LAZE_TURN_FILE) return "";
|
|
80608
|
-
return
|
|
80904
|
+
return readFile26(env.LAZE_TURN_FILE, "utf8").then(
|
|
80609
80905
|
(text2) => text2.trim(),
|
|
80610
80906
|
() => ""
|
|
80611
80907
|
);
|
|
@@ -80639,7 +80935,7 @@ async function githubGh({
|
|
|
80639
80935
|
args: args.rest,
|
|
80640
80936
|
agentName: profile.name ?? "An agent",
|
|
80641
80937
|
threadUrl: threadUrlOf({ env, workspaceId: profile.workspaceId }),
|
|
80642
|
-
readBodyFile: (path) => path === "-" ? context.readStdin() :
|
|
80938
|
+
readBodyFile: (path) => path === "-" ? context.readStdin() : readFile26(path, "utf8")
|
|
80643
80939
|
});
|
|
80644
80940
|
return context.runCommand({
|
|
80645
80941
|
command: [REAL_GH, ...ghArgs],
|
|
@@ -80738,7 +81034,7 @@ async function setAgentGithub({
|
|
|
80738
81034
|
}
|
|
80739
81035
|
|
|
80740
81036
|
// src/services/history-commands.service.ts
|
|
80741
|
-
import { readFile as
|
|
81037
|
+
import { readFile as readFile27 } from "node:fs/promises";
|
|
80742
81038
|
|
|
80743
81039
|
// src/rules/history-format.rules.ts
|
|
80744
81040
|
function timeOf2(iso) {
|
|
@@ -80834,7 +81130,7 @@ async function turnTokenOf3({ context }) {
|
|
|
80834
81130
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
80835
81131
|
if (pinned) return pinned;
|
|
80836
81132
|
if (!env.LAZE_TURN_FILE) return "";
|
|
80837
|
-
return
|
|
81133
|
+
return readFile27(env.LAZE_TURN_FILE, "utf8").then(
|
|
80838
81134
|
(text2) => text2.trim(),
|
|
80839
81135
|
() => ""
|
|
80840
81136
|
);
|
|
@@ -81026,19 +81322,19 @@ async function ip({ context, args }) {
|
|
|
81026
81322
|
}
|
|
81027
81323
|
|
|
81028
81324
|
// src/services/join-commands.service.ts
|
|
81029
|
-
import { mkdir as mkdir17, readFile as
|
|
81030
|
-
import { dirname as
|
|
81325
|
+
import { mkdir as mkdir17, readFile as readFile28, rename as rename5, rm as rm10, writeFile as writeFile18 } from "node:fs/promises";
|
|
81326
|
+
import { dirname as dirname17, join as join19 } from "node:path";
|
|
81031
81327
|
var DEFAULT_WAIT_SECONDS2 = 100;
|
|
81032
81328
|
var JOIN_USAGE = "Usage: laze join [--workspace <name|id|invite link>] [--for <email>] [--name <name>] [--note <text>] [--timeout <seconds>] [--project <folder>]";
|
|
81033
81329
|
function pendingPathOf({ context }) {
|
|
81034
|
-
return
|
|
81330
|
+
return join19(dirname17(context.environment.configPath), "join", "pending.json");
|
|
81035
81331
|
}
|
|
81036
81332
|
async function readPending({
|
|
81037
81333
|
context,
|
|
81038
81334
|
url: url2,
|
|
81039
81335
|
args
|
|
81040
81336
|
}) {
|
|
81041
|
-
const pending = await
|
|
81337
|
+
const pending = await readFile28(pendingPathOf({ context }), "utf8").then(
|
|
81042
81338
|
(text2) => JSON.parse(text2),
|
|
81043
81339
|
() => void 0
|
|
81044
81340
|
);
|
|
@@ -81048,7 +81344,7 @@ async function readPending({
|
|
|
81048
81344
|
}
|
|
81049
81345
|
async function keepPending({ context, pending }) {
|
|
81050
81346
|
const path = pendingPathOf({ context });
|
|
81051
|
-
await mkdir17(
|
|
81347
|
+
await mkdir17(dirname17(path), { recursive: true, mode: 448 });
|
|
81052
81348
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
81053
81349
|
await writeFile18(temporary, JSON.stringify(pending), { mode: 384 });
|
|
81054
81350
|
await rename5(temporary, path);
|
|
@@ -81368,9 +81664,9 @@ function machineAccessCommand(name2) {
|
|
|
81368
81664
|
|
|
81369
81665
|
// src/services/vault-commands.service.ts
|
|
81370
81666
|
import { createHash as createHash2 } from "node:crypto";
|
|
81371
|
-
import { mkdir as mkdir18, readFile as
|
|
81667
|
+
import { mkdir as mkdir18, readFile as readFile29, rm as rm11, writeFile as writeFile19 } from "node:fs/promises";
|
|
81372
81668
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
81373
|
-
import { dirname as
|
|
81669
|
+
import { dirname as dirname18, join as join20 } from "node:path";
|
|
81374
81670
|
var USAGE10 = `Usage: laze vault run <connection> --reason "<one plain sentence>" [--wait <s>] -- <command> [args...]
|
|
81375
81671
|
Runs the command with the connection's values in its environment, on a Laze agent's computer
|
|
81376
81672
|
or on a machine it runs on.`;
|
|
@@ -81409,7 +81705,7 @@ async function turnTokenOf4({
|
|
|
81409
81705
|
if (pinned) return pinned;
|
|
81410
81706
|
if (!turnFile) throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
81411
81707
|
try {
|
|
81412
|
-
return (await
|
|
81708
|
+
return (await readFile29(turnFile, "utf8")).trim();
|
|
81413
81709
|
} catch {
|
|
81414
81710
|
throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
81415
81711
|
}
|
|
@@ -81419,11 +81715,11 @@ function runKeyPathOf({
|
|
|
81419
81715
|
connection
|
|
81420
81716
|
}) {
|
|
81421
81717
|
const name2 = createHash2("sha256").update(connection).digest("hex");
|
|
81422
|
-
const base = turnFile ?
|
|
81423
|
-
return
|
|
81718
|
+
const base = turnFile ? dirname18(turnFile) : join20(tmpdir2(), "laze-vault");
|
|
81719
|
+
return join20(base, "vault-run-keys", `${name2}.json`);
|
|
81424
81720
|
}
|
|
81425
81721
|
async function runKeyAt({ path }) {
|
|
81426
|
-
const saved3 = await
|
|
81722
|
+
const saved3 = await readFile29(path, "utf8").then(
|
|
81427
81723
|
(text2) => JSON.parse(text2),
|
|
81428
81724
|
() => void 0
|
|
81429
81725
|
);
|
|
@@ -81433,7 +81729,7 @@ async function runKeyAt({ path }) {
|
|
|
81433
81729
|
}
|
|
81434
81730
|
const fresh = await generateEcdhKeys();
|
|
81435
81731
|
const jwk = await globalThis.crypto.subtle.exportKey("jwk", fresh.privateKey);
|
|
81436
|
-
await mkdir18(
|
|
81732
|
+
await mkdir18(dirname18(path), { recursive: true, mode: 448 });
|
|
81437
81733
|
await writeFile19(path, JSON.stringify({ publicKey: fresh.publicKey, privateKey: jwk }), {
|
|
81438
81734
|
mode: 384
|
|
81439
81735
|
});
|
|
@@ -82106,14 +82402,14 @@ async function serveMcp({
|
|
|
82106
82402
|
}
|
|
82107
82403
|
|
|
82108
82404
|
// src/services/mount-files.service.ts
|
|
82109
|
-
import { mkdir as mkdir19, readFile as
|
|
82110
|
-
import { dirname as
|
|
82405
|
+
import { mkdir as mkdir19, readFile as readFile30, rm as rm12, writeFile as writeFile20 } from "node:fs/promises";
|
|
82406
|
+
import { dirname as dirname19, relative as relative5, resolve as resolve11 } from "node:path";
|
|
82111
82407
|
async function textArgument({
|
|
82112
82408
|
context,
|
|
82113
82409
|
value
|
|
82114
82410
|
}) {
|
|
82115
82411
|
if (value === "-") return context.readStdin();
|
|
82116
|
-
if (value.startsWith("@")) return
|
|
82412
|
+
if (value.startsWith("@")) return readFile30(resolve11(context.cwd, value.slice(1)), "utf8");
|
|
82117
82413
|
return value;
|
|
82118
82414
|
}
|
|
82119
82415
|
function turnChannel({ context, args }) {
|
|
@@ -82133,7 +82429,7 @@ async function writeMount({
|
|
|
82133
82429
|
const inside = relative5(root, target);
|
|
82134
82430
|
if (!inside || inside.startsWith(".."))
|
|
82135
82431
|
throw new Error(`Refusing to write outside ${root}: ${file3.path}`);
|
|
82136
|
-
await mkdir19(
|
|
82432
|
+
await mkdir19(dirname19(target), { recursive: true });
|
|
82137
82433
|
await writeFile20(target, file3.content);
|
|
82138
82434
|
}
|
|
82139
82435
|
return root;
|
|
@@ -82775,8 +83071,8 @@ ${OPS_USAGE}`);
|
|
|
82775
83071
|
}
|
|
82776
83072
|
|
|
82777
83073
|
// src/services/release-watch.service.ts
|
|
82778
|
-
import { mkdir as mkdir20, readFile as
|
|
82779
|
-
import { dirname as
|
|
83074
|
+
import { mkdir as mkdir20, readFile as readFile31, realpath, writeFile as writeFile21 } from "node:fs/promises";
|
|
83075
|
+
import { dirname as dirname20, join as join21 } from "node:path";
|
|
82780
83076
|
|
|
82781
83077
|
// src/rules/cli-update.rules.ts
|
|
82782
83078
|
var CLI_PACKAGE_LATEST = "@lazehq/cli@latest";
|
|
@@ -82877,16 +83173,16 @@ async function startedUpdate({
|
|
|
82877
83173
|
if (context.environment.inherited.LAZE_AUTO_UPDATE === "0") return null;
|
|
82878
83174
|
const plan2 = updatePlanOf({ script: await scriptOf(context) });
|
|
82879
83175
|
if (plan2.kind !== "install") return null;
|
|
82880
|
-
const folder =
|
|
82881
|
-
const stamp =
|
|
82882
|
-
const last = await
|
|
83176
|
+
const folder = dirname20(context.environment.configPath);
|
|
83177
|
+
const stamp = join21(folder, "auto-update.json");
|
|
83178
|
+
const last = await readFile31(stamp, "utf8").then((text2) => JSON.parse(text2)).catch(() => null);
|
|
82883
83179
|
const now = context.nowMs();
|
|
82884
83180
|
if (last?.server === server && now - last.atMs < RETRY_AFTER_MS) return null;
|
|
82885
83181
|
await mkdir20(folder, { recursive: true, mode: 448 });
|
|
82886
83182
|
await writeFile21(stamp, JSON.stringify({ server, atMs: now }), { mode: 384 });
|
|
82887
83183
|
context.processes.spawnDetached({
|
|
82888
83184
|
argv: [...context.program, "update"],
|
|
82889
|
-
logPath:
|
|
83185
|
+
logPath: join21(folder, "auto-update.log")
|
|
82890
83186
|
});
|
|
82891
83187
|
return { manager: plan2.manager };
|
|
82892
83188
|
}
|
|
@@ -82916,19 +83212,19 @@ function watchingRelease({
|
|
|
82916
83212
|
}
|
|
82917
83213
|
|
|
82918
83214
|
// src/services/rush-guard.service.ts
|
|
82919
|
-
import { readFile as
|
|
83215
|
+
import { readFile as readFile32, rm as rm13 } from "node:fs/promises";
|
|
82920
83216
|
var WATCH_MS3 = 2e3;
|
|
82921
83217
|
var RETRY_MS2 = 3e4;
|
|
82922
83218
|
async function guardRound({ context, client, name: name2, lock, claudePid, session, rush }) {
|
|
82923
83219
|
const key = session ? sessionKeyOf({ session }) : void 0;
|
|
82924
|
-
if (key && await liveElsewhere({ context, key, claudePid })) return true;
|
|
83220
|
+
if (key && await liveElsewhere({ context, key, claudePid, asleepCounts: false })) return true;
|
|
82925
83221
|
const holder = await holderOf({ path: lock });
|
|
82926
83222
|
if (holder?.pid !== context.processes.pid) {
|
|
82927
83223
|
if (!await takeLock({ context, path: lock, claudePid, ...sessionIdOf({ session }) }))
|
|
82928
83224
|
return true;
|
|
82929
83225
|
}
|
|
82930
83226
|
const due = await dueFromSpool({ context, profile: name2, seen: async () => "", pushedToo: true });
|
|
82931
|
-
const messages = due.length > 0 ? due : await
|
|
83227
|
+
const messages = due.length > 0 ? due : await takeRound2({ context, client, claudePid: 0, session });
|
|
82932
83228
|
if (messages.length === 0) return false;
|
|
82933
83229
|
await keepTaken({ context, profile: name2, messages });
|
|
82934
83230
|
const self2 = await currentNameOf({ context, client, profile: name2 });
|
|
@@ -82952,7 +83248,7 @@ async function rushWakeHook({ context, args }) {
|
|
|
82952
83248
|
while (context.processes.alive(claudePid)) await context.sleep(WATCH_MS3);
|
|
82953
83249
|
const { client, name: name2 } = await signedIn({ context, args });
|
|
82954
83250
|
const noted = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
|
|
82955
|
-
const session = await
|
|
83251
|
+
const session = await readFile32(noted, "utf8").then(
|
|
82956
83252
|
(text2) => JSON.parse(text2),
|
|
82957
83253
|
() => void 0
|
|
82958
83254
|
);
|
|
@@ -83118,8 +83414,8 @@ async function schedule({ context, args }) {
|
|
|
83118
83414
|
}
|
|
83119
83415
|
|
|
83120
83416
|
// src/services/skill-commands.service.ts
|
|
83121
|
-
import { readdir as
|
|
83122
|
-
import { join as
|
|
83417
|
+
import { readdir as readdir7, readFile as readFile33 } from "node:fs/promises";
|
|
83418
|
+
import { join as join22, relative as relative6, resolve as resolve12 } from "node:path";
|
|
83123
83419
|
var USAGE16 = `Usage:
|
|
83124
83420
|
laze skill list [--agent <agentId>]
|
|
83125
83421
|
laze skill install <catalogue-id> [--as <name>] [--agent <agentId>]
|
|
@@ -83136,12 +83432,12 @@ var USAGE16 = `Usage:
|
|
|
83136
83432
|
--agent names the agent with a person's key; an agent's key works on its own skills.
|
|
83137
83433
|
With a person's key, list without --agent shows every agent's skills.`;
|
|
83138
83434
|
async function folderFiles({ root }) {
|
|
83139
|
-
const entries = await
|
|
83435
|
+
const entries = await readdir7(root, { recursive: true, withFileTypes: true });
|
|
83140
83436
|
const files2 = [];
|
|
83141
83437
|
for (const entry of entries) {
|
|
83142
83438
|
if (!entry.isFile()) continue;
|
|
83143
|
-
const full =
|
|
83144
|
-
files2.push({ path: relative6(root, full), content: await
|
|
83439
|
+
const full = join22(entry.parentPath, entry.name);
|
|
83440
|
+
files2.push({ path: relative6(root, full), content: await readFile33(full, "utf8") });
|
|
83145
83441
|
}
|
|
83146
83442
|
return files2.toSorted((a, b) => a.path.localeCompare(b.path));
|
|
83147
83443
|
}
|
|
@@ -83239,7 +83535,7 @@ async function skillUpdate({ context, args }) {
|
|
|
83239
83535
|
if (!name2 || !newName && description === void 0 && !skillMdFile) {
|
|
83240
83536
|
throw new CliUsageError(USAGE16);
|
|
83241
83537
|
}
|
|
83242
|
-
const skillMd = skillMdFile ? await
|
|
83538
|
+
const skillMd = skillMdFile ? await readFile33(resolve12(context.cwd, skillMdFile), "utf8") : void 0;
|
|
83243
83539
|
const { client } = await signedIn({ context, args });
|
|
83244
83540
|
const updated = await client.post("/api/skills/update", {
|
|
83245
83541
|
name: name2,
|
|
@@ -83285,7 +83581,7 @@ async function skill({ context, args }) {
|
|
|
83285
83581
|
}
|
|
83286
83582
|
|
|
83287
83583
|
// src/services/slack-commands.service.ts
|
|
83288
|
-
import { readFile as
|
|
83584
|
+
import { readFile as readFile34 } from "node:fs/promises";
|
|
83289
83585
|
import { resolve as resolve13 } from "node:path";
|
|
83290
83586
|
var SLACK_USAGE = `Usage (a person's key; Slack stays the source, the bot joins no channel by itself):
|
|
83291
83587
|
laze slack overview connected Slack workspaces, mirrors, your link
|
|
@@ -83333,7 +83629,7 @@ async function secretLines({ context, args }) {
|
|
|
83333
83629
|
throw new CliUsageError("A secret never goes in a flag: pipe it on stdin or use --from-file.");
|
|
83334
83630
|
}
|
|
83335
83631
|
const file3 = flagText({ args, name: "from-file" });
|
|
83336
|
-
const text2 = file3 ? await
|
|
83632
|
+
const text2 = file3 ? await readFile34(resolve13(context.cwd, file3), "utf8") : await context.readStdin();
|
|
83337
83633
|
return text2.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
83338
83634
|
}
|
|
83339
83635
|
async function secretsOf({
|
|
@@ -83637,7 +83933,7 @@ async function slack({
|
|
|
83637
83933
|
}
|
|
83638
83934
|
|
|
83639
83935
|
// src/services/sso-commands.service.ts
|
|
83640
|
-
import { readFile as
|
|
83936
|
+
import { readFile as readFile35 } from "node:fs/promises";
|
|
83641
83937
|
var SSO_USAGE = `Usage:
|
|
83642
83938
|
laze sso domains claimed domains and how each signs in (admins)
|
|
83643
83939
|
laze sso claim <domain> the TXT record that proves the domain
|
|
@@ -83724,7 +84020,7 @@ function refuseSecretFlags({ args }) {
|
|
|
83724
84020
|
}
|
|
83725
84021
|
async function clientSecretOf({ context, args }) {
|
|
83726
84022
|
const file3 = flagText({ args, name: "from-file" });
|
|
83727
|
-
const text2 = file3 ? await
|
|
84023
|
+
const text2 = file3 ? await readFile35(file3, "utf8") : await context.readStdin();
|
|
83728
84024
|
const secret = text2.trim();
|
|
83729
84025
|
if (!secret) throw new CliUsageError("No client secret: pipe it on stdin or use --from-file.");
|
|
83730
84026
|
return secret;
|
|
@@ -84098,7 +84394,7 @@ async function vaultScrub({ context, args }) {
|
|
|
84098
84394
|
}
|
|
84099
84395
|
|
|
84100
84396
|
// src/services/whatsapp-business-commands.service.ts
|
|
84101
|
-
import { readFile as
|
|
84397
|
+
import { readFile as readFile36 } from "node:fs/promises";
|
|
84102
84398
|
import { resolve as resolve14 } from "node:path";
|
|
84103
84399
|
|
|
84104
84400
|
// ../../modules/whatsapp-business/contract/src/whatsapp-business.prices.ts
|
|
@@ -84518,7 +84814,7 @@ async function secretsOf2({ context, args }) {
|
|
|
84518
84814
|
const fromConnection = flagText({ args, name: "from-vault" });
|
|
84519
84815
|
if (fromConnection) return { fromConnection };
|
|
84520
84816
|
const file3 = flagText({ args, name: "from-file" });
|
|
84521
|
-
const text2 = file3 ? await
|
|
84817
|
+
const text2 = file3 ? await readFile36(resolve14(context.cwd, file3), "utf8") : await context.readStdin();
|
|
84522
84818
|
const lines = text2.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
84523
84819
|
if (lines.length !== 2) {
|
|
84524
84820
|
throw new CliUsageError(
|
|
@@ -85099,7 +85395,7 @@ async function flags({ context, args }) {
|
|
|
85099
85395
|
}
|
|
85100
85396
|
|
|
85101
85397
|
// src/services/workspace-commands.service.ts
|
|
85102
|
-
import { readFile as
|
|
85398
|
+
import { readFile as readFile37 } from "node:fs/promises";
|
|
85103
85399
|
import { resolve as resolve16 } from "node:path";
|
|
85104
85400
|
var ROLE_NAMES2 = {
|
|
85105
85401
|
OWNER: "Owner",
|
|
@@ -85282,7 +85578,7 @@ var LOGO_USAGE = "Usage: laze workspace logo set <file.png|jpg|webp> | laze work
|
|
|
85282
85578
|
async function readLogo({ context, file: file3 }) {
|
|
85283
85579
|
let bytes;
|
|
85284
85580
|
try {
|
|
85285
|
-
bytes = new Uint8Array(await
|
|
85581
|
+
bytes = new Uint8Array(await readFile37(resolve16(context.cwd, file3)));
|
|
85286
85582
|
} catch {
|
|
85287
85583
|
throw new CliUsageError(`No file to read at ${file3}.`);
|
|
85288
85584
|
}
|
|
@@ -85589,7 +85885,7 @@ var HELP = `laze: work in a Laze workspace from your terminal or your agent.
|
|
|
85589
85885
|
to your vault first; --save saves it without asking,
|
|
85590
85886
|
--as-is sends it raw, --keychain workspace saves it
|
|
85591
85887
|
for everyone
|
|
85592
|
-
laze inbox [--wait] [--timeout <s>]
|
|
85888
|
+
laze inbox [--wait] [--timeout <s>] [--take] messages addressed to your agent (--take: from outside its bound session)
|
|
85593
85889
|
laze search <query> [--channel <c>] [--limit <n>] search messages, and Slack when yours is linked
|
|
85594
85890
|
the sidebar's search: words, "phrases", from:@name in:#channel has: before: after: is:thread
|
|
85595
85891
|
laze history <channel> [--before <id>] [--limit <n>] a channel's messages, oldest first
|
|
@@ -85950,8 +86246,8 @@ async function runCli({
|
|
|
85950
86246
|
// src/services/processes.service.ts
|
|
85951
86247
|
import { execFile as execFile2, spawn as spawn4 } from "node:child_process";
|
|
85952
86248
|
import { mkdirSync, openSync } from "node:fs";
|
|
85953
|
-
import { readFile as
|
|
85954
|
-
import { dirname as
|
|
86249
|
+
import { readFile as readFile38, readlink } from "node:fs/promises";
|
|
86250
|
+
import { dirname as dirname21 } from "node:path";
|
|
85955
86251
|
import { promisify as promisify2 } from "node:util";
|
|
85956
86252
|
var run3 = promisify2(execFile2);
|
|
85957
86253
|
function alive(pid) {
|
|
@@ -85964,15 +86260,15 @@ function alive(pid) {
|
|
|
85964
86260
|
}
|
|
85965
86261
|
}
|
|
85966
86262
|
async function argsOf(pid) {
|
|
85967
|
-
const raw = await
|
|
86263
|
+
const raw = await readFile38(`/proc/${pid}/cmdline`, "utf8").catch(() => void 0);
|
|
85968
86264
|
if (raw) return raw.split("\0").filter(Boolean);
|
|
85969
86265
|
const listed = await run3("ps", ["-o", "args=", "-p", String(pid)]).catch(() => void 0);
|
|
85970
86266
|
const line = listed?.stdout.trim();
|
|
85971
86267
|
return line ? line.split(/\s+/) : void 0;
|
|
85972
86268
|
}
|
|
85973
86269
|
async function parentOf(pid) {
|
|
85974
|
-
const
|
|
85975
|
-
const fromStat =
|
|
86270
|
+
const stat5 = await readFile38(`/proc/${pid}/stat`, "utf8").catch(() => void 0);
|
|
86271
|
+
const fromStat = stat5 ? Number(stat5.slice(stat5.lastIndexOf(")") + 2).split(" ")[1]) : NaN;
|
|
85976
86272
|
if (fromStat > 0) return fromStat;
|
|
85977
86273
|
const listed = await run3("ps", ["-o", "ppid=", "-p", String(pid)]).catch(() => void 0);
|
|
85978
86274
|
const parent = Number(listed?.stdout.trim());
|
|
@@ -85988,7 +86284,7 @@ async function cwdOf(pid) {
|
|
|
85988
86284
|
return line ? line.slice(1) : void 0;
|
|
85989
86285
|
}
|
|
85990
86286
|
function spawnDetached({ argv, logPath }) {
|
|
85991
|
-
mkdirSync(
|
|
86287
|
+
mkdirSync(dirname21(logPath), { recursive: true, mode: 448 });
|
|
85992
86288
|
const log = openSync(logPath, "a", 384);
|
|
85993
86289
|
const [program = "", ...rest] = argv;
|
|
85994
86290
|
const child = spawn4(program, rest, { detached: true, stdio: ["ignore", log, log] });
|