@alook/daemon 0.1.29 → 0.1.30
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/cli/index.js +552 -166
- package/dist/index.js +399 -89
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -98,7 +98,7 @@ var init_nanoid = () => {};
|
|
|
98
98
|
// src/cli/index.ts
|
|
99
99
|
import { Command, CommanderError } from "commander";
|
|
100
100
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
101
|
-
import { randomUUID as
|
|
101
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
102
102
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
103
103
|
|
|
104
104
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
@@ -16762,6 +16762,10 @@ var OwnerDiagnosticReportSchema = exports_external.discriminatedUnion("status",
|
|
|
16762
16762
|
// ../shared/src/community-cli-contract.ts
|
|
16763
16763
|
var DM_SERVER = ".dm";
|
|
16764
16764
|
var CONTROL_HEARTBEAT_CAPABILITY = "control-heartbeat-v1";
|
|
16765
|
+
var AgentInterruptRequestSchema = exports_external.strictObject({
|
|
16766
|
+
type: exports_external.literal("agent:interrupt"),
|
|
16767
|
+
agentId: exports_external.string().min(1).max(128)
|
|
16768
|
+
});
|
|
16765
16769
|
function parseRef(ref) {
|
|
16766
16770
|
if (!ref.startsWith("/"))
|
|
16767
16771
|
throw new Error(`ref must start with "/": ${ref}`);
|
|
@@ -16853,6 +16857,7 @@ var HostCommandSchema = exports_external.discriminatedUnion("type", [
|
|
|
16853
16857
|
type: exports_external.literal("agent:stop"),
|
|
16854
16858
|
agentId: exports_external.string().min(1)
|
|
16855
16859
|
}),
|
|
16860
|
+
AgentInterruptRequestSchema,
|
|
16856
16861
|
exports_external.object({
|
|
16857
16862
|
type: exports_external.literal("agent:reset"),
|
|
16858
16863
|
agentId: exports_external.string().min(1),
|
|
@@ -16920,7 +16925,6 @@ var MAX_FOLDER_NAME_LENGTH = 100;
|
|
|
16920
16925
|
var MAX_PROFILE_NAME_LENGTH = 100;
|
|
16921
16926
|
var MAX_PROFILE_ABOUT_LENGTH = 1000;
|
|
16922
16927
|
var MAX_MESSAGE_CONTENT_LENGTH = 4000;
|
|
16923
|
-
var MAX_EMOJI_BYTES = 32;
|
|
16924
16928
|
var MAX_ATTACHMENTS_PER_MESSAGE = 10;
|
|
16925
16929
|
var MAX_ATTACHMENT_SIZE_BYTES = 25 * 1024 * 1024;
|
|
16926
16930
|
var MAX_ATTACHMENT_THUMBNAIL_EDGE_PX = 1024;
|
|
@@ -17830,17 +17834,18 @@ var CommunityAgentNapRequestSchema = exports_external.object({
|
|
|
17830
17834
|
message: "handoff is required"
|
|
17831
17835
|
})
|
|
17832
17836
|
});
|
|
17833
|
-
var
|
|
17837
|
+
var CommunityAgentMessagePropertyRequestSchema = exports_external.object({
|
|
17834
17838
|
channel: exports_external.string().min(1),
|
|
17835
17839
|
seq: CommunityAgentPositiveSeqSchema,
|
|
17836
|
-
|
|
17840
|
+
property: exports_external.unknown()
|
|
17837
17841
|
});
|
|
17838
17842
|
var CommunityAgentFriendRequestSchema = exports_external.object({
|
|
17839
17843
|
username: exports_external.string().min(1)
|
|
17840
17844
|
});
|
|
17841
17845
|
var CommunityAgentListFriendsSchema = exports_external.object({});
|
|
17842
17846
|
var AuditLogCliInvocationPayloadSchema = exports_external.object({
|
|
17843
|
-
subcommand: exports_external.string().min(1)
|
|
17847
|
+
subcommand: exports_external.string().min(1),
|
|
17848
|
+
propertyType: exports_external.enum(["emoji", "tag", "mark"]).optional()
|
|
17844
17849
|
});
|
|
17845
17850
|
var AuditLogToolCallPayloadSchema = exports_external.object({
|
|
17846
17851
|
name: exports_external.string().min(1),
|
|
@@ -19136,6 +19141,14 @@ function proxyServerApiFromEnv(prefix = "ALOOK", env = process.env) {
|
|
|
19136
19141
|
function createProxyServerApi(config2) {
|
|
19137
19142
|
const fetchImpl = config2.fetchImpl ?? fetch;
|
|
19138
19143
|
const base = config2.proxyUrl.replace(/\/+$/, "");
|
|
19144
|
+
const propertyAuditQuery = (property) => {
|
|
19145
|
+
if (!property || typeof property !== "object" || Array.isArray(property))
|
|
19146
|
+
return "";
|
|
19147
|
+
const type = property.type;
|
|
19148
|
+
if (type !== "emoji" && type !== "tag" && type !== "mark")
|
|
19149
|
+
return "";
|
|
19150
|
+
return `?type=${encodeURIComponent(type)}`;
|
|
19151
|
+
};
|
|
19139
19152
|
async function parseJsonResponse(res, method) {
|
|
19140
19153
|
let text2;
|
|
19141
19154
|
try {
|
|
@@ -19253,17 +19266,37 @@ function createProxyServerApi(config2) {
|
|
|
19253
19266
|
});
|
|
19254
19267
|
return parseJsonResponse(res, "resolve");
|
|
19255
19268
|
}
|
|
19256
|
-
async function
|
|
19257
|
-
const res = await fetchImpl(`${base}/api/community/messages/${REF_PLACEHOLDER_ID}/
|
|
19269
|
+
async function callMessagePropertySet(req) {
|
|
19270
|
+
const res = await fetchImpl(`${base}/api/community/messages/${REF_PLACEHOLDER_ID}/properties${propertyAuditQuery(req.property)}`, {
|
|
19258
19271
|
method: "PUT",
|
|
19259
19272
|
headers: {
|
|
19260
19273
|
"content-type": "application/json",
|
|
19261
19274
|
authorization: `Bearer ${config2.voucher}`
|
|
19262
19275
|
},
|
|
19263
|
-
body: JSON.stringify(
|
|
19276
|
+
body: JSON.stringify(req)
|
|
19264
19277
|
});
|
|
19265
|
-
|
|
19266
|
-
|
|
19278
|
+
return parseJsonResponse(res, "messagePropertySet");
|
|
19279
|
+
}
|
|
19280
|
+
async function callMessagePropertyList(req) {
|
|
19281
|
+
const q = new URLSearchParams;
|
|
19282
|
+
q.set("ref", req.channel);
|
|
19283
|
+
q.set("seq", String(req.seq));
|
|
19284
|
+
const res = await fetchImpl(`${base}/api/community/messages/${REF_PLACEHOLDER_ID}/properties?${q.toString()}`, {
|
|
19285
|
+
method: "GET",
|
|
19286
|
+
headers: { authorization: `Bearer ${config2.voucher}` }
|
|
19287
|
+
});
|
|
19288
|
+
return parseJsonResponse(res, "messagePropertyList");
|
|
19289
|
+
}
|
|
19290
|
+
async function callMessagePropertyRemove(req) {
|
|
19291
|
+
const res = await fetchImpl(`${base}/api/community/messages/${REF_PLACEHOLDER_ID}/properties${propertyAuditQuery(req.property)}`, {
|
|
19292
|
+
method: "DELETE",
|
|
19293
|
+
headers: {
|
|
19294
|
+
"content-type": "application/json",
|
|
19295
|
+
authorization: `Bearer ${config2.voucher}`
|
|
19296
|
+
},
|
|
19297
|
+
body: JSON.stringify(req)
|
|
19298
|
+
});
|
|
19299
|
+
return parseJsonResponse(res, "messagePropertyRemove");
|
|
19267
19300
|
}
|
|
19268
19301
|
async function callListMembers(req) {
|
|
19269
19302
|
const q = new URLSearchParams;
|
|
@@ -19315,28 +19348,6 @@ function createProxyServerApi(config2) {
|
|
|
19315
19348
|
});
|
|
19316
19349
|
return parseJsonResponse(res, "inboxPull");
|
|
19317
19350
|
}
|
|
19318
|
-
async function callMarkSet(req) {
|
|
19319
|
-
const res = await fetchImpl(`${base}/api/community/messages/resolve/marks`, {
|
|
19320
|
-
method: "PUT",
|
|
19321
|
-
headers: {
|
|
19322
|
-
"content-type": "application/json",
|
|
19323
|
-
authorization: `Bearer ${config2.voucher}`
|
|
19324
|
-
},
|
|
19325
|
-
body: JSON.stringify(req)
|
|
19326
|
-
});
|
|
19327
|
-
await parseJsonResponse(res, "markSet");
|
|
19328
|
-
}
|
|
19329
|
-
async function callMarkRemove(req) {
|
|
19330
|
-
const res = await fetchImpl(`${base}/api/community/messages/resolve/marks`, {
|
|
19331
|
-
method: "DELETE",
|
|
19332
|
-
headers: {
|
|
19333
|
-
"content-type": "application/json",
|
|
19334
|
-
authorization: `Bearer ${config2.voucher}`
|
|
19335
|
-
},
|
|
19336
|
-
body: JSON.stringify(req)
|
|
19337
|
-
});
|
|
19338
|
-
await parseJsonResponse(res, "markRemove");
|
|
19339
|
-
}
|
|
19340
19351
|
async function callListMarks() {
|
|
19341
19352
|
const res = await fetchImpl(`${base}/api/community/users/me/marks`, {
|
|
19342
19353
|
method: "GET",
|
|
@@ -19493,11 +19504,32 @@ function createProxyServerApi(config2) {
|
|
|
19493
19504
|
}
|
|
19494
19505
|
return { server: projectServer(body.server) };
|
|
19495
19506
|
}
|
|
19507
|
+
async function callLeaveChannel(req) {
|
|
19508
|
+
const parsed = parseRef(req.channel);
|
|
19509
|
+
const scope = parsed.threadRootSeq === undefined ? "channel" : "thread";
|
|
19510
|
+
const collection = scope === "thread" ? "participants" : "members";
|
|
19511
|
+
const res = await fetchImpl(`${base}/api/community/channels/${REF_PLACEHOLDER_ID}/${collection}/self?ref=${encodeURIComponent(req.channel)}`, {
|
|
19512
|
+
method: "DELETE",
|
|
19513
|
+
headers: { authorization: `Bearer ${config2.voucher}` }
|
|
19514
|
+
});
|
|
19515
|
+
await parseJsonResponse(res, "leaveChannel");
|
|
19516
|
+
return { left: req.channel, scope };
|
|
19517
|
+
}
|
|
19518
|
+
async function callLeaveServer(req) {
|
|
19519
|
+
const res = await fetchImpl(`${base}/api/community/servers/${REF_PLACEHOLDER_ID}/leave?server=${encodeURIComponent(req.server)}`, {
|
|
19520
|
+
method: "POST",
|
|
19521
|
+
headers: { authorization: `Bearer ${config2.voucher}` }
|
|
19522
|
+
});
|
|
19523
|
+
await parseJsonResponse(res, "leaveServer");
|
|
19524
|
+
return { left: req.server, scope: "server" };
|
|
19525
|
+
}
|
|
19496
19526
|
return {
|
|
19497
19527
|
listServers: (_r) => callListServers(),
|
|
19498
19528
|
joinServer: callJoinServer,
|
|
19529
|
+
leaveServer: callLeaveServer,
|
|
19499
19530
|
listChannels: callListChannels,
|
|
19500
19531
|
channelMember: callChannelMember,
|
|
19532
|
+
leaveChannel: callLeaveChannel,
|
|
19501
19533
|
inboxPull: callInboxPull,
|
|
19502
19534
|
inboxSnapshot: (_r) => callInboxSnapshot(),
|
|
19503
19535
|
ack: callAck,
|
|
@@ -19508,9 +19540,9 @@ function createProxyServerApi(config2) {
|
|
|
19508
19540
|
attachmentUpload: callUpload,
|
|
19509
19541
|
attachmentDownload: callDownload,
|
|
19510
19542
|
updateProfile: callUpdateProfile,
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19543
|
+
messagePropertySet: callMessagePropertySet,
|
|
19544
|
+
messagePropertyList: callMessagePropertyList,
|
|
19545
|
+
messagePropertyRemove: callMessagePropertyRemove,
|
|
19514
19546
|
listMarks: (_r) => callListMarks(),
|
|
19515
19547
|
friendRequest: callFriendRequest,
|
|
19516
19548
|
listFriends: (_r) => callListFriends(),
|
|
@@ -19557,6 +19589,9 @@ function createDefaultAgentDriverHost(options = {}) {
|
|
|
19557
19589
|
};
|
|
19558
19590
|
}
|
|
19559
19591
|
|
|
19592
|
+
// agent-driver/dist/adapters/claude/index.js
|
|
19593
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
19594
|
+
|
|
19560
19595
|
// agent-driver/dist/controller/process-host.js
|
|
19561
19596
|
import { EventEmitter } from "events";
|
|
19562
19597
|
|
|
@@ -20136,6 +20171,7 @@ class ProcessLane {
|
|
|
20136
20171
|
admissionSequence = 0;
|
|
20137
20172
|
activeTerminalReceipt;
|
|
20138
20173
|
stopPromise;
|
|
20174
|
+
pendingInterrupt;
|
|
20139
20175
|
pendingPromptAdmission;
|
|
20140
20176
|
constructor(driver, ctx, opts = {}) {
|
|
20141
20177
|
this.driver = driver;
|
|
@@ -20175,12 +20211,14 @@ class ProcessLane {
|
|
|
20175
20211
|
try {
|
|
20176
20212
|
spawned = await this.driver.spawn(launchCtx);
|
|
20177
20213
|
} catch (error51) {
|
|
20214
|
+
this.settlePendingInterrupt(false);
|
|
20178
20215
|
this.settlePendingPrompt({ ok: false, reason: "runtime_error", error: String(error51) });
|
|
20179
20216
|
throw error51;
|
|
20180
20217
|
}
|
|
20181
20218
|
const { process: proc } = spawned;
|
|
20182
20219
|
this.process = proc;
|
|
20183
20220
|
this.attachProcess(proc);
|
|
20221
|
+
this.dispatchPendingInterrupt(proc);
|
|
20184
20222
|
this.armPendingPromptTimeout();
|
|
20185
20223
|
if (this.driver.execution.lifetime === "session" && !this.writableStdin(proc)) {
|
|
20186
20224
|
const rejection = this.stdinUnavailableAdmission();
|
|
@@ -20279,6 +20317,7 @@ class ProcessLane {
|
|
|
20279
20317
|
pending.resolve(admission);
|
|
20280
20318
|
}
|
|
20281
20319
|
stop(opts = {}) {
|
|
20320
|
+
this.settlePendingInterrupt(false);
|
|
20282
20321
|
this.settlePendingPrompt({ ok: false, reason: "closed", error: "runtime lane stopped before command admission" });
|
|
20283
20322
|
if (!this.process)
|
|
20284
20323
|
return Promise.resolve();
|
|
@@ -20297,11 +20336,39 @@ class ProcessLane {
|
|
|
20297
20336
|
proc.kill(opts?.signal ?? "SIGTERM");
|
|
20298
20337
|
}
|
|
20299
20338
|
}
|
|
20300
|
-
async interrupt() {
|
|
20339
|
+
async interrupt(input) {
|
|
20301
20340
|
const proc = this.process;
|
|
20302
|
-
if (!proc
|
|
20341
|
+
if (!proc) {
|
|
20342
|
+
if (!this.started)
|
|
20343
|
+
return false;
|
|
20344
|
+
if (this.pendingInterrupt)
|
|
20345
|
+
return this.pendingInterrupt.promise;
|
|
20346
|
+
let resolve;
|
|
20347
|
+
let reject;
|
|
20348
|
+
const promise2 = new Promise((res, rej) => {
|
|
20349
|
+
resolve = res;
|
|
20350
|
+
reject = rej;
|
|
20351
|
+
});
|
|
20352
|
+
this.pendingInterrupt = { input, promise: promise2, resolve, reject };
|
|
20353
|
+
return promise2;
|
|
20354
|
+
}
|
|
20355
|
+
if (this.closed)
|
|
20303
20356
|
return false;
|
|
20304
|
-
return
|
|
20357
|
+
return this.driver.interrupt(input, proc);
|
|
20358
|
+
}
|
|
20359
|
+
dispatchPendingInterrupt(proc) {
|
|
20360
|
+
const pending = this.pendingInterrupt;
|
|
20361
|
+
if (!pending)
|
|
20362
|
+
return;
|
|
20363
|
+
this.pendingInterrupt = undefined;
|
|
20364
|
+
this.driver.interrupt(pending.input, proc).then(pending.resolve, pending.reject);
|
|
20365
|
+
}
|
|
20366
|
+
settlePendingInterrupt(accepted) {
|
|
20367
|
+
const pending = this.pendingInterrupt;
|
|
20368
|
+
if (!pending)
|
|
20369
|
+
return;
|
|
20370
|
+
this.pendingInterrupt = undefined;
|
|
20371
|
+
pending.resolve(accepted);
|
|
20305
20372
|
}
|
|
20306
20373
|
updateSettings(input) {
|
|
20307
20374
|
return this.driver.updateSettings?.(input) ?? Promise.resolve({ status: "unsupported" });
|
|
@@ -20638,6 +20705,13 @@ function tryParseJsonLine(line) {
|
|
|
20638
20705
|
|
|
20639
20706
|
// agent-driver/dist/adapters/claude/normalizer.js
|
|
20640
20707
|
var API_ERROR_RE = /API Error:.*(?:Connection error|\b[45]\d{2}\b)/i;
|
|
20708
|
+
var CLAUDE_RESULT_ERROR_CODES = new Map([
|
|
20709
|
+
["error_max_turns", "claude.error_max_turns"],
|
|
20710
|
+
["error_during_execution", "claude.error_during_execution"],
|
|
20711
|
+
["error_max_budget_usd", "claude.error_max_budget_usd"],
|
|
20712
|
+
["error_max_structured_output_retries", "claude.error_max_structured_output_retries"]
|
|
20713
|
+
]);
|
|
20714
|
+
var CLAUDE_INTERRUPT_TERMINAL_REASONS = new Set(["aborted_streaming", "aborted_tools"]);
|
|
20641
20715
|
var CLAUDE_USAGE_COMPONENTS = [
|
|
20642
20716
|
"inputTokens",
|
|
20643
20717
|
"outputTokens",
|
|
@@ -20731,9 +20805,9 @@ class ClaudeEventNormalizer {
|
|
|
20731
20805
|
out.push({ kind: "assistant_reasoning_completed", text: block.thinking ?? "" });
|
|
20732
20806
|
} else if (block?.type === "text") {
|
|
20733
20807
|
const text2 = block.text ?? "";
|
|
20734
|
-
if (API_ERROR_RE.test(text2))
|
|
20735
|
-
out.push({ kind: "error", message: text2 });
|
|
20736
|
-
else
|
|
20808
|
+
if (API_ERROR_RE.test(text2)) {
|
|
20809
|
+
out.push({ kind: "error", code: "claude.api_error", message: text2 });
|
|
20810
|
+
} else
|
|
20737
20811
|
completedText.push(text2);
|
|
20738
20812
|
} else if (block?.type === "tool_use") {
|
|
20739
20813
|
out.push({ kind: "tool_call", name: block.name ?? "unknown_tool", input: block.input });
|
|
@@ -20759,14 +20833,19 @@ class ClaudeEventNormalizer {
|
|
|
20759
20833
|
}
|
|
20760
20834
|
handleResult(event, out) {
|
|
20761
20835
|
const rawOwner = typeof event.user_message_uuid === "string" && event.user_message_uuid.length > 0 ? event.user_message_uuid : null;
|
|
20762
|
-
const
|
|
20836
|
+
const interruptedTerminal = Boolean(this.turnProtocol && !rawOwner && event.subtype === "error_during_execution" && CLAUDE_INTERRUPT_TERMINAL_REASONS.has(event.terminal_reason));
|
|
20837
|
+
const turnOwner = rawOwner ? this.turnProtocol?.claimResult(rawOwner) ?? (this.turnProtocol ? null : `claude:${rawOwner}`) : interruptedTerminal ? this.turnProtocol.claimInterruptedResult() : null;
|
|
20763
20838
|
if (this.turnProtocol && !turnOwner)
|
|
20764
20839
|
return;
|
|
20765
20840
|
const usage = this.buildUsageTelemetry(event, rawOwner);
|
|
20766
20841
|
if (usage)
|
|
20767
20842
|
out.push(usage);
|
|
20768
|
-
if (event.is_error || event.subtype === "error_during_execution") {
|
|
20769
|
-
out.push({
|
|
20843
|
+
if (!interruptedTerminal && (event.is_error || event.subtype === "error_during_execution")) {
|
|
20844
|
+
out.push({
|
|
20845
|
+
kind: "error",
|
|
20846
|
+
code: CLAUDE_RESULT_ERROR_CODES.get(event.subtype) ?? "claude.result_error",
|
|
20847
|
+
message: String(event.result ?? "Claude runtime error")
|
|
20848
|
+
});
|
|
20770
20849
|
}
|
|
20771
20850
|
out.push({
|
|
20772
20851
|
kind: "turn_end",
|
|
@@ -21044,6 +21123,7 @@ class ClaudeTurnProtocol {
|
|
|
21044
21123
|
segmentOwnerUuid = null;
|
|
21045
21124
|
delivered = new Map;
|
|
21046
21125
|
awaitingFollowOn = false;
|
|
21126
|
+
interruptRequested = false;
|
|
21047
21127
|
finalized = false;
|
|
21048
21128
|
beginTurn() {
|
|
21049
21129
|
const uuid3 = randomUUID4();
|
|
@@ -21052,6 +21132,7 @@ class ClaudeTurnProtocol {
|
|
|
21052
21132
|
this.delivered.clear();
|
|
21053
21133
|
this.delivered.set(uuid3, { acknowledged: false, followOn: false });
|
|
21054
21134
|
this.awaitingFollowOn = false;
|
|
21135
|
+
this.interruptRequested = false;
|
|
21055
21136
|
this.finalized = false;
|
|
21056
21137
|
return this.receipt(uuid3);
|
|
21057
21138
|
}
|
|
@@ -21078,6 +21159,13 @@ class ClaudeTurnProtocol {
|
|
|
21078
21159
|
return false;
|
|
21079
21160
|
return this.delivered.get(this.rootUuid)?.acknowledged === true;
|
|
21080
21161
|
}
|
|
21162
|
+
hasActiveTurn() {
|
|
21163
|
+
return this.rootUuid !== null && !this.finalized;
|
|
21164
|
+
}
|
|
21165
|
+
noteInterruptRequested() {
|
|
21166
|
+
if (this.hasActiveTurn())
|
|
21167
|
+
this.interruptRequested = true;
|
|
21168
|
+
}
|
|
21081
21169
|
claimResult(userMessageUuid) {
|
|
21082
21170
|
if (this.finalized || !this.rootUuid || userMessageUuid !== this.segmentOwnerUuid)
|
|
21083
21171
|
return null;
|
|
@@ -21094,6 +21182,19 @@ class ClaudeTurnProtocol {
|
|
|
21094
21182
|
this.finalized = true;
|
|
21095
21183
|
return this.receipt(this.rootUuid);
|
|
21096
21184
|
}
|
|
21185
|
+
claimInterruptedResult() {
|
|
21186
|
+
if (this.finalized || !this.rootUuid || !this.interruptRequested)
|
|
21187
|
+
return null;
|
|
21188
|
+
const unacknowledged = [...this.delivered.values()].filter((input) => !input.acknowledged);
|
|
21189
|
+
if (unacknowledged.length > 0) {
|
|
21190
|
+
this.awaitingFollowOn = true;
|
|
21191
|
+
for (const input of unacknowledged)
|
|
21192
|
+
input.followOn = true;
|
|
21193
|
+
return null;
|
|
21194
|
+
}
|
|
21195
|
+
this.finalized = true;
|
|
21196
|
+
return this.receipt(this.rootUuid);
|
|
21197
|
+
}
|
|
21097
21198
|
receipt(uuid3) {
|
|
21098
21199
|
return `claude:${uuid3}`;
|
|
21099
21200
|
}
|
|
@@ -21119,7 +21220,9 @@ class ClaudeDriver {
|
|
|
21119
21220
|
};
|
|
21120
21221
|
turnProtocol = new ClaudeTurnProtocol;
|
|
21121
21222
|
eventNormalizer = new ClaudeEventNormalizer(this.turnProtocol);
|
|
21223
|
+
pendingInterrupt;
|
|
21122
21224
|
beginTurn() {
|
|
21225
|
+
this.pendingInterrupt = undefined;
|
|
21123
21226
|
const receipt = this.turnProtocol.beginTurn();
|
|
21124
21227
|
this.eventNormalizer.beginTurn();
|
|
21125
21228
|
return receipt;
|
|
@@ -21158,11 +21261,45 @@ class ClaudeDriver {
|
|
|
21158
21261
|
return { process: proc };
|
|
21159
21262
|
}
|
|
21160
21263
|
normalizeLine(line) {
|
|
21161
|
-
|
|
21264
|
+
const events = this.eventNormalizer.normalizeLine(line);
|
|
21265
|
+
this.flushPendingInterrupt();
|
|
21266
|
+
return events;
|
|
21162
21267
|
}
|
|
21163
21268
|
get currentSessionId() {
|
|
21164
21269
|
return this.eventNormalizer.currentSessionId;
|
|
21165
21270
|
}
|
|
21271
|
+
async interrupt(input, process3) {
|
|
21272
|
+
const stdin = process3.stdin;
|
|
21273
|
+
if (!this.turnProtocol.hasActiveTurn() || !stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false)
|
|
21274
|
+
return false;
|
|
21275
|
+
this.turnProtocol.noteInterruptRequested();
|
|
21276
|
+
if (!this.turnProtocol.acceptsTurnWork()) {
|
|
21277
|
+
this.pendingInterrupt ??= { input, process: process3 };
|
|
21278
|
+
return true;
|
|
21279
|
+
}
|
|
21280
|
+
this.writeInterrupt(input, process3);
|
|
21281
|
+
return true;
|
|
21282
|
+
}
|
|
21283
|
+
writeInterrupt(input, process3) {
|
|
21284
|
+
process3.stdin.write(JSON.stringify({
|
|
21285
|
+
type: "control_request",
|
|
21286
|
+
request_id: input.requestId ?? randomUUID5(),
|
|
21287
|
+
request: { subtype: "interrupt" }
|
|
21288
|
+
}) + `
|
|
21289
|
+
`);
|
|
21290
|
+
}
|
|
21291
|
+
flushPendingInterrupt() {
|
|
21292
|
+
const pending = this.pendingInterrupt;
|
|
21293
|
+
if (!pending || !this.turnProtocol.acceptsTurnWork())
|
|
21294
|
+
return;
|
|
21295
|
+
this.pendingInterrupt = undefined;
|
|
21296
|
+
const stdin = pending.process.stdin;
|
|
21297
|
+
if (!stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false)
|
|
21298
|
+
return;
|
|
21299
|
+
try {
|
|
21300
|
+
this.writeInterrupt(pending.input, pending.process);
|
|
21301
|
+
} catch {}
|
|
21302
|
+
}
|
|
21166
21303
|
encodeMessage(text2, sessionId, opts) {
|
|
21167
21304
|
const uuid3 = opts?.mode === "idle" ? this.turnProtocol.rootInputUuid() : this.turnProtocol.steeringInputUuid();
|
|
21168
21305
|
return JSON.stringify({
|
|
@@ -21294,6 +21431,35 @@ import { randomBytes } from "node:crypto";
|
|
|
21294
21431
|
var codexQuotaSourceEpoch = randomBytes(16).toString("base64url");
|
|
21295
21432
|
var codexQuotaSourceGeneration = 0;
|
|
21296
21433
|
var codexAccountFingerprint = null;
|
|
21434
|
+
var CODEX_ERROR_INFO_CODES = new Set([
|
|
21435
|
+
"contextWindowExceeded",
|
|
21436
|
+
"sessionBudgetExceeded",
|
|
21437
|
+
"usageLimitExceeded",
|
|
21438
|
+
"serverOverloaded",
|
|
21439
|
+
"cyberPolicy",
|
|
21440
|
+
"misalignmentPolicyViolation",
|
|
21441
|
+
"internalServerError",
|
|
21442
|
+
"unauthorized",
|
|
21443
|
+
"badRequest",
|
|
21444
|
+
"threadRollbackFailed",
|
|
21445
|
+
"sandboxError",
|
|
21446
|
+
"other",
|
|
21447
|
+
"httpConnectionFailed",
|
|
21448
|
+
"responseStreamConnectionFailed",
|
|
21449
|
+
"responseStreamDisconnected",
|
|
21450
|
+
"responseTooManyFailedAttempts",
|
|
21451
|
+
"activeTurnNotSteerable"
|
|
21452
|
+
]);
|
|
21453
|
+
function snakeCase(value) {
|
|
21454
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
21455
|
+
}
|
|
21456
|
+
function codexErrorInfoCode(value, fallback) {
|
|
21457
|
+
const label = typeof value === "string" ? value : value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value)[0] : undefined;
|
|
21458
|
+
return label && CODEX_ERROR_INFO_CODES.has(label) ? `codex.${snakeCase(label)}` : fallback;
|
|
21459
|
+
}
|
|
21460
|
+
function codexRpcErrorCode(value) {
|
|
21461
|
+
return typeof value === "number" && Number.isSafeInteger(value) ? `codex.rpc.${value}` : "codex.rpc_error";
|
|
21462
|
+
}
|
|
21297
21463
|
function rotateCodexQuotaSource() {
|
|
21298
21464
|
codexQuotaSourceEpoch = randomBytes(16).toString("base64url");
|
|
21299
21465
|
codexQuotaSourceGeneration += 1;
|
|
@@ -21451,7 +21617,11 @@ class CodexEventNormalizer {
|
|
|
21451
21617
|
return this.replaceQuotaSnapshots(msg.result ?? {});
|
|
21452
21618
|
}
|
|
21453
21619
|
if (msg?.error && msg.id !== undefined) {
|
|
21454
|
-
return [{
|
|
21620
|
+
return [{
|
|
21621
|
+
kind: "error",
|
|
21622
|
+
code: codexRpcErrorCode(msg.error?.code),
|
|
21623
|
+
message: msg.error?.message ?? "Codex RPC error"
|
|
21624
|
+
}];
|
|
21455
21625
|
}
|
|
21456
21626
|
if (msg?.result?.thread?.id) {
|
|
21457
21627
|
return this.adoptAndInit(msg.result.thread.id);
|
|
@@ -21520,20 +21690,26 @@ class CodexEventNormalizer {
|
|
|
21520
21690
|
return [];
|
|
21521
21691
|
this.releaseUsageForTurn(params.threadId, params.turn.id);
|
|
21522
21692
|
if (params.turn.status === "failed") {
|
|
21693
|
+
const error51 = params.turn.error;
|
|
21523
21694
|
return [
|
|
21524
|
-
{
|
|
21695
|
+
{
|
|
21696
|
+
kind: "error",
|
|
21697
|
+
code: codexErrorInfoCode(error51?.codexErrorInfo, "codex.turn_failed"),
|
|
21698
|
+
message: error51?.message ?? "Codex turn failed"
|
|
21699
|
+
},
|
|
21525
21700
|
{ kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }
|
|
21526
21701
|
];
|
|
21527
21702
|
}
|
|
21528
|
-
if (params.turn.status === "interrupted") {
|
|
21529
|
-
return [{ kind: "error", message: "Codex turn interrupted" }, { kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }];
|
|
21530
|
-
}
|
|
21531
21703
|
return [{ kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }];
|
|
21532
21704
|
case "error":
|
|
21533
21705
|
if (params?.willRetry === true) {
|
|
21534
21706
|
return [{ kind: "runtime_recovery", stage: "retrying", source: "codex_stream" }];
|
|
21535
21707
|
}
|
|
21536
|
-
return [{
|
|
21708
|
+
return [{
|
|
21709
|
+
kind: "error",
|
|
21710
|
+
code: codexErrorInfoCode(params?.error?.codexErrorInfo, "codex.error"),
|
|
21711
|
+
message: params?.error?.message ?? params?.message ?? "Codex error"
|
|
21712
|
+
}];
|
|
21537
21713
|
case "thread/tokenUsage/updated":
|
|
21538
21714
|
return [];
|
|
21539
21715
|
case "account/rateLimits/updated":
|
|
@@ -21630,42 +21806,46 @@ class CodexEventNormalizer {
|
|
|
21630
21806
|
}
|
|
21631
21807
|
handleItemStarted(params) {
|
|
21632
21808
|
const t = params?.item?.type ?? params?.type;
|
|
21809
|
+
const callId = this.itemCallId(params);
|
|
21810
|
+
const identity = callId ? { callId } : {};
|
|
21633
21811
|
switch (t) {
|
|
21634
21812
|
case "commandExecution":
|
|
21635
|
-
return [{ kind: "tool_call", name: "shell", input: params?.item }];
|
|
21813
|
+
return [{ kind: "tool_call", ...identity, name: "shell", input: params?.item }];
|
|
21636
21814
|
case "contextCompaction":
|
|
21637
21815
|
return [{ kind: "compaction_started" }];
|
|
21638
21816
|
case "enteredReviewMode":
|
|
21639
21817
|
return [{ kind: "review_started" }];
|
|
21640
21818
|
case "fileChange":
|
|
21641
|
-
return [{ kind: "tool_call", name: "file_change", input: normalizeFileChangeInput(params?.item) }];
|
|
21819
|
+
return [{ kind: "tool_call", ...identity, name: "file_change", input: normalizeFileChangeInput(params?.item) }];
|
|
21642
21820
|
case "mcpToolCall":
|
|
21643
|
-
return [{ kind: "tool_call", name: `mcp_${params?.item?.name ?? "tool"}`, input: params?.item }];
|
|
21821
|
+
return [{ kind: "tool_call", ...identity, name: `mcp_${params?.item?.tool ?? params?.item?.name ?? "tool"}`, input: params?.item }];
|
|
21644
21822
|
case "webSearch":
|
|
21645
|
-
return [{ kind: "tool_call", name: "web_search", input: params?.item }];
|
|
21823
|
+
return [{ kind: "tool_call", ...identity, name: "web_search", input: params?.item }];
|
|
21646
21824
|
case "collabAgentToolCall":
|
|
21647
|
-
return [{ kind: "tool_call", name: "collab_tool_call", input: params?.item }];
|
|
21825
|
+
return [{ kind: "tool_call", ...identity, name: "collab_tool_call", input: params?.item }];
|
|
21648
21826
|
default:
|
|
21649
21827
|
return [];
|
|
21650
21828
|
}
|
|
21651
21829
|
}
|
|
21652
21830
|
handleItemCompleted(params) {
|
|
21653
21831
|
const t = params?.item?.type ?? params?.type;
|
|
21832
|
+
const callId = this.itemCallId(params);
|
|
21833
|
+
const identity = callId ? { callId } : {};
|
|
21654
21834
|
switch (t) {
|
|
21655
21835
|
case "commandExecution":
|
|
21656
|
-
return [{ kind: "tool_output", name: "shell" }];
|
|
21836
|
+
return [{ kind: "tool_output", ...identity, name: "shell" }];
|
|
21657
21837
|
case "contextCompaction":
|
|
21658
21838
|
return [{ kind: "compaction_finished" }];
|
|
21659
21839
|
case "exitedReviewMode":
|
|
21660
21840
|
return [{ kind: "review_finished" }];
|
|
21661
21841
|
case "fileChange":
|
|
21662
|
-
return [{ kind: "tool_output", name: "file_change" }];
|
|
21842
|
+
return [{ kind: "tool_output", ...identity, name: "file_change" }];
|
|
21663
21843
|
case "mcpToolCall":
|
|
21664
|
-
return [{ kind: "tool_output", name: `mcp_${params?.item?.name ?? "tool"}` }];
|
|
21844
|
+
return [{ kind: "tool_output", ...identity, name: `mcp_${params?.item?.tool ?? params?.item?.name ?? "tool"}` }];
|
|
21665
21845
|
case "webSearch":
|
|
21666
|
-
return [{ kind: "tool_output", name: "web_search" }];
|
|
21846
|
+
return [{ kind: "tool_output", ...identity, name: "web_search" }];
|
|
21667
21847
|
case "collabAgentToolCall":
|
|
21668
|
-
return [{ kind: "tool_output", name: "collab_tool_call" }];
|
|
21848
|
+
return [{ kind: "tool_output", ...identity, name: "collab_tool_call" }];
|
|
21669
21849
|
case "agentMessage":
|
|
21670
21850
|
return [{ kind: "assistant_message_completed", text: params?.item?.text ?? "" }];
|
|
21671
21851
|
case "reasoning":
|
|
@@ -21674,6 +21854,10 @@ class CodexEventNormalizer {
|
|
|
21674
21854
|
return [];
|
|
21675
21855
|
}
|
|
21676
21856
|
}
|
|
21857
|
+
itemCallId(params) {
|
|
21858
|
+
const value = params?.item?.id ?? params?.itemId;
|
|
21859
|
+
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
21860
|
+
}
|
|
21677
21861
|
}
|
|
21678
21862
|
|
|
21679
21863
|
// agent-driver/dist/adapters/codex/home.js
|
|
@@ -22144,6 +22328,16 @@ class CodexDriver {
|
|
|
22144
22328
|
get currentSessionId() {
|
|
22145
22329
|
return this.eventNormalizer.currentSessionId;
|
|
22146
22330
|
}
|
|
22331
|
+
async interrupt(_input, process3) {
|
|
22332
|
+
const threadId = this.eventNormalizer.currentSessionId;
|
|
22333
|
+
const turnId = this.eventNormalizer.currentTurnId;
|
|
22334
|
+
const stdin = process3.stdin;
|
|
22335
|
+
if (!threadId || !turnId || !stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false)
|
|
22336
|
+
return false;
|
|
22337
|
+
stdin.write(jsonRpcRequest("turn/interrupt", { threadId, turnId }, this.nextRequestId()) + `
|
|
22338
|
+
`);
|
|
22339
|
+
return true;
|
|
22340
|
+
}
|
|
22147
22341
|
buildTurnStart(threadId, text2) {
|
|
22148
22342
|
return jsonRpcRequest("turn/start", { threadId, input: [{ type: "text", text: text2 }] }, this.nextRequestId());
|
|
22149
22343
|
}
|
|
@@ -22643,7 +22837,7 @@ class CursorAcpLane {
|
|
|
22643
22837
|
return;
|
|
22644
22838
|
const result = record3(value);
|
|
22645
22839
|
if (!result || typeof result.stopReason !== "string" || !PROMPT_STOP_REASONS.has(result.stopReason)) {
|
|
22646
|
-
this.failPrompt(prompt, new Error("Cursor ACP prompt response did not contain a supported stopReason"));
|
|
22840
|
+
this.failPrompt(prompt, new Error("Cursor ACP prompt response did not contain a supported stopReason"), "cursor.invalid_stop_reason");
|
|
22647
22841
|
return;
|
|
22648
22842
|
}
|
|
22649
22843
|
const terminalOwner = this.terminalOwner ?? prompt.receipt;
|
|
@@ -22656,7 +22850,7 @@ class CursorAcpLane {
|
|
|
22656
22850
|
turnOwner: terminalOwner
|
|
22657
22851
|
});
|
|
22658
22852
|
}
|
|
22659
|
-
failPrompt(prompt, error51) {
|
|
22853
|
+
failPrompt(prompt, error51, code = "cursor.prompt_failed") {
|
|
22660
22854
|
if (this.currentPromptRequestId !== prompt.requestId)
|
|
22661
22855
|
return;
|
|
22662
22856
|
const terminalOwner = this.terminalOwner ?? prompt.receipt;
|
|
@@ -22665,6 +22859,7 @@ class CursorAcpLane {
|
|
|
22665
22859
|
this.openToolCalls.clear();
|
|
22666
22860
|
this.events.emit("runtime_event", {
|
|
22667
22861
|
kind: "error",
|
|
22862
|
+
code,
|
|
22668
22863
|
message: error51 instanceof Error ? error51.message : String(error51)
|
|
22669
22864
|
});
|
|
22670
22865
|
this.events.emit("runtime_event", {
|
|
@@ -22818,9 +23013,10 @@ class CursorAcpLane {
|
|
|
22818
23013
|
this.pending.delete(id);
|
|
22819
23014
|
if (message2.error !== undefined) {
|
|
22820
23015
|
const payload = record3(message2.error);
|
|
22821
|
-
|
|
23016
|
+
const rpcCode = typeof payload?.code === "number" && Number.isSafeInteger(payload.code) ? payload.code : undefined;
|
|
23017
|
+
this.failPrompt(pending.prompt, new CursorAcpRpcError(pending.method, rpcCode, rpcErrorMessage(message2.error)), rpcCode === undefined ? "cursor.rpc_error" : `cursor.rpc.${rpcCode}`);
|
|
22822
23018
|
} else if (!("result" in message2)) {
|
|
22823
|
-
this.failPrompt(pending.prompt, new Error("Cursor ACP response omitted result"));
|
|
23019
|
+
this.failPrompt(pending.prompt, new Error("Cursor ACP response omitted result"), "cursor.invalid_response");
|
|
22824
23020
|
} else {
|
|
22825
23021
|
this.completePrompt(pending.prompt, message2.result);
|
|
22826
23022
|
}
|
|
@@ -23105,7 +23301,11 @@ function parseModelRef(model) {
|
|
|
23105
23301
|
function messageFromError(value) {
|
|
23106
23302
|
const payload = record4(value);
|
|
23107
23303
|
const message2 = typeof payload?.message === "string" && payload.message.trim() ? payload.message : undefined;
|
|
23108
|
-
return message2
|
|
23304
|
+
return message2 ?? "OpenCode reported an inconsistent turn outcome";
|
|
23305
|
+
}
|
|
23306
|
+
function codeFromError(value) {
|
|
23307
|
+
const payload = record4(value);
|
|
23308
|
+
return payload?.type === "unknown" ? "opencode.unknown" : "opencode.step_failed";
|
|
23109
23309
|
}
|
|
23110
23310
|
|
|
23111
23311
|
class OpenCodeServiceLane {
|
|
@@ -23773,7 +23973,10 @@ class OpenCodeServiceLane {
|
|
|
23773
23973
|
root.outcomes.push({
|
|
23774
23974
|
seq,
|
|
23775
23975
|
ok: successful,
|
|
23776
|
-
...!successful ? {
|
|
23976
|
+
...!successful ? {
|
|
23977
|
+
code: "opencode.unsupported_finish",
|
|
23978
|
+
message: "OpenCode reported an unsupported final step outcome"
|
|
23979
|
+
} : {}
|
|
23777
23980
|
});
|
|
23778
23981
|
}
|
|
23779
23982
|
const tokens = record4(data.tokens);
|
|
@@ -23802,7 +24005,12 @@ class OpenCodeServiceLane {
|
|
|
23802
24005
|
break;
|
|
23803
24006
|
}
|
|
23804
24007
|
case "session.next.step.failed":
|
|
23805
|
-
root.outcomes.push({
|
|
24008
|
+
root.outcomes.push({
|
|
24009
|
+
seq,
|
|
24010
|
+
ok: false,
|
|
24011
|
+
code: codeFromError(data.error),
|
|
24012
|
+
message: messageFromError(data.error)
|
|
24013
|
+
});
|
|
23806
24014
|
break;
|
|
23807
24015
|
default:
|
|
23808
24016
|
break;
|
|
@@ -23982,11 +24190,11 @@ class OpenCodeServiceLane {
|
|
|
23982
24190
|
return;
|
|
23983
24191
|
const outcome = root.outcomes.filter((item) => item.seq > maxAdmission).sort((left, right) => left.seq - right.seq).at(-1);
|
|
23984
24192
|
if (!root.interrupted && !outcome) {
|
|
23985
|
-
this.settleRoot(root, false, "OpenCode drain settled without a durable turn outcome");
|
|
24193
|
+
this.settleRoot(root, false, "OpenCode drain settled without a durable turn outcome", "opencode.missing_outcome");
|
|
23986
24194
|
return;
|
|
23987
24195
|
}
|
|
23988
24196
|
if (outcome && !outcome.ok) {
|
|
23989
|
-
this.settleRoot(root, false, outcome.message ?? "OpenCode turn failed");
|
|
24197
|
+
this.settleRoot(root, false, outcome.message ?? "OpenCode turn failed", outcome.code ?? "opencode.turn_failed");
|
|
23990
24198
|
return;
|
|
23991
24199
|
}
|
|
23992
24200
|
this.settleRoot(root, true);
|
|
@@ -24012,7 +24220,7 @@ class OpenCodeServiceLane {
|
|
|
24012
24220
|
barrierStillCurrent(root, identity, generation) {
|
|
24013
24221
|
return this.activeRoot === root && root.generation === generation && root.pendingAdmissions === 0 && !root.interruptPending && this.isIdentity(identity) && this.identityMatches();
|
|
24014
24222
|
}
|
|
24015
|
-
settleRoot(root, success2, message2) {
|
|
24223
|
+
settleRoot(root, success2, message2, code = "opencode.turn_failed") {
|
|
24016
24224
|
if (this.activeRoot !== root)
|
|
24017
24225
|
return;
|
|
24018
24226
|
this.activeRoot = null;
|
|
@@ -24020,6 +24228,7 @@ class OpenCodeServiceLane {
|
|
|
24020
24228
|
if (!success2) {
|
|
24021
24229
|
this.events.emit("runtime_event", {
|
|
24022
24230
|
kind: "error",
|
|
24231
|
+
code,
|
|
24023
24232
|
message: message2 ?? "OpenCode turn failed"
|
|
24024
24233
|
});
|
|
24025
24234
|
}
|
|
@@ -24535,7 +24744,11 @@ function mapPiSdkEvent(event, sessionId, state) {
|
|
|
24535
24744
|
return [{ kind: "assistant_message_completed", text: d.content ?? "" }];
|
|
24536
24745
|
}
|
|
24537
24746
|
case "error":
|
|
24538
|
-
return [{
|
|
24747
|
+
return [{
|
|
24748
|
+
kind: "error",
|
|
24749
|
+
code: "pi.message_error",
|
|
24750
|
+
message: d.error?.errorMessage ?? "Pi error"
|
|
24751
|
+
}];
|
|
24539
24752
|
default:
|
|
24540
24753
|
return [];
|
|
24541
24754
|
}
|
|
@@ -25123,7 +25336,9 @@ class LogicalAgentSession {
|
|
|
25123
25336
|
interruptedTurnId;
|
|
25124
25337
|
processTurnEnded = false;
|
|
25125
25338
|
stopRequestId;
|
|
25126
|
-
|
|
25339
|
+
anonymousOutstandingToolUses = 0;
|
|
25340
|
+
outstandingToolCallIds = new Set;
|
|
25341
|
+
toolLifecycleMismatchCount = 0;
|
|
25127
25342
|
compacting = false;
|
|
25128
25343
|
reviewing = false;
|
|
25129
25344
|
steeringDeliveries = new Set;
|
|
@@ -25313,6 +25528,9 @@ class LogicalAgentSession {
|
|
|
25313
25528
|
queueDwellCount: this.metricValue(this.queueDwellCount),
|
|
25314
25529
|
queueDwellTotalMs: this.metricValue(this.queueDwellTotalMs),
|
|
25315
25530
|
sseReconnectCount: this.metricValue(this.sseReconnectCount),
|
|
25531
|
+
outstandingToolUses: this.outstandingToolUseCount(),
|
|
25532
|
+
anonymousOutstandingToolUses: this.metricValue(this.anonymousOutstandingToolUses),
|
|
25533
|
+
toolLifecycleMismatchCount: this.metricValue(this.toolLifecycleMismatchCount),
|
|
25316
25534
|
resumeOutcome: this.resumeOutcome,
|
|
25317
25535
|
terminalOwnerKind: this.adapter.execution.terminalOwnership
|
|
25318
25536
|
}
|
|
@@ -25632,15 +25850,36 @@ class LogicalAgentSession {
|
|
|
25632
25850
|
}
|
|
25633
25851
|
return;
|
|
25634
25852
|
case "tool_call":
|
|
25635
|
-
|
|
25636
|
-
|
|
25637
|
-
|
|
25853
|
+
if (!turnId) {
|
|
25854
|
+
this.toolLifecycleMismatchCount += 1;
|
|
25855
|
+
return;
|
|
25856
|
+
}
|
|
25857
|
+
if (!this.startToolUse(event.callId))
|
|
25858
|
+
return;
|
|
25859
|
+
const startedCallId = this.toolCallId(event.callId);
|
|
25860
|
+
this.emit({
|
|
25861
|
+
type: "tool_started",
|
|
25862
|
+
turnId,
|
|
25863
|
+
...startedCallId ? { callId: startedCallId } : {},
|
|
25864
|
+
name: event.name,
|
|
25865
|
+
input: jsonValue(event.input)
|
|
25866
|
+
});
|
|
25638
25867
|
return;
|
|
25639
25868
|
case "tool_output":
|
|
25640
|
-
|
|
25641
|
-
|
|
25642
|
-
|
|
25643
|
-
|
|
25869
|
+
if (!turnId) {
|
|
25870
|
+
this.toolLifecycleMismatchCount += 1;
|
|
25871
|
+
return;
|
|
25872
|
+
}
|
|
25873
|
+
if (!this.finishToolUse(event.callId))
|
|
25874
|
+
return;
|
|
25875
|
+
const finishedCallId = this.toolCallId(event.callId);
|
|
25876
|
+
this.emit({
|
|
25877
|
+
type: "tool_finished",
|
|
25878
|
+
turnId,
|
|
25879
|
+
...finishedCallId ? { callId: finishedCallId } : {},
|
|
25880
|
+
name: event.name
|
|
25881
|
+
});
|
|
25882
|
+
if (this.outstandingToolUseCount() === 0 && !this.toolBoundaryFlushDisabled)
|
|
25644
25883
|
this.flushSafeBoundaryQueue();
|
|
25645
25884
|
return;
|
|
25646
25885
|
case "compaction_started":
|
|
@@ -25696,7 +25935,7 @@ class LogicalAgentSession {
|
|
|
25696
25935
|
}
|
|
25697
25936
|
case "error":
|
|
25698
25937
|
this.toolBoundaryFlushDisabled = true;
|
|
25699
|
-
this.turnError = driverError("process", "runtime_error", event.message, true);
|
|
25938
|
+
this.turnError = driverError("process", stableErrorCode(event.code, "runtime_error"), event.message, true);
|
|
25700
25939
|
this.emit({
|
|
25701
25940
|
type: "diagnostic",
|
|
25702
25941
|
turnId,
|
|
@@ -25783,7 +26022,7 @@ class LogicalAgentSession {
|
|
|
25783
26022
|
this.activeTurn = undefined;
|
|
25784
26023
|
this.turnError = undefined;
|
|
25785
26024
|
this.interruptedTurnId = undefined;
|
|
25786
|
-
this.
|
|
26025
|
+
this.clearOutstandingToolUses();
|
|
25787
26026
|
this.compacting = false;
|
|
25788
26027
|
this.reviewing = false;
|
|
25789
26028
|
this.toolBoundaryFlushDisabled = false;
|
|
@@ -25807,7 +26046,7 @@ class LogicalAgentSession {
|
|
|
25807
26046
|
return this.safeBoundaryFlush;
|
|
25808
26047
|
}
|
|
25809
26048
|
canFlushSafeBoundaryQueue() {
|
|
25810
|
-
return this.state === "working" && this.behavior.midTurnDelivery === "safe_boundary_queue" && this.
|
|
26049
|
+
return this.state === "working" && this.behavior.midTurnDelivery === "safe_boundary_queue" && this.outstandingToolUseCount() === 0 && !this.compacting && !this.reviewing && this.activeTurn !== undefined && this.lane !== null && this.queued.length > 0;
|
|
25811
26050
|
}
|
|
25812
26051
|
async drainSafeBoundaryQueue() {
|
|
25813
26052
|
while (this.canFlushSafeBoundaryQueue()) {
|
|
@@ -25988,7 +26227,7 @@ class LogicalAgentSession {
|
|
|
25988
26227
|
return "compacting";
|
|
25989
26228
|
if (this.reviewing)
|
|
25990
26229
|
return "reviewing";
|
|
25991
|
-
if (this.
|
|
26230
|
+
if (this.outstandingToolUseCount() > 0)
|
|
25992
26231
|
return "tool_wait";
|
|
25993
26232
|
if (this.activeTurn)
|
|
25994
26233
|
return "working";
|
|
@@ -25998,6 +26237,46 @@ class LogicalAgentSession {
|
|
|
25998
26237
|
const now = this.host.now();
|
|
25999
26238
|
return Number.isFinite(now) && now >= 0 ? now : 0;
|
|
26000
26239
|
}
|
|
26240
|
+
outstandingToolUseCount() {
|
|
26241
|
+
return this.anonymousOutstandingToolUses + this.outstandingToolCallIds.size;
|
|
26242
|
+
}
|
|
26243
|
+
startToolUse(rawCallId) {
|
|
26244
|
+
const callId = this.toolCallId(rawCallId);
|
|
26245
|
+
if (!callId) {
|
|
26246
|
+
this.anonymousOutstandingToolUses += 1;
|
|
26247
|
+
return true;
|
|
26248
|
+
}
|
|
26249
|
+
if (this.outstandingToolCallIds.has(callId)) {
|
|
26250
|
+
this.toolLifecycleMismatchCount += 1;
|
|
26251
|
+
return false;
|
|
26252
|
+
}
|
|
26253
|
+
this.outstandingToolCallIds.add(callId);
|
|
26254
|
+
return true;
|
|
26255
|
+
}
|
|
26256
|
+
finishToolUse(rawCallId) {
|
|
26257
|
+
const callId = this.toolCallId(rawCallId);
|
|
26258
|
+
if (!callId) {
|
|
26259
|
+
if (this.anonymousOutstandingToolUses === 0) {
|
|
26260
|
+
this.toolLifecycleMismatchCount += 1;
|
|
26261
|
+
return false;
|
|
26262
|
+
}
|
|
26263
|
+
this.anonymousOutstandingToolUses -= 1;
|
|
26264
|
+
return true;
|
|
26265
|
+
}
|
|
26266
|
+
if (!this.outstandingToolCallIds.delete(callId)) {
|
|
26267
|
+
this.toolLifecycleMismatchCount += 1;
|
|
26268
|
+
return false;
|
|
26269
|
+
}
|
|
26270
|
+
return true;
|
|
26271
|
+
}
|
|
26272
|
+
clearOutstandingToolUses() {
|
|
26273
|
+
this.anonymousOutstandingToolUses = 0;
|
|
26274
|
+
this.outstandingToolCallIds.clear();
|
|
26275
|
+
}
|
|
26276
|
+
toolCallId(rawCallId) {
|
|
26277
|
+
const callId = rawCallId?.trim();
|
|
26278
|
+
return callId && callId.length <= 1024 ? callId : undefined;
|
|
26279
|
+
}
|
|
26001
26280
|
metricValue(value) {
|
|
26002
26281
|
return Number.isFinite(value) && value >= 0 ? value : 0;
|
|
26003
26282
|
}
|
|
@@ -27636,10 +27915,11 @@ var DEFAULT_CAPABILITY_RESOLVER = (method, pathname) => {
|
|
|
27636
27915
|
const isMessagesDoor = /\/channels\/[^/]+\/messages(\/|$|\?)/.test(pathname);
|
|
27637
27916
|
if (isMessagesDoor)
|
|
27638
27917
|
return method === "GET" ? "read" : "send";
|
|
27918
|
+
if (/\/messages\/[^/]+\/properties(\/|$|\?)/.test(pathname)) {
|
|
27919
|
+
return method === "GET" ? "read" : "send";
|
|
27920
|
+
}
|
|
27639
27921
|
if (/\/messages\/[^/]+\/reactions\//.test(pathname))
|
|
27640
27922
|
return "send";
|
|
27641
|
-
if ((method === "PUT" || method === "DELETE") && /\/messages\/[^/]+\/marks(\/|$|\?)/.test(pathname))
|
|
27642
|
-
return "send";
|
|
27643
27923
|
if (method === "GET" && /\/users\/me\/marks(\/|$|\?)/.test(pathname))
|
|
27644
27924
|
return "read";
|
|
27645
27925
|
if (method === "GET" && /\/messages\/[^/]+(\?|$)/.test(pathname))
|
|
@@ -27680,6 +27960,12 @@ function isCanonicalChannelScope(channel2) {
|
|
|
27680
27960
|
return false;
|
|
27681
27961
|
}
|
|
27682
27962
|
}
|
|
27963
|
+
function propertyAuditMetadata(method, pathname, requestUrl) {
|
|
27964
|
+
if (method !== "PUT" && method !== "DELETE" || !/^\/api\/community\/messages\/[^/]+\/properties$/.test(pathname))
|
|
27965
|
+
return;
|
|
27966
|
+
const type = new URL2(requestUrl, "http://placeholder").searchParams.get("type");
|
|
27967
|
+
return type === "emoji" || type === "tag" || type === "mark" ? { propertyType: type } : undefined;
|
|
27968
|
+
}
|
|
27683
27969
|
function parseLocalMessageReminderBody(body, agentId) {
|
|
27684
27970
|
let value;
|
|
27685
27971
|
try {
|
|
@@ -27818,7 +28104,12 @@ async function startCredentialProxy(broker, options = {}) {
|
|
|
27818
28104
|
}
|
|
27819
28105
|
if (onProxyRequest) {
|
|
27820
28106
|
try {
|
|
27821
|
-
|
|
28107
|
+
const method = req.method ?? "GET";
|
|
28108
|
+
const metadata = propertyAuditMetadata(method, pathname, req.url ?? pathname);
|
|
28109
|
+
if (metadata)
|
|
28110
|
+
onProxyRequest(reg.agentId, method, pathname, metadata);
|
|
28111
|
+
else
|
|
28112
|
+
onProxyRequest(reg.agentId, method, pathname);
|
|
27822
28113
|
} catch {}
|
|
27823
28114
|
}
|
|
27824
28115
|
const outHeaders = { ...req.headers };
|
|
@@ -28101,6 +28392,7 @@ function reduceManager(state, event) {
|
|
|
28101
28392
|
if ((lease.state === "active" || lease.state === "suspect_active") && lease.outstandingToolUses !== undefined) {
|
|
28102
28393
|
const unblockedLease = { ...lease };
|
|
28103
28394
|
delete unblockedLease.outstandingToolUses;
|
|
28395
|
+
delete unblockedLease.outstandingToolCallIds;
|
|
28104
28396
|
a.execution.lease = unblockedLease;
|
|
28105
28397
|
}
|
|
28106
28398
|
});
|
|
@@ -28361,26 +28653,40 @@ function onTurnToolLifecycle(state, event, lifecycle) {
|
|
|
28361
28653
|
const matchesTerminal = lifecycle === "started" && current.state === "none" && current.lastTerminal !== null && sameIdentity(current.lastTerminal.identity, identity);
|
|
28362
28654
|
if (!matchesActive && !matchesTerminal)
|
|
28363
28655
|
return { state, effects: [] };
|
|
28364
|
-
if (lifecycle === "finished" && matchesActive && (current.outstandingToolUses ?? 0) === 0) {
|
|
28365
|
-
return { state, effects: [] };
|
|
28366
|
-
}
|
|
28367
28656
|
return mutate(state, event.agentId, (agent2) => {
|
|
28368
28657
|
if (!matchesSession(agent2, event.sessionInstanceId))
|
|
28369
28658
|
return;
|
|
28370
28659
|
const lease = agent2.execution.lease;
|
|
28660
|
+
const callId = normalizedToolCallId(event.callId);
|
|
28371
28661
|
if ((lease.state === "active" || lease.state === "suspect_active") && sameIdentity(lease.identity, identity)) {
|
|
28372
|
-
const
|
|
28662
|
+
const identified = new Set(lease.outstandingToolCallIds ?? []);
|
|
28663
|
+
const currentCount = lease.outstandingToolUses ?? 0;
|
|
28664
|
+
const anonymousCount = Math.max(0, currentCount - identified.size);
|
|
28665
|
+
if (lifecycle === "started") {
|
|
28666
|
+
if (callId && identified.has(callId))
|
|
28667
|
+
return;
|
|
28668
|
+
if (callId)
|
|
28669
|
+
identified.add(callId);
|
|
28670
|
+
} else if (callId) {
|
|
28671
|
+
if (!identified.delete(callId))
|
|
28672
|
+
return;
|
|
28673
|
+
} else if (anonymousCount === 0) {
|
|
28674
|
+
return;
|
|
28675
|
+
}
|
|
28676
|
+
const outstandingToolUses = currentCount + (lifecycle === "started" ? 1 : -1);
|
|
28373
28677
|
if (outstandingToolUses > 0) {
|
|
28374
28678
|
agent2.execution.lease = {
|
|
28375
28679
|
...lease,
|
|
28376
28680
|
lastWorkAt: event.nowMs,
|
|
28377
28681
|
nativeDeadlineAt: event.nowMs + agent2.turnSilence.normalBudgetMs,
|
|
28378
28682
|
recoveryExtensionsUsed: 0,
|
|
28379
|
-
outstandingToolUses
|
|
28683
|
+
outstandingToolUses,
|
|
28684
|
+
...identified.size > 0 ? { outstandingToolCallIds: [...identified] } : {}
|
|
28380
28685
|
};
|
|
28381
28686
|
} else {
|
|
28382
28687
|
const unblockedLease = { ...lease };
|
|
28383
28688
|
delete unblockedLease.outstandingToolUses;
|
|
28689
|
+
delete unblockedLease.outstandingToolCallIds;
|
|
28384
28690
|
agent2.execution.lease = {
|
|
28385
28691
|
...unblockedLease,
|
|
28386
28692
|
lastWorkAt: event.nowMs,
|
|
@@ -28399,6 +28705,7 @@ function onTurnToolLifecycle(state, event, lifecycle) {
|
|
|
28399
28705
|
nativeDeadlineAt: event.nowMs + agent2.turnSilence.normalBudgetMs,
|
|
28400
28706
|
recoveryExtensionsUsed: 0,
|
|
28401
28707
|
outstandingToolUses: 1,
|
|
28708
|
+
...callId ? { outstandingToolCallIds: [callId] } : {},
|
|
28402
28709
|
reason: "work_after_terminal"
|
|
28403
28710
|
};
|
|
28404
28711
|
}
|
|
@@ -28562,6 +28869,10 @@ function identityOf(event) {
|
|
|
28562
28869
|
function sameIdentity(left, right) {
|
|
28563
28870
|
return left.sessionInstanceId === right.sessionInstanceId && left.turnId === right.turnId;
|
|
28564
28871
|
}
|
|
28872
|
+
function normalizedToolCallId(rawCallId) {
|
|
28873
|
+
const callId = rawCallId?.trim();
|
|
28874
|
+
return callId && callId.length <= 1024 ? callId : undefined;
|
|
28875
|
+
}
|
|
28565
28876
|
function leaseIsWorking(lease) {
|
|
28566
28877
|
return lease.state === "active" || lease.state === "suspect_active";
|
|
28567
28878
|
}
|
|
@@ -28783,13 +29094,13 @@ function cliCommandsSection() {
|
|
|
28783
29094
|
"",
|
|
28784
29095
|
"### Messaging",
|
|
28785
29096
|
"",
|
|
28786
|
-
`1. \`${CLI} inbox pull\` — fetch unread messages
|
|
29097
|
+
`1. \`${CLI} inbox pull\` — fetch unread messages and advance their read waterlines.`,
|
|
28787
29098
|
`2. \`${CLI} message send --target <ref> --remind-after <0|Nm|Nh> --stdin\` — send to a ` + `channel, DM, or thread. ` + `The body is required through \`--stdin\` and limited to 1 KiB of UTF-8. ` + `Attach uploaded files with \`--attachment <id>\` (repeatable, order matters). ` + `\`--remind-after\` accepts \`0\`, or a whole-number duration from \`1m\` to \`24h\`.`,
|
|
28788
29099
|
`3. \`${CLI} message attachment upload --target <ref> --file <path>\` — upload a file; ` + `returns an id stable across pending→persisted.`,
|
|
28789
29100
|
`4. \`${CLI} message attachment download --id <id> [--out <path>]\` — download any ` + `attachment you can see (or your own pending uploads).`,
|
|
28790
|
-
`5. \`${CLI} message
|
|
28791
|
-
`6. \`${CLI} message
|
|
28792
|
-
`7. \`${CLI} message
|
|
29101
|
+
`5. \`${CLI} message property set --target <full-message-ref> --json <json>\` — add a supported property value to a message.`,
|
|
29102
|
+
`6. \`${CLI} message property list --target <full-message-ref>\` — list the message's current properties and supported capabilities.`,
|
|
29103
|
+
`7. \`${CLI} message property remove --target <full-message-ref> --json <json>\` — remove a supported property value from a message.`,
|
|
28793
29104
|
`8. \`${CLI} message mark list\` — list every currently visible marked message with its full content.`,
|
|
28794
29105
|
"",
|
|
28795
29106
|
"### Servers",
|
|
@@ -28797,12 +29108,14 @@ function cliCommandsSection() {
|
|
|
28797
29108
|
`1. \`${CLI} server list\` — list your servers.`,
|
|
28798
29109
|
`2. \`${CLI} server member --server <name#discriminator>\` — list a server's members.`,
|
|
28799
29110
|
`3. \`${CLI} server join --invite <link>\` — join via invite link or token.`,
|
|
29111
|
+
`4. \`${CLI} server leave --server <name#NNNN>\` — leave a server you belong to. A server owner cannot leave.`,
|
|
28800
29112
|
"",
|
|
28801
29113
|
"### Channels",
|
|
28802
29114
|
"",
|
|
28803
29115
|
`1. \`${CLI} channel list --server <name#discriminator>\` — list top-level channels, grouped by ` + `category; each is marked \`public\` or \`private\`.`,
|
|
28804
29116
|
`2. \`${CLI} channel history --channel <ref>\` — read a channel's or thread's past messages ` + `(the context you weren't awake for). Page with \`--before N\` / \`--after N\` (seq N as ` + "anchor), `--around N` to center on a message, `--limit N` for page size.",
|
|
28805
29117
|
`3. \`${CLI} channel member --channel <ref>\` — roster of a channel or thread. A private ` + `channel/forum returns its concrete member list; a public one returns a hint pointing at ` + `\`${CLI} server member\` (its audience is the whole server).`,
|
|
29118
|
+
`4. \`${CLI} channel leave --channel <ref>\` — leave a thread or private channel/forum. Public channels require leaving their server; DMs cannot be left.`,
|
|
28806
29119
|
"",
|
|
28807
29120
|
"### Friends",
|
|
28808
29121
|
"",
|
|
@@ -28855,6 +29168,15 @@ function messagingSection() {
|
|
|
28855
29168
|
"Reply where the message came from. Post results in the channel that owns the topic. " + "When uncertain, read history (below) or DM the relevant people.",
|
|
28856
29169
|
"Write every message body in the stdin/heredoc block; never place it directly on the command line.",
|
|
28857
29170
|
"",
|
|
29171
|
+
"### Message properties",
|
|
29172
|
+
"",
|
|
29173
|
+
`Message properties are capabilities determined by the target message's channel type. \`${CLI} ` + "message property list --target <full-message-ref>` returns its current values and supported `capabilities`.",
|
|
29174
|
+
"",
|
|
29175
|
+
`- \`emoji\` works on text-channel, DM, and thread messages. Set or remove your own reaction with ` + `\`{"type":"emoji","value":"\uD83D\uDC4D"}\`; \`list\` shows everyone who reacted. Add: ` + `\`${CLI} message property set --target <full-message-ref> --json '{"type":"emoji","value":"\uD83D\uDC4D"}'\`.`,
|
|
29176
|
+
`- \`tag\` works on forum opener messages. Set or remove named tags with ` + `\`{"type":"tag","value":["bug","ready"]}\`. A forum reply is a thread message, so it ` + `supports \`emoji\`, not \`tag\`. Add: \`${CLI} message property set --target ` + `<full-message-ref> --json '{"type":"tag","value":["bug"]}'\`.`,
|
|
29177
|
+
`- \`mark\` works on every message. Mark outstanding work with \`{"type":"mark","value":true}\`: ` + `\`${CLI} message property set --target <full-message-ref> --json ` + `'{"type":"mark","value":true}'\`. Clear it with the same JSON through ` + `\`message property remove\`. Use \`${CLI} message mark list\` for the one-shot global view ` + `of all currently visible marked messages.`,
|
|
29178
|
+
"- `archived` is a reserved tag meaning the forum post is complete. Setting it hides the " + "post from the normal forum feed; removing it reopens the post.",
|
|
29179
|
+
"",
|
|
28858
29180
|
"### Context refs",
|
|
28859
29181
|
"",
|
|
28860
29182
|
"Path-style refs:",
|
|
@@ -28967,6 +29289,7 @@ function criticalRulesSection() {
|
|
|
28967
29289
|
`- **\`${CLI}\` is the only way to communicate.** Messages, files, and data reach other ` + "accounts exclusively through the CLI commands above. Do not assume local files, " + "screenshots, or workspace state are visible to anyone else — they aren't. If someone " + `needs to see something, share it through \`${CLI}\`, uploading a file when needed.`,
|
|
28968
29290
|
"- **Never expose tokens, keys, or secrets.** Redact credential-like strings from tool output " + "before sharing.",
|
|
28969
29291
|
"- **Match the sender's language.** Reply in the language they wrote in.",
|
|
29292
|
+
`- **Leaving a scope is destructive.** Use \`${CLI} channel leave\` or \`${CLI} server leave\` only after your owner explicitly asks you to leave that exact scope.`,
|
|
28970
29293
|
"- **Channel alignment**: you can't send to a channel with unread messages. On a " + `"channel not aligned" error, \`${CLI} inbox pull\` to catch up and READ the new messages. ` + "Judge if your message is still needed or overlaps with what just landed. Adjust or skip; " + "don't mechanically resend."
|
|
28971
29294
|
].join(`
|
|
28972
29295
|
`);
|
|
@@ -28979,7 +29302,7 @@ function executionModelSection() {
|
|
|
28979
29302
|
"",
|
|
28980
29303
|
"On wake, restore durable context from `memory.md` and the context timeline, then pull your inbox. " + "Follow *Outstanding work marks* below before taking new work.",
|
|
28981
29304
|
"",
|
|
28982
|
-
"`inbox pull` advances your read waterline
|
|
29305
|
+
"`inbox pull` advances your read waterline — pulled messages won't come back in a " + "future pull. A task-bearing message stays durable through its server mark even after the " + "read waterline advances."
|
|
28983
29306
|
].join(`
|
|
28984
29307
|
`);
|
|
28985
29308
|
}
|
|
@@ -29051,9 +29374,9 @@ function workspaceMemorySection(config2) {
|
|
|
29051
29374
|
"",
|
|
29052
29375
|
"### Outstanding work marks",
|
|
29053
29376
|
"",
|
|
29054
|
-
"Marks are the durable work queue. If a message requires work beyond an immediate reply, " + `acknowledge it, then run \`${CLI} message
|
|
29377
|
+
"Marks are the durable work queue. If a message requires work beyond an immediate reply, " + `acknowledge it, then run \`${CLI} message property set --target <full-message-ref> ` + `--json '{"type":"mark","value":true}'\` before ` + "starting or queuing. Do not mark a message you answer immediately.",
|
|
29055
29378
|
"",
|
|
29056
|
-
"Keep it marked while the work is active, queued, or blocked; report blockers where the task " + `came from. Run \`${CLI} message
|
|
29379
|
+
"Keep it marked while the work is active, queued, or blocked; report blockers where the task " + `came from. Run \`${CLI} message property remove --target <full-message-ref> ` + `--json '{"type":"mark","value":true}'\` only after ` + "sending the result, or when the request is cancelled or superseded and nothing remains.",
|
|
29057
29380
|
"",
|
|
29058
29381
|
"If `inbox pull` returns a `markedReminder`, run " + `\`${CLI} message mark list\` before taking new work. Do not copy marked tasks into local files.`
|
|
29059
29382
|
].join(`
|
|
@@ -29106,7 +29429,7 @@ function toLocalISO(iso) {
|
|
|
29106
29429
|
}
|
|
29107
29430
|
|
|
29108
29431
|
// src/manager/managerRuntime.ts
|
|
29109
|
-
import { randomUUID as
|
|
29432
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
29110
29433
|
var SESSION_STOP_GRACE_MS2 = 2000;
|
|
29111
29434
|
function normalizeTerminationCause(value) {
|
|
29112
29435
|
return value === "runtime_error" || value === "killed_stalled" ? value : "other";
|
|
@@ -29343,7 +29666,7 @@ class AgentProcessManager {
|
|
|
29343
29666
|
liveBackendIds = new Map;
|
|
29344
29667
|
activeSpawnState = new Map;
|
|
29345
29668
|
publishedAgentActivity = new Map;
|
|
29346
|
-
traceProcessNonce =
|
|
29669
|
+
traceProcessNonce = randomUUID6();
|
|
29347
29670
|
nextSpawnOrdinal = 1;
|
|
29348
29671
|
nextDaemonTurnOrdinal = 1;
|
|
29349
29672
|
nextDeliveryOrdinal = 1;
|
|
@@ -29619,6 +29942,12 @@ class AgentProcessManager {
|
|
|
29619
29942
|
if (this.sessions.get(agentId) === session2)
|
|
29620
29943
|
this.sessions.delete(agentId);
|
|
29621
29944
|
}
|
|
29945
|
+
async interrupt(agentId) {
|
|
29946
|
+
const session2 = this.sessions.get(agentId);
|
|
29947
|
+
if (!session2)
|
|
29948
|
+
return;
|
|
29949
|
+
await session2.interrupt({ requestId: randomUUID6(), reason: "owner_request" });
|
|
29950
|
+
}
|
|
29622
29951
|
async stopAll() {
|
|
29623
29952
|
if (this.tickTimer) {
|
|
29624
29953
|
clearInterval(this.tickTimer);
|
|
@@ -30116,7 +30445,7 @@ ${this.opts.wakePromptFooter}` : text2;
|
|
|
30116
30445
|
case "reset_idle_session": {
|
|
30117
30446
|
const spawnState = this.activeSpawnState.get(effect.agentId);
|
|
30118
30447
|
const completion = {
|
|
30119
|
-
eventId: `bae_${
|
|
30448
|
+
eventId: `bae_${randomUUID6()}`,
|
|
30120
30449
|
occurredAt: new Date(this.now()).toISOString()
|
|
30121
30450
|
};
|
|
30122
30451
|
const persisted = this.forgetSession(effect.agentId, "reset_session", effect.sessionId, completion);
|
|
@@ -30511,11 +30840,12 @@ ${this.opts.wakePromptFooter}` : text2;
|
|
|
30511
30840
|
emitErrorAudit(agentId, scope, code, rawMessage) {
|
|
30512
30841
|
if (!this.opts.onBotAuditEvent)
|
|
30513
30842
|
return;
|
|
30843
|
+
const stableCode = /^[A-Za-z0-9_.-]{1,100}$/.test(code) ? code : "runtime_error";
|
|
30514
30844
|
const message2 = scrubRuntimeErrorDiagnosticText(rawMessage).slice(0, AUDIT_ERROR_MESSAGE_MAX_LEN);
|
|
30515
30845
|
try {
|
|
30516
30846
|
this.opts.onBotAuditEvent(agentId, {
|
|
30517
30847
|
kind: "error",
|
|
30518
|
-
payload: { scope, code, message: message2, model: this.currentModelFor(agentId) }
|
|
30848
|
+
payload: { scope, code: stableCode, message: message2, model: this.currentModelFor(agentId) }
|
|
30519
30849
|
}, {
|
|
30520
30850
|
sessionId: this.liveSessions.get(agentId) ?? null,
|
|
30521
30851
|
launchId: this.launchIds.get(agentId) ?? null
|
|
@@ -30540,18 +30870,18 @@ ${this.opts.wakePromptFooter}` : text2;
|
|
|
30540
30870
|
return;
|
|
30541
30871
|
}
|
|
30542
30872
|
const sessionSuperseded = owner.superseded;
|
|
30543
|
-
const
|
|
30544
|
-
if (
|
|
30545
|
-
this.emitErrorAudit(agentId, "runtime",
|
|
30873
|
+
const runtimeError = event.type === "session_failed" ? event.error : event.type === "turn_completed" && event.result.outcome === "failed" ? event.result.error : undefined;
|
|
30874
|
+
if (runtimeError !== undefined && !sessionSuperseded) {
|
|
30875
|
+
this.emitErrorAudit(agentId, "runtime", runtimeError.code, runtimeError.message);
|
|
30546
30876
|
if (this.nonCleanEndMarker.get(agentId)?.cause !== "killed_stalled") {
|
|
30547
|
-
this.nonCleanEndMarker.set(agentId, { cause: "runtime_error", detail:
|
|
30877
|
+
this.nonCleanEndMarker.set(agentId, { cause: "runtime_error", detail: runtimeError.message });
|
|
30548
30878
|
}
|
|
30549
30879
|
const agent2 = this.state.agents[agentId];
|
|
30550
30880
|
if (agent2?.resetting && agent2.resettingSince !== null && this.now() - agent2.resettingSince >= this.state.resetStuckThresholdMs) {
|
|
30551
30881
|
this.log.warn("runtime error during a stuck reset window", {
|
|
30552
30882
|
agentId,
|
|
30553
30883
|
resettingForMs: this.now() - agent2.resettingSince,
|
|
30554
|
-
message:
|
|
30884
|
+
message: runtimeError.message
|
|
30555
30885
|
});
|
|
30556
30886
|
}
|
|
30557
30887
|
}
|
|
@@ -30646,9 +30976,9 @@ ${this.opts.wakePromptFooter}` : text2;
|
|
|
30646
30976
|
case "assistant_message_completed":
|
|
30647
30977
|
return { type: "turn_work", turnId: event.turnId };
|
|
30648
30978
|
case "tool_started":
|
|
30649
|
-
return { type: "turn_tool_started", turnId: event.turnId };
|
|
30979
|
+
return { type: "turn_tool_started", turnId: event.turnId, callId: event.callId };
|
|
30650
30980
|
case "tool_finished":
|
|
30651
|
-
return { type: "turn_tool_finished", turnId: event.turnId };
|
|
30981
|
+
return { type: "turn_tool_finished", turnId: event.turnId, callId: event.callId };
|
|
30652
30982
|
case "compaction_started":
|
|
30653
30983
|
case "compaction_finished":
|
|
30654
30984
|
case "review_started":
|
|
@@ -31101,6 +31431,10 @@ class AgentRouter {
|
|
|
31101
31431
|
}
|
|
31102
31432
|
break;
|
|
31103
31433
|
}
|
|
31434
|
+
case "agent:interrupt": {
|
|
31435
|
+
await this.opts.manager.interrupt(cmd.agentId);
|
|
31436
|
+
break;
|
|
31437
|
+
}
|
|
31104
31438
|
case "agent:stop":
|
|
31105
31439
|
this.log.info("agent:stop received", { agentId: cmd.agentId });
|
|
31106
31440
|
try {
|
|
@@ -32543,7 +32877,7 @@ class MessageReminderScheduler {
|
|
|
32543
32877
|
}
|
|
32544
32878
|
|
|
32545
32879
|
// src/manager/agentDriverHost.ts
|
|
32546
|
-
import { randomUUID as
|
|
32880
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
32547
32881
|
import { homedir as homedir4 } from "node:os";
|
|
32548
32882
|
import { join as join13 } from "node:path";
|
|
32549
32883
|
|
|
@@ -32699,7 +33033,7 @@ function createDaemonAgentDriverHost(ctx, onRawLine) {
|
|
|
32699
33033
|
onRawLine?.(event.text);
|
|
32700
33034
|
},
|
|
32701
33035
|
now: () => Date.now(),
|
|
32702
|
-
createId: () =>
|
|
33036
|
+
createId: () => randomUUID7()
|
|
32703
33037
|
};
|
|
32704
33038
|
}
|
|
32705
33039
|
|
|
@@ -32778,7 +33112,7 @@ class DaemonSelfSleepScheduler {
|
|
|
32778
33112
|
// src/telemetry/dailyTokenUsage.ts
|
|
32779
33113
|
import { chmod, mkdir, open, readFile as readFile2, rename, rm } from "node:fs/promises";
|
|
32780
33114
|
import { dirname as dirname6, join as join14 } from "node:path";
|
|
32781
|
-
import { randomUUID as
|
|
33115
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
32782
33116
|
var TOKEN_USAGE_WINDOW_DAYS = 30;
|
|
32783
33117
|
var TOKEN_USAGE_RECOVERY_DAYS = 2;
|
|
32784
33118
|
var TOKEN_USAGE_RETENTION_DAYS = TOKEN_USAGE_WINDOW_DAYS + TOKEN_USAGE_RECOVERY_DAYS;
|
|
@@ -32949,7 +33283,7 @@ class DailyTokenUsageStore {
|
|
|
32949
33283
|
async persist() {
|
|
32950
33284
|
const directory = dirname6(this.filePath);
|
|
32951
33285
|
await mkdir(directory, { recursive: true, mode: 448 });
|
|
32952
|
-
const temporary = `${this.filePath}.${
|
|
33286
|
+
const temporary = `${this.filePath}.${randomUUID8()}.tmp`;
|
|
32953
33287
|
try {
|
|
32954
33288
|
const file2 = await open(temporary, "wx", 384);
|
|
32955
33289
|
try {
|
|
@@ -33031,15 +33365,17 @@ function createRuntimeRawLineTap(args) {
|
|
|
33031
33365
|
}
|
|
33032
33366
|
function deriveAuditLogSubcommand(pathname, method) {
|
|
33033
33367
|
const canonical = pathname.split("?")[0] ?? pathname;
|
|
33034
|
-
if (/^\/api\/community\/messages\/[^/]+\/
|
|
33035
|
-
|
|
33036
|
-
|
|
33368
|
+
if (/^\/api\/community\/messages\/[^/]+\/properties$/.test(canonical)) {
|
|
33369
|
+
if (method === "GET")
|
|
33370
|
+
return "messagePropertyList";
|
|
33037
33371
|
if (method === "PUT")
|
|
33038
|
-
return "
|
|
33372
|
+
return "messagePropertySet";
|
|
33039
33373
|
if (method === "DELETE")
|
|
33040
|
-
return "
|
|
33374
|
+
return "messagePropertyRemove";
|
|
33041
33375
|
return null;
|
|
33042
33376
|
}
|
|
33377
|
+
if (/^\/api\/community\/messages\/[^/]+\/reactions\//.test(canonical))
|
|
33378
|
+
return "reactAdd";
|
|
33043
33379
|
if (method === "GET" && /^\/api\/community\/users\/me\/marks$/.test(canonical))
|
|
33044
33380
|
return "markList";
|
|
33045
33381
|
if (/^\/api\/community\/channels\/[^/]+\/messages\/seq\//.test(canonical))
|
|
@@ -33205,14 +33541,14 @@ async function createDaemon(opts) {
|
|
|
33205
33541
|
log2.warn("inbox pull timeline observation failed", { agentId, reason, contentEncoding });
|
|
33206
33542
|
},
|
|
33207
33543
|
onMessageReminderArm: (input) => reminderSchedulerRef?.arm(input) ?? { armed: false, reason: "reminder_scheduler_unavailable" },
|
|
33208
|
-
onProxyRequest: (agentId, method, pathname) => {
|
|
33544
|
+
onProxyRequest: (agentId, method, pathname, metadata) => {
|
|
33209
33545
|
const subcommand = deriveAuditLogSubcommand(pathname, method);
|
|
33210
33546
|
if (!subcommand)
|
|
33211
33547
|
return;
|
|
33212
33548
|
const context = managerRef?.auditContext(agentId);
|
|
33213
33549
|
emitBotAuditEvent(agentId, {
|
|
33214
33550
|
kind: "cli_invocation",
|
|
33215
|
-
payload: { subcommand }
|
|
33551
|
+
payload: { subcommand, ...metadata ? { propertyType: metadata.propertyType } : {} }
|
|
33216
33552
|
}, context);
|
|
33217
33553
|
emitImplicitTypingStopOnSend({
|
|
33218
33554
|
subcommand,
|
|
@@ -34134,10 +34470,17 @@ function projectFsm(row, targetAgentId) {
|
|
|
34134
34470
|
"queueDwellTotalMs",
|
|
34135
34471
|
"sseReconnectCount"
|
|
34136
34472
|
];
|
|
34137
|
-
const
|
|
34473
|
+
const toolMetricKeys = [
|
|
34474
|
+
"outstandingToolUses",
|
|
34475
|
+
"anonymousOutstandingToolUses",
|
|
34476
|
+
"toolLifecycleMismatchCount"
|
|
34477
|
+
];
|
|
34478
|
+
const hasMetrics = metricKeys.some((key) => (key in row) || row[key] !== undefined) || toolMetricKeys.some((key) => (key in row) || row[key] !== undefined) || "resumeOutcome" in row || "terminalOwnerKind" in row;
|
|
34138
34479
|
if (hasMetrics) {
|
|
34139
34480
|
if (!metricKeys.every((key) => copyFiniteNumber(row, output, key)))
|
|
34140
34481
|
return null;
|
|
34482
|
+
if (!toolMetricKeys.every((key) => copyInteger(row, output, key, { optional: true })))
|
|
34483
|
+
return null;
|
|
34141
34484
|
const resumeOutcome = enumValue(row.resumeOutcome, RESUME_OUTCOMES);
|
|
34142
34485
|
const terminalOwnerKind = enumValue(row.terminalOwnerKind, TERMINAL_OWNER_KINDS);
|
|
34143
34486
|
if (!resumeOutcome || !terminalOwnerKind)
|
|
@@ -36849,7 +37192,7 @@ ${MESSAGE_SEND_STDIN_POLICY}`);
|
|
|
36849
37192
|
}
|
|
36850
37193
|
replyToSeq = n;
|
|
36851
37194
|
}
|
|
36852
|
-
const nonce =
|
|
37195
|
+
const nonce = randomUUID11();
|
|
36853
37196
|
const res = await sendWithRetry(api2, {
|
|
36854
37197
|
agentId: agent2,
|
|
36855
37198
|
channel: channel2,
|
|
@@ -36878,22 +37221,43 @@ ${MESSAGE_SEND_STDIN_POLICY}`);
|
|
|
36878
37221
|
return { sent, reminder: { armed: false, reason: "local reminder request failed" } };
|
|
36879
37222
|
}
|
|
36880
37223
|
}
|
|
36881
|
-
|
|
37224
|
+
function parseMessagePropertyJson(command, raw) {
|
|
37225
|
+
if (typeof raw !== "string")
|
|
37226
|
+
throw new CliError(`${command}: --json <json> is required`);
|
|
37227
|
+
try {
|
|
37228
|
+
return JSON.parse(raw);
|
|
37229
|
+
} catch {
|
|
37230
|
+
throw new CliError(`${command}: --json must be valid JSON`);
|
|
37231
|
+
}
|
|
37232
|
+
}
|
|
37233
|
+
async function cmdMessagePropertySet(opts) {
|
|
36882
37234
|
const api2 = getApi();
|
|
36883
37235
|
const target2 = opts.target;
|
|
36884
|
-
const emoji3 = opts.emoji;
|
|
36885
37236
|
if (!target2)
|
|
36886
|
-
throw new CliError("message
|
|
36887
|
-
|
|
36888
|
-
|
|
36889
|
-
const
|
|
36890
|
-
|
|
36891
|
-
|
|
36892
|
-
|
|
36893
|
-
|
|
36894
|
-
|
|
36895
|
-
|
|
36896
|
-
|
|
37237
|
+
throw new CliError("message property set: --target <ref> is required");
|
|
37238
|
+
const request = parseMessageTarget("message property set", target2);
|
|
37239
|
+
const property = parseMessagePropertyJson("message property set", opts.json);
|
|
37240
|
+
const result = await withTransientMutationRetry(() => api2.messagePropertySet({ ...request, property }));
|
|
37241
|
+
return { target: target2, ...result };
|
|
37242
|
+
}
|
|
37243
|
+
async function cmdMessagePropertyList(opts) {
|
|
37244
|
+
const api2 = getApi();
|
|
37245
|
+
const target2 = opts.target;
|
|
37246
|
+
if (!target2)
|
|
37247
|
+
throw new CliError("message property list: --target <ref> is required");
|
|
37248
|
+
const request = parseMessageTarget("message property list", target2);
|
|
37249
|
+
const result = await api2.messagePropertyList(request);
|
|
37250
|
+
return { target: target2, ...result };
|
|
37251
|
+
}
|
|
37252
|
+
async function cmdMessagePropertyRemove(opts) {
|
|
37253
|
+
const api2 = getApi();
|
|
37254
|
+
const target2 = opts.target;
|
|
37255
|
+
if (!target2)
|
|
37256
|
+
throw new CliError("message property remove: --target <ref> is required");
|
|
37257
|
+
const request = parseMessageTarget("message property remove", target2);
|
|
37258
|
+
const property = parseMessagePropertyJson("message property remove", opts.json);
|
|
37259
|
+
const result = await withTransientMutationRetry(() => api2.messagePropertyRemove({ ...request, property }));
|
|
37260
|
+
return { target: target2, ...result };
|
|
36897
37261
|
}
|
|
36898
37262
|
function parseMessageTarget(command, target2) {
|
|
36899
37263
|
let parsed;
|
|
@@ -36910,24 +37274,6 @@ function parseMessageTarget(command, target2) {
|
|
|
36910
37274
|
const channel2 = parsed.threadRootSeq !== undefined ? `/${parsed.server}/${parsed.channel}/#${parsed.threadRootSeq}` : `/${parsed.server}/${parsed.channel}`;
|
|
36911
37275
|
return { channel: channel2, seq: parsed.seq };
|
|
36912
37276
|
}
|
|
36913
|
-
async function cmdMessageMarkSet(opts) {
|
|
36914
|
-
const api2 = getApi();
|
|
36915
|
-
const target2 = opts.target;
|
|
36916
|
-
if (!target2)
|
|
36917
|
-
throw new CliError("message mark set: --target <ref> is required");
|
|
36918
|
-
const request = parseMessageTarget("message mark set", target2);
|
|
36919
|
-
await withTransientMutationRetry(() => api2.markSet(request));
|
|
36920
|
-
return { target: target2, marked: true };
|
|
36921
|
-
}
|
|
36922
|
-
async function cmdMessageMarkRemove(opts) {
|
|
36923
|
-
const api2 = getApi();
|
|
36924
|
-
const target2 = opts.target;
|
|
36925
|
-
if (!target2)
|
|
36926
|
-
throw new CliError("message mark remove: --target <ref> is required");
|
|
36927
|
-
const request = parseMessageTarget("message mark remove", target2);
|
|
36928
|
-
await withTransientMutationRetry(() => api2.markRemove(request));
|
|
36929
|
-
return { target: target2, marked: false };
|
|
36930
|
-
}
|
|
36931
37277
|
async function cmdMessageMarkList(opts) {
|
|
36932
37278
|
const api2 = getApi();
|
|
36933
37279
|
const { marked } = await api2.listMarks({ agentId: agentId(opts) });
|
|
@@ -37057,7 +37403,7 @@ async function cmdInboxPull(opts) {
|
|
|
37057
37403
|
let acked = 0;
|
|
37058
37404
|
let ackError;
|
|
37059
37405
|
let failed;
|
|
37060
|
-
if (
|
|
37406
|
+
if (messages.length > 0) {
|
|
37061
37407
|
const latest = new Map;
|
|
37062
37408
|
for (const m of messages) {
|
|
37063
37409
|
const seqN = Number(m.seq.replace("#", ""));
|
|
@@ -37125,6 +37471,14 @@ async function cmdServerJoin(opts) {
|
|
|
37125
37471
|
const { server } = await api2.joinServer({ agentId: agent2, invite: token });
|
|
37126
37472
|
return { server };
|
|
37127
37473
|
}
|
|
37474
|
+
async function cmdServerLeave(opts) {
|
|
37475
|
+
const api2 = getApi();
|
|
37476
|
+
const agent2 = agentId(opts);
|
|
37477
|
+
const server = opts.server;
|
|
37478
|
+
if (!server)
|
|
37479
|
+
throw new CliError("server leave: --server <name#NNNN> is required");
|
|
37480
|
+
return await api2.leaveServer({ agentId: agent2, server });
|
|
37481
|
+
}
|
|
37128
37482
|
async function cmdChannelList(opts) {
|
|
37129
37483
|
const api2 = getApi();
|
|
37130
37484
|
const agent2 = agentId(opts);
|
|
@@ -37141,6 +37495,26 @@ async function cmdChannelMember(opts) {
|
|
|
37141
37495
|
throw new CliError("channel member: --channel <ref> is required");
|
|
37142
37496
|
return await api2.channelMember({ agentId: agent2, channel: channel2 });
|
|
37143
37497
|
}
|
|
37498
|
+
async function cmdChannelLeave(opts) {
|
|
37499
|
+
const api2 = getApi();
|
|
37500
|
+
const agent2 = agentId(opts);
|
|
37501
|
+
const channel2 = opts.channel;
|
|
37502
|
+
if (!channel2)
|
|
37503
|
+
throw new CliError("channel leave: --channel <ref> is required");
|
|
37504
|
+
let parsed;
|
|
37505
|
+
try {
|
|
37506
|
+
parsed = parseRef(channel2);
|
|
37507
|
+
} catch {
|
|
37508
|
+
throw new CliError("channel leave: malformed channel ref");
|
|
37509
|
+
}
|
|
37510
|
+
if (parsed.server === DM_SERVER) {
|
|
37511
|
+
throw new CliError("channel leave: DMs cannot be left");
|
|
37512
|
+
}
|
|
37513
|
+
if (parsed.seq !== undefined) {
|
|
37514
|
+
throw new CliError("channel leave: message refs cannot be left; use a channel or thread-root ref");
|
|
37515
|
+
}
|
|
37516
|
+
return await api2.leaveChannel({ agentId: agent2, channel: channel2 });
|
|
37517
|
+
}
|
|
37144
37518
|
async function cmdChannelHistory(opts) {
|
|
37145
37519
|
const api2 = getApi();
|
|
37146
37520
|
const agent2 = agentId(opts);
|
|
@@ -37198,22 +37572,22 @@ function buildProgram(stdin) {
|
|
|
37198
37572
|
const result = await cmdMessageSend({ ...globalOpts, ...localOpts }, stdin);
|
|
37199
37573
|
printEnvelope({ success: result });
|
|
37200
37574
|
});
|
|
37201
|
-
message2.command("
|
|
37202
|
-
|
|
37203
|
-
|
|
37204
|
-
const result = await
|
|
37575
|
+
const property = message2.command("property").description("message property operations").exitOverride();
|
|
37576
|
+
property.configureOutput({ writeOut: () => {}, writeErr: () => {} });
|
|
37577
|
+
property.command("set").description("add a supported property value to a message").requiredOption("--target <ref>", "full message ref").requiredOption("--json <json>", "property JSON").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37578
|
+
const result = await cmdMessagePropertySet({ ...program.opts(), ...this.opts() });
|
|
37205
37579
|
printEnvelope({ success: result });
|
|
37206
37580
|
});
|
|
37207
|
-
|
|
37208
|
-
|
|
37209
|
-
mark.command("set").description("mark a message as outstanding work").requiredOption("--target <ref>", "full message ref").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37210
|
-
const result = await cmdMessageMarkSet({ ...program.opts(), ...this.opts() });
|
|
37581
|
+
property.command("list").description("list current properties and supported capabilities").requiredOption("--target <ref>", "full message ref").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37582
|
+
const result = await cmdMessagePropertyList({ ...program.opts(), ...this.opts() });
|
|
37211
37583
|
printEnvelope({ success: result });
|
|
37212
37584
|
});
|
|
37213
|
-
|
|
37214
|
-
const result = await
|
|
37585
|
+
property.command("remove").description("remove a supported property value from a message").requiredOption("--target <ref>", "full message ref").requiredOption("--json <json>", "property JSON").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37586
|
+
const result = await cmdMessagePropertyRemove({ ...program.opts(), ...this.opts() });
|
|
37215
37587
|
printEnvelope({ success: result });
|
|
37216
37588
|
});
|
|
37589
|
+
const mark = message2.command("mark").description("global durable-mark queries").exitOverride();
|
|
37590
|
+
mark.configureOutput({ writeOut: () => {}, writeErr: () => {} });
|
|
37217
37591
|
mark.command("list").description("list all currently visible marked messages").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37218
37592
|
const result = await cmdMessageMarkList({ ...program.opts(), ...this.opts() });
|
|
37219
37593
|
printEnvelope({ success: result });
|
|
@@ -37234,7 +37608,7 @@ function buildProgram(stdin) {
|
|
|
37234
37608
|
});
|
|
37235
37609
|
const inbox = program.command("inbox").description("inbox operations").exitOverride();
|
|
37236
37610
|
inbox.configureOutput({ writeOut: () => {}, writeErr: () => {} });
|
|
37237
|
-
inbox.command("pull").description("fetch unread messages from all channels").option("--max <n>", "max messages to return").
|
|
37611
|
+
inbox.command("pull").description("fetch unread messages from all channels").option("--max <n>", "max messages to return").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37238
37612
|
const localOpts = this.opts();
|
|
37239
37613
|
const globalOpts = program.opts();
|
|
37240
37614
|
const result = await cmdInboxPull({ ...globalOpts, ...localOpts });
|
|
@@ -37260,6 +37634,12 @@ function buildProgram(stdin) {
|
|
|
37260
37634
|
const result = await cmdServerJoin({ ...globalOpts, ...localOpts });
|
|
37261
37635
|
printEnvelope({ success: result });
|
|
37262
37636
|
});
|
|
37637
|
+
server.command("leave").description("leave a server you belong to").option("--server <handle>", "server name#NNNN handle (from `server list`)").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37638
|
+
const localOpts = this.opts();
|
|
37639
|
+
const globalOpts = program.opts();
|
|
37640
|
+
const result = await cmdServerLeave({ ...globalOpts, ...localOpts });
|
|
37641
|
+
printEnvelope({ success: result });
|
|
37642
|
+
});
|
|
37263
37643
|
const channel2 = program.command("channel").description("channel operations").exitOverride();
|
|
37264
37644
|
channel2.configureOutput({ writeOut: () => {}, writeErr: () => {} });
|
|
37265
37645
|
channel2.command("list").description("list top-level channels visible to this agent in one server").option("--server <handle>", "server name#discriminator handle (from `server list`)").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
@@ -37280,6 +37660,12 @@ function buildProgram(stdin) {
|
|
|
37280
37660
|
const result = await cmdChannelMember({ ...globalOpts, ...localOpts });
|
|
37281
37661
|
printEnvelope({ success: result });
|
|
37282
37662
|
});
|
|
37663
|
+
channel2.command("leave").description("leave a thread or private channel/forum").option("--channel <ref>", "channel/thread ref (path-style)").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|
|
37664
|
+
const localOpts = this.opts();
|
|
37665
|
+
const globalOpts = program.opts();
|
|
37666
|
+
const result = await cmdChannelLeave({ ...globalOpts, ...localOpts });
|
|
37667
|
+
printEnvelope({ success: result });
|
|
37668
|
+
});
|
|
37283
37669
|
const friend = program.command("friend").description("friend operations").exitOverride();
|
|
37284
37670
|
friend.configureOutput({ writeOut: () => {}, writeErr: () => {} });
|
|
37285
37671
|
friend.command("request").description("send a friend request to a user by handle (owner-approval required)").option("--username <name#0042>", "the target's global handle, e.g. Alice#0042").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
|