@agentconnect.md/daemon 1.0.0-rc.22 → 1.0.0-rc.23
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 +547 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -12,7 +12,6 @@ import { createInterface } from "node:readline";
|
|
|
12
12
|
import { freemem, homedir, hostname, loadavg, totalmem, type } from "node:os";
|
|
13
13
|
import { spawn as spawn$1 } from "child_process";
|
|
14
14
|
import { Readable, Writable } from "node:stream";
|
|
15
|
-
import { MAX_FRAME_BYTES, buildEnvelope, decodeEnvelope, encode, isFrame } from "@agentconnect.md/protocol";
|
|
16
15
|
import { randomUUID } from "node:crypto";
|
|
17
16
|
import { lstat, open, readdir, realpath, stat as stat$1 } from "node:fs/promises";
|
|
18
17
|
import { DatabaseSync } from "node:sqlite";
|
|
@@ -16872,6 +16871,553 @@ async function runChat(opts) {
|
|
|
16872
16871
|
//#region src/version.ts
|
|
16873
16872
|
const DAEMON_VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
16874
16873
|
//#endregion
|
|
16874
|
+
//#region ../protocol/dist/envelope.js
|
|
16875
|
+
/**
|
|
16876
|
+
* The protocol envelope — every frame, both directions, is wrapped in this.
|
|
16877
|
+
* Mirrors daemon-cp-ws-protocol.md §1.1.
|
|
16878
|
+
*
|
|
16879
|
+
* `payload` is left as `unknown` here and validated by the per-type schema in
|
|
16880
|
+
* `frames/*` via `FRAME_SCHEMAS[type]` (see `frame.ts`). This two-step parse is
|
|
16881
|
+
* what lets the codec answer an unknown `type` with `UNKNOWN_FRAME` (a REP)
|
|
16882
|
+
* instead of a hard close — forward-compat, protocol §1.
|
|
16883
|
+
*/
|
|
16884
|
+
const Envelope = object({
|
|
16885
|
+
v: literal(1),
|
|
16886
|
+
id: string().uuid(),
|
|
16887
|
+
ts: string().datetime(),
|
|
16888
|
+
type: string(),
|
|
16889
|
+
corr: string().uuid().optional(),
|
|
16890
|
+
payload: unknown()
|
|
16891
|
+
});
|
|
16892
|
+
object({
|
|
16893
|
+
epoch: number().int(),
|
|
16894
|
+
seq: number().int().optional(),
|
|
16895
|
+
agentId: string().uuid().optional(),
|
|
16896
|
+
launchId: string().uuid().optional()
|
|
16897
|
+
});
|
|
16898
|
+
/** The all-zero UUID used when a frame is malformed past the point of reading `id`. */
|
|
16899
|
+
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
16900
|
+
//#endregion
|
|
16901
|
+
//#region ../protocol/dist/frames/auth.js
|
|
16902
|
+
/**
|
|
16903
|
+
* Auth & identity — protocol §3.1 / §3.2.
|
|
16904
|
+
*
|
|
16905
|
+
* `auth` is the first frame after the socket opens. `auth/ok` carries the
|
|
16906
|
+
* minted `sessionEpoch` (the global fencing token), heartbeat cadence, and the
|
|
16907
|
+
* resume verdict.
|
|
16908
|
+
*/
|
|
16909
|
+
const AuthReq = object({
|
|
16910
|
+
apiKey: string(),
|
|
16911
|
+
daemonId: string().uuid().optional(),
|
|
16912
|
+
machineId: string().uuid().optional(),
|
|
16913
|
+
attestation: string().optional(),
|
|
16914
|
+
agentVersion: string(),
|
|
16915
|
+
resume: object({
|
|
16916
|
+
lastEpoch: number().int(),
|
|
16917
|
+
lastRecvSeq: record(string(), number())
|
|
16918
|
+
}).optional()
|
|
16919
|
+
});
|
|
16920
|
+
const AuthOk = object({
|
|
16921
|
+
daemonId: string().uuid(),
|
|
16922
|
+
sessionEpoch: number().int(),
|
|
16923
|
+
heartbeatSec: number().int(),
|
|
16924
|
+
serverTime: string().datetime(),
|
|
16925
|
+
resume: object({
|
|
16926
|
+
accepted: boolean(),
|
|
16927
|
+
redeliverFromSeq: record(string(), number()).optional()
|
|
16928
|
+
}).optional()
|
|
16929
|
+
});
|
|
16930
|
+
//#endregion
|
|
16931
|
+
//#region ../protocol/dist/frames/route.js
|
|
16932
|
+
/**
|
|
16933
|
+
* Routing & orchestration (C→D control) — protocol §5.
|
|
16934
|
+
*
|
|
16935
|
+
* `SessionKey` is the canonical session primitive shared across route/*,
|
|
16936
|
+
* agent/*, and event/session. Its canonical string form is
|
|
16937
|
+
* `${platform}:${channel}:${thread ?? "-"}`.
|
|
16938
|
+
*/
|
|
16939
|
+
const Platform = _enum(["slack", "telegram"]);
|
|
16940
|
+
const SessionKey = object({
|
|
16941
|
+
platform: Platform,
|
|
16942
|
+
channel: string(),
|
|
16943
|
+
thread: string().optional()
|
|
16944
|
+
});
|
|
16945
|
+
/** Trigger-matching rule for a binding (protocol §5.1). */
|
|
16946
|
+
const BindRule = object({ match: discriminatedUnion("kind", [
|
|
16947
|
+
object({ kind: literal("mention") }),
|
|
16948
|
+
object({ kind: literal("dm") }),
|
|
16949
|
+
object({
|
|
16950
|
+
kind: literal("keyword"),
|
|
16951
|
+
value: string()
|
|
16952
|
+
}),
|
|
16953
|
+
object({ kind: literal("auto") })
|
|
16954
|
+
]) });
|
|
16955
|
+
const RouteAssign = object({
|
|
16956
|
+
sessionKey: SessionKey,
|
|
16957
|
+
agentId: string().uuid(),
|
|
16958
|
+
workspaceId: string().uuid(),
|
|
16959
|
+
bindRules: array(BindRule).default([])
|
|
16960
|
+
});
|
|
16961
|
+
const RouteAssignAck = object({
|
|
16962
|
+
ok: boolean(),
|
|
16963
|
+
sessionKey: SessionKey,
|
|
16964
|
+
reason: string().optional()
|
|
16965
|
+
});
|
|
16966
|
+
const RouteUpdate = object({
|
|
16967
|
+
routingEpoch: number().int(),
|
|
16968
|
+
rules: array(object({
|
|
16969
|
+
match: unknown(),
|
|
16970
|
+
agentId: string().uuid()
|
|
16971
|
+
}))
|
|
16972
|
+
});
|
|
16973
|
+
/** Graceful scale-down / rebalance — protocol §5.3. */
|
|
16974
|
+
const Drain = object({
|
|
16975
|
+
scope: union([
|
|
16976
|
+
object({
|
|
16977
|
+
kind: literal("agent"),
|
|
16978
|
+
agentId: string().uuid()
|
|
16979
|
+
}),
|
|
16980
|
+
object({ kind: literal("daemon") }),
|
|
16981
|
+
object({
|
|
16982
|
+
kind: literal("session"),
|
|
16983
|
+
sessionKey: SessionKey
|
|
16984
|
+
})
|
|
16985
|
+
]),
|
|
16986
|
+
deadline: string().datetime()
|
|
16987
|
+
});
|
|
16988
|
+
const DrainProgress = object({
|
|
16989
|
+
remaining: number().int(),
|
|
16990
|
+
drained: array(SessionKey)
|
|
16991
|
+
});
|
|
16992
|
+
const DrainDone = object({ released: array(SessionKey) });
|
|
16993
|
+
//#endregion
|
|
16994
|
+
//#region ../protocol/dist/frames/cron.js
|
|
16995
|
+
/**
|
|
16996
|
+
* Cron sinks to the daemon (D5) — protocol §5.4.
|
|
16997
|
+
*
|
|
16998
|
+
* The CP owns the definition; the daemon owns firing + last-run persistence so
|
|
16999
|
+
* crons fire even when the CP is down.
|
|
17000
|
+
*/
|
|
17001
|
+
const CronUpsert = object({
|
|
17002
|
+
cronId: string().uuid(),
|
|
17003
|
+
schedule: string(),
|
|
17004
|
+
target: object({ channel: string() }),
|
|
17005
|
+
trigger: string(),
|
|
17006
|
+
enabled: boolean().default(true)
|
|
17007
|
+
});
|
|
17008
|
+
const CronRemove = object({ cronId: string().uuid() });
|
|
17009
|
+
//#endregion
|
|
17010
|
+
//#region ../protocol/dist/frames/secrets.js
|
|
17011
|
+
/**
|
|
17012
|
+
* Secrets (C5 ↔ D10) — protocol §6.
|
|
17013
|
+
*
|
|
17014
|
+
* Lease-based, no plaintext on the wire or in PG. Every frame carries a
|
|
17015
|
+
* REFERENCE to a Vault/KMS path, never the secret material itself.
|
|
17016
|
+
*/
|
|
17017
|
+
const SecretsRequest = object({ scope: object({
|
|
17018
|
+
platform: Platform,
|
|
17019
|
+
workspaceId: string().uuid()
|
|
17020
|
+
}) });
|
|
17021
|
+
const SecretsGrant = object({
|
|
17022
|
+
leaseId: string().uuid(),
|
|
17023
|
+
scope: object({
|
|
17024
|
+
platform: string(),
|
|
17025
|
+
workspaceId: string().uuid()
|
|
17026
|
+
}),
|
|
17027
|
+
ref: string(),
|
|
17028
|
+
ttl: number().int(),
|
|
17029
|
+
renewBeforeSec: number().int()
|
|
17030
|
+
});
|
|
17031
|
+
const SecretsRenew = object({ leaseId: string().uuid() });
|
|
17032
|
+
const SecretsRevoke = object({
|
|
17033
|
+
leaseId: string().uuid(),
|
|
17034
|
+
reason: string()
|
|
17035
|
+
});
|
|
17036
|
+
/** 🅼 Direct-to-store upload/download grant — protocol §3.2 / frame #25. */
|
|
17037
|
+
const ScopeAttestation = object({
|
|
17038
|
+
machineId: string().uuid(),
|
|
17039
|
+
scope: _enum([
|
|
17040
|
+
"attachment.put",
|
|
17041
|
+
"attachment.get",
|
|
17042
|
+
"facts.put"
|
|
17043
|
+
]),
|
|
17044
|
+
resourceRef: string(),
|
|
17045
|
+
jws: string(),
|
|
17046
|
+
exp: string().datetime()
|
|
17047
|
+
});
|
|
17048
|
+
//#endregion
|
|
17049
|
+
//#region ../protocol/dist/frames/agent.js
|
|
17050
|
+
/**
|
|
17051
|
+
* Agent lifecycle + delivery (protocol §4.3, §4.4, §7.4, §8).
|
|
17052
|
+
*
|
|
17053
|
+
* Body-locality invariant (protocol §12): no frame here carries
|
|
17054
|
+
* `NormalizedMessage.text`. `agent/prompt` ships a `NormalizedMessageRef` — a
|
|
17055
|
+
* reference the daemon resolves against its local body store.
|
|
17056
|
+
*/
|
|
17057
|
+
/**
|
|
17058
|
+
* A REFERENCE/digest of a normalized message, NOT the body (protocol §4.3).
|
|
17059
|
+
* Enough for D4/D6 to fetch the local body and prompt.
|
|
17060
|
+
*/
|
|
17061
|
+
const NormalizedMessageRef = object({
|
|
17062
|
+
sessionKey: SessionKey,
|
|
17063
|
+
platformMsgId: string(),
|
|
17064
|
+
seenUpToSeq: number().int()
|
|
17065
|
+
});
|
|
17066
|
+
/**
|
|
17067
|
+
* The editable agent definition the CP owns and the daemon needs to run it:
|
|
17068
|
+
* prompt + runtime selection. Raft ships this in the launch config and the
|
|
17069
|
+
* daemon synthesizes the system prompt locally; `description` IS the prompt.
|
|
17070
|
+
*/
|
|
17071
|
+
const AgentSpec = object({
|
|
17072
|
+
name: string(),
|
|
17073
|
+
description: string().optional(),
|
|
17074
|
+
model: string().optional(),
|
|
17075
|
+
reasoningEffort: string().optional(),
|
|
17076
|
+
executionMode: string().optional(),
|
|
17077
|
+
env: record(string(), string()).optional()
|
|
17078
|
+
});
|
|
17079
|
+
const AgentLaunch = object({
|
|
17080
|
+
agentId: string().uuid(),
|
|
17081
|
+
runtime: string(),
|
|
17082
|
+
workspaceId: string().uuid(),
|
|
17083
|
+
capabilities: array(string()),
|
|
17084
|
+
spec: AgentSpec,
|
|
17085
|
+
mode: _enum(["long_lived", "per_turn"]).default("long_lived")
|
|
17086
|
+
});
|
|
17087
|
+
/**
|
|
17088
|
+
* Live agent CRUD (C→D): the console edited an agent's spec; push it so a
|
|
17089
|
+
* running daemon reloads without waiting for the next launch. `agent/remove`
|
|
17090
|
+
* tears the agent down. Deleting an agent never relaunches it.
|
|
17091
|
+
*/
|
|
17092
|
+
const AgentUpsert = object({
|
|
17093
|
+
agentId: string().uuid(),
|
|
17094
|
+
spec: AgentSpec
|
|
17095
|
+
});
|
|
17096
|
+
const AgentRemove = object({ agentId: string().uuid() });
|
|
17097
|
+
const AgentLaunched = object({
|
|
17098
|
+
agentId: string().uuid(),
|
|
17099
|
+
launchId: string().uuid(),
|
|
17100
|
+
acpSessionId: string().optional(),
|
|
17101
|
+
startedAt: string().datetime(),
|
|
17102
|
+
runtime: string()
|
|
17103
|
+
});
|
|
17104
|
+
const AgentStop = object({
|
|
17105
|
+
agentId: string().uuid(),
|
|
17106
|
+
launchId: string().uuid(),
|
|
17107
|
+
reason: string()
|
|
17108
|
+
});
|
|
17109
|
+
const AgentPrompt = object({
|
|
17110
|
+
sessionKey: SessionKey,
|
|
17111
|
+
agentId: string().uuid(),
|
|
17112
|
+
content: NormalizedMessageRef,
|
|
17113
|
+
seenUpToSeq: number().int()
|
|
17114
|
+
});
|
|
17115
|
+
const AgentPromptAck = object({
|
|
17116
|
+
accepted: boolean(),
|
|
17117
|
+
reason: _enum([
|
|
17118
|
+
"queued",
|
|
17119
|
+
"held",
|
|
17120
|
+
"scope_denied",
|
|
17121
|
+
"no_session",
|
|
17122
|
+
"stale"
|
|
17123
|
+
]).optional(),
|
|
17124
|
+
seq: number().int()
|
|
17125
|
+
});
|
|
17126
|
+
const AgentActivity = object({
|
|
17127
|
+
agentId: string().uuid(),
|
|
17128
|
+
launchId: string().uuid(),
|
|
17129
|
+
state: _enum([
|
|
17130
|
+
"thinking",
|
|
17131
|
+
"tool_call",
|
|
17132
|
+
"awaiting_permission",
|
|
17133
|
+
"idle"
|
|
17134
|
+
]),
|
|
17135
|
+
ts: string().datetime()
|
|
17136
|
+
});
|
|
17137
|
+
const AgentScopeDenied = object({
|
|
17138
|
+
agentId: string().uuid(),
|
|
17139
|
+
launchId: string().uuid(),
|
|
17140
|
+
capability: string()
|
|
17141
|
+
});
|
|
17142
|
+
//#endregion
|
|
17143
|
+
//#region ../protocol/dist/frame.js
|
|
17144
|
+
/**
|
|
17145
|
+
* The single source of truth for the wire: `type` string → payload zod schema.
|
|
17146
|
+
*
|
|
17147
|
+
* Mirrors the frame index in daemon-cp-ws-protocol.md §10 (the 29 numbered
|
|
17148
|
+
* frames) plus the correlated REP types named in the "Reply" column
|
|
17149
|
+
* (`route/assign/ack`, `drain/done`, and the generic `ack` replies) that also
|
|
17150
|
+
* travel on the wire and must be decodable.
|
|
17151
|
+
*
|
|
17152
|
+
* `ws/codec.ts` validates every inbound `payload` against `FRAME_SCHEMAS[type]`;
|
|
17153
|
+
* an unknown `type` → `ErrorFrame{code:"UNKNOWN_FRAME"}` (a REP, not a close).
|
|
17154
|
+
*/
|
|
17155
|
+
const FRAME_SCHEMAS = {
|
|
17156
|
+
auth: AuthReq,
|
|
17157
|
+
"auth/ok": AuthOk,
|
|
17158
|
+
register: object({
|
|
17159
|
+
host: string(),
|
|
17160
|
+
capabilities: object({
|
|
17161
|
+
platforms: array(Platform),
|
|
17162
|
+
runtimes: array(string()),
|
|
17163
|
+
acp: boolean(),
|
|
17164
|
+
features: array(string()).default([])
|
|
17165
|
+
}),
|
|
17166
|
+
maxAgents: number().int(),
|
|
17167
|
+
localState: object({
|
|
17168
|
+
assignments: array(string()),
|
|
17169
|
+
crons: array(string()),
|
|
17170
|
+
leases: array(string())
|
|
17171
|
+
})
|
|
17172
|
+
}),
|
|
17173
|
+
"register/ok": object({
|
|
17174
|
+
routingEpoch: number().int(),
|
|
17175
|
+
assignments: array(RouteAssign),
|
|
17176
|
+
agents: array(AgentSpec.extend({ agentId: string().uuid() })).default([]),
|
|
17177
|
+
crons: array(CronUpsert),
|
|
17178
|
+
leases: array(SecretsGrant),
|
|
17179
|
+
drop: object({
|
|
17180
|
+
assignments: array(string()),
|
|
17181
|
+
crons: array(string())
|
|
17182
|
+
})
|
|
17183
|
+
}),
|
|
17184
|
+
heartbeat: object({
|
|
17185
|
+
load: object({
|
|
17186
|
+
cpu: number(),
|
|
17187
|
+
mem: number(),
|
|
17188
|
+
agents: number().int()
|
|
17189
|
+
}),
|
|
17190
|
+
health: _enum(["ok", "degraded"]),
|
|
17191
|
+
activeSessions: number().int(),
|
|
17192
|
+
degradedScopes: array(string()).default([])
|
|
17193
|
+
}),
|
|
17194
|
+
"agent/launch": AgentLaunch,
|
|
17195
|
+
"agent/launched": AgentLaunched,
|
|
17196
|
+
"agent/stop": AgentStop,
|
|
17197
|
+
"agent/upsert": AgentUpsert,
|
|
17198
|
+
"agent/remove": AgentRemove,
|
|
17199
|
+
"agent/prompt": AgentPrompt,
|
|
17200
|
+
"agent/prompt/ack": AgentPromptAck,
|
|
17201
|
+
"agent/activity": AgentActivity,
|
|
17202
|
+
"agent/scope-denied": AgentScopeDenied,
|
|
17203
|
+
"route/assign": RouteAssign,
|
|
17204
|
+
"route/assign/ack": RouteAssignAck,
|
|
17205
|
+
"route/update": RouteUpdate,
|
|
17206
|
+
"daemon/drain": Drain,
|
|
17207
|
+
"drain/progress": DrainProgress,
|
|
17208
|
+
"drain/done": DrainDone,
|
|
17209
|
+
"cron/upsert": CronUpsert,
|
|
17210
|
+
"cron/remove": CronRemove,
|
|
17211
|
+
"secrets/request": SecretsRequest,
|
|
17212
|
+
"secrets/grant": SecretsGrant,
|
|
17213
|
+
"secrets/renew": SecretsRenew,
|
|
17214
|
+
"secrets/revoke": SecretsRevoke,
|
|
17215
|
+
"scope-attestation": ScopeAttestation,
|
|
17216
|
+
"event/session": object({
|
|
17217
|
+
sessionId: string().uuid(),
|
|
17218
|
+
agentId: string().uuid(),
|
|
17219
|
+
launchId: string().uuid(),
|
|
17220
|
+
phase: _enum([
|
|
17221
|
+
"start",
|
|
17222
|
+
"plan",
|
|
17223
|
+
"problem",
|
|
17224
|
+
"end"
|
|
17225
|
+
]),
|
|
17226
|
+
link: string().optional(),
|
|
17227
|
+
summary: string().optional(),
|
|
17228
|
+
ts: string().datetime()
|
|
17229
|
+
}),
|
|
17230
|
+
"facts/runtime-profile": object({
|
|
17231
|
+
runtime: string(),
|
|
17232
|
+
version: string(),
|
|
17233
|
+
models: array(string()),
|
|
17234
|
+
contextWindow: number().int().optional(),
|
|
17235
|
+
acpSupport: _enum([
|
|
17236
|
+
"full",
|
|
17237
|
+
"partial",
|
|
17238
|
+
"none"
|
|
17239
|
+
]),
|
|
17240
|
+
toolCalling: boolean()
|
|
17241
|
+
}),
|
|
17242
|
+
"config/push": object({ keys: record(string(), unknown()) }),
|
|
17243
|
+
"daemon/restart": object({
|
|
17244
|
+
reason: string(),
|
|
17245
|
+
drainFirst: boolean().default(true)
|
|
17246
|
+
}),
|
|
17247
|
+
"daemon/upgrade": object({
|
|
17248
|
+
targetVersion: string(),
|
|
17249
|
+
drainFirst: boolean().default(true)
|
|
17250
|
+
}),
|
|
17251
|
+
"daemon/control/ack": object({
|
|
17252
|
+
accepted: boolean(),
|
|
17253
|
+
willDrainUntil: string().datetime().optional()
|
|
17254
|
+
}),
|
|
17255
|
+
ack: object({
|
|
17256
|
+
ok: boolean(),
|
|
17257
|
+
reason: string().optional()
|
|
17258
|
+
}),
|
|
17259
|
+
error: object({
|
|
17260
|
+
code: _enum([
|
|
17261
|
+
"UNKNOWN_FRAME",
|
|
17262
|
+
"FRAME_TOO_LARGE",
|
|
17263
|
+
"PROTOCOL_STATE",
|
|
17264
|
+
"BAD_PAYLOAD",
|
|
17265
|
+
"AUTH_FAILED",
|
|
17266
|
+
"ATTESTATION_INVALID",
|
|
17267
|
+
"STALE_EPOCH",
|
|
17268
|
+
"STALE_LAUNCH",
|
|
17269
|
+
"SEQ_GAP",
|
|
17270
|
+
"NO_SESSION",
|
|
17271
|
+
"HELD",
|
|
17272
|
+
"SCOPE_DENIED",
|
|
17273
|
+
"LEASE_EXPIRED",
|
|
17274
|
+
"LEASE_DENIED",
|
|
17275
|
+
"RATE_LIMITED",
|
|
17276
|
+
"INTERNAL"
|
|
17277
|
+
]),
|
|
17278
|
+
message: string(),
|
|
17279
|
+
retryable: boolean(),
|
|
17280
|
+
details: record(string(), unknown()).optional()
|
|
17281
|
+
})
|
|
17282
|
+
};
|
|
17283
|
+
Object.keys(FRAME_SCHEMAS);
|
|
17284
|
+
/**
|
|
17285
|
+
* Builds the envelope schema for one frame `type` with a `type` literal and the
|
|
17286
|
+
* typed payload, so the discriminated union infers `payload` precisely.
|
|
17287
|
+
*/
|
|
17288
|
+
function frame(type, payload) {
|
|
17289
|
+
return object({
|
|
17290
|
+
v: literal(1),
|
|
17291
|
+
id: string().uuid(),
|
|
17292
|
+
ts: string().datetime(),
|
|
17293
|
+
type: literal(type),
|
|
17294
|
+
corr: string().uuid().optional(),
|
|
17295
|
+
payload
|
|
17296
|
+
});
|
|
17297
|
+
}
|
|
17298
|
+
discriminatedUnion("type", [
|
|
17299
|
+
frame("auth", FRAME_SCHEMAS["auth"]),
|
|
17300
|
+
frame("auth/ok", FRAME_SCHEMAS["auth/ok"]),
|
|
17301
|
+
frame("register", FRAME_SCHEMAS["register"]),
|
|
17302
|
+
frame("register/ok", FRAME_SCHEMAS["register/ok"]),
|
|
17303
|
+
frame("heartbeat", FRAME_SCHEMAS["heartbeat"]),
|
|
17304
|
+
frame("agent/launch", FRAME_SCHEMAS["agent/launch"]),
|
|
17305
|
+
frame("agent/launched", FRAME_SCHEMAS["agent/launched"]),
|
|
17306
|
+
frame("agent/stop", FRAME_SCHEMAS["agent/stop"]),
|
|
17307
|
+
frame("agent/upsert", FRAME_SCHEMAS["agent/upsert"]),
|
|
17308
|
+
frame("agent/remove", FRAME_SCHEMAS["agent/remove"]),
|
|
17309
|
+
frame("agent/prompt", FRAME_SCHEMAS["agent/prompt"]),
|
|
17310
|
+
frame("agent/prompt/ack", FRAME_SCHEMAS["agent/prompt/ack"]),
|
|
17311
|
+
frame("agent/activity", FRAME_SCHEMAS["agent/activity"]),
|
|
17312
|
+
frame("agent/scope-denied", FRAME_SCHEMAS["agent/scope-denied"]),
|
|
17313
|
+
frame("route/assign", FRAME_SCHEMAS["route/assign"]),
|
|
17314
|
+
frame("route/assign/ack", FRAME_SCHEMAS["route/assign/ack"]),
|
|
17315
|
+
frame("route/update", FRAME_SCHEMAS["route/update"]),
|
|
17316
|
+
frame("daemon/drain", FRAME_SCHEMAS["daemon/drain"]),
|
|
17317
|
+
frame("drain/progress", FRAME_SCHEMAS["drain/progress"]),
|
|
17318
|
+
frame("drain/done", FRAME_SCHEMAS["drain/done"]),
|
|
17319
|
+
frame("cron/upsert", FRAME_SCHEMAS["cron/upsert"]),
|
|
17320
|
+
frame("cron/remove", FRAME_SCHEMAS["cron/remove"]),
|
|
17321
|
+
frame("secrets/request", FRAME_SCHEMAS["secrets/request"]),
|
|
17322
|
+
frame("secrets/grant", FRAME_SCHEMAS["secrets/grant"]),
|
|
17323
|
+
frame("secrets/renew", FRAME_SCHEMAS["secrets/renew"]),
|
|
17324
|
+
frame("secrets/revoke", FRAME_SCHEMAS["secrets/revoke"]),
|
|
17325
|
+
frame("scope-attestation", FRAME_SCHEMAS["scope-attestation"]),
|
|
17326
|
+
frame("event/session", FRAME_SCHEMAS["event/session"]),
|
|
17327
|
+
frame("facts/runtime-profile", FRAME_SCHEMAS["facts/runtime-profile"]),
|
|
17328
|
+
frame("config/push", FRAME_SCHEMAS["config/push"]),
|
|
17329
|
+
frame("daemon/restart", FRAME_SCHEMAS["daemon/restart"]),
|
|
17330
|
+
frame("daemon/upgrade", FRAME_SCHEMAS["daemon/upgrade"]),
|
|
17331
|
+
frame("daemon/control/ack", FRAME_SCHEMAS["daemon/control/ack"]),
|
|
17332
|
+
frame("ack", FRAME_SCHEMAS["ack"]),
|
|
17333
|
+
frame("error", FRAME_SCHEMAS["error"])
|
|
17334
|
+
]);
|
|
17335
|
+
//#endregion
|
|
17336
|
+
//#region ../protocol/dist/codec.js
|
|
17337
|
+
/** Soft cap per frame — 256 KiB (protocol §1). Over this → FRAME_TOO_LARGE. */
|
|
17338
|
+
const MAX_FRAME_BYTES = 256 * 1024;
|
|
17339
|
+
const textEncoder = new TextEncoder();
|
|
17340
|
+
function byteLength(text) {
|
|
17341
|
+
return textEncoder.encode(text).length;
|
|
17342
|
+
}
|
|
17343
|
+
function extractControlExt(json) {
|
|
17344
|
+
if (typeof json !== "object" || json === null) return void 0;
|
|
17345
|
+
const o = json;
|
|
17346
|
+
const ext = {};
|
|
17347
|
+
if (typeof o.epoch === "number") ext.epoch = o.epoch;
|
|
17348
|
+
if (typeof o.seq === "number") ext.seq = o.seq;
|
|
17349
|
+
if (typeof o.agentId === "string") ext.agentId = o.agentId;
|
|
17350
|
+
if (typeof o.launchId === "string") ext.launchId = o.launchId;
|
|
17351
|
+
return Object.keys(ext).length > 0 ? ext : void 0;
|
|
17352
|
+
}
|
|
17353
|
+
function decodeEnvelope(text) {
|
|
17354
|
+
if (byteLength(text) > 262144) return {
|
|
17355
|
+
ok: false,
|
|
17356
|
+
id: NIL_UUID,
|
|
17357
|
+
msg: "FRAME_TOO_LARGE"
|
|
17358
|
+
};
|
|
17359
|
+
let json;
|
|
17360
|
+
try {
|
|
17361
|
+
json = JSON.parse(text);
|
|
17362
|
+
} catch {
|
|
17363
|
+
return {
|
|
17364
|
+
ok: false,
|
|
17365
|
+
id: NIL_UUID,
|
|
17366
|
+
msg: "invalid json"
|
|
17367
|
+
};
|
|
17368
|
+
}
|
|
17369
|
+
const env = Envelope.safeParse(json);
|
|
17370
|
+
if (!env.success) return {
|
|
17371
|
+
ok: false,
|
|
17372
|
+
id: typeof json === "object" && json !== null && typeof json.id === "string" ? json.id : NIL_UUID,
|
|
17373
|
+
msg: env.error.message
|
|
17374
|
+
};
|
|
17375
|
+
const schema = FRAME_SCHEMAS[env.data.type];
|
|
17376
|
+
if (!schema) return {
|
|
17377
|
+
ok: false,
|
|
17378
|
+
id: env.data.id,
|
|
17379
|
+
msg: "UNKNOWN_FRAME"
|
|
17380
|
+
};
|
|
17381
|
+
const payload = schema.safeParse(env.data.payload);
|
|
17382
|
+
if (!payload.success) return {
|
|
17383
|
+
ok: false,
|
|
17384
|
+
id: env.data.id,
|
|
17385
|
+
msg: payload.error.message
|
|
17386
|
+
};
|
|
17387
|
+
const ext = extractControlExt(json);
|
|
17388
|
+
return {
|
|
17389
|
+
ok: true,
|
|
17390
|
+
frame: {
|
|
17391
|
+
...env.data,
|
|
17392
|
+
payload: payload.data
|
|
17393
|
+
},
|
|
17394
|
+
...ext ? { ext } : {}
|
|
17395
|
+
};
|
|
17396
|
+
}
|
|
17397
|
+
function buildEnvelope(type, payload, opts = {}) {
|
|
17398
|
+
return {
|
|
17399
|
+
v: 1,
|
|
17400
|
+
id: opts.id ?? randomUUID(),
|
|
17401
|
+
ts: opts.ts ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
17402
|
+
type,
|
|
17403
|
+
payload,
|
|
17404
|
+
...opts.corr ? { corr: opts.corr } : {},
|
|
17405
|
+
...opts.ext ?? {}
|
|
17406
|
+
};
|
|
17407
|
+
}
|
|
17408
|
+
function encode(frame) {
|
|
17409
|
+
return JSON.stringify(frame);
|
|
17410
|
+
}
|
|
17411
|
+
//#endregion
|
|
17412
|
+
//#region ../protocol/dist/index.js
|
|
17413
|
+
/**
|
|
17414
|
+
* Narrowing guard factory: `isFrame("auth")(frame)` narrows a decoded
|
|
17415
|
+
* `AnyFrame` to the member whose `type` matches.
|
|
17416
|
+
*/
|
|
17417
|
+
function isFrame(type) {
|
|
17418
|
+
return (frame) => frame.type === type;
|
|
17419
|
+
}
|
|
17420
|
+
//#endregion
|
|
16875
17421
|
//#region ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js
|
|
16876
17422
|
var require_constants$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
16877
17423
|
const BINARY_TYPES = [
|