@parall/parall 1.63.0 → 1.65.0
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/gateway.d.ts.map +1 -1
- package/dist/gateway.js +6 -1
- package/dist/index.bundle.mjs +1065 -515
- package/package.json +3 -3
- package/skills/parall-browser/SKILL.md +53 -0
- package/skills/parall-clips/SKILL.md +3 -6
- package/src/gateway.ts +6 -1
package/dist/index.bundle.mjs
CHANGED
|
@@ -52248,6 +52248,67 @@ function describeRuntimeTurnTrigger(trigger) {
|
|
|
52248
52248
|
}
|
|
52249
52249
|
}
|
|
52250
52250
|
|
|
52251
|
+
// ../agent-core/dist/redact.js
|
|
52252
|
+
function redactSecrets(s, knownValues = []) {
|
|
52253
|
+
return maskKnownValues(s, knownValues).replace(/\b(agk|mck|cpk)_[A-Za-z0-9_-]+/g, "$1_***").replace(/\b(sk|pk|rk)-[A-Za-z0-9_-]{8,}/g, "$1-***").replace(/\bAKIA[0-9A-Z]{16}\b/g, "AKIA***").replace(/\b((?:bearer|basic)\s+)[A-Za-z0-9._~+/=-]+/gi, "$1***").replace(/(\b(?:[\w-]*[_-])?(?:api[_-]?key|key|token|secret|password|passwd|authorization)["']?\s*[=:]\s*)(?:"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'|[^\s&;,}\]"']+)/gi, "$1***").replace(/[A-Za-z0-9_-]{32,}/g, "***");
|
|
52254
|
+
}
|
|
52255
|
+
function maskKnownValues(s, knownValues) {
|
|
52256
|
+
let out = s;
|
|
52257
|
+
for (const v of knownValues) {
|
|
52258
|
+
if (typeof v === "string" && v.length >= 6)
|
|
52259
|
+
out = out.split(v).join("***");
|
|
52260
|
+
}
|
|
52261
|
+
return out;
|
|
52262
|
+
}
|
|
52263
|
+
function redactTurnOutcome(event, knownValues) {
|
|
52264
|
+
const redacted = { ...event };
|
|
52265
|
+
if (redacted.detail)
|
|
52266
|
+
redacted.detail = redactSecrets(redacted.detail, knownValues);
|
|
52267
|
+
if (redacted.raw) {
|
|
52268
|
+
redacted.raw = Object.fromEntries(Object.entries(redacted.raw).map(([k, v]) => [
|
|
52269
|
+
k,
|
|
52270
|
+
typeof v === "string" ? redactSecrets(v, knownValues) : v
|
|
52271
|
+
]));
|
|
52272
|
+
}
|
|
52273
|
+
return redacted;
|
|
52274
|
+
}
|
|
52275
|
+
function describeTurnOutcomeFailure(outcome) {
|
|
52276
|
+
const retryNote = outcome.retryAt ? `, retry at ${outcome.retryAt}` : "";
|
|
52277
|
+
return {
|
|
52278
|
+
warn: `${outcome.outcome}${retryNote}${outcome.detail ? ` \u2014 ${outcome.detail}` : ""}`,
|
|
52279
|
+
stepMessage: `LLM turn ${outcome.outcome}${retryNote}${outcome.detail ? `: ${outcome.detail}` : ""}`
|
|
52280
|
+
};
|
|
52281
|
+
}
|
|
52282
|
+
function redactLogger(log, knownValues) {
|
|
52283
|
+
if (!log)
|
|
52284
|
+
return void 0;
|
|
52285
|
+
return {
|
|
52286
|
+
info: (message) => log.info(redactSecrets(message, knownValues)),
|
|
52287
|
+
warn: (message) => log.warn(redactSecrets(message, knownValues)),
|
|
52288
|
+
error: (message) => log.error(redactSecrets(message, knownValues)),
|
|
52289
|
+
...log.child ? { child: (name) => redactLogger(log.child(name), knownValues) } : {}
|
|
52290
|
+
};
|
|
52291
|
+
}
|
|
52292
|
+
|
|
52293
|
+
// ../agent-core/dist/runtime-observation.js
|
|
52294
|
+
async function persistRuntimeObservation(persister, sessionId, target, event, log, knownSecrets = []) {
|
|
52295
|
+
const native = event.content.native && Object.fromEntries(Object.entries(event.content.native).map(([key, value]) => [
|
|
52296
|
+
key,
|
|
52297
|
+
typeof value !== "string" ? value : key.endsWith("_id") ? maskKnownValues(value, knownSecrets) : redactSecrets(value, knownSecrets)
|
|
52298
|
+
]));
|
|
52299
|
+
try {
|
|
52300
|
+
await persister.persist(sessionId, "observation", {
|
|
52301
|
+
step_type: "observation",
|
|
52302
|
+
...target,
|
|
52303
|
+
idempotency_key: `observation:${event.observationId}`,
|
|
52304
|
+
content: { ...event.content, ...native ? { native } : {} },
|
|
52305
|
+
projection: false
|
|
52306
|
+
});
|
|
52307
|
+
} catch (err) {
|
|
52308
|
+
log?.warn(`runtime observation could not be saved for ${sessionId}: ${String(err)}`);
|
|
52309
|
+
}
|
|
52310
|
+
}
|
|
52311
|
+
|
|
52251
52312
|
// ../agent-core/dist/fork-prefix.js
|
|
52252
52313
|
function sanitizeMeta(value) {
|
|
52253
52314
|
return value.replace(/[\r\n]+/g, " ").replace(/[[\]|]/g, " ").trim();
|
|
@@ -52286,6 +52347,143 @@ function buildForkResultPrefix(results) {
|
|
|
52286
52347
|
return blocks.join("\n\n") + "\n\n---\n\n";
|
|
52287
52348
|
}
|
|
52288
52349
|
|
|
52350
|
+
// ../agent-core/dist/gateway-runtime-step.js
|
|
52351
|
+
import { randomUUID } from "node:crypto";
|
|
52352
|
+
async function createRuntimeStep(host, sessionId, target, runtimeEvent, stepIdFilePath, contextFilePath, laneContextFilePath2) {
|
|
52353
|
+
switch (runtimeEvent.type) {
|
|
52354
|
+
case "observation":
|
|
52355
|
+
await persistRuntimeObservation(host.stepPersister, sessionId, target, runtimeEvent, host.opts?.log, host.opts?.config ? [host.opts.config.api_key] : []);
|
|
52356
|
+
break;
|
|
52357
|
+
case "thinking":
|
|
52358
|
+
await host.stepPersister.persist(sessionId, "thinking", {
|
|
52359
|
+
step_type: "thinking",
|
|
52360
|
+
target_type: target.target_type,
|
|
52361
|
+
target_id: target.target_id,
|
|
52362
|
+
idempotency_key: randomUUID(),
|
|
52363
|
+
content: { text: runtimeEvent.text },
|
|
52364
|
+
group_key: runtimeEvent.groupKey
|
|
52365
|
+
});
|
|
52366
|
+
break;
|
|
52367
|
+
case "text":
|
|
52368
|
+
await host.stepPersister.persist(sessionId, "text", {
|
|
52369
|
+
step_type: "text",
|
|
52370
|
+
target_type: target.target_type,
|
|
52371
|
+
target_id: target.target_id,
|
|
52372
|
+
idempotency_key: randomUUID(),
|
|
52373
|
+
content: {
|
|
52374
|
+
text: runtimeEvent.text,
|
|
52375
|
+
suppressed: runtimeEvent.project !== true
|
|
52376
|
+
},
|
|
52377
|
+
projection: runtimeEvent.project === true,
|
|
52378
|
+
group_key: runtimeEvent.groupKey
|
|
52379
|
+
});
|
|
52380
|
+
break;
|
|
52381
|
+
case "tool_call": {
|
|
52382
|
+
const step = await host.stepPersister.persist(sessionId, "tool_call", {
|
|
52383
|
+
step_type: "tool_call",
|
|
52384
|
+
target_type: target.target_type,
|
|
52385
|
+
target_id: target.target_id,
|
|
52386
|
+
// call_id is session-unique for bridge runtimes (server-enforced),
|
|
52387
|
+
// so the bare form anchors the tool step pair across retries —
|
|
52388
|
+
// unlike parel's turn-scoped `tc:{turnId}:{callId}` (see
|
|
52389
|
+
// protocol-vectors/agent-steps.json).
|
|
52390
|
+
idempotency_key: `tc:${runtimeEvent.callId}`,
|
|
52391
|
+
content: {
|
|
52392
|
+
call_id: runtimeEvent.callId,
|
|
52393
|
+
tool_name: runtimeEvent.toolName,
|
|
52394
|
+
tool_input: runtimeEvent.input,
|
|
52395
|
+
status: "running",
|
|
52396
|
+
started_at: runtimeEvent.startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
52397
|
+
},
|
|
52398
|
+
group_key: runtimeEvent.groupKey,
|
|
52399
|
+
runtime_key: runtimeEvent.callId
|
|
52400
|
+
});
|
|
52401
|
+
if (step) {
|
|
52402
|
+
if (contextFilePath) {
|
|
52403
|
+
host.updateContextFileStepId(contextFilePath, step.id);
|
|
52404
|
+
} else if (stepIdFilePath) {
|
|
52405
|
+
host.writeStepIdFile(stepIdFilePath, step.id);
|
|
52406
|
+
}
|
|
52407
|
+
if (laneContextFilePath2) {
|
|
52408
|
+
host.updateContextFileStepId(laneContextFilePath2, step.id);
|
|
52409
|
+
}
|
|
52410
|
+
}
|
|
52411
|
+
break;
|
|
52412
|
+
}
|
|
52413
|
+
case "tool_result":
|
|
52414
|
+
await host.stepPersister.persist(sessionId, "tool_result", {
|
|
52415
|
+
step_type: "tool_result",
|
|
52416
|
+
target_type: target.target_type,
|
|
52417
|
+
target_id: target.target_id,
|
|
52418
|
+
idempotency_key: `tr:${runtimeEvent.callId}`,
|
|
52419
|
+
content: {
|
|
52420
|
+
call_id: runtimeEvent.callId,
|
|
52421
|
+
tool_name: runtimeEvent.toolName,
|
|
52422
|
+
status: runtimeEvent.error ? "error" : "success",
|
|
52423
|
+
output: runtimeEvent.output,
|
|
52424
|
+
duration_ms: runtimeEvent.durationMs ?? 0,
|
|
52425
|
+
collapsible: true
|
|
52426
|
+
},
|
|
52427
|
+
group_key: runtimeEvent.groupKey
|
|
52428
|
+
});
|
|
52429
|
+
if (contextFilePath) {
|
|
52430
|
+
host.updateContextFileStepId(contextFilePath, null);
|
|
52431
|
+
} else if (stepIdFilePath) {
|
|
52432
|
+
host.clearStepIdFile(stepIdFilePath);
|
|
52433
|
+
}
|
|
52434
|
+
if (laneContextFilePath2) {
|
|
52435
|
+
host.updateContextFileStepId(laneContextFilePath2, null);
|
|
52436
|
+
}
|
|
52437
|
+
break;
|
|
52438
|
+
case "error":
|
|
52439
|
+
await host.stepPersister.persist(sessionId, "error", {
|
|
52440
|
+
step_type: "text",
|
|
52441
|
+
target_type: target.target_type,
|
|
52442
|
+
target_id: target.target_id,
|
|
52443
|
+
idempotency_key: randomUUID(),
|
|
52444
|
+
content: buildErrorStepContent(runtimeEvent.message),
|
|
52445
|
+
projection: false,
|
|
52446
|
+
group_key: runtimeEvent.groupKey
|
|
52447
|
+
});
|
|
52448
|
+
break;
|
|
52449
|
+
}
|
|
52450
|
+
}
|
|
52451
|
+
|
|
52452
|
+
// ../agent-core/dist/dispatch-recovery.js
|
|
52453
|
+
var DispatchRecovery = class {
|
|
52454
|
+
scan;
|
|
52455
|
+
stopped;
|
|
52456
|
+
onError;
|
|
52457
|
+
running = false;
|
|
52458
|
+
requested = false;
|
|
52459
|
+
constructor(scan, stopped, onError) {
|
|
52460
|
+
this.scan = scan;
|
|
52461
|
+
this.stopped = stopped;
|
|
52462
|
+
this.onError = onError;
|
|
52463
|
+
}
|
|
52464
|
+
request = () => {
|
|
52465
|
+
if (this.stopped())
|
|
52466
|
+
return;
|
|
52467
|
+
this.requested = true;
|
|
52468
|
+
if (this.running)
|
|
52469
|
+
return;
|
|
52470
|
+
this.running = true;
|
|
52471
|
+
void this.run();
|
|
52472
|
+
};
|
|
52473
|
+
async run() {
|
|
52474
|
+
try {
|
|
52475
|
+
while (this.requested && !this.stopped()) {
|
|
52476
|
+
this.requested = false;
|
|
52477
|
+
await this.scan();
|
|
52478
|
+
}
|
|
52479
|
+
} catch (err) {
|
|
52480
|
+
this.onError(err);
|
|
52481
|
+
} finally {
|
|
52482
|
+
this.running = false;
|
|
52483
|
+
}
|
|
52484
|
+
}
|
|
52485
|
+
};
|
|
52486
|
+
|
|
52289
52487
|
// ../agent-core/dist/gateway-base.js
|
|
52290
52488
|
import * as os from "node:os";
|
|
52291
52489
|
|
|
@@ -52310,7 +52508,7 @@ function splitChangeSource(sourceId) {
|
|
|
52310
52508
|
// ../agent-core/dist/gateway-base.js
|
|
52311
52509
|
import * as fs4 from "node:fs";
|
|
52312
52510
|
import * as path5 from "node:path";
|
|
52313
|
-
import { randomUUID } from "node:crypto";
|
|
52511
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
52314
52512
|
|
|
52315
52513
|
// ../sdk/dist/browser-viewer.js
|
|
52316
52514
|
var BROWSER_VIEWER_READINESS_TIMEOUT_MS = 6e4;
|
|
@@ -52323,8 +52521,23 @@ function browserViewerRequestOptions(command, opts) {
|
|
|
52323
52521
|
};
|
|
52324
52522
|
}
|
|
52325
52523
|
|
|
52524
|
+
// ../sdk/dist/slack-endpoints.js
|
|
52525
|
+
function slackEndpoints(apiBase) {
|
|
52526
|
+
return {
|
|
52527
|
+
SLACK_CHANNELS: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/channels`,
|
|
52528
|
+
SLACK_USERS: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/users`,
|
|
52529
|
+
SLACK_REPLIES: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/replies`,
|
|
52530
|
+
SLACK_HISTORY: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/history`,
|
|
52531
|
+
SLACK_MEMBERS: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/members`,
|
|
52532
|
+
SLACK_STATUS: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/status`,
|
|
52533
|
+
SLACK_FILE: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/file`,
|
|
52534
|
+
SLACK_FILES: (orgId) => `${apiBase}/orgs/${orgId}/agents/me/slack/files`
|
|
52535
|
+
};
|
|
52536
|
+
}
|
|
52537
|
+
|
|
52326
52538
|
// ../sdk/dist/clip-connection-endpoints.js
|
|
52327
52539
|
var clipConnectionEndpoints = {
|
|
52540
|
+
ORG_CLIP_MCP_OAUTH_ATTEMPT: (orgId, clipId, attemptId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/mcp-oauth-attempts/${attemptId}`,
|
|
52328
52541
|
CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
|
|
52329
52542
|
CLIP_CONNECTION_ACCESS: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}/access`,
|
|
52330
52543
|
CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`
|
|
@@ -52625,6 +52838,7 @@ var ENDPOINTS = {
|
|
|
52625
52838
|
TRIGGER: (orgId, triggerId) => `${API_BASE2}/orgs/${orgId}/external-triggers/${triggerId}`,
|
|
52626
52839
|
/** @deprecated Use TRIGGER. Same compatibility path. */
|
|
52627
52840
|
EXTERNAL_TRIGGER: (orgId, triggerId) => `${API_BASE2}/orgs/${orgId}/external-triggers/${triggerId}`,
|
|
52841
|
+
PLATFORM_TRIGGER_SCHEMA: (orgId) => `${API_BASE2}/orgs/${orgId}/platform-trigger-schema`,
|
|
52628
52842
|
TRIGGER_RUNS: (orgId) => `${API_BASE2}/orgs/${orgId}/external-trigger-runs`,
|
|
52629
52843
|
/** @deprecated Use TRIGGER_RUNS. Same compatibility path. */
|
|
52630
52844
|
EXTERNAL_TRIGGER_RUNS: (orgId) => `${API_BASE2}/orgs/${orgId}/external-trigger-runs`,
|
|
@@ -52649,13 +52863,7 @@ var ENDPOINTS = {
|
|
|
52649
52863
|
// Tier-B platform verb (agent-only): send one message as the bound bot.
|
|
52650
52864
|
CHANNEL_SEND: (orgId) => `${API_BASE2}/orgs/${orgId}/agents/me/channel-send`,
|
|
52651
52865
|
// Tier-B read verbs (agent-only): workspace visibility as the bot sees it.
|
|
52652
|
-
|
|
52653
|
-
SLACK_USERS: (orgId) => `${API_BASE2}/orgs/${orgId}/agents/me/slack/users`,
|
|
52654
|
-
SLACK_HISTORY: (orgId) => `${API_BASE2}/orgs/${orgId}/agents/me/slack/history`,
|
|
52655
|
-
SLACK_MEMBERS: (orgId) => `${API_BASE2}/orgs/${orgId}/agents/me/slack/members`,
|
|
52656
|
-
SLACK_STATUS: (orgId) => `${API_BASE2}/orgs/${orgId}/agents/me/slack/status`,
|
|
52657
|
-
SLACK_FILE: (orgId) => `${API_BASE2}/orgs/${orgId}/agents/me/slack/file`,
|
|
52658
|
-
SLACK_FILES: (orgId) => `${API_BASE2}/orgs/${orgId}/agents/me/slack/files`,
|
|
52866
|
+
...slackEndpoints(API_BASE2),
|
|
52659
52867
|
// WeChat tier-B read verbs (agent-only; internal research preview).
|
|
52660
52868
|
...wechatEndpoints(API_BASE2),
|
|
52661
52869
|
// Invitations (org-scoped, admin)
|
|
@@ -52802,6 +53010,8 @@ var ENDPOINTS = {
|
|
|
52802
53010
|
BILLING_CHECKOUT: (orgId) => `${API_BASE2}/orgs/${orgId}/billing/checkout`,
|
|
52803
53011
|
BILLING_AUTO_RELOAD: (orgId) => `${API_BASE2}/orgs/${orgId}/billing/auto-reload`,
|
|
52804
53012
|
BILLING_SETUP_INTENT: (orgId) => `${API_BASE2}/orgs/${orgId}/billing/setup-intent`,
|
|
53013
|
+
BILLING_USAGE_DAILY: (orgId) => `${API_BASE2}/orgs/${orgId}/billing/usage-daily`,
|
|
53014
|
+
BILLING_USAGE_HEATMAP: (orgId) => `${API_BASE2}/orgs/${orgId}/billing/usage-heatmap`,
|
|
52805
53015
|
COMPUTE_PRICING: () => `${API_BASE2}/billing/compute-pricing`,
|
|
52806
53016
|
// Runtime capability table (public, no auth) — SSOT for the create/settings
|
|
52807
53017
|
// interlock: per-runtime compute modes, native model family, cross-family
|
|
@@ -52836,16 +53046,6 @@ var ENDPOINTS = {
|
|
|
52836
53046
|
BROWSER_PROFILE_VIEWER_COMMAND: (orgId, profileId) => `${API_BASE2}/orgs/${orgId}/browser-profiles/${profileId}/viewer/command`,
|
|
52837
53047
|
// Edge device endpoints
|
|
52838
53048
|
...edgeEndpoints,
|
|
52839
|
-
ORG_BROWSER_ALIASES: (orgId) => `/api/v1/orgs/${orgId}/browser-aliases`,
|
|
52840
|
-
ORG_BROWSER_ALIAS: (orgId, aliasId) => `/api/v1/orgs/${orgId}/browser-aliases/${aliasId}`,
|
|
52841
|
-
ORG_BROWSER_ALIAS_READINESS_CHECKS: (orgId, aliasId) => `/api/v1/orgs/${orgId}/browser-aliases/${aliasId}/readiness-checks`,
|
|
52842
|
-
ORG_BROWSER_ALIAS_READINESS_CHECK: (orgId, aliasId, checkId) => `/api/v1/orgs/${orgId}/browser-aliases/${aliasId}/readiness-checks/${checkId}`,
|
|
52843
|
-
ORG_API_KEY_BROWSER_ALIAS_GRANTS: (orgId, keyId) => `/api/v1/orgs/${orgId}/api-keys/${keyId}/browser-alias-grants`,
|
|
52844
|
-
ORG_API_KEY_BROWSER_ALIAS_GRANT: (orgId, keyId, aliasId) => `/api/v1/orgs/${orgId}/api-keys/${keyId}/browser-alias-grants/${aliasId}`,
|
|
52845
|
-
ORG_MANAGED_ALIASES: (orgId) => `/api/v1/orgs/${orgId}/aliases`,
|
|
52846
|
-
ORG_MANAGED_ALIAS: (orgId, aliasName) => `/api/v1/orgs/${orgId}/aliases/${encodeURIComponent(aliasName)}`,
|
|
52847
|
-
ORG_BROWSER_ALIAS_EXECUTIONS: (orgId) => `/api/v1/orgs/${orgId}/executions`,
|
|
52848
|
-
ORG_BROWSER_ALIAS_EXECUTION: (orgId, requestId) => `/api/v1/orgs/${orgId}/executions/${encodeURIComponent(requestId)}`,
|
|
52849
53049
|
ORG_BROWSER_USE_OPERATIONS: (orgId) => `/api/v1/orgs/${orgId}/browser-use/operations`,
|
|
52850
53050
|
ORG_BROWSER_USE_OPERATION: (orgId, operationId) => `/api/v1/orgs/${orgId}/browser-use/operations/${encodeURIComponent(operationId)}`,
|
|
52851
53051
|
// Per-profile egress proxy (hosted Cloud Profiles; manager-only, human-only).
|
|
@@ -53345,14 +53545,16 @@ var SlackFilesClient = class extends AttachmentClient {
|
|
|
53345
53545
|
}
|
|
53346
53546
|
/**
|
|
53347
53547
|
* Tier-B file upload verb (agent-only): share a file into a Slack
|
|
53348
|
-
* conversation
|
|
53349
|
-
*
|
|
53548
|
+
* conversation or thread with the same addressing as text sends.
|
|
53549
|
+
* Native threadTs requires a server supporting Slack thread sends.
|
|
53350
53550
|
*/
|
|
53351
53551
|
async sendSlackFile(orgId, input) {
|
|
53352
53552
|
const fd = new FormData();
|
|
53353
53553
|
fd.append("conversation_id", input.conversationId);
|
|
53354
53554
|
if (input.replyTo)
|
|
53355
53555
|
fd.append("reply_to", input.replyTo);
|
|
53556
|
+
if (input.threadTs)
|
|
53557
|
+
fd.append("thread_ts", input.threadTs);
|
|
53356
53558
|
if (input.text)
|
|
53357
53559
|
fd.append("text", input.text);
|
|
53358
53560
|
fd.append("file", input.content, input.fileName);
|
|
@@ -53360,8 +53562,48 @@ var SlackFilesClient = class extends AttachmentClient {
|
|
|
53360
53562
|
}
|
|
53361
53563
|
};
|
|
53362
53564
|
|
|
53565
|
+
// ../sdk/dist/slack-read-client.js
|
|
53566
|
+
var SlackReadClient = class extends SlackFilesClient {
|
|
53567
|
+
slackReadQuery(base, query, extra) {
|
|
53568
|
+
const params = new URLSearchParams();
|
|
53569
|
+
if (query?.cursor)
|
|
53570
|
+
params.set("cursor", query.cursor);
|
|
53571
|
+
if (query?.limit)
|
|
53572
|
+
params.set("limit", String(query.limit));
|
|
53573
|
+
for (const [k, v] of Object.entries(extra ?? {}))
|
|
53574
|
+
params.set(k, v);
|
|
53575
|
+
const qs = params.toString();
|
|
53576
|
+
return qs ? `${base}?${qs}` : base;
|
|
53577
|
+
}
|
|
53578
|
+
/**
|
|
53579
|
+
* Tier-B read verbs (agent-only): workspace visibility as the bot sees
|
|
53580
|
+
* it. Same live gate as the send verb; authorization beyond it is the
|
|
53581
|
+
* bot's own Slack permissions.
|
|
53582
|
+
*/
|
|
53583
|
+
async listSlackChannels(orgId, query) {
|
|
53584
|
+
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_CHANNELS(orgId), query));
|
|
53585
|
+
}
|
|
53586
|
+
async listSlackUsers(orgId, query) {
|
|
53587
|
+
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_USERS(orgId), query));
|
|
53588
|
+
}
|
|
53589
|
+
async slackHistory(orgId, conversationId, query) {
|
|
53590
|
+
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_HISTORY(orgId), query, { conversation: conversationId }));
|
|
53591
|
+
}
|
|
53592
|
+
/** Read a Slack thread (parent and replies), one page in Slack order. */
|
|
53593
|
+
async slackReplies(orgId, channel, ts, query) {
|
|
53594
|
+
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_REPLIES(orgId), query, { channel, ts }));
|
|
53595
|
+
}
|
|
53596
|
+
async slackMembers(orgId, conversationId, query) {
|
|
53597
|
+
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_MEMBERS(orgId), query, { conversation: conversationId }));
|
|
53598
|
+
}
|
|
53599
|
+
/** Set/clear the Agents-pane "typing…" indicator (best-effort cosmetic). */
|
|
53600
|
+
async setSlackStatus(orgId, input) {
|
|
53601
|
+
await this.request("POST", ENDPOINTS.SLACK_STATUS(orgId), input);
|
|
53602
|
+
}
|
|
53603
|
+
};
|
|
53604
|
+
|
|
53363
53605
|
// ../sdk/dist/channel-conversation-client.js
|
|
53364
|
-
var ChannelConversationClient = class extends
|
|
53606
|
+
var ChannelConversationClient = class extends SlackReadClient {
|
|
53365
53607
|
/**
|
|
53366
53608
|
* Org-admin write of what the agent receives from a group root
|
|
53367
53609
|
* (`PATCH …/channel-conversations/{id}/attention`); the agent's own path
|
|
@@ -53392,10 +53634,62 @@ var ClipConnectionClient = class extends ChannelConversationClient {
|
|
|
53392
53634
|
async putClipConnectionAccess(orgId, connId, input) {
|
|
53393
53635
|
return this.request("PUT", ENDPOINTS.CLIP_CONNECTION_ACCESS(orgId, connId), input);
|
|
53394
53636
|
}
|
|
53637
|
+
/** Start OAuth using the reviewed platform app or provider registration ladder.
|
|
53638
|
+
* Allow discovery (30s), persistence (10s), and network overhead to finish. */
|
|
53639
|
+
async createClipMCPOAuthConnection(orgId, clipId, serverUrl, alias, oauthClient) {
|
|
53640
|
+
return this.request("POST", ENDPOINTS.ORG_CLIP_MCP_CONFIGS(orgId, clipId), {
|
|
53641
|
+
server_url: serverUrl,
|
|
53642
|
+
auth_type: "oauth",
|
|
53643
|
+
...alias ? { alias } : {},
|
|
53644
|
+
...oauthClient ? { oauth_client: oauthClient } : {}
|
|
53645
|
+
}, void 0, false, { timeoutMs: 5e4 });
|
|
53646
|
+
}
|
|
53647
|
+
/** Cancel exactly one pending attempt; requires its initiator or an org admin. */
|
|
53648
|
+
async cancelClipMCPOAuthAttempt(orgId, clipId, attemptId) {
|
|
53649
|
+
return this.request("DELETE", ENDPOINTS.ORG_CLIP_MCP_OAUTH_ATTEMPT(orgId, clipId, attemptId));
|
|
53650
|
+
}
|
|
53395
53651
|
};
|
|
53396
53652
|
|
|
53397
53653
|
// ../sdk/dist/browser-profile-client.js
|
|
53398
53654
|
var BrowserProfileClient = class extends ClipConnectionClient {
|
|
53655
|
+
/** Metadata-only compatibility discovery. Management scope errors propagate;
|
|
53656
|
+
* callers with a known Profile can execute without this discovery chain. */
|
|
53657
|
+
async listBrowserUseProfiles(orgId, profileId) {
|
|
53658
|
+
const me = await this.request("GET", ENDPOINTS.USERS_ME);
|
|
53659
|
+
const devices = await this.request("GET", ENDPOINTS.ORG_EDGE_DEVICES(orgId));
|
|
53660
|
+
const data = [];
|
|
53661
|
+
for (const device of devices.data) {
|
|
53662
|
+
const personal = device.managed_by === "member";
|
|
53663
|
+
if (personal && device.owner_user_id !== me.id)
|
|
53664
|
+
continue;
|
|
53665
|
+
const profiles = await this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, device.id));
|
|
53666
|
+
for (const profile of profiles) {
|
|
53667
|
+
if (profileId && profile.id !== profileId)
|
|
53668
|
+
continue;
|
|
53669
|
+
const access = personal ? null : await this.getBrowserProfileAccess(orgId, device.id, profile.name);
|
|
53670
|
+
if (!personal && !access?.org_public && !(access?.grants ?? []).some((g) => g.user_id === me.id && g.grants.length > 0))
|
|
53671
|
+
continue;
|
|
53672
|
+
data.push({
|
|
53673
|
+
profile_id: profile.id,
|
|
53674
|
+
name: profile.name,
|
|
53675
|
+
device_name: device.name,
|
|
53676
|
+
placement: device.placement ?? "byoc",
|
|
53677
|
+
lifecycle_state: profile.lifecycle_state,
|
|
53678
|
+
can_access: true,
|
|
53679
|
+
availability: device.placement === "hosted" ? device.hosted_state ?? "unknown" : device.status
|
|
53680
|
+
});
|
|
53681
|
+
}
|
|
53682
|
+
}
|
|
53683
|
+
return { data };
|
|
53684
|
+
}
|
|
53685
|
+
/** Submit once: even refresh-enabled clients must not replay browser actions. */
|
|
53686
|
+
async createBrowserUseOperation(orgId, request3) {
|
|
53687
|
+
return this.request("POST", ENDPOINTS.ORG_BROWSER_USE_OPERATIONS(orgId), request3, void 0, true);
|
|
53688
|
+
}
|
|
53689
|
+
/** Recover proof/data without creating a new browser operation. */
|
|
53690
|
+
async getBrowserUseOperation(orgId, operationId, opts) {
|
|
53691
|
+
return this.request("GET", ENDPOINTS.ORG_BROWSER_USE_OPERATION(orgId, operationId), void 0, void 0, false, opts);
|
|
53692
|
+
}
|
|
53399
53693
|
async getBrowserProfileAccess(orgId, edgeId, profileName) {
|
|
53400
53694
|
return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILE_ACCESS(orgId, edgeId, profileName));
|
|
53401
53695
|
}
|
|
@@ -53839,8 +54133,8 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
53839
54133
|
return this.request("POST", ENDPOINTS.AUTH_OAUTH_EXCHANGE, { code });
|
|
53840
54134
|
}
|
|
53841
54135
|
// ---- WebSocket ----
|
|
53842
|
-
async getWsTicket() {
|
|
53843
|
-
return this.request("POST", ENDPOINTS.WS_TICKET);
|
|
54136
|
+
async getWsTicket(req) {
|
|
54137
|
+
return this.request("POST", ENDPOINTS.WS_TICKET, req);
|
|
53844
54138
|
}
|
|
53845
54139
|
// ---- Users ----
|
|
53846
54140
|
async getMe() {
|
|
@@ -54827,8 +55121,8 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
54827
55121
|
* no_action sweep otherwise. Idempotent.
|
|
54828
55122
|
*
|
|
54829
55123
|
* @deprecated Legacy ok-only alias — use {@link completeDispatch} with the
|
|
54830
|
-
* `sources` form, which also carries `turn_outcome`.
|
|
54831
|
-
*
|
|
55124
|
+
* `sources` form, which also carries `turn_outcome`. Retirement conditions:
|
|
55125
|
+
* agent-dispatch-idempotency-design.md#compatibility.
|
|
54832
55126
|
*/
|
|
54833
55127
|
async completeDispatchSources(orgId, req) {
|
|
54834
55128
|
return this.request("POST", ENDPOINTS.DISPATCH_COMPLETE_SOURCES(orgId), req);
|
|
@@ -54983,38 +55277,6 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
54983
55277
|
async sendChannelMessage(orgId, input) {
|
|
54984
55278
|
return this.request("POST", ENDPOINTS.CHANNEL_SEND(orgId), input);
|
|
54985
55279
|
}
|
|
54986
|
-
slackReadQuery(base, query, extra) {
|
|
54987
|
-
const params = new URLSearchParams();
|
|
54988
|
-
if (query?.cursor)
|
|
54989
|
-
params.set("cursor", query.cursor);
|
|
54990
|
-
if (query?.limit)
|
|
54991
|
-
params.set("limit", String(query.limit));
|
|
54992
|
-
for (const [k, v] of Object.entries(extra ?? {}))
|
|
54993
|
-
params.set(k, v);
|
|
54994
|
-
const qs = params.toString();
|
|
54995
|
-
return qs ? `${base}?${qs}` : base;
|
|
54996
|
-
}
|
|
54997
|
-
/**
|
|
54998
|
-
* Tier-B read verbs (agent-only): workspace visibility as the bot sees
|
|
54999
|
-
* it. Same live gate as the send verb; authorization beyond it is the
|
|
55000
|
-
* bot's own Slack permissions.
|
|
55001
|
-
*/
|
|
55002
|
-
async listSlackChannels(orgId, query) {
|
|
55003
|
-
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_CHANNELS(orgId), query));
|
|
55004
|
-
}
|
|
55005
|
-
async listSlackUsers(orgId, query) {
|
|
55006
|
-
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_USERS(orgId), query));
|
|
55007
|
-
}
|
|
55008
|
-
async slackHistory(orgId, conversationId, query) {
|
|
55009
|
-
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_HISTORY(orgId), query, { conversation: conversationId }));
|
|
55010
|
-
}
|
|
55011
|
-
async slackMembers(orgId, conversationId, query) {
|
|
55012
|
-
return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_MEMBERS(orgId), query, { conversation: conversationId }));
|
|
55013
|
-
}
|
|
55014
|
-
/** Set/clear the Agents-pane "typing…" indicator (best-effort cosmetic). */
|
|
55015
|
-
async setSlackStatus(orgId, input) {
|
|
55016
|
-
await this.request("POST", ENDPOINTS.SLACK_STATUS(orgId), input);
|
|
55017
|
-
}
|
|
55018
55280
|
/**
|
|
55019
55281
|
* Authorized raw GET (binary responses) with the same auth, 401
|
|
55020
55282
|
* refresh-and-retry-once, and error-envelope handling as `request` — the
|
|
@@ -55071,6 +55333,9 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
55071
55333
|
async getTriggerSchema(orgId, connectionId) {
|
|
55072
55334
|
return this.request("GET", ENDPOINTS.TRIGGER_SCHEMA(orgId, connectionId));
|
|
55073
55335
|
}
|
|
55336
|
+
async getPlatformTriggerSchema(orgId, eventTypes) {
|
|
55337
|
+
return this.request("GET", ENDPOINTS.PLATFORM_TRIGGER_SCHEMA(orgId), void 0, eventTypes && eventTypes.length > 0 ? { event_types: eventTypes.join(",") } : void 0);
|
|
55338
|
+
}
|
|
55074
55339
|
async listTriggerIngressEvents(orgId, filters) {
|
|
55075
55340
|
return this.request("GET", ENDPOINTS.TRIGGER_INGRESS_EVENTS(orgId), void 0, filters);
|
|
55076
55341
|
}
|
|
@@ -55172,8 +55437,8 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
55172
55437
|
return url;
|
|
55173
55438
|
return `${this.baseUrlFor(url)}${url}`;
|
|
55174
55439
|
}
|
|
55175
|
-
async getWikiBlob(orgId, wikiId, params) {
|
|
55176
|
-
const blob = await this.request("GET", ENDPOINTS.WIKI_BLOB(orgId, wikiId), void 0, params);
|
|
55440
|
+
async getWikiBlob(orgId, wikiId, params, opts) {
|
|
55441
|
+
const blob = await this.request("GET", ENDPOINTS.WIKI_BLOB(orgId, wikiId), void 0, params, false, opts);
|
|
55177
55442
|
if (blob.signed_url)
|
|
55178
55443
|
blob.signed_url = this.absoluteMediaUrl(blob.signed_url);
|
|
55179
55444
|
return blob;
|
|
@@ -55546,6 +55811,21 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
55546
55811
|
async getBilling(orgId) {
|
|
55547
55812
|
return this.request("GET", ENDPOINTS.BILLING(orgId));
|
|
55548
55813
|
}
|
|
55814
|
+
async getUsageDaily(orgId, opts) {
|
|
55815
|
+
const params = new URLSearchParams();
|
|
55816
|
+
params.set("start_date", opts.start_date);
|
|
55817
|
+
params.set("end_date", opts.end_date);
|
|
55818
|
+
return this.request("GET", `${ENDPOINTS.BILLING_USAGE_DAILY(orgId)}?${params}`);
|
|
55819
|
+
}
|
|
55820
|
+
async getUsageHeatmap(orgId, opts) {
|
|
55821
|
+
const params = new URLSearchParams();
|
|
55822
|
+
params.set("start_time", opts.start_time);
|
|
55823
|
+
if (opts.limit != null)
|
|
55824
|
+
params.set("limit", String(opts.limit));
|
|
55825
|
+
if (opts.offset != null)
|
|
55826
|
+
params.set("offset", String(opts.offset));
|
|
55827
|
+
return this.request("GET", `${ENDPOINTS.BILLING_USAGE_HEATMAP(orgId)}?${params}`);
|
|
55828
|
+
}
|
|
55549
55829
|
async listBillingTransactions(orgId, opts) {
|
|
55550
55830
|
const params = new URLSearchParams();
|
|
55551
55831
|
if (opts?.cursor)
|
|
@@ -55715,12 +55995,14 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
55715
55995
|
}
|
|
55716
55996
|
// ---- Clip registry (v3, api-server org registry — `crg_` entries) ----
|
|
55717
55997
|
/**
|
|
55718
|
-
* List registry clips visible to the org: its own plus
|
|
55719
|
-
* cross-org entries
|
|
55720
|
-
* connections operate on.
|
|
55998
|
+
* List one page of registry clips visible to the org: its own plus
|
|
55999
|
+
* public+approved cross-org entries, used by installs and connections.
|
|
55721
56000
|
*/
|
|
55722
|
-
async listOrgRegistryClips(orgId) {
|
|
55723
|
-
const
|
|
56001
|
+
async listOrgRegistryClips(orgId, opts) {
|
|
56002
|
+
const params = new URLSearchParams({ limit: String(opts?.limit ?? 100) });
|
|
56003
|
+
if (opts?.offset !== void 0)
|
|
56004
|
+
params.set("offset", String(opts.offset));
|
|
56005
|
+
const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?${params}`);
|
|
55724
56006
|
return resp ?? [];
|
|
55725
56007
|
}
|
|
55726
56008
|
/**
|
|
@@ -55801,7 +56083,6 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
55801
56083
|
/**
|
|
55802
56084
|
* Read a clip's per-org exec access (by user id — humans and agents alike).
|
|
55803
56085
|
* Org-member readable, so a denied caller can learn why exec answered
|
|
55804
|
-
* `CONNECTION_NOT_ALLOWED` (retired: `CLIP_NOT_ALLOWED` / `CLIP_CONNECTION_NOT_ALLOWED`) (agents:
|
|
55805
56086
|
* `CLIP_AGENT_NOT_ALLOWED` / `CLIP_AGENT_CONNECTION_NOT_ALLOWED`). Writing
|
|
55806
56087
|
* it (`putClipAgentExecAccess`) is an org owner/admin's act.
|
|
55807
56088
|
*/
|
|
@@ -55882,69 +56163,6 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
55882
56163
|
async getEdgeProfileOperation(orgId, edgeId, operationId) {
|
|
55883
56164
|
return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILE_OPERATION(orgId, edgeId, operationId));
|
|
55884
56165
|
}
|
|
55885
|
-
/** Create and atomically materialize one Local BYOC Browser Alias. A replay
|
|
55886
|
-
* with the same idempotency key and body returns the original stable ccn_. */
|
|
55887
|
-
async createBrowserAlias(orgId, request3) {
|
|
55888
|
-
return this.request("POST", ENDPOINTS.ORG_BROWSER_ALIASES(orgId), request3);
|
|
55889
|
-
}
|
|
55890
|
-
async listBrowserAliases(orgId) {
|
|
55891
|
-
return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIASES(orgId));
|
|
55892
|
-
}
|
|
55893
|
-
async getBrowserAlias(orgId, aliasId) {
|
|
55894
|
-
return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIAS(orgId, aliasId));
|
|
55895
|
-
}
|
|
55896
|
-
async renameBrowserAlias(orgId, aliasId, request3) {
|
|
55897
|
-
return this.request("PATCH", ENDPOINTS.ORG_BROWSER_ALIAS(orgId, aliasId), request3);
|
|
55898
|
-
}
|
|
55899
|
-
async deleteBrowserAlias(orgId, aliasId, request3) {
|
|
55900
|
-
return this.request("DELETE", ENDPOINTS.ORG_BROWSER_ALIAS(orgId, aliasId), request3);
|
|
55901
|
-
}
|
|
55902
|
-
/** Start one durable readiness check. The key is carried as the standard
|
|
55903
|
-
* Idempotency-Key header; the request body is intentionally empty. */
|
|
55904
|
-
async createBrowserAliasReadinessCheck(orgId, aliasId, request3) {
|
|
55905
|
-
return this.request("POST", ENDPOINTS.ORG_BROWSER_ALIAS_READINESS_CHECKS(orgId, aliasId), void 0, void 0, false, { headers: { "Idempotency-Key": request3.idempotency_key } });
|
|
55906
|
-
}
|
|
55907
|
-
/** Sole durable recovery surface for one readiness request. */
|
|
55908
|
-
async getBrowserAliasReadinessCheck(orgId, aliasId, checkId) {
|
|
55909
|
-
return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIAS_READINESS_CHECK(orgId, aliasId, checkId));
|
|
55910
|
-
}
|
|
55911
|
-
/** Organization Owner view. Hashes, reviewed snapshots and deltas are
|
|
55912
|
-
* intentionally available only on this human-JWT management surface. */
|
|
55913
|
-
async listBrowserAliasGrants(orgId, keyId) {
|
|
55914
|
-
return this.request("GET", ENDPOINTS.ORG_API_KEY_BROWSER_ALIAS_GRANTS(orgId, keyId));
|
|
55915
|
-
}
|
|
55916
|
-
async getBrowserAliasGrant(orgId, keyId, aliasId) {
|
|
55917
|
-
return this.request("GET", ENDPOINTS.ORG_API_KEY_BROWSER_ALIAS_GRANT(orgId, keyId, aliasId));
|
|
55918
|
-
}
|
|
55919
|
-
async replaceBrowserAliasGrant(orgId, keyId, aliasId, request3) {
|
|
55920
|
-
return this.request("PUT", ENDPOINTS.ORG_API_KEY_BROWSER_ALIAS_GRANT(orgId, keyId, aliasId), request3);
|
|
55921
|
-
}
|
|
55922
|
-
/** Managed-key discovery. The response is already grant-filtered and never
|
|
55923
|
-
* carries contract hashes, review snapshots, Edge IDs or Profile IDs. */
|
|
55924
|
-
async listManagedBrowserAliases(orgId) {
|
|
55925
|
-
return this.request("GET", ENDPOINTS.ORG_MANAGED_ALIASES(orgId));
|
|
55926
|
-
}
|
|
55927
|
-
async getManagedBrowserAlias(orgId, aliasName) {
|
|
55928
|
-
return this.request("GET", ENDPOINTS.ORG_MANAGED_ALIAS(orgId, aliasName));
|
|
55929
|
-
}
|
|
55930
|
-
/** Accept and dispatch one @alias command. request_id is generated by the
|
|
55931
|
-
* caller before local validation and is also the sole durable recovery key. */
|
|
55932
|
-
async createBrowserAliasExecution(orgId, request3) {
|
|
55933
|
-
return this.request("POST", ENDPOINTS.ORG_BROWSER_ALIAS_EXECUTIONS(orgId), request3);
|
|
55934
|
-
}
|
|
55935
|
-
async getBrowserAliasExecution(orgId, requestId) {
|
|
55936
|
-
return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIAS_EXECUTION(orgId, requestId));
|
|
55937
|
-
}
|
|
55938
|
-
/** Accept one idempotent Browser Use operation for an explicit Profile.
|
|
55939
|
-
* JWT, personal, agent and managed keys use profile access. The Server resolves Profile→Edge. */
|
|
55940
|
-
async createBrowserUseOperation(orgId, request3) {
|
|
55941
|
-
return this.request("POST", ENDPOINTS.ORG_BROWSER_USE_OPERATIONS(orgId), request3);
|
|
55942
|
-
}
|
|
55943
|
-
/** Recover the durable receipt. Successful data is present only inside the
|
|
55944
|
-
* Server's short encrypted result TTL; terminal proof remains afterwards. */
|
|
55945
|
-
async getBrowserUseOperation(orgId, operationId) {
|
|
55946
|
-
return this.request("GET", ENDPOINTS.ORG_BROWSER_USE_OPERATION(orgId, operationId));
|
|
55947
|
-
}
|
|
55948
56166
|
/**
|
|
55949
56167
|
* Read a hosted Cloud Profile's egress-proxy status (manager-only: hosted
|
|
55950
56168
|
* human maintainer or org admin). Sanitized — the password never comes back.
|
|
@@ -56054,7 +56272,6 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
56054
56272
|
* - `EDGE_HOSTED_DISABLED_FOR_ORG` 403, `EDGE_REPAIR` 503 (operator-held),
|
|
56055
56273
|
* `EDGE_RUNTIME_UNAVAILABLE` 503 (deployment has no hosted runtime).
|
|
56056
56274
|
* - Access errors (before side effects): human `CONNECTION_NOT_ALLOWED`.
|
|
56057
|
-
* `CLIP_NOT_ALLOWED` / `CLIP_CONNECTION_NOT_ALLOWED` are retired.
|
|
56058
56275
|
* Agent principals receive the historical
|
|
56059
56276
|
* `CLIP_AGENT_NOT_ALLOWED` / `CLIP_AGENT_CONNECTION_NOT_ALLOWED` for one
|
|
56060
56277
|
* release. An org owner/admin can widen access in the clip's settings.
|
|
@@ -56138,17 +56355,6 @@ var ParallClient = class _ParallClient extends BrowserProfileClient {
|
|
|
56138
56355
|
timeoutMs: 4e4
|
|
56139
56356
|
});
|
|
56140
56357
|
}
|
|
56141
|
-
/** Start a new Official OAuth MCP connection with the platform-owned app.
|
|
56142
|
-
* Omitting oauth_client is load-bearing: the server resolves the exact
|
|
56143
|
-
* reviewed-version binding and never falls back to DCR/CIMD cross-org. */
|
|
56144
|
-
async createClipMCPOAuthConnection(orgId, clipId, serverUrl, alias, oauthClient) {
|
|
56145
|
-
return this.request("POST", ENDPOINTS.ORG_CLIP_MCP_CONFIGS(orgId, clipId), {
|
|
56146
|
-
server_url: serverUrl,
|
|
56147
|
-
auth_type: "oauth",
|
|
56148
|
-
...alias ? { alias } : {},
|
|
56149
|
-
...oauthClient ? { oauth_client: oauthClient } : {}
|
|
56150
|
-
});
|
|
56151
|
-
}
|
|
56152
56358
|
/** Re-authorize an existing MCP credential slot. */
|
|
56153
56359
|
async initiateClipMCPOAuthById(orgId, clipId, configId, serverUrl, expectedVersion, oauthClient) {
|
|
56154
56360
|
const req = {
|
|
@@ -56337,6 +56543,11 @@ function describeWsStateDetail(detail) {
|
|
|
56337
56543
|
function isRetryableNetworkError(err) {
|
|
56338
56544
|
return err instanceof Error && err.name === "ApiError" && "status" in err && err.status === 0;
|
|
56339
56545
|
}
|
|
56546
|
+
function authRejectionFrom(err) {
|
|
56547
|
+
if (!(err instanceof ApiError) || err.status !== 401)
|
|
56548
|
+
return null;
|
|
56549
|
+
return { status: err.status, code: err.code, message: err.message };
|
|
56550
|
+
}
|
|
56340
56551
|
function isBrowserRuntime() {
|
|
56341
56552
|
return typeof window !== "undefined";
|
|
56342
56553
|
}
|
|
@@ -56345,9 +56556,12 @@ var ParallWs = class {
|
|
|
56345
56556
|
options;
|
|
56346
56557
|
listeners = /* @__PURE__ */ new Map();
|
|
56347
56558
|
stateListeners = /* @__PURE__ */ new Set();
|
|
56559
|
+
authInvalidListeners = /* @__PURE__ */ new Set();
|
|
56348
56560
|
heartbeatTimer = null;
|
|
56349
56561
|
reconnectTimer = null;
|
|
56350
56562
|
reconnectAttempts = 0;
|
|
56563
|
+
/** Ticket attempts in the current auth-invalid episode (reset on success). */
|
|
56564
|
+
authAttempts = 0;
|
|
56351
56565
|
lastSeq = 0;
|
|
56352
56566
|
_state = "disconnected";
|
|
56353
56567
|
intentionalClose = false;
|
|
@@ -56360,6 +56574,7 @@ var ParallWs = class {
|
|
|
56360
56574
|
reconnect: true,
|
|
56361
56575
|
reconnectInterval: 1e3,
|
|
56362
56576
|
maxReconnectInterval: 3e4,
|
|
56577
|
+
maxAuthAttempts: 3,
|
|
56363
56578
|
...options
|
|
56364
56579
|
};
|
|
56365
56580
|
this.lastSeq = options.lastSeq ?? 0;
|
|
@@ -56369,12 +56584,25 @@ var ParallWs = class {
|
|
|
56369
56584
|
}
|
|
56370
56585
|
async connect() {
|
|
56371
56586
|
this.intentionalClose = false;
|
|
56587
|
+
if (this._state === "auth-invalid")
|
|
56588
|
+
this.authAttempts = 0;
|
|
56372
56589
|
this.setupBrowserListeners();
|
|
56373
56590
|
this.setState("connecting");
|
|
56374
56591
|
let ticket;
|
|
56375
56592
|
try {
|
|
56376
56593
|
ticket = await this.options.getTicket();
|
|
56377
56594
|
} catch (err) {
|
|
56595
|
+
const authRejection = authRejectionFrom(err);
|
|
56596
|
+
if (authRejection) {
|
|
56597
|
+
this.authAttempts += 1;
|
|
56598
|
+
if (this.authAttempts < this.options.maxAuthAttempts && this.options.reconnect) {
|
|
56599
|
+
console.warn(`WS ticket auth rejected (attempt ${this.authAttempts}/${this.options.maxAuthAttempts}):`, err);
|
|
56600
|
+
this.scheduleReconnect({ cause: "ticket_failed" });
|
|
56601
|
+
} else {
|
|
56602
|
+
this.enterAuthInvalid(authRejection);
|
|
56603
|
+
}
|
|
56604
|
+
return;
|
|
56605
|
+
}
|
|
56378
56606
|
if (isBrowserRuntime() && isRetryableNetworkError(err)) {
|
|
56379
56607
|
console.warn("Failed to get WS ticket:", err);
|
|
56380
56608
|
} else {
|
|
@@ -56421,6 +56649,7 @@ var ParallWs = class {
|
|
|
56421
56649
|
this.ws.onopen = () => {
|
|
56422
56650
|
clearTimeout(connectTimeout);
|
|
56423
56651
|
this.reconnectAttempts = 0;
|
|
56652
|
+
this.authAttempts = 0;
|
|
56424
56653
|
this.lastReceivedAt = Date.now();
|
|
56425
56654
|
this.setState("connected");
|
|
56426
56655
|
};
|
|
@@ -56508,6 +56737,20 @@ var ParallWs = class {
|
|
|
56508
56737
|
this.stateListeners.delete(handler);
|
|
56509
56738
|
};
|
|
56510
56739
|
}
|
|
56740
|
+
/**
|
|
56741
|
+
* Subscribe to the auth-invalid transition. Fired exactly once when the
|
|
56742
|
+
* client enters the terminal 'auth-invalid' state (a second episode after
|
|
56743
|
+
* a recovered reconnect fires again — one event per transition edge).
|
|
56744
|
+
* Consumers: runtime bridges exit for supervisor re-mint (see
|
|
56745
|
+
* @parall/agent-core gateway-base), the daemon logs recovery guidance for
|
|
56746
|
+
* its machine key, UIs surface a re-authenticate action.
|
|
56747
|
+
*/
|
|
56748
|
+
onAuthInvalid(handler) {
|
|
56749
|
+
this.authInvalidListeners.add(handler);
|
|
56750
|
+
return () => {
|
|
56751
|
+
this.authInvalidListeners.delete(handler);
|
|
56752
|
+
};
|
|
56753
|
+
}
|
|
56511
56754
|
// ---- Internal ----
|
|
56512
56755
|
send(frame) {
|
|
56513
56756
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
@@ -56553,6 +56796,8 @@ var ParallWs = class {
|
|
|
56553
56796
|
}
|
|
56554
56797
|
}
|
|
56555
56798
|
scheduleReconnect(detail) {
|
|
56799
|
+
if (this._state === "auth-invalid")
|
|
56800
|
+
return;
|
|
56556
56801
|
this.setState("reconnecting", { ...detail, attempt: this.reconnectAttempts + 1 });
|
|
56557
56802
|
this.clearReconnect();
|
|
56558
56803
|
const base = Math.min(this.options.reconnectInterval * Math.pow(2, this.reconnectAttempts), this.options.maxReconnectInterval);
|
|
@@ -56568,6 +56813,20 @@ var ParallWs = class {
|
|
|
56568
56813
|
this.reconnectTimer = null;
|
|
56569
56814
|
}
|
|
56570
56815
|
}
|
|
56816
|
+
/**
|
|
56817
|
+
* Enter the terminal auth-invalid state and notify consumers once. Loud on
|
|
56818
|
+
* purpose: before this branch existed, a revoked key produced an infinite
|
|
56819
|
+
* silent connecting→reconnecting loop with no indication that the
|
|
56820
|
+
* credential — not the network — was the problem.
|
|
56821
|
+
*/
|
|
56822
|
+
enterAuthInvalid(event) {
|
|
56823
|
+
this.clearReconnect();
|
|
56824
|
+
this.setState("auth-invalid");
|
|
56825
|
+
console.error(`WS auth-invalid: server rejected this credential (status ${event.status}${event.code ? `, code ${event.code}` : ""}) \u2014 ${event.message}. The key is invalid, expired, or revoked; retrying it cannot succeed, so reconnects are stopped. Recover by refreshing credentials (re-login, or issue a new API key), then connect again.`);
|
|
56826
|
+
for (const listener of this.authInvalidListeners) {
|
|
56827
|
+
listener(event);
|
|
56828
|
+
}
|
|
56829
|
+
}
|
|
56571
56830
|
/** Force-close a dead/stale connection and trigger reconnect. */
|
|
56572
56831
|
forceReconnect(cause) {
|
|
56573
56832
|
this.stopHeartbeat();
|
|
@@ -56672,6 +56931,16 @@ var ParallWs = class {
|
|
|
56672
56931
|
}
|
|
56673
56932
|
};
|
|
56674
56933
|
|
|
56934
|
+
// ../sdk/dist/browser-use-contract.generated.js
|
|
56935
|
+
var browserUseContract = { "actions": { "read": { "grant": "browser.read", "target": "optional_tab", "params": { "required": [], "properties": { "url": { "type": "string", "min_length": 1, "max_length": 8192, "schemes": ["http", "https", "about:blank"] } }, "rules": ["exactly one of params.url or target is required", "params.url creates a hidden Profile-bound tab and closes it before terminal success or failure"], "additional_properties": false }, "success": { "base": null, "fields": { "profile_id": "ebp_identifier", "url": "string", "title": "string", "article": "nullable_article" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "tabs": { "grant": "browser.read", "target": "none", "params": { "required": [], "properties": {}, "additional_properties": false }, "success": { "base": null, "fields": { "tabs": "tab_summary_array" } }, "errors": ["TAB_GONE"] }, "wait": { "grant": "browser.read", "target": "tab", "params": { "required": [], "properties": { "selector": { "type": "string", "min_length": 1, "max_length": 4096 }, "state": { "enum": ["attached", "detached", "visible", "hidden", "load"], "default": "attached" }, "timeout_ms": { "type": "integer", "minimum": 1, "maximum": 3e4, "default": 1e4 } }, "rules": ["selector is required unless state=load", "state=load forbids selector"], "additional_properties": false }, "success": { "base": "tab_state", "fields": { "matched": { "const": true } } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "snapshot": { "grant": "browser.read", "target": "tab", "params": { "required": [], "properties": { "interactive": { "type": "boolean", "default": false }, "compact": { "type": "boolean", "default": false }, "depth": { "type": "integer", "minimum": 0, "maximum": 64 } }, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "snapshot": "string", "snapshot_id": "identifier" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "get": { "grant": "browser.read", "target": "tab_or_ref", "params": { "required": ["prop"], "properties": { "selector": { "type": "string", "min_length": 1, "max_length": 4096 }, "prop": { "enum": ["text", "html", "value", "attr", "title", "url"] }, "name": { "type": "string", "min_length": 1, "max_length": 256 } }, "rules": ["title/url forbid locator and name", "text/html/value require exactly one locator", "attr requires exactly one locator and name"], "additional_properties": false }, "success": { "base": "tab_state", "fields": { "value": "nullable_string" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "STALE_REF", "PAGE_LOAD_FAILED"] }, "screenshot": { "grant": "browser.read", "target": "tab", "params": { "required": [], "properties": {}, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "format": { "const": "png" }, "base64": "canonical_base64" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "open": { "grant": "browser.interact", "target": "none", "params": { "required": ["url"], "properties": { "url": { "type": "string", "min_length": 1, "max_length": 8192, "schemes": ["http", "https", "about:blank"] }, "hidden": { "type": "boolean", "default": false }, "viewport": { "type": "viewport" } }, "additional_properties": false }, "success": { "base": "tab_state", "fields": {} }, "errors": ["PAGE_LOAD_FAILED"] }, "navigate": { "grant": "browser.interact", "target": "tab", "params": { "required": ["url"], "properties": { "url": { "type": "string", "min_length": 1, "max_length": 8192, "schemes": ["http", "https", "about:blank"] } }, "additional_properties": false }, "success": { "base": "tab_state", "fields": {} }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "viewport": { "grant": "browser.interact", "target": "tab", "params": { "required": ["width", "height"], "properties": { "width": { "type": "integer", "minimum": 320, "maximum": 3840 }, "height": { "type": "integer", "minimum": 240, "maximum": 2160 } }, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "viewport": "viewport" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE"] }, "click": { "grant": "browser.interact", "target": "tab_or_ref", "params": { "required": [], "properties": { "selector": "selector" }, "rules": ["exactly one of params.selector or target.ref"], "additional_properties": false }, "success": { "base": "tab_state", "fields": { "clicked": { "const": true } } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "STALE_REF", "PAGE_LOAD_FAILED"] }, "fill": { "grant": "browser.interact", "target": "tab_or_ref", "params": { "required": ["text"], "properties": { "selector": "selector", "text": { "type": "string", "allow_empty": true } }, "rules": ["exactly one of params.selector or target.ref"], "additional_properties": false }, "success": { "base": "tab_state", "fields": { "filled": { "const": true }, "characters": "non_negative_integer" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "STALE_REF", "PAGE_LOAD_FAILED"] }, "type": { "grant": "browser.interact", "target": "tab_or_ref", "params": { "required": ["text"], "properties": { "selector": "selector", "text": { "type": "string", "min_length": 1 } }, "rules": ["exactly one of params.selector or target.ref"], "additional_properties": false }, "success": { "base": "tab_state", "fields": { "typed": { "const": true }, "characters": "non_negative_integer" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "STALE_REF", "PAGE_LOAD_FAILED"] }, "press": { "grant": "browser.interact", "target": "tab", "params": { "required": ["key"], "properties": { "key": "single_unicode_character_or_named_key" }, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "pressed": { "const": true } } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "scroll": { "grant": "browser.interact", "target": "tab", "params": { "required": [], "properties": { "direction": { "enum": ["up", "down", "left", "right"], "default": "down" }, "pixels": { "type": "integer", "minimum": 1, "maximum": 1e5, "default": 500 } }, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "scrolled": { "const": true } } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "close": { "grant": "browser.interact", "target": "tab", "params": { "required": [], "properties": {}, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "closed": { "const": true } } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE"] }, "recover": { "grant": "browser.interact", "target": "tab", "params": { "required": [], "properties": {}, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "recovered_from_tab_id": "identifier" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] }, "eval": { "grant": "browser.advanced", "target": "tab", "params": { "required": ["expression"], "properties": { "expression": { "type": "string", "min_length": 1 }, "timeout_ms": { "type": "integer", "minimum": 1, "maximum": 15e3, "default": 15e3 } }, "additional_properties": false }, "success": { "base": "tab_state", "fields": { "value": "json_value_max_256_kib" } }, "errors": ["TAB_NOT_FOUND", "TAB_GONE", "PAGE_LOAD_FAILED"] } }, "successShapes": { "tab_state": { "required": ["tab_id", "profile_id", "browser_generation", "document_generation", "url", "title"], "fields": { "tab_id": "identifier", "profile_id": "ebp_identifier", "browser_generation": "positive_integer", "document_generation": "positive_integer", "url": "string", "title": "string" }, "additional_properties": false }, "tab_summary": { "base": "tab_state", "required_additions": ["loading"], "fields": { "loading": "boolean" }, "additional_properties": false }, "article": { "required": ["title", "byline", "excerpt", "text", "published_time", "site_name", "length"], "fields": { "title": "nullable_string", "byline": "nullable_string", "excerpt": "nullable_string", "text": "string", "published_time": "nullable_string", "site_name": "nullable_string", "length": "non_negative_integer" }, "additional_properties": false } } };
|
|
56936
|
+
|
|
56937
|
+
// ../sdk/dist/browser-use-validation.js
|
|
56938
|
+
var BROWSER_USE_ACTION_SCHEMAS = browserUseContract.actions;
|
|
56939
|
+
var BROWSER_USE_ACTIONS = Object.freeze(Object.keys(BROWSER_USE_ACTION_SCHEMAS));
|
|
56940
|
+
|
|
56941
|
+
// ../sdk/dist/browser-use-receipt.js
|
|
56942
|
+
var KEYS = "contract_version operation_id request_id profile_id profile_version profile_config_revision action required_grant phase dispatched receipt_id receipt_digest occurred_at tab_id browser_generation duration_ms result_digest result_available result_expires_at data error deadline accepted_at started_at terminal_at updated_at".split(" ");
|
|
56943
|
+
|
|
56675
56944
|
// ../agent-core/dist/fork-state.js
|
|
56676
56945
|
var FORK_CONTINUATION_RETRY_CAP = 256;
|
|
56677
56946
|
function forkContinuationRetryKey(event) {
|
|
@@ -56722,46 +56991,60 @@ function createActiveForkState(fork, targetId, continuationPrefix) {
|
|
|
56722
56991
|
};
|
|
56723
56992
|
}
|
|
56724
56993
|
|
|
56725
|
-
// ../agent-core/dist/
|
|
56726
|
-
|
|
56727
|
-
|
|
56994
|
+
// ../agent-core/dist/gateway-steer.js
|
|
56995
|
+
var pendingSteers = /* @__PURE__ */ new WeakMap();
|
|
56996
|
+
function hasMainSteers(state) {
|
|
56997
|
+
return (pendingSteers.get(state)?.size ?? 0) > 0;
|
|
56728
56998
|
}
|
|
56729
|
-
function
|
|
56730
|
-
|
|
56731
|
-
for (const v of knownValues) {
|
|
56732
|
-
if (typeof v === "string" && v.length >= 6)
|
|
56733
|
-
out = out.split(v).join("***");
|
|
56734
|
-
}
|
|
56735
|
-
return out;
|
|
56999
|
+
async function waitForMainSteers(state) {
|
|
57000
|
+
await Promise.allSettled(pendingSteers.get(state) ?? []);
|
|
56736
57001
|
}
|
|
56737
|
-
function
|
|
56738
|
-
|
|
56739
|
-
if (
|
|
56740
|
-
|
|
56741
|
-
|
|
56742
|
-
|
|
56743
|
-
|
|
56744
|
-
|
|
56745
|
-
|
|
57002
|
+
async function steerLaneMessage(host, event) {
|
|
57003
|
+
let pending = pendingSteers.get(host.dispatchState);
|
|
57004
|
+
if (!pending) {
|
|
57005
|
+
pending = /* @__PURE__ */ new Set();
|
|
57006
|
+
pendingSteers.set(host.dispatchState, pending);
|
|
57007
|
+
}
|
|
57008
|
+
const work = Promise.resolve().then(() => steerLaneMessageInner(host, event));
|
|
57009
|
+
pending.add(work);
|
|
57010
|
+
try {
|
|
57011
|
+
await work;
|
|
57012
|
+
} finally {
|
|
57013
|
+
pending.delete(work);
|
|
57014
|
+
if (pending.size === 0)
|
|
57015
|
+
pendingSteers.delete(host.dispatchState);
|
|
57016
|
+
host.notifyDrainWaiters?.();
|
|
56746
57017
|
}
|
|
56747
|
-
return redacted;
|
|
56748
57018
|
}
|
|
56749
|
-
function
|
|
56750
|
-
const
|
|
56751
|
-
|
|
56752
|
-
|
|
56753
|
-
|
|
56754
|
-
|
|
57019
|
+
function hasUninjectedSameLaneEventAhead(host, event) {
|
|
57020
|
+
const eventIndex = host.dispatchState.mainBuffer.lastIndexOf(event);
|
|
57021
|
+
if (eventIndex <= 0)
|
|
57022
|
+
return false;
|
|
57023
|
+
const groupKey = host.dispatchGroupKey(event);
|
|
57024
|
+
return host.dispatchState.mainBuffer.slice(0, eventIndex).some((buffered) => host.dispatchGroupKey(buffered) === groupKey && !host.injectedMainBufferEvents.has(buffered));
|
|
56755
57025
|
}
|
|
56756
|
-
function
|
|
56757
|
-
|
|
56758
|
-
|
|
56759
|
-
|
|
56760
|
-
|
|
56761
|
-
|
|
56762
|
-
|
|
56763
|
-
|
|
56764
|
-
|
|
57026
|
+
async function steerLaneMessageInner(host, event) {
|
|
57027
|
+
const { laneLedger: ledger, opts } = host;
|
|
57028
|
+
const adapter = opts.dispatchAdapter;
|
|
57029
|
+
if (!ledger || !adapter.enqueueDuringDispatch)
|
|
57030
|
+
return;
|
|
57031
|
+
if (hasUninjectedSameLaneEventAhead(host, event))
|
|
57032
|
+
return;
|
|
57033
|
+
const folded = await ledger.steerLive(event);
|
|
57034
|
+
if (!folded)
|
|
57035
|
+
return;
|
|
57036
|
+
if (!folded.frame)
|
|
57037
|
+
return;
|
|
57038
|
+
event.frame = folded.frame;
|
|
57039
|
+
const injected = await adapter.enqueueDuringDispatch(opts.runtimeKey, eventBody(event), folded.inputLifecycle);
|
|
57040
|
+
if (injected) {
|
|
57041
|
+
host.injectedMainBufferEvents.add(event);
|
|
57042
|
+
ledger.markSeen(event, folded.covered);
|
|
57043
|
+
opts.log?.info(`steer frame handed to adapter for ${event.messageId} (will drain for bookkeeping)`);
|
|
57044
|
+
} else if (folded.frame) {
|
|
57045
|
+
ledger.deferFrame(event, folded.frame, folded.covered);
|
|
57046
|
+
opts.log?.info(`steer folded but not injected for ${event.messageId} \u2014 frame deferred to the drain`);
|
|
57047
|
+
}
|
|
56765
57048
|
}
|
|
56766
57049
|
|
|
56767
57050
|
// ../agent-core/dist/lane-ledger.js
|
|
@@ -56794,21 +57077,218 @@ function laneTargetUri(event) {
|
|
|
56794
57077
|
if (event.type === "message") {
|
|
56795
57078
|
return event.targetId.startsWith(CHAT_LANE_PREFIX) ? `${PRLL_SCHEME}${event.targetId}` : void 0;
|
|
56796
57079
|
}
|
|
56797
|
-
if (event.type === "channel_message") {
|
|
56798
|
-
return event.targetUri?.startsWith(CHANNEL_LANE_PREFIX) ? event.targetUri : void 0;
|
|
57080
|
+
if (event.type === "channel_message") {
|
|
57081
|
+
return event.targetUri?.startsWith(CHANNEL_LANE_PREFIX) ? event.targetUri : void 0;
|
|
57082
|
+
}
|
|
57083
|
+
return void 0;
|
|
57084
|
+
}
|
|
57085
|
+
function isTypedEvent(event) {
|
|
57086
|
+
return event.type !== "message" && laneTargetUri(event) === void 0;
|
|
57087
|
+
}
|
|
57088
|
+
|
|
57089
|
+
// ../agent-core/dist/lane-outcome.js
|
|
57090
|
+
function errorWireClass(cls) {
|
|
57091
|
+
if (!cls || cls === "ok" || cls === "usage_limit")
|
|
57092
|
+
return void 0;
|
|
57093
|
+
return cls;
|
|
57094
|
+
}
|
|
57095
|
+
|
|
57096
|
+
// ../agent-core/dist/runtime-instance.js
|
|
57097
|
+
function isTurnToken(token) {
|
|
57098
|
+
return token.startsWith("turn_");
|
|
57099
|
+
}
|
|
57100
|
+
|
|
57101
|
+
// ../agent-core/dist/lane-input-receipts.js
|
|
57102
|
+
var LaneInputReceipts = class {
|
|
57103
|
+
opts;
|
|
57104
|
+
confirmations;
|
|
57105
|
+
constructor(opts, confirmations) {
|
|
57106
|
+
this.opts = opts;
|
|
57107
|
+
this.confirmations = confirmations;
|
|
57108
|
+
}
|
|
57109
|
+
lifecycle(lane, messageIds) {
|
|
57110
|
+
const explicit = lane.coverageMode === "explicit";
|
|
57111
|
+
const unique = [...new Set(messageIds)];
|
|
57112
|
+
const dispatchEventIds = unique.map((messageId) => lane.folded.get(messageId)).filter((id) => Boolean(id));
|
|
57113
|
+
if (explicit && dispatchEventIds.length !== unique.length) {
|
|
57114
|
+
throw new Error(`explicit lane ${lane.lane} is missing a folded WorkItem mapping`);
|
|
57115
|
+
}
|
|
57116
|
+
if (!explicit && dispatchEventIds.length === 0)
|
|
57117
|
+
return void 0;
|
|
57118
|
+
return {
|
|
57119
|
+
deliveryKey: dispatchEventIds.join(","),
|
|
57120
|
+
dispatchEventIds,
|
|
57121
|
+
update: explicit ? (state, failure) => this.updateInputState(lane, dispatchEventIds, state, failure) : async () => void 0
|
|
57122
|
+
};
|
|
57123
|
+
}
|
|
57124
|
+
async updateInputState(lane, dispatchEventIds, state, failure) {
|
|
57125
|
+
lane.observedInputs ??= /* @__PURE__ */ new Map();
|
|
57126
|
+
for (const id of dispatchEventIds)
|
|
57127
|
+
lane.observedInputs.set(id, state);
|
|
57128
|
+
let confirmed;
|
|
57129
|
+
const ids = [...dispatchEventIds];
|
|
57130
|
+
const failed = new Set(state === "failed" ? ids : []);
|
|
57131
|
+
const sourceIds = [...lane.folded].filter(([, id]) => failed.has(id)).map(([id]) => id);
|
|
57132
|
+
const request3 = {
|
|
57133
|
+
lane: lane.lane,
|
|
57134
|
+
target_uri: lane.targetUri,
|
|
57135
|
+
thread_root_id: lane.threadRootId,
|
|
57136
|
+
dispatch_event_ids: ids,
|
|
57137
|
+
state,
|
|
57138
|
+
session_id: lane.sessionAmbiguous ? void 0 : lane.sessionId,
|
|
57139
|
+
...state === "failed" && failure ? {
|
|
57140
|
+
outcome_class: errorWireClass(failure.outcomeClass),
|
|
57141
|
+
detail: failure.detail ? redactSecrets(failure.detail, this.opts.knownSecrets).slice(0, 500) : void 0
|
|
57142
|
+
} : {}
|
|
57143
|
+
};
|
|
57144
|
+
await this.confirmations.submit(lane.lane, {
|
|
57145
|
+
label: `input ${state}`,
|
|
57146
|
+
send: async () => {
|
|
57147
|
+
const restore = sourceIds.length ? this.opts.releaseLocalClaims?.(sourceIds) : void 0;
|
|
57148
|
+
let result;
|
|
57149
|
+
try {
|
|
57150
|
+
result = await this.opts.client.updateDispatchInputState(this.opts.orgId, request3);
|
|
57151
|
+
} catch (err) {
|
|
57152
|
+
restore?.();
|
|
57153
|
+
throw err;
|
|
57154
|
+
}
|
|
57155
|
+
if (result.recognized !== ids.length && !isTurnToken(lane.lane)) {
|
|
57156
|
+
restore?.();
|
|
57157
|
+
throw new ApiError(409, "input acknowledgement scope changed", "INPUT_SCOPE_CHANGED");
|
|
57158
|
+
}
|
|
57159
|
+
if (state === "failed") {
|
|
57160
|
+
for (const sourceId of sourceIds) {
|
|
57161
|
+
lane.folded.delete(sourceId);
|
|
57162
|
+
lane.seen.delete(sourceId);
|
|
57163
|
+
}
|
|
57164
|
+
}
|
|
57165
|
+
confirmed = { retry: state === "failed" && result.released > 0 };
|
|
57166
|
+
}
|
|
57167
|
+
});
|
|
57168
|
+
return confirmed ?? { retry: false, pending: true };
|
|
57169
|
+
}
|
|
57170
|
+
async syncAttribution(lane) {
|
|
57171
|
+
if (lane.settlementMode !== "receipt" || lane.settling || lane.sessionAmbiguous || !lane.sessionId || !lane.observedInputs?.size)
|
|
57172
|
+
return;
|
|
57173
|
+
const sessionId = lane.sessionId;
|
|
57174
|
+
const groups = /* @__PURE__ */ new Map();
|
|
57175
|
+
for (const [id, state] of lane.observedInputs) {
|
|
57176
|
+
const ids = groups.get(state) ?? [];
|
|
57177
|
+
ids.push(id);
|
|
57178
|
+
groups.set(state, ids);
|
|
57179
|
+
}
|
|
57180
|
+
for (const [state, ids] of groups) {
|
|
57181
|
+
await this.confirmations.submit(lane.lane, {
|
|
57182
|
+
label: "input session",
|
|
57183
|
+
send: async () => {
|
|
57184
|
+
await this.opts.client.updateDispatchInputState(this.opts.orgId, {
|
|
57185
|
+
lane: lane.lane,
|
|
57186
|
+
target_uri: lane.targetUri,
|
|
57187
|
+
thread_root_id: lane.threadRootId,
|
|
57188
|
+
dispatch_event_ids: ids,
|
|
57189
|
+
state,
|
|
57190
|
+
session_id: sessionId
|
|
57191
|
+
});
|
|
57192
|
+
}
|
|
57193
|
+
});
|
|
57194
|
+
}
|
|
57195
|
+
}
|
|
57196
|
+
};
|
|
57197
|
+
|
|
57198
|
+
// ../agent-core/dist/lane-confirmations.js
|
|
57199
|
+
var LaneConfirmations = class {
|
|
57200
|
+
opts;
|
|
57201
|
+
pending = /* @__PURE__ */ new Map();
|
|
57202
|
+
disposed = false;
|
|
57203
|
+
constructor(opts) {
|
|
57204
|
+
this.opts = opts;
|
|
57205
|
+
}
|
|
57206
|
+
/** Try once inline; a retained write returns without blocking native execution. */
|
|
57207
|
+
async submit(token, write) {
|
|
57208
|
+
if (this.disposed)
|
|
57209
|
+
return;
|
|
57210
|
+
let pending = this.pending.get(token);
|
|
57211
|
+
if (pending) {
|
|
57212
|
+
if (pending.blocked)
|
|
57213
|
+
return;
|
|
57214
|
+
pending.writes.push(write);
|
|
57215
|
+
return;
|
|
57216
|
+
}
|
|
57217
|
+
pending = { writes: [write], failures: 0, blocked: false };
|
|
57218
|
+
this.pending.set(token, pending);
|
|
57219
|
+
await this.run(token, pending);
|
|
57220
|
+
}
|
|
57221
|
+
async run(token, pending) {
|
|
57222
|
+
if (pending.running || pending.blocked || this.pending.get(token) !== pending)
|
|
57223
|
+
return;
|
|
57224
|
+
const recovered = pending.failures > 0;
|
|
57225
|
+
pending.running = Promise.resolve().then(async () => {
|
|
57226
|
+
while (pending.writes.length && this.pending.get(token) === pending) {
|
|
57227
|
+
const write = pending.writes[0];
|
|
57228
|
+
try {
|
|
57229
|
+
await write.send();
|
|
57230
|
+
pending.writes.shift();
|
|
57231
|
+
} catch (err) {
|
|
57232
|
+
if (this.pending.get(token) !== pending)
|
|
57233
|
+
return;
|
|
57234
|
+
if (err instanceof ApiError && err.status === 409 && err.code === "STALE_LANE") {
|
|
57235
|
+
this.pending.delete(token);
|
|
57236
|
+
this.opts.onStale(token);
|
|
57237
|
+
this.opts.onRecovered?.();
|
|
57238
|
+
return;
|
|
57239
|
+
}
|
|
57240
|
+
const transient = !(err instanceof ApiError) || err.status === 0 || err.status >= 500 || err.status === 408 || err.status === 429;
|
|
57241
|
+
if (!transient) {
|
|
57242
|
+
pending.blocked = true;
|
|
57243
|
+
this.opts.log?.error(`lane ${write.label} rejected for ${token}; confirmation retained: ${String(err)}`);
|
|
57244
|
+
return;
|
|
57245
|
+
}
|
|
57246
|
+
pending.failures += 1;
|
|
57247
|
+
this.opts.log?.warn(`lane ${write.label} unconfirmed for ${token}; retry ${pending.failures}: ${String(err)}`);
|
|
57248
|
+
const delays = this.opts.delaysMs?.length ? this.opts.delaysMs : [2e3, 1e4, 3e4, 6e4, 12e4];
|
|
57249
|
+
const delay = delays[Math.min(pending.failures - 1, delays.length - 1)];
|
|
57250
|
+
pending.timer = setTimeout(() => {
|
|
57251
|
+
pending.timer = void 0;
|
|
57252
|
+
void this.run(token, pending);
|
|
57253
|
+
}, delay);
|
|
57254
|
+
pending.timer.unref?.();
|
|
57255
|
+
return;
|
|
57256
|
+
}
|
|
57257
|
+
}
|
|
57258
|
+
if (this.pending.get(token) === pending)
|
|
57259
|
+
this.pending.delete(token);
|
|
57260
|
+
if (recovered)
|
|
57261
|
+
this.opts.onRecovered?.();
|
|
57262
|
+
});
|
|
57263
|
+
try {
|
|
57264
|
+
await pending.running;
|
|
57265
|
+
} finally {
|
|
57266
|
+
pending.running = void 0;
|
|
57267
|
+
}
|
|
57268
|
+
}
|
|
57269
|
+
/** Reconnect/shutdown may accelerate retries; permanent rejections stay visible. */
|
|
57270
|
+
async retryNow() {
|
|
57271
|
+
await Promise.all([...this.pending].map(async ([token, pending]) => {
|
|
57272
|
+
if (pending.timer)
|
|
57273
|
+
clearTimeout(pending.timer);
|
|
57274
|
+
pending.timer = void 0;
|
|
57275
|
+
await this.run(token, pending);
|
|
57276
|
+
}));
|
|
56799
57277
|
}
|
|
56800
|
-
|
|
56801
|
-
|
|
56802
|
-
|
|
56803
|
-
|
|
56804
|
-
|
|
57278
|
+
forget(token) {
|
|
57279
|
+
const pending = this.pending.get(token);
|
|
57280
|
+
if (pending?.timer)
|
|
57281
|
+
clearTimeout(pending.timer);
|
|
57282
|
+
this.pending.delete(token);
|
|
57283
|
+
}
|
|
57284
|
+
dispose() {
|
|
57285
|
+
this.disposed = true;
|
|
57286
|
+
for (const token of this.pending.keys())
|
|
57287
|
+
this.forget(token);
|
|
57288
|
+
}
|
|
57289
|
+
};
|
|
56805
57290
|
|
|
56806
57291
|
// ../agent-core/dist/lane-ledger.js
|
|
56807
|
-
function errorWireClass(cls) {
|
|
56808
|
-
if (!cls || cls === "ok" || cls === "usage_limit")
|
|
56809
|
-
return void 0;
|
|
56810
|
-
return cls;
|
|
56811
|
-
}
|
|
56812
57292
|
var LedgerUnsupportedError = class extends Error {
|
|
56813
57293
|
};
|
|
56814
57294
|
function bindLaneSession(lane, agentSessionId) {
|
|
@@ -56834,8 +57314,24 @@ function isEndpointMissing2(err) {
|
|
|
56834
57314
|
var LaneLedger = class {
|
|
56835
57315
|
opts;
|
|
56836
57316
|
lanes = /* @__PURE__ */ new Map();
|
|
57317
|
+
confirmations;
|
|
57318
|
+
inputs;
|
|
57319
|
+
claimResponses = /* @__PURE__ */ new Map();
|
|
57320
|
+
claims = /* @__PURE__ */ new Map();
|
|
56837
57321
|
constructor(opts) {
|
|
56838
57322
|
this.opts = opts;
|
|
57323
|
+
this.confirmations = new LaneConfirmations({
|
|
57324
|
+
delaysMs: opts.terminalRetryDelaysMs,
|
|
57325
|
+
log: opts.log,
|
|
57326
|
+
onRecovered: opts.onRecovered,
|
|
57327
|
+
onStale: (token) => {
|
|
57328
|
+
for (const lane of this.lanes.values()) {
|
|
57329
|
+
if (lane.lane === token)
|
|
57330
|
+
this.forgetLane(lane);
|
|
57331
|
+
}
|
|
57332
|
+
}
|
|
57333
|
+
});
|
|
57334
|
+
this.inputs = new LaneInputReceipts(opts, this.confirmations);
|
|
56839
57335
|
}
|
|
56840
57336
|
get contextDir() {
|
|
56841
57337
|
return this.opts.contextDir;
|
|
@@ -56934,7 +57430,16 @@ ${frame}` : frame;
|
|
|
56934
57430
|
* incumbent completes.
|
|
56935
57431
|
*/
|
|
56936
57432
|
async ensureLane(events) {
|
|
56937
|
-
|
|
57433
|
+
const key = this.laneKeyFor(events[events.length - 1]);
|
|
57434
|
+
const prior = this.claims.get(key);
|
|
57435
|
+
const claim = (prior ? prior.catch(() => null) : Promise.resolve()).then(() => this.ensureLaneAttempt(events, false));
|
|
57436
|
+
this.claims.set(key, claim);
|
|
57437
|
+
try {
|
|
57438
|
+
return await claim;
|
|
57439
|
+
} finally {
|
|
57440
|
+
if (this.claims.get(key) === claim)
|
|
57441
|
+
this.claims.delete(key);
|
|
57442
|
+
}
|
|
56938
57443
|
}
|
|
56939
57444
|
/**
|
|
56940
57445
|
* One ensureLane pass. `reclaimed` marks the arbitration retry: STALE_LANE
|
|
@@ -56952,22 +57457,22 @@ ${frame}` : frame;
|
|
|
56952
57457
|
const trigger = events[events.length - 1];
|
|
56953
57458
|
const laneKey = this.laneKeyFor(trigger);
|
|
56954
57459
|
let lane = this.lanes.get(laneKey);
|
|
57460
|
+
if (lane?.settling)
|
|
57461
|
+
return null;
|
|
56955
57462
|
const reused = lane != null;
|
|
56956
57463
|
if (!lane) {
|
|
56957
57464
|
const targetUri = laneTargetUri(trigger) ?? `prll://${trigger.targetId}`;
|
|
56958
|
-
|
|
56959
|
-
|
|
56960
|
-
|
|
56961
|
-
|
|
56962
|
-
|
|
56963
|
-
|
|
56964
|
-
|
|
56965
|
-
|
|
56966
|
-
}
|
|
56967
|
-
|
|
56968
|
-
|
|
56969
|
-
throw err;
|
|
56970
|
-
}
|
|
57465
|
+
const res = await this.claimRecoverably(laneKey, {
|
|
57466
|
+
target_uri: targetUri,
|
|
57467
|
+
thread_root_id: trigger.threadRootId,
|
|
57468
|
+
limit: 100,
|
|
57469
|
+
coverage_mode: this.opts.coverageMode ?? "implicit",
|
|
57470
|
+
settlement_mode: this.opts.instanceId ? this.opts.settlementMode : void 0,
|
|
57471
|
+
resume_received: this.opts.instanceId ? true : void 0,
|
|
57472
|
+
instance_id: this.opts.instanceId
|
|
57473
|
+
});
|
|
57474
|
+
if (!res)
|
|
57475
|
+
return null;
|
|
56971
57476
|
if (!res.claimed || !res.lane) {
|
|
56972
57477
|
if (res.reason === "empty") {
|
|
56973
57478
|
this.opts.log?.warn(`claim for ${targetUri} came back empty \u2014 nothing foldable; leaving to the reconciler`);
|
|
@@ -56990,6 +57495,7 @@ ${frame}` : frame;
|
|
|
56990
57495
|
targetUri,
|
|
56991
57496
|
threadRootId: trigger.threadRootId,
|
|
56992
57497
|
coverageMode: actualCoverage,
|
|
57498
|
+
settlementMode: res.settlement_mode ?? "legacy",
|
|
56993
57499
|
folded: /* @__PURE__ */ new Map(),
|
|
56994
57500
|
framed: [],
|
|
56995
57501
|
seen: /* @__PURE__ */ new Set(),
|
|
@@ -57024,9 +57530,8 @@ ${frame}` : frame;
|
|
|
57024
57530
|
}
|
|
57025
57531
|
return null;
|
|
57026
57532
|
}
|
|
57027
|
-
this.opts.log?.warn(`steer fold failed for ${ev.messageId}
|
|
57028
|
-
|
|
57029
|
-
return null;
|
|
57533
|
+
this.opts.log?.warn(`steer fold failed for ${ev.messageId}; preserving prior members: ${String(err)}`);
|
|
57534
|
+
continue;
|
|
57030
57535
|
}
|
|
57031
57536
|
}
|
|
57032
57537
|
return lane;
|
|
@@ -57040,7 +57545,7 @@ ${frame}` : frame;
|
|
|
57040
57545
|
async steerLive(event) {
|
|
57041
57546
|
const laneKey = this.laneKeyFor(event);
|
|
57042
57547
|
const lane = this.lanes.get(laneKey);
|
|
57043
|
-
if (!lane)
|
|
57548
|
+
if (!lane || lane.settling)
|
|
57044
57549
|
return null;
|
|
57045
57550
|
if (lane.seen.has(event.messageId))
|
|
57046
57551
|
return null;
|
|
@@ -57086,54 +57591,7 @@ ${frame}` : frame;
|
|
|
57086
57591
|
* prompt or injection actually delivers (frame coverage ∪ buffered group).
|
|
57087
57592
|
*/
|
|
57088
57593
|
inputLifecycleFor(lane, messageIds) {
|
|
57089
|
-
|
|
57090
|
-
const unique = [...new Set(messageIds)];
|
|
57091
|
-
const dispatchEventIds = unique.map((messageId) => lane.folded.get(messageId)).filter((id) => Boolean(id));
|
|
57092
|
-
if (explicit && dispatchEventIds.length !== unique.length) {
|
|
57093
|
-
throw new Error(`explicit lane ${lane.lane} is missing a folded WorkItem mapping`);
|
|
57094
|
-
}
|
|
57095
|
-
if (!explicit && dispatchEventIds.length === 0)
|
|
57096
|
-
return void 0;
|
|
57097
|
-
return {
|
|
57098
|
-
deliveryKey: dispatchEventIds.join(","),
|
|
57099
|
-
dispatchEventIds,
|
|
57100
|
-
update: explicit ? (state, failure) => this.updateInputState(lane, dispatchEventIds, state, failure) : async () => void 0
|
|
57101
|
-
};
|
|
57102
|
-
}
|
|
57103
|
-
async updateInputState(lane, dispatchEventIds, state, failure) {
|
|
57104
|
-
const failed = new Set(state === "failed" ? dispatchEventIds : []);
|
|
57105
|
-
const failedSourceIds = [...lane.folded].filter(([, dispatchEventId]) => failed.has(dispatchEventId)).map(([sourceId]) => sourceId);
|
|
57106
|
-
const restoreLocalClaims = failedSourceIds.length > 0 ? this.opts.releaseLocalClaims?.(failedSourceIds) : void 0;
|
|
57107
|
-
try {
|
|
57108
|
-
const result = await this.opts.client.updateDispatchInputState(this.opts.orgId, {
|
|
57109
|
-
lane: lane.lane,
|
|
57110
|
-
target_uri: lane.targetUri,
|
|
57111
|
-
thread_root_id: lane.threadRootId,
|
|
57112
|
-
dispatch_event_ids: dispatchEventIds,
|
|
57113
|
-
state,
|
|
57114
|
-
...state === "failed" && failure ? {
|
|
57115
|
-
outcome_class: errorWireClass(failure.outcomeClass),
|
|
57116
|
-
detail: failure.detail ? redactSecrets(failure.detail, this.opts.knownSecrets).slice(0, 500) : void 0
|
|
57117
|
-
} : {}
|
|
57118
|
-
});
|
|
57119
|
-
if (result.recognized !== dispatchEventIds.length) {
|
|
57120
|
-
throw new Error(`input lifecycle ${state} recognized ${result.recognized}/${dispatchEventIds.length} WorkItems`);
|
|
57121
|
-
}
|
|
57122
|
-
if (state === "failed" && result.released === 0) {
|
|
57123
|
-
restoreLocalClaims?.();
|
|
57124
|
-
return { retry: false };
|
|
57125
|
-
}
|
|
57126
|
-
} catch (err) {
|
|
57127
|
-
restoreLocalClaims?.();
|
|
57128
|
-
throw err;
|
|
57129
|
-
}
|
|
57130
|
-
if (state === "failed") {
|
|
57131
|
-
for (const [sourceId, dispatchEventId] of lane.folded) {
|
|
57132
|
-
if (failed.has(dispatchEventId))
|
|
57133
|
-
lane.folded.delete(sourceId);
|
|
57134
|
-
}
|
|
57135
|
-
}
|
|
57136
|
-
return { retry: state === "failed" };
|
|
57594
|
+
return this.inputs.lifecycle(lane, messageIds);
|
|
57137
57595
|
}
|
|
57138
57596
|
/** Carry the runtime error into the lane's forced completion. */
|
|
57139
57597
|
markTurnError(laneKey, info = {}) {
|
|
@@ -57162,62 +57620,62 @@ ${frame}` : frame;
|
|
|
57162
57620
|
const lane = this.lanes.get(laneKey);
|
|
57163
57621
|
if (!lane || hasMoreLocal)
|
|
57164
57622
|
return;
|
|
57165
|
-
|
|
57166
|
-
|
|
57623
|
+
if (lane.settling)
|
|
57624
|
+
return;
|
|
57625
|
+
lane.settling = true;
|
|
57167
57626
|
const deferred = !lane.turnError && !this.deferredUnsupported ? lane.turnDeferred : void 0;
|
|
57168
57627
|
const outcome = lane.turnError ? "error" : lane.turnDeferred ? this.deferredUnsupported ? "error" : "deferred" : "ok";
|
|
57169
|
-
|
|
57170
|
-
|
|
57171
|
-
|
|
57172
|
-
|
|
57173
|
-
|
|
57174
|
-
|
|
57175
|
-
|
|
57176
|
-
|
|
57177
|
-
|
|
57178
|
-
|
|
57179
|
-
|
|
57180
|
-
|
|
57181
|
-
|
|
57182
|
-
|
|
57183
|
-
|
|
57184
|
-
|
|
57185
|
-
|
|
57186
|
-
|
|
57187
|
-
|
|
57188
|
-
...
|
|
57189
|
-
|
|
57190
|
-
|
|
57191
|
-
|
|
57192
|
-
|
|
57193
|
-
|
|
57194
|
-
|
|
57195
|
-
|
|
57196
|
-
|
|
57197
|
-
} catch (err) {
|
|
57198
|
-
if (isStaleLane(err)) {
|
|
57199
|
-
this.opts.log?.info(`lane complete skipped for ${lane.targetUri} \u2014 taken over`);
|
|
57200
|
-
return;
|
|
57201
|
-
}
|
|
57202
|
-
if (outcome === "deferred" && err instanceof ApiError && err.status === 400) {
|
|
57203
|
-
this.deferredUnsupported = true;
|
|
57204
|
-
this.opts.log?.warn(`server rejected turn_outcome=deferred for ${lane.targetUri} \u2014 falling back to error completes`);
|
|
57628
|
+
const request3 = {
|
|
57629
|
+
lane: lane.lane,
|
|
57630
|
+
target_uri: lane.targetUri,
|
|
57631
|
+
thread_root_id: lane.threadRootId,
|
|
57632
|
+
// An error turn releases its members for retry; a deferred turn
|
|
57633
|
+
// re-delivers them at retry_at without burning redrive budget
|
|
57634
|
+
// (ignored by older servers, which 400 on the unknown enum — see the
|
|
57635
|
+
// fallback below).
|
|
57636
|
+
turn_outcome: outcome,
|
|
57637
|
+
...deferred ? {
|
|
57638
|
+
outcome_class: deferred.outcomeClass,
|
|
57639
|
+
...deferred.retryAt ? { retry_at: deferred.retryAt } : {}
|
|
57640
|
+
} : {},
|
|
57641
|
+
// An error complete carries the bridge's classification and redacted
|
|
57642
|
+
// evidence so the server can persist WHY on the released row
|
|
57643
|
+
// (agent-health-alerting-design.md §4.5). usage_limit never travels
|
|
57644
|
+
// with error: it is the deferred contract, and a server that rejected
|
|
57645
|
+
// deferred (deferredUnsupported) also predates the class field.
|
|
57646
|
+
...outcome === "error" && lane.turnError ? {
|
|
57647
|
+
...errorWireClass(lane.turnError.outcomeClass) ? { outcome_class: errorWireClass(lane.turnError.outcomeClass) } : {},
|
|
57648
|
+
...lane.turnError.detail ? { detail: lane.turnError.detail.slice(0, 500) } : {}
|
|
57649
|
+
} : {},
|
|
57650
|
+
session_id: lane.sessionAmbiguous ? void 0 : lane.sessionId
|
|
57651
|
+
};
|
|
57652
|
+
let fallback = false;
|
|
57653
|
+
await this.confirmations.submit(lane.lane, {
|
|
57654
|
+
label: "complete",
|
|
57655
|
+
send: async () => {
|
|
57205
57656
|
try {
|
|
57206
|
-
await this.opts.client.completeDispatch(this.opts.orgId, {
|
|
57207
|
-
lane:
|
|
57208
|
-
target_uri:
|
|
57209
|
-
thread_root_id:
|
|
57657
|
+
await this.opts.client.completeDispatch(this.opts.orgId, fallback ? {
|
|
57658
|
+
lane: request3.lane,
|
|
57659
|
+
target_uri: request3.target_uri,
|
|
57660
|
+
thread_root_id: request3.thread_root_id,
|
|
57210
57661
|
turn_outcome: "error"
|
|
57211
|
-
});
|
|
57212
|
-
} catch (
|
|
57213
|
-
if (
|
|
57214
|
-
|
|
57215
|
-
|
|
57662
|
+
} : request3);
|
|
57663
|
+
} catch (err) {
|
|
57664
|
+
if (!fallback && outcome === "deferred" && err instanceof ApiError && err.status === 400) {
|
|
57665
|
+
this.deferredUnsupported = true;
|
|
57666
|
+
fallback = true;
|
|
57667
|
+
await this.opts.client.completeDispatch(this.opts.orgId, {
|
|
57668
|
+
lane: request3.lane,
|
|
57669
|
+
target_uri: request3.target_uri,
|
|
57670
|
+
thread_root_id: request3.thread_root_id,
|
|
57671
|
+
turn_outcome: "error"
|
|
57672
|
+
});
|
|
57673
|
+
} else
|
|
57674
|
+
throw err;
|
|
57216
57675
|
}
|
|
57217
|
-
|
|
57676
|
+
this.forgetLane(lane);
|
|
57218
57677
|
}
|
|
57219
|
-
|
|
57220
|
-
}
|
|
57678
|
+
});
|
|
57221
57679
|
}
|
|
57222
57680
|
/**
|
|
57223
57681
|
* Renew one lane by its key — the external runtime-activity hook for
|
|
@@ -57239,6 +57697,8 @@ ${frame}` : frame;
|
|
|
57239
57697
|
* write's incumbency check anyway.
|
|
57240
57698
|
*/
|
|
57241
57699
|
maybeRenew(lane) {
|
|
57700
|
+
if (isTurnToken(lane.lane))
|
|
57701
|
+
return;
|
|
57242
57702
|
const now = Date.now();
|
|
57243
57703
|
const ttl = lane.leaseTtlMs ?? 10 * 6e4;
|
|
57244
57704
|
const until = lane.leaseUntilMs ?? now;
|
|
@@ -57269,26 +57729,40 @@ ${frame}` : frame;
|
|
|
57269
57729
|
*/
|
|
57270
57730
|
async release(laneKey, reason = "unspecified", info) {
|
|
57271
57731
|
const lane = this.lanes.get(laneKey);
|
|
57272
|
-
if (!lane)
|
|
57732
|
+
if (!lane || lane.settling)
|
|
57273
57733
|
return;
|
|
57274
|
-
|
|
57275
|
-
|
|
57276
|
-
|
|
57277
|
-
|
|
57278
|
-
|
|
57279
|
-
|
|
57280
|
-
|
|
57281
|
-
|
|
57282
|
-
|
|
57283
|
-
|
|
57284
|
-
|
|
57285
|
-
|
|
57734
|
+
lane.settling = true;
|
|
57735
|
+
const wireClass = errorWireClass(info?.outcomeClass);
|
|
57736
|
+
const outcome = info && (wireClass || info.detail) ? {
|
|
57737
|
+
...wireClass ? { outcome_class: wireClass } : {},
|
|
57738
|
+
...info.detail ? { detail: redactSecrets(info.detail, this.opts.knownSecrets).slice(0, 500) } : {}
|
|
57739
|
+
} : void 0;
|
|
57740
|
+
await this.confirmations.submit(lane.lane, {
|
|
57741
|
+
label: "release",
|
|
57742
|
+
send: async () => {
|
|
57743
|
+
await this.opts.client.releaseDispatchLane(this.opts.orgId, lane.lane, reason, outcome);
|
|
57744
|
+
this.forgetLane(lane);
|
|
57745
|
+
}
|
|
57746
|
+
});
|
|
57286
57747
|
}
|
|
57287
57748
|
async releaseAll(reason = "shutdown") {
|
|
57749
|
+
await this.confirmations.retryNow();
|
|
57288
57750
|
const keys = [...this.lanes.keys()];
|
|
57289
57751
|
for (const key of keys) {
|
|
57290
57752
|
await this.release(key, reason);
|
|
57291
57753
|
}
|
|
57754
|
+
for (const [key, claim] of this.claimResponses) {
|
|
57755
|
+
if (!claim.response?.lane)
|
|
57756
|
+
continue;
|
|
57757
|
+
const token = claim.response.lane;
|
|
57758
|
+
await this.confirmations.submit(token, {
|
|
57759
|
+
label: "unconsumed claim release",
|
|
57760
|
+
send: async () => {
|
|
57761
|
+
await this.opts.client.releaseDispatchLane(this.opts.orgId, token, reason);
|
|
57762
|
+
this.claimResponses.delete(key);
|
|
57763
|
+
}
|
|
57764
|
+
});
|
|
57765
|
+
}
|
|
57292
57766
|
}
|
|
57293
57767
|
/** True when any lane is currently active (used by shutdown logging). */
|
|
57294
57768
|
get activeCount() {
|
|
@@ -57303,18 +57777,57 @@ ${frame}` : frame;
|
|
|
57303
57777
|
* — the caller must skip processing.
|
|
57304
57778
|
*/
|
|
57305
57779
|
async claimTyped(ref) {
|
|
57306
|
-
|
|
57780
|
+
const key = `typed:${ref.dispatchEventId ?? `${ref.sourceType}:${ref.sourceId}`}`;
|
|
57781
|
+
if (this.claims.has(key))
|
|
57782
|
+
return null;
|
|
57783
|
+
if (ref.dispatchEventId && this.lanes.has(laneKeyForTarget(`dsp:${ref.dispatchEventId}`)))
|
|
57784
|
+
return null;
|
|
57785
|
+
const claim = this.claimTypedAttempt(ref);
|
|
57786
|
+
this.claims.set(key, claim);
|
|
57307
57787
|
try {
|
|
57308
|
-
|
|
57309
|
-
|
|
57310
|
-
|
|
57311
|
-
|
|
57788
|
+
return await claim;
|
|
57789
|
+
} finally {
|
|
57790
|
+
this.claims.delete(key);
|
|
57791
|
+
}
|
|
57792
|
+
}
|
|
57793
|
+
async claimRecoverably(key, request3) {
|
|
57794
|
+
let claim = this.claimResponses.get(key);
|
|
57795
|
+
if (!claim) {
|
|
57796
|
+
claim = { request: request3 };
|
|
57797
|
+
this.claimResponses.set(key, claim);
|
|
57798
|
+
const captured = claim;
|
|
57799
|
+
await this.confirmations.submit(`claim:${key}`, {
|
|
57800
|
+
label: "claim",
|
|
57801
|
+
send: async () => {
|
|
57802
|
+
try {
|
|
57803
|
+
captured.response = await this.opts.client.claimDispatch(this.opts.orgId, request3);
|
|
57804
|
+
} catch (err) {
|
|
57805
|
+
if (isEndpointMissing2(err))
|
|
57806
|
+
captured.unsupported = true;
|
|
57807
|
+
else
|
|
57808
|
+
throw err;
|
|
57809
|
+
}
|
|
57810
|
+
}
|
|
57312
57811
|
});
|
|
57313
|
-
} catch (err) {
|
|
57314
|
-
if (isEndpointMissing2(err))
|
|
57315
|
-
throw new LedgerUnsupportedError("claim endpoint unavailable");
|
|
57316
|
-
throw err;
|
|
57317
57812
|
}
|
|
57813
|
+
if (claim.unsupported) {
|
|
57814
|
+
this.claimResponses.delete(key);
|
|
57815
|
+
throw new LedgerUnsupportedError("claim endpoint unavailable");
|
|
57816
|
+
}
|
|
57817
|
+
if (!claim.response)
|
|
57818
|
+
return null;
|
|
57819
|
+
this.claimResponses.delete(key);
|
|
57820
|
+
return claim.response;
|
|
57821
|
+
}
|
|
57822
|
+
async claimTypedAttempt(ref) {
|
|
57823
|
+
const res = await this.claimRecoverably(`typed:${ref.dispatchEventId ?? `${ref.sourceType}:${ref.sourceId}`}`, {
|
|
57824
|
+
dispatch_event_id: ref.dispatchEventId,
|
|
57825
|
+
source_type: ref.dispatchEventId ? void 0 : ref.sourceType,
|
|
57826
|
+
source_id: ref.dispatchEventId ? void 0 : ref.sourceId,
|
|
57827
|
+
instance_id: this.opts.instanceId
|
|
57828
|
+
});
|
|
57829
|
+
if (!res)
|
|
57830
|
+
return null;
|
|
57318
57831
|
if (!res.claimed || !res.lane || !res.events?.length) {
|
|
57319
57832
|
if (res.reason === "stale") {
|
|
57320
57833
|
this.opts.log?.info(`typed dispatch ${ref.dispatchEventId ?? `${ref.sourceType}:${ref.sourceId}`} resolved by the server as stale (${res.stale_reason ?? "unspecified"})`);
|
|
@@ -57326,6 +57839,8 @@ ${frame}` : frame;
|
|
|
57326
57839
|
}
|
|
57327
57840
|
const workItem = res.events[0];
|
|
57328
57841
|
const targetUri = `dsp:${workItem.id}`;
|
|
57842
|
+
if (this.lanes.has(laneKeyForTarget(targetUri)))
|
|
57843
|
+
return null;
|
|
57329
57844
|
const leaseUntilMs = Date.parse(res.lease_until ?? "");
|
|
57330
57845
|
const lane = {
|
|
57331
57846
|
laneKey: laneKeyForTarget(targetUri),
|
|
@@ -57354,7 +57869,34 @@ ${frame}` : frame;
|
|
|
57354
57869
|
const lane = this.lanes.get(laneKey);
|
|
57355
57870
|
if (!lane)
|
|
57356
57871
|
return;
|
|
57357
|
-
this.
|
|
57872
|
+
this.confirmations.forget(lane.lane);
|
|
57873
|
+
this.forgetLane(lane);
|
|
57874
|
+
}
|
|
57875
|
+
syncInputAttribution(lane) {
|
|
57876
|
+
return this.inputs.syncAttribution(lane);
|
|
57877
|
+
}
|
|
57878
|
+
async confirmTyped(lane, send) {
|
|
57879
|
+
if (lane.settling)
|
|
57880
|
+
return;
|
|
57881
|
+
lane.settling = true;
|
|
57882
|
+
await this.confirmations.submit(lane.lane, {
|
|
57883
|
+
label: "typed complete",
|
|
57884
|
+
send: async () => {
|
|
57885
|
+
await send();
|
|
57886
|
+
this.forgetLane(lane);
|
|
57887
|
+
}
|
|
57888
|
+
});
|
|
57889
|
+
}
|
|
57890
|
+
retryConfirmations() {
|
|
57891
|
+
return this.confirmations.retryNow();
|
|
57892
|
+
}
|
|
57893
|
+
dispose() {
|
|
57894
|
+
this.confirmations.dispose();
|
|
57895
|
+
}
|
|
57896
|
+
forgetLane(lane) {
|
|
57897
|
+
if (this.lanes.get(lane.laneKey) !== lane)
|
|
57898
|
+
return;
|
|
57899
|
+
this.lanes.delete(lane.laneKey);
|
|
57358
57900
|
this.removeLaneContext(lane);
|
|
57359
57901
|
}
|
|
57360
57902
|
/**
|
|
@@ -58248,36 +58790,6 @@ function applyWake(event, wake) {
|
|
|
58248
58790
|
if (wake.attachments?.length)
|
|
58249
58791
|
event.attachments = wake.attachments;
|
|
58250
58792
|
}
|
|
58251
|
-
function hasUninjectedSameLaneEventAhead(host, event) {
|
|
58252
|
-
const eventIndex = host.dispatchState.mainBuffer.lastIndexOf(event);
|
|
58253
|
-
if (eventIndex <= 0)
|
|
58254
|
-
return false;
|
|
58255
|
-
const groupKey = host.dispatchGroupKey(event);
|
|
58256
|
-
return host.dispatchState.mainBuffer.slice(0, eventIndex).some((buffered) => host.dispatchGroupKey(buffered) === groupKey && !host.injectedMainBufferEvents.has(buffered));
|
|
58257
|
-
}
|
|
58258
|
-
async function steerLaneMessage(host, event) {
|
|
58259
|
-
const { laneLedger: ledger, opts } = host;
|
|
58260
|
-
const adapter = opts.dispatchAdapter;
|
|
58261
|
-
if (!ledger || !adapter.enqueueDuringDispatch)
|
|
58262
|
-
return;
|
|
58263
|
-
if (hasUninjectedSameLaneEventAhead(host, event))
|
|
58264
|
-
return;
|
|
58265
|
-
const folded = await ledger.steerLive(event);
|
|
58266
|
-
if (!folded)
|
|
58267
|
-
return;
|
|
58268
|
-
if (!folded.frame)
|
|
58269
|
-
return;
|
|
58270
|
-
event.frame = folded.frame;
|
|
58271
|
-
const injected = await adapter.enqueueDuringDispatch(opts.runtimeKey, eventBody(event), folded.inputLifecycle);
|
|
58272
|
-
if (injected) {
|
|
58273
|
-
host.injectedMainBufferEvents.add(event);
|
|
58274
|
-
ledger.markSeen(event, folded.covered);
|
|
58275
|
-
opts.log?.info(`steer folded+injected for ${event.messageId} (will drain for bookkeeping)`);
|
|
58276
|
-
} else if (folded.frame) {
|
|
58277
|
-
ledger.deferFrame(event, folded.frame, folded.covered);
|
|
58278
|
-
opts.log?.info(`steer folded but not injected for ${event.messageId} \u2014 frame deferred to the drain`);
|
|
58279
|
-
}
|
|
58280
|
-
}
|
|
58281
58793
|
async function dispatchLaneGroup(host, opts) {
|
|
58282
58794
|
const event = opts.events[opts.events.length - 1];
|
|
58283
58795
|
return runInDispatchTrace({
|
|
@@ -58297,7 +58809,7 @@ async function dispatchLaneGroup(host, opts) {
|
|
|
58297
58809
|
}
|
|
58298
58810
|
async function dispatchLaneGroupInner(host, opts) {
|
|
58299
58811
|
const ledger = host.laneLedger;
|
|
58300
|
-
|
|
58812
|
+
let event = opts.events[opts.events.length - 1];
|
|
58301
58813
|
let lane;
|
|
58302
58814
|
try {
|
|
58303
58815
|
lane = await runInPhaseSpan("claim", () => ledger.ensureLane(opts.events));
|
|
@@ -58315,18 +58827,51 @@ async function dispatchLaneGroupInner(host, opts) {
|
|
|
58315
58827
|
}
|
|
58316
58828
|
return "foreign";
|
|
58317
58829
|
}
|
|
58830
|
+
const foldedEvents = opts.events.filter((ev) => lane.folded.has(ev.messageId));
|
|
58831
|
+
for (const ev of opts.events) {
|
|
58832
|
+
if (!lane.folded.has(ev.messageId))
|
|
58833
|
+
host.dispatchedMessages.delete(ev.messageId);
|
|
58834
|
+
}
|
|
58835
|
+
if (foldedEvents.length === 0) {
|
|
58836
|
+
await ledger.completeIfIdle(lane.laneKey, unsettledInjections(host, opts.sessionKey) || opts.hasMoreLocal());
|
|
58837
|
+
return "foreign";
|
|
58838
|
+
}
|
|
58839
|
+
opts = { ...opts, events: foldedEvents, earlier: foldedEvents.slice(0, -1) };
|
|
58840
|
+
event = foldedEvents[foldedEvents.length - 1];
|
|
58318
58841
|
const pending = ledger.takeFrame(lane);
|
|
58319
58842
|
const frame = pending.frame;
|
|
58320
58843
|
if (!frame && opts.events.every((ev) => lane.seen.has(ev.messageId))) {
|
|
58321
58844
|
host.opts.log?.info(`lane group for ${event.messageId} already rendered by the server frame \u2014 no turn`);
|
|
58322
58845
|
const acknowledge = host.opts.dispatchAdapter.acknowledgeDiscardedInjection?.bind(host.opts.dispatchAdapter);
|
|
58846
|
+
const withdrawn = [];
|
|
58323
58847
|
if (acknowledge) {
|
|
58324
|
-
|
|
58325
|
-
const
|
|
58326
|
-
|
|
58327
|
-
|
|
58328
|
-
|
|
58848
|
+
try {
|
|
58849
|
+
for (const ev of opts.events) {
|
|
58850
|
+
const deliveryKey = lane.folded.get(ev.messageId);
|
|
58851
|
+
if (!deliveryKey)
|
|
58852
|
+
continue;
|
|
58853
|
+
if (await acknowledge(opts.sessionKey, deliveryKey) === "cancelled")
|
|
58854
|
+
withdrawn.push(ev);
|
|
58855
|
+
}
|
|
58856
|
+
} catch (err) {
|
|
58857
|
+
host.opts.log?.warn(`discarded input acknowledgement failed for ${event.messageId}: ${String(err)}`);
|
|
58858
|
+
}
|
|
58859
|
+
}
|
|
58860
|
+
if (withdrawn.length > 0 && !opts.withdrawnRetry) {
|
|
58861
|
+
for (const ev of withdrawn)
|
|
58862
|
+
host.dispatchedMessages.delete(ev.messageId);
|
|
58863
|
+
await ledger.completeIfIdle(lane.laneKey, unsettledInjections(host, opts.sessionKey));
|
|
58864
|
+
if (ledger.getForEvent(event))
|
|
58865
|
+
return "no_turn";
|
|
58866
|
+
return dispatchLaneGroupInner(host, {
|
|
58867
|
+
...opts,
|
|
58868
|
+
events: withdrawn,
|
|
58869
|
+
earlier: withdrawn.slice(0, -1),
|
|
58870
|
+
withdrawnRetry: true
|
|
58871
|
+
});
|
|
58329
58872
|
}
|
|
58873
|
+
for (const ev of opts.events)
|
|
58874
|
+
host.dispatchedMessages.delete(ev.messageId);
|
|
58330
58875
|
await runInPhaseSpan("settle", () => ledger.completeIfIdle(lane.laneKey, unsettledInjections(host, opts.sessionKey) || opts.hasMoreLocal()));
|
|
58331
58876
|
return "no_turn";
|
|
58332
58877
|
}
|
|
@@ -58350,6 +58895,9 @@ async function dispatchLaneGroupInner(host, opts) {
|
|
|
58350
58895
|
]);
|
|
58351
58896
|
dispatched = await host.runDispatch(event, opts.sessionKey, opts.bodyPrefix + eventBody(event), opts.earlier, opts.captureText, inputLifecycle);
|
|
58352
58897
|
} catch (err) {
|
|
58898
|
+
while (opts.sessionKey === host.opts.runtimeKey && hasMainSteers(host.dispatchState)) {
|
|
58899
|
+
await waitForMainSteers(host.dispatchState);
|
|
58900
|
+
}
|
|
58353
58901
|
host.noteSessionLane(opts.sessionKey, null);
|
|
58354
58902
|
await runInPhaseSpan("settle", () => ledger.release(lane.laneKey, "runtime_error", releaseErrorInfo(err, [host.opts.config.api_key])).catch(() => {
|
|
58355
58903
|
}));
|
|
@@ -58361,6 +58909,9 @@ async function dispatchLaneGroupInner(host, opts) {
|
|
|
58361
58909
|
if (!dispatched) {
|
|
58362
58910
|
return "shutdown";
|
|
58363
58911
|
}
|
|
58912
|
+
while (opts.sessionKey === host.opts.runtimeKey && hasMainSteers(host.dispatchState)) {
|
|
58913
|
+
await waitForMainSteers(host.dispatchState);
|
|
58914
|
+
}
|
|
58364
58915
|
const settled = host.consumeTurnOutcome(opts.sessionKey);
|
|
58365
58916
|
if (settled) {
|
|
58366
58917
|
if (settled.kind === "deferred") {
|
|
@@ -58512,17 +59063,24 @@ async function consumeTypedDispatch(host, ref, run, hooks) {
|
|
|
58512
59063
|
viaLegacyAck = true;
|
|
58513
59064
|
resolved = settleAck(await runInPhaseSpan("settle", () => hooks.legacyAck(claimed.typedDispatchEventId)));
|
|
58514
59065
|
} else {
|
|
58515
|
-
|
|
58516
|
-
|
|
58517
|
-
|
|
58518
|
-
|
|
58519
|
-
|
|
58520
|
-
|
|
58521
|
-
|
|
58522
|
-
|
|
58523
|
-
|
|
58524
|
-
|
|
58525
|
-
|
|
59066
|
+
await runInPhaseSpan("settle", () => ledger.confirmTyped(claimed, async () => {
|
|
59067
|
+
try {
|
|
59068
|
+
await host.opts.client.completeDispatch(host.opts.config.org_id, {
|
|
59069
|
+
dispatch_event_id: claimed.typedDispatchEventId,
|
|
59070
|
+
lane: claimed.lane,
|
|
59071
|
+
turn_outcome: "ok"
|
|
59072
|
+
});
|
|
59073
|
+
} catch (err) {
|
|
59074
|
+
if (!isByIDCompleteUnsupported(err))
|
|
59075
|
+
throw err;
|
|
59076
|
+
host.typedByIdCompleteUnsupported = true;
|
|
59077
|
+
if (!settleAck(await hooks.legacyAck(claimed.typedDispatchEventId))) {
|
|
59078
|
+
throw new Error("legacy typed acknowledgement unconfirmed");
|
|
59079
|
+
}
|
|
59080
|
+
await host.opts.client.releaseDispatchLane(host.opts.config.org_id, claimed.lane);
|
|
59081
|
+
}
|
|
59082
|
+
}));
|
|
59083
|
+
resolved = true;
|
|
58526
59084
|
}
|
|
58527
59085
|
}
|
|
58528
59086
|
} catch (err) {
|
|
@@ -58532,7 +59090,8 @@ async function consumeTypedDispatch(host, ref, run, hooks) {
|
|
|
58532
59090
|
settle(resolved);
|
|
58533
59091
|
span.setAttribute("dispatch.lane_result", resolved ? "dispatched" : "released");
|
|
58534
59092
|
if (resolved && !viaLegacyAck) {
|
|
58535
|
-
|
|
59093
|
+
if (!claimed.settling)
|
|
59094
|
+
ledger.dropLocal(claimed.laneKey);
|
|
58536
59095
|
} else {
|
|
58537
59096
|
await runInPhaseSpan("settle", () => ledger.completeIfIdle(claimed.laneKey, false).catch(() => {
|
|
58538
59097
|
}));
|
|
@@ -58696,6 +59255,19 @@ async function handleCompactSignal(host, data) {
|
|
|
58696
59255
|
// ../agent-core/dist/gateway-runtime-turns.js
|
|
58697
59256
|
var UNTARGETED_STEP = { target_type: "" };
|
|
58698
59257
|
function handleRuntimeActivity(host, event) {
|
|
59258
|
+
if (event.kind === "observation") {
|
|
59259
|
+
const binding = host.sessionBindings.get(event.sessionKey);
|
|
59260
|
+
if (!binding || binding.runtimeSessionId !== event.event.runtimeSessionId) {
|
|
59261
|
+
host.opts.log?.warn(`runtime observation has no matching session binding on ${event.sessionKey}`);
|
|
59262
|
+
return;
|
|
59263
|
+
}
|
|
59264
|
+
host.inFlightRuntimeTurns += 1;
|
|
59265
|
+
void persistRuntimeObservation(host.stepPersister, binding.agentSessionId, UNTARGETED_STEP, event.event, host.opts.log, [host.opts.config.api_key]).finally(() => {
|
|
59266
|
+
host.inFlightRuntimeTurns -= 1;
|
|
59267
|
+
host.notifyDrainWaiters();
|
|
59268
|
+
});
|
|
59269
|
+
return;
|
|
59270
|
+
}
|
|
58699
59271
|
const sessionKey = event.kind === "turn" ? event.turn.sessionKey : event.sessionKey;
|
|
58700
59272
|
const label = event.kind === "turn" ? `runtime-initiated turn ${event.turn.groupKey} on ${sessionKey}` : `runtime child session close for ${sessionKey}`;
|
|
58701
59273
|
const prior = host.runtimeActivityChains.get(sessionKey) ?? Promise.resolve();
|
|
@@ -58738,7 +59310,8 @@ async function runRuntimeTurn(host, turn) {
|
|
|
58738
59310
|
};
|
|
58739
59311
|
try {
|
|
58740
59312
|
for await (const runtimeEvent of turn.events) {
|
|
58741
|
-
|
|
59313
|
+
if (runtimeEvent.type !== "observation")
|
|
59314
|
+
deadline.touch();
|
|
58742
59315
|
if (runtimeEvent.type === "runtime_session") {
|
|
58743
59316
|
try {
|
|
58744
59317
|
binding = await host.bindRuntimeSession(sessionKey, runtimeEvent, contextFilePath);
|
|
@@ -58748,7 +59321,7 @@ async function runRuntimeTurn(host, turn) {
|
|
|
58748
59321
|
}
|
|
58749
59322
|
continue;
|
|
58750
59323
|
}
|
|
58751
|
-
if (!binding) {
|
|
59324
|
+
if (!binding || runtimeEvent.type === "observation" && binding.runtimeSessionId !== runtimeEvent.runtimeSessionId) {
|
|
58752
59325
|
droppedWithoutBinding += 1;
|
|
58753
59326
|
continue;
|
|
58754
59327
|
}
|
|
@@ -58763,7 +59336,8 @@ async function runRuntimeTurn(host, turn) {
|
|
|
58763
59336
|
await host.createRuntimeStep(binding.agentSessionId, UNTARGETED_STEP, { type: "error", message: failure.stepMessage, groupKey }, void 0, contextFilePath);
|
|
58764
59337
|
continue;
|
|
58765
59338
|
}
|
|
58766
|
-
|
|
59339
|
+
if (runtimeEvent.type !== "observation")
|
|
59340
|
+
await ensureBegun();
|
|
58767
59341
|
stepCount += 1;
|
|
58768
59342
|
await host.createRuntimeStep(binding.agentSessionId, UNTARGETED_STEP, runtimeEvent, void 0, contextFilePath);
|
|
58769
59343
|
}
|
|
@@ -58972,6 +59546,19 @@ var DispatchInactivityDeadline = class {
|
|
|
58972
59546
|
this.onExpire();
|
|
58973
59547
|
}, delayMs);
|
|
58974
59548
|
}
|
|
59549
|
+
/**
|
|
59550
|
+
* Re-arm after an expiry that was only reported, not acted on (the
|
|
59551
|
+
* no-abort default: a long silent turn is logged at intervals, never
|
|
59552
|
+
* killed — attached-turn-ownership).
|
|
59553
|
+
*/
|
|
59554
|
+
rearm() {
|
|
59555
|
+
if (this.disposed || this.timeoutMs <= 0)
|
|
59556
|
+
return;
|
|
59557
|
+
this.expired = false;
|
|
59558
|
+
this.lastActivityAt = Date.now();
|
|
59559
|
+
if (!this.timer)
|
|
59560
|
+
this.arm(this.timeoutMs);
|
|
59561
|
+
}
|
|
58975
59562
|
dispose() {
|
|
58976
59563
|
if (this.disposed)
|
|
58977
59564
|
return;
|
|
@@ -59881,6 +60468,7 @@ function recordToolCall(sessionKey) {
|
|
|
59881
60468
|
}
|
|
59882
60469
|
|
|
59883
60470
|
// ../agent-core/dist/gateway-base.js
|
|
60471
|
+
var AUTH_INVALID_EXIT_CODE = 86;
|
|
59884
60472
|
var TYPED_EVENT_KINDS = {
|
|
59885
60473
|
task_assign: { type: "task", ackSourceType: "task_activity" },
|
|
59886
60474
|
task_update: { type: "task", ackSourceType: "task_activity" },
|
|
@@ -59917,11 +60505,11 @@ function parseDispatchDeadlineMs(raw) {
|
|
|
59917
60505
|
}
|
|
59918
60506
|
function inputStepIdempotencyKey(event) {
|
|
59919
60507
|
if (event.type === "message" || event.type === "channel_message") {
|
|
59920
|
-
return event.messageId ? `input:${event.messageId}` :
|
|
60508
|
+
return event.messageId ? `input:${event.messageId}` : randomUUID2();
|
|
59921
60509
|
}
|
|
59922
60510
|
if (event.dispatchEventId)
|
|
59923
60511
|
return `input:${event.dispatchEventId}`;
|
|
59924
|
-
return
|
|
60512
|
+
return randomUUID2();
|
|
59925
60513
|
}
|
|
59926
60514
|
function resolveStepTarget(event) {
|
|
59927
60515
|
if (event.input?.step_target) {
|
|
@@ -60050,14 +60638,9 @@ var ParallAgentGateway = class {
|
|
|
60050
60638
|
pendingRestartNotification = null;
|
|
60051
60639
|
laneLedger;
|
|
60052
60640
|
stepPersister;
|
|
60053
|
-
//
|
|
60054
|
-
// desired-state reconciler (see session-lifecycle.ts). The gateway only
|
|
60055
|
-
// declares turn boundaries; ordering, retries and stale-finish rejection
|
|
60056
|
-
// live in the coordinator.
|
|
60641
|
+
// Session lifecycle owns ordering, retries and stale-finish rejection.
|
|
60057
60642
|
sessionLifecycle;
|
|
60058
|
-
//
|
|
60059
|
-
// gateway only triggers it; ordering and ownership live in the finalizer
|
|
60060
|
-
// (see fork-session-finalizer.ts).
|
|
60643
|
+
// ForkSessionFinalizer owns seal → drain → close → release.
|
|
60061
60644
|
forkFinalizer;
|
|
60062
60645
|
// Sticky fallback: flipped when the server predates the ledger (claim
|
|
60063
60646
|
// endpoint 404) so every subsequent dispatch uses the legacy flow.
|
|
@@ -60073,10 +60656,12 @@ var ParallAgentGateway = class {
|
|
|
60073
60656
|
SHUTDOWN_DEADLINE_MS;
|
|
60074
60657
|
FORK_DEADLINE_MS;
|
|
60075
60658
|
DISPATCH_DEADLINE_MS;
|
|
60659
|
+
INACTIVITY_WARN_MS;
|
|
60076
60660
|
constructor(opts) {
|
|
60077
60661
|
this.opts = opts;
|
|
60078
60662
|
opts = this.opts = { ...opts, log: redactLogger(opts.log, [opts.config.api_key]) };
|
|
60079
60663
|
if (opts.dispatchContextDir) {
|
|
60664
|
+
const recovery = new DispatchRecovery(() => this.catchUpFromDispatch(), () => this.shuttingDown, (err) => opts.log?.warn(`dispatch recovery failed: ${String(err)}`));
|
|
60080
60665
|
this.laneLedger = new LaneLedger({
|
|
60081
60666
|
client: opts.client,
|
|
60082
60667
|
orgId: opts.config.org_id,
|
|
@@ -60084,12 +60669,17 @@ var ParallAgentGateway = class {
|
|
|
60084
60669
|
log: opts.log,
|
|
60085
60670
|
knownSecrets: [opts.config.api_key],
|
|
60086
60671
|
coverageMode: opts.dispatchAdapter.inputLifecycleMode ?? "implicit",
|
|
60672
|
+
settlementMode: opts.dispatchAdapter.inputSettlementMode,
|
|
60673
|
+
instanceId: opts.instanceId,
|
|
60674
|
+
terminalRetryDelaysMs: opts.laneTerminalRetryDelaysMs,
|
|
60675
|
+
onRecovered: recovery.request,
|
|
60087
60676
|
releaseLocalClaims: (sourceIds) => releaseLocalMessageClaims(this.dispatchedMessages, sourceIds)
|
|
60088
60677
|
});
|
|
60089
60678
|
}
|
|
60090
60679
|
this.SHUTDOWN_DEADLINE_MS = opts.shutdownDeadlineMs ?? 6e4;
|
|
60091
|
-
this.FORK_DEADLINE_MS = opts.forkDeadlineMs ??
|
|
60092
|
-
this.DISPATCH_DEADLINE_MS = opts.dispatchDeadlineMs ??
|
|
60680
|
+
this.FORK_DEADLINE_MS = opts.forkDeadlineMs ?? 0;
|
|
60681
|
+
this.DISPATCH_DEADLINE_MS = opts.dispatchDeadlineMs ?? 0;
|
|
60682
|
+
this.INACTIVITY_WARN_MS = opts.inactivityWarnMs ?? 30 * 6e4;
|
|
60093
60683
|
this.unsubscribeRuntimeActivity = opts.dispatchAdapter.subscribeRuntimeActivity?.((event) => this.handleRuntimeActivity(event));
|
|
60094
60684
|
this.stepPersister = new StepPersister({
|
|
60095
60685
|
client: opts.client,
|
|
@@ -60167,12 +60757,34 @@ var ParallAgentGateway = class {
|
|
|
60167
60757
|
}
|
|
60168
60758
|
});
|
|
60169
60759
|
this.opts.log?.info(`connecting to ${this.opts.connectionLabel ?? "Parall WS"}...`);
|
|
60760
|
+
let settled = false;
|
|
60761
|
+
let onSettled = null;
|
|
60762
|
+
const finish = async (opts) => {
|
|
60763
|
+
if (settled)
|
|
60764
|
+
return;
|
|
60765
|
+
settled = true;
|
|
60766
|
+
await this.shutdown(opts);
|
|
60767
|
+
onSettled?.();
|
|
60768
|
+
};
|
|
60769
|
+
ws.onAuthInvalid((event) => {
|
|
60770
|
+
const exitCode = this.opts.authInvalidExitCode === void 0 ? AUTH_INVALID_EXIT_CODE : this.opts.authInvalidExitCode;
|
|
60771
|
+
log?.error(`AUTH-INVALID agent=${this.opts.agentUserId} status=${event.status}${event.code ? ` code=${event.code}` : ""} \u2014 the server rejected this runtime's credential (${event.message}); the key is invalid, expired, or revoked.`);
|
|
60772
|
+
if (exitCode === null) {
|
|
60773
|
+
log?.error("AUTH-INVALID: reconnects are stopped and this account gateway has shut down. Refresh this account\u2019s credential and start it again; other accounts in this process are unaffected.");
|
|
60774
|
+
} else {
|
|
60775
|
+
log?.error(`AUTH-INVALID: reconnects are stopped. Exiting with code ${exitCode} so the supervisor can re-mint the launch credential and restart this agent; if no supervisor manages this process, replace its PRLL_API_KEY and start it again.`);
|
|
60776
|
+
process.exitCode = exitCode;
|
|
60777
|
+
}
|
|
60778
|
+
void finish({ skipDrain: true });
|
|
60779
|
+
});
|
|
60170
60780
|
await ws.connect();
|
|
60171
60781
|
return new Promise((resolve3) => {
|
|
60172
|
-
|
|
60173
|
-
await this.shutdown();
|
|
60782
|
+
if (settled) {
|
|
60174
60783
|
resolve3();
|
|
60175
|
-
|
|
60784
|
+
return;
|
|
60785
|
+
}
|
|
60786
|
+
onSettled = resolve3;
|
|
60787
|
+
abortSignal.addEventListener("abort", () => void finish());
|
|
60176
60788
|
});
|
|
60177
60789
|
}
|
|
60178
60790
|
tryClaimMessage(id) {
|
|
@@ -60404,100 +61016,7 @@ var ParallAgentGateway = class {
|
|
|
60404
61016
|
});
|
|
60405
61017
|
}
|
|
60406
61018
|
async createRuntimeStep(sessionId, target, runtimeEvent, stepIdFilePath, contextFilePath, laneContextFilePath2) {
|
|
60407
|
-
|
|
60408
|
-
case "thinking":
|
|
60409
|
-
await this.stepPersister.persist(sessionId, "thinking", {
|
|
60410
|
-
step_type: "thinking",
|
|
60411
|
-
target_type: target.target_type,
|
|
60412
|
-
target_id: target.target_id,
|
|
60413
|
-
idempotency_key: randomUUID(),
|
|
60414
|
-
content: { text: runtimeEvent.text },
|
|
60415
|
-
group_key: runtimeEvent.groupKey
|
|
60416
|
-
});
|
|
60417
|
-
break;
|
|
60418
|
-
case "text":
|
|
60419
|
-
await this.stepPersister.persist(sessionId, "text", {
|
|
60420
|
-
step_type: "text",
|
|
60421
|
-
target_type: target.target_type,
|
|
60422
|
-
target_id: target.target_id,
|
|
60423
|
-
idempotency_key: randomUUID(),
|
|
60424
|
-
content: {
|
|
60425
|
-
text: runtimeEvent.text,
|
|
60426
|
-
suppressed: runtimeEvent.project !== true
|
|
60427
|
-
},
|
|
60428
|
-
projection: runtimeEvent.project === true,
|
|
60429
|
-
group_key: runtimeEvent.groupKey
|
|
60430
|
-
});
|
|
60431
|
-
break;
|
|
60432
|
-
case "tool_call": {
|
|
60433
|
-
const step = await this.stepPersister.persist(sessionId, "tool_call", {
|
|
60434
|
-
step_type: "tool_call",
|
|
60435
|
-
target_type: target.target_type,
|
|
60436
|
-
target_id: target.target_id,
|
|
60437
|
-
// call_id is session-unique for bridge runtimes (server-enforced),
|
|
60438
|
-
// so the bare form anchors the tool step pair across retries —
|
|
60439
|
-
// unlike parel's turn-scoped `tc:{turnId}:{callId}` (see
|
|
60440
|
-
// protocol-vectors/agent-steps.json).
|
|
60441
|
-
idempotency_key: `tc:${runtimeEvent.callId}`,
|
|
60442
|
-
content: {
|
|
60443
|
-
call_id: runtimeEvent.callId,
|
|
60444
|
-
tool_name: runtimeEvent.toolName,
|
|
60445
|
-
tool_input: runtimeEvent.input,
|
|
60446
|
-
status: "running",
|
|
60447
|
-
started_at: runtimeEvent.startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
60448
|
-
},
|
|
60449
|
-
group_key: runtimeEvent.groupKey,
|
|
60450
|
-
runtime_key: runtimeEvent.callId
|
|
60451
|
-
});
|
|
60452
|
-
if (step) {
|
|
60453
|
-
if (contextFilePath) {
|
|
60454
|
-
this.updateContextFileStepId(contextFilePath, step.id);
|
|
60455
|
-
} else if (stepIdFilePath) {
|
|
60456
|
-
this.writeStepIdFile(stepIdFilePath, step.id);
|
|
60457
|
-
}
|
|
60458
|
-
if (laneContextFilePath2) {
|
|
60459
|
-
this.updateContextFileStepId(laneContextFilePath2, step.id);
|
|
60460
|
-
}
|
|
60461
|
-
}
|
|
60462
|
-
break;
|
|
60463
|
-
}
|
|
60464
|
-
case "tool_result":
|
|
60465
|
-
await this.stepPersister.persist(sessionId, "tool_result", {
|
|
60466
|
-
step_type: "tool_result",
|
|
60467
|
-
target_type: target.target_type,
|
|
60468
|
-
target_id: target.target_id,
|
|
60469
|
-
idempotency_key: `tr:${runtimeEvent.callId}`,
|
|
60470
|
-
content: {
|
|
60471
|
-
call_id: runtimeEvent.callId,
|
|
60472
|
-
tool_name: runtimeEvent.toolName,
|
|
60473
|
-
status: runtimeEvent.error ? "error" : "success",
|
|
60474
|
-
output: runtimeEvent.output,
|
|
60475
|
-
duration_ms: runtimeEvent.durationMs ?? 0,
|
|
60476
|
-
collapsible: true
|
|
60477
|
-
},
|
|
60478
|
-
group_key: runtimeEvent.groupKey
|
|
60479
|
-
});
|
|
60480
|
-
if (contextFilePath) {
|
|
60481
|
-
this.updateContextFileStepId(contextFilePath, null);
|
|
60482
|
-
} else if (stepIdFilePath) {
|
|
60483
|
-
this.clearStepIdFile(stepIdFilePath);
|
|
60484
|
-
}
|
|
60485
|
-
if (laneContextFilePath2) {
|
|
60486
|
-
this.updateContextFileStepId(laneContextFilePath2, null);
|
|
60487
|
-
}
|
|
60488
|
-
break;
|
|
60489
|
-
case "error":
|
|
60490
|
-
await this.stepPersister.persist(sessionId, "error", {
|
|
60491
|
-
step_type: "text",
|
|
60492
|
-
target_type: target.target_type,
|
|
60493
|
-
target_id: target.target_id,
|
|
60494
|
-
idempotency_key: randomUUID(),
|
|
60495
|
-
content: buildErrorStepContent(runtimeEvent.message),
|
|
60496
|
-
projection: false,
|
|
60497
|
-
group_key: runtimeEvent.groupKey
|
|
60498
|
-
});
|
|
60499
|
-
break;
|
|
60500
|
-
}
|
|
61019
|
+
return createRuntimeStep(this, sessionId, target, runtimeEvent, stepIdFilePath, contextFilePath, laneContextFilePath2);
|
|
60501
61020
|
}
|
|
60502
61021
|
writeContextFile(filePath, ctx) {
|
|
60503
61022
|
try {
|
|
@@ -60590,6 +61109,7 @@ var ParallAgentGateway = class {
|
|
|
60590
61109
|
step_id: null,
|
|
60591
61110
|
dispatch_event_id: activeLane?.typedDispatchEventId ?? activeLane?.folded.get(event.messageId) ?? null,
|
|
60592
61111
|
lane: activeLane?.lane ?? null,
|
|
61112
|
+
settlement_mode: activeLane?.settlementMode ?? "legacy",
|
|
60593
61113
|
target_uri: activeLane?.targetUri ?? null,
|
|
60594
61114
|
thread_root_id: activeLane?.threadRootId ?? null,
|
|
60595
61115
|
// Typed binding hint for the CLI: which task this dispatch is about
|
|
@@ -60609,13 +61129,19 @@ var ParallAgentGateway = class {
|
|
|
60609
61129
|
threadRootId: contextBody.thread_root_id
|
|
60610
61130
|
});
|
|
60611
61131
|
this.inFlightDispatches++;
|
|
60612
|
-
const
|
|
60613
|
-
|
|
60614
|
-
|
|
60615
|
-
this.opts.
|
|
60616
|
-
|
|
60617
|
-
|
|
61132
|
+
const abortAfterMs = this.DISPATCH_DEADLINE_MS;
|
|
61133
|
+
const dispatchDeadline = this.dispatchInactivityDeadlines.start(sessionKey, abortAfterMs > 0 ? abortAfterMs : this.INACTIVITY_WARN_MS, () => {
|
|
61134
|
+
if (abortAfterMs > 0) {
|
|
61135
|
+
this.opts.log?.warn(`dispatch inactivity deadline exceeded (${abortAfterMs}ms) for ${event.messageId} on ${sessionKey}; aborting`);
|
|
61136
|
+
try {
|
|
61137
|
+
this.opts.dispatchAdapter.abortDispatch?.(sessionKey);
|
|
61138
|
+
} catch (err) {
|
|
61139
|
+
this.opts.log?.warn(`abortDispatch threw for ${sessionKey}: ${String(err)}`);
|
|
61140
|
+
}
|
|
61141
|
+
return;
|
|
60618
61142
|
}
|
|
61143
|
+
this.opts.log?.warn(`no runtime output for ${Math.round(this.INACTIVITY_WARN_MS / 6e4)} min on ${sessionKey} (${event.messageId}); the turn stays open \u2014 only the runtime finishing or a process restart ends it`);
|
|
61144
|
+
dispatchDeadline.rearm();
|
|
60619
61145
|
});
|
|
60620
61146
|
let binding = this.sessionBindings.get(sessionKey);
|
|
60621
61147
|
let inputStepsCreated = false;
|
|
@@ -60640,12 +61166,14 @@ var ParallAgentGateway = class {
|
|
|
60640
61166
|
inputLifecycle,
|
|
60641
61167
|
noteActivity: dispatchDeadline.touch
|
|
60642
61168
|
})) {
|
|
60643
|
-
|
|
61169
|
+
if (runtimeEvent.type !== "observation")
|
|
61170
|
+
dispatchDeadline.touch();
|
|
60644
61171
|
if (runtimeEvent.type === "runtime_session") {
|
|
60645
61172
|
const priorAgentSessionId = binding?.agentSessionId;
|
|
60646
61173
|
binding = await runInPhaseSpan("session", () => this.bindRuntimeSession(sessionKey, runtimeEvent, contextFilePath, laneContextFilePath2));
|
|
60647
61174
|
if (activeLane) {
|
|
60648
61175
|
bindLaneSession(activeLane, binding.agentSessionId);
|
|
61176
|
+
await this.laneLedger?.syncInputAttribution(activeLane);
|
|
60649
61177
|
}
|
|
60650
61178
|
if (event.targetType === "channel_conversation" && binding.agentSessionId !== priorAgentSessionId) {
|
|
60651
61179
|
try {
|
|
@@ -60664,6 +61192,14 @@ var ParallAgentGateway = class {
|
|
|
60664
61192
|
}
|
|
60665
61193
|
continue;
|
|
60666
61194
|
}
|
|
61195
|
+
if (runtimeEvent.type === "observation") {
|
|
61196
|
+
if (binding?.runtimeSessionId === runtimeEvent.runtimeSessionId) {
|
|
61197
|
+
await this.createRuntimeStep(binding.agentSessionId, stepTarget, runtimeEvent);
|
|
61198
|
+
} else {
|
|
61199
|
+
this.opts.log?.warn("runtime observation has no matching active session binding");
|
|
61200
|
+
}
|
|
61201
|
+
continue;
|
|
61202
|
+
}
|
|
60667
61203
|
if (runtimeEvent.type === "turn_outcome") {
|
|
60668
61204
|
const outcomeEvent = redactTurnOutcome(runtimeEvent, [this.opts.config.api_key]);
|
|
60669
61205
|
turnOutcomeEvent = outcomeEvent;
|
|
@@ -61036,6 +61572,8 @@ var ParallAgentGateway = class {
|
|
|
61036
61572
|
while (this.idleCompact.inFlight)
|
|
61037
61573
|
await this.idleCompact.inFlight;
|
|
61038
61574
|
while (this.dispatchState.mainBuffer.length > 0) {
|
|
61575
|
+
while (hasMainSteers(this.dispatchState))
|
|
61576
|
+
await waitForMainSteers(this.dispatchState);
|
|
61039
61577
|
if (this.shuttingDown) {
|
|
61040
61578
|
this.opts.log?.info(`drainMainBuffer halted (shutting down) \u2014 ${this.dispatchState.mainBuffer.length} buffered, ${this.dispatchState.pendingForkResults.length} pending fork results left for catch-up`);
|
|
61041
61579
|
break;
|
|
@@ -61285,9 +61823,11 @@ var ParallAgentGateway = class {
|
|
|
61285
61823
|
const activeFork = createActiveForkState(fork, event.targetId, continuationPrefix);
|
|
61286
61824
|
this.forkStates.set(event.targetId, activeFork);
|
|
61287
61825
|
this.dispatchState.activeForks.set(event.targetId, fork.sessionKey);
|
|
61288
|
-
|
|
61289
|
-
|
|
61290
|
-
|
|
61826
|
+
if (this.FORK_DEADLINE_MS > 0) {
|
|
61827
|
+
activeFork.deadlineTimer = setTimeout(() => {
|
|
61828
|
+
this.abortFork(event.targetId, `deadline exceeded (${this.FORK_DEADLINE_MS}ms)`);
|
|
61829
|
+
}, this.FORK_DEADLINE_MS);
|
|
61830
|
+
}
|
|
61291
61831
|
const firstEventPromise = new Promise((resolve3) => {
|
|
61292
61832
|
activeFork.queue.push({ event, resolve: resolve3 });
|
|
61293
61833
|
});
|
|
@@ -61486,12 +62026,16 @@ ${fullSummary}` : fullSummary;
|
|
|
61486
62026
|
this.sessionId = data.session_id ?? "";
|
|
61487
62027
|
if (this.forkStates.size > 0) {
|
|
61488
62028
|
const targetIds = [...this.forkStates.keys()];
|
|
61489
|
-
|
|
61490
|
-
|
|
61491
|
-
|
|
62029
|
+
if (this.opts.instanceId) {
|
|
62030
|
+
log?.info(`${targetIds.length} active fork(s) continue across the reconnect`);
|
|
62031
|
+
} else {
|
|
62032
|
+
log?.info(`aborting ${targetIds.length} active fork(s) on reconnect`);
|
|
62033
|
+
for (const targetId of targetIds) {
|
|
62034
|
+
this.abortFork(targetId, "ws reconnect");
|
|
62035
|
+
}
|
|
61492
62036
|
}
|
|
61493
62037
|
}
|
|
61494
|
-
if (this.laneLedger && this.inFlightDispatches === 0 && this.laneLedger.activeCount > 0) {
|
|
62038
|
+
if (this.laneLedger && !this.opts.instanceId && this.inFlightDispatches === 0 && this.laneLedger.activeCount > 0) {
|
|
61495
62039
|
log?.info(`releasing ${this.laneLedger.activeCount} stale lane(s) on reconnect`);
|
|
61496
62040
|
await this.laneLedger.releaseAll();
|
|
61497
62041
|
}
|
|
@@ -61538,6 +62082,7 @@ ${fullSummary}` : fullSummary;
|
|
|
61538
62082
|
uptime: os.uptime()
|
|
61539
62083
|
});
|
|
61540
62084
|
}, intervalSec * 1e3);
|
|
62085
|
+
await this.laneLedger?.retryConfirmations();
|
|
61541
62086
|
this.catchUpFromDispatch().catch((err) => {
|
|
61542
62087
|
log?.warn(`dispatch catch-up failed: ${String(err)}`);
|
|
61543
62088
|
});
|
|
@@ -61604,13 +62149,9 @@ ${fullSummary}` : fullSummary;
|
|
|
61604
62149
|
}
|
|
61605
62150
|
}
|
|
61606
62151
|
}
|
|
61607
|
-
/**
|
|
61608
|
-
* Nothing in flight: no dispatch, no runtime-initiated turn, and the
|
|
61609
|
-
* runtime itself reports idle (isBusy — a turn it is executing that has
|
|
61610
|
-
* not surfaced yet, or a follow-up hold after background work finished).
|
|
61611
|
-
*/
|
|
62152
|
+
/** Drain includes in-flight native work and unfinished steer registration. */
|
|
61612
62153
|
isDrained() {
|
|
61613
|
-
return this.inFlightDispatches === 0 && this.inFlightRuntimeTurns === 0 && !this.adapterBusy();
|
|
62154
|
+
return this.inFlightDispatches === 0 && this.inFlightRuntimeTurns === 0 && !hasMainSteers(this.dispatchState) && !this.adapterBusy();
|
|
61614
62155
|
}
|
|
61615
62156
|
adapterBusy() {
|
|
61616
62157
|
try {
|
|
@@ -61623,10 +62164,12 @@ ${fullSummary}` : fullSummary;
|
|
|
61623
62164
|
notifyDrainWaiters() {
|
|
61624
62165
|
this.drainGate.notify();
|
|
61625
62166
|
}
|
|
61626
|
-
async shutdown() {
|
|
62167
|
+
async shutdown(opts = { skipDrain: false }) {
|
|
61627
62168
|
this.shuttingDown = true;
|
|
61628
62169
|
this.idleCompact.abort?.();
|
|
61629
|
-
if (!this.isDrained()) {
|
|
62170
|
+
if (opts.skipDrain && !this.isDrained()) {
|
|
62171
|
+
this.opts.log?.warn(`skipping drain (credential rejected): ${this.inFlightDispatches} dispatch(es), ${this.inFlightRuntimeTurns} runtime-initiated turn(s) abandoned to server redelivery`);
|
|
62172
|
+
} else if (!this.isDrained()) {
|
|
61630
62173
|
this.opts.log?.info(`draining ${this.inFlightDispatches} in-flight dispatch(es), ${this.inFlightRuntimeTurns} runtime-initiated turn(s), runtime busy=${this.adapterBusy()}, deadline ${this.SHUTDOWN_DEADLINE_MS}ms`);
|
|
61631
62174
|
await this.drainGate.wait(this.SHUTDOWN_DEADLINE_MS);
|
|
61632
62175
|
if (!this.isDrained()) {
|
|
@@ -61637,7 +62180,7 @@ ${fullSummary}` : fullSummary;
|
|
|
61637
62180
|
}
|
|
61638
62181
|
if (this.heartbeatTimer)
|
|
61639
62182
|
clearInterval(this.heartbeatTimer);
|
|
61640
|
-
if (this.laneLedger
|
|
62183
|
+
if (this.laneLedger) {
|
|
61641
62184
|
this.opts.log?.info(`releasing ${this.laneLedger.activeCount} lane(s) on shutdown`);
|
|
61642
62185
|
await this.laneLedger.releaseAll();
|
|
61643
62186
|
}
|
|
@@ -61657,6 +62200,8 @@ ${fullSummary}` : fullSummary;
|
|
|
61657
62200
|
this.opts.log?.warn(`${lifecycleRemaining} session lifecycle write(s) unreconciled at shutdown`);
|
|
61658
62201
|
}
|
|
61659
62202
|
this.sessionLifecycle.dispose();
|
|
62203
|
+
await this.laneLedger?.retryConfirmations();
|
|
62204
|
+
this.laneLedger?.dispose();
|
|
61660
62205
|
this.opts.ws.disconnect();
|
|
61661
62206
|
this.unsubscribeRuntimeActivity?.();
|
|
61662
62207
|
this.opts.log?.info(`disconnected`);
|
|
@@ -62649,17 +63194,17 @@ async function startWikiHelper(params) {
|
|
|
62649
63194
|
}
|
|
62650
63195
|
|
|
62651
63196
|
// dist/oc-session.js
|
|
62652
|
-
import { randomUUID as
|
|
63197
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
62653
63198
|
import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
|
|
62654
63199
|
import { join as join7, resolve as resolve2 } from "node:path";
|
|
62655
63200
|
var CURRENT_SESSION_VERSION = 3;
|
|
62656
63201
|
function generateId(existing) {
|
|
62657
63202
|
for (let i = 0; i < 100; i++) {
|
|
62658
|
-
const id =
|
|
63203
|
+
const id = randomUUID3().slice(0, 8);
|
|
62659
63204
|
if (!existing.has(id))
|
|
62660
63205
|
return id;
|
|
62661
63206
|
}
|
|
62662
|
-
return
|
|
63207
|
+
return randomUUID3();
|
|
62663
63208
|
}
|
|
62664
63209
|
function loadEntries(filePath) {
|
|
62665
63210
|
if (!existsSync4(filePath))
|
|
@@ -62774,14 +63319,14 @@ var SessionManager = class _SessionManager {
|
|
|
62774
63319
|
if (header && header.version > CURRENT_SESSION_VERSION) {
|
|
62775
63320
|
throw new Error(`Session file ${this.sessionFile} uses version ${header.version}, but oc-session.ts only supports up to ${CURRENT_SESSION_VERSION}. Sync oc-session.ts with upstream pi-coding-agent (see AGENTS.md step 4).`);
|
|
62776
63321
|
}
|
|
62777
|
-
this.sessionId = header?.id ??
|
|
63322
|
+
this.sessionId = header?.id ?? randomUUID3();
|
|
62778
63323
|
if (migrate(this.fileEntries))
|
|
62779
63324
|
this.rewrite();
|
|
62780
63325
|
this.buildIndex();
|
|
62781
63326
|
this.flushed = true;
|
|
62782
63327
|
}
|
|
62783
63328
|
initEmpty() {
|
|
62784
|
-
this.sessionId =
|
|
63329
|
+
this.sessionId = randomUUID3();
|
|
62785
63330
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
62786
63331
|
this.fileEntries = [
|
|
62787
63332
|
{
|
|
@@ -62858,7 +63403,7 @@ var SessionManager = class _SessionManager {
|
|
|
62858
63403
|
if (branch.length === 0)
|
|
62859
63404
|
throw new Error(`Entry ${leafId} not found`);
|
|
62860
63405
|
const pathWithoutLabels = branch.filter((e) => e.type !== "label");
|
|
62861
|
-
const newId =
|
|
63406
|
+
const newId = randomUUID3();
|
|
62862
63407
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
62863
63408
|
const ts = timestamp.replace(/[:.]/g, "-");
|
|
62864
63409
|
const newFile = join7(this.sessionDir, `${ts}_${newId}.jsonl`);
|
|
@@ -63429,13 +63974,18 @@ var parallGateway = {
|
|
|
63429
63974
|
runtimeKey: orchestratorKey,
|
|
63430
63975
|
runtimeRef: { hostname: os2.hostname(), pid: process.pid },
|
|
63431
63976
|
dispatchAdapter,
|
|
63977
|
+
// One OpenClaw host embeds many account gateways in one process: a
|
|
63978
|
+
// rejected credential stops THIS account's gateway only — it must
|
|
63979
|
+
// not set the host-wide process exit code or claim the process is
|
|
63980
|
+
// exiting.
|
|
63981
|
+
authInvalidExitCode: null,
|
|
63432
63982
|
// Opts openclaw into the dispatch ledger (claim/fold/complete +
|
|
63433
63983
|
// idempotent reply effects) — the same shared-gateway machinery
|
|
63434
63984
|
// claude/codex ride; openclaw stays buffer-only (no mid-turn steer),
|
|
63435
63985
|
// which the ledger does not require. Replies already flow through
|
|
63436
63986
|
// @parall/cli, which reads PRLL_CONTEXT_DIR (injected in hooks.ts)
|
|
63437
63987
|
// to bind dispatch_lane + reply effect keys.
|
|
63438
|
-
// Design: docs/engineering-design/dispatch-
|
|
63988
|
+
// Design: docs/engineering-design/agent-dispatch-idempotency-design.md#effects.
|
|
63439
63989
|
dispatchContextDir: dispatchLaneContextDir(stateDir),
|
|
63440
63990
|
// Per-session context file (PRLL_CONTEXT_FILE contract) — the CLI's
|
|
63441
63991
|
// TYPED dispatch binding (parall tasks update → task_update effect)
|