@agentconnect.md/setup 1.37.0-rc.3 → 1.37.0-rc.4
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/index.js +6 -1119
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36023,20 +36023,6 @@ const ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => {
|
|
|
36023
36023
|
inst.keyType = def.keyType;
|
|
36024
36024
|
inst.valueType = def.valueType;
|
|
36025
36025
|
});
|
|
36026
|
-
function record$1(keyType, valueType, params) {
|
|
36027
|
-
if (!valueType || !valueType._zod) return new ZodRecord({
|
|
36028
|
-
type: "record",
|
|
36029
|
-
keyType: string(),
|
|
36030
|
-
valueType: keyType,
|
|
36031
|
-
...normalizeParams(valueType)
|
|
36032
|
-
});
|
|
36033
|
-
return new ZodRecord({
|
|
36034
|
-
type: "record",
|
|
36035
|
-
keyType,
|
|
36036
|
-
valueType,
|
|
36037
|
-
...normalizeParams(params)
|
|
36038
|
-
});
|
|
36039
|
-
}
|
|
36040
36026
|
function partialRecord(keyType, valueType, params) {
|
|
36041
36027
|
const k = clone(keyType);
|
|
36042
36028
|
k._zod.values = void 0;
|
|
@@ -36293,1115 +36279,16 @@ function number(params) {
|
|
|
36293
36279
|
return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
|
|
36294
36280
|
}
|
|
36295
36281
|
//#endregion
|
|
36296
|
-
//#region ../protocol/dist/
|
|
36282
|
+
//#region ../protocol/dist/slack-app-manifest.js
|
|
36297
36283
|
var import_fastify = /* @__PURE__ */ __toESM(require_fastify(), 1);
|
|
36298
|
-
object({
|
|
36299
|
-
v: literal(1),
|
|
36300
|
-
id: string().uuid(),
|
|
36301
|
-
ts: string().datetime(),
|
|
36302
|
-
type: string(),
|
|
36303
|
-
corr: string().uuid().optional(),
|
|
36304
|
-
payload: unknown()
|
|
36305
|
-
});
|
|
36306
|
-
object({
|
|
36307
|
-
epoch: number$1().int(),
|
|
36308
|
-
agentId: string().uuid().optional(),
|
|
36309
|
-
launchId: string().uuid().optional()
|
|
36310
|
-
});
|
|
36311
|
-
/**
|
|
36312
|
-
* Builds the envelope schema for one frame `type` — the `type` literal plus the
|
|
36313
|
-
* typed payload — so a wire's discriminated union infers `payload` precisely.
|
|
36314
|
-
* Shared by the daemon↔CP union (`frame.ts`) and the relay wire unions
|
|
36315
|
-
* (`frames/relay-cp.ts` / `frames/relay-daemon.ts`), which are deliberately
|
|
36316
|
-
* SEPARATE unions over the same envelope shape (shared-bot-relay.md §8).
|
|
36317
|
-
*/
|
|
36318
|
-
function frameSchema(type, payload) {
|
|
36319
|
-
return object({
|
|
36320
|
-
v: literal(1),
|
|
36321
|
-
id: string().uuid(),
|
|
36322
|
-
ts: string().datetime(),
|
|
36323
|
-
type: literal(type),
|
|
36324
|
-
corr: string().uuid().optional(),
|
|
36325
|
-
payload
|
|
36326
|
-
});
|
|
36327
|
-
}
|
|
36328
|
-
const ErrorFrame = object({
|
|
36329
|
-
code: _enum([
|
|
36330
|
-
"UNKNOWN_FRAME",
|
|
36331
|
-
"FRAME_TOO_LARGE",
|
|
36332
|
-
"PROTOCOL_STATE",
|
|
36333
|
-
"BAD_PAYLOAD",
|
|
36334
|
-
"AUTH_FAILED",
|
|
36335
|
-
"ATTESTATION_INVALID",
|
|
36336
|
-
"STALE_EPOCH",
|
|
36337
|
-
"STALE_LAUNCH",
|
|
36338
|
-
"NO_SESSION",
|
|
36339
|
-
"SCOPE_DENIED",
|
|
36340
|
-
"DELEGATION_DENIED",
|
|
36341
|
-
"INVOCATION_CONFLICT",
|
|
36342
|
-
"LEASE_EXPIRED",
|
|
36343
|
-
"LEASE_DENIED",
|
|
36344
|
-
"RATE_LIMITED",
|
|
36345
|
-
"CONFLICT",
|
|
36346
|
-
"INTERNAL"
|
|
36347
|
-
]),
|
|
36348
|
-
message: string(),
|
|
36349
|
-
retryable: boolean(),
|
|
36350
|
-
details: record$1(string(), unknown()).optional()
|
|
36351
|
-
});
|
|
36352
|
-
//#endregion
|
|
36353
|
-
//#region ../protocol/dist/frames/route.js
|
|
36354
|
-
const Platform = string().min(1);
|
|
36355
|
-
const SessionKey = object({
|
|
36356
|
-
platform: Platform,
|
|
36357
|
-
channel: string(),
|
|
36358
|
-
thread: string().optional()
|
|
36359
|
-
});
|
|
36360
|
-
/** Trigger-matching rule for a binding (protocol §5.1). */
|
|
36361
|
-
const BindRule = object({ match: discriminatedUnion("kind", [
|
|
36362
|
-
object({ kind: literal("mention") }),
|
|
36363
|
-
object({ kind: literal("dm") }),
|
|
36364
|
-
object({
|
|
36365
|
-
kind: literal("keyword"),
|
|
36366
|
-
value: string()
|
|
36367
|
-
}),
|
|
36368
|
-
object({ kind: literal("auto") })
|
|
36369
|
-
]) });
|
|
36370
|
-
object({
|
|
36371
|
-
sessionKey: SessionKey,
|
|
36372
|
-
agentId: string().uuid(),
|
|
36373
|
-
workspaceId: string().uuid(),
|
|
36374
|
-
bindRules: array(BindRule).default([])
|
|
36375
|
-
});
|
|
36376
|
-
object({
|
|
36377
|
-
ok: boolean(),
|
|
36378
|
-
sessionKey: SessionKey,
|
|
36379
|
-
reason: string().optional()
|
|
36380
|
-
});
|
|
36381
|
-
object({
|
|
36382
|
-
routingEpoch: number$1().int(),
|
|
36383
|
-
rules: array(object({
|
|
36384
|
-
match: unknown(),
|
|
36385
|
-
agentId: string().uuid()
|
|
36386
|
-
}))
|
|
36387
|
-
});
|
|
36388
|
-
object({
|
|
36389
|
-
scope: union([
|
|
36390
|
-
object({
|
|
36391
|
-
kind: literal("agent"),
|
|
36392
|
-
agentId: string().uuid()
|
|
36393
|
-
}),
|
|
36394
|
-
object({ kind: literal("daemon") }),
|
|
36395
|
-
object({
|
|
36396
|
-
kind: literal("session"),
|
|
36397
|
-
sessionKey: SessionKey
|
|
36398
|
-
})
|
|
36399
|
-
]),
|
|
36400
|
-
deadline: string().datetime()
|
|
36401
|
-
});
|
|
36402
|
-
object({
|
|
36403
|
-
remaining: number$1().int(),
|
|
36404
|
-
drained: array(SessionKey)
|
|
36405
|
-
});
|
|
36406
|
-
object({ released: array(SessionKey) });
|
|
36407
|
-
//#endregion
|
|
36408
|
-
//#region ../protocol/dist/frames/integration.js
|
|
36409
|
-
/**
|
|
36410
|
-
* Platform integration distribution (C→D) — the Slack "install" flow.
|
|
36411
|
-
*
|
|
36412
|
-
* The Control Plane is the source of truth for platform integrations and pushes
|
|
36413
|
-
* them to the daemon that owns the integration's agent (`integration/upsert`, and
|
|
36414
|
-
* the reconcile snapshot `RegisterOk.integrations[]`). The daemon opens the Socket
|
|
36415
|
-
* Mode connection from the delivered config (see slack/connection.ts).
|
|
36416
|
-
*
|
|
36417
|
-
* SECURITY: `integration/upsert` and `RegisterOk.integrations[]` carry PLAINTEXT
|
|
36418
|
-
* platform tokens (botToken/appToken/appSecret). These payloads MUST NEVER be
|
|
36419
|
-
* logged — no body dump on decode error, no register/ok snapshot debug dump.
|
|
36420
|
-
* CP-owned integrations live only in daemon MEMORY and are re-converged on
|
|
36421
|
-
* reconnect; hand-authored agents keep tokens in their own `agent.json` (the
|
|
36422
|
-
* same trust boundary as the daemon process).
|
|
36423
|
-
*
|
|
36424
|
-
* `signingSecret` is intentionally absent: Socket Mode authenticates with the
|
|
36425
|
-
* app-level token, so the daemon never needs a signing secret.
|
|
36426
|
-
*/
|
|
36427
|
-
/** Trigger match — mirrors the daemon BindRuleConfig.match (agents/agent-schema.ts). */
|
|
36428
|
-
const BindMatch = discriminatedUnion("kind", [
|
|
36429
|
-
object({ kind: literal("mention") }),
|
|
36430
|
-
object({ kind: literal("dm") }),
|
|
36431
|
-
object({
|
|
36432
|
-
kind: literal("keyword"),
|
|
36433
|
-
value: string()
|
|
36434
|
-
}),
|
|
36435
|
-
object({ kind: literal("auto") })
|
|
36436
|
-
]);
|
|
36437
|
-
/** One channel/thread trigger binding — mirrors the daemon BindRuleConfig. */
|
|
36438
|
-
const IntegrationBindRule = object({
|
|
36439
|
-
channel: string().optional(),
|
|
36440
|
-
thread: string().optional(),
|
|
36441
|
-
match: BindMatch
|
|
36442
|
-
});
|
|
36443
|
-
object({
|
|
36444
|
-
botToken: string(),
|
|
36445
|
-
appToken: string().optional(),
|
|
36446
|
-
appId: string().optional(),
|
|
36447
|
-
shareable: boolean().default(false),
|
|
36448
|
-
botUserId: string().optional()
|
|
36449
|
-
});
|
|
36450
|
-
object({ botToken: string() });
|
|
36451
|
-
object({
|
|
36452
|
-
botToken: string(),
|
|
36453
|
-
applicationId: string().optional()
|
|
36454
|
-
});
|
|
36455
|
-
/**
|
|
36456
|
-
* The Feishu / Lark config payload — the long-connection WebSocket
|
|
36457
|
-
* (`@larksuiteoapi/node-sdk` `WSClient`) + REST client. A Feishu self-built app
|
|
36458
|
-
* authenticates with an `appId` + `appSecret` PAIR — the SDK exchanges them for a
|
|
36459
|
-
* short-lived `tenant_access_token` internally (no Slack-style app-level token, no
|
|
36460
|
-
* signing secret). `appId` is a semi-public identifier (`cli_…`); `appSecret` is
|
|
36461
|
-
* plaintext secret material — NEVER log it. `botOpenId` is the bot's own open_id
|
|
36462
|
-
* for @-mention routing; lazily resolved by the daemon via `bot/info` if absent.
|
|
36463
|
-
*
|
|
36464
|
-
* The envelope's `mode` decides the transport: `direct` opens the SDK long
|
|
36465
|
-
* connection on the daemon; `shared` keeps only the authenticated REST client
|
|
36466
|
-
* (callbacks arrive through the relay, pre-addressed over rd/*).
|
|
36467
|
-
*
|
|
36468
|
-
* `region` selects the open-platform gateway the daemon SDK (and CP verifier)
|
|
36469
|
-
* talk to — `'feishu'` = mainland China (`open.feishu.cn`, the SDK default) vs
|
|
36470
|
-
* `'lark'` = international (`open.larksuite.com`). Same app model, different host;
|
|
36471
|
-
* an app is registered in exactly one region. Defaults to `'feishu'` so existing
|
|
36472
|
-
* installs are unaffected.
|
|
36473
|
-
*/
|
|
36474
|
-
const FeishuRegion = _enum(["feishu", "lark"]);
|
|
36475
|
-
object({
|
|
36476
|
-
appId: string(),
|
|
36477
|
-
appSecret: string(),
|
|
36478
|
-
botOpenId: string().optional(),
|
|
36479
|
-
region: FeishuRegion.default("feishu")
|
|
36480
|
-
});
|
|
36481
|
-
/**
|
|
36482
|
-
* §6.4 core routing ENVELOPE (integration-plugin-architecture.md D4): the knobs CORE
|
|
36483
|
-
* reads — routing, gating, ingress mode — platform-independent. This is the ONLY
|
|
36484
|
-
* carrier of these knobs on the wire: the opaque per-platform `config` payload
|
|
36485
|
-
* never duplicates them (the daemon reads routing exclusively from here).
|
|
36486
|
-
*/
|
|
36487
|
-
const IntegrationCoreEnvelope = object({
|
|
36488
|
-
mode: _enum(["direct", "shared"]).default("direct"),
|
|
36489
|
-
bindRules: array(IntegrationBindRule).default([]),
|
|
36490
|
-
mutedChannels: array(string()).default([]),
|
|
36491
|
-
gated: boolean().default(false)
|
|
36492
|
-
});
|
|
36493
|
-
object({
|
|
36494
|
-
integrationId: string().uuid(),
|
|
36495
|
-
agentId: string().uuid(),
|
|
36496
|
-
platform: Platform,
|
|
36497
|
-
core: IntegrationCoreEnvelope,
|
|
36498
|
-
config: unknown().optional()
|
|
36499
|
-
});
|
|
36500
|
-
object({ integrationId: string().uuid() });
|
|
36501
|
-
/**
|
|
36502
|
-
* One conversation the bot participates in (metadata only — no messages).
|
|
36503
|
-
* `kind` distinguishes member channels from direct conversations (resource-
|
|
36504
|
-
* visibility.md §14.3): absent = 'channel' for wire compatibility. DM rows
|
|
36505
|
-
* (`kind: 'im'`, Slack "D…" ids) are reported for every integration on first
|
|
36506
|
-
* inbound DM; their `name` is the counterpart's display name. Group DMs
|
|
36507
|
-
* (`kind: 'mpim'`, Slack multi-person DMs) are reported on observation the same
|
|
36508
|
-
* way — never enumerated, because Slack does not list them as bot membership —
|
|
36509
|
-
* but they behave like a channel: several humans share the room, so the agent
|
|
36510
|
-
* stays mention-gated there rather than answering every message.
|
|
36511
|
-
*
|
|
36512
|
-
* `spaceId`/`space` identify the container the conversation lives in — a Discord
|
|
36513
|
-
* GUILD, which a bot in several servers needs for the channel to be identifiable at
|
|
36514
|
-
* all (every server has a "#general"). The ID is the identity: two distinct guilds
|
|
36515
|
-
* may carry the SAME name, so grouping on the name alone would merge them and hide
|
|
36516
|
-
* the ambiguity it was meant to resolve. `space` is the display label only. Both are
|
|
36517
|
-
* absent on platforms with one implicit container per bot (Slack workspace, Telegram,
|
|
36518
|
-
* Feishu tenant) and on DM rows.
|
|
36519
|
-
*/
|
|
36520
|
-
const IntegrationChannel = object({
|
|
36521
|
-
id: string(),
|
|
36522
|
-
name: string().optional(),
|
|
36523
|
-
spaceId: string().optional(),
|
|
36524
|
-
space: string().optional(),
|
|
36525
|
-
isPrivate: boolean().optional(),
|
|
36526
|
-
kind: _enum([
|
|
36527
|
-
"channel",
|
|
36528
|
-
"im",
|
|
36529
|
-
"mpim"
|
|
36530
|
-
]).optional()
|
|
36531
|
-
});
|
|
36532
|
-
object({
|
|
36533
|
-
integrationId: string().uuid(),
|
|
36534
|
-
channels: array(IntegrationChannel),
|
|
36535
|
-
authoritative: boolean().optional(),
|
|
36536
|
-
removed: array(string()).optional()
|
|
36537
|
-
});
|
|
36538
|
-
/**
|
|
36539
|
-
* What a leave targets. Platforms disagree about what a bot can withdraw from, and
|
|
36540
|
-
* the difference is not cosmetic — so the caller has to say which it means rather
|
|
36541
|
-
* than the daemon guessing from an id:
|
|
36542
|
-
*
|
|
36543
|
-
* - `conversation` — one channel/group the bot is a member of (Slack
|
|
36544
|
-
* `conversations.leave`, Telegram `leaveChat`).
|
|
36545
|
-
* - `space` — the whole container. Discord has no per-channel membership for a
|
|
36546
|
-
* bot at all: it is in a GUILD and sees that guild's channels through
|
|
36547
|
-
* permissions, so the only thing it can leave is the entire server. That is a
|
|
36548
|
-
* much larger action than leaving one channel and must be requested as such.
|
|
36549
|
-
*/
|
|
36550
|
-
const IntegrationLeaveTarget = discriminatedUnion("kind", [object({
|
|
36551
|
-
kind: literal("conversation"),
|
|
36552
|
-
channel: string().min(1)
|
|
36553
|
-
}), object({
|
|
36554
|
-
kind: literal("space"),
|
|
36555
|
-
spaceId: string().min(1)
|
|
36556
|
-
})]);
|
|
36557
|
-
object({
|
|
36558
|
-
integrationId: string().uuid(),
|
|
36559
|
-
target: IntegrationLeaveTarget
|
|
36560
|
-
});
|
|
36561
|
-
object({
|
|
36562
|
-
integrationId: string().uuid(),
|
|
36563
|
-
channels: array(string()).min(1)
|
|
36564
|
-
});
|
|
36565
|
-
object({
|
|
36566
|
-
ok: boolean(),
|
|
36567
|
-
error: string().optional()
|
|
36568
|
-
});
|
|
36569
|
-
//#endregion
|
|
36570
|
-
//#region ../protocol/dist/frames/cron.js
|
|
36571
|
-
/**
|
|
36572
|
-
* Cron sinks to the daemon (D5) — protocol §5.4.
|
|
36573
|
-
*
|
|
36574
|
-
* A cron periodically triggers ONE AGENT with a synthetic prompt (`trigger`) to
|
|
36575
|
-
* carry out some work. The CP owns the definition; the daemon owns firing +
|
|
36576
|
-
* last-run persistence, so crons fire even when the CP is down. On receipt the
|
|
36577
|
-
* daemon persists the def into the owning agent's `agent.json` `crons[]` (the
|
|
36578
|
-
* single source of truth, same model as integrations) — surviving a restart
|
|
36579
|
-
* with the CP down.
|
|
36580
|
-
*
|
|
36581
|
-
* `target` is OPTIONAL output routing: when present, the daemon posts the
|
|
36582
|
-
* trigger as a real message in that channel and the agent's session replies in
|
|
36583
|
-
* its thread; when absent the fire is headless (the agent works with no
|
|
36584
|
-
* platform output).
|
|
36585
|
-
*/
|
|
36586
|
-
const CronTarget = object({
|
|
36587
|
-
platform: Platform.default("slack"),
|
|
36588
|
-
channel: string(),
|
|
36589
|
-
integrationId: string().uuid().optional()
|
|
36590
|
-
});
|
|
36591
|
-
object({
|
|
36592
|
-
cronId: string().uuid(),
|
|
36593
|
-
agentId: string().uuid(),
|
|
36594
|
-
schedule: string(),
|
|
36595
|
-
timezone: string().min(1),
|
|
36596
|
-
target: CronTarget.optional(),
|
|
36597
|
-
trigger: string(),
|
|
36598
|
-
enabled: boolean().default(true)
|
|
36599
|
-
});
|
|
36600
|
-
object({ cronId: string().uuid() });
|
|
36601
|
-
/**
|
|
36602
|
-
* `cron/report` (D→C EVT, fire-and-forget) — one CP-owned cron fired. The
|
|
36603
|
-
* daemon stamps the fire into its local store first (it stays authoritative,
|
|
36604
|
-
* §5.4) and reports it here so the console's `lastRunAt` converges; the CP
|
|
36605
|
-
* upsert is latest-wins, so the daemon re-asserting its stored stamps on
|
|
36606
|
-
* reconnect (fires while the CP was unreachable) is idempotent and can never
|
|
36607
|
-
* regress the value. Hand-authored (no-origin) crons are never reported.
|
|
36608
|
-
*
|
|
36609
|
-
* Reports are keyed by `(cronId, firedAt)`: the FIRE report (no `status`)
|
|
36610
|
-
* opens the run, an optional SESSION report attaches the ACP session as soon
|
|
36611
|
-
* as it is initialized, and the COMPLETION report (with `status` + outcome
|
|
36612
|
-
* fields) closes the run once the dispatched turn ends. A completion without
|
|
36613
|
-
* a prior fire report (CP was down at fire time) still creates the run row.
|
|
36614
|
-
*/
|
|
36615
|
-
const CronRunStatus = _enum(["success", "failed"]);
|
|
36616
|
-
object({
|
|
36617
|
-
cronId: string().uuid(),
|
|
36618
|
-
agentId: string().uuid(),
|
|
36619
|
-
firedAt: string().datetime(),
|
|
36620
|
-
status: CronRunStatus.optional(),
|
|
36621
|
-
durationMs: number$1().int().nonnegative().optional(),
|
|
36622
|
-
sessionId: string().optional(),
|
|
36623
|
-
reason: string().optional()
|
|
36624
|
-
});
|
|
36625
|
-
object({ cronId: string().uuid() });
|
|
36626
|
-
//#endregion
|
|
36627
|
-
//#region ../protocol/dist/frames/collab.js
|
|
36628
|
-
/**
|
|
36629
|
-
* Bot-AGNOSTIC agent-collaboration routing snapshot (agent-collaboration §2.3 / §6.2 / §6.5).
|
|
36630
|
-
*
|
|
36631
|
-
* The existing shared-bot `members` table is keyed by botId (`BotAssignment`) and
|
|
36632
|
-
* CANNOT address an agent on a DIFFERENT bot / arbitrary channel. This snapshot is
|
|
36633
|
-
* the fix: it maps a channel — `(orgId, platform, channelId)` — to the per-agent
|
|
36634
|
-
* placement + call policy the relay needs to route a cross-daemon `rd/agentmsg` and
|
|
36635
|
-
* the target daemon needs to terminal-verify a remote caller.
|
|
36636
|
-
*
|
|
36637
|
-
* It carries NO message body — pure routing/policy metadata, like the rest of the
|
|
36638
|
-
* control plane. The SAME shape is distributed two ways (§6.5):
|
|
36639
|
-
* - CP→relay over the `rc/*` wire (`rc/collab-routes`) — the relay routes
|
|
36640
|
-
* `toAgentId` → owning `daemonId` and authorizes the caller/target policy.
|
|
36641
|
-
* - CP→daemon over the daemon↔CP wire — as a `register/ok` field (reconnect
|
|
36642
|
-
* baseline) + a `collaboration/routes` EVT (hot push) — so the OWNING daemon of
|
|
36643
|
-
* the target can terminal-verify (defense in depth, §2.5 #4) the remote caller's
|
|
36644
|
-
* org/channel/placement against its OWN copy, never trusting the relay's claim
|
|
36645
|
-
* blindly.
|
|
36646
|
-
*
|
|
36647
|
-
* FOLLOW-UP (scoped down in P2, see PR description): the full versioned lifecycle
|
|
36648
|
-
* of §6.5 — per-entry tombstones, TTL/expiry after a CP disconnect, and
|
|
36649
|
-
* fail-closed-on-stale — is NOT fully implemented here. `generation` is present as
|
|
36650
|
-
* the version hook and the snapshot is FULL-REPLACE (converge-don't-diff, same as
|
|
36651
|
-
* `register/ok`), which is enough to route + authorize on a live CP. TTL-expiry and
|
|
36652
|
-
* tombstone semantics are a follow-up within this phase.
|
|
36653
|
-
*/
|
|
36654
|
-
/** One agent's placement + call policy within a channel. `daemonId` is the owning
|
|
36655
|
-
* daemon the relay forwards to; `integrationId` is the DEFINITE reply integration
|
|
36656
|
-
* (§6.2 — no fallback to "first connection"). */
|
|
36657
|
-
const CollabAgentPlacement = object({
|
|
36658
|
-
agentId: string().uuid(),
|
|
36659
|
-
daemonId: string().uuid(),
|
|
36660
|
-
integrationId: string().uuid().optional(),
|
|
36661
|
-
/** Public Slack app id (`A…`) for this agent's bot. Receivers use it to recognize
|
|
36662
|
-
* AgentConnect-authored platform messages — the first half of verifying an
|
|
36663
|
-
* authorship claim (send-message-routing-rework.md §4). */
|
|
36664
|
-
botAppId: string().optional(),
|
|
36665
|
-
/** Public platform member id this agent's bot posts as (Slack `U…`) — the id a
|
|
36666
|
-
* `<@…>` mention resolves to. With {@link botShared} and `name` it is the complete
|
|
36667
|
-
* input for the conversation-specific mention ADDRESS
|
|
36668
|
-
* (send-message-routing-rework.md §8.5), which both directions need: rendering an
|
|
36669
|
-
* exact address to post, and resolving an inbound mention back to an agent.
|
|
36670
|
-
* Public metadata, never a credential. */
|
|
36671
|
-
botUserId: string().optional(),
|
|
36672
|
-
/** True when {@link botUserId} backs MORE THAN ONE agent (a shared bot). The bot user
|
|
36673
|
-
* id alone then cannot identify an agent, so its address carries the agent slug too
|
|
36674
|
-
* (`<@U_SHARED> reviewer`) and a BARE mention of it addresses no specific agent —
|
|
36675
|
-
* which is why a shared bot with no exact author claim fails closed at ingress (§4)
|
|
36676
|
-
* and why a bare shared-bot mention from an agent must not fall back to the channel
|
|
36677
|
-
* default (§6). */
|
|
36678
|
-
botShared: boolean().optional(),
|
|
36679
|
-
callPolicy: _enum(["all", "selected"]).default("all"),
|
|
36680
|
-
allowedCallerAgentIds: array(string()).default([]),
|
|
36681
|
-
/** Caller-side authorization. Effective A→B access requires A's outbound
|
|
36682
|
-
* policy to admit B and B's inbound call policy to admit A. */
|
|
36683
|
-
outboundPolicy: _enum(["all", "selected"]).default("all"),
|
|
36684
|
-
allowedTargetAgentIds: array(string()).default([]),
|
|
36685
|
-
name: string().optional(),
|
|
36686
|
-
displayName: string().optional()
|
|
36687
|
-
});
|
|
36688
|
-
/**
|
|
36689
|
-
* One agent's placement + call policy carried OUTSIDE any channel — the org-scoped
|
|
36690
|
-
* peer directory entry.
|
|
36691
|
-
*
|
|
36692
|
-
* Every structure on the CP→daemon and CP→relay wires is channel-keyed, so an agent
|
|
36693
|
-
* with NO IM integration (webchat, hook, dream, memory-only) never appears in any
|
|
36694
|
-
* `channels[]` entry at all. The channel-keyed snapshot structurally cannot express
|
|
36695
|
-
* "which agents exist in this org", which is precisely the input channel-free
|
|
36696
|
-
* authorization needs: discovery and A2A authorization depend only on the directional
|
|
36697
|
-
* call policy (`outboundPolicy`/`allowedTargetAgentIds` on the caller,
|
|
36698
|
-
* `callPolicy`/`allowedCallerAgentIds` on the target), org-scoped, with channel
|
|
36699
|
-
* demoted to an optional filter. Hence the flat list below.
|
|
36700
|
-
*/
|
|
36701
|
-
const CollabOrgAgent = CollabAgentPlacement.extend({ orgId: string().min(1) });
|
|
36702
|
-
/** All agents present in one channel, across daemons. `orgId` scopes routing +
|
|
36703
|
-
* authorization: a cross-org caller/target pair never resolves (§2.5 — cross-org
|
|
36704
|
-
* rejected). */
|
|
36705
|
-
const CollabChannelRoute = object({
|
|
36706
|
-
orgId: string().min(1),
|
|
36707
|
-
platform: Platform,
|
|
36708
|
-
channelId: string().min(1),
|
|
36709
|
-
agents: array(CollabAgentPlacement)
|
|
36710
|
-
});
|
|
36711
|
-
/**
|
|
36712
|
-
* The full collaboration snapshot — FULL-REPLACE (converge-don't-diff): the
|
|
36713
|
-
* recipient replaces its whole table with `channels`. `generation` monotonically
|
|
36714
|
-
* increases per source so a recipient can ignore a stale re-order (version hook for
|
|
36715
|
-
* the §6.5 lifecycle follow-up).
|
|
36716
|
-
*/
|
|
36717
|
-
const CollabRoutesSnapshot = object({
|
|
36718
|
-
generation: number$1().int().nonnegative().default(0),
|
|
36719
|
-
channels: array(CollabChannelRoute).default([]),
|
|
36720
|
-
/**
|
|
36721
|
-
* FLAT org-scoped directory, alongside (not instead of) `channels`. It is the only
|
|
36722
|
-
* place an integration-less agent can appear — see `CollabOrgAgent` — and therefore
|
|
36723
|
-
* the authorization input for channel-free A2A. `default([])` keeps a snapshot from
|
|
36724
|
-
* an older CP (which advertises no `agent-directory-org-scope-v1`) decodable.
|
|
36725
|
-
*/
|
|
36726
|
-
agents: array(CollabOrgAgent).default([]),
|
|
36727
|
-
/**
|
|
36728
|
-
* §6.1 origin-kind classification for the platform ids the EMITTER knows — how an
|
|
36729
|
-
* older peer classifies an id a newer CP introduces (its own built-in seed only
|
|
36730
|
-
* covers ids its build shipped with). Consumers overlay these entries on their
|
|
36731
|
-
* seed; an id classified by neither defaults to `'chat'`, the fail-closed answer
|
|
36732
|
-
* wherever placements matter (`coordsDecision`). Both fields read as open strings
|
|
36733
|
-
* per the S1a rule. `default([])` keeps a pre-S1b snapshot decodable.
|
|
36734
|
-
*/
|
|
36735
|
-
platformKinds: array(object({
|
|
36736
|
-
platformId: string().min(1),
|
|
36737
|
-
originKind: string().min(1)
|
|
36738
|
-
})).default([])
|
|
36739
|
-
});
|
|
36740
|
-
//#endregion
|
|
36741
|
-
//#region ../protocol/dist/frames/hook.js
|
|
36742
|
-
/** Decimal wire form for Prisma/GitHub bigint values. */
|
|
36743
|
-
const HookBigIntString = string().regex(/^(?:0|[1-9]\d*)$/);
|
|
36744
|
-
/** The highest formal-review event one hook permits. */
|
|
36745
|
-
const HookReviewPolicy = _enum([
|
|
36746
|
-
"off",
|
|
36747
|
-
"comment",
|
|
36748
|
-
"request_changes",
|
|
36749
|
-
"full"
|
|
36750
|
-
]);
|
|
36751
|
-
/** External run-reporting transport. `status` is reserved for the later R3. */
|
|
36752
|
-
const HookReportingMode = _enum([
|
|
36753
|
-
"off",
|
|
36754
|
-
"check",
|
|
36755
|
-
"status"
|
|
36756
|
-
]);
|
|
36757
|
-
/** R2a only admits informational; `required` remains a fail-closed future mode. */
|
|
36758
|
-
const HookGateMode = _enum(["informational", "required"]);
|
|
36759
|
-
/**
|
|
36760
|
-
* Exact config + dispatch identity captured when the CP compiles a hook fire.
|
|
36761
|
-
*
|
|
36762
|
-
* The relay-facing frames expose these fields individually at top level so an
|
|
36763
|
-
* older CP/relay can omit them without making the whole fire undecodable. A
|
|
36764
|
-
* consumer MUST have every field before enabling review/reporting; absence is
|
|
36765
|
-
* not filled with a revision and therefore fails closed. Action-time RPCs use
|
|
36766
|
-
* this complete object so a partially rolled-out tuple cannot authorize an
|
|
36767
|
-
* effect.
|
|
36768
|
-
*/
|
|
36769
|
-
const HookConfigSnapshot = object({
|
|
36770
|
-
configRevision: HookBigIntString,
|
|
36771
|
-
dispatchRevision: HookBigIntString,
|
|
36772
|
-
dispatchDaemonId: string().uuid(),
|
|
36773
|
-
reviewPolicy: HookReviewPolicy,
|
|
36774
|
-
reportingMode: HookReportingMode,
|
|
36775
|
-
gateMode: HookGateMode
|
|
36776
|
-
});
|
|
36777
|
-
/** Optional top-level form used only on rolling-compatible delivery frames. */
|
|
36778
|
-
const OptionalHookConfigSnapshot = HookConfigSnapshot.partial();
|
|
36779
|
-
/**
|
|
36780
|
-
* Trusted, body-free GitHub subject/revision metadata. It is deliberately
|
|
36781
|
-
* separate from HookContext: HookContext contains attacker-authored prompt
|
|
36782
|
-
* excerpts, whereas this object is cut from a signature-verified payload and
|
|
36783
|
-
* fenced to the CP-compiled numeric repo/installation rule.
|
|
36784
|
-
*
|
|
36785
|
-
* `headSha` is absent for PR issue_comment deliveries because GitHub omits the
|
|
36786
|
-
* revision there; the daemon resolves it before `hook/start`. R2a informational
|
|
36787
|
-
* checks use `reportSha=headSha` once known. Review-comment deliveries may also
|
|
36788
|
-
* identify the triggering comment and its normalized thread root; both remain
|
|
36789
|
-
* optional so mixed-version relay/daemon rollouts continue to decode.
|
|
36790
|
-
*/
|
|
36791
|
-
const GithubHookMetadata = object({
|
|
36792
|
-
repoId: HookBigIntString,
|
|
36793
|
-
repoFullName: string().min(1),
|
|
36794
|
-
sourceInstallationId: HookBigIntString,
|
|
36795
|
-
subjectKind: _enum(["issue", "pull_request"]),
|
|
36796
|
-
pullNumber: number$1().int().positive().optional(),
|
|
36797
|
-
headSha: string().min(1).optional(),
|
|
36798
|
-
baseSha: string().min(1).optional(),
|
|
36799
|
-
reportSha: string().min(1).optional(),
|
|
36800
|
-
headRepoFullName: string().min(1).optional(),
|
|
36801
|
-
mergeCommitSha: string().min(1).optional(),
|
|
36802
|
-
isDraft: boolean().optional(),
|
|
36803
|
-
baseChanged: boolean().optional(),
|
|
36804
|
-
explicitReviewRequest: boolean().optional(),
|
|
36805
|
-
reviewCommentId: HookBigIntString.optional(),
|
|
36806
|
-
reviewThreadRootCommentId: HookBigIntString.optional()
|
|
36807
|
-
}).superRefine((value, ctx) => {
|
|
36808
|
-
if (value.subjectKind === "pull_request" && value.pullNumber === void 0) ctx.addIssue({
|
|
36809
|
-
code: "custom",
|
|
36810
|
-
path: ["pullNumber"],
|
|
36811
|
-
message: "pullNumber is required for a pull_request subject"
|
|
36812
|
-
});
|
|
36813
|
-
if (value.reportSha !== void 0 && value.headSha === void 0) ctx.addIssue({
|
|
36814
|
-
code: "custom",
|
|
36815
|
-
path: ["reportSha"],
|
|
36816
|
-
message: "reportSha requires an authoritative headSha"
|
|
36817
|
-
});
|
|
36818
|
-
if (value.reportSha !== void 0 && value.headSha !== void 0 && value.reportSha !== value.headSha) ctx.addIssue({
|
|
36819
|
-
code: "custom",
|
|
36820
|
-
path: ["reportSha"],
|
|
36821
|
-
message: "R2a reports only the authoritative pull head SHA"
|
|
36822
|
-
});
|
|
36823
|
-
});
|
|
36824
|
-
const HookReviewEvent = _enum([
|
|
36825
|
-
"COMMENT",
|
|
36826
|
-
"REQUEST_CHANGES",
|
|
36827
|
-
"APPROVE"
|
|
36828
|
-
]);
|
|
36829
|
-
const HookReviewVerdict = _enum([
|
|
36830
|
-
"pass",
|
|
36831
|
-
"fail",
|
|
36832
|
-
"neutral"
|
|
36833
|
-
]);
|
|
36834
|
-
/** Short machine code only; raw GitHub/runtime exception text never crosses to reporting. */
|
|
36835
|
-
const HookReviewResultCode = string().min(1).max(100).regex(/^[a-z0-9_:-]+$/);
|
|
36836
|
-
/**
|
|
36837
|
-
* Body-free outcome of one reserved formal-review attempt.
|
|
36838
|
-
*
|
|
36839
|
-
* `not_submitted` is only legal after a deterministic no-effect failure and
|
|
36840
|
-
* lets the CP release the reservation. An uncertain POST remains `ambiguous`
|
|
36841
|
-
* until marker reconciliation proves whether GitHub created it.
|
|
36842
|
-
*/
|
|
36843
|
-
const HookReviewResult = discriminatedUnion("state", [
|
|
36844
|
-
object({
|
|
36845
|
-
state: literal("submitted"),
|
|
36846
|
-
reviewId: string().min(1),
|
|
36847
|
-
event: HookReviewEvent,
|
|
36848
|
-
verdict: HookReviewVerdict,
|
|
36849
|
-
commitId: string().min(1)
|
|
36850
|
-
}),
|
|
36851
|
-
object({
|
|
36852
|
-
state: literal("not_submitted"),
|
|
36853
|
-
code: HookReviewResultCode
|
|
36854
|
-
}),
|
|
36855
|
-
object({
|
|
36856
|
-
state: literal("ambiguous"),
|
|
36857
|
-
code: HookReviewResultCode
|
|
36858
|
-
})
|
|
36859
|
-
]);
|
|
36860
|
-
/** Body-free identity of the daemon's one fallback GitHub comment. */
|
|
36861
|
-
const GithubPublishedComment = object({
|
|
36862
|
-
kind: _enum(["issue_comment", "review_comment"]),
|
|
36863
|
-
commentId: HookBigIntString
|
|
36864
|
-
});
|
|
36865
|
-
object({
|
|
36866
|
-
source: _enum(["webhook", "github"]),
|
|
36867
|
-
event: string().optional(),
|
|
36868
|
-
action: string().optional(),
|
|
36869
|
-
repo: string().optional(),
|
|
36870
|
-
number: number$1().int().optional(),
|
|
36871
|
-
title: string().optional(),
|
|
36872
|
-
senderLogin: string().optional(),
|
|
36873
|
-
senderAvatarUrl: string().url().optional(),
|
|
36874
|
-
authorAssociation: string().optional(),
|
|
36875
|
-
labels: array(string()).optional(),
|
|
36876
|
-
htmlUrl: string().optional(),
|
|
36877
|
-
bodyExcerpt: string().optional(),
|
|
36878
|
-
body: string().optional(),
|
|
36879
|
-
truncated: boolean().optional()
|
|
36880
|
-
});
|
|
36881
|
-
object({
|
|
36882
|
-
hookId: string().uuid(),
|
|
36883
|
-
agentId: string().uuid(),
|
|
36884
|
-
deliveryKey: string().min(1),
|
|
36885
|
-
...OptionalHookConfigSnapshot.shape,
|
|
36886
|
-
event: string().min(1).optional(),
|
|
36887
|
-
github: GithubHookMetadata.optional(),
|
|
36888
|
-
status: _enum(["success", "failed"]),
|
|
36889
|
-
durationMs: number$1().int().nonnegative().optional(),
|
|
36890
|
-
sessionId: string().optional(),
|
|
36891
|
-
reason: string().optional(),
|
|
36892
|
-
reviewAttemptId: string().uuid().optional(),
|
|
36893
|
-
reviewResult: HookReviewResult.optional(),
|
|
36894
|
-
publishedComment: GithubPublishedComment.optional()
|
|
36895
|
-
}).superRefine((report, ctx) => {
|
|
36896
|
-
if (report.reviewAttemptId === void 0 !== (report.reviewResult === void 0)) ctx.addIssue({
|
|
36897
|
-
code: "custom",
|
|
36898
|
-
path: report.reviewAttemptId === void 0 ? ["reviewAttemptId"] : ["reviewResult"],
|
|
36899
|
-
message: "reviewAttemptId and reviewResult must be reported together"
|
|
36900
|
-
});
|
|
36901
|
-
if (report.publishedComment && report.reviewResult?.state === "submitted") ctx.addIssue({
|
|
36902
|
-
code: "custom",
|
|
36903
|
-
path: ["publishedComment"],
|
|
36904
|
-
message: "a submitted formal review and fallback comment are mutually exclusive"
|
|
36905
|
-
});
|
|
36906
|
-
});
|
|
36907
|
-
object({
|
|
36908
|
-
hookId: string().uuid(),
|
|
36909
|
-
agentId: string().uuid(),
|
|
36910
|
-
deliveryKey: string().min(1),
|
|
36911
|
-
sessionId: string().min(1).optional(),
|
|
36912
|
-
event: string().min(1).optional(),
|
|
36913
|
-
github: GithubHookMetadata,
|
|
36914
|
-
...HookConfigSnapshot.shape
|
|
36915
|
-
});
|
|
36916
|
-
object({ accepted: literal(true) });
|
|
36917
|
-
object({
|
|
36918
|
-
hookId: string().uuid(),
|
|
36919
|
-
deliveryKey: string().min(1),
|
|
36920
|
-
attemptId: string().uuid(),
|
|
36921
|
-
requestedEvent: HookReviewEvent,
|
|
36922
|
-
requestedVerdict: HookReviewVerdict,
|
|
36923
|
-
snapshot: HookConfigSnapshot
|
|
36924
|
-
});
|
|
36925
|
-
object({
|
|
36926
|
-
attemptId: string().uuid(),
|
|
36927
|
-
token: string().min(1),
|
|
36928
|
-
ttlSec: number$1().int().positive(),
|
|
36929
|
-
expiresAt: string().datetime(),
|
|
36930
|
-
repoId: HookBigIntString,
|
|
36931
|
-
repoFullName: string().min(1),
|
|
36932
|
-
pullNumber: number$1().int().positive(),
|
|
36933
|
-
expectedHeadSha: string().min(1),
|
|
36934
|
-
expectedBaseSha: string().min(1)
|
|
36935
|
-
});
|
|
36936
|
-
object({
|
|
36937
|
-
hookId: string().uuid(),
|
|
36938
|
-
deliveryKey: string().min(1),
|
|
36939
|
-
attemptId: string().uuid(),
|
|
36940
|
-
snapshot: HookConfigSnapshot,
|
|
36941
|
-
result: HookReviewResult
|
|
36942
|
-
});
|
|
36943
|
-
object({ accepted: literal(true) });
|
|
36944
|
-
//#endregion
|
|
36945
|
-
//#region ../protocol/dist/frames/remote-mcp.js
|
|
36946
|
-
/** Non-secret entitlement carried CP → relay → daemon after webchat verification. */
|
|
36947
|
-
const WebchatRemoteMcpEntitlement = object({
|
|
36948
|
-
authorityId: string().uuid(),
|
|
36949
|
-
authorityGeneration: number$1().int().positive(),
|
|
36950
|
-
expiresAt: string().datetime()
|
|
36951
|
-
}).strict();
|
|
36952
|
-
const DescriptorFence = object({
|
|
36953
|
-
authorityId: string().uuid(),
|
|
36954
|
-
authorityGeneration: number$1().int().positive(),
|
|
36955
|
-
conversationId: string().uuid(),
|
|
36956
|
-
descriptorInstanceId: string().uuid(),
|
|
36957
|
-
grantRevision: number$1().int().positive()
|
|
36958
|
-
}).strict();
|
|
36959
|
-
object({
|
|
36960
|
-
authorityId: string().uuid(),
|
|
36961
|
-
authorityGeneration: number$1().int().positive(),
|
|
36962
|
-
conversationId: string().uuid(),
|
|
36963
|
-
descriptorInstanceId: string().uuid()
|
|
36964
|
-
}).strict();
|
|
36965
|
-
DescriptorFence.extend({
|
|
36966
|
-
grantId: string().uuid(),
|
|
36967
|
-
token: string().min(32),
|
|
36968
|
-
expiresAt: string().datetime(),
|
|
36969
|
-
mcpUrl: string().url()
|
|
36970
|
-
}).strict();
|
|
36971
|
-
DescriptorFence.extend({ grantId: string().uuid() }).strict().extend({ activated: boolean() }).strict();
|
|
36972
|
-
object({
|
|
36973
|
-
authorityId: string().uuid(),
|
|
36974
|
-
authorityGeneration: number$1().int().positive(),
|
|
36975
|
-
conversationId: string().uuid(),
|
|
36976
|
-
reason: _enum([
|
|
36977
|
-
"session_closed",
|
|
36978
|
-
"session_expired",
|
|
36979
|
-
"agent_detached",
|
|
36980
|
-
"feature_disabled",
|
|
36981
|
-
"security"
|
|
36982
|
-
])
|
|
36983
|
-
}).strict().pick({
|
|
36984
|
-
authorityId: true,
|
|
36985
|
-
authorityGeneration: true,
|
|
36986
|
-
conversationId: true
|
|
36987
|
-
}).extend({ revoked: boolean() }).strict();
|
|
36988
|
-
//#endregion
|
|
36989
|
-
//#region ../protocol/dist/frames/relay-cp.js
|
|
36990
|
-
const RcAuth = object({
|
|
36991
|
-
method: _enum(["token", "apikey"]),
|
|
36992
|
-
credential: string().min(1)
|
|
36993
|
-
});
|
|
36994
|
-
const RcDeploymentConfig = object({
|
|
36995
|
-
revision: number$1().int().nonnegative(),
|
|
36996
|
-
githubWebhookSecret: string().min(1).optional()
|
|
36997
|
-
});
|
|
36998
|
-
const RcAuthOk = object({
|
|
36999
|
-
heartbeatSec: number$1().int(),
|
|
37000
|
-
serverTime: string().datetime(),
|
|
37001
|
-
deploymentConfig: RcDeploymentConfig.optional()
|
|
37002
|
-
});
|
|
37003
|
-
const RcRegister = object({
|
|
37004
|
-
name: string().min(1),
|
|
37005
|
-
daemonUrl: string().min(1)
|
|
37006
|
-
});
|
|
37007
|
-
const RcRegistered = object({ relayId: string().uuid() });
|
|
37008
|
-
const RcHeartbeat = object({});
|
|
37009
|
-
const RcVerify = discriminatedUnion("kind", [object({
|
|
37010
|
-
kind: literal("daemon-key"),
|
|
37011
|
-
credential: string().min(1)
|
|
37012
|
-
}), object({
|
|
37013
|
-
kind: literal("webchat-token"),
|
|
37014
|
-
credential: string().min(1),
|
|
37015
|
-
conversationBinding: literal("v1").optional()
|
|
37016
|
-
})]);
|
|
37017
|
-
const RcWebchatParticipant = object({
|
|
37018
|
-
agentId: string().uuid(),
|
|
37019
|
-
daemonId: string().uuid().optional(),
|
|
37020
|
-
primary: boolean().optional()
|
|
37021
|
-
});
|
|
37022
|
-
const RcVerifyResult = object({
|
|
37023
|
-
ok: boolean(),
|
|
37024
|
-
reason: string().optional(),
|
|
37025
|
-
orgId: string().optional(),
|
|
37026
|
-
daemonId: string().uuid().optional(),
|
|
37027
|
-
userId: string().optional(),
|
|
37028
|
-
user: string().optional(),
|
|
37029
|
-
agentId: string().uuid().optional(),
|
|
37030
|
-
conversationId: string().uuid().optional(),
|
|
37031
|
-
participants: array(RcWebchatParticipant).max(16).optional(),
|
|
37032
|
-
remoteMcp: WebchatRemoteMcpEntitlement.optional()
|
|
37033
|
-
});
|
|
37034
|
-
const RcGithubHookFence = object({
|
|
37035
|
-
hookId: string().uuid(),
|
|
37036
|
-
configRevision: HookBigIntString,
|
|
37037
|
-
dispatchRevision: HookBigIntString
|
|
37038
|
-
}).strict();
|
|
37039
|
-
const RcGithubCommentAuthz = object({
|
|
37040
|
-
hookId: string().uuid(),
|
|
37041
|
-
installationId: string().regex(/^[1-9]\d*$/),
|
|
37042
|
-
repoId: string().regex(/^[1-9]\d*$/),
|
|
37043
|
-
repoFullName: string().regex(/^[^/\s]+\/[^/\s]+$/),
|
|
37044
|
-
senderLogin: string().min(1),
|
|
37045
|
-
subjectAuthorLogin: string().min(1).optional(),
|
|
37046
|
-
configRevision: HookBigIntString,
|
|
37047
|
-
dispatchRevision: HookBigIntString,
|
|
37048
|
-
siblingFences: array(RcGithubHookFence).min(1).optional()
|
|
37049
|
-
}).strict();
|
|
37050
|
-
const RcGithubCommentAuthzResult = object({ allowed: boolean() }).strict();
|
|
37051
|
-
const GithubNumericId = string().regex(/^[1-9]\d*$/);
|
|
37052
|
-
const RcGithubRerequest = union([object({
|
|
37053
|
-
checkRunId: GithubNumericId,
|
|
37054
|
-
repoId: GithubNumericId,
|
|
37055
|
-
headSha: string().min(1),
|
|
37056
|
-
deliveryKey: string().min(1).max(200),
|
|
37057
|
-
includeBaseSha: literal(true).optional()
|
|
37058
|
-
}).strict(), object({
|
|
37059
|
-
scope: literal("suite"),
|
|
37060
|
-
appId: GithubNumericId,
|
|
37061
|
-
installationId: GithubNumericId,
|
|
37062
|
-
repoId: GithubNumericId,
|
|
37063
|
-
headSha: string().min(1),
|
|
37064
|
-
deliveryKey: string().min(1).max(200)
|
|
37065
|
-
}).strict()]);
|
|
37066
|
-
const RcGithubRerequestTarget = object({
|
|
37067
|
-
hookId: string().uuid(),
|
|
37068
|
-
pullNumber: number$1().int().positive(),
|
|
37069
|
-
baseSha: string().min(1),
|
|
37070
|
-
configRevision: HookBigIntString,
|
|
37071
|
-
dispatchRevision: HookBigIntString
|
|
37072
|
-
}).strict();
|
|
37073
|
-
const RcGithubRerequestResult = union([
|
|
37074
|
-
object({ allowed: literal(false) }).strict(),
|
|
37075
|
-
object({
|
|
37076
|
-
allowed: literal(true),
|
|
37077
|
-
hookId: string().uuid(),
|
|
37078
|
-
pullNumber: number$1().int().positive(),
|
|
37079
|
-
baseSha: string().min(1).optional(),
|
|
37080
|
-
configRevision: HookBigIntString,
|
|
37081
|
-
dispatchRevision: HookBigIntString
|
|
37082
|
-
}).strict(),
|
|
37083
|
-
object({
|
|
37084
|
-
allowed: literal(true),
|
|
37085
|
-
targets: array(RcGithubRerequestTarget).min(1)
|
|
37086
|
-
}).strict()
|
|
37087
|
-
]);
|
|
37088
|
-
const RcHookAssign = object({
|
|
37089
|
-
hookId: string().uuid(),
|
|
37090
|
-
kind: _enum(["webhook", "github"]),
|
|
37091
|
-
agentId: string().uuid(),
|
|
37092
|
-
daemonId: string().uuid(),
|
|
37093
|
-
...OptionalHookConfigSnapshot.shape,
|
|
37094
|
-
sessionMode: _enum([
|
|
37095
|
-
"perDelivery",
|
|
37096
|
-
"perThread",
|
|
37097
|
-
"shared"
|
|
37098
|
-
]),
|
|
37099
|
-
target: CronTarget.optional(),
|
|
37100
|
-
webhook: object({
|
|
37101
|
-
urlToken: string().min(1),
|
|
37102
|
-
hmacSecret: string().optional()
|
|
37103
|
-
}).optional(),
|
|
37104
|
-
github: object({
|
|
37105
|
-
repoId: string(),
|
|
37106
|
-
repoFullName: string(),
|
|
37107
|
-
sessionKeyPrefix: string().min(1).optional(),
|
|
37108
|
-
events: array(string()),
|
|
37109
|
-
labelFilter: array(string()),
|
|
37110
|
-
commentFamilies: array(_enum(["issues", "pull_request"])).optional(),
|
|
37111
|
-
mentionOnly: boolean(),
|
|
37112
|
-
appSlug: string().optional(),
|
|
37113
|
-
agentName: string().optional(),
|
|
37114
|
-
installationIds: array(string())
|
|
37115
|
-
}).optional()
|
|
37116
|
-
}).superRefine((rule, ctx) => {
|
|
37117
|
-
if (rule.dispatchDaemonId !== void 0 && rule.dispatchDaemonId !== rule.daemonId) ctx.addIssue({
|
|
37118
|
-
code: "custom",
|
|
37119
|
-
path: ["dispatchDaemonId"],
|
|
37120
|
-
message: "dispatchDaemonId must equal daemonId on a compiled rule"
|
|
37121
|
-
});
|
|
37122
|
-
});
|
|
37123
|
-
const RcHookRemove = object({ hookId: string().uuid() });
|
|
37124
|
-
const RcRunReport = object({
|
|
37125
|
-
hookId: string().uuid(),
|
|
37126
|
-
deliveryKey: string().min(1),
|
|
37127
|
-
firedAt: string().datetime(),
|
|
37128
|
-
agentId: string().uuid(),
|
|
37129
|
-
daemonId: string().uuid().optional(),
|
|
37130
|
-
...OptionalHookConfigSnapshot.shape,
|
|
37131
|
-
event: string().min(1).optional(),
|
|
37132
|
-
github: GithubHookMetadata.optional(),
|
|
37133
|
-
status: _enum(["accepted", "failed"]),
|
|
37134
|
-
reason: string().optional()
|
|
37135
|
-
}).superRefine((report, ctx) => {
|
|
37136
|
-
if (report.daemonId !== void 0 && report.dispatchDaemonId !== void 0 && report.daemonId !== report.dispatchDaemonId) ctx.addIssue({
|
|
37137
|
-
code: "custom",
|
|
37138
|
-
path: ["dispatchDaemonId"],
|
|
37139
|
-
message: "dispatchDaemonId must equal daemonId on a delivery report"
|
|
37140
|
-
});
|
|
37141
|
-
});
|
|
37142
|
-
const RcGithubInstallation = object({
|
|
37143
|
-
installationId: string().min(1),
|
|
37144
|
-
action: string().min(1)
|
|
37145
|
-
});
|
|
37146
|
-
const RcDaemonRevoke = object({ daemonId: string().uuid() });
|
|
37147
36284
|
/** App-level Slack message shortcut for opening the controls of the session that
|
|
37148
36285
|
* owns the selected message's conversation. Direct apps receive it over Socket
|
|
37149
|
-
* Mode; shared apps receive the same callback through the relay HTTP edge.
|
|
36286
|
+
* Mode; shared apps receive the same callback through the relay HTTP edge.
|
|
36287
|
+
*
|
|
36288
|
+
* Declared to Slack by {@link buildSlackAppManifest} below, which is why it lives
|
|
36289
|
+
* here rather than beside the runtime Block Kit action ids in `frames/relay-cp.ts`:
|
|
36290
|
+
* those name controls on messages we post, this one names a manifest feature. */
|
|
37150
36291
|
const SLACK_MANAGE_SESSION_SHORTCUT_CALLBACK_ID = "ac_manage_session";
|
|
37151
|
-
/** One short choice from the compact Slack status overflow. Slack caps option
|
|
37152
|
-
* values at 150 characters; the longer session target rides in `block_id`. */
|
|
37153
|
-
const SlackStatusOverflowAction = _enum([
|
|
37154
|
-
"switch-agent",
|
|
37155
|
-
"manage",
|
|
37156
|
-
"cancel"
|
|
37157
|
-
]);
|
|
37158
|
-
object({
|
|
37159
|
-
v: literal(1),
|
|
37160
|
-
action: SlackStatusOverflowAction,
|
|
37161
|
-
target: string().min(1)
|
|
37162
|
-
}).strict();
|
|
37163
|
-
object({
|
|
37164
|
-
v: literal(1),
|
|
37165
|
-
agentId: string().min(1),
|
|
37166
|
-
integrationId: string().min(1),
|
|
37167
|
-
sessionKey: string().min(1)
|
|
37168
|
-
}).strict();
|
|
37169
|
-
const AttributedRoute = object({
|
|
37170
|
-
agentId: string().uuid(),
|
|
37171
|
-
daemonId: string().uuid(),
|
|
37172
|
-
integrationId: string().uuid(),
|
|
37173
|
-
scope: object({
|
|
37174
|
-
channel: string().optional(),
|
|
37175
|
-
thread: string().optional()
|
|
37176
|
-
}).optional(),
|
|
37177
|
-
match: BindMatch
|
|
37178
|
-
});
|
|
37179
|
-
const RcBotSecrets = union([
|
|
37180
|
-
object({
|
|
37181
|
-
botToken: string(),
|
|
37182
|
-
signingSecret: string()
|
|
37183
|
-
}).catchall(unknown()),
|
|
37184
|
-
object({
|
|
37185
|
-
verificationToken: string(),
|
|
37186
|
-
encryptKey: string().optional()
|
|
37187
|
-
}).catchall(unknown()),
|
|
37188
|
-
record$1(string(), unknown())
|
|
37189
|
-
]);
|
|
37190
|
-
const RcAgentDirEntry = object({
|
|
37191
|
-
agentId: string().uuid(),
|
|
37192
|
-
name: string(),
|
|
37193
|
-
daemonId: string().uuid(),
|
|
37194
|
-
integrationId: string().uuid().optional()
|
|
37195
|
-
});
|
|
37196
|
-
const RcBotAssign = object({
|
|
37197
|
-
botId: string().uuid(),
|
|
37198
|
-
platform: Platform,
|
|
37199
|
-
originKind: string().min(1).optional(),
|
|
37200
|
-
credentialRevision: number$1().int().nonnegative().optional(),
|
|
37201
|
-
secrets: RcBotSecrets,
|
|
37202
|
-
ingress: unknown().optional(),
|
|
37203
|
-
members: array(object({
|
|
37204
|
-
daemonId: string().uuid(),
|
|
37205
|
-
agentIds: array(string().uuid())
|
|
37206
|
-
})),
|
|
37207
|
-
agents: array(RcAgentDirEntry).default([]),
|
|
37208
|
-
routes: array(AttributedRoute),
|
|
37209
|
-
defaultAgentId: string().uuid().optional(),
|
|
37210
|
-
defaultDaemonId: string().uuid().optional(),
|
|
37211
|
-
gatedAgentIds: array(string().uuid()).default([]),
|
|
37212
|
-
mutedChannels: array(string()).default([]),
|
|
37213
|
-
gatedOffChannels: array(string()).default([]),
|
|
37214
|
-
noticeAuthority: string().uuid().optional(),
|
|
37215
|
-
noticedDmConversations: array(string()).default([])
|
|
37216
|
-
});
|
|
37217
|
-
const RcBotUnassign = object({
|
|
37218
|
-
botId: string().uuid(),
|
|
37219
|
-
credentialRevision: number$1().int().nonnegative().optional()
|
|
37220
|
-
});
|
|
37221
|
-
const RcRoutes = object({
|
|
37222
|
-
botId: string().uuid(),
|
|
37223
|
-
members: array(object({
|
|
37224
|
-
daemonId: string().uuid(),
|
|
37225
|
-
agentIds: array(string().uuid())
|
|
37226
|
-
})),
|
|
37227
|
-
agents: array(RcAgentDirEntry).default([]),
|
|
37228
|
-
routes: array(AttributedRoute),
|
|
37229
|
-
defaultAgentId: string().uuid().optional(),
|
|
37230
|
-
defaultDaemonId: string().uuid().optional(),
|
|
37231
|
-
gatedAgentIds: array(string().uuid()).default([]),
|
|
37232
|
-
mutedChannels: array(string()).default([]),
|
|
37233
|
-
gatedOffChannels: array(string()).default([]),
|
|
37234
|
-
noticeAuthority: string().uuid().optional(),
|
|
37235
|
-
noticedDmConversations: array(string()).default([])
|
|
37236
|
-
});
|
|
37237
|
-
const RcAssign = object({
|
|
37238
|
-
botId: string().uuid(),
|
|
37239
|
-
sessionKey: string().min(1),
|
|
37240
|
-
agentId: string().uuid(),
|
|
37241
|
-
daemonId: string().uuid()
|
|
37242
|
-
});
|
|
37243
|
-
const RcParticipantAssign = object({
|
|
37244
|
-
botId: string().uuid(),
|
|
37245
|
-
sessionKey: string().min(1),
|
|
37246
|
-
agentId: string().uuid(),
|
|
37247
|
-
daemonId: string().uuid()
|
|
37248
|
-
});
|
|
37249
|
-
const RcSetChannelAgent = object({
|
|
37250
|
-
botId: string().uuid(),
|
|
37251
|
-
channelId: string().min(1),
|
|
37252
|
-
agentId: string().uuid()
|
|
37253
|
-
});
|
|
37254
|
-
const RcBotChannels = object({
|
|
37255
|
-
botId: string().uuid(),
|
|
37256
|
-
channels: array(IntegrationChannel)
|
|
37257
|
-
});
|
|
37258
|
-
const RcNoticePosted = object({
|
|
37259
|
-
botId: string().uuid(),
|
|
37260
|
-
channel: string().min(1)
|
|
37261
|
-
});
|
|
37262
|
-
const RcBotRevoked = object({
|
|
37263
|
-
botId: string().uuid(),
|
|
37264
|
-
reason: _enum(["app_uninstalled", "tokens_revoked"]),
|
|
37265
|
-
credentialRevision: number$1().int().nonnegative().optional(),
|
|
37266
|
-
eventAtMs: number$1().int().nonnegative().optional()
|
|
37267
|
-
});
|
|
37268
|
-
const RcBotRevokedOk = object({
|
|
37269
|
-
botId: string().uuid(),
|
|
37270
|
-
applied: boolean()
|
|
37271
|
-
});
|
|
37272
|
-
/** `type` string → payload schema for the relay↔CP wire. */
|
|
37273
|
-
const RELAY_CP_SCHEMAS = {
|
|
37274
|
-
"rc/auth": RcAuth,
|
|
37275
|
-
"rc/auth/ok": RcAuthOk,
|
|
37276
|
-
"rc/register": RcRegister,
|
|
37277
|
-
"rc/registered": RcRegistered,
|
|
37278
|
-
"rc/heartbeat": RcHeartbeat,
|
|
37279
|
-
"rc/verify": RcVerify,
|
|
37280
|
-
"rc/verify/ok": RcVerifyResult,
|
|
37281
|
-
"rc/github-comment-authz": RcGithubCommentAuthz,
|
|
37282
|
-
"rc/github-comment-authz/ok": RcGithubCommentAuthzResult,
|
|
37283
|
-
"rc/github-rerequest": RcGithubRerequest,
|
|
37284
|
-
"rc/github-rerequest/ok": RcGithubRerequestResult,
|
|
37285
|
-
"rc/hook-assign": RcHookAssign,
|
|
37286
|
-
"rc/hook-remove": RcHookRemove,
|
|
37287
|
-
"rc/run-report": RcRunReport,
|
|
37288
|
-
"rc/github-installation": RcGithubInstallation,
|
|
37289
|
-
"rc/daemon-revoke": RcDaemonRevoke,
|
|
37290
|
-
"rc/bot-assign": RcBotAssign,
|
|
37291
|
-
"rc/bot-unassign": RcBotUnassign,
|
|
37292
|
-
"rc/routes": RcRoutes,
|
|
37293
|
-
"rc/assign": RcAssign,
|
|
37294
|
-
"rc/participant-assign": RcParticipantAssign,
|
|
37295
|
-
"rc/set-channel-agent": RcSetChannelAgent,
|
|
37296
|
-
"rc/bot-channels": RcBotChannels,
|
|
37297
|
-
"rc/bot-conversation": object({
|
|
37298
|
-
botId: string().uuid(),
|
|
37299
|
-
conversation: IntegrationChannel
|
|
37300
|
-
}),
|
|
37301
|
-
"rc/bot-revoked": RcBotRevoked,
|
|
37302
|
-
"rc/bot-revoked/ok": RcBotRevokedOk,
|
|
37303
|
-
"rc/notice-posted": RcNoticePosted,
|
|
37304
|
-
"rc/thread-assign": object({
|
|
37305
|
-
botId: string().uuid(),
|
|
37306
|
-
sessionKey: string().min(1),
|
|
37307
|
-
agentId: string().uuid(),
|
|
37308
|
-
daemonId: string().uuid()
|
|
37309
|
-
}),
|
|
37310
|
-
"rc/thread-participant": object({
|
|
37311
|
-
botId: string().uuid(),
|
|
37312
|
-
sessionKey: string().min(1),
|
|
37313
|
-
agentId: string().uuid(),
|
|
37314
|
-
daemonId: string().uuid()
|
|
37315
|
-
}),
|
|
37316
|
-
"rc/thread-lookup": object({
|
|
37317
|
-
botId: string().uuid(),
|
|
37318
|
-
sessionKey: string().min(1)
|
|
37319
|
-
}),
|
|
37320
|
-
"rc/thread-lookup/ok": object({
|
|
37321
|
-
botId: string().uuid(),
|
|
37322
|
-
sessionKey: string().min(1),
|
|
37323
|
-
target: object({
|
|
37324
|
-
agentId: string().uuid(),
|
|
37325
|
-
daemonId: string().uuid()
|
|
37326
|
-
}).nullable(),
|
|
37327
|
-
participants: array(object({
|
|
37328
|
-
agentId: string().uuid(),
|
|
37329
|
-
daemonId: string().uuid()
|
|
37330
|
-
})).default([])
|
|
37331
|
-
}),
|
|
37332
|
-
"rc/collab-routes": CollabRoutesSnapshot,
|
|
37333
|
-
"rc/mcp-assign": object({
|
|
37334
|
-
providerId: string().uuid(),
|
|
37335
|
-
upstreamUrl: string(),
|
|
37336
|
-
headers: array(object({
|
|
37337
|
-
name: string(),
|
|
37338
|
-
value: string()
|
|
37339
|
-
})).default([]),
|
|
37340
|
-
grantKeyHashes: array(string().min(1)).min(1)
|
|
37341
|
-
}),
|
|
37342
|
-
"rc/mcp-unassign": object({
|
|
37343
|
-
providerId: string().uuid(),
|
|
37344
|
-
grantKeyHash: string().optional()
|
|
37345
|
-
}),
|
|
37346
|
-
"rc/memoryconnection-assign": object({
|
|
37347
|
-
connectionId: string().uuid(),
|
|
37348
|
-
revision: number$1().int().positive(),
|
|
37349
|
-
upstreamUrl: string().url().max(2048),
|
|
37350
|
-
headers: array(object({
|
|
37351
|
-
name: string().min(1).max(128),
|
|
37352
|
-
value: string().max(16 * 1024)
|
|
37353
|
-
})).max(64).default([]),
|
|
37354
|
-
grantKeyHashes: array(string().regex(/^[a-f0-9]{64}$/)).min(1).max(64)
|
|
37355
|
-
}),
|
|
37356
|
-
"rc/memoryconnection-unassign": object({
|
|
37357
|
-
connectionId: string().uuid(),
|
|
37358
|
-
revision: number$1().int().positive(),
|
|
37359
|
-
grantKeyHash: string().regex(/^[a-f0-9]{64}$/).optional()
|
|
37360
|
-
}),
|
|
37361
|
-
error: ErrorFrame
|
|
37362
|
-
};
|
|
37363
|
-
Object.keys(RELAY_CP_SCHEMAS);
|
|
37364
|
-
discriminatedUnion("type", [
|
|
37365
|
-
frameSchema("rc/auth", RELAY_CP_SCHEMAS["rc/auth"]),
|
|
37366
|
-
frameSchema("rc/auth/ok", RELAY_CP_SCHEMAS["rc/auth/ok"]),
|
|
37367
|
-
frameSchema("rc/register", RELAY_CP_SCHEMAS["rc/register"]),
|
|
37368
|
-
frameSchema("rc/registered", RELAY_CP_SCHEMAS["rc/registered"]),
|
|
37369
|
-
frameSchema("rc/heartbeat", RELAY_CP_SCHEMAS["rc/heartbeat"]),
|
|
37370
|
-
frameSchema("rc/verify", RELAY_CP_SCHEMAS["rc/verify"]),
|
|
37371
|
-
frameSchema("rc/verify/ok", RELAY_CP_SCHEMAS["rc/verify/ok"]),
|
|
37372
|
-
frameSchema("rc/github-comment-authz", RELAY_CP_SCHEMAS["rc/github-comment-authz"]),
|
|
37373
|
-
frameSchema("rc/github-comment-authz/ok", RELAY_CP_SCHEMAS["rc/github-comment-authz/ok"]),
|
|
37374
|
-
frameSchema("rc/github-rerequest", RELAY_CP_SCHEMAS["rc/github-rerequest"]),
|
|
37375
|
-
frameSchema("rc/github-rerequest/ok", RELAY_CP_SCHEMAS["rc/github-rerequest/ok"]),
|
|
37376
|
-
frameSchema("rc/hook-assign", RELAY_CP_SCHEMAS["rc/hook-assign"]),
|
|
37377
|
-
frameSchema("rc/hook-remove", RELAY_CP_SCHEMAS["rc/hook-remove"]),
|
|
37378
|
-
frameSchema("rc/run-report", RELAY_CP_SCHEMAS["rc/run-report"]),
|
|
37379
|
-
frameSchema("rc/github-installation", RELAY_CP_SCHEMAS["rc/github-installation"]),
|
|
37380
|
-
frameSchema("rc/daemon-revoke", RELAY_CP_SCHEMAS["rc/daemon-revoke"]),
|
|
37381
|
-
frameSchema("rc/bot-assign", RELAY_CP_SCHEMAS["rc/bot-assign"]),
|
|
37382
|
-
frameSchema("rc/bot-unassign", RELAY_CP_SCHEMAS["rc/bot-unassign"]),
|
|
37383
|
-
frameSchema("rc/routes", RELAY_CP_SCHEMAS["rc/routes"]),
|
|
37384
|
-
frameSchema("rc/assign", RELAY_CP_SCHEMAS["rc/assign"]),
|
|
37385
|
-
frameSchema("rc/participant-assign", RELAY_CP_SCHEMAS["rc/participant-assign"]),
|
|
37386
|
-
frameSchema("rc/set-channel-agent", RELAY_CP_SCHEMAS["rc/set-channel-agent"]),
|
|
37387
|
-
frameSchema("rc/bot-channels", RELAY_CP_SCHEMAS["rc/bot-channels"]),
|
|
37388
|
-
frameSchema("rc/bot-conversation", RELAY_CP_SCHEMAS["rc/bot-conversation"]),
|
|
37389
|
-
frameSchema("rc/bot-revoked", RELAY_CP_SCHEMAS["rc/bot-revoked"]),
|
|
37390
|
-
frameSchema("rc/bot-revoked/ok", RELAY_CP_SCHEMAS["rc/bot-revoked/ok"]),
|
|
37391
|
-
frameSchema("rc/notice-posted", RELAY_CP_SCHEMAS["rc/notice-posted"]),
|
|
37392
|
-
frameSchema("rc/thread-assign", RELAY_CP_SCHEMAS["rc/thread-assign"]),
|
|
37393
|
-
frameSchema("rc/thread-participant", RELAY_CP_SCHEMAS["rc/thread-participant"]),
|
|
37394
|
-
frameSchema("rc/thread-lookup", RELAY_CP_SCHEMAS["rc/thread-lookup"]),
|
|
37395
|
-
frameSchema("rc/thread-lookup/ok", RELAY_CP_SCHEMAS["rc/thread-lookup/ok"]),
|
|
37396
|
-
frameSchema("rc/collab-routes", RELAY_CP_SCHEMAS["rc/collab-routes"]),
|
|
37397
|
-
frameSchema("rc/mcp-assign", RELAY_CP_SCHEMAS["rc/mcp-assign"]),
|
|
37398
|
-
frameSchema("rc/mcp-unassign", RELAY_CP_SCHEMAS["rc/mcp-unassign"]),
|
|
37399
|
-
frameSchema("rc/memoryconnection-assign", RELAY_CP_SCHEMAS["rc/memoryconnection-assign"]),
|
|
37400
|
-
frameSchema("rc/memoryconnection-unassign", RELAY_CP_SCHEMAS["rc/memoryconnection-unassign"]),
|
|
37401
|
-
frameSchema("error", RELAY_CP_SCHEMAS["error"])
|
|
37402
|
-
]);
|
|
37403
|
-
//#endregion
|
|
37404
|
-
//#region ../protocol/dist/slack-app-manifest.js
|
|
37405
36292
|
/** Public platform profile copy. Never derive this from an Agent description. */
|
|
37406
36293
|
const PLATFORM_APP_DESCRIPTION = "AI agent powered by AgentConnect.";
|
|
37407
36294
|
const SLACK_BOT_SCOPES = [
|