@lazehq/cli 0.1.29 → 0.1.31
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 +1131 -834
- 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.31";
|
|
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"),
|
|
@@ -60942,17 +60978,17 @@ var computerBrowserStateSchemaDefinition = external_exports.object({ running: ex
|
|
|
60942
60978
|
var computerNoticeSchemaDefinition = external_exports.discriminatedUnion("type", [
|
|
60943
60979
|
external_exports.object({
|
|
60944
60980
|
type: external_exports.literal("memory_stop"),
|
|
60945
|
-
/** "stopped: your computer is out of memory (3.9 of 4 GB)". */
|
|
60981
|
+
/** "stopped: your agent computer is out of memory (3.9 of 4 GB)". */
|
|
60946
60982
|
text: external_exports.string().min(1).max(500)
|
|
60947
60983
|
}),
|
|
60948
60984
|
external_exports.object({
|
|
60949
60985
|
type: external_exports.literal("disk_warning"),
|
|
60950
|
-
/** "your computer's disk is 92% full (36.8 of 40 GB)". */
|
|
60986
|
+
/** "your agent computer's disk is 92% full (36.8 of 40 GB)". */
|
|
60951
60987
|
text: external_exports.string().min(1).max(500)
|
|
60952
60988
|
}),
|
|
60953
60989
|
external_exports.object({
|
|
60954
60990
|
type: external_exports.literal("disk_full"),
|
|
60955
|
-
/** "stopped: your computer's disk is full (40.1 of 40 GB)". */
|
|
60991
|
+
/** "stopped: your agent computer's disk is full (40.1 of 40 GB)". */
|
|
60956
60992
|
text: external_exports.string().min(1).max(500),
|
|
60957
60993
|
/** Whether one of this agent's commands was stopped for it. */
|
|
60958
60994
|
stopped: external_exports.boolean()
|
|
@@ -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) {
|
|
@@ -68045,396 +67964,21 @@ function rolloutEventOf({
|
|
|
68045
67964
|
return held.length > 0 ? { kind: "holds", messageIds: held } : void 0;
|
|
68046
67965
|
}
|
|
68047
67966
|
|
|
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
67967
|
// src/services/connect-delivery.service.ts
|
|
68424
|
-
import { mkdir as
|
|
67968
|
+
import { mkdir as mkdir7, readFile as readFile9, rename as rename3, rm as rm2, stat as stat2, writeFile as writeFile7 } from "node:fs/promises";
|
|
68425
67969
|
import { homedir as homedir2, hostname as hostname4 } from "node:os";
|
|
68426
|
-
import { dirname as
|
|
67970
|
+
import { dirname as dirname8, join as join10 } from "node:path";
|
|
68427
67971
|
|
|
68428
67972
|
// src/services/codex-turn-watch.service.ts
|
|
68429
|
-
import { open as open2, readdir as
|
|
68430
|
-
import { join as
|
|
67973
|
+
import { open as open2, readdir as readdir2 } from "node:fs/promises";
|
|
67974
|
+
import { join as join6 } from "node:path";
|
|
68431
67975
|
var READ_MS = 1500;
|
|
68432
67976
|
var KEEP_WORKING_MS = 3e4;
|
|
68433
67977
|
async function rolloutPathOf({ delivery }) {
|
|
68434
|
-
const root =
|
|
68435
|
-
const files2 = await
|
|
67978
|
+
const root = join6(delivery.codexHome, "sessions");
|
|
67979
|
+
const files2 = await readdir2(root, { recursive: true }).catch(() => []);
|
|
68436
67980
|
const file3 = files2.find((name2) => name2.endsWith(`-${delivery.threadId}.jsonl`));
|
|
68437
|
-
return file3 ?
|
|
67981
|
+
return file3 ? join6(root, file3) : void 0;
|
|
68438
67982
|
}
|
|
68439
67983
|
async function readFrom({ path, offset }) {
|
|
68440
67984
|
const handle = await open2(path, "r");
|
|
@@ -68520,8 +68064,8 @@ var CodexTurnWatch = class _CodexTurnWatch {
|
|
|
68520
68064
|
};
|
|
68521
68065
|
|
|
68522
68066
|
// src/services/openclaw-relay.service.ts
|
|
68523
|
-
import { chmod as chmod2, mkdir as
|
|
68524
|
-
import { dirname as
|
|
68067
|
+
import { chmod as chmod2, mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
|
|
68068
|
+
import { dirname as dirname5, join as join7 } from "node:path";
|
|
68525
68069
|
|
|
68526
68070
|
// ../../modules/openclaw/contract/src/openclaw.ts
|
|
68527
68071
|
var workspaceIdSchema14 = external_exports.string().min(1);
|
|
@@ -68749,11 +68293,11 @@ var STOPS = /* @__PURE__ */ new Map([
|
|
|
68749
68293
|
[OPENCLAW_RELAY_CLOSE.replaced.code, "another relay for this gateway took over"]
|
|
68750
68294
|
]);
|
|
68751
68295
|
function relaysPathOf({ context }) {
|
|
68752
|
-
return
|
|
68296
|
+
return join7(dirname5(context.environment.configPath), "connect", "openclaw-relays.json");
|
|
68753
68297
|
}
|
|
68754
68298
|
async function readRelays({ context }) {
|
|
68755
68299
|
try {
|
|
68756
|
-
return JSON.parse(await
|
|
68300
|
+
return JSON.parse(await readFile6(relaysPathOf({ context }), "utf8"));
|
|
68757
68301
|
} catch {
|
|
68758
68302
|
return {};
|
|
68759
68303
|
}
|
|
@@ -68763,8 +68307,8 @@ async function saveRelays({
|
|
|
68763
68307
|
relays
|
|
68764
68308
|
}) {
|
|
68765
68309
|
const path = relaysPathOf({ context });
|
|
68766
|
-
await
|
|
68767
|
-
await
|
|
68310
|
+
await mkdir5(dirname5(path), { recursive: true, mode: 448 });
|
|
68311
|
+
await writeFile5(path, `${JSON.stringify(relays, null, 2)}
|
|
68768
68312
|
`, { mode: 384 });
|
|
68769
68313
|
await chmod2(path, 384);
|
|
68770
68314
|
}
|
|
@@ -68948,16 +68492,148 @@ var RelayLoops = class _RelayLoops {
|
|
|
68948
68492
|
}
|
|
68949
68493
|
};
|
|
68950
68494
|
|
|
68495
|
+
// src/services/rush-listeners.service.ts
|
|
68496
|
+
import { readFile as readFile8, readdir as readdir3, stat } from "node:fs/promises";
|
|
68497
|
+
import { dirname as dirname7, join as join9 } from "node:path";
|
|
68498
|
+
|
|
68499
|
+
// src/services/rush-host.service.ts
|
|
68500
|
+
import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
68501
|
+
import { dirname as dirname6, join as join8 } from "node:path";
|
|
68502
|
+
async function rushAboveOf({
|
|
68503
|
+
context,
|
|
68504
|
+
from = context.processes.pid
|
|
68505
|
+
}) {
|
|
68506
|
+
let pid = await context.processes.parentOf(from);
|
|
68507
|
+
for (let depth = 0; pid !== void 0 && pid > 1 && depth < 16; depth += 1) {
|
|
68508
|
+
const rush = rushSessionOf({ parentArgs: await context.processes.argsOf(pid) });
|
|
68509
|
+
if (rush) return rush;
|
|
68510
|
+
pid = await context.processes.parentOf(pid);
|
|
68511
|
+
}
|
|
68512
|
+
return void 0;
|
|
68513
|
+
}
|
|
68514
|
+
function guardPathOf({ context, claudePid }) {
|
|
68515
|
+
return join8(dirname6(context.environment.configPath), "rush-guards", `${claudePid}.json`);
|
|
68516
|
+
}
|
|
68517
|
+
async function startRushGuard({
|
|
68518
|
+
context,
|
|
68519
|
+
profile,
|
|
68520
|
+
claudePid,
|
|
68521
|
+
rush
|
|
68522
|
+
}) {
|
|
68523
|
+
const path = guardPathOf({ context, claudePid });
|
|
68524
|
+
const holder = await guardHolderOf({ path });
|
|
68525
|
+
if (holder && context.processes.alive(holder.pid)) return;
|
|
68526
|
+
const flags2 = ["--profile", profile, "--claude-pid", String(claudePid), "--rush-id", rush.id];
|
|
68527
|
+
const argv = [...context.program, "hook", "rush-wake", ...flags2, "--rush-program", rush.program];
|
|
68528
|
+
const logPath = join8(dirname6(context.environment.configPath), "rush-guards", "guard.log");
|
|
68529
|
+
context.processes.spawnDetached({ argv: ["sh", "-c", '"$@" &', "sh", ...argv], logPath });
|
|
68530
|
+
}
|
|
68531
|
+
async function claimRushGuard({
|
|
68532
|
+
context,
|
|
68533
|
+
claudePid
|
|
68534
|
+
}) {
|
|
68535
|
+
const path = guardPathOf({ context, claudePid });
|
|
68536
|
+
const holder = await guardHolderOf({ path });
|
|
68537
|
+
const self2 = context.processes.pid;
|
|
68538
|
+
if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) return false;
|
|
68539
|
+
await mkdir6(dirname6(path), { recursive: true, mode: 448 });
|
|
68540
|
+
await writeFile6(path, JSON.stringify({ pid: self2, claudePid }), { mode: 384 });
|
|
68541
|
+
return true;
|
|
68542
|
+
}
|
|
68543
|
+
function guardHolderOf({ path }) {
|
|
68544
|
+
return readFile7(path, "utf8").then(
|
|
68545
|
+
(text2) => JSON.parse(text2),
|
|
68546
|
+
() => void 0
|
|
68547
|
+
);
|
|
68548
|
+
}
|
|
68549
|
+
|
|
68550
|
+
// src/services/rush-listeners.service.ts
|
|
68551
|
+
async function jsonOf(path) {
|
|
68552
|
+
return readFile8(path, "utf8").then(
|
|
68553
|
+
(text2) => JSON.parse(text2),
|
|
68554
|
+
() => void 0
|
|
68555
|
+
);
|
|
68556
|
+
}
|
|
68557
|
+
async function notesOf({ context }) {
|
|
68558
|
+
const folder = dirname7(statePathOf({ context, kind: "sessions", profile: "x" }));
|
|
68559
|
+
const files2 = await readdir3(folder).catch(() => []);
|
|
68560
|
+
const notes = await Promise.all(
|
|
68561
|
+
files2.map(async (file3) => {
|
|
68562
|
+
const pid = Number(file3.replace(/\.json$/, ""));
|
|
68563
|
+
const session = await jsonOf(join9(folder, file3));
|
|
68564
|
+
const at = await stat(join9(folder, file3)).then(
|
|
68565
|
+
(info) => info.mtimeMs,
|
|
68566
|
+
() => 0
|
|
68567
|
+
);
|
|
68568
|
+
return pid && session ? [{ pid, key: sessionKeyOf({ session }), at }] : [];
|
|
68569
|
+
})
|
|
68570
|
+
);
|
|
68571
|
+
return notes.flat().toSorted((a, b) => b.at - a.at);
|
|
68572
|
+
}
|
|
68573
|
+
async function rushListenersOf({
|
|
68574
|
+
context
|
|
68575
|
+
}) {
|
|
68576
|
+
const bound = Object.entries((await context.store.read()).sessions ?? {}).filter(
|
|
68577
|
+
([key]) => key.startsWith("claude-code:")
|
|
68578
|
+
);
|
|
68579
|
+
if (bound.length === 0) return [];
|
|
68580
|
+
const listed = await rushListingOf({ context });
|
|
68581
|
+
if (listed === void 0) return [];
|
|
68582
|
+
const sessions = rushListedOf({ listed });
|
|
68583
|
+
const notes = await notesOf({ context });
|
|
68584
|
+
const rows = [];
|
|
68585
|
+
for (const [key, profile] of bound) {
|
|
68586
|
+
const one = sessions.find((each) => `claude-code:${each.sessionId}` === key);
|
|
68587
|
+
if (!one?.id) continue;
|
|
68588
|
+
const pids = notes.filter((note) => note.key === key).map((note) => note.pid);
|
|
68589
|
+
const listenerPid = await listenerOf({ context, key, profile, pids });
|
|
68590
|
+
const lastClaudePid = pids.find((pid) => !context.processes.alive(pid));
|
|
68591
|
+
rows.push({
|
|
68592
|
+
profile,
|
|
68593
|
+
rushId: one.id,
|
|
68594
|
+
standing: rushStandingOf({ one }),
|
|
68595
|
+
...listenerPid ? { listenerPid } : {},
|
|
68596
|
+
...lastClaudePid ? { lastClaudePid } : {}
|
|
68597
|
+
});
|
|
68598
|
+
}
|
|
68599
|
+
return rows;
|
|
68600
|
+
}
|
|
68601
|
+
async function listenerOf({
|
|
68602
|
+
context,
|
|
68603
|
+
key,
|
|
68604
|
+
profile,
|
|
68605
|
+
pids
|
|
68606
|
+
}) {
|
|
68607
|
+
for (const claudePid of pids) {
|
|
68608
|
+
const guard = await jsonOf(guardPathOf({ context, claudePid }));
|
|
68609
|
+
if (guard && context.processes.alive(guard.pid)) return guard.pid;
|
|
68610
|
+
}
|
|
68611
|
+
const lock = statePathOf({ context, kind: "waiters", profile });
|
|
68612
|
+
const waiter = await jsonOf(lock);
|
|
68613
|
+
const mine4 = waiter?.sessionId === key.slice(key.indexOf(":") + 1);
|
|
68614
|
+
return waiter && mine4 && context.processes.alive(waiter.pid) ? waiter.pid : void 0;
|
|
68615
|
+
}
|
|
68616
|
+
async function rearmRushGuards({ context }) {
|
|
68617
|
+
let started = 0;
|
|
68618
|
+
for (const row of await rushListenersOf({ context })) {
|
|
68619
|
+
if (row.standing !== "asleep" || row.listenerPid || !row.lastClaudePid) continue;
|
|
68620
|
+
const rush = { id: row.rushId, program: "rush" };
|
|
68621
|
+
await startRushGuard({ context, profile: row.profile, claudePid: row.lastClaudePid, rush });
|
|
68622
|
+
started += 1;
|
|
68623
|
+
}
|
|
68624
|
+
return started;
|
|
68625
|
+
}
|
|
68626
|
+
|
|
68951
68627
|
// src/services/connect-delivery.service.ts
|
|
68952
68628
|
function connectFolderOf({ context }) {
|
|
68953
|
-
return join10(
|
|
68629
|
+
return join10(dirname8(context.environment.configPath), "connect");
|
|
68954
68630
|
}
|
|
68955
68631
|
function runStatePathOf({ context }) {
|
|
68956
68632
|
return join10(connectFolderOf({ context }), "run.json");
|
|
68957
68633
|
}
|
|
68958
68634
|
async function readJson({ path }) {
|
|
68959
68635
|
try {
|
|
68960
|
-
return JSON.parse(await
|
|
68636
|
+
return JSON.parse(await readFile9(path, "utf8"));
|
|
68961
68637
|
} catch {
|
|
68962
68638
|
return void 0;
|
|
68963
68639
|
}
|
|
@@ -68965,9 +68641,18 @@ async function readJson({ path }) {
|
|
|
68965
68641
|
async function runStateOf({ context }) {
|
|
68966
68642
|
return readJson({ path: runStatePathOf({ context }) });
|
|
68967
68643
|
}
|
|
68968
|
-
var
|
|
68644
|
+
var ROUND_SECONDS = 50;
|
|
68969
68645
|
var REFRESH_MS = 3e4;
|
|
68970
68646
|
var MAX_RETRY_SECONDS2 = 60;
|
|
68647
|
+
var CLI_CHANGED_EXIT = 75;
|
|
68648
|
+
async function cliStampOf({ context }) {
|
|
68649
|
+
const file3 = context.program.at(-1);
|
|
68650
|
+
if (!file3) return "";
|
|
68651
|
+
return stat2(file3).then(
|
|
68652
|
+
(info) => `${info.mtimeMs}:${info.size}`,
|
|
68653
|
+
() => ""
|
|
68654
|
+
);
|
|
68655
|
+
}
|
|
68971
68656
|
var CodexQueueError = class extends Error {
|
|
68972
68657
|
constructor(reason, detail) {
|
|
68973
68658
|
super(detail);
|
|
@@ -68998,7 +68683,7 @@ async function queueInCodex({
|
|
|
68998
68683
|
throw new CodexQueueError(codexQueueFailureOf({ stderr: stderr2 }), stderr2.trim() || `exit ${code}`);
|
|
68999
68684
|
}
|
|
69000
68685
|
}
|
|
69001
|
-
async function
|
|
68686
|
+
async function takeRound({
|
|
69002
68687
|
client,
|
|
69003
68688
|
signal,
|
|
69004
68689
|
delivery
|
|
@@ -69010,7 +68695,7 @@ async function takeRound2({
|
|
|
69010
68695
|
host: hostname4()
|
|
69011
68696
|
};
|
|
69012
68697
|
try {
|
|
69013
|
-
return await client.withHeaders(sessionHeadersOf({ session })).post("/api/agents/me/inbox", { waitSeconds:
|
|
68698
|
+
return await client.withHeaders(sessionHeadersOf({ session })).post("/api/agents/me/inbox", { waitSeconds: ROUND_SECONDS }, { signal });
|
|
69014
68699
|
} catch (error62) {
|
|
69015
68700
|
if (signal.aborted) return [];
|
|
69016
68701
|
throw error62;
|
|
@@ -69025,7 +68710,7 @@ async function deliverRound({
|
|
|
69025
68710
|
watch
|
|
69026
68711
|
}) {
|
|
69027
68712
|
const kept = await dueFromSpool({ context, profile, seen: async () => "", pushedToo: true });
|
|
69028
|
-
const messages = kept.length > 0 ? kept : await
|
|
68713
|
+
const messages = kept.length > 0 ? kept : await takeRound({ client, signal, delivery });
|
|
69029
68714
|
if (messages.length === 0) return 0;
|
|
69030
68715
|
if (kept.length === 0) await keepTaken({ context, profile, messages });
|
|
69031
68716
|
const self2 = await currentNameOf({ context, client, profile });
|
|
@@ -69108,9 +68793,9 @@ async function serveRounds({
|
|
|
69108
68793
|
}
|
|
69109
68794
|
var saves = 0;
|
|
69110
68795
|
async function save(run4) {
|
|
69111
|
-
await
|
|
68796
|
+
await mkdir7(dirname8(run4.path), { recursive: true, mode: 448 });
|
|
69112
68797
|
const temporary = `${run4.path}.${run4.self}.${saves += 1}.tmp`;
|
|
69113
|
-
await
|
|
68798
|
+
await writeFile7(temporary, JSON.stringify(run4.state));
|
|
69114
68799
|
await rename3(temporary, run4.path);
|
|
69115
68800
|
}
|
|
69116
68801
|
async function holdsLock(run4) {
|
|
@@ -69165,6 +68850,7 @@ async function runConnectLoop({ context }) {
|
|
|
69165
68850
|
await save(run4);
|
|
69166
68851
|
context.out(`laze connect run: pid ${self2}
|
|
69167
68852
|
`);
|
|
68853
|
+
const startedFrom = await cliStampOf({ context });
|
|
69168
68854
|
const relays = RelayLoops.create({
|
|
69169
68855
|
context,
|
|
69170
68856
|
report: async (connectionId, relay2) => {
|
|
@@ -69177,26 +68863,31 @@ async function runConnectLoop({ context }) {
|
|
|
69177
68863
|
while (await holdsLock(run4)) {
|
|
69178
68864
|
await syncLoops(run4);
|
|
69179
68865
|
await relays.sync();
|
|
68866
|
+
await rearmRushGuards({ context }).catch((error62) => {
|
|
68867
|
+
context.err(`laze connect: no rush guard check this round: ${String(error62)}
|
|
68868
|
+
`);
|
|
68869
|
+
});
|
|
69180
68870
|
await save(run4);
|
|
69181
68871
|
await context.sleep(REFRESH_MS);
|
|
68872
|
+
if (await cliStampOf({ context }) !== startedFrom) {
|
|
68873
|
+
context.out("laze connect run: the CLI changed on disk, exiting so the new one starts\n");
|
|
68874
|
+
return CLI_CHANGED_EXIT;
|
|
68875
|
+
}
|
|
69182
68876
|
}
|
|
69183
68877
|
} finally {
|
|
69184
68878
|
await relays.stopAll();
|
|
69185
68879
|
for (const current2 of run4.served.values()) current2.stop.abort();
|
|
69186
68880
|
await Promise.all([...run4.served.values()].map((current2) => current2.done));
|
|
69187
|
-
if (await holdsLock(run4)) await
|
|
68881
|
+
if (await holdsLock(run4)) await rm2(run4.path, { force: true });
|
|
69188
68882
|
}
|
|
69189
68883
|
return 0;
|
|
69190
68884
|
}
|
|
69191
68885
|
|
|
69192
68886
|
// 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.
|
|
68887
|
+
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
68888
|
|
|
69198
68889
|
laze connect install install and start it (systemd --user, a LaunchAgent, or detached)
|
|
69199
|
-
laze connect status whether it runs
|
|
68890
|
+
laze connect status whether it runs, which agents it serves, who listens per rush session
|
|
69200
68891
|
laze connect stop stop it until the next login or install
|
|
69201
68892
|
laze connect uninstall stop it and remove it
|
|
69202
68893
|
laze connect run the service itself, in the foreground
|
|
@@ -69211,7 +68902,7 @@ function logPathOf({ context }) {
|
|
|
69211
68902
|
return join11(connectFolderOf({ context }), "connect.log");
|
|
69212
68903
|
}
|
|
69213
68904
|
function homeOf({ context }) {
|
|
69214
|
-
return context.environment.inherited.HOME ??
|
|
68905
|
+
return context.environment.inherited.HOME ?? dirname9(dirname9(context.environment.configPath));
|
|
69215
68906
|
}
|
|
69216
68907
|
function serviceNameOf({ context }) {
|
|
69217
68908
|
const { configPath } = context.environment;
|
|
@@ -69240,8 +68931,8 @@ async function installSystemd({ context }) {
|
|
|
69240
68931
|
const env = context.environment.inherited;
|
|
69241
68932
|
const base = env.XDG_CONFIG_HOME || join11(homeOf({ context }), ".config");
|
|
69242
68933
|
const file3 = join11(base, "systemd", "user", `${name2}.service`);
|
|
69243
|
-
await
|
|
69244
|
-
await
|
|
68934
|
+
await mkdir8(dirname9(file3), { recursive: true });
|
|
68935
|
+
await writeFile8(
|
|
69245
68936
|
file3,
|
|
69246
68937
|
systemdUnitOf({ argv: runArgvOf({ context }), env: serviceEnvOf({ context }) })
|
|
69247
68938
|
);
|
|
@@ -69256,8 +68947,8 @@ async function installLaunchd({ context }) {
|
|
|
69256
68947
|
const label2 = `ai.laze.${name2}`;
|
|
69257
68948
|
const file3 = join11(homeOf({ context }), "Library", "LaunchAgents", `${label2}.plist`);
|
|
69258
68949
|
const log = logPathOf({ context });
|
|
69259
|
-
await
|
|
69260
|
-
await
|
|
68950
|
+
await mkdir8(dirname9(file3), { recursive: true });
|
|
68951
|
+
await writeFile8(
|
|
69261
68952
|
file3,
|
|
69262
68953
|
launchAgentOf({
|
|
69263
68954
|
label: label2,
|
|
@@ -69309,10 +69000,16 @@ async function installConnectService({ context }) {
|
|
|
69309
69000
|
const manager = await managerOf({ context });
|
|
69310
69001
|
const install = { systemd: installSystemd, launchd: installLaunchd, detached: installDetached };
|
|
69311
69002
|
const installed = await install[manager]({ context });
|
|
69312
|
-
await
|
|
69313
|
-
await
|
|
69003
|
+
await mkdir8(dirname9(path), { recursive: true, mode: 448 });
|
|
69004
|
+
await writeFile8(path, JSON.stringify(installed));
|
|
69314
69005
|
return describeInstalled({ installed });
|
|
69315
69006
|
}
|
|
69007
|
+
async function ensureConnectService({ context }) {
|
|
69008
|
+
const running = await runStateOf({ context });
|
|
69009
|
+
if (running && context.processes.alive(running.pid)) return false;
|
|
69010
|
+
await installConnectService({ context });
|
|
69011
|
+
return true;
|
|
69012
|
+
}
|
|
69316
69013
|
function describeInstalled({ installed }) {
|
|
69317
69014
|
switch (installed.manager) {
|
|
69318
69015
|
case "systemd":
|
|
@@ -69340,6 +69037,8 @@ async function status({ context }) {
|
|
|
69340
69037
|
`
|
|
69341
69038
|
);
|
|
69342
69039
|
}
|
|
69040
|
+
for (const row of await rushListenersOf({ context })) context.out(`${rushLineOf({ row })}
|
|
69041
|
+
`);
|
|
69343
69042
|
const config2 = await context.store.read();
|
|
69344
69043
|
const linked = Object.entries(config2.profiles).filter(([, profile]) => profile.delivery);
|
|
69345
69044
|
if (linked.length === 0) {
|
|
@@ -69352,6 +69051,13 @@ async function status({ context }) {
|
|
|
69352
69051
|
`);
|
|
69353
69052
|
}
|
|
69354
69053
|
}
|
|
69054
|
+
function rushLineOf({ row }) {
|
|
69055
|
+
const head = `${row.profile} Claude Code in rush ${row.rushId} ${row.standing}`;
|
|
69056
|
+
if (row.standing === "awake") return `${head}, its Claude Code delivers`;
|
|
69057
|
+
if (row.standing === "stopped") return `${head}, gets messages when rush starts it again`;
|
|
69058
|
+
if (row.listenerPid) return `${head}, guard pid ${row.listenerPid}`;
|
|
69059
|
+
return `${head}, NO LISTENER: messages wait in Laze; \`laze connect install\` brings a guard back`;
|
|
69060
|
+
}
|
|
69355
69061
|
async function stop({ context }) {
|
|
69356
69062
|
const installed = await readJson({ path: installedPathOf({ context }) });
|
|
69357
69063
|
if (!installed) {
|
|
@@ -69376,11 +69082,11 @@ async function uninstall({ context }) {
|
|
|
69376
69082
|
command: ["systemctl", "--user", "disable", `${installed.name}.service`]
|
|
69377
69083
|
});
|
|
69378
69084
|
}
|
|
69379
|
-
if (installed.file) await
|
|
69085
|
+
if (installed.file) await rm3(installed.file, { force: true });
|
|
69380
69086
|
if (installed.manager === "systemd") {
|
|
69381
69087
|
await run({ context, command: ["systemctl", "--user", "daemon-reload"] });
|
|
69382
69088
|
}
|
|
69383
|
-
await
|
|
69089
|
+
await rm3(path, { force: true });
|
|
69384
69090
|
context.out(
|
|
69385
69091
|
`Removed the connect service (${installed.manager}, ${installed.name}). Linked Codex agents get no messages until \`laze connect install\`.
|
|
69386
69092
|
`
|
|
@@ -69405,6 +69111,571 @@ async function connectService({ context, args }) {
|
|
|
69405
69111
|
}
|
|
69406
69112
|
}
|
|
69407
69113
|
|
|
69114
|
+
// src/services/claude-wait.service.ts
|
|
69115
|
+
var ROUND_SECONDS2 = 50;
|
|
69116
|
+
var WATCH_MS = 2e3;
|
|
69117
|
+
var CHANNEL_CHECK_MS = 5e3;
|
|
69118
|
+
async function holderOf({ path }) {
|
|
69119
|
+
return readFile10(path, "utf8").then(
|
|
69120
|
+
(text2) => JSON.parse(text2),
|
|
69121
|
+
() => void 0
|
|
69122
|
+
);
|
|
69123
|
+
}
|
|
69124
|
+
async function holderClaudeOf({ context, holder }) {
|
|
69125
|
+
if (holder.claudePid) return holder.claudePid;
|
|
69126
|
+
return (await nearestHarnessOf({ context, from: holder.pid }))?.pid;
|
|
69127
|
+
}
|
|
69128
|
+
async function takeLock({
|
|
69129
|
+
context,
|
|
69130
|
+
path,
|
|
69131
|
+
sessionId,
|
|
69132
|
+
claudePid,
|
|
69133
|
+
preempt = false
|
|
69134
|
+
}) {
|
|
69135
|
+
const holder = await holderOf({ path });
|
|
69136
|
+
const self2 = context.processes.pid;
|
|
69137
|
+
if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) {
|
|
69138
|
+
const served = await holderClaudeOf({ context, holder });
|
|
69139
|
+
const mine4 = preempt && served === claudePid && !holder.monitor;
|
|
69140
|
+
if (served && context.processes.alive(served) && !mine4) return false;
|
|
69141
|
+
context.processes.stop(holder.pid);
|
|
69142
|
+
}
|
|
69143
|
+
await mkdir9(dirname10(path), { recursive: true, mode: 448 });
|
|
69144
|
+
await writeFile9(
|
|
69145
|
+
path,
|
|
69146
|
+
JSON.stringify({
|
|
69147
|
+
pid: self2,
|
|
69148
|
+
claudePid,
|
|
69149
|
+
...sessionId ? { sessionId } : {},
|
|
69150
|
+
...preempt ? { monitor: true } : {}
|
|
69151
|
+
})
|
|
69152
|
+
);
|
|
69153
|
+
return true;
|
|
69154
|
+
}
|
|
69155
|
+
async function channelLive({ context, profile }) {
|
|
69156
|
+
const holder = await holderOf({ path: statePathOf({ context, kind: "channels", profile }) });
|
|
69157
|
+
return holder !== void 0 && context.processes.alive(holder.pid);
|
|
69158
|
+
}
|
|
69159
|
+
async function takeRound2({
|
|
69160
|
+
context,
|
|
69161
|
+
client,
|
|
69162
|
+
claudePid,
|
|
69163
|
+
session
|
|
69164
|
+
}) {
|
|
69165
|
+
const controller = new AbortController();
|
|
69166
|
+
const { signal } = controller;
|
|
69167
|
+
const watch = (async () => {
|
|
69168
|
+
while (!signal.aborted) {
|
|
69169
|
+
await context.sleep(WATCH_MS, signal);
|
|
69170
|
+
if (claudePid && !context.processes.alive(claudePid)) controller.abort();
|
|
69171
|
+
}
|
|
69172
|
+
})();
|
|
69173
|
+
try {
|
|
69174
|
+
return await forSession({ client, session }).post(
|
|
69175
|
+
"/api/agents/me/inbox",
|
|
69176
|
+
{ waitSeconds: ROUND_SECONDS2 },
|
|
69177
|
+
{ signal }
|
|
69178
|
+
);
|
|
69179
|
+
} catch (error62) {
|
|
69180
|
+
if (signal.aborted) return [];
|
|
69181
|
+
throw error62;
|
|
69182
|
+
} finally {
|
|
69183
|
+
controller.abort();
|
|
69184
|
+
await watch;
|
|
69185
|
+
}
|
|
69186
|
+
}
|
|
69187
|
+
async function roundOf({ context, client, name: name2, lock, claudePid, session, seen }) {
|
|
69188
|
+
if ((await holderOf({ path: lock }))?.pid !== context.processes.pid) return void 0;
|
|
69189
|
+
if (claudePid && !context.processes.alive(claudePid)) return void 0;
|
|
69190
|
+
const due = await dueFromSpool({ context, profile: name2, seen, pushedToo: true });
|
|
69191
|
+
if (due.length > 0) return due;
|
|
69192
|
+
if (await channelLive({ context, profile: name2 })) {
|
|
69193
|
+
await context.sleep(CHANNEL_CHECK_MS);
|
|
69194
|
+
return [];
|
|
69195
|
+
}
|
|
69196
|
+
const taken = await takeRound2({ context, client, claudePid, session });
|
|
69197
|
+
if (taken.length === 0) {
|
|
69198
|
+
await context.sleep(1e3);
|
|
69199
|
+
return [];
|
|
69200
|
+
}
|
|
69201
|
+
await keepTaken({ context, profile: name2, messages: taken });
|
|
69202
|
+
return taken;
|
|
69203
|
+
}
|
|
69204
|
+
async function claudePidOf({ context }) {
|
|
69205
|
+
const harness = await nearestHarnessOf({ context });
|
|
69206
|
+
if (harness?.harness === "claude-code") return harness.pid;
|
|
69207
|
+
return await context.processes.parentOf(context.processes.pid) ?? 0;
|
|
69208
|
+
}
|
|
69209
|
+
async function settleRound(round) {
|
|
69210
|
+
const { context, client, name: name2, session } = round;
|
|
69211
|
+
const messages = await roundOf(round).catch(async (error62) => {
|
|
69212
|
+
const refused = await notBoundNotice({
|
|
69213
|
+
context,
|
|
69214
|
+
client: forSession({ client, session }),
|
|
69215
|
+
session,
|
|
69216
|
+
error: error62,
|
|
69217
|
+
profile: name2
|
|
69218
|
+
});
|
|
69219
|
+
if (!refused) throw error62;
|
|
69220
|
+
return refused;
|
|
69221
|
+
});
|
|
69222
|
+
if (messages === void 0) return 0;
|
|
69223
|
+
if (!Array.isArray(messages)) {
|
|
69224
|
+
if (messages.rebound) return "again";
|
|
69225
|
+
if (!messages.notice) return 0;
|
|
69226
|
+
context.err(`${messages.notice}
|
|
69227
|
+
`);
|
|
69228
|
+
return 2;
|
|
69229
|
+
}
|
|
69230
|
+
if (messages.length === 0) return "again";
|
|
69231
|
+
await turnStarted({ context, client, agent: name2, messages }).catch(() => void 0);
|
|
69232
|
+
const self2 = await currentNameOf({ context, client, profile: name2 });
|
|
69233
|
+
context.err(`${hookContextOf({ messages, self: self2 })}
|
|
69234
|
+
`);
|
|
69235
|
+
const messageIds = messages.map((message2) => message2.messageId);
|
|
69236
|
+
await dropFromSpool({ context, profile: name2, messageIds });
|
|
69237
|
+
return 2;
|
|
69238
|
+
}
|
|
69239
|
+
async function waitForMessages({ context, args }) {
|
|
69240
|
+
const raw = await context.readStdin();
|
|
69241
|
+
const input2 = raw.trim() ? JSON.parse(raw) : {};
|
|
69242
|
+
const session = sessionOf({ context, harness: "claude-code", sessionId: input2.session_id });
|
|
69243
|
+
const claudePid = await claudePidOf({ context });
|
|
69244
|
+
const asked = await pluginHookArgs({ context, args, session, claudePid });
|
|
69245
|
+
if (!asked) return 0;
|
|
69246
|
+
const named = await sessionProfileArgs({ context, args: asked, session });
|
|
69247
|
+
const { client, name: name2 } = await signedIn({ context, args: named });
|
|
69248
|
+
await rememberSession({ context, claudePid, session });
|
|
69249
|
+
const rush = rushSessionOf({
|
|
69250
|
+
parentArgs: await context.processes.argsOf(await context.processes.parentOf(claudePid) ?? 0)
|
|
69251
|
+
});
|
|
69252
|
+
if (rush) await startRushGuard({ context, profile: name2, claudePid, rush });
|
|
69253
|
+
if (rush) await healRushDelivery({ context });
|
|
69254
|
+
const lock = statePathOf({ context, kind: "waiters", profile: name2 });
|
|
69255
|
+
if (!await takeLock({ context, path: lock, sessionId: input2.session_id, claudePid })) return 0;
|
|
69256
|
+
const seen = () => input2.transcript_path ? readFile10(input2.transcript_path, "utf8") : Promise.resolve("");
|
|
69257
|
+
const deadline = context.nowMs() + (WAIT_HOOK_TIMEOUT_SECONDS - 60) * 1e3;
|
|
69258
|
+
try {
|
|
69259
|
+
while (context.nowMs() < deadline) {
|
|
69260
|
+
const code = await settleRound({ context, client, name: name2, lock, claudePid, session, seen });
|
|
69261
|
+
if (code !== "again") return code;
|
|
69262
|
+
}
|
|
69263
|
+
return 0;
|
|
69264
|
+
} finally {
|
|
69265
|
+
if ((await holderOf({ path: lock }))?.pid === context.processes.pid)
|
|
69266
|
+
await rm4(lock, { force: true });
|
|
69267
|
+
}
|
|
69268
|
+
}
|
|
69269
|
+
async function healRushDelivery({ context }) {
|
|
69270
|
+
await rearmRushGuards({ context }).catch((error62) => {
|
|
69271
|
+
context.err(`laze: could not check the other rush sessions: ${String(error62)}
|
|
69272
|
+
`);
|
|
69273
|
+
});
|
|
69274
|
+
await ensureConnectService({ context }).catch((error62) => {
|
|
69275
|
+
context.err(`laze: could not start the connect service: ${String(error62)}
|
|
69276
|
+
`);
|
|
69277
|
+
});
|
|
69278
|
+
}
|
|
69279
|
+
async function waitHook({ context, args }) {
|
|
69280
|
+
try {
|
|
69281
|
+
return await waitForMessages({ context, args });
|
|
69282
|
+
} catch (error62) {
|
|
69283
|
+
context.err(`laze: the background waiter stopped: ${String(error62)}
|
|
69284
|
+
`);
|
|
69285
|
+
return 0;
|
|
69286
|
+
}
|
|
69287
|
+
}
|
|
69288
|
+
async function monitorServes({
|
|
69289
|
+
context,
|
|
69290
|
+
profile,
|
|
69291
|
+
claudePid
|
|
69292
|
+
}) {
|
|
69293
|
+
const holder = await holderOf({ path: statePathOf({ context, kind: "waiters", profile }) });
|
|
69294
|
+
if (!holder?.monitor || !context.processes.alive(holder.pid)) return false;
|
|
69295
|
+
return await holderClaudeOf({ context, holder }) === claudePid;
|
|
69296
|
+
}
|
|
69297
|
+
|
|
69298
|
+
// src/services/codex-link.service.ts
|
|
69299
|
+
import { createReadStream } from "node:fs";
|
|
69300
|
+
import { readdir as readdir5, rm as rm6, stat as stat4 } from "node:fs/promises";
|
|
69301
|
+
import { join as join13, resolve as resolve3 } from "node:path";
|
|
69302
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
69303
|
+
|
|
69304
|
+
// src/services/codex-adopt.service.ts
|
|
69305
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
69306
|
+
import { mkdir as mkdir10, readdir as readdir4, readFile as readFile11, rm as rm5, stat as stat3, writeFile as writeFile10 } from "node:fs/promises";
|
|
69307
|
+
import { dirname as dirname11, join as join12 } from "node:path";
|
|
69308
|
+
import { createInterface } from "node:readline";
|
|
69309
|
+
|
|
69310
|
+
// src/rules/codex-requests.rules.ts
|
|
69311
|
+
var DECLINED_DECISION = {
|
|
69312
|
+
"item/commandExecution/requestApproval": "decline",
|
|
69313
|
+
"item/fileChange/requestApproval": "decline",
|
|
69314
|
+
execCommandApproval: "denied",
|
|
69315
|
+
applyPatchApproval: "denied"
|
|
69316
|
+
};
|
|
69317
|
+
function codexRequestReplyOf({ method }) {
|
|
69318
|
+
const decision = DECLINED_DECISION[method];
|
|
69319
|
+
if (decision) return { result: { decision } };
|
|
69320
|
+
if (method === "item/permissions/requestApproval") {
|
|
69321
|
+
return { result: { permissions: {}, scope: "turn" } };
|
|
69322
|
+
}
|
|
69323
|
+
if (method === "mcpServer/elicitation/request") {
|
|
69324
|
+
return { result: { action: "decline", content: null } };
|
|
69325
|
+
}
|
|
69326
|
+
return { error: { code: -32601, message: `${method} is not supported here` } };
|
|
69327
|
+
}
|
|
69328
|
+
|
|
69329
|
+
// src/services/codex-adopt.service.ts
|
|
69330
|
+
function record3(value) {
|
|
69331
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
69332
|
+
}
|
|
69333
|
+
function absorbTurnEvent({ result, message: message2 }) {
|
|
69334
|
+
const params = record3(message2.params);
|
|
69335
|
+
if (message2.method === "item/completed") {
|
|
69336
|
+
const item = record3(params.item);
|
|
69337
|
+
if (item.type === "agentMessage" && typeof item.text === "string") result.answer = item.text;
|
|
69338
|
+
return;
|
|
69339
|
+
}
|
|
69340
|
+
if (message2.method !== "thread/tokenUsage/updated") return;
|
|
69341
|
+
const usage = record3(params.tokenUsage);
|
|
69342
|
+
const total = record3(usage.last).totalTokens;
|
|
69343
|
+
if (typeof total === "number") result.contextTokens = total;
|
|
69344
|
+
const window2 = usage.modelContextWindow;
|
|
69345
|
+
if (typeof window2 === "number" && window2 > 0) result.contextWindow = window2;
|
|
69346
|
+
}
|
|
69347
|
+
var TURN_HEARTBEAT_MS = 1e4;
|
|
69348
|
+
var CodexAppServer = class _CodexAppServer {
|
|
69349
|
+
constructor(child) {
|
|
69350
|
+
this.child = child;
|
|
69351
|
+
createInterface({ input: child.stdout }).on("line", (line) => this.receive(line));
|
|
69352
|
+
}
|
|
69353
|
+
child;
|
|
69354
|
+
#nextId = 0;
|
|
69355
|
+
#pending = /* @__PURE__ */ new Map();
|
|
69356
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
69357
|
+
static start({
|
|
69358
|
+
codexHome,
|
|
69359
|
+
inherited
|
|
69360
|
+
}) {
|
|
69361
|
+
const env = { ...inherited, CODEX_HOME: codexHome };
|
|
69362
|
+
return new _CodexAppServer(spawn2("codex", ["app-server"], { env, stdio: "pipe" }));
|
|
69363
|
+
}
|
|
69364
|
+
async call(method, params) {
|
|
69365
|
+
const id = ++this.#nextId;
|
|
69366
|
+
const reply2 = await new Promise((resolve17) => {
|
|
69367
|
+
this.#pending.set(id, resolve17);
|
|
69368
|
+
this.write({ id, method, params });
|
|
69369
|
+
});
|
|
69370
|
+
if (reply2.error !== void 0) throw new Error(`${method}: ${JSON.stringify(reply2.error)}`);
|
|
69371
|
+
return record3(reply2.result);
|
|
69372
|
+
}
|
|
69373
|
+
notify(method) {
|
|
69374
|
+
this.write({ method });
|
|
69375
|
+
}
|
|
69376
|
+
/** Starts one turn; `done` settles when it completes, keeping its last agent message. */
|
|
69377
|
+
async startTurn({ threadId, text: text2 }) {
|
|
69378
|
+
const result = { answer: "" };
|
|
69379
|
+
const done = new Promise((resolve17) => {
|
|
69380
|
+
const listen = (message2) => {
|
|
69381
|
+
absorbTurnEvent({ result, message: message2 });
|
|
69382
|
+
if (message2.method !== "turn/completed") return;
|
|
69383
|
+
this.#listeners.delete(listen);
|
|
69384
|
+
resolve17(result);
|
|
69385
|
+
};
|
|
69386
|
+
this.#listeners.add(listen);
|
|
69387
|
+
});
|
|
69388
|
+
const started = await this.call("turn/start", {
|
|
69389
|
+
threadId,
|
|
69390
|
+
input: [{ type: "text", text: text2, text_elements: [] }]
|
|
69391
|
+
});
|
|
69392
|
+
const turnId = record3(started.turn).id;
|
|
69393
|
+
return { turnId: typeof turnId === "string" ? turnId : null, done };
|
|
69394
|
+
}
|
|
69395
|
+
stop() {
|
|
69396
|
+
this.child.kill("SIGTERM");
|
|
69397
|
+
}
|
|
69398
|
+
write(message2) {
|
|
69399
|
+
this.child.stdin.write(`${JSON.stringify(message2)}
|
|
69400
|
+
`);
|
|
69401
|
+
}
|
|
69402
|
+
receive(line) {
|
|
69403
|
+
let message2;
|
|
69404
|
+
try {
|
|
69405
|
+
message2 = record3(JSON.parse(line));
|
|
69406
|
+
} catch {
|
|
69407
|
+
return;
|
|
69408
|
+
}
|
|
69409
|
+
if (typeof message2.id === "number" && message2.method === void 0) {
|
|
69410
|
+
this.#pending.get(message2.id)?.(message2);
|
|
69411
|
+
this.#pending.delete(message2.id);
|
|
69412
|
+
return;
|
|
69413
|
+
}
|
|
69414
|
+
if (message2.method !== void 0 && message2.id !== void 0) {
|
|
69415
|
+
this.write({
|
|
69416
|
+
id: message2.id,
|
|
69417
|
+
...codexRequestReplyOf({
|
|
69418
|
+
method: typeof message2.method === "string" ? message2.method : ""
|
|
69419
|
+
})
|
|
69420
|
+
});
|
|
69421
|
+
return;
|
|
69422
|
+
}
|
|
69423
|
+
for (const listen of this.#listeners) listen(message2);
|
|
69424
|
+
}
|
|
69425
|
+
};
|
|
69426
|
+
async function newestThreadId({ codexHome }) {
|
|
69427
|
+
const root = join12(codexHome, "sessions");
|
|
69428
|
+
const files2 = await readdir4(root, { recursive: true }).catch(() => []);
|
|
69429
|
+
const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
|
|
69430
|
+
const dated = await Promise.all(
|
|
69431
|
+
rollouts.map(async (file3) => ({ file: file3, at: (await stat3(join12(root, file3))).mtimeMs }))
|
|
69432
|
+
);
|
|
69433
|
+
const newest = dated.toSorted((a, b) => b.at - a.at)[0]?.file ?? "";
|
|
69434
|
+
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);
|
|
69435
|
+
if (!id?.[1]) throw new CliUsageError("No Codex session found: pass --thread <id>.");
|
|
69436
|
+
return id[1];
|
|
69437
|
+
}
|
|
69438
|
+
function promptOf({ message: message2, self: self2 }) {
|
|
69439
|
+
return [
|
|
69440
|
+
`A message reached you in the Laze workspace${selfClauseOf({ self: self2 })}. Answer it; your final`,
|
|
69441
|
+
"message is posted as your reply in its thread.",
|
|
69442
|
+
"",
|
|
69443
|
+
formatInboxMessage({ message: message2 }).split("\n").slice(0, -1).join("\n")
|
|
69444
|
+
].join("\n");
|
|
69445
|
+
}
|
|
69446
|
+
async function heartbeat({
|
|
69447
|
+
client,
|
|
69448
|
+
message: message2,
|
|
69449
|
+
state
|
|
69450
|
+
}) {
|
|
69451
|
+
return client.post("/api/agents/me/turn", {
|
|
69452
|
+
channelId: message2.channelId,
|
|
69453
|
+
threadRootId: message2.threadRootId,
|
|
69454
|
+
state,
|
|
69455
|
+
...state === "working" ? { messageId: message2.messageId } : {}
|
|
69456
|
+
}).catch(() => void 0);
|
|
69457
|
+
}
|
|
69458
|
+
async function watchTurn({
|
|
69459
|
+
context,
|
|
69460
|
+
client,
|
|
69461
|
+
codex,
|
|
69462
|
+
threadId,
|
|
69463
|
+
turn,
|
|
69464
|
+
message: message2
|
|
69465
|
+
}) {
|
|
69466
|
+
const finished = new AbortController();
|
|
69467
|
+
void turn.done.then(() => finished.abort());
|
|
69468
|
+
while (!finished.signal.aborted) {
|
|
69469
|
+
const beat2 = await heartbeat({ client, message: message2, state: "working" });
|
|
69470
|
+
if (beat2?.stop && turn.turnId) {
|
|
69471
|
+
await codex.call("turn/interrupt", { threadId, turnId: turn.turnId }).catch(() => void 0);
|
|
69472
|
+
return beat2.stoppedBy ?? "someone";
|
|
69473
|
+
}
|
|
69474
|
+
await context.sleep(TURN_HEARTBEAT_MS, finished.signal);
|
|
69475
|
+
}
|
|
69476
|
+
return void 0;
|
|
69477
|
+
}
|
|
69478
|
+
async function answer({
|
|
69479
|
+
context,
|
|
69480
|
+
codex,
|
|
69481
|
+
client,
|
|
69482
|
+
threadId,
|
|
69483
|
+
message: message2,
|
|
69484
|
+
profile
|
|
69485
|
+
}) {
|
|
69486
|
+
const self2 = await currentNameOf({ context, client, profile });
|
|
69487
|
+
const running = await codex.startTurn({ threadId, text: promptOf({ message: message2, self: self2 }) });
|
|
69488
|
+
const stoppedBy = await watchTurn({ context, client, codex, threadId, turn: running, message: message2 });
|
|
69489
|
+
const turn = await running.done;
|
|
69490
|
+
await heartbeat({ client, message: message2, state: "idle" });
|
|
69491
|
+
if (stoppedBy !== void 0) return `(stopped by ${stoppedBy})`;
|
|
69492
|
+
const body = turn.answer.trim() || "(no answer)";
|
|
69493
|
+
await client.post("/api/agents/me/replies", { messageId: message2.messageId, body });
|
|
69494
|
+
if (turn.contextTokens !== void 0) {
|
|
69495
|
+
await client.post("/api/agents/me/activity", {
|
|
69496
|
+
sessionId: threadId,
|
|
69497
|
+
contextTokens: turn.contextTokens,
|
|
69498
|
+
...turn.contextWindow ? { contextWindow: turn.contextWindow } : {}
|
|
69499
|
+
});
|
|
69500
|
+
}
|
|
69501
|
+
return body;
|
|
69502
|
+
}
|
|
69503
|
+
var MAX_RESTART_WAIT_SECONDS = 60;
|
|
69504
|
+
var HEALTHY_RUN_MS = 6e4;
|
|
69505
|
+
async function recordOf({ path }) {
|
|
69506
|
+
return readFile11(path, "utf8").then(
|
|
69507
|
+
(text2) => JSON.parse(text2),
|
|
69508
|
+
() => void 0
|
|
69509
|
+
);
|
|
69510
|
+
}
|
|
69511
|
+
function threadFlag({ thread: thread2 }) {
|
|
69512
|
+
return thread2 ? ["--thread", thread2] : [];
|
|
69513
|
+
}
|
|
69514
|
+
async function startAdoptInBackground({
|
|
69515
|
+
context,
|
|
69516
|
+
args,
|
|
69517
|
+
profile,
|
|
69518
|
+
laze
|
|
69519
|
+
}) {
|
|
69520
|
+
const thread2 = flagText({ args, name: "thread" }) || context.environment.inherited.CODEX_THREAD_ID || null;
|
|
69521
|
+
const path = statePathOf({ context, kind: "adopt", profile });
|
|
69522
|
+
const log = statePathOf({ context, kind: "adopt", profile, extension: "log" });
|
|
69523
|
+
const running = await recordOf({ path });
|
|
69524
|
+
if (running) context.processes.stop(running.pid);
|
|
69525
|
+
const adopt = ["adopt", "codex", "--profile", profile, ...threadFlag({ thread: thread2 })];
|
|
69526
|
+
const argv = [...context.program, ...adopt, "--supervise"];
|
|
69527
|
+
const pid = context.processes.spawnDetached({ argv, logPath: log });
|
|
69528
|
+
await mkdir10(dirname11(path), { recursive: true, mode: 448 });
|
|
69529
|
+
await writeFile10(path, JSON.stringify({ pid, thread: thread2, log, startedAt: context.nowMs() }));
|
|
69530
|
+
return [
|
|
69531
|
+
`Started \`${laze} adopt codex\` in the background (pid ${pid}). It answers each Laze message`,
|
|
69532
|
+
`as a turn in ${thread2 ? `this Codex thread (${thread2})` : "the newest Codex thread"}, and starts again if it stops.`,
|
|
69533
|
+
`Log: ${log}`,
|
|
69534
|
+
` ${laze} adopt codex --status --profile ${profile} shows whether it runs`,
|
|
69535
|
+
` ${laze} adopt codex --stop --profile ${profile} stops it`,
|
|
69536
|
+
"Nothing else needs to run. While this Codex window stays open, Codex lets only it write the",
|
|
69537
|
+
"thread, so adopt answers in a fork of it (the same history so far; `codex resume <fork id>`",
|
|
69538
|
+
"from the log opens it). Started again with this window closed, it answers in the thread itself."
|
|
69539
|
+
].join("\n");
|
|
69540
|
+
}
|
|
69541
|
+
async function supervise({
|
|
69542
|
+
context,
|
|
69543
|
+
args,
|
|
69544
|
+
profile
|
|
69545
|
+
}) {
|
|
69546
|
+
const path = statePathOf({ context, kind: "adopt", profile });
|
|
69547
|
+
const thread2 = flagText({ args, name: "thread" });
|
|
69548
|
+
const adopt = ["adopt", "codex", "--profile", profile, ...threadFlag({ thread: thread2 })];
|
|
69549
|
+
const command = [...context.program, ...adopt];
|
|
69550
|
+
let wait = 1;
|
|
69551
|
+
while ((await recordOf({ path }))?.pid === context.processes.pid) {
|
|
69552
|
+
const started = context.nowMs();
|
|
69553
|
+
context.out(
|
|
69554
|
+
`${Temporal3.Instant.fromEpochMilliseconds(started).toString()} starting laze adopt codex
|
|
69555
|
+
`
|
|
69556
|
+
);
|
|
69557
|
+
const code = await context.runCommand({ command, env: {} }).catch(() => 1);
|
|
69558
|
+
if (context.nowMs() - started > HEALTHY_RUN_MS) wait = 1;
|
|
69559
|
+
if ((await recordOf({ path }))?.pid !== context.processes.pid) break;
|
|
69560
|
+
context.out(`laze adopt codex exited ${code}; starting it again in ${wait}s
|
|
69561
|
+
`);
|
|
69562
|
+
await context.sleep(wait * 1e3);
|
|
69563
|
+
wait = Math.min(MAX_RESTART_WAIT_SECONDS, wait * 2);
|
|
69564
|
+
}
|
|
69565
|
+
return 0;
|
|
69566
|
+
}
|
|
69567
|
+
async function adoptStatus({ context, profile }) {
|
|
69568
|
+
const record4 = await recordOf({ path: statePathOf({ context, kind: "adopt", profile }) });
|
|
69569
|
+
if (!record4 || !context.processes.alive(record4.pid)) {
|
|
69570
|
+
context.out(`laze adopt codex does not run in the background for profile "${profile}".
|
|
69571
|
+
`);
|
|
69572
|
+
return;
|
|
69573
|
+
}
|
|
69574
|
+
const thread2 = record4.thread ?? "the newest thread";
|
|
69575
|
+
context.out(
|
|
69576
|
+
`laze adopt codex runs in the background for profile "${profile}" (pid ${record4.pid}), thread ${thread2}.
|
|
69577
|
+
Log: ${record4.log}
|
|
69578
|
+
`
|
|
69579
|
+
);
|
|
69580
|
+
}
|
|
69581
|
+
async function adoptStop({ context, profile }) {
|
|
69582
|
+
const path = statePathOf({ context, kind: "adopt", profile });
|
|
69583
|
+
const record4 = await recordOf({ path });
|
|
69584
|
+
await rm5(path, { force: true });
|
|
69585
|
+
if (!record4 || !context.processes.stop(record4.pid)) {
|
|
69586
|
+
context.out(`laze adopt codex was not running in the background for profile "${profile}".
|
|
69587
|
+
`);
|
|
69588
|
+
return;
|
|
69589
|
+
}
|
|
69590
|
+
context.out(`Stopped laze adopt codex (pid ${record4.pid}) for profile "${profile}".
|
|
69591
|
+
`);
|
|
69592
|
+
}
|
|
69593
|
+
var HELD_THREAD = /active writer/;
|
|
69594
|
+
async function adoptedThreadOf({
|
|
69595
|
+
context,
|
|
69596
|
+
codex,
|
|
69597
|
+
threadId,
|
|
69598
|
+
profile
|
|
69599
|
+
}) {
|
|
69600
|
+
const held = await codex.call("thread/resume", { threadId }).then(
|
|
69601
|
+
() => false,
|
|
69602
|
+
(error62) => {
|
|
69603
|
+
if (HELD_THREAD.test(String(error62))) return true;
|
|
69604
|
+
throw error62;
|
|
69605
|
+
}
|
|
69606
|
+
);
|
|
69607
|
+
if (!held) return threadId;
|
|
69608
|
+
const path = statePathOf({ context, kind: "adopt", profile, extension: "forks.json" });
|
|
69609
|
+
const forks = await readFile11(path, "utf8").then(
|
|
69610
|
+
(text2) => JSON.parse(text2),
|
|
69611
|
+
() => ({})
|
|
69612
|
+
);
|
|
69613
|
+
const known = forks[threadId];
|
|
69614
|
+
if (known && await codex.call("thread/resume", { threadId: known }).then(
|
|
69615
|
+
() => true,
|
|
69616
|
+
() => false
|
|
69617
|
+
)) {
|
|
69618
|
+
context.out(`Codex holds thread ${threadId} open elsewhere; answering in its fork ${known}.
|
|
69619
|
+
`);
|
|
69620
|
+
return known;
|
|
69621
|
+
}
|
|
69622
|
+
const forked = record3((await codex.call("thread/fork", { threadId })).thread).id;
|
|
69623
|
+
if (typeof forked !== "string") throw new Error("thread/fork answered no thread id");
|
|
69624
|
+
await mkdir10(dirname11(path), { recursive: true, mode: 448 });
|
|
69625
|
+
await writeFile10(path, JSON.stringify({ ...forks, [threadId]: forked }));
|
|
69626
|
+
context.out(
|
|
69627
|
+
`Codex holds thread ${threadId} open elsewhere; answering in its new fork ${forked}.
|
|
69628
|
+
`
|
|
69629
|
+
);
|
|
69630
|
+
return forked;
|
|
69631
|
+
}
|
|
69632
|
+
async function adoptCodex({ context, args }) {
|
|
69633
|
+
if (args.words[1] !== "codex") {
|
|
69634
|
+
throw new CliUsageError("Usage: laze adopt codex [--thread <id>] | --status | --stop");
|
|
69635
|
+
}
|
|
69636
|
+
const { client, name: name2 } = await signedIn({ context, args });
|
|
69637
|
+
if (args.flags.status) return adoptStatus({ context, profile: name2 });
|
|
69638
|
+
if (args.flags.stop) return adoptStop({ context, profile: name2 });
|
|
69639
|
+
if (args.flags.supervise) return supervise({ context, args, profile: name2 });
|
|
69640
|
+
const { codexHome } = context.environment;
|
|
69641
|
+
const threadId = flagText({ args, name: "thread" }) || context.environment.inherited.CODEX_THREAD_ID || await newestThreadId({ codexHome });
|
|
69642
|
+
const once = Boolean(args.flags.once);
|
|
69643
|
+
const codex = CodexAppServer.start({ codexHome, inherited: context.environment.inherited });
|
|
69644
|
+
try {
|
|
69645
|
+
await codex.call("initialize", {
|
|
69646
|
+
clientInfo: { name: "laze", title: "Laze", version: "1" },
|
|
69647
|
+
capabilities: null
|
|
69648
|
+
});
|
|
69649
|
+
codex.notify("initialized");
|
|
69650
|
+
const adopted = await adoptedThreadOf({ context, codex, threadId, profile: name2 });
|
|
69651
|
+
context.out(`Adopted Codex thread ${adopted}; answering Laze messages.
|
|
69652
|
+
`);
|
|
69653
|
+
const timeout = Number(flagText({ args, name: "timeout", fallback: "0" }));
|
|
69654
|
+
do {
|
|
69655
|
+
const messages = await receiveMessages({
|
|
69656
|
+
context,
|
|
69657
|
+
client,
|
|
69658
|
+
waitSeconds: timeout > 0 ? timeout : Infinity
|
|
69659
|
+
});
|
|
69660
|
+
for (const message2 of messages) {
|
|
69661
|
+
const body = await answer({
|
|
69662
|
+
context,
|
|
69663
|
+
codex,
|
|
69664
|
+
client,
|
|
69665
|
+
threadId: adopted,
|
|
69666
|
+
message: message2,
|
|
69667
|
+
profile: name2
|
|
69668
|
+
});
|
|
69669
|
+
context.out(`Answered ${message2.messageId}: ${body.slice(0, 120)}
|
|
69670
|
+
`);
|
|
69671
|
+
}
|
|
69672
|
+
if (messages.length === 0 && timeout > 0) break;
|
|
69673
|
+
} while (!once);
|
|
69674
|
+
} finally {
|
|
69675
|
+
codex.stop();
|
|
69676
|
+
}
|
|
69677
|
+
}
|
|
69678
|
+
|
|
69408
69679
|
// src/services/codex-link.service.ts
|
|
69409
69680
|
var ROLLOUTS_READ = 200;
|
|
69410
69681
|
async function firstLineOf({ path }) {
|
|
@@ -69422,13 +69693,13 @@ async function newestThreadIn({
|
|
|
69422
69693
|
codexHome,
|
|
69423
69694
|
directory
|
|
69424
69695
|
}) {
|
|
69425
|
-
const root =
|
|
69426
|
-
const files2 = await
|
|
69696
|
+
const root = join13(codexHome, "sessions");
|
|
69697
|
+
const files2 = await readdir5(root, { recursive: true }).catch(() => []);
|
|
69427
69698
|
const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
|
|
69428
69699
|
const dated = await Promise.all(
|
|
69429
69700
|
rollouts.map(async (file3) => ({
|
|
69430
|
-
path:
|
|
69431
|
-
at: await
|
|
69701
|
+
path: join13(root, file3),
|
|
69702
|
+
at: await stat4(join13(root, file3)).then(
|
|
69432
69703
|
(info) => info.mtimeMs,
|
|
69433
69704
|
() => 0
|
|
69434
69705
|
)
|
|
@@ -69498,9 +69769,9 @@ async function linkCodexSession({
|
|
|
69498
69769
|
}
|
|
69499
69770
|
|
|
69500
69771
|
// src/services/laze-plugin.service.ts
|
|
69501
|
-
import { mkdir as mkdir11, readFile as
|
|
69772
|
+
import { mkdir as mkdir11, readFile as readFile12, writeFile as writeFile11 } from "node:fs/promises";
|
|
69502
69773
|
import { homedir as homedir3 } from "node:os";
|
|
69503
|
-
import { dirname as
|
|
69774
|
+
import { dirname as dirname12, join as join14 } from "node:path";
|
|
69504
69775
|
|
|
69505
69776
|
// src/rules/laze-plugin.rules.ts
|
|
69506
69777
|
var LAZE_PLUGIN = "laze";
|
|
@@ -69616,11 +69887,11 @@ function lazePluginFiles({
|
|
|
69616
69887
|
var REGISTER_LIMIT_MS = 6e4;
|
|
69617
69888
|
var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
69618
69889
|
function pluginFolderOf({ context }) {
|
|
69619
|
-
return
|
|
69890
|
+
return join14(dirname12(context.environment.configPath), "plugins");
|
|
69620
69891
|
}
|
|
69621
69892
|
async function pluginIsCurrent({ context }) {
|
|
69622
|
-
const manifest =
|
|
69623
|
-
const written = await
|
|
69893
|
+
const manifest = join14(pluginFolderOf({ context }), LAZE_PLUGIN, ".claude-plugin", "plugin.json");
|
|
69894
|
+
const written = await readFile12(manifest, "utf8").then(
|
|
69624
69895
|
(text2) => JSON.parse(text2).version,
|
|
69625
69896
|
() => void 0
|
|
69626
69897
|
);
|
|
@@ -69634,8 +69905,8 @@ async function writeLazePlugin({ context }) {
|
|
|
69634
69905
|
configPath: context.environment.configPath
|
|
69635
69906
|
});
|
|
69636
69907
|
for (const [path, text2] of Object.entries(files2)) {
|
|
69637
|
-
const target =
|
|
69638
|
-
await mkdir11(
|
|
69908
|
+
const target = join14(folder, path);
|
|
69909
|
+
await mkdir11(dirname12(target), { recursive: true });
|
|
69639
69910
|
await writeFile11(target, text2);
|
|
69640
69911
|
}
|
|
69641
69912
|
return folder;
|
|
@@ -69666,8 +69937,8 @@ var RUN_FILES = ["hooks/hooks.json", "monitors/monitors.json"];
|
|
|
69666
69937
|
async function cachedPluginOf({ context }) {
|
|
69667
69938
|
const inherited = context.environment.inherited;
|
|
69668
69939
|
const home = inherited.HOME || homedir3();
|
|
69669
|
-
const claude = inherited.CLAUDE_CONFIG_DIR ||
|
|
69670
|
-
const listed = await
|
|
69940
|
+
const claude = inherited.CLAUDE_CONFIG_DIR || join14(home, ".claude");
|
|
69941
|
+
const listed = await readFile12(join14(claude, "plugins", "installed_plugins.json"), "utf8").then(
|
|
69671
69942
|
(text2) => JSON.parse(text2),
|
|
69672
69943
|
() => void 0
|
|
69673
69944
|
);
|
|
@@ -69676,10 +69947,10 @@ async function cachedPluginOf({ context }) {
|
|
|
69676
69947
|
async function refreshStaleCache({ context, folder }) {
|
|
69677
69948
|
const cached2 = await cachedPluginOf({ context });
|
|
69678
69949
|
if (!cached2) return true;
|
|
69679
|
-
const read3 = (path) =>
|
|
69950
|
+
const read3 = (path) => readFile12(path, "utf8").catch(() => "");
|
|
69680
69951
|
for (const file3 of RUN_FILES) {
|
|
69681
|
-
const ours = await read3(
|
|
69682
|
-
if (ours === await read3(
|
|
69952
|
+
const ours = await read3(join14(folder, LAZE_PLUGIN, file3));
|
|
69953
|
+
if (ours === await read3(join14(cached2, file3))) continue;
|
|
69683
69954
|
const plugin2 = `${LAZE_PLUGIN}@${LAZE_PLUGIN}`;
|
|
69684
69955
|
const script = [
|
|
69685
69956
|
`claude plugin uninstall ${plugin2} --scope user ${QUIET}`,
|
|
@@ -69690,10 +69961,10 @@ async function refreshStaleCache({ context, folder }) {
|
|
|
69690
69961
|
return true;
|
|
69691
69962
|
}
|
|
69692
69963
|
function registeredMarkOf({ context }) {
|
|
69693
|
-
return
|
|
69964
|
+
return join14(pluginFolderOf({ context }), "registered");
|
|
69694
69965
|
}
|
|
69695
69966
|
async function pluginRegistered({ context }) {
|
|
69696
|
-
return
|
|
69967
|
+
return readFile12(registeredMarkOf({ context }), "utf8").then(
|
|
69697
69968
|
() => true,
|
|
69698
69969
|
() => false
|
|
69699
69970
|
);
|
|
@@ -69707,7 +69978,7 @@ async function installLazePlugin({ context }) {
|
|
|
69707
69978
|
async function plugin({ context, args }) {
|
|
69708
69979
|
const action = args.words[1] ?? "install";
|
|
69709
69980
|
if (action === "path") {
|
|
69710
|
-
context.out(`${
|
|
69981
|
+
context.out(`${join14(pluginFolderOf({ context }), LAZE_PLUGIN)}
|
|
69711
69982
|
`);
|
|
69712
69983
|
return 0;
|
|
69713
69984
|
}
|
|
@@ -69726,7 +69997,7 @@ async function plugin({ context, args }) {
|
|
|
69726
69997
|
|
|
69727
69998
|
// src/services/mcp-channel.service.ts
|
|
69728
69999
|
import { mkdir as mkdir12, rm as rm7, writeFile as writeFile12 } from "node:fs/promises";
|
|
69729
|
-
import { dirname as
|
|
70000
|
+
import { dirname as dirname13 } from "node:path";
|
|
69730
70001
|
var LAZE_MCP_SERVER = "laze";
|
|
69731
70002
|
var DEV_CHANNELS_FLAG = "--dangerously-load-development-channels";
|
|
69732
70003
|
var ROUND_SECONDS3 = 50;
|
|
@@ -69816,7 +70087,7 @@ async function pushInbox({
|
|
|
69816
70087
|
signal
|
|
69817
70088
|
}) {
|
|
69818
70089
|
const marker = statePathOf({ context, kind: "channels", profile });
|
|
69819
|
-
await mkdir12(
|
|
70090
|
+
await mkdir12(dirname13(marker), { recursive: true, mode: 448 });
|
|
69820
70091
|
await writeFile12(marker, JSON.stringify({ pid: context.processes.pid }));
|
|
69821
70092
|
try {
|
|
69822
70093
|
while (!signal.aborted) {
|
|
@@ -69844,8 +70115,8 @@ async function pushInbox({
|
|
|
69844
70115
|
}
|
|
69845
70116
|
|
|
69846
70117
|
// src/services/plugin-tip.service.ts
|
|
69847
|
-
import { mkdir as mkdir13, readFile as
|
|
69848
|
-
import { dirname as
|
|
70118
|
+
import { mkdir as mkdir13, readFile as readFile13, writeFile as writeFile13 } from "node:fs/promises";
|
|
70119
|
+
import { dirname as dirname14 } from "node:path";
|
|
69849
70120
|
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
70121
|
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
70122
|
function monitorsRunHere({ context }) {
|
|
@@ -69879,7 +70150,7 @@ async function markReloadTipTold({
|
|
|
69879
70150
|
}) {
|
|
69880
70151
|
if (!session) return;
|
|
69881
70152
|
const path = toldPathOf({ context, session });
|
|
69882
|
-
await mkdir13(
|
|
70153
|
+
await mkdir13(dirname14(path), { recursive: true, mode: 448 });
|
|
69883
70154
|
await writeFile13(path, String(context.nowMs()), { mode: 384 });
|
|
69884
70155
|
}
|
|
69885
70156
|
async function reloadTipOnce({
|
|
@@ -69888,7 +70159,7 @@ async function reloadTipOnce({
|
|
|
69888
70159
|
}) {
|
|
69889
70160
|
if (!session || !monitorsRunHere({ context })) return void 0;
|
|
69890
70161
|
if (!await pluginRegistered({ context })) return void 0;
|
|
69891
|
-
const told = await
|
|
70162
|
+
const told = await readFile13(toldPathOf({ context, session }), "utf8").then(
|
|
69892
70163
|
() => true,
|
|
69893
70164
|
() => false
|
|
69894
70165
|
);
|
|
@@ -69954,9 +70225,9 @@ async function installHooks({
|
|
|
69954
70225
|
directory,
|
|
69955
70226
|
profile
|
|
69956
70227
|
}) {
|
|
69957
|
-
const folder =
|
|
69958
|
-
const path =
|
|
69959
|
-
const current2 = await
|
|
70228
|
+
const folder = join15(directory, ".claude");
|
|
70229
|
+
const path = join15(folder, "settings.local.json");
|
|
70230
|
+
const current2 = await readFile14(path, "utf8").then(
|
|
69960
70231
|
(text2) => JSON.parse(text2),
|
|
69961
70232
|
() => ({})
|
|
69962
70233
|
);
|
|
@@ -70158,7 +70429,7 @@ async function reportTranscript({
|
|
|
70158
70429
|
input: input2
|
|
70159
70430
|
}) {
|
|
70160
70431
|
if (!input2.transcript_path || !input2.session_id) return;
|
|
70161
|
-
const lines = (await
|
|
70432
|
+
const lines = (await readFile14(input2.transcript_path, "utf8")).split("\n");
|
|
70162
70433
|
const context = readTranscript({ lines });
|
|
70163
70434
|
await client.post("/api/agents/me/activity", {
|
|
70164
70435
|
sessionId: input2.session_id,
|
|
@@ -70191,7 +70462,7 @@ async function handOver({ context, args }) {
|
|
|
70191
70462
|
const kept = await dueFromSpool({
|
|
70192
70463
|
context,
|
|
70193
70464
|
profile: agent2,
|
|
70194
|
-
seen: () => input2.transcript_path ?
|
|
70465
|
+
seen: () => input2.transcript_path ? readFile14(input2.transcript_path, "utf8") : Promise.resolve(""),
|
|
70195
70466
|
pushedToo: false
|
|
70196
70467
|
});
|
|
70197
70468
|
const claim3 = forSession({ client, session });
|
|
@@ -70231,8 +70502,8 @@ async function addSessionStartWaiter({ context, args }) {
|
|
|
70231
70502
|
const directory = context.environment.inherited.CLAUDE_PROJECT_DIR;
|
|
70232
70503
|
const profile = flagText({ args, name: "profile" });
|
|
70233
70504
|
if (!directory || !profile) return;
|
|
70234
|
-
const path =
|
|
70235
|
-
const settings2 = await
|
|
70505
|
+
const path = join15(directory, ".claude", "settings.local.json");
|
|
70506
|
+
const settings2 = await readFile14(path, "utf8").then(
|
|
70236
70507
|
(text2) => JSON.parse(text2),
|
|
70237
70508
|
() => void 0
|
|
70238
70509
|
);
|
|
@@ -70241,7 +70512,7 @@ async function addSessionStartWaiter({ context, args }) {
|
|
|
70241
70512
|
}
|
|
70242
70513
|
async function refreshPlugin({ context }) {
|
|
70243
70514
|
if (await pluginIsCurrent({ context })) return;
|
|
70244
|
-
const logPath =
|
|
70515
|
+
const logPath = join15(pluginFolderOf({ context }), "install.log");
|
|
70245
70516
|
context.processes.spawnDetached({ argv: [...context.program, "plugin", "install"], logPath });
|
|
70246
70517
|
}
|
|
70247
70518
|
async function stopHook({ context, args }) {
|
|
@@ -70259,7 +70530,7 @@ async function stopHook({ context, args }) {
|
|
|
70259
70530
|
}
|
|
70260
70531
|
|
|
70261
70532
|
// src/services/agent-manage-commands.service.ts
|
|
70262
|
-
import { readFile as
|
|
70533
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
70263
70534
|
import { extname, resolve as resolve5 } from "node:path";
|
|
70264
70535
|
|
|
70265
70536
|
// src/rules/login-format.rules.ts
|
|
@@ -70388,7 +70659,7 @@ async function avatarOf({
|
|
|
70388
70659
|
}) {
|
|
70389
70660
|
const path = flagText({ args, name: "avatar" });
|
|
70390
70661
|
if (!path) return void 0;
|
|
70391
|
-
const bytes = await
|
|
70662
|
+
const bytes = await readFile15(resolve5(context.cwd, path)).catch(() => {
|
|
70392
70663
|
throw new CliUsageError(`laze: cannot read the avatar file ${path}.`);
|
|
70393
70664
|
});
|
|
70394
70665
|
const uploaded = await client.post("/api/agents/avatars", {
|
|
@@ -71091,8 +71362,8 @@ async function requestAgent({ context, args }) {
|
|
|
71091
71362
|
}
|
|
71092
71363
|
|
|
71093
71364
|
// src/services/app-commands.service.ts
|
|
71094
|
-
import { mkdir as mkdir15, readdir as
|
|
71095
|
-
import { dirname as
|
|
71365
|
+
import { mkdir as mkdir15, readdir as readdir6, readFile as readFile16, writeFile as writeFile16 } from "node:fs/promises";
|
|
71366
|
+
import { dirname as dirname15, join as join17, relative as relative3, resolve as resolve6, sep as sep2 } from "node:path";
|
|
71096
71367
|
|
|
71097
71368
|
// ../../modules/app/contract/src/app.connections.ts
|
|
71098
71369
|
var appFunctionNameSchema = external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/);
|
|
@@ -73487,7 +73758,7 @@ async function appPinsCommand({
|
|
|
73487
73758
|
import { execFile } from "node:child_process";
|
|
73488
73759
|
import { mkdtemp, rm as rm8, writeFile as writeFile15 } from "node:fs/promises";
|
|
73489
73760
|
import { tmpdir } from "node:os";
|
|
73490
|
-
import { join as
|
|
73761
|
+
import { join as join16 } from "node:path";
|
|
73491
73762
|
import { promisify } from "node:util";
|
|
73492
73763
|
var run2 = promisify(execFile);
|
|
73493
73764
|
var MODULE_SYNTAX = /^\s*(import|export)\s/m;
|
|
@@ -73516,11 +73787,11 @@ async function scriptErrorsOf({
|
|
|
73516
73787
|
const unknown2 = unknownCollectionsOf({ files: files2, collections });
|
|
73517
73788
|
const scripts = files2.flatMap(scriptsOf);
|
|
73518
73789
|
if (scripts.length === 0) return unknown2;
|
|
73519
|
-
const dir = await mkdtemp(
|
|
73790
|
+
const dir = await mkdtemp(join16(tmpdir(), "laze-app-check-"));
|
|
73520
73791
|
try {
|
|
73521
73792
|
const errors = await Promise.all(
|
|
73522
73793
|
scripts.map(async (script, index) => {
|
|
73523
|
-
const file3 =
|
|
73794
|
+
const file3 = join16(dir, `${index}.${script.module ? "mjs" : "cjs"}`);
|
|
73524
73795
|
await writeFile15(file3, script.code);
|
|
73525
73796
|
try {
|
|
73526
73797
|
await run2(process.execPath, ["--check", file3]);
|
|
@@ -73670,7 +73941,7 @@ async function turnTokenOf({
|
|
|
73670
73941
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
73671
73942
|
if (pinned) return pinned;
|
|
73672
73943
|
if (env.LAZE_TURN_FILE) {
|
|
73673
|
-
return
|
|
73944
|
+
return readFile16(env.LAZE_TURN_FILE, "utf8").then(
|
|
73674
73945
|
(text2) => text2.trim(),
|
|
73675
73946
|
() => ""
|
|
73676
73947
|
);
|
|
@@ -73696,7 +73967,7 @@ function folderOf({ context, word: word3 }) {
|
|
|
73696
73967
|
return resolve6(context.cwd, word3 ?? ".");
|
|
73697
73968
|
}
|
|
73698
73969
|
async function readManifest(folder) {
|
|
73699
|
-
const text2 = await
|
|
73970
|
+
const text2 = await readFile16(join17(folder, APP_MANIFEST_FILE), "utf8").catch(() => void 0);
|
|
73700
73971
|
if (text2 === void 0) return void 0;
|
|
73701
73972
|
const parsed = appManifestSchema.safeParse(JSON.parse(text2));
|
|
73702
73973
|
if (!parsed.success) {
|
|
@@ -73731,7 +74002,7 @@ async function jsonFlag({
|
|
|
73731
74002
|
}) {
|
|
73732
74003
|
const raw = flagText({ args, name: name2 });
|
|
73733
74004
|
if (!raw) return void 0;
|
|
73734
|
-
const text2 = raw.startsWith("@") ? await
|
|
74005
|
+
const text2 = raw.startsWith("@") ? await readFile16(resolve6(context.cwd, raw.slice(1)), "utf8") : raw;
|
|
73735
74006
|
try {
|
|
73736
74007
|
return JSON.parse(text2);
|
|
73737
74008
|
} catch {
|
|
@@ -73743,8 +74014,8 @@ async function listFiles(folder) {
|
|
|
73743
74014
|
const pending = [folder];
|
|
73744
74015
|
while (pending.length > 0 && found.length <= MAX_FILES) {
|
|
73745
74016
|
const current2 = pending.pop() ?? folder;
|
|
73746
|
-
for (const entry of await
|
|
73747
|
-
const path =
|
|
74017
|
+
for (const entry of await readdir6(current2, { withFileTypes: true })) {
|
|
74018
|
+
const path = join17(current2, entry.name);
|
|
73748
74019
|
const rel = relative3(folder, path).split(sep2).join("/");
|
|
73749
74020
|
if (isSkippedPath({ path: rel })) continue;
|
|
73750
74021
|
if (entry.isDirectory()) pending.push(path);
|
|
@@ -73788,8 +74059,8 @@ var appCreate = async ({ context, args }) => {
|
|
|
73788
74059
|
await mkdir15(folder, { recursive: true });
|
|
73789
74060
|
const files2 = template ? templateFiles({ template, name: name2 }) : {};
|
|
73790
74061
|
for (const [path, content] of Object.entries(files2)) {
|
|
73791
|
-
await mkdir15(
|
|
73792
|
-
await writeFile16(
|
|
74062
|
+
await mkdir15(dirname15(join17(folder, path)), { recursive: true });
|
|
74063
|
+
await writeFile16(join17(folder, path), content);
|
|
73793
74064
|
}
|
|
73794
74065
|
const manifest = {
|
|
73795
74066
|
app: { id: app2.id, name: app2.name, slug: app2.slug },
|
|
@@ -73797,7 +74068,7 @@ var appCreate = async ({ context, args }) => {
|
|
|
73797
74068
|
views: template?.views ? [...template.views] : [],
|
|
73798
74069
|
seed: template ? { ...template.seed } : {}
|
|
73799
74070
|
};
|
|
73800
|
-
await writeFile16(
|
|
74071
|
+
await writeFile16(join17(folder, APP_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
|
|
73801
74072
|
`);
|
|
73802
74073
|
print5({
|
|
73803
74074
|
context,
|
|
@@ -73834,7 +74105,7 @@ var appPush = async ({ context, args }) => {
|
|
|
73834
74105
|
paths.map(
|
|
73835
74106
|
async (path) => buildFileOf({
|
|
73836
74107
|
path: relative3(folder, path).split(sep2).join("/"),
|
|
73837
|
-
bytes: await
|
|
74108
|
+
bytes: await readFile16(path)
|
|
73838
74109
|
})
|
|
73839
74110
|
)
|
|
73840
74111
|
);
|
|
@@ -74217,7 +74488,7 @@ var appImport = async ({ context, args }) => {
|
|
|
74217
74488
|
const words = args.words.slice(2);
|
|
74218
74489
|
const [named, collection, file3] = words.length >= 3 ? words : [void 0, ...words];
|
|
74219
74490
|
if (!collection || !file3) throw new CliUsageError(USAGE5);
|
|
74220
|
-
const csv = await
|
|
74491
|
+
const csv = await readFile16(resolve6(context.cwd, file3), "utf8").catch(() => {
|
|
74221
74492
|
throw new CliUsageError(`Cannot read ${file3}`);
|
|
74222
74493
|
});
|
|
74223
74494
|
const scoped = named ? { ...args, flags: { ...args.flags, app: named } } : args;
|
|
@@ -74783,8 +75054,8 @@ async function billing({ context, args }) {
|
|
|
74783
75054
|
|
|
74784
75055
|
// src/services/browser-commands.service.ts
|
|
74785
75056
|
import { randomBytes } from "node:crypto";
|
|
74786
|
-
import { mkdir as mkdir16, readFile as
|
|
74787
|
-
import { dirname as
|
|
75057
|
+
import { mkdir as mkdir16, readFile as readFile17, writeFile as writeFile17 } from "node:fs/promises";
|
|
75058
|
+
import { dirname as dirname16, join as join18 } from "node:path";
|
|
74788
75059
|
|
|
74789
75060
|
// src/services/browser-tab-commands.service.ts
|
|
74790
75061
|
var BROWSER_TAB_PATHS = {
|
|
@@ -75330,7 +75601,7 @@ async function turnTokenOf2({ context }) {
|
|
|
75330
75601
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
75331
75602
|
if (pinned) return pinned;
|
|
75332
75603
|
if (!env.LAZE_TURN_FILE) return "";
|
|
75333
|
-
return
|
|
75604
|
+
return readFile17(env.LAZE_TURN_FILE, "utf8").then(
|
|
75334
75605
|
(text2) => text2.trim(),
|
|
75335
75606
|
() => ""
|
|
75336
75607
|
);
|
|
@@ -75404,7 +75675,7 @@ async function cdp({ context, args }) {
|
|
|
75404
75675
|
}
|
|
75405
75676
|
function bridgeStatePath({ context, machine: machine2 }) {
|
|
75406
75677
|
const safe = machine2.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
75407
|
-
return
|
|
75678
|
+
return join18(dirname16(context.environment.configPath), "bridges", `${safe}.json`);
|
|
75408
75679
|
}
|
|
75409
75680
|
async function bridgePort({
|
|
75410
75681
|
context,
|
|
@@ -75412,7 +75683,7 @@ async function bridgePort({
|
|
|
75412
75683
|
access
|
|
75413
75684
|
}) {
|
|
75414
75685
|
const path = bridgeStatePath({ context, machine: machine2 });
|
|
75415
|
-
const live = await
|
|
75686
|
+
const live = await readFile17(path, "utf8").then(
|
|
75416
75687
|
(text2) => JSON.parse(text2),
|
|
75417
75688
|
() => void 0
|
|
75418
75689
|
);
|
|
@@ -75425,7 +75696,7 @@ async function bridgePort({
|
|
|
75425
75696
|
key,
|
|
75426
75697
|
...target
|
|
75427
75698
|
});
|
|
75428
|
-
await mkdir16(
|
|
75699
|
+
await mkdir16(dirname16(path), { recursive: true, mode: 448 });
|
|
75429
75700
|
await writeFile17(path, JSON.stringify({ port, key }), { mode: 384 });
|
|
75430
75701
|
return port;
|
|
75431
75702
|
}
|
|
@@ -76070,9 +76341,42 @@ async function channelSettings({ context, args }) {
|
|
|
76070
76341
|
}
|
|
76071
76342
|
|
|
76072
76343
|
// src/services/chat-actions-commands.service.ts
|
|
76073
|
-
import { readFile as
|
|
76344
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
76074
76345
|
import { basename as basename3, isAbsolute as isAbsolute2, relative as relative4, resolve as resolve7 } from "node:path";
|
|
76075
76346
|
|
|
76347
|
+
// src/rules/file-types.rules.ts
|
|
76348
|
+
var TYPES = {
|
|
76349
|
+
png: "image/png",
|
|
76350
|
+
jpg: "image/jpeg",
|
|
76351
|
+
jpeg: "image/jpeg",
|
|
76352
|
+
webp: "image/webp",
|
|
76353
|
+
gif: "image/gif",
|
|
76354
|
+
svg: "image/svg+xml",
|
|
76355
|
+
pdf: "application/pdf",
|
|
76356
|
+
txt: "text/plain",
|
|
76357
|
+
md: "text/markdown",
|
|
76358
|
+
csv: "text/csv",
|
|
76359
|
+
json: "application/json",
|
|
76360
|
+
zip: "application/zip"
|
|
76361
|
+
};
|
|
76362
|
+
function contentTypeOf(fileName) {
|
|
76363
|
+
const extension2 = fileName.toLowerCase().split(".").pop() ?? "";
|
|
76364
|
+
return TYPES[extension2] ?? "application/octet-stream";
|
|
76365
|
+
}
|
|
76366
|
+
var MACHINE_NAME = /^(?:[a-z]{1,8}[_-])?[0-9a-f][0-9a-f_-]{11,}$/i;
|
|
76367
|
+
function readableUploadName({ name: name2, asked }) {
|
|
76368
|
+
const slash = name2.lastIndexOf("/");
|
|
76369
|
+
const base = name2.slice(slash + 1);
|
|
76370
|
+
const dot = base.lastIndexOf(".");
|
|
76371
|
+
const extension2 = dot > 0 ? base.slice(dot) : "";
|
|
76372
|
+
const wanted = asked?.trim();
|
|
76373
|
+
if (wanted) return /\.[A-Za-z0-9]{1,8}$/.test(wanted) ? wanted : `${wanted}${extension2}`;
|
|
76374
|
+
const stem = dot > 0 ? base.slice(0, dot) : base;
|
|
76375
|
+
if (!MACHINE_NAME.test(stem)) return name2;
|
|
76376
|
+
const image = contentTypeOf(base).startsWith("image/");
|
|
76377
|
+
return `${image ? "image" : "file"}${extension2}`;
|
|
76378
|
+
}
|
|
76379
|
+
|
|
76076
76380
|
// src/services/file-upload.service.ts
|
|
76077
76381
|
async function sendParts({
|
|
76078
76382
|
context,
|
|
@@ -76171,7 +76475,7 @@ var CHAT_ACTIONS_USAGE = `Usage:
|
|
|
76171
76475
|
laze files <channel> [--before <fileId>] [--limit <n>] its files, newest first
|
|
76172
76476
|
laze file link <fileId> [--variant original|thumbnail|poster|preview] [--download]
|
|
76173
76477
|
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
|
|
76478
|
+
laze file upload <channel> <path> [--name <name>] [--type <content-type>] upload a file; post it with its id
|
|
76175
76479
|
laze saved [--done] [--limit <n>] | laze saved marks your saved messages (people)
|
|
76176
76480
|
laze save <messageId> [--off] save a message for later, or take it out
|
|
76177
76481
|
laze saved done <messageId> [--undo] mark a saved message done, or open again
|
|
@@ -76375,19 +76679,27 @@ function uploadNameOf({ cwd, path }) {
|
|
|
76375
76679
|
}
|
|
76376
76680
|
var fileUpload = async ({ context, args, client }) => {
|
|
76377
76681
|
const path = resolve7(context.cwd, wordAt(args, 3));
|
|
76378
|
-
const bytes = new Uint8Array(await
|
|
76682
|
+
const bytes = new Uint8Array(await readFile18(path));
|
|
76379
76683
|
const answer4 = await uploadFile({
|
|
76380
76684
|
context,
|
|
76381
76685
|
client,
|
|
76382
76686
|
file: {
|
|
76383
76687
|
channel: wordAt(args, 2),
|
|
76384
|
-
fileName:
|
|
76385
|
-
|
|
76688
|
+
fileName: readableUploadName({
|
|
76689
|
+
name: uploadNameOf({ cwd: context.cwd, path }),
|
|
76690
|
+
...flagText({ args, name: "name" }) && { asked: flagText({ args, name: "name" }) }
|
|
76691
|
+
}),
|
|
76692
|
+
contentType: flagText({ args, name: "type", fallback: contentTypeOf(path) }),
|
|
76386
76693
|
bytes
|
|
76387
76694
|
}
|
|
76388
76695
|
});
|
|
76389
|
-
print6({
|
|
76390
|
-
|
|
76696
|
+
print6({
|
|
76697
|
+
context,
|
|
76698
|
+
args,
|
|
76699
|
+
answer: answer4,
|
|
76700
|
+
text: (it) => `Uploaded ${it.fileName} as ${it.id}. Put <file:${it.id}> in a message to share it.
|
|
76701
|
+
`
|
|
76702
|
+
});
|
|
76391
76703
|
};
|
|
76392
76704
|
var FILE_VERBS = {
|
|
76393
76705
|
link: async ({ context, args, client }) => {
|
|
@@ -76540,7 +76852,7 @@ async function chatActions({
|
|
|
76540
76852
|
}
|
|
76541
76853
|
|
|
76542
76854
|
// src/services/claude-monitor.service.ts
|
|
76543
|
-
import { readFile as
|
|
76855
|
+
import { readFile as readFile19, rm as rm9 } from "node:fs/promises";
|
|
76544
76856
|
var MONITOR_IDLE_MS = 3e4;
|
|
76545
76857
|
var MONITOR_OUTRANKED_MS = 3e3;
|
|
76546
76858
|
async function deliverOnce({
|
|
@@ -76558,7 +76870,7 @@ async function deliverOnce({
|
|
|
76558
76870
|
const named = { ...args, flags: { ...args.flags, profile } };
|
|
76559
76871
|
const { client } = await signedIn({ context, args: named });
|
|
76560
76872
|
const due = await dueFromSpool({ context, profile, seen: async () => "", pushedToo: true });
|
|
76561
|
-
const taken = due.length > 0 ? [] : await
|
|
76873
|
+
const taken = due.length > 0 ? [] : await takeRound2({ context, client, claudePid, session });
|
|
76562
76874
|
const messages = [...due, ...taken];
|
|
76563
76875
|
if (messages.length === 0) {
|
|
76564
76876
|
await context.sleep(1e3);
|
|
@@ -76635,7 +76947,7 @@ async function monitorSessionOf({
|
|
|
76635
76947
|
const fromEnv = sessionOf({ context, harness: "claude-code", sessionId });
|
|
76636
76948
|
if (fromEnv || !claudePid) return fromEnv;
|
|
76637
76949
|
const path = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
|
|
76638
|
-
return
|
|
76950
|
+
return readFile19(path, "utf8").then(
|
|
76639
76951
|
(text2) => JSON.parse(text2),
|
|
76640
76952
|
() => void 0
|
|
76641
76953
|
);
|
|
@@ -77220,7 +77532,7 @@ var computerStatusDefinition = external_exports.object({
|
|
|
77220
77532
|
/** The person whose computer this is; an agent reads its owner's. */
|
|
77221
77533
|
ownerUserId: external_exports.string(),
|
|
77222
77534
|
ownerName: external_exports.string(),
|
|
77223
|
-
/** "
|
|
77535
|
+
/** "Agent computer" for its owner, "Mia's agent computer" for an agent or anyone else. */
|
|
77224
77536
|
name: external_exports.string(),
|
|
77225
77537
|
/** The size it runs at: the chosen one, or the included one when none was chosen. */
|
|
77226
77538
|
size: computerSizeSchema,
|
|
@@ -78076,7 +78388,7 @@ async function mine({ context, args }) {
|
|
|
78076
78388
|
const client = await computeClient({ context, args });
|
|
78077
78389
|
const answer4 = await client.get(COMPUTER_REST_PATHS.mine);
|
|
78078
78390
|
if (args.flags.json) return printJson2(context, answer4);
|
|
78079
|
-
context.out(`Your
|
|
78391
|
+
context.out(`Your agent computers:
|
|
78080
78392
|
${answer4.computers.map(lineOf3).join("\n")}
|
|
78081
78393
|
`);
|
|
78082
78394
|
}
|
|
@@ -78137,14 +78449,14 @@ var COMPUTER_FLEET_COMMANDS = { mine, add: add2, remove: remove3, creators, move
|
|
|
78137
78449
|
|
|
78138
78450
|
// src/services/computer-commands.service.ts
|
|
78139
78451
|
var COMPUTER_USAGE = `Usage:
|
|
78140
|
-
laze computer status [--json] your computer: size, CPU, memory and disk in use, your agents, the sizes
|
|
78452
|
+
laze computer status [--json] your agent computer: size, CPU, memory and disk in use, your agents, the sizes
|
|
78141
78453
|
laze computer sizes the sizes with their prices and what the plan includes per person
|
|
78142
|
-
laze computer upgrade <size> change your computer's size: small, medium, large or xl (Owners and
|
|
78454
|
+
laze computer upgrade <size> change your agent computer's size: small, medium, large or xl (Owners and
|
|
78143
78455
|
Admins); anyone else gets a message to forward and the admins a card
|
|
78144
|
-
laze computer request <size> ask the admins for a size for your computer
|
|
78456
|
+
laze computer request <size> ask the admins for a size for your agent computer
|
|
78145
78457
|
laze computer cancel <request> withdraw your request
|
|
78146
78458
|
laze computer restart [--person <user id>] [--computer <computer>]
|
|
78147
|
-
stop and start your computer, or a person's (Owners and Admins);
|
|
78459
|
+
stop and start your agent computer, or a person's (Owners and Admins);
|
|
78148
78460
|
its agents start again on their next message
|
|
78149
78461
|
laze computer list [--json] everyone's computers with size and monthly cost (Owners and Admins)
|
|
78150
78462
|
${COMPUTER_FLEET_USAGE}`;
|
|
@@ -78169,10 +78481,10 @@ function sizeLines(status8) {
|
|
|
78169
78481
|
});
|
|
78170
78482
|
}
|
|
78171
78483
|
function stateLine(status8) {
|
|
78172
|
-
if (status8.state === "none") return "State: no agent used
|
|
78484
|
+
if (status8.state === "none") return "State: ready, no agent used it yet";
|
|
78173
78485
|
if (status8.state === "asleep") {
|
|
78174
78486
|
const since = status8.lastRunningAt ? `, last ran ${utc(status8.lastRunningAt)}` : "";
|
|
78175
|
-
return `State:
|
|
78487
|
+
return `State: ready, wakes in seconds when an agent needs it${since}`;
|
|
78176
78488
|
}
|
|
78177
78489
|
return "State: running";
|
|
78178
78490
|
}
|
|
@@ -78310,10 +78622,10 @@ async function computer({ context, args }) {
|
|
|
78310
78622
|
}
|
|
78311
78623
|
|
|
78312
78624
|
// src/services/connect-commands.service.ts
|
|
78313
|
-
import { readFile as
|
|
78625
|
+
import { readFile as readFile21 } from "node:fs/promises";
|
|
78314
78626
|
|
|
78315
78627
|
// src/services/mcp-gateway.service.ts
|
|
78316
|
-
import { readFile as
|
|
78628
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
78317
78629
|
import { createInterface as createInterface3 } from "node:readline";
|
|
78318
78630
|
var TURN_HEADER = "x-laze-turn";
|
|
78319
78631
|
function serveMcpGateway({
|
|
@@ -78356,7 +78668,7 @@ async function relayMcpLines({
|
|
|
78356
78668
|
const github3 = env.LAZE_GITHUB_CONNECTION;
|
|
78357
78669
|
const url2 = `${profile.url.replace(/\/+$/, "")}/api/connectors/mcp/${encodeURIComponent(profile.agentId)}${github3 ? `?github=${encodeURIComponent(github3)}` : ""}`;
|
|
78358
78670
|
const turnFile = env.LAZE_TURN_FILE;
|
|
78359
|
-
const readTurn = () =>
|
|
78671
|
+
const readTurn = () => readFile20(turnFile, "utf8").then(
|
|
78360
78672
|
(text2) => text2.trim(),
|
|
78361
78673
|
() => ""
|
|
78362
78674
|
);
|
|
@@ -78446,7 +78758,7 @@ async function turnOf({ context }) {
|
|
|
78446
78758
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
78447
78759
|
if (pinned) return pinned;
|
|
78448
78760
|
const file3 = env.LAZE_TURN_FILE;
|
|
78449
|
-
const turn = file3 ? await
|
|
78761
|
+
const turn = file3 ? await readFile21(file3, "utf8").then(
|
|
78450
78762
|
(text2) => text2.trim(),
|
|
78451
78763
|
() => ""
|
|
78452
78764
|
) : "";
|
|
@@ -78504,11 +78816,11 @@ async function connect({
|
|
|
78504
78816
|
}
|
|
78505
78817
|
|
|
78506
78818
|
// src/services/connector-commands.service.ts
|
|
78507
|
-
import { readFile as
|
|
78819
|
+
import { readFile as readFile23 } from "node:fs/promises";
|
|
78508
78820
|
import { resolve as resolve8 } from "node:path";
|
|
78509
78821
|
|
|
78510
78822
|
// src/services/vault-keychain-commands.service.ts
|
|
78511
|
-
import { readFile as
|
|
78823
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
78512
78824
|
|
|
78513
78825
|
// src/rules/vault-input.rules.ts
|
|
78514
78826
|
function secondsOf(text2) {
|
|
@@ -78830,7 +79142,7 @@ async function secretText({ context, args }) {
|
|
|
78830
79142
|
);
|
|
78831
79143
|
}
|
|
78832
79144
|
const file3 = flagText({ args, name: "from-file" });
|
|
78833
|
-
const text2 = file3 ? await
|
|
79145
|
+
const text2 = file3 ? await readFile22(file3, "utf8") : await context.readStdin();
|
|
78834
79146
|
const trimmed = text2.replace(/\r?\n$/, "");
|
|
78835
79147
|
if (!trimmed.trim()) throw new CliUsageError("No value: pipe it on stdin or use --from-file.");
|
|
78836
79148
|
return trimmed;
|
|
@@ -78949,8 +79261,8 @@ function removal(path) {
|
|
|
78949
79261
|
};
|
|
78950
79262
|
}
|
|
78951
79263
|
function usedBy(row) {
|
|
78952
|
-
if (row.agentId) return `agent ${row.agentId}`;
|
|
78953
79264
|
if (row.actorKind === "user") return `person ${row.actorId ?? ""}`;
|
|
79265
|
+
if (row.agentId) return `agent ${row.agentId}`;
|
|
78954
79266
|
return "laze";
|
|
78955
79267
|
}
|
|
78956
79268
|
var uses = async ({ context, args }) => {
|
|
@@ -79040,7 +79352,7 @@ async function keyText({ context, args }) {
|
|
|
79040
79352
|
throw new CliUsageError("A key never goes in a flag: pipe it on stdin or use --from-file.");
|
|
79041
79353
|
}
|
|
79042
79354
|
const file3 = flagText({ args, name: "from-file" });
|
|
79043
|
-
const text2 = file3 ? await
|
|
79355
|
+
const text2 = file3 ? await readFile23(resolve8(context.cwd, file3), "utf8") : await context.readStdin();
|
|
79044
79356
|
const trimmed = text2.trim();
|
|
79045
79357
|
if (!trimmed) throw new CliUsageError("No key: pipe it on stdin or use --from-file.");
|
|
79046
79358
|
return trimmed;
|
|
@@ -79432,8 +79744,8 @@ var DOMAINS_USAGE = `Usage:
|
|
|
79432
79744
|
var printJson5 = (context, data) => context.out(`${JSON.stringify(data, null, 2)}
|
|
79433
79745
|
`);
|
|
79434
79746
|
function printDomain(context, row) {
|
|
79435
|
-
const
|
|
79436
|
-
context.out(`${row.domain} ${
|
|
79747
|
+
const join23 = row.autoJoin ? "auto-join on" : "auto-join off";
|
|
79748
|
+
context.out(`${row.domain} ${join23}${row.enforced ? " single sign-on enforced" : ""}
|
|
79437
79749
|
`);
|
|
79438
79750
|
}
|
|
79439
79751
|
async function list4({ context, args }) {
|
|
@@ -79465,7 +79777,7 @@ async function domains({ context, args }) {
|
|
|
79465
79777
|
}
|
|
79466
79778
|
|
|
79467
79779
|
// src/services/feed-commands.service.ts
|
|
79468
|
-
import { readFile as
|
|
79780
|
+
import { readFile as readFile25 } from "node:fs/promises";
|
|
79469
79781
|
import { resolve as resolve10 } from "node:path";
|
|
79470
79782
|
|
|
79471
79783
|
// src/rules/feed-input.rules.ts
|
|
@@ -79590,7 +79902,7 @@ function feedFlagsOf({ args }) {
|
|
|
79590
79902
|
}
|
|
79591
79903
|
|
|
79592
79904
|
// src/services/feed-files.service.ts
|
|
79593
|
-
import { readFile as
|
|
79905
|
+
import { readFile as readFile24 } from "node:fs/promises";
|
|
79594
79906
|
import { basename as basename4, resolve as resolve9 } from "node:path";
|
|
79595
79907
|
|
|
79596
79908
|
// ../../modules/feed/contract/src/feed.ts
|
|
@@ -80135,26 +80447,6 @@ var feedWakeIntentSchemaDefinition = external_exports.object({
|
|
|
80135
80447
|
// ../../modules/feed/contract/src/feed.config.ts
|
|
80136
80448
|
var feedConfig = Config.define(() => ({ publicBaseUrl }));
|
|
80137
80449
|
|
|
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
80450
|
// src/services/feed-files.service.ts
|
|
80159
80451
|
async function bytesOf2({
|
|
80160
80452
|
context,
|
|
@@ -80185,7 +80477,7 @@ async function local({ context, path }) {
|
|
|
80185
80477
|
return {
|
|
80186
80478
|
fileName,
|
|
80187
80479
|
contentType: contentTypeOf(fileName),
|
|
80188
|
-
bytes: new Uint8Array(await
|
|
80480
|
+
bytes: new Uint8Array(await readFile24(full))
|
|
80189
80481
|
};
|
|
80190
80482
|
}
|
|
80191
80483
|
async function directWith({ client, to }) {
|
|
@@ -80263,7 +80555,7 @@ async function bodyOf2({
|
|
|
80263
80555
|
flags: flags2
|
|
80264
80556
|
}) {
|
|
80265
80557
|
const body = { ...flags2.fields };
|
|
80266
|
-
const read3 = (source) => "file" in source ?
|
|
80558
|
+
const read3 = (source) => "file" in source ? readFile25(resolve10(context.cwd, source.file), "utf8") : source.text;
|
|
80267
80559
|
for (const [field, source] of Object.entries(flags2.texts)) body[field] = await read3(source);
|
|
80268
80560
|
if (flags2.rich) {
|
|
80269
80561
|
const text2 = await read3(flags2.rich.source);
|
|
@@ -80425,7 +80717,7 @@ async function textFlag({
|
|
|
80425
80717
|
}) {
|
|
80426
80718
|
const value = flagText({ args, name: name2 });
|
|
80427
80719
|
if (!value.startsWith("@")) return value;
|
|
80428
|
-
return
|
|
80720
|
+
return readFile25(resolve10(context.cwd, value.slice(1)), "utf8");
|
|
80429
80721
|
}
|
|
80430
80722
|
async function feedList({ context, args }) {
|
|
80431
80723
|
const { client } = await signedIn({ context, args });
|
|
@@ -80535,7 +80827,7 @@ async function feed({ context, args }) {
|
|
|
80535
80827
|
}
|
|
80536
80828
|
|
|
80537
80829
|
// src/services/github-commands.service.ts
|
|
80538
|
-
import { readFile as
|
|
80830
|
+
import { readFile as readFile26 } from "node:fs/promises";
|
|
80539
80831
|
|
|
80540
80832
|
// src/rules/github-signature.rules.ts
|
|
80541
80833
|
var TURN_SEPARATOR = "~";
|
|
@@ -80605,7 +80897,7 @@ var REAL_GH = "/usr/bin/gh";
|
|
|
80605
80897
|
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
80898
|
async function turnFileToken({ env }) {
|
|
80607
80899
|
if (!env.LAZE_TURN_FILE) return "";
|
|
80608
|
-
return
|
|
80900
|
+
return readFile26(env.LAZE_TURN_FILE, "utf8").then(
|
|
80609
80901
|
(text2) => text2.trim(),
|
|
80610
80902
|
() => ""
|
|
80611
80903
|
);
|
|
@@ -80639,7 +80931,7 @@ async function githubGh({
|
|
|
80639
80931
|
args: args.rest,
|
|
80640
80932
|
agentName: profile.name ?? "An agent",
|
|
80641
80933
|
threadUrl: threadUrlOf({ env, workspaceId: profile.workspaceId }),
|
|
80642
|
-
readBodyFile: (path) => path === "-" ? context.readStdin() :
|
|
80934
|
+
readBodyFile: (path) => path === "-" ? context.readStdin() : readFile26(path, "utf8")
|
|
80643
80935
|
});
|
|
80644
80936
|
return context.runCommand({
|
|
80645
80937
|
command: [REAL_GH, ...ghArgs],
|
|
@@ -80738,7 +81030,7 @@ async function setAgentGithub({
|
|
|
80738
81030
|
}
|
|
80739
81031
|
|
|
80740
81032
|
// src/services/history-commands.service.ts
|
|
80741
|
-
import { readFile as
|
|
81033
|
+
import { readFile as readFile27 } from "node:fs/promises";
|
|
80742
81034
|
|
|
80743
81035
|
// src/rules/history-format.rules.ts
|
|
80744
81036
|
function timeOf2(iso) {
|
|
@@ -80834,7 +81126,7 @@ async function turnTokenOf3({ context }) {
|
|
|
80834
81126
|
const pinned = env.LAZE_TURN_TOKEN?.trim();
|
|
80835
81127
|
if (pinned) return pinned;
|
|
80836
81128
|
if (!env.LAZE_TURN_FILE) return "";
|
|
80837
|
-
return
|
|
81129
|
+
return readFile27(env.LAZE_TURN_FILE, "utf8").then(
|
|
80838
81130
|
(text2) => text2.trim(),
|
|
80839
81131
|
() => ""
|
|
80840
81132
|
);
|
|
@@ -81026,19 +81318,19 @@ async function ip({ context, args }) {
|
|
|
81026
81318
|
}
|
|
81027
81319
|
|
|
81028
81320
|
// src/services/join-commands.service.ts
|
|
81029
|
-
import { mkdir as mkdir17, readFile as
|
|
81030
|
-
import { dirname as
|
|
81321
|
+
import { mkdir as mkdir17, readFile as readFile28, rename as rename5, rm as rm10, writeFile as writeFile18 } from "node:fs/promises";
|
|
81322
|
+
import { dirname as dirname17, join as join19 } from "node:path";
|
|
81031
81323
|
var DEFAULT_WAIT_SECONDS2 = 100;
|
|
81032
81324
|
var JOIN_USAGE = "Usage: laze join [--workspace <name|id|invite link>] [--for <email>] [--name <name>] [--note <text>] [--timeout <seconds>] [--project <folder>]";
|
|
81033
81325
|
function pendingPathOf({ context }) {
|
|
81034
|
-
return
|
|
81326
|
+
return join19(dirname17(context.environment.configPath), "join", "pending.json");
|
|
81035
81327
|
}
|
|
81036
81328
|
async function readPending({
|
|
81037
81329
|
context,
|
|
81038
81330
|
url: url2,
|
|
81039
81331
|
args
|
|
81040
81332
|
}) {
|
|
81041
|
-
const pending = await
|
|
81333
|
+
const pending = await readFile28(pendingPathOf({ context }), "utf8").then(
|
|
81042
81334
|
(text2) => JSON.parse(text2),
|
|
81043
81335
|
() => void 0
|
|
81044
81336
|
);
|
|
@@ -81048,7 +81340,7 @@ async function readPending({
|
|
|
81048
81340
|
}
|
|
81049
81341
|
async function keepPending({ context, pending }) {
|
|
81050
81342
|
const path = pendingPathOf({ context });
|
|
81051
|
-
await mkdir17(
|
|
81343
|
+
await mkdir17(dirname17(path), { recursive: true, mode: 448 });
|
|
81052
81344
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
81053
81345
|
await writeFile18(temporary, JSON.stringify(pending), { mode: 384 });
|
|
81054
81346
|
await rename5(temporary, path);
|
|
@@ -81368,9 +81660,9 @@ function machineAccessCommand(name2) {
|
|
|
81368
81660
|
|
|
81369
81661
|
// src/services/vault-commands.service.ts
|
|
81370
81662
|
import { createHash as createHash2 } from "node:crypto";
|
|
81371
|
-
import { mkdir as mkdir18, readFile as
|
|
81663
|
+
import { mkdir as mkdir18, readFile as readFile29, rm as rm11, writeFile as writeFile19 } from "node:fs/promises";
|
|
81372
81664
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
81373
|
-
import { dirname as
|
|
81665
|
+
import { dirname as dirname18, join as join20 } from "node:path";
|
|
81374
81666
|
var USAGE10 = `Usage: laze vault run <connection> --reason "<one plain sentence>" [--wait <s>] -- <command> [args...]
|
|
81375
81667
|
Runs the command with the connection's values in its environment, on a Laze agent's computer
|
|
81376
81668
|
or on a machine it runs on.`;
|
|
@@ -81409,7 +81701,7 @@ async function turnTokenOf4({
|
|
|
81409
81701
|
if (pinned) return pinned;
|
|
81410
81702
|
if (!turnFile) throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
81411
81703
|
try {
|
|
81412
|
-
return (await
|
|
81704
|
+
return (await readFile29(turnFile, "utf8")).trim();
|
|
81413
81705
|
} catch {
|
|
81414
81706
|
throw new CliUsageError(`${command} works only during an agent's turn`);
|
|
81415
81707
|
}
|
|
@@ -81419,11 +81711,11 @@ function runKeyPathOf({
|
|
|
81419
81711
|
connection
|
|
81420
81712
|
}) {
|
|
81421
81713
|
const name2 = createHash2("sha256").update(connection).digest("hex");
|
|
81422
|
-
const base = turnFile ?
|
|
81423
|
-
return
|
|
81714
|
+
const base = turnFile ? dirname18(turnFile) : join20(tmpdir2(), "laze-vault");
|
|
81715
|
+
return join20(base, "vault-run-keys", `${name2}.json`);
|
|
81424
81716
|
}
|
|
81425
81717
|
async function runKeyAt({ path }) {
|
|
81426
|
-
const saved3 = await
|
|
81718
|
+
const saved3 = await readFile29(path, "utf8").then(
|
|
81427
81719
|
(text2) => JSON.parse(text2),
|
|
81428
81720
|
() => void 0
|
|
81429
81721
|
);
|
|
@@ -81433,7 +81725,7 @@ async function runKeyAt({ path }) {
|
|
|
81433
81725
|
}
|
|
81434
81726
|
const fresh = await generateEcdhKeys();
|
|
81435
81727
|
const jwk = await globalThis.crypto.subtle.exportKey("jwk", fresh.privateKey);
|
|
81436
|
-
await mkdir18(
|
|
81728
|
+
await mkdir18(dirname18(path), { recursive: true, mode: 448 });
|
|
81437
81729
|
await writeFile19(path, JSON.stringify({ publicKey: fresh.publicKey, privateKey: jwk }), {
|
|
81438
81730
|
mode: 384
|
|
81439
81731
|
});
|
|
@@ -81616,7 +81908,7 @@ var USAGE11 = [
|
|
|
81616
81908
|
' laze machine exec <machine> --vault <connection> [--vault <other>] --reason "<why>" -- <command>',
|
|
81617
81909
|
" the same, with vault connections in its environment",
|
|
81618
81910
|
" laze machine host <machine> <agent> [--when-offline wait|computer] run your personal agent there (people)",
|
|
81619
|
-
" laze machine unhost <agent> run the agent on your computer again (people)",
|
|
81911
|
+
" laze machine unhost <agent> run the agent on your agent computer again (people)",
|
|
81620
81912
|
" laze machine remove <machine> cut the machine off and forget it (people)",
|
|
81621
81913
|
MACHINE_ACCESS_USAGE
|
|
81622
81914
|
].join("\n");
|
|
@@ -81822,7 +82114,7 @@ ${USAGE11}`);
|
|
|
81822
82114
|
});
|
|
81823
82115
|
if (args.flags.json) return context.out(`${JSON.stringify(machine2, null, 2)}
|
|
81824
82116
|
`);
|
|
81825
|
-
const offline = whenOffline === "wait" ? `${agent2} waits` : `${agent2} answers from your computer`;
|
|
82117
|
+
const offline = whenOffline === "wait" ? `${agent2} waits` : `${agent2} answers from your agent computer`;
|
|
81826
82118
|
context.out(
|
|
81827
82119
|
`${agent2} now runs on ${machine2.name}. While ${machine2.name} is offline, ${offline}.
|
|
81828
82120
|
`
|
|
@@ -81835,7 +82127,7 @@ async function unhost({ context, args }) {
|
|
|
81835
82127
|
const done = await client.post(COMPUTE_REST_PATHS.unhost, { agent: agent2 });
|
|
81836
82128
|
if (args.flags.json) return context.out(`${JSON.stringify(done, null, 2)}
|
|
81837
82129
|
`);
|
|
81838
|
-
context.out(`${agent2} runs on your computer again.
|
|
82130
|
+
context.out(`${agent2} runs on your agent computer again.
|
|
81839
82131
|
`);
|
|
81840
82132
|
}
|
|
81841
82133
|
async function remove4({ context, args }) {
|
|
@@ -82106,14 +82398,14 @@ async function serveMcp({
|
|
|
82106
82398
|
}
|
|
82107
82399
|
|
|
82108
82400
|
// src/services/mount-files.service.ts
|
|
82109
|
-
import { mkdir as mkdir19, readFile as
|
|
82110
|
-
import { dirname as
|
|
82401
|
+
import { mkdir as mkdir19, readFile as readFile30, rm as rm12, writeFile as writeFile20 } from "node:fs/promises";
|
|
82402
|
+
import { dirname as dirname19, relative as relative5, resolve as resolve11 } from "node:path";
|
|
82111
82403
|
async function textArgument({
|
|
82112
82404
|
context,
|
|
82113
82405
|
value
|
|
82114
82406
|
}) {
|
|
82115
82407
|
if (value === "-") return context.readStdin();
|
|
82116
|
-
if (value.startsWith("@")) return
|
|
82408
|
+
if (value.startsWith("@")) return readFile30(resolve11(context.cwd, value.slice(1)), "utf8");
|
|
82117
82409
|
return value;
|
|
82118
82410
|
}
|
|
82119
82411
|
function turnChannel({ context, args }) {
|
|
@@ -82133,7 +82425,7 @@ async function writeMount({
|
|
|
82133
82425
|
const inside = relative5(root, target);
|
|
82134
82426
|
if (!inside || inside.startsWith(".."))
|
|
82135
82427
|
throw new Error(`Refusing to write outside ${root}: ${file3.path}`);
|
|
82136
|
-
await mkdir19(
|
|
82428
|
+
await mkdir19(dirname19(target), { recursive: true });
|
|
82137
82429
|
await writeFile20(target, file3.content);
|
|
82138
82430
|
}
|
|
82139
82431
|
return root;
|
|
@@ -82775,8 +83067,8 @@ ${OPS_USAGE}`);
|
|
|
82775
83067
|
}
|
|
82776
83068
|
|
|
82777
83069
|
// src/services/release-watch.service.ts
|
|
82778
|
-
import { mkdir as mkdir20, readFile as
|
|
82779
|
-
import { dirname as
|
|
83070
|
+
import { mkdir as mkdir20, readFile as readFile31, realpath, writeFile as writeFile21 } from "node:fs/promises";
|
|
83071
|
+
import { dirname as dirname20, join as join21 } from "node:path";
|
|
82780
83072
|
|
|
82781
83073
|
// src/rules/cli-update.rules.ts
|
|
82782
83074
|
var CLI_PACKAGE_LATEST = "@lazehq/cli@latest";
|
|
@@ -82877,16 +83169,16 @@ async function startedUpdate({
|
|
|
82877
83169
|
if (context.environment.inherited.LAZE_AUTO_UPDATE === "0") return null;
|
|
82878
83170
|
const plan2 = updatePlanOf({ script: await scriptOf(context) });
|
|
82879
83171
|
if (plan2.kind !== "install") return null;
|
|
82880
|
-
const folder =
|
|
82881
|
-
const stamp =
|
|
82882
|
-
const last = await
|
|
83172
|
+
const folder = dirname20(context.environment.configPath);
|
|
83173
|
+
const stamp = join21(folder, "auto-update.json");
|
|
83174
|
+
const last = await readFile31(stamp, "utf8").then((text2) => JSON.parse(text2)).catch(() => null);
|
|
82883
83175
|
const now = context.nowMs();
|
|
82884
83176
|
if (last?.server === server && now - last.atMs < RETRY_AFTER_MS) return null;
|
|
82885
83177
|
await mkdir20(folder, { recursive: true, mode: 448 });
|
|
82886
83178
|
await writeFile21(stamp, JSON.stringify({ server, atMs: now }), { mode: 384 });
|
|
82887
83179
|
context.processes.spawnDetached({
|
|
82888
83180
|
argv: [...context.program, "update"],
|
|
82889
|
-
logPath:
|
|
83181
|
+
logPath: join21(folder, "auto-update.log")
|
|
82890
83182
|
});
|
|
82891
83183
|
return { manager: plan2.manager };
|
|
82892
83184
|
}
|
|
@@ -82916,19 +83208,19 @@ function watchingRelease({
|
|
|
82916
83208
|
}
|
|
82917
83209
|
|
|
82918
83210
|
// src/services/rush-guard.service.ts
|
|
82919
|
-
import { readFile as
|
|
83211
|
+
import { readFile as readFile32, rm as rm13 } from "node:fs/promises";
|
|
82920
83212
|
var WATCH_MS3 = 2e3;
|
|
82921
83213
|
var RETRY_MS2 = 3e4;
|
|
82922
83214
|
async function guardRound({ context, client, name: name2, lock, claudePid, session, rush }) {
|
|
82923
83215
|
const key = session ? sessionKeyOf({ session }) : void 0;
|
|
82924
|
-
if (key && await liveElsewhere({ context, key, claudePid })) return true;
|
|
83216
|
+
if (key && await liveElsewhere({ context, key, claudePid, asleepCounts: false })) return true;
|
|
82925
83217
|
const holder = await holderOf({ path: lock });
|
|
82926
83218
|
if (holder?.pid !== context.processes.pid) {
|
|
82927
83219
|
if (!await takeLock({ context, path: lock, claudePid, ...sessionIdOf({ session }) }))
|
|
82928
83220
|
return true;
|
|
82929
83221
|
}
|
|
82930
83222
|
const due = await dueFromSpool({ context, profile: name2, seen: async () => "", pushedToo: true });
|
|
82931
|
-
const messages = due.length > 0 ? due : await
|
|
83223
|
+
const messages = due.length > 0 ? due : await takeRound2({ context, client, claudePid: 0, session });
|
|
82932
83224
|
if (messages.length === 0) return false;
|
|
82933
83225
|
await keepTaken({ context, profile: name2, messages });
|
|
82934
83226
|
const self2 = await currentNameOf({ context, client, profile: name2 });
|
|
@@ -82952,7 +83244,7 @@ async function rushWakeHook({ context, args }) {
|
|
|
82952
83244
|
while (context.processes.alive(claudePid)) await context.sleep(WATCH_MS3);
|
|
82953
83245
|
const { client, name: name2 } = await signedIn({ context, args });
|
|
82954
83246
|
const noted = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
|
|
82955
|
-
const session = await
|
|
83247
|
+
const session = await readFile32(noted, "utf8").then(
|
|
82956
83248
|
(text2) => JSON.parse(text2),
|
|
82957
83249
|
() => void 0
|
|
82958
83250
|
);
|
|
@@ -83118,8 +83410,8 @@ async function schedule({ context, args }) {
|
|
|
83118
83410
|
}
|
|
83119
83411
|
|
|
83120
83412
|
// src/services/skill-commands.service.ts
|
|
83121
|
-
import { readdir as
|
|
83122
|
-
import { join as
|
|
83413
|
+
import { readdir as readdir7, readFile as readFile33 } from "node:fs/promises";
|
|
83414
|
+
import { join as join22, relative as relative6, resolve as resolve12 } from "node:path";
|
|
83123
83415
|
var USAGE16 = `Usage:
|
|
83124
83416
|
laze skill list [--agent <agentId>]
|
|
83125
83417
|
laze skill install <catalogue-id> [--as <name>] [--agent <agentId>]
|
|
@@ -83136,12 +83428,12 @@ var USAGE16 = `Usage:
|
|
|
83136
83428
|
--agent names the agent with a person's key; an agent's key works on its own skills.
|
|
83137
83429
|
With a person's key, list without --agent shows every agent's skills.`;
|
|
83138
83430
|
async function folderFiles({ root }) {
|
|
83139
|
-
const entries = await
|
|
83431
|
+
const entries = await readdir7(root, { recursive: true, withFileTypes: true });
|
|
83140
83432
|
const files2 = [];
|
|
83141
83433
|
for (const entry of entries) {
|
|
83142
83434
|
if (!entry.isFile()) continue;
|
|
83143
|
-
const full =
|
|
83144
|
-
files2.push({ path: relative6(root, full), content: await
|
|
83435
|
+
const full = join22(entry.parentPath, entry.name);
|
|
83436
|
+
files2.push({ path: relative6(root, full), content: await readFile33(full, "utf8") });
|
|
83145
83437
|
}
|
|
83146
83438
|
return files2.toSorted((a, b) => a.path.localeCompare(b.path));
|
|
83147
83439
|
}
|
|
@@ -83239,7 +83531,7 @@ async function skillUpdate({ context, args }) {
|
|
|
83239
83531
|
if (!name2 || !newName && description === void 0 && !skillMdFile) {
|
|
83240
83532
|
throw new CliUsageError(USAGE16);
|
|
83241
83533
|
}
|
|
83242
|
-
const skillMd = skillMdFile ? await
|
|
83534
|
+
const skillMd = skillMdFile ? await readFile33(resolve12(context.cwd, skillMdFile), "utf8") : void 0;
|
|
83243
83535
|
const { client } = await signedIn({ context, args });
|
|
83244
83536
|
const updated = await client.post("/api/skills/update", {
|
|
83245
83537
|
name: name2,
|
|
@@ -83285,7 +83577,7 @@ async function skill({ context, args }) {
|
|
|
83285
83577
|
}
|
|
83286
83578
|
|
|
83287
83579
|
// src/services/slack-commands.service.ts
|
|
83288
|
-
import { readFile as
|
|
83580
|
+
import { readFile as readFile34 } from "node:fs/promises";
|
|
83289
83581
|
import { resolve as resolve13 } from "node:path";
|
|
83290
83582
|
var SLACK_USAGE = `Usage (a person's key; Slack stays the source, the bot joins no channel by itself):
|
|
83291
83583
|
laze slack overview connected Slack workspaces, mirrors, your link
|
|
@@ -83333,7 +83625,7 @@ async function secretLines({ context, args }) {
|
|
|
83333
83625
|
throw new CliUsageError("A secret never goes in a flag: pipe it on stdin or use --from-file.");
|
|
83334
83626
|
}
|
|
83335
83627
|
const file3 = flagText({ args, name: "from-file" });
|
|
83336
|
-
const text2 = file3 ? await
|
|
83628
|
+
const text2 = file3 ? await readFile34(resolve13(context.cwd, file3), "utf8") : await context.readStdin();
|
|
83337
83629
|
return text2.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
83338
83630
|
}
|
|
83339
83631
|
async function secretsOf({
|
|
@@ -83637,7 +83929,7 @@ async function slack({
|
|
|
83637
83929
|
}
|
|
83638
83930
|
|
|
83639
83931
|
// src/services/sso-commands.service.ts
|
|
83640
|
-
import { readFile as
|
|
83932
|
+
import { readFile as readFile35 } from "node:fs/promises";
|
|
83641
83933
|
var SSO_USAGE = `Usage:
|
|
83642
83934
|
laze sso domains claimed domains and how each signs in (admins)
|
|
83643
83935
|
laze sso claim <domain> the TXT record that proves the domain
|
|
@@ -83724,7 +84016,7 @@ function refuseSecretFlags({ args }) {
|
|
|
83724
84016
|
}
|
|
83725
84017
|
async function clientSecretOf({ context, args }) {
|
|
83726
84018
|
const file3 = flagText({ args, name: "from-file" });
|
|
83727
|
-
const text2 = file3 ? await
|
|
84019
|
+
const text2 = file3 ? await readFile35(file3, "utf8") : await context.readStdin();
|
|
83728
84020
|
const secret = text2.trim();
|
|
83729
84021
|
if (!secret) throw new CliUsageError("No client secret: pipe it on stdin or use --from-file.");
|
|
83730
84022
|
return secret;
|
|
@@ -84098,7 +84390,7 @@ async function vaultScrub({ context, args }) {
|
|
|
84098
84390
|
}
|
|
84099
84391
|
|
|
84100
84392
|
// src/services/whatsapp-business-commands.service.ts
|
|
84101
|
-
import { readFile as
|
|
84393
|
+
import { readFile as readFile36 } from "node:fs/promises";
|
|
84102
84394
|
import { resolve as resolve14 } from "node:path";
|
|
84103
84395
|
|
|
84104
84396
|
// ../../modules/whatsapp-business/contract/src/whatsapp-business.prices.ts
|
|
@@ -84518,7 +84810,7 @@ async function secretsOf2({ context, args }) {
|
|
|
84518
84810
|
const fromConnection = flagText({ args, name: "from-vault" });
|
|
84519
84811
|
if (fromConnection) return { fromConnection };
|
|
84520
84812
|
const file3 = flagText({ args, name: "from-file" });
|
|
84521
|
-
const text2 = file3 ? await
|
|
84813
|
+
const text2 = file3 ? await readFile36(resolve14(context.cwd, file3), "utf8") : await context.readStdin();
|
|
84522
84814
|
const lines = text2.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
84523
84815
|
if (lines.length !== 2) {
|
|
84524
84816
|
throw new CliUsageError(
|
|
@@ -85099,7 +85391,7 @@ async function flags({ context, args }) {
|
|
|
85099
85391
|
}
|
|
85100
85392
|
|
|
85101
85393
|
// src/services/workspace-commands.service.ts
|
|
85102
|
-
import { readFile as
|
|
85394
|
+
import { readFile as readFile37 } from "node:fs/promises";
|
|
85103
85395
|
import { resolve as resolve16 } from "node:path";
|
|
85104
85396
|
var ROLE_NAMES2 = {
|
|
85105
85397
|
OWNER: "Owner",
|
|
@@ -85282,7 +85574,7 @@ var LOGO_USAGE = "Usage: laze workspace logo set <file.png|jpg|webp> | laze work
|
|
|
85282
85574
|
async function readLogo({ context, file: file3 }) {
|
|
85283
85575
|
let bytes;
|
|
85284
85576
|
try {
|
|
85285
|
-
bytes = new Uint8Array(await
|
|
85577
|
+
bytes = new Uint8Array(await readFile37(resolve16(context.cwd, file3)));
|
|
85286
85578
|
} catch {
|
|
85287
85579
|
throw new CliUsageError(`No file to read at ${file3}.`);
|
|
85288
85580
|
}
|
|
@@ -85589,7 +85881,7 @@ var HELP = `laze: work in a Laze workspace from your terminal or your agent.
|
|
|
85589
85881
|
to your vault first; --save saves it without asking,
|
|
85590
85882
|
--as-is sends it raw, --keychain workspace saves it
|
|
85591
85883
|
for everyone
|
|
85592
|
-
laze inbox [--wait] [--timeout <s>]
|
|
85884
|
+
laze inbox [--wait] [--timeout <s>] [--take] messages addressed to your agent (--take: from outside its bound session)
|
|
85593
85885
|
laze search <query> [--channel <c>] [--limit <n>] search messages, and Slack when yours is linked
|
|
85594
85886
|
the sidebar's search: words, "phrases", from:@name in:#channel has: before: after: is:thread
|
|
85595
85887
|
laze history <channel> [--before <id>] [--limit <n>] a channel's messages, oldest first
|
|
@@ -85674,12 +85966,12 @@ var HELP = `laze: work in a Laze workspace from your terminal or your agent.
|
|
|
85674
85966
|
laze machine list | health <machine> own machines: online or not, system, disk and tools
|
|
85675
85967
|
laze machine get|rename|grant|revoke|budget <machine> one machine, its name, who it is shared with, its cap
|
|
85676
85968
|
laze machine status whether Laze can rent machines here
|
|
85677
|
-
laze computer status | sizes your computer: size, CPU, memory, disk, each agent's share, prices
|
|
85969
|
+
laze computer status | sizes your agent computer: size, CPU, memory, disk, each agent's share, prices
|
|
85678
85970
|
laze computer upgrade <size> small, medium, large or xl (admins); only after the person said yes in chat
|
|
85679
85971
|
laze computer request <size> | cancel <request> ask the admins for a size, or withdraw the ask
|
|
85680
85972
|
laze computer list everyone's computers, size and monthly cost (Owners and Admins)
|
|
85681
85973
|
laze computer restart [--person <user id>] stop and start a computer that runs fine (people, not agents)
|
|
85682
|
-
laze computer mine | add <name> --size <size> [--shared] your
|
|
85974
|
+
laze computer mine | add <name> --size <size> [--shared] your agent computers; add one (Owners and Admins)
|
|
85683
85975
|
laze computer remove <computer> [--to <computer>] | move <agent> <computer|default> delete one, or move an agent
|
|
85684
85976
|
laze computer creators <computer> --everyone | --people <id,id> who may add agents on a shared computer
|
|
85685
85977
|
laze ip [status|on <country>|off|countries|domains [add|remove|reset]|list] your dedicated IP for sites that block Laze
|
|
@@ -85689,7 +85981,7 @@ var HELP = `laze: work in a Laze workspace from your terminal or your agent.
|
|
|
85689
85981
|
When someone wants work done on their own machine, run it there; if it is offline, say so and go on where you run
|
|
85690
85982
|
laze machine exec <machine> --vault <connection> --reason "<why>" -- <command> the same, with a vault connection
|
|
85691
85983
|
laze machine host <machine> <agent> [--when-offline wait|computer] run your personal agent on your machine
|
|
85692
|
-
laze machine unhost <agent> run the agent on your computer again
|
|
85984
|
+
laze machine unhost <agent> run the agent on your agent computer again
|
|
85693
85985
|
laze whatsapp chats|read <machine> [<chat>] [--limit <n>] a person's WhatsApp, through their own machine
|
|
85694
85986
|
laze whatsapp send <machine> <chat> "<text>" send as its owner; each message waits for their approval
|
|
85695
85987
|
laze whatsapp pair|unpair <machine>, pairing|cancel <id> link WhatsApp on your own machine (owner)
|
|
@@ -85950,8 +86242,8 @@ async function runCli({
|
|
|
85950
86242
|
// src/services/processes.service.ts
|
|
85951
86243
|
import { execFile as execFile2, spawn as spawn4 } from "node:child_process";
|
|
85952
86244
|
import { mkdirSync, openSync } from "node:fs";
|
|
85953
|
-
import { readFile as
|
|
85954
|
-
import { dirname as
|
|
86245
|
+
import { readFile as readFile38, readlink } from "node:fs/promises";
|
|
86246
|
+
import { dirname as dirname21 } from "node:path";
|
|
85955
86247
|
import { promisify as promisify2 } from "node:util";
|
|
85956
86248
|
var run3 = promisify2(execFile2);
|
|
85957
86249
|
function alive(pid) {
|
|
@@ -85964,15 +86256,15 @@ function alive(pid) {
|
|
|
85964
86256
|
}
|
|
85965
86257
|
}
|
|
85966
86258
|
async function argsOf(pid) {
|
|
85967
|
-
const raw = await
|
|
86259
|
+
const raw = await readFile38(`/proc/${pid}/cmdline`, "utf8").catch(() => void 0);
|
|
85968
86260
|
if (raw) return raw.split("\0").filter(Boolean);
|
|
85969
86261
|
const listed = await run3("ps", ["-o", "args=", "-p", String(pid)]).catch(() => void 0);
|
|
85970
86262
|
const line = listed?.stdout.trim();
|
|
85971
86263
|
return line ? line.split(/\s+/) : void 0;
|
|
85972
86264
|
}
|
|
85973
86265
|
async function parentOf(pid) {
|
|
85974
|
-
const
|
|
85975
|
-
const fromStat =
|
|
86266
|
+
const stat5 = await readFile38(`/proc/${pid}/stat`, "utf8").catch(() => void 0);
|
|
86267
|
+
const fromStat = stat5 ? Number(stat5.slice(stat5.lastIndexOf(")") + 2).split(" ")[1]) : NaN;
|
|
85976
86268
|
if (fromStat > 0) return fromStat;
|
|
85977
86269
|
const listed = await run3("ps", ["-o", "ppid=", "-p", String(pid)]).catch(() => void 0);
|
|
85978
86270
|
const parent = Number(listed?.stdout.trim());
|
|
@@ -85988,7 +86280,7 @@ async function cwdOf(pid) {
|
|
|
85988
86280
|
return line ? line.slice(1) : void 0;
|
|
85989
86281
|
}
|
|
85990
86282
|
function spawnDetached({ argv, logPath }) {
|
|
85991
|
-
mkdirSync(
|
|
86283
|
+
mkdirSync(dirname21(logPath), { recursive: true, mode: 448 });
|
|
85992
86284
|
const log = openSync(logPath, "a", 384);
|
|
85993
86285
|
const [program = "", ...rest] = argv;
|
|
85994
86286
|
const child = spawn4(program, rest, { detached: true, stdio: ["ignore", log, log] });
|
|
@@ -86095,7 +86387,12 @@ function sleep(ms, signal) {
|
|
|
86095
86387
|
signal?.addEventListener("abort", stop3, { once: true });
|
|
86096
86388
|
});
|
|
86097
86389
|
}
|
|
86390
|
+
function quietOnClosedPipe(error62) {
|
|
86391
|
+
if (error62.code !== "EPIPE") throw error62;
|
|
86392
|
+
process.exit(process.exitCode ?? 0);
|
|
86393
|
+
}
|
|
86098
86394
|
if (true) {
|
|
86395
|
+
process.stdout.on("error", quietOnClosedPipe);
|
|
86099
86396
|
const environment = cliEnvironment();
|
|
86100
86397
|
const ask = terminalAsk();
|
|
86101
86398
|
process.exitCode = await runCli({
|