@alook/daemon 0.1.11 → 0.1.13
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/README.md +36 -0
- package/dist/cli/index.js +812 -238
- package/dist/index.js +1186 -772
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -57,7 +57,7 @@ function cliCommandsSection() {
|
|
|
57
57
|
"### Messaging",
|
|
58
58
|
"",
|
|
59
59
|
`1. \`${CLI} inbox pull\` — fetch unread messages (advances your read waterline by default, ` + `so they won't re-pull; \`--no-ack\` to peek without advancing).`,
|
|
60
|
-
`2. \`${CLI} message send\` — send to a channel, DM, or thread.
|
|
60
|
+
`2. \`${CLI} message send\` — send to a channel, DM, or thread. ` + `For a short body, use explicit \`--stdin\` with a quoted heredoc; for a long or complicated body, ` + `use \`--file <path>\`. Attach with \`--attachment <id>\` (repeatable, order matters). Optionally add ` + `\`--remind-after <duration>\` to be reminded if the same channel, thread, or DM receives no ` + `newer message after your send. Use a whole number of minutes or hours from \`1m\` to \`24h\`, ` + `such as \`15m\` or \`2h\`.`,
|
|
61
61
|
`3. \`${CLI} message attachment upload --target <ref> --file <path>\` — upload a file; ` + `returns an id stable across pending→persisted. Feed it into ` + `\`message send --attachment <id>\`.`,
|
|
62
62
|
`4. \`${CLI} message attachment download --id <id> [--out <path>]\` — download any ` + `attachment you can see (or your own pending uploads).`,
|
|
63
63
|
`5. \`${CLI} message emoji --target <ref> --emoji <e>\` — react with a single emoji. ` + `Works on channel messages (\`/<server>/<channel>#N\`), DM messages ` + `(\`/.dm/<peer>#N\`), and thread-reply messages (\`/<server>/<channel>/#N#M\`).`,
|
|
@@ -88,7 +88,7 @@ function cliCommandsSection() {
|
|
|
88
88
|
"",
|
|
89
89
|
"### Context Lifecycle",
|
|
90
90
|
"",
|
|
91
|
-
`1. \`${CLI} nap --handoff <file>\`
|
|
91
|
+
`1. \`${CLI} nap --handoff <file>\` — reset your current session and ` + `start fresh. The required handoff is injected into the new session so your future self can ` + `quickly pick up unfinished work. Never nap on your own; only do it when someone explicitly asks.`,
|
|
92
92
|
"",
|
|
93
93
|
"### Output format",
|
|
94
94
|
"",
|
|
@@ -107,9 +107,11 @@ function messagingSection() {
|
|
|
107
107
|
"You can initiate conversations — send to any channel or DM someone directly. You're not " + "limited to replying. Use the same `message send` command whether you're replying or " + "starting a conversation.",
|
|
108
108
|
"",
|
|
109
109
|
"- Reply where the message came from. Post results in the channel that owns the topic. " + "When uncertain, read history (below) or DM the relevant people.",
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
`-
|
|
110
|
+
"Free-form message bodies never go in command arguments.",
|
|
111
|
+
"",
|
|
112
|
+
`- Short reply: use \`${CLI} message send --target <ref> --stdin\` with the quoted-heredoc form shown ` + "under *Message formatting*. Choose a fresh quoted delimiter that does not occur as a standalone line in the body.",
|
|
113
|
+
`- Long or complicated: write the body to a temporary file with a filesystem tool, then ` + `\`${CLI} message send --target <ref> --file ./temp_msg.md\`.`,
|
|
114
|
+
`- Cite a specific message: add \`--reply "#37"\` to either form — \`--reply\` takes the \`#N\` seq ` + "(within `--target`) of the message you're answering.",
|
|
113
115
|
"",
|
|
114
116
|
"### Context refs",
|
|
115
117
|
"",
|
|
@@ -149,8 +151,10 @@ function messagingSection() {
|
|
|
149
151
|
"- **Mentions** — `@name#NNNN` calls that person's attention specifically. In a private " + "channel, first verify they " + `are a member with \`${CLI} channel member --channel <ref>\` before mentioning them.`,
|
|
150
152
|
"",
|
|
151
153
|
"```bash",
|
|
152
|
-
"#
|
|
153
|
-
`${CLI} message send --target "/demo#1234/general" --
|
|
154
|
+
"# Choose a fresh quoted delimiter that does not occur as a standalone line in the body.",
|
|
155
|
+
`${CLI} message send --target "/demo#1234/general" --stdin <<'ALOOK_MESSAGE_7F3C'`,
|
|
156
|
+
"@alice#0001 Please review /demo#1234/general#42",
|
|
157
|
+
"ALOOK_MESSAGE_7F3C",
|
|
154
158
|
"```",
|
|
155
159
|
"",
|
|
156
160
|
"### Pulled messages",
|
|
@@ -216,7 +220,7 @@ function utilsSection() {
|
|
|
216
220
|
"",
|
|
217
221
|
`Use \`message send --remind-after <duration>\` when you send something that may need a later ` + "follow-up — for example, a question, approval request, handoff, or blocker — and silence would " + "leave the work unfinished. If no newer message appears in that channel, thread, or DM during " + "the duration, you'll receive a reminder to return and decide what to do next. Don't add it to " + "ordinary messages that need no follow-up.",
|
|
218
222
|
"",
|
|
219
|
-
`Example:
|
|
223
|
+
`Example: ${CLI} message send --target "/demo#1234/team" --remind-after 1m --file ./message.md`
|
|
220
224
|
].join(`
|
|
221
225
|
`);
|
|
222
226
|
}
|
|
@@ -4815,624 +4819,248 @@ ${this.opts.wakePromptFooter}` : text;
|
|
|
4815
4819
|
}
|
|
4816
4820
|
}
|
|
4817
4821
|
}
|
|
4818
|
-
//
|
|
4819
|
-
var
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
launchId: cmd.launchId,
|
|
5061
|
-
payload: {
|
|
5062
|
-
requested: err.requested ?? null,
|
|
5063
|
-
available: err.available
|
|
5064
|
-
}
|
|
5065
|
-
};
|
|
5066
|
-
await this.opts.channel.reportSessionError?.(frame);
|
|
5067
|
-
await this.opts.channel.reportWakeAck?.({
|
|
5068
|
-
agentId: cmd.agentId,
|
|
5069
|
-
launchId: cmd.launchId,
|
|
5070
|
-
status: "error",
|
|
5071
|
-
error: {
|
|
5072
|
-
code: "bot_runtime_missing",
|
|
5073
|
-
message: err.message
|
|
5074
|
-
}
|
|
5075
|
-
});
|
|
5076
|
-
this.log.info("agent:wake ack", {
|
|
5077
|
-
agentId: cmd.agentId,
|
|
5078
|
-
status: "error",
|
|
5079
|
-
"error.code": "bot_runtime_missing"
|
|
5080
|
-
});
|
|
5081
|
-
return;
|
|
5082
|
-
}
|
|
5083
|
-
{
|
|
5084
|
-
const code = classifyErrorCode(err);
|
|
5085
|
-
await this.opts.channel.reportWakeAck?.({
|
|
5086
|
-
agentId: cmd.agentId,
|
|
5087
|
-
launchId: cmd.launchId,
|
|
5088
|
-
status: "error",
|
|
5089
|
-
error: {
|
|
5090
|
-
code,
|
|
5091
|
-
message: err instanceof Error ? err.message : String(err)
|
|
5092
|
-
}
|
|
5093
|
-
});
|
|
5094
|
-
this.log.info("agent:wake ack", { agentId: cmd.agentId, status: "error", "error.code": code });
|
|
5095
|
-
}
|
|
5096
|
-
return;
|
|
5097
|
-
}
|
|
5098
|
-
break;
|
|
5099
|
-
case "agent:reset":
|
|
5100
|
-
await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:reset", () => this.opts.manager.resetSession(cmd.agentId, {
|
|
5101
|
-
runtimeConfig: cmd.config,
|
|
5102
|
-
launchId: cmd.launchId,
|
|
5103
|
-
rewakePrompt: REWAKE_PROMPT
|
|
5104
|
-
}));
|
|
5105
|
-
break;
|
|
5106
|
-
case "machine:reset_all":
|
|
5107
|
-
for (const r of cmd.resets) {
|
|
5108
|
-
await this.runRestartCommand(r.agentId, r.launchId, "agent:reset", () => this.opts.manager.resetSession(r.agentId, {
|
|
5109
|
-
runtimeConfig: r.config,
|
|
5110
|
-
launchId: r.launchId,
|
|
5111
|
-
rewakePrompt: REWAKE_PROMPT
|
|
5112
|
-
}));
|
|
5113
|
-
}
|
|
5114
|
-
break;
|
|
5115
|
-
case "agent:nap":
|
|
5116
|
-
await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:nap", () => this.opts.manager.resetSession(cmd.agentId, {
|
|
5117
|
-
runtimeConfig: cmd.config,
|
|
5118
|
-
launchId: cmd.launchId,
|
|
5119
|
-
rewakePrompt: buildNapRewakePrompt(cmd.handoff),
|
|
5120
|
-
barrierType: "nap"
|
|
5121
|
-
}));
|
|
5122
|
-
break;
|
|
5123
|
-
case "agent:model_switch":
|
|
5124
|
-
await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:model_switch", () => this.opts.manager.switchModel(cmd.agentId, {
|
|
5125
|
-
runtimeConfig: cmd.config,
|
|
5126
|
-
launchId: cmd.launchId,
|
|
5127
|
-
rewakePrompt: MODEL_SWITCH_REWAKE_PROMPT
|
|
5128
|
-
}));
|
|
5129
|
-
break;
|
|
5130
|
-
case "agent:stop":
|
|
5131
|
-
this.log.info("agent:stop received", { agentId: cmd.agentId });
|
|
5132
|
-
try {
|
|
5133
|
-
this.running.delete(cmd.agentId);
|
|
5134
|
-
this.opts.manager.stop(cmd.agentId);
|
|
5135
|
-
await this.opts.channel.reportStoppedAck?.({
|
|
5136
|
-
agentId: cmd.agentId,
|
|
5137
|
-
status: "ok"
|
|
5138
|
-
});
|
|
5139
|
-
this.log.info("agent:stop ack", { agentId: cmd.agentId, status: "ok" });
|
|
5140
|
-
} catch (err) {
|
|
5141
|
-
const code = classifyErrorCode(err);
|
|
5142
|
-
await this.opts.channel.reportStoppedAck?.({
|
|
5143
|
-
agentId: cmd.agentId,
|
|
5144
|
-
status: "error",
|
|
5145
|
-
error: {
|
|
5146
|
-
code,
|
|
5147
|
-
message: err instanceof Error ? err.message : String(err)
|
|
5148
|
-
}
|
|
5149
|
-
});
|
|
5150
|
-
this.log.info("agent:stop ack", { agentId: cmd.agentId, status: "error", "error.code": code });
|
|
5151
|
-
}
|
|
5152
|
-
break;
|
|
5153
|
-
case "bot:added":
|
|
5154
|
-
case "bot:updated":
|
|
5155
|
-
case "bot:removed":
|
|
5156
|
-
break;
|
|
5157
|
-
}
|
|
5158
|
-
}
|
|
5159
|
-
}
|
|
5160
|
-
// src/manager/typingScopeTracker.ts
|
|
5161
|
-
function createTypingScopeTracker() {
|
|
5162
|
-
const scopes = new Map;
|
|
5163
|
-
return {
|
|
5164
|
-
add(agentId, channelId) {
|
|
5165
|
-
let set = scopes.get(agentId);
|
|
5166
|
-
if (!set) {
|
|
5167
|
-
set = new Set;
|
|
5168
|
-
scopes.set(agentId, set);
|
|
5169
|
-
}
|
|
5170
|
-
set.add(channelId);
|
|
5171
|
-
},
|
|
5172
|
-
snapshot(agentId) {
|
|
5173
|
-
const set = scopes.get(agentId);
|
|
5174
|
-
return set ? [...set] : [];
|
|
5175
|
-
},
|
|
5176
|
-
hasAny(agentId) {
|
|
5177
|
-
const set = scopes.get(agentId);
|
|
5178
|
-
return !!set && set.size > 0;
|
|
5179
|
-
},
|
|
5180
|
-
clear(agentId) {
|
|
5181
|
-
scopes.delete(agentId);
|
|
5182
|
-
}
|
|
5183
|
-
};
|
|
5184
|
-
}
|
|
5185
|
-
// src/credentials/credentialProxy.ts
|
|
5186
|
-
import * as crypto2 from "crypto";
|
|
5187
|
-
import * as fs5 from "fs";
|
|
5188
|
-
import * as http from "http";
|
|
5189
|
-
import * as https from "https";
|
|
5190
|
-
import * as os2 from "os";
|
|
5191
|
-
import * as path7 from "path";
|
|
5192
|
-
import { URL as URL2 } from "url";
|
|
5193
|
-
|
|
5194
|
-
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
5195
|
-
var exports_external = {};
|
|
5196
|
-
__export(exports_external, {
|
|
5197
|
-
xor: () => xor,
|
|
5198
|
-
xid: () => xid2,
|
|
5199
|
-
void: () => _void2,
|
|
5200
|
-
uuidv7: () => uuidv7,
|
|
5201
|
-
uuidv6: () => uuidv6,
|
|
5202
|
-
uuidv4: () => uuidv4,
|
|
5203
|
-
uuid: () => uuid2,
|
|
5204
|
-
util: () => exports_util,
|
|
5205
|
-
url: () => url,
|
|
5206
|
-
uppercase: () => _uppercase,
|
|
5207
|
-
unknown: () => unknown,
|
|
5208
|
-
union: () => union,
|
|
5209
|
-
undefined: () => _undefined3,
|
|
5210
|
-
ulid: () => ulid2,
|
|
5211
|
-
uint64: () => uint64,
|
|
5212
|
-
uint32: () => uint32,
|
|
5213
|
-
tuple: () => tuple,
|
|
5214
|
-
trim: () => _trim,
|
|
5215
|
-
treeifyError: () => treeifyError,
|
|
5216
|
-
transform: () => transform,
|
|
5217
|
-
toUpperCase: () => _toUpperCase,
|
|
5218
|
-
toLowerCase: () => _toLowerCase,
|
|
5219
|
-
toJSONSchema: () => toJSONSchema,
|
|
5220
|
-
templateLiteral: () => templateLiteral,
|
|
5221
|
-
symbol: () => symbol,
|
|
5222
|
-
superRefine: () => superRefine,
|
|
5223
|
-
success: () => success,
|
|
5224
|
-
stringbool: () => stringbool,
|
|
5225
|
-
stringFormat: () => stringFormat,
|
|
5226
|
-
string: () => string2,
|
|
5227
|
-
strictObject: () => strictObject,
|
|
5228
|
-
startsWith: () => _startsWith,
|
|
5229
|
-
slugify: () => _slugify,
|
|
5230
|
-
size: () => _size,
|
|
5231
|
-
setErrorMap: () => setErrorMap,
|
|
5232
|
-
set: () => set,
|
|
5233
|
-
safeParseAsync: () => safeParseAsync2,
|
|
5234
|
-
safeParse: () => safeParse2,
|
|
5235
|
-
safeEncodeAsync: () => safeEncodeAsync2,
|
|
5236
|
-
safeEncode: () => safeEncode2,
|
|
5237
|
-
safeDecodeAsync: () => safeDecodeAsync2,
|
|
5238
|
-
safeDecode: () => safeDecode2,
|
|
5239
|
-
registry: () => registry,
|
|
5240
|
-
regexes: () => exports_regexes,
|
|
5241
|
-
regex: () => _regex,
|
|
5242
|
-
refine: () => refine,
|
|
5243
|
-
record: () => record,
|
|
5244
|
-
readonly: () => readonly,
|
|
5245
|
-
property: () => _property,
|
|
5246
|
-
promise: () => promise,
|
|
5247
|
-
prettifyError: () => prettifyError,
|
|
5248
|
-
preprocess: () => preprocess,
|
|
5249
|
-
prefault: () => prefault,
|
|
5250
|
-
positive: () => _positive,
|
|
5251
|
-
pipe: () => pipe,
|
|
5252
|
-
partialRecord: () => partialRecord,
|
|
5253
|
-
parseAsync: () => parseAsync2,
|
|
5254
|
-
parse: () => parse3,
|
|
5255
|
-
overwrite: () => _overwrite,
|
|
5256
|
-
optional: () => optional,
|
|
5257
|
-
object: () => object,
|
|
5258
|
-
number: () => number2,
|
|
5259
|
-
nullish: () => nullish2,
|
|
5260
|
-
nullable: () => nullable,
|
|
5261
|
-
null: () => _null3,
|
|
5262
|
-
normalize: () => _normalize,
|
|
5263
|
-
nonpositive: () => _nonpositive,
|
|
5264
|
-
nonoptional: () => nonoptional,
|
|
5265
|
-
nonnegative: () => _nonnegative,
|
|
5266
|
-
never: () => never,
|
|
5267
|
-
negative: () => _negative,
|
|
5268
|
-
nativeEnum: () => nativeEnum,
|
|
5269
|
-
nanoid: () => nanoid2,
|
|
5270
|
-
nan: () => nan,
|
|
5271
|
-
multipleOf: () => _multipleOf,
|
|
5272
|
-
minSize: () => _minSize,
|
|
5273
|
-
minLength: () => _minLength,
|
|
5274
|
-
mime: () => _mime,
|
|
5275
|
-
meta: () => meta2,
|
|
5276
|
-
maxSize: () => _maxSize,
|
|
5277
|
-
maxLength: () => _maxLength,
|
|
5278
|
-
map: () => map,
|
|
5279
|
-
mac: () => mac2,
|
|
5280
|
-
lte: () => _lte,
|
|
5281
|
-
lt: () => _lt,
|
|
5282
|
-
lowercase: () => _lowercase,
|
|
5283
|
-
looseRecord: () => looseRecord,
|
|
5284
|
-
looseObject: () => looseObject,
|
|
5285
|
-
locales: () => exports_locales,
|
|
5286
|
-
literal: () => literal,
|
|
5287
|
-
length: () => _length,
|
|
5288
|
-
lazy: () => lazy,
|
|
5289
|
-
ksuid: () => ksuid2,
|
|
5290
|
-
keyof: () => keyof,
|
|
5291
|
-
jwt: () => jwt,
|
|
5292
|
-
json: () => json,
|
|
5293
|
-
iso: () => exports_iso,
|
|
5294
|
-
ipv6: () => ipv62,
|
|
5295
|
-
ipv4: () => ipv42,
|
|
5296
|
-
invertCodec: () => invertCodec,
|
|
5297
|
-
intersection: () => intersection,
|
|
5298
|
-
int64: () => int64,
|
|
5299
|
-
int32: () => int32,
|
|
5300
|
-
int: () => int,
|
|
5301
|
-
instanceof: () => _instanceof,
|
|
5302
|
-
includes: () => _includes,
|
|
5303
|
-
httpUrl: () => httpUrl,
|
|
5304
|
-
hostname: () => hostname2,
|
|
5305
|
-
hex: () => hex2,
|
|
5306
|
-
hash: () => hash,
|
|
5307
|
-
guid: () => guid2,
|
|
5308
|
-
gte: () => _gte,
|
|
5309
|
-
gt: () => _gt,
|
|
5310
|
-
globalRegistry: () => globalRegistry,
|
|
5311
|
-
getErrorMap: () => getErrorMap,
|
|
5312
|
-
function: () => _function,
|
|
5313
|
-
fromJSONSchema: () => fromJSONSchema,
|
|
5314
|
-
formatError: () => formatError,
|
|
5315
|
-
float64: () => float64,
|
|
5316
|
-
float32: () => float32,
|
|
5317
|
-
flattenError: () => flattenError,
|
|
5318
|
-
file: () => file,
|
|
5319
|
-
exactOptional: () => exactOptional,
|
|
5320
|
-
enum: () => _enum2,
|
|
5321
|
-
endsWith: () => _endsWith,
|
|
5322
|
-
encodeAsync: () => encodeAsync2,
|
|
5323
|
-
encode: () => encode2,
|
|
5324
|
-
emoji: () => emoji2,
|
|
5325
|
-
email: () => email2,
|
|
5326
|
-
e164: () => e1642,
|
|
5327
|
-
discriminatedUnion: () => discriminatedUnion,
|
|
5328
|
-
describe: () => describe2,
|
|
5329
|
-
decodeAsync: () => decodeAsync2,
|
|
5330
|
-
decode: () => decode2,
|
|
5331
|
-
date: () => date3,
|
|
5332
|
-
custom: () => custom,
|
|
5333
|
-
cuid2: () => cuid22,
|
|
5334
|
-
cuid: () => cuid3,
|
|
5335
|
-
core: () => exports_core2,
|
|
5336
|
-
config: () => config,
|
|
5337
|
-
coerce: () => exports_coerce,
|
|
5338
|
-
codec: () => codec,
|
|
5339
|
-
clone: () => clone2,
|
|
5340
|
-
cidrv6: () => cidrv62,
|
|
5341
|
-
cidrv4: () => cidrv42,
|
|
5342
|
-
check: () => check,
|
|
5343
|
-
catch: () => _catch2,
|
|
5344
|
-
boolean: () => boolean2,
|
|
5345
|
-
bigint: () => bigint2,
|
|
5346
|
-
base64url: () => base64url2,
|
|
5347
|
-
base64: () => base642,
|
|
5348
|
-
array: () => array,
|
|
5349
|
-
any: () => any,
|
|
5350
|
-
_function: () => _function,
|
|
5351
|
-
_default: () => _default2,
|
|
5352
|
-
_ZodString: () => _ZodString,
|
|
5353
|
-
ZodXor: () => ZodXor,
|
|
5354
|
-
ZodXID: () => ZodXID,
|
|
5355
|
-
ZodVoid: () => ZodVoid,
|
|
5356
|
-
ZodUnknown: () => ZodUnknown,
|
|
5357
|
-
ZodUnion: () => ZodUnion,
|
|
5358
|
-
ZodUndefined: () => ZodUndefined,
|
|
5359
|
-
ZodUUID: () => ZodUUID,
|
|
5360
|
-
ZodURL: () => ZodURL,
|
|
5361
|
-
ZodULID: () => ZodULID,
|
|
5362
|
-
ZodType: () => ZodType,
|
|
5363
|
-
ZodTuple: () => ZodTuple,
|
|
5364
|
-
ZodTransform: () => ZodTransform,
|
|
5365
|
-
ZodTemplateLiteral: () => ZodTemplateLiteral,
|
|
5366
|
-
ZodSymbol: () => ZodSymbol,
|
|
5367
|
-
ZodSuccess: () => ZodSuccess,
|
|
5368
|
-
ZodStringFormat: () => ZodStringFormat,
|
|
5369
|
-
ZodString: () => ZodString,
|
|
5370
|
-
ZodSet: () => ZodSet,
|
|
5371
|
-
ZodRecord: () => ZodRecord,
|
|
5372
|
-
ZodRealError: () => ZodRealError,
|
|
5373
|
-
ZodReadonly: () => ZodReadonly,
|
|
5374
|
-
ZodPromise: () => ZodPromise,
|
|
5375
|
-
ZodPreprocess: () => ZodPreprocess,
|
|
5376
|
-
ZodPrefault: () => ZodPrefault,
|
|
5377
|
-
ZodPipe: () => ZodPipe,
|
|
5378
|
-
ZodOptional: () => ZodOptional,
|
|
5379
|
-
ZodObject: () => ZodObject,
|
|
5380
|
-
ZodNumberFormat: () => ZodNumberFormat,
|
|
5381
|
-
ZodNumber: () => ZodNumber,
|
|
5382
|
-
ZodNullable: () => ZodNullable,
|
|
5383
|
-
ZodNull: () => ZodNull,
|
|
5384
|
-
ZodNonOptional: () => ZodNonOptional,
|
|
5385
|
-
ZodNever: () => ZodNever,
|
|
5386
|
-
ZodNanoID: () => ZodNanoID,
|
|
5387
|
-
ZodNaN: () => ZodNaN,
|
|
5388
|
-
ZodMap: () => ZodMap,
|
|
5389
|
-
ZodMAC: () => ZodMAC,
|
|
5390
|
-
ZodLiteral: () => ZodLiteral,
|
|
5391
|
-
ZodLazy: () => ZodLazy,
|
|
5392
|
-
ZodKSUID: () => ZodKSUID,
|
|
5393
|
-
ZodJWT: () => ZodJWT,
|
|
5394
|
-
ZodIssueCode: () => ZodIssueCode,
|
|
5395
|
-
ZodIntersection: () => ZodIntersection,
|
|
5396
|
-
ZodISOTime: () => ZodISOTime,
|
|
5397
|
-
ZodISODuration: () => ZodISODuration,
|
|
5398
|
-
ZodISODateTime: () => ZodISODateTime,
|
|
5399
|
-
ZodISODate: () => ZodISODate,
|
|
5400
|
-
ZodIPv6: () => ZodIPv6,
|
|
5401
|
-
ZodIPv4: () => ZodIPv4,
|
|
5402
|
-
ZodGUID: () => ZodGUID,
|
|
5403
|
-
ZodFunction: () => ZodFunction,
|
|
5404
|
-
ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
|
|
5405
|
-
ZodFile: () => ZodFile,
|
|
5406
|
-
ZodExactOptional: () => ZodExactOptional,
|
|
5407
|
-
ZodError: () => ZodError,
|
|
5408
|
-
ZodEnum: () => ZodEnum,
|
|
5409
|
-
ZodEmoji: () => ZodEmoji,
|
|
5410
|
-
ZodEmail: () => ZodEmail,
|
|
5411
|
-
ZodE164: () => ZodE164,
|
|
5412
|
-
ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
|
|
5413
|
-
ZodDefault: () => ZodDefault,
|
|
5414
|
-
ZodDate: () => ZodDate,
|
|
5415
|
-
ZodCustomStringFormat: () => ZodCustomStringFormat,
|
|
5416
|
-
ZodCustom: () => ZodCustom,
|
|
5417
|
-
ZodCodec: () => ZodCodec,
|
|
5418
|
-
ZodCatch: () => ZodCatch,
|
|
5419
|
-
ZodCUID2: () => ZodCUID2,
|
|
5420
|
-
ZodCUID: () => ZodCUID,
|
|
5421
|
-
ZodCIDRv6: () => ZodCIDRv6,
|
|
5422
|
-
ZodCIDRv4: () => ZodCIDRv4,
|
|
5423
|
-
ZodBoolean: () => ZodBoolean,
|
|
5424
|
-
ZodBigIntFormat: () => ZodBigIntFormat,
|
|
5425
|
-
ZodBigInt: () => ZodBigInt,
|
|
5426
|
-
ZodBase64URL: () => ZodBase64URL,
|
|
5427
|
-
ZodBase64: () => ZodBase64,
|
|
5428
|
-
ZodArray: () => ZodArray,
|
|
5429
|
-
ZodAny: () => ZodAny,
|
|
5430
|
-
TimePrecision: () => TimePrecision,
|
|
5431
|
-
NEVER: () => NEVER,
|
|
5432
|
-
$output: () => $output,
|
|
5433
|
-
$input: () => $input,
|
|
5434
|
-
$brand: () => $brand
|
|
5435
|
-
});
|
|
4822
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
4823
|
+
var exports_external = {};
|
|
4824
|
+
__export(exports_external, {
|
|
4825
|
+
xor: () => xor,
|
|
4826
|
+
xid: () => xid2,
|
|
4827
|
+
void: () => _void2,
|
|
4828
|
+
uuidv7: () => uuidv7,
|
|
4829
|
+
uuidv6: () => uuidv6,
|
|
4830
|
+
uuidv4: () => uuidv4,
|
|
4831
|
+
uuid: () => uuid2,
|
|
4832
|
+
util: () => exports_util,
|
|
4833
|
+
url: () => url,
|
|
4834
|
+
uppercase: () => _uppercase,
|
|
4835
|
+
unknown: () => unknown,
|
|
4836
|
+
union: () => union,
|
|
4837
|
+
undefined: () => _undefined3,
|
|
4838
|
+
ulid: () => ulid2,
|
|
4839
|
+
uint64: () => uint64,
|
|
4840
|
+
uint32: () => uint32,
|
|
4841
|
+
tuple: () => tuple,
|
|
4842
|
+
trim: () => _trim,
|
|
4843
|
+
treeifyError: () => treeifyError,
|
|
4844
|
+
transform: () => transform,
|
|
4845
|
+
toUpperCase: () => _toUpperCase,
|
|
4846
|
+
toLowerCase: () => _toLowerCase,
|
|
4847
|
+
toJSONSchema: () => toJSONSchema,
|
|
4848
|
+
templateLiteral: () => templateLiteral,
|
|
4849
|
+
symbol: () => symbol,
|
|
4850
|
+
superRefine: () => superRefine,
|
|
4851
|
+
success: () => success,
|
|
4852
|
+
stringbool: () => stringbool,
|
|
4853
|
+
stringFormat: () => stringFormat,
|
|
4854
|
+
string: () => string2,
|
|
4855
|
+
strictObject: () => strictObject,
|
|
4856
|
+
startsWith: () => _startsWith,
|
|
4857
|
+
slugify: () => _slugify,
|
|
4858
|
+
size: () => _size,
|
|
4859
|
+
setErrorMap: () => setErrorMap,
|
|
4860
|
+
set: () => set,
|
|
4861
|
+
safeParseAsync: () => safeParseAsync2,
|
|
4862
|
+
safeParse: () => safeParse2,
|
|
4863
|
+
safeEncodeAsync: () => safeEncodeAsync2,
|
|
4864
|
+
safeEncode: () => safeEncode2,
|
|
4865
|
+
safeDecodeAsync: () => safeDecodeAsync2,
|
|
4866
|
+
safeDecode: () => safeDecode2,
|
|
4867
|
+
registry: () => registry,
|
|
4868
|
+
regexes: () => exports_regexes,
|
|
4869
|
+
regex: () => _regex,
|
|
4870
|
+
refine: () => refine,
|
|
4871
|
+
record: () => record,
|
|
4872
|
+
readonly: () => readonly,
|
|
4873
|
+
property: () => _property,
|
|
4874
|
+
promise: () => promise,
|
|
4875
|
+
prettifyError: () => prettifyError,
|
|
4876
|
+
preprocess: () => preprocess,
|
|
4877
|
+
prefault: () => prefault,
|
|
4878
|
+
positive: () => _positive,
|
|
4879
|
+
pipe: () => pipe,
|
|
4880
|
+
partialRecord: () => partialRecord,
|
|
4881
|
+
parseAsync: () => parseAsync2,
|
|
4882
|
+
parse: () => parse3,
|
|
4883
|
+
overwrite: () => _overwrite,
|
|
4884
|
+
optional: () => optional,
|
|
4885
|
+
object: () => object,
|
|
4886
|
+
number: () => number2,
|
|
4887
|
+
nullish: () => nullish2,
|
|
4888
|
+
nullable: () => nullable,
|
|
4889
|
+
null: () => _null3,
|
|
4890
|
+
normalize: () => _normalize,
|
|
4891
|
+
nonpositive: () => _nonpositive,
|
|
4892
|
+
nonoptional: () => nonoptional,
|
|
4893
|
+
nonnegative: () => _nonnegative,
|
|
4894
|
+
never: () => never,
|
|
4895
|
+
negative: () => _negative,
|
|
4896
|
+
nativeEnum: () => nativeEnum,
|
|
4897
|
+
nanoid: () => nanoid2,
|
|
4898
|
+
nan: () => nan,
|
|
4899
|
+
multipleOf: () => _multipleOf,
|
|
4900
|
+
minSize: () => _minSize,
|
|
4901
|
+
minLength: () => _minLength,
|
|
4902
|
+
mime: () => _mime,
|
|
4903
|
+
meta: () => meta2,
|
|
4904
|
+
maxSize: () => _maxSize,
|
|
4905
|
+
maxLength: () => _maxLength,
|
|
4906
|
+
map: () => map,
|
|
4907
|
+
mac: () => mac2,
|
|
4908
|
+
lte: () => _lte,
|
|
4909
|
+
lt: () => _lt,
|
|
4910
|
+
lowercase: () => _lowercase,
|
|
4911
|
+
looseRecord: () => looseRecord,
|
|
4912
|
+
looseObject: () => looseObject,
|
|
4913
|
+
locales: () => exports_locales,
|
|
4914
|
+
literal: () => literal,
|
|
4915
|
+
length: () => _length,
|
|
4916
|
+
lazy: () => lazy,
|
|
4917
|
+
ksuid: () => ksuid2,
|
|
4918
|
+
keyof: () => keyof,
|
|
4919
|
+
jwt: () => jwt,
|
|
4920
|
+
json: () => json,
|
|
4921
|
+
iso: () => exports_iso,
|
|
4922
|
+
ipv6: () => ipv62,
|
|
4923
|
+
ipv4: () => ipv42,
|
|
4924
|
+
invertCodec: () => invertCodec,
|
|
4925
|
+
intersection: () => intersection,
|
|
4926
|
+
int64: () => int64,
|
|
4927
|
+
int32: () => int32,
|
|
4928
|
+
int: () => int,
|
|
4929
|
+
instanceof: () => _instanceof,
|
|
4930
|
+
includes: () => _includes,
|
|
4931
|
+
httpUrl: () => httpUrl,
|
|
4932
|
+
hostname: () => hostname2,
|
|
4933
|
+
hex: () => hex2,
|
|
4934
|
+
hash: () => hash,
|
|
4935
|
+
guid: () => guid2,
|
|
4936
|
+
gte: () => _gte,
|
|
4937
|
+
gt: () => _gt,
|
|
4938
|
+
globalRegistry: () => globalRegistry,
|
|
4939
|
+
getErrorMap: () => getErrorMap,
|
|
4940
|
+
function: () => _function,
|
|
4941
|
+
fromJSONSchema: () => fromJSONSchema,
|
|
4942
|
+
formatError: () => formatError,
|
|
4943
|
+
float64: () => float64,
|
|
4944
|
+
float32: () => float32,
|
|
4945
|
+
flattenError: () => flattenError,
|
|
4946
|
+
file: () => file,
|
|
4947
|
+
exactOptional: () => exactOptional,
|
|
4948
|
+
enum: () => _enum2,
|
|
4949
|
+
endsWith: () => _endsWith,
|
|
4950
|
+
encodeAsync: () => encodeAsync2,
|
|
4951
|
+
encode: () => encode2,
|
|
4952
|
+
emoji: () => emoji2,
|
|
4953
|
+
email: () => email2,
|
|
4954
|
+
e164: () => e1642,
|
|
4955
|
+
discriminatedUnion: () => discriminatedUnion,
|
|
4956
|
+
describe: () => describe2,
|
|
4957
|
+
decodeAsync: () => decodeAsync2,
|
|
4958
|
+
decode: () => decode2,
|
|
4959
|
+
date: () => date3,
|
|
4960
|
+
custom: () => custom,
|
|
4961
|
+
cuid2: () => cuid22,
|
|
4962
|
+
cuid: () => cuid3,
|
|
4963
|
+
core: () => exports_core2,
|
|
4964
|
+
config: () => config,
|
|
4965
|
+
coerce: () => exports_coerce,
|
|
4966
|
+
codec: () => codec,
|
|
4967
|
+
clone: () => clone2,
|
|
4968
|
+
cidrv6: () => cidrv62,
|
|
4969
|
+
cidrv4: () => cidrv42,
|
|
4970
|
+
check: () => check,
|
|
4971
|
+
catch: () => _catch2,
|
|
4972
|
+
boolean: () => boolean2,
|
|
4973
|
+
bigint: () => bigint2,
|
|
4974
|
+
base64url: () => base64url2,
|
|
4975
|
+
base64: () => base642,
|
|
4976
|
+
array: () => array,
|
|
4977
|
+
any: () => any,
|
|
4978
|
+
_function: () => _function,
|
|
4979
|
+
_default: () => _default2,
|
|
4980
|
+
_ZodString: () => _ZodString,
|
|
4981
|
+
ZodXor: () => ZodXor,
|
|
4982
|
+
ZodXID: () => ZodXID,
|
|
4983
|
+
ZodVoid: () => ZodVoid,
|
|
4984
|
+
ZodUnknown: () => ZodUnknown,
|
|
4985
|
+
ZodUnion: () => ZodUnion,
|
|
4986
|
+
ZodUndefined: () => ZodUndefined,
|
|
4987
|
+
ZodUUID: () => ZodUUID,
|
|
4988
|
+
ZodURL: () => ZodURL,
|
|
4989
|
+
ZodULID: () => ZodULID,
|
|
4990
|
+
ZodType: () => ZodType,
|
|
4991
|
+
ZodTuple: () => ZodTuple,
|
|
4992
|
+
ZodTransform: () => ZodTransform,
|
|
4993
|
+
ZodTemplateLiteral: () => ZodTemplateLiteral,
|
|
4994
|
+
ZodSymbol: () => ZodSymbol,
|
|
4995
|
+
ZodSuccess: () => ZodSuccess,
|
|
4996
|
+
ZodStringFormat: () => ZodStringFormat,
|
|
4997
|
+
ZodString: () => ZodString,
|
|
4998
|
+
ZodSet: () => ZodSet,
|
|
4999
|
+
ZodRecord: () => ZodRecord,
|
|
5000
|
+
ZodRealError: () => ZodRealError,
|
|
5001
|
+
ZodReadonly: () => ZodReadonly,
|
|
5002
|
+
ZodPromise: () => ZodPromise,
|
|
5003
|
+
ZodPreprocess: () => ZodPreprocess,
|
|
5004
|
+
ZodPrefault: () => ZodPrefault,
|
|
5005
|
+
ZodPipe: () => ZodPipe,
|
|
5006
|
+
ZodOptional: () => ZodOptional,
|
|
5007
|
+
ZodObject: () => ZodObject,
|
|
5008
|
+
ZodNumberFormat: () => ZodNumberFormat,
|
|
5009
|
+
ZodNumber: () => ZodNumber,
|
|
5010
|
+
ZodNullable: () => ZodNullable,
|
|
5011
|
+
ZodNull: () => ZodNull,
|
|
5012
|
+
ZodNonOptional: () => ZodNonOptional,
|
|
5013
|
+
ZodNever: () => ZodNever,
|
|
5014
|
+
ZodNanoID: () => ZodNanoID,
|
|
5015
|
+
ZodNaN: () => ZodNaN,
|
|
5016
|
+
ZodMap: () => ZodMap,
|
|
5017
|
+
ZodMAC: () => ZodMAC,
|
|
5018
|
+
ZodLiteral: () => ZodLiteral,
|
|
5019
|
+
ZodLazy: () => ZodLazy,
|
|
5020
|
+
ZodKSUID: () => ZodKSUID,
|
|
5021
|
+
ZodJWT: () => ZodJWT,
|
|
5022
|
+
ZodIssueCode: () => ZodIssueCode,
|
|
5023
|
+
ZodIntersection: () => ZodIntersection,
|
|
5024
|
+
ZodISOTime: () => ZodISOTime,
|
|
5025
|
+
ZodISODuration: () => ZodISODuration,
|
|
5026
|
+
ZodISODateTime: () => ZodISODateTime,
|
|
5027
|
+
ZodISODate: () => ZodISODate,
|
|
5028
|
+
ZodIPv6: () => ZodIPv6,
|
|
5029
|
+
ZodIPv4: () => ZodIPv4,
|
|
5030
|
+
ZodGUID: () => ZodGUID,
|
|
5031
|
+
ZodFunction: () => ZodFunction,
|
|
5032
|
+
ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
|
|
5033
|
+
ZodFile: () => ZodFile,
|
|
5034
|
+
ZodExactOptional: () => ZodExactOptional,
|
|
5035
|
+
ZodError: () => ZodError,
|
|
5036
|
+
ZodEnum: () => ZodEnum,
|
|
5037
|
+
ZodEmoji: () => ZodEmoji,
|
|
5038
|
+
ZodEmail: () => ZodEmail,
|
|
5039
|
+
ZodE164: () => ZodE164,
|
|
5040
|
+
ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
|
|
5041
|
+
ZodDefault: () => ZodDefault,
|
|
5042
|
+
ZodDate: () => ZodDate,
|
|
5043
|
+
ZodCustomStringFormat: () => ZodCustomStringFormat,
|
|
5044
|
+
ZodCustom: () => ZodCustom,
|
|
5045
|
+
ZodCodec: () => ZodCodec,
|
|
5046
|
+
ZodCatch: () => ZodCatch,
|
|
5047
|
+
ZodCUID2: () => ZodCUID2,
|
|
5048
|
+
ZodCUID: () => ZodCUID,
|
|
5049
|
+
ZodCIDRv6: () => ZodCIDRv6,
|
|
5050
|
+
ZodCIDRv4: () => ZodCIDRv4,
|
|
5051
|
+
ZodBoolean: () => ZodBoolean,
|
|
5052
|
+
ZodBigIntFormat: () => ZodBigIntFormat,
|
|
5053
|
+
ZodBigInt: () => ZodBigInt,
|
|
5054
|
+
ZodBase64URL: () => ZodBase64URL,
|
|
5055
|
+
ZodBase64: () => ZodBase64,
|
|
5056
|
+
ZodArray: () => ZodArray,
|
|
5057
|
+
ZodAny: () => ZodAny,
|
|
5058
|
+
TimePrecision: () => TimePrecision,
|
|
5059
|
+
NEVER: () => NEVER,
|
|
5060
|
+
$output: () => $output,
|
|
5061
|
+
$input: () => $input,
|
|
5062
|
+
$brand: () => $brand
|
|
5063
|
+
});
|
|
5436
5064
|
|
|
5437
5065
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/index.js
|
|
5438
5066
|
var exports_core2 = {};
|
|
@@ -21713,6 +21341,7 @@ var OwnerDiagnosticReportSchema = exports_external.discriminatedUnion("status",
|
|
|
21713
21341
|
|
|
21714
21342
|
// ../shared/src/community-cli-contract.ts
|
|
21715
21343
|
var DM_SERVER = ".dm";
|
|
21344
|
+
var CONTROL_HEARTBEAT_CAPABILITY = "control-heartbeat-v1";
|
|
21716
21345
|
function parseRef(ref) {
|
|
21717
21346
|
if (!ref.startsWith("/"))
|
|
21718
21347
|
throw new Error(`ref must start with "/": ${ref}`);
|
|
@@ -21724,137 +21353,516 @@ function parseRef(ref) {
|
|
|
21724
21353
|
if (server !== DM_SERVER && !parseNameAndTag(server)) {
|
|
21725
21354
|
throw new Error(`server ref must use a name#discriminator handle: ${ref}`);
|
|
21726
21355
|
}
|
|
21727
|
-
let seq;
|
|
21728
|
-
if (parts.length >= 3 && parts[parts.length - 1].startsWith("#")) {
|
|
21729
|
-
const tail = parseThreadTail(parts[parts.length - 1]);
|
|
21730
|
-
return { server, channel: parts[1], ...tail };
|
|
21356
|
+
let seq;
|
|
21357
|
+
if (parts.length >= 3 && parts[parts.length - 1].startsWith("#")) {
|
|
21358
|
+
const tail = parseThreadTail(parts[parts.length - 1]);
|
|
21359
|
+
return { server, channel: parts[1], ...tail };
|
|
21360
|
+
}
|
|
21361
|
+
if (parts.length >= 3 && server !== DM_SERVER) {
|
|
21362
|
+
throw new Error(`ref has too many segments: ${ref}`);
|
|
21363
|
+
}
|
|
21364
|
+
const chSeg = parts[1];
|
|
21365
|
+
if (server === DM_SERVER) {
|
|
21366
|
+
const lastHash = chSeg.lastIndexOf("#");
|
|
21367
|
+
if (lastHash < 0)
|
|
21368
|
+
return { server, channel: chSeg };
|
|
21369
|
+
const firstHash = chSeg.indexOf("#");
|
|
21370
|
+
const tail = chSeg.slice(lastHash + 1);
|
|
21371
|
+
const isBareHandle = firstHash === lastHash && /^\d{4,}$/.test(tail);
|
|
21372
|
+
if (isBareHandle)
|
|
21373
|
+
return { server, channel: chSeg };
|
|
21374
|
+
const tailNum = Number(tail.startsWith("#") ? tail.slice(1) : tail);
|
|
21375
|
+
if (!Number.isFinite(tailNum))
|
|
21376
|
+
return { server, channel: chSeg };
|
|
21377
|
+
seq = parseSeq(tail);
|
|
21378
|
+
return { server, channel: chSeg.slice(0, lastHash), seq };
|
|
21379
|
+
}
|
|
21380
|
+
const hashIdx = chSeg.indexOf("#");
|
|
21381
|
+
if (hashIdx >= 0) {
|
|
21382
|
+
seq = parseSeq(chSeg.slice(hashIdx));
|
|
21383
|
+
return { server, channel: chSeg.slice(0, hashIdx), seq };
|
|
21384
|
+
}
|
|
21385
|
+
return { server, channel: chSeg };
|
|
21386
|
+
}
|
|
21387
|
+
function parseThreadTail(segment) {
|
|
21388
|
+
const stripped = segment.startsWith("#") ? segment.slice(1) : segment;
|
|
21389
|
+
const tokens = stripped.split("#");
|
|
21390
|
+
if (tokens.length < 1 || tokens.length > 2) {
|
|
21391
|
+
throw new Error(`bad thread ref tail: #${stripped}`);
|
|
21392
|
+
}
|
|
21393
|
+
for (const t of tokens) {
|
|
21394
|
+
if (!t)
|
|
21395
|
+
throw new Error(`bad thread ref tail: #${stripped} (empty seq)`);
|
|
21396
|
+
}
|
|
21397
|
+
const threadRootSeq = parseSeq(tokens[0]);
|
|
21398
|
+
if (tokens.length === 1)
|
|
21399
|
+
return { threadRootSeq };
|
|
21400
|
+
return { threadRootSeq, seq: parseSeq(tokens[1]) };
|
|
21401
|
+
}
|
|
21402
|
+
function formatRef(p) {
|
|
21403
|
+
if (p.seq !== undefined && p.threadRootSeq === undefined) {
|
|
21404
|
+
throw new Error("formatRef: seq without threadRootSeq is not supported");
|
|
21405
|
+
}
|
|
21406
|
+
const base = `/${p.server}/${p.channel}`;
|
|
21407
|
+
if (p.threadRootSeq === undefined)
|
|
21408
|
+
return base;
|
|
21409
|
+
if (p.seq === undefined)
|
|
21410
|
+
return `${base}/#${p.threadRootSeq}`;
|
|
21411
|
+
return `${base}/#${p.threadRootSeq}#${p.seq}`;
|
|
21412
|
+
}
|
|
21413
|
+
function parseSeq(s) {
|
|
21414
|
+
const n = Number(s.startsWith("#") ? s.slice(1) : s);
|
|
21415
|
+
if (!Number.isFinite(n))
|
|
21416
|
+
throw new Error(`bad seq: ${s}`);
|
|
21417
|
+
return n;
|
|
21418
|
+
}
|
|
21419
|
+
var HostCommandSchema = exports_external.discriminatedUnion("type", [
|
|
21420
|
+
exports_external.strictObject({
|
|
21421
|
+
type: exports_external.literal("machine:heartbeat"),
|
|
21422
|
+
nonce: exports_external.string().min(1).max(128)
|
|
21423
|
+
}),
|
|
21424
|
+
exports_external.object({
|
|
21425
|
+
type: exports_external.literal("agent:wake"),
|
|
21426
|
+
agentId: exports_external.string().min(1),
|
|
21427
|
+
config: exports_external.unknown(),
|
|
21428
|
+
sessionId: exports_external.string().optional(),
|
|
21429
|
+
launchId: exports_external.string().min(1),
|
|
21430
|
+
unreadNotice: exports_external.unknown()
|
|
21431
|
+
}),
|
|
21432
|
+
exports_external.object({
|
|
21433
|
+
type: exports_external.literal("agent:stop"),
|
|
21434
|
+
agentId: exports_external.string().min(1)
|
|
21435
|
+
}),
|
|
21436
|
+
exports_external.object({
|
|
21437
|
+
type: exports_external.literal("agent:reset"),
|
|
21438
|
+
agentId: exports_external.string().min(1),
|
|
21439
|
+
config: exports_external.unknown(),
|
|
21440
|
+
launchId: exports_external.string().min(1)
|
|
21441
|
+
}),
|
|
21442
|
+
exports_external.object({
|
|
21443
|
+
type: exports_external.literal("agent:nap"),
|
|
21444
|
+
agentId: exports_external.string().min(1),
|
|
21445
|
+
config: exports_external.unknown(),
|
|
21446
|
+
launchId: exports_external.string().min(1),
|
|
21447
|
+
handoff: exports_external.string().min(1)
|
|
21448
|
+
}),
|
|
21449
|
+
exports_external.object({
|
|
21450
|
+
type: exports_external.literal("agent:model_switch"),
|
|
21451
|
+
agentId: exports_external.string().min(1),
|
|
21452
|
+
config: exports_external.unknown(),
|
|
21453
|
+
launchId: exports_external.string().min(1)
|
|
21454
|
+
}),
|
|
21455
|
+
exports_external.object({
|
|
21456
|
+
type: exports_external.literal("machine:reset_all"),
|
|
21457
|
+
resets: exports_external.array(exports_external.object({
|
|
21458
|
+
agentId: exports_external.string().min(1),
|
|
21459
|
+
config: exports_external.unknown(),
|
|
21460
|
+
launchId: exports_external.string().min(1)
|
|
21461
|
+
}))
|
|
21462
|
+
}),
|
|
21463
|
+
exports_external.strictObject({
|
|
21464
|
+
type: exports_external.literal("machine:update")
|
|
21465
|
+
}),
|
|
21466
|
+
exports_external.object({
|
|
21467
|
+
type: exports_external.literal("bot:added"),
|
|
21468
|
+
botId: exports_external.string().min(1),
|
|
21469
|
+
name: exports_external.string().optional(),
|
|
21470
|
+
discriminator: exports_external.string().optional(),
|
|
21471
|
+
description: exports_external.string().optional(),
|
|
21472
|
+
ownerName: exports_external.string().optional(),
|
|
21473
|
+
ownerDiscriminator: exports_external.string().optional()
|
|
21474
|
+
}),
|
|
21475
|
+
exports_external.object({
|
|
21476
|
+
type: exports_external.literal("bot:updated"),
|
|
21477
|
+
botId: exports_external.string().min(1),
|
|
21478
|
+
name: exports_external.string().optional(),
|
|
21479
|
+
discriminator: exports_external.string().optional(),
|
|
21480
|
+
description: exports_external.string().optional(),
|
|
21481
|
+
ownerName: exports_external.string().optional(),
|
|
21482
|
+
ownerDiscriminator: exports_external.string().optional()
|
|
21483
|
+
}),
|
|
21484
|
+
exports_external.object({
|
|
21485
|
+
type: exports_external.literal("bot:removed"),
|
|
21486
|
+
botId: exports_external.string().min(1)
|
|
21487
|
+
}),
|
|
21488
|
+
DiagnosticCollectCommandSchema
|
|
21489
|
+
]);
|
|
21490
|
+
// src/manager/agentRouter.ts
|
|
21491
|
+
var DEFINITIVE_EXECUTABLE_FAILURES = new Set(["ENOENT", "EACCES", "ENOEXEC", "EPERM"]);
|
|
21492
|
+
|
|
21493
|
+
class UnknownBotError extends Error {
|
|
21494
|
+
botId;
|
|
21495
|
+
constructor(botId) {
|
|
21496
|
+
super(`Bot not in this daemon's cache: ${botId}`);
|
|
21497
|
+
this.botId = botId;
|
|
21498
|
+
this.name = "UnknownBotError";
|
|
21499
|
+
}
|
|
21500
|
+
}
|
|
21501
|
+
|
|
21502
|
+
class BotEnrollFailedError extends Error {
|
|
21503
|
+
botId;
|
|
21504
|
+
constructor(botId, cause) {
|
|
21505
|
+
super(`Failed to enroll bot ${botId}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
21506
|
+
this.botId = botId;
|
|
21507
|
+
this.name = "BotEnrollFailedError";
|
|
21508
|
+
}
|
|
21509
|
+
}
|
|
21510
|
+
function classifyErrorCode(err) {
|
|
21511
|
+
if (err instanceof UnknownBotError)
|
|
21512
|
+
return "bot_unknown";
|
|
21513
|
+
if (err instanceof BotEnrollFailedError)
|
|
21514
|
+
return "bot_enroll_failed";
|
|
21515
|
+
if (err instanceof UnknownRuntimeError)
|
|
21516
|
+
return "bot_runtime_missing";
|
|
21517
|
+
return "internal_error";
|
|
21518
|
+
}
|
|
21519
|
+
|
|
21520
|
+
class UnknownRuntimeError extends Error {
|
|
21521
|
+
requested;
|
|
21522
|
+
available;
|
|
21523
|
+
constructor(requested, available) {
|
|
21524
|
+
super(`Runtime not available on this host: ${requested ?? "<unspecified>"} — installed: ${available.join(", ") || "(none)"}`);
|
|
21525
|
+
this.requested = requested;
|
|
21526
|
+
this.available = available;
|
|
21527
|
+
this.name = "UnknownRuntimeError";
|
|
21528
|
+
}
|
|
21529
|
+
}
|
|
21530
|
+
function defaultFormatUnreadNoticeText(notice) {
|
|
21531
|
+
return `You have unread messages in channel ${notice.channel}.`;
|
|
21532
|
+
}
|
|
21533
|
+
var REWAKE_PROMPT = "Your session was reset by your owner. Prior conversation context is gone. " + "Read @memory.md and your .context_timeline for durable context, then pull your inbox " + "before doing anything else. If it reports marked messages, run `$ALOOK_CLI message mark list` " + "and resume that outstanding work.";
|
|
21534
|
+
var MODEL_SWITCH_REWAKE_PROMPT = "You were just switched to a different model. Continue any unfinished work.";
|
|
21535
|
+
function buildNapRewakePrompt(handoff) {
|
|
21536
|
+
return "You took a nap: you reset your own session, so prior conversation context " + `is gone. Before sleeping you left yourself this handoff —
|
|
21537
|
+
|
|
21538
|
+
` + handoff + `
|
|
21539
|
+
|
|
21540
|
+
Then read @memory.md and your .context_timeline for durable context, and pull ` + "your inbox before doing anything else. If it reports marked messages, run `$ALOOK_CLI " + "message mark list` and resume that outstanding work.";
|
|
21541
|
+
}
|
|
21542
|
+
|
|
21543
|
+
class AgentRouter {
|
|
21544
|
+
opts;
|
|
21545
|
+
running = new Set;
|
|
21546
|
+
runtimes = new Map;
|
|
21547
|
+
pendingResend = false;
|
|
21548
|
+
scheduleResend;
|
|
21549
|
+
log;
|
|
21550
|
+
constructor(opts) {
|
|
21551
|
+
this.opts = opts;
|
|
21552
|
+
this.log = opts.logger ?? createLogger({ header: "@alook/daemon:router" });
|
|
21553
|
+
this.scheduleResend = opts.scheduleReadyResend ?? queueMicrotask.bind(globalThis);
|
|
21554
|
+
for (const r of opts.runtimeReport) {
|
|
21555
|
+
this.runtimes.set(r.id, {
|
|
21556
|
+
id: r.id,
|
|
21557
|
+
version: r.version,
|
|
21558
|
+
status: r.status ?? "healthy",
|
|
21559
|
+
lastError: r.lastError,
|
|
21560
|
+
lastErrorAt: r.lastErrorAt
|
|
21561
|
+
});
|
|
21562
|
+
}
|
|
21563
|
+
}
|
|
21564
|
+
async start() {
|
|
21565
|
+
this.opts.channel.onCommand((cmd) => this.onCommand(cmd));
|
|
21566
|
+
this.opts.channel.onResync?.(() => ({
|
|
21567
|
+
ready: this.buildReady(),
|
|
21568
|
+
sessions: this.opts.manager.liveSessionReports(),
|
|
21569
|
+
activities: this.opts.manager.liveAgentActivities()
|
|
21570
|
+
}));
|
|
21571
|
+
await this.opts.channel.reportReady(this.buildReady());
|
|
21572
|
+
}
|
|
21573
|
+
buildReady() {
|
|
21574
|
+
return {
|
|
21575
|
+
runtimeReport: [...this.runtimes.values()],
|
|
21576
|
+
capabilities: [CONTROL_HEARTBEAT_CAPABILITY],
|
|
21577
|
+
runningAgents: [...this.running],
|
|
21578
|
+
hostname: this.opts.hostname,
|
|
21579
|
+
platform: this.opts.platform,
|
|
21580
|
+
arch: this.opts.arch,
|
|
21581
|
+
osRelease: this.opts.osRelease,
|
|
21582
|
+
daemonVersion: this.opts.daemonVersion
|
|
21583
|
+
};
|
|
21584
|
+
}
|
|
21585
|
+
healthyRuntimeIds() {
|
|
21586
|
+
const out = [];
|
|
21587
|
+
for (const r of this.runtimes.values()) {
|
|
21588
|
+
if (r.status === "healthy")
|
|
21589
|
+
out.push(r.id);
|
|
21590
|
+
}
|
|
21591
|
+
return out;
|
|
21592
|
+
}
|
|
21593
|
+
isRuntimeHealthy(id) {
|
|
21594
|
+
return this.runtimes.get(id)?.status === "healthy";
|
|
21731
21595
|
}
|
|
21732
|
-
|
|
21733
|
-
|
|
21596
|
+
recordRuntimeSpawnFailure(id, reason) {
|
|
21597
|
+
if (!DEFINITIVE_EXECUTABLE_FAILURES.has(reason))
|
|
21598
|
+
return;
|
|
21599
|
+
this.markRuntimeUnhealthy(id, reason);
|
|
21734
21600
|
}
|
|
21735
|
-
|
|
21736
|
-
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
|
|
21742
|
-
|
|
21743
|
-
|
|
21744
|
-
|
|
21745
|
-
|
|
21746
|
-
|
|
21747
|
-
|
|
21748
|
-
|
|
21749
|
-
|
|
21601
|
+
markRuntimeUnhealthy(id, reason) {
|
|
21602
|
+
const existing = this.runtimes.get(id);
|
|
21603
|
+
if (!existing)
|
|
21604
|
+
return;
|
|
21605
|
+
const nowIso = new Date().toISOString();
|
|
21606
|
+
if (existing.status === "unhealthy" && existing.lastError === reason)
|
|
21607
|
+
return;
|
|
21608
|
+
this.runtimes.set(id, {
|
|
21609
|
+
...existing,
|
|
21610
|
+
status: "unhealthy",
|
|
21611
|
+
lastError: reason,
|
|
21612
|
+
lastErrorAt: nowIso
|
|
21613
|
+
});
|
|
21614
|
+
this.log.warn("runtime marked unhealthy", { runtimeId: id, reason });
|
|
21615
|
+
this.scheduleReadyFrameResend();
|
|
21750
21616
|
}
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21617
|
+
markRuntimeHealthy(id) {
|
|
21618
|
+
const existing = this.runtimes.get(id);
|
|
21619
|
+
if (!existing)
|
|
21620
|
+
return;
|
|
21621
|
+
if (existing.status === "healthy" && !existing.lastError && !existing.lastErrorAt)
|
|
21622
|
+
return;
|
|
21623
|
+
this.runtimes.set(id, {
|
|
21624
|
+
id: existing.id,
|
|
21625
|
+
version: existing.version,
|
|
21626
|
+
status: "healthy"
|
|
21627
|
+
});
|
|
21628
|
+
this.log.info("runtime marked healthy again", { runtimeId: id });
|
|
21629
|
+
this.scheduleReadyFrameResend();
|
|
21755
21630
|
}
|
|
21756
|
-
|
|
21757
|
-
|
|
21758
|
-
|
|
21759
|
-
|
|
21760
|
-
|
|
21761
|
-
if (tokens.length < 1 || tokens.length > 2) {
|
|
21762
|
-
throw new Error(`bad thread ref tail: #${stripped}`);
|
|
21631
|
+
markLocallyStopped(agentId) {
|
|
21632
|
+
if (!this.running.delete(agentId))
|
|
21633
|
+
return;
|
|
21634
|
+
this.log.info("agent removed from running set (local stop)", { agentId });
|
|
21635
|
+
this.scheduleReadyFrameResend();
|
|
21763
21636
|
}
|
|
21764
|
-
|
|
21765
|
-
if (
|
|
21766
|
-
|
|
21637
|
+
scheduleReadyFrameResend() {
|
|
21638
|
+
if (this.pendingResend)
|
|
21639
|
+
return;
|
|
21640
|
+
this.pendingResend = true;
|
|
21641
|
+
this.scheduleResend(() => {
|
|
21642
|
+
this.pendingResend = false;
|
|
21643
|
+
try {
|
|
21644
|
+
this.opts.channel.sendReady?.(this.buildReady());
|
|
21645
|
+
} catch {}
|
|
21646
|
+
});
|
|
21767
21647
|
}
|
|
21768
|
-
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
|
|
21772
|
-
|
|
21773
|
-
|
|
21774
|
-
|
|
21775
|
-
|
|
21648
|
+
async runRestartCommand(agentId, launchId, opName, run) {
|
|
21649
|
+
this.log.info(`${opName} received`, { agentId, launchId });
|
|
21650
|
+
try {
|
|
21651
|
+
await this.opts.onBeforeAgent?.(agentId);
|
|
21652
|
+
await run();
|
|
21653
|
+
this.running.add(agentId);
|
|
21654
|
+
this.scheduleReadyFrameResend();
|
|
21655
|
+
this.log.info(`${opName} ok`, { agentId });
|
|
21656
|
+
} catch (err) {
|
|
21657
|
+
if (err instanceof UnknownRuntimeError) {
|
|
21658
|
+
const frame = {
|
|
21659
|
+
type: "session.error",
|
|
21660
|
+
code: "runtime_not_available",
|
|
21661
|
+
agentId,
|
|
21662
|
+
launchId,
|
|
21663
|
+
payload: { requested: err.requested ?? null, available: err.available }
|
|
21664
|
+
};
|
|
21665
|
+
await this.opts.channel.reportSessionError?.(frame);
|
|
21666
|
+
this.log.info(`${opName} error`, { agentId, "error.code": "runtime_not_available" });
|
|
21667
|
+
return;
|
|
21668
|
+
}
|
|
21669
|
+
const code = classifyErrorCode(err);
|
|
21670
|
+
await this.opts.channel.reportWakeAck?.({
|
|
21671
|
+
agentId,
|
|
21672
|
+
launchId,
|
|
21673
|
+
status: "error",
|
|
21674
|
+
error: { code, message: err instanceof Error ? err.message : String(err) }
|
|
21675
|
+
});
|
|
21676
|
+
this.log.warn(`${opName} failed`, {
|
|
21677
|
+
agentId,
|
|
21678
|
+
"error.code": code,
|
|
21679
|
+
err: err instanceof Error ? err.message : String(err)
|
|
21680
|
+
});
|
|
21681
|
+
}
|
|
21682
|
+
}
|
|
21683
|
+
async onCommand(cmd) {
|
|
21684
|
+
switch (cmd.type) {
|
|
21685
|
+
case "agent:wake":
|
|
21686
|
+
this.log.info("agent:wake received", {
|
|
21687
|
+
agentId: cmd.agentId,
|
|
21688
|
+
channel: cmd.unreadNotice.channel,
|
|
21689
|
+
latestSeq: cmd.unreadNotice.latestSeq
|
|
21690
|
+
});
|
|
21691
|
+
try {
|
|
21692
|
+
const beforeStatus = this.opts.manager.snapshot?.().agents?.[cmd.agentId]?.status ?? "unregistered";
|
|
21693
|
+
const wasActive = this.opts.typingTracker?.hasAny(cmd.agentId) ?? false;
|
|
21694
|
+
await this.opts.onBeforeAgent?.(cmd.agentId);
|
|
21695
|
+
this.opts.manager.register(cmd.agentId, {
|
|
21696
|
+
runtimeConfig: cmd.config,
|
|
21697
|
+
sessionId: cmd.sessionId,
|
|
21698
|
+
launchId: cmd.launchId
|
|
21699
|
+
});
|
|
21700
|
+
this.running.add(cmd.agentId);
|
|
21701
|
+
const channelScope = cmd.unreadNotice.channelId;
|
|
21702
|
+
if (channelScope)
|
|
21703
|
+
this.opts.typingTracker?.add(cmd.agentId, channelScope);
|
|
21704
|
+
const text2 = (this.opts.formatUnreadNoticeText ?? defaultFormatUnreadNoticeText)(cmd.unreadNotice);
|
|
21705
|
+
const producedEffect = this.opts.manager.deliver(cmd.agentId, {
|
|
21706
|
+
seq: cmd.unreadNotice.latestSeq,
|
|
21707
|
+
text: text2
|
|
21708
|
+
});
|
|
21709
|
+
if (producedEffect === false && beforeStatus === "running") {
|
|
21710
|
+
this.log.info("agent:wake produced no effect (coalesced onto running agent)", {
|
|
21711
|
+
agentId: cmd.agentId,
|
|
21712
|
+
latestSeq: cmd.unreadNotice.latestSeq
|
|
21713
|
+
});
|
|
21714
|
+
}
|
|
21715
|
+
if (channelScope && wasActive && beforeStatus === "running") {
|
|
21716
|
+
this.opts.channel.reportAgentTyping?.({
|
|
21717
|
+
agentId: cmd.agentId,
|
|
21718
|
+
channelId: channelScope
|
|
21719
|
+
});
|
|
21720
|
+
}
|
|
21721
|
+
await this.opts.channel.reportWakeAck?.({
|
|
21722
|
+
agentId: cmd.agentId,
|
|
21723
|
+
launchId: cmd.launchId,
|
|
21724
|
+
status: "ok"
|
|
21725
|
+
});
|
|
21726
|
+
this.log.info("agent:wake ack", { agentId: cmd.agentId, status: "ok" });
|
|
21727
|
+
} catch (err) {
|
|
21728
|
+
if (err instanceof UnknownRuntimeError) {
|
|
21729
|
+
const frame = {
|
|
21730
|
+
type: "session.error",
|
|
21731
|
+
code: "runtime_not_available",
|
|
21732
|
+
agentId: cmd.agentId,
|
|
21733
|
+
launchId: cmd.launchId,
|
|
21734
|
+
payload: {
|
|
21735
|
+
requested: err.requested ?? null,
|
|
21736
|
+
available: err.available
|
|
21737
|
+
}
|
|
21738
|
+
};
|
|
21739
|
+
await this.opts.channel.reportSessionError?.(frame);
|
|
21740
|
+
await this.opts.channel.reportWakeAck?.({
|
|
21741
|
+
agentId: cmd.agentId,
|
|
21742
|
+
launchId: cmd.launchId,
|
|
21743
|
+
status: "error",
|
|
21744
|
+
error: {
|
|
21745
|
+
code: "bot_runtime_missing",
|
|
21746
|
+
message: err.message
|
|
21747
|
+
}
|
|
21748
|
+
});
|
|
21749
|
+
this.log.info("agent:wake ack", {
|
|
21750
|
+
agentId: cmd.agentId,
|
|
21751
|
+
status: "error",
|
|
21752
|
+
"error.code": "bot_runtime_missing"
|
|
21753
|
+
});
|
|
21754
|
+
return;
|
|
21755
|
+
}
|
|
21756
|
+
{
|
|
21757
|
+
const code = classifyErrorCode(err);
|
|
21758
|
+
await this.opts.channel.reportWakeAck?.({
|
|
21759
|
+
agentId: cmd.agentId,
|
|
21760
|
+
launchId: cmd.launchId,
|
|
21761
|
+
status: "error",
|
|
21762
|
+
error: {
|
|
21763
|
+
code,
|
|
21764
|
+
message: err instanceof Error ? err.message : String(err)
|
|
21765
|
+
}
|
|
21766
|
+
});
|
|
21767
|
+
this.log.info("agent:wake ack", { agentId: cmd.agentId, status: "error", "error.code": code });
|
|
21768
|
+
}
|
|
21769
|
+
return;
|
|
21770
|
+
}
|
|
21771
|
+
break;
|
|
21772
|
+
case "agent:reset":
|
|
21773
|
+
await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:reset", () => this.opts.manager.resetSession(cmd.agentId, {
|
|
21774
|
+
runtimeConfig: cmd.config,
|
|
21775
|
+
launchId: cmd.launchId,
|
|
21776
|
+
rewakePrompt: REWAKE_PROMPT
|
|
21777
|
+
}));
|
|
21778
|
+
break;
|
|
21779
|
+
case "machine:reset_all":
|
|
21780
|
+
for (const r of cmd.resets) {
|
|
21781
|
+
await this.runRestartCommand(r.agentId, r.launchId, "agent:reset", () => this.opts.manager.resetSession(r.agentId, {
|
|
21782
|
+
runtimeConfig: r.config,
|
|
21783
|
+
launchId: r.launchId,
|
|
21784
|
+
rewakePrompt: REWAKE_PROMPT
|
|
21785
|
+
}));
|
|
21786
|
+
}
|
|
21787
|
+
break;
|
|
21788
|
+
case "agent:nap":
|
|
21789
|
+
await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:nap", () => this.opts.manager.resetSession(cmd.agentId, {
|
|
21790
|
+
runtimeConfig: cmd.config,
|
|
21791
|
+
launchId: cmd.launchId,
|
|
21792
|
+
rewakePrompt: buildNapRewakePrompt(cmd.handoff),
|
|
21793
|
+
barrierType: "nap"
|
|
21794
|
+
}));
|
|
21795
|
+
break;
|
|
21796
|
+
case "agent:model_switch":
|
|
21797
|
+
await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:model_switch", () => this.opts.manager.switchModel(cmd.agentId, {
|
|
21798
|
+
runtimeConfig: cmd.config,
|
|
21799
|
+
launchId: cmd.launchId,
|
|
21800
|
+
rewakePrompt: MODEL_SWITCH_REWAKE_PROMPT
|
|
21801
|
+
}));
|
|
21802
|
+
break;
|
|
21803
|
+
case "agent:stop":
|
|
21804
|
+
this.log.info("agent:stop received", { agentId: cmd.agentId });
|
|
21805
|
+
try {
|
|
21806
|
+
this.running.delete(cmd.agentId);
|
|
21807
|
+
this.opts.manager.stop(cmd.agentId);
|
|
21808
|
+
await this.opts.channel.reportStoppedAck?.({
|
|
21809
|
+
agentId: cmd.agentId,
|
|
21810
|
+
status: "ok"
|
|
21811
|
+
});
|
|
21812
|
+
this.log.info("agent:stop ack", { agentId: cmd.agentId, status: "ok" });
|
|
21813
|
+
} catch (err) {
|
|
21814
|
+
const code = classifyErrorCode(err);
|
|
21815
|
+
await this.opts.channel.reportStoppedAck?.({
|
|
21816
|
+
agentId: cmd.agentId,
|
|
21817
|
+
status: "error",
|
|
21818
|
+
error: {
|
|
21819
|
+
code,
|
|
21820
|
+
message: err instanceof Error ? err.message : String(err)
|
|
21821
|
+
}
|
|
21822
|
+
});
|
|
21823
|
+
this.log.info("agent:stop ack", { agentId: cmd.agentId, status: "error", "error.code": code });
|
|
21824
|
+
}
|
|
21825
|
+
break;
|
|
21826
|
+
case "bot:added":
|
|
21827
|
+
case "bot:updated":
|
|
21828
|
+
case "bot:removed":
|
|
21829
|
+
break;
|
|
21830
|
+
}
|
|
21776
21831
|
}
|
|
21777
|
-
const base = `/${p.server}/${p.channel}`;
|
|
21778
|
-
if (p.threadRootSeq === undefined)
|
|
21779
|
-
return base;
|
|
21780
|
-
if (p.seq === undefined)
|
|
21781
|
-
return `${base}/#${p.threadRootSeq}`;
|
|
21782
|
-
return `${base}/#${p.threadRootSeq}#${p.seq}`;
|
|
21783
21832
|
}
|
|
21784
|
-
|
|
21785
|
-
|
|
21786
|
-
|
|
21787
|
-
|
|
21788
|
-
|
|
21833
|
+
// src/manager/typingScopeTracker.ts
|
|
21834
|
+
function createTypingScopeTracker() {
|
|
21835
|
+
const scopes = new Map;
|
|
21836
|
+
return {
|
|
21837
|
+
add(agentId, channelId) {
|
|
21838
|
+
let set2 = scopes.get(agentId);
|
|
21839
|
+
if (!set2) {
|
|
21840
|
+
set2 = new Set;
|
|
21841
|
+
scopes.set(agentId, set2);
|
|
21842
|
+
}
|
|
21843
|
+
set2.add(channelId);
|
|
21844
|
+
},
|
|
21845
|
+
snapshot(agentId) {
|
|
21846
|
+
const set2 = scopes.get(agentId);
|
|
21847
|
+
return set2 ? [...set2] : [];
|
|
21848
|
+
},
|
|
21849
|
+
hasAny(agentId) {
|
|
21850
|
+
const set2 = scopes.get(agentId);
|
|
21851
|
+
return !!set2 && set2.size > 0;
|
|
21852
|
+
},
|
|
21853
|
+
clear(agentId) {
|
|
21854
|
+
scopes.delete(agentId);
|
|
21855
|
+
}
|
|
21856
|
+
};
|
|
21789
21857
|
}
|
|
21790
|
-
var HostCommandSchema = exports_external.discriminatedUnion("type", [
|
|
21791
|
-
exports_external.object({
|
|
21792
|
-
type: exports_external.literal("agent:wake"),
|
|
21793
|
-
agentId: exports_external.string().min(1),
|
|
21794
|
-
config: exports_external.unknown(),
|
|
21795
|
-
sessionId: exports_external.string().optional(),
|
|
21796
|
-
launchId: exports_external.string().min(1),
|
|
21797
|
-
unreadNotice: exports_external.unknown()
|
|
21798
|
-
}),
|
|
21799
|
-
exports_external.object({
|
|
21800
|
-
type: exports_external.literal("agent:stop"),
|
|
21801
|
-
agentId: exports_external.string().min(1)
|
|
21802
|
-
}),
|
|
21803
|
-
exports_external.object({
|
|
21804
|
-
type: exports_external.literal("agent:reset"),
|
|
21805
|
-
agentId: exports_external.string().min(1),
|
|
21806
|
-
config: exports_external.unknown(),
|
|
21807
|
-
launchId: exports_external.string().min(1)
|
|
21808
|
-
}),
|
|
21809
|
-
exports_external.object({
|
|
21810
|
-
type: exports_external.literal("agent:nap"),
|
|
21811
|
-
agentId: exports_external.string().min(1),
|
|
21812
|
-
config: exports_external.unknown(),
|
|
21813
|
-
launchId: exports_external.string().min(1),
|
|
21814
|
-
handoff: exports_external.string().min(1)
|
|
21815
|
-
}),
|
|
21816
|
-
exports_external.object({
|
|
21817
|
-
type: exports_external.literal("agent:model_switch"),
|
|
21818
|
-
agentId: exports_external.string().min(1),
|
|
21819
|
-
config: exports_external.unknown(),
|
|
21820
|
-
launchId: exports_external.string().min(1)
|
|
21821
|
-
}),
|
|
21822
|
-
exports_external.object({
|
|
21823
|
-
type: exports_external.literal("machine:reset_all"),
|
|
21824
|
-
resets: exports_external.array(exports_external.object({
|
|
21825
|
-
agentId: exports_external.string().min(1),
|
|
21826
|
-
config: exports_external.unknown(),
|
|
21827
|
-
launchId: exports_external.string().min(1)
|
|
21828
|
-
}))
|
|
21829
|
-
}),
|
|
21830
|
-
exports_external.strictObject({
|
|
21831
|
-
type: exports_external.literal("machine:update")
|
|
21832
|
-
}),
|
|
21833
|
-
exports_external.object({
|
|
21834
|
-
type: exports_external.literal("bot:added"),
|
|
21835
|
-
botId: exports_external.string().min(1),
|
|
21836
|
-
name: exports_external.string().optional(),
|
|
21837
|
-
discriminator: exports_external.string().optional(),
|
|
21838
|
-
description: exports_external.string().optional(),
|
|
21839
|
-
ownerName: exports_external.string().optional(),
|
|
21840
|
-
ownerDiscriminator: exports_external.string().optional()
|
|
21841
|
-
}),
|
|
21842
|
-
exports_external.object({
|
|
21843
|
-
type: exports_external.literal("bot:updated"),
|
|
21844
|
-
botId: exports_external.string().min(1),
|
|
21845
|
-
name: exports_external.string().optional(),
|
|
21846
|
-
discriminator: exports_external.string().optional(),
|
|
21847
|
-
description: exports_external.string().optional(),
|
|
21848
|
-
ownerName: exports_external.string().optional(),
|
|
21849
|
-
ownerDiscriminator: exports_external.string().optional()
|
|
21850
|
-
}),
|
|
21851
|
-
exports_external.object({
|
|
21852
|
-
type: exports_external.literal("bot:removed"),
|
|
21853
|
-
botId: exports_external.string().min(1)
|
|
21854
|
-
}),
|
|
21855
|
-
DiagnosticCollectCommandSchema
|
|
21856
|
-
]);
|
|
21857
21858
|
// src/credentials/credentialProxy.ts
|
|
21859
|
+
import * as crypto2 from "crypto";
|
|
21860
|
+
import * as fs5 from "fs";
|
|
21861
|
+
import * as http from "http";
|
|
21862
|
+
import * as https from "https";
|
|
21863
|
+
import * as os2 from "os";
|
|
21864
|
+
import * as path7 from "path";
|
|
21865
|
+
import { URL as URL2 } from "url";
|
|
21858
21866
|
var LOCAL_MESSAGE_REMINDER_PATH = "/__alook/local/message-reminder";
|
|
21859
21867
|
var LOCAL_MESSAGE_REMINDER_BODY_MAX_BYTES = 4 * 1024;
|
|
21860
21868
|
var LOCAL_MESSAGE_REMINDER_MIN_MS = 60000;
|
|
@@ -21980,6 +21988,14 @@ function writeJson(res, status, body) {
|
|
|
21980
21988
|
res.writeHead(status, { "content-type": "application/json" });
|
|
21981
21989
|
res.end(JSON.stringify(body));
|
|
21982
21990
|
}
|
|
21991
|
+
function normalizeContentEncoding(value) {
|
|
21992
|
+
const normalized = (Array.isArray(value) ? value.join(",") : value ?? "").trim().toLowerCase();
|
|
21993
|
+
if (!normalized || normalized === "identity")
|
|
21994
|
+
return "identity";
|
|
21995
|
+
if (normalized === "gzip" || normalized === "deflate" || normalized === "br")
|
|
21996
|
+
return normalized;
|
|
21997
|
+
return "other";
|
|
21998
|
+
}
|
|
21983
21999
|
function isCanonicalChannelScope(channel2) {
|
|
21984
22000
|
try {
|
|
21985
22001
|
const parsed = parseRef(channel2);
|
|
@@ -22076,6 +22092,11 @@ async function startCredentialProxy(broker, options = {}) {
|
|
|
22076
22092
|
const upstreamClient = upstream.protocol === "https:" ? https : http;
|
|
22077
22093
|
const onPull = options.onInboxPullResponse;
|
|
22078
22094
|
const onProxyRequest = options.onProxyRequest;
|
|
22095
|
+
const reportInboxPullObservationError = (failure) => {
|
|
22096
|
+
try {
|
|
22097
|
+
options.onInboxPullObservationError?.(failure);
|
|
22098
|
+
} catch {}
|
|
22099
|
+
};
|
|
22079
22100
|
const server = http.createServer((req, res) => {
|
|
22080
22101
|
const pathname = new URL2(req.url ?? "/", "http://placeholder").pathname;
|
|
22081
22102
|
if (pathname.startsWith("/__alook/local/")) {
|
|
@@ -22114,7 +22135,20 @@ async function startCredentialProxy(broker, options = {}) {
|
|
|
22114
22135
|
return;
|
|
22115
22136
|
}
|
|
22116
22137
|
const reg = verdict.reg;
|
|
22117
|
-
const isInboxPull =
|
|
22138
|
+
const isInboxPull = req.method === "POST" && pathname === "/api/community/users/me/inbox/pull";
|
|
22139
|
+
const shouldObserveInboxPull = Boolean(isInboxPull && onPull);
|
|
22140
|
+
let inboxPullObservationToken;
|
|
22141
|
+
if (shouldObserveInboxPull) {
|
|
22142
|
+
try {
|
|
22143
|
+
inboxPullObservationToken = options.onInboxPullStart?.(reg.agentId);
|
|
22144
|
+
} catch {
|
|
22145
|
+
reportInboxPullObservationError({
|
|
22146
|
+
agentId: reg.agentId,
|
|
22147
|
+
reason: "observer_failed",
|
|
22148
|
+
contentEncoding: "identity"
|
|
22149
|
+
});
|
|
22150
|
+
}
|
|
22151
|
+
}
|
|
22118
22152
|
if (onProxyRequest) {
|
|
22119
22153
|
try {
|
|
22120
22154
|
onProxyRequest(reg.agentId, req.method ?? "GET", pathname);
|
|
@@ -22127,6 +22161,8 @@ async function startCredentialProxy(broker, options = {}) {
|
|
|
22127
22161
|
outHeaders[broker.headerNames.agentId.toLowerCase()] = reg.agentId;
|
|
22128
22162
|
outHeaders[broker.headerNames.client.toLowerCase()] = broker.clientLabel;
|
|
22129
22163
|
outHeaders[broker.headerNames.capabilities.toLowerCase()] = [...reg.capabilities].join(",");
|
|
22164
|
+
if (isInboxPull)
|
|
22165
|
+
outHeaders["accept-encoding"] = "identity";
|
|
22130
22166
|
let responded = false;
|
|
22131
22167
|
let upstreamRes;
|
|
22132
22168
|
const upstreamReq = upstreamClient.request({
|
|
@@ -22145,18 +22181,54 @@ async function startCredentialProxy(broker, options = {}) {
|
|
|
22145
22181
|
};
|
|
22146
22182
|
res_.on("error", destroyResIfIncomplete);
|
|
22147
22183
|
res_.on("close", destroyResIfIncomplete);
|
|
22148
|
-
if (
|
|
22184
|
+
if (shouldObserveInboxPull && res_.statusCode !== undefined && res_.statusCode >= 200 && res_.statusCode < 300) {
|
|
22149
22185
|
const chunks = [];
|
|
22150
22186
|
res_.on("data", (chunk) => chunks.push(chunk));
|
|
22151
22187
|
res_.on("end", () => {
|
|
22152
22188
|
const body = Buffer.concat(chunks);
|
|
22189
|
+
const contentEncoding = normalizeContentEncoding(res_.headers["content-encoding"]);
|
|
22190
|
+
if (contentEncoding !== "identity") {
|
|
22191
|
+
reportInboxPullObservationError({
|
|
22192
|
+
agentId: reg.agentId,
|
|
22193
|
+
reason: "unexpected_content_encoding",
|
|
22194
|
+
contentEncoding
|
|
22195
|
+
});
|
|
22196
|
+
} else {
|
|
22197
|
+
let parsed;
|
|
22198
|
+
try {
|
|
22199
|
+
parsed = JSON.parse(body.toString("utf8"));
|
|
22200
|
+
} catch {
|
|
22201
|
+
reportInboxPullObservationError({
|
|
22202
|
+
agentId: reg.agentId,
|
|
22203
|
+
reason: "invalid_json",
|
|
22204
|
+
contentEncoding
|
|
22205
|
+
});
|
|
22206
|
+
}
|
|
22207
|
+
if (parsed !== undefined) {
|
|
22208
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || !Array.isArray(parsed.messages)) {
|
|
22209
|
+
reportInboxPullObservationError({
|
|
22210
|
+
agentId: reg.agentId,
|
|
22211
|
+
reason: "invalid_inbox_shape",
|
|
22212
|
+
contentEncoding
|
|
22213
|
+
});
|
|
22214
|
+
} else {
|
|
22215
|
+
const messages = parsed.messages;
|
|
22216
|
+
if (messages.length > 0) {
|
|
22217
|
+
try {
|
|
22218
|
+
onPull(reg.agentId, messages, inboxPullObservationToken);
|
|
22219
|
+
} catch {
|
|
22220
|
+
reportInboxPullObservationError({
|
|
22221
|
+
agentId: reg.agentId,
|
|
22222
|
+
reason: "observer_failed",
|
|
22223
|
+
contentEncoding
|
|
22224
|
+
});
|
|
22225
|
+
}
|
|
22226
|
+
}
|
|
22227
|
+
}
|
|
22228
|
+
}
|
|
22229
|
+
}
|
|
22153
22230
|
res.writeHead(res_.statusCode, res_.headers);
|
|
22154
22231
|
res.end(body);
|
|
22155
|
-
try {
|
|
22156
|
-
const parsed = JSON.parse(body.toString());
|
|
22157
|
-
if (parsed.messages)
|
|
22158
|
-
onPull(reg.agentId, parsed.messages);
|
|
22159
|
-
} catch {}
|
|
22160
22232
|
});
|
|
22161
22233
|
} else {
|
|
22162
22234
|
res.writeHead(res_.statusCode ?? 502, res_.headers);
|
|
@@ -22481,6 +22553,236 @@ function writeStatusFile(path8, snapshot) {
|
|
|
22481
22553
|
} catch {}
|
|
22482
22554
|
}
|
|
22483
22555
|
|
|
22556
|
+
// src/manager/wakeCoordinator.ts
|
|
22557
|
+
class WakeCoordinator {
|
|
22558
|
+
agents = new Map;
|
|
22559
|
+
async run(command, dispatch, onDesiredAdvance) {
|
|
22560
|
+
const state = this.agent(command.agentId);
|
|
22561
|
+
const channel2 = command.unreadNotice.channel;
|
|
22562
|
+
const seq = command.unreadNotice.latestSeq;
|
|
22563
|
+
const scope = state.scopes.get(channel2);
|
|
22564
|
+
const coveredSeq = Math.max(scope?.modelSeenSeq ?? 0, scope?.admittedSeq ?? 0);
|
|
22565
|
+
if (seq <= coveredSeq) {
|
|
22566
|
+
this.rememberReplacement(state, command);
|
|
22567
|
+
return { state: "suppressed", coveredSeq };
|
|
22568
|
+
}
|
|
22569
|
+
const desiredAdvanced = !scope || seq > scope.desiredSeq;
|
|
22570
|
+
if (!scope || seq >= scope.desiredSeq) {
|
|
22571
|
+
state.scopes.set(channel2, {
|
|
22572
|
+
desiredSeq: Math.max(scope?.desiredSeq ?? 0, seq),
|
|
22573
|
+
admittedSeq: scope?.admittedSeq ?? 0,
|
|
22574
|
+
modelSeenSeq: scope?.modelSeenSeq ?? 0,
|
|
22575
|
+
command
|
|
22576
|
+
});
|
|
22577
|
+
}
|
|
22578
|
+
if (desiredAdvanced)
|
|
22579
|
+
onDesiredAdvance?.(command);
|
|
22580
|
+
state.dispatch = dispatch;
|
|
22581
|
+
if (state.active || state.admitting) {
|
|
22582
|
+
this.rememberReplacement(state, command);
|
|
22583
|
+
return { state: "suppressed", coveredSeq: seq };
|
|
22584
|
+
}
|
|
22585
|
+
await this.admit(command.agentId, command);
|
|
22586
|
+
return { state: "accepted" };
|
|
22587
|
+
}
|
|
22588
|
+
modelSeenGeneration(agentId) {
|
|
22589
|
+
return this.agent(agentId).observationGeneration;
|
|
22590
|
+
}
|
|
22591
|
+
recordModelSeen(agentId, messages, generation) {
|
|
22592
|
+
const state = this.agent(agentId);
|
|
22593
|
+
if (generation !== state.observationGeneration)
|
|
22594
|
+
return false;
|
|
22595
|
+
for (const message2 of messages) {
|
|
22596
|
+
const seq = Number(message2.seq.startsWith("#") ? message2.seq.slice(1) : message2.seq);
|
|
22597
|
+
if (!Number.isSafeInteger(seq) || seq <= 0)
|
|
22598
|
+
continue;
|
|
22599
|
+
const scope = state.scopes.get(message2.channel);
|
|
22600
|
+
if (scope) {
|
|
22601
|
+
scope.modelSeenSeq = Math.max(scope.modelSeenSeq, seq);
|
|
22602
|
+
} else {
|
|
22603
|
+
state.scopes.set(message2.channel, {
|
|
22604
|
+
desiredSeq: 0,
|
|
22605
|
+
admittedSeq: 0,
|
|
22606
|
+
modelSeenSeq: seq,
|
|
22607
|
+
command: null
|
|
22608
|
+
});
|
|
22609
|
+
}
|
|
22610
|
+
}
|
|
22611
|
+
return true;
|
|
22612
|
+
}
|
|
22613
|
+
recordAgentActivity(agentId, activity) {
|
|
22614
|
+
const state = this.agent(agentId);
|
|
22615
|
+
if (activity === "starting" || activity === "running") {
|
|
22616
|
+
state.active = true;
|
|
22617
|
+
return;
|
|
22618
|
+
}
|
|
22619
|
+
if (activity !== "idle")
|
|
22620
|
+
return;
|
|
22621
|
+
state.active = false;
|
|
22622
|
+
state.activeAdmission = null;
|
|
22623
|
+
const next = this.nextPending(state);
|
|
22624
|
+
if (next && state.dispatch)
|
|
22625
|
+
this.admit(agentId, next);
|
|
22626
|
+
}
|
|
22627
|
+
recordDeliveryAck(agentId, launchId, status) {
|
|
22628
|
+
const state = this.agents.get(agentId);
|
|
22629
|
+
const admission = state?.activeAdmission;
|
|
22630
|
+
if (!state || !admission || admission.launchId !== launchId)
|
|
22631
|
+
return;
|
|
22632
|
+
if (status === "ok")
|
|
22633
|
+
return;
|
|
22634
|
+
for (const [channel2, coverage] of admission.coverage) {
|
|
22635
|
+
const scope = state.scopes.get(channel2);
|
|
22636
|
+
if (scope?.admittedSeq === coverage.admittedSeq) {
|
|
22637
|
+
scope.admittedSeq = coverage.previousSeq;
|
|
22638
|
+
}
|
|
22639
|
+
}
|
|
22640
|
+
state.active = false;
|
|
22641
|
+
state.failedAdmissionLaunchId = launchId;
|
|
22642
|
+
state.retryAfterFailure = state.coalescedReplacement;
|
|
22643
|
+
state.coalescedReplacement = null;
|
|
22644
|
+
state.activeAdmission = null;
|
|
22645
|
+
if (!state.admitting && state.retryAfterFailure) {
|
|
22646
|
+
this.retryFailedAdmission(agentId, state).catch(() => {});
|
|
22647
|
+
}
|
|
22648
|
+
}
|
|
22649
|
+
invalidate(agentId, clearModelSeen) {
|
|
22650
|
+
const state = this.agent(agentId);
|
|
22651
|
+
state.observationGeneration += 1;
|
|
22652
|
+
state.active = false;
|
|
22653
|
+
state.admitting = false;
|
|
22654
|
+
state.activeAdmission = null;
|
|
22655
|
+
state.failedAdmissionLaunchId = null;
|
|
22656
|
+
state.coalescedReplacement = null;
|
|
22657
|
+
state.retryAfterFailure = null;
|
|
22658
|
+
if (clearModelSeen) {
|
|
22659
|
+
state.scopes.clear();
|
|
22660
|
+
return;
|
|
22661
|
+
}
|
|
22662
|
+
for (const scope of state.scopes.values()) {
|
|
22663
|
+
scope.desiredSeq = scope.modelSeenSeq;
|
|
22664
|
+
scope.admittedSeq = scope.modelSeenSeq;
|
|
22665
|
+
}
|
|
22666
|
+
}
|
|
22667
|
+
agent(agentId) {
|
|
22668
|
+
let state = this.agents.get(agentId);
|
|
22669
|
+
if (!state) {
|
|
22670
|
+
state = {
|
|
22671
|
+
active: false,
|
|
22672
|
+
admitting: false,
|
|
22673
|
+
activeAdmission: null,
|
|
22674
|
+
failedAdmissionLaunchId: null,
|
|
22675
|
+
coalescedReplacement: null,
|
|
22676
|
+
retryAfterFailure: null,
|
|
22677
|
+
observationGeneration: 0,
|
|
22678
|
+
scopes: new Map,
|
|
22679
|
+
dispatch: null
|
|
22680
|
+
};
|
|
22681
|
+
this.agents.set(agentId, state);
|
|
22682
|
+
}
|
|
22683
|
+
return state;
|
|
22684
|
+
}
|
|
22685
|
+
nextPending(state) {
|
|
22686
|
+
let next = null;
|
|
22687
|
+
for (const scope of state.scopes.values()) {
|
|
22688
|
+
if (scope.desiredSeq <= Math.max(scope.modelSeenSeq, scope.admittedSeq))
|
|
22689
|
+
continue;
|
|
22690
|
+
if (!scope.command)
|
|
22691
|
+
continue;
|
|
22692
|
+
if (scope.command.launchId === state.failedAdmissionLaunchId)
|
|
22693
|
+
continue;
|
|
22694
|
+
if (!next || scope.desiredSeq > next.desiredSeq)
|
|
22695
|
+
next = scope;
|
|
22696
|
+
}
|
|
22697
|
+
return next?.command ?? null;
|
|
22698
|
+
}
|
|
22699
|
+
async admit(agentId, preferred) {
|
|
22700
|
+
const state = this.agent(agentId);
|
|
22701
|
+
if (state.active || state.admitting || !state.dispatch)
|
|
22702
|
+
return;
|
|
22703
|
+
const admissionGeneration = state.observationGeneration;
|
|
22704
|
+
const command = preferred ?? this.nextPending(state);
|
|
22705
|
+
if (!command)
|
|
22706
|
+
return;
|
|
22707
|
+
const commandScope = state.scopes.get(command.unreadNotice.channel);
|
|
22708
|
+
if (commandScope && command.unreadNotice.latestSeq >= commandScope.desiredSeq) {
|
|
22709
|
+
commandScope.command = command;
|
|
22710
|
+
}
|
|
22711
|
+
const coverage = new Map;
|
|
22712
|
+
for (const [channel2, scope] of state.scopes) {
|
|
22713
|
+
if (scope.desiredSeq <= Math.max(scope.modelSeenSeq, scope.admittedSeq))
|
|
22714
|
+
continue;
|
|
22715
|
+
coverage.set(channel2, {
|
|
22716
|
+
previousSeq: scope.admittedSeq,
|
|
22717
|
+
admittedSeq: scope.desiredSeq
|
|
22718
|
+
});
|
|
22719
|
+
scope.admittedSeq = scope.desiredSeq;
|
|
22720
|
+
scope.command = command;
|
|
22721
|
+
}
|
|
22722
|
+
if (coverage.size === 0)
|
|
22723
|
+
return;
|
|
22724
|
+
state.admitting = true;
|
|
22725
|
+
state.active = true;
|
|
22726
|
+
state.failedAdmissionLaunchId = null;
|
|
22727
|
+
state.coalescedReplacement = null;
|
|
22728
|
+
state.activeAdmission = { launchId: command.launchId, coverage };
|
|
22729
|
+
let dispatchError;
|
|
22730
|
+
try {
|
|
22731
|
+
await state.dispatch(command);
|
|
22732
|
+
} catch (error51) {
|
|
22733
|
+
if (state.observationGeneration === admissionGeneration) {
|
|
22734
|
+
for (const [channel2, admitted] of coverage) {
|
|
22735
|
+
const scope = state.scopes.get(channel2);
|
|
22736
|
+
if (scope?.admittedSeq === admitted.admittedSeq) {
|
|
22737
|
+
scope.admittedSeq = admitted.previousSeq;
|
|
22738
|
+
}
|
|
22739
|
+
}
|
|
22740
|
+
state.active = false;
|
|
22741
|
+
state.failedAdmissionLaunchId = command.launchId;
|
|
22742
|
+
state.retryAfterFailure = state.coalescedReplacement;
|
|
22743
|
+
state.coalescedReplacement = null;
|
|
22744
|
+
state.activeAdmission = null;
|
|
22745
|
+
}
|
|
22746
|
+
dispatchError = error51;
|
|
22747
|
+
} finally {
|
|
22748
|
+
if (state.observationGeneration === admissionGeneration) {
|
|
22749
|
+
state.admitting = false;
|
|
22750
|
+
}
|
|
22751
|
+
}
|
|
22752
|
+
if (state.observationGeneration === admissionGeneration) {
|
|
22753
|
+
await this.retryFailedAdmission(agentId, state);
|
|
22754
|
+
if (!state.active && !state.admitting) {
|
|
22755
|
+
const next = this.nextPending(state);
|
|
22756
|
+
if (next)
|
|
22757
|
+
await this.admit(agentId, next);
|
|
22758
|
+
}
|
|
22759
|
+
}
|
|
22760
|
+
if (dispatchError)
|
|
22761
|
+
throw dispatchError;
|
|
22762
|
+
}
|
|
22763
|
+
rememberReplacement(state, command) {
|
|
22764
|
+
const failedOrActiveLaunchId = state.activeAdmission?.launchId ?? state.failedAdmissionLaunchId;
|
|
22765
|
+
if (!failedOrActiveLaunchId || command.launchId === failedOrActiveLaunchId)
|
|
22766
|
+
return;
|
|
22767
|
+
const scope = state.scopes.get(command.unreadNotice.channel);
|
|
22768
|
+
if (!scope || command.unreadNotice.latestSeq < scope.desiredSeq)
|
|
22769
|
+
return;
|
|
22770
|
+
state.coalescedReplacement = command;
|
|
22771
|
+
if (state.failedAdmissionLaunchId)
|
|
22772
|
+
state.retryAfterFailure = command;
|
|
22773
|
+
}
|
|
22774
|
+
async retryFailedAdmission(agentId, state) {
|
|
22775
|
+
if (state.active || state.admitting)
|
|
22776
|
+
return;
|
|
22777
|
+
const replacement = state.retryAfterFailure;
|
|
22778
|
+
state.retryAfterFailure = null;
|
|
22779
|
+
if (!replacement)
|
|
22780
|
+
return;
|
|
22781
|
+
state.failedAdmissionLaunchId = null;
|
|
22782
|
+
await this.admit(agentId, replacement);
|
|
22783
|
+
}
|
|
22784
|
+
}
|
|
22785
|
+
|
|
22484
22786
|
// src/server/wsControlChannel.ts
|
|
22485
22787
|
var WS_CONTROL_COMMAND_CONSUMED = Symbol("ws-control-command-consumed");
|
|
22486
22788
|
var DEFAULT_PING_INTERVAL_MS = 15000;
|
|
@@ -22495,6 +22797,7 @@ class WsControlChannel {
|
|
|
22495
22797
|
opts;
|
|
22496
22798
|
statusValue = "idle";
|
|
22497
22799
|
commandCbs = [];
|
|
22800
|
+
wakeDesiredCbs = [];
|
|
22498
22801
|
resyncHooks = [];
|
|
22499
22802
|
ws = null;
|
|
22500
22803
|
attempt = 0;
|
|
@@ -22504,6 +22807,7 @@ class WsControlChannel {
|
|
|
22504
22807
|
pongDeadline = 0;
|
|
22505
22808
|
resyncProvider = null;
|
|
22506
22809
|
log;
|
|
22810
|
+
wakeCoordinator = new WakeCoordinator;
|
|
22507
22811
|
constructor(opts) {
|
|
22508
22812
|
this.opts = opts;
|
|
22509
22813
|
this.log = opts.logger ?? createLogger({ header: "@alook/daemon:ws" });
|
|
@@ -22526,6 +22830,30 @@ class WsControlChannel {
|
|
|
22526
22830
|
onCommand(cb) {
|
|
22527
22831
|
this.commandCbs.push(cb);
|
|
22528
22832
|
}
|
|
22833
|
+
onWakeDesiredAdvance(cb) {
|
|
22834
|
+
this.wakeDesiredCbs.push(cb);
|
|
22835
|
+
}
|
|
22836
|
+
async ingestCommand(frame) {
|
|
22837
|
+
const parsed = HostCommandSchema.safeParse(frame);
|
|
22838
|
+
if (!parsed.success) {
|
|
22839
|
+
this.log.warn("dropped malformed HostCommand frame", {
|
|
22840
|
+
type: typeof frame === "object" && frame !== null && "type" in frame ? String(frame.type) : "unknown",
|
|
22841
|
+
issues: parsed.error.issues.map((issue3) => ({
|
|
22842
|
+
path: issue3.path.join("."),
|
|
22843
|
+
code: issue3.code
|
|
22844
|
+
}))
|
|
22845
|
+
});
|
|
22846
|
+
return false;
|
|
22847
|
+
}
|
|
22848
|
+
await this.dispatchIngressCommand(parsed.data);
|
|
22849
|
+
return true;
|
|
22850
|
+
}
|
|
22851
|
+
modelSeenGeneration(agentId) {
|
|
22852
|
+
return this.wakeCoordinator.modelSeenGeneration(agentId);
|
|
22853
|
+
}
|
|
22854
|
+
recordModelSeen(agentId, messages, generation = this.wakeCoordinator.modelSeenGeneration(agentId)) {
|
|
22855
|
+
return this.wakeCoordinator.recordModelSeen(agentId, messages, generation);
|
|
22856
|
+
}
|
|
22529
22857
|
onResync(provider) {
|
|
22530
22858
|
this.resyncProvider = provider;
|
|
22531
22859
|
}
|
|
@@ -22542,6 +22870,7 @@ class WsControlChannel {
|
|
|
22542
22870
|
this.sendFrame({ type: "agent_session", ...info });
|
|
22543
22871
|
}
|
|
22544
22872
|
async reportAgentActivity(info) {
|
|
22873
|
+
this.wakeCoordinator.recordAgentActivity(info.agentId, info.state);
|
|
22545
22874
|
this.sendFrame({ type: "agent_activity", ...info });
|
|
22546
22875
|
}
|
|
22547
22876
|
reportAgentTyping(info) {
|
|
@@ -22554,6 +22883,7 @@ class WsControlChannel {
|
|
|
22554
22883
|
this.sendFrame(frame);
|
|
22555
22884
|
}
|
|
22556
22885
|
async reportWakeAck(info) {
|
|
22886
|
+
this.wakeCoordinator.recordDeliveryAck(info.agentId, info.launchId, info.status);
|
|
22557
22887
|
this.sendFrame({ type: "agent_wake_ack", ...info });
|
|
22558
22888
|
}
|
|
22559
22889
|
async reportStoppedAck(info) {
|
|
@@ -22625,27 +22955,75 @@ class WsControlChannel {
|
|
|
22625
22955
|
return;
|
|
22626
22956
|
}
|
|
22627
22957
|
this.attempt = 0;
|
|
22628
|
-
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
|
|
22633
|
-
|
|
22634
|
-
return;
|
|
22635
|
-
}
|
|
22636
|
-
const cmd = parsed.data;
|
|
22958
|
+
this.ingestCommand(frame).catch((err) => {
|
|
22959
|
+
this.log.warn("command ingress failed", { type: frame.type, err: describeErr(err) });
|
|
22960
|
+
});
|
|
22961
|
+
}
|
|
22962
|
+
async dispatchListeners(cmd) {
|
|
22963
|
+
const pending = [];
|
|
22637
22964
|
for (const cb of this.commandCbs) {
|
|
22638
22965
|
try {
|
|
22639
22966
|
const result = cb(cmd);
|
|
22640
22967
|
if (result === WS_CONTROL_COMMAND_CONSUMED)
|
|
22641
22968
|
break;
|
|
22642
|
-
Promise.resolve(result).catch((err) => {
|
|
22969
|
+
pending.push(Promise.resolve(result).catch((err) => {
|
|
22643
22970
|
this.log.warn("command listener threw", { type: cmd.type, err: describeErr(err) });
|
|
22644
|
-
});
|
|
22971
|
+
}));
|
|
22645
22972
|
} catch (err) {
|
|
22646
22973
|
this.log.warn("command listener threw synchronously", { type: cmd.type, err: describeErr(err) });
|
|
22647
22974
|
}
|
|
22648
22975
|
}
|
|
22976
|
+
await Promise.all(pending);
|
|
22977
|
+
}
|
|
22978
|
+
async dispatchIngressCommand(cmd) {
|
|
22979
|
+
if (cmd.type === "machine:heartbeat") {
|
|
22980
|
+
this.sendFrame({ type: "machine_heartbeat_ack", nonce: cmd.nonce });
|
|
22981
|
+
return;
|
|
22982
|
+
}
|
|
22983
|
+
if (cmd.type === "diagnostics:collect") {
|
|
22984
|
+
this.sendFrame({ type: "diagnostics_ack", reportId: cmd.reportId });
|
|
22985
|
+
await this.dispatchListeners(cmd);
|
|
22986
|
+
return;
|
|
22987
|
+
}
|
|
22988
|
+
if (cmd.type === "agent:wake") {
|
|
22989
|
+
const result = await this.wakeCoordinator.run(cmd, (accepted) => this.dispatchListeners(accepted), (advanced) => {
|
|
22990
|
+
for (const cb of this.wakeDesiredCbs) {
|
|
22991
|
+
try {
|
|
22992
|
+
cb(advanced);
|
|
22993
|
+
} catch (err) {
|
|
22994
|
+
this.log.warn("wake desired observer threw", { err: describeErr(err) });
|
|
22995
|
+
}
|
|
22996
|
+
}
|
|
22997
|
+
});
|
|
22998
|
+
if (result.state === "suppressed") {
|
|
22999
|
+
await this.reportWakeAck({
|
|
23000
|
+
agentId: cmd.agentId,
|
|
23001
|
+
launchId: cmd.launchId,
|
|
23002
|
+
status: "ok"
|
|
23003
|
+
});
|
|
23004
|
+
this.log.debug("duplicate wake suppressed", {
|
|
23005
|
+
agentId: cmd.agentId,
|
|
23006
|
+
channel: cmd.unreadNotice.channel,
|
|
23007
|
+
latestSeq: cmd.unreadNotice.latestSeq,
|
|
23008
|
+
coveredSeq: result.coveredSeq
|
|
23009
|
+
});
|
|
23010
|
+
}
|
|
23011
|
+
return;
|
|
23012
|
+
}
|
|
23013
|
+
if (cmd.type === "machine:reset_all") {
|
|
23014
|
+
for (const reset of cmd.resets)
|
|
23015
|
+
this.wakeCoordinator.invalidate(reset.agentId, true);
|
|
23016
|
+
await this.dispatchListeners(cmd);
|
|
23017
|
+
return;
|
|
23018
|
+
}
|
|
23019
|
+
if (cmd.type === "agent:stop" || cmd.type === "agent:model_switch") {
|
|
23020
|
+
this.wakeCoordinator.invalidate(cmd.agentId, false);
|
|
23021
|
+
} else if (cmd.type === "agent:reset" || cmd.type === "agent:nap") {
|
|
23022
|
+
this.wakeCoordinator.invalidate(cmd.agentId, true);
|
|
23023
|
+
} else if (cmd.type === "bot:removed") {
|
|
23024
|
+
this.wakeCoordinator.invalidate(cmd.botId, true);
|
|
23025
|
+
}
|
|
23026
|
+
await this.dispatchListeners(cmd);
|
|
22649
23027
|
}
|
|
22650
23028
|
onSocketClosed(code, reason) {
|
|
22651
23029
|
this.log.warn("control channel closed", { code, reason: reason ? String(reason) : "" });
|
|
@@ -22680,7 +23058,10 @@ class WsControlChannel {
|
|
|
22680
23058
|
this.pingTimer = setInterval(() => {
|
|
22681
23059
|
if (this.now() > this.pongDeadline) {
|
|
22682
23060
|
this.log.warn("heartbeat pong timeout — forcing reconnect");
|
|
22683
|
-
this.ws?.
|
|
23061
|
+
if (this.ws?.terminate)
|
|
23062
|
+
this.ws.terminate();
|
|
23063
|
+
else
|
|
23064
|
+
this.ws?.close();
|
|
22684
23065
|
return;
|
|
22685
23066
|
}
|
|
22686
23067
|
this.log.debug("heartbeat ping");
|
|
@@ -23259,6 +23640,8 @@ function createTimelineRecorder(opts) {
|
|
|
23259
23640
|
sessionByAgent.set(agentId, sessionId);
|
|
23260
23641
|
},
|
|
23261
23642
|
appendEntryForAgent(agentId, messages) {
|
|
23643
|
+
if (messages.length === 0)
|
|
23644
|
+
return;
|
|
23262
23645
|
const dir = dirFor(agentId);
|
|
23263
23646
|
if (!prepareTimelineDirectory(dir))
|
|
23264
23647
|
return;
|
|
@@ -23747,7 +24130,16 @@ async function createDaemon(opts) {
|
|
|
23747
24130
|
const typingTracker = createTypingScopeTracker();
|
|
23748
24131
|
const broker = new CredentialBroker({ upstreamBaseUrl: opts.serverUrl });
|
|
23749
24132
|
const proxy = await startCredentialProxy(broker, {
|
|
23750
|
-
|
|
24133
|
+
onInboxPullStart: (agentId) => channelRef?.modelSeenGeneration(agentId),
|
|
24134
|
+
onInboxPullResponse: (agentId, messages, observationToken) => {
|
|
24135
|
+
timeline2.appendEntryForAgent(agentId, messages);
|
|
24136
|
+
if (typeof observationToken === "number") {
|
|
24137
|
+
channelRef?.recordModelSeen(agentId, messages, observationToken);
|
|
24138
|
+
}
|
|
24139
|
+
},
|
|
24140
|
+
onInboxPullObservationError: ({ agentId, reason, contentEncoding }) => {
|
|
24141
|
+
log.warn("inbox pull timeline observation failed", { agentId, reason, contentEncoding });
|
|
24142
|
+
},
|
|
23751
24143
|
onMessageReminderArm: (input) => reminderSchedulerRef?.arm(input) ?? { armed: false, reason: "reminder_scheduler_unavailable" },
|
|
23752
24144
|
onProxyRequest: (agentId, method, pathname) => {
|
|
23753
24145
|
const subcommand = deriveAuditLogSubcommand(pathname, method);
|
|
@@ -23848,11 +24240,29 @@ async function createDaemon(opts) {
|
|
|
23848
24240
|
if (!res.ok)
|
|
23849
24241
|
throw new Error(`resync-wakes ${res.status}`);
|
|
23850
24242
|
const json2 = await res.json();
|
|
23851
|
-
log.info("wake resync completed", {
|
|
24243
|
+
log.info("wake resync completed", { attempted: json2.attempted ?? 0 });
|
|
23852
24244
|
} catch (err) {
|
|
23853
24245
|
log.warn("wake resync failed", { err: err instanceof Error ? err.message : String(err) });
|
|
23854
24246
|
}
|
|
23855
24247
|
}
|
|
24248
|
+
async function resyncPendingDiagnostics() {
|
|
24249
|
+
try {
|
|
24250
|
+
const res = await fetch(`${opts.serverUrl}/api/community/daemon/resync-diagnostics`, {
|
|
24251
|
+
method: "POST",
|
|
24252
|
+
headers: { authorization: `Bearer ${opts.machineKey}` }
|
|
24253
|
+
});
|
|
24254
|
+
if (!res.ok)
|
|
24255
|
+
throw new Error(`resync-diagnostics ${res.status}`);
|
|
24256
|
+
const json2 = await res.json();
|
|
24257
|
+
log.info("diagnostics resync completed", {
|
|
24258
|
+
pending: json2.pending ?? 0,
|
|
24259
|
+
attempted: json2.attempted ?? 0,
|
|
24260
|
+
ambiguous: json2.ambiguous ?? 0
|
|
24261
|
+
});
|
|
24262
|
+
} catch (err) {
|
|
24263
|
+
log.warn("diagnostics resync failed", { err: err instanceof Error ? err.message : String(err) });
|
|
24264
|
+
}
|
|
24265
|
+
}
|
|
23856
24266
|
const enrollAgent = async (agentId) => {
|
|
23857
24267
|
const existing = enrolledKeys.get(agentId);
|
|
23858
24268
|
if (existing)
|
|
@@ -24028,7 +24438,10 @@ async function createDaemon(opts) {
|
|
|
24028
24438
|
let statusTimer = null;
|
|
24029
24439
|
if (opts.statusFilePath) {
|
|
24030
24440
|
const statusPath = opts.statusFilePath;
|
|
24031
|
-
const writeStatus = () =>
|
|
24441
|
+
const writeStatus = () => {
|
|
24442
|
+
const nowMs = Date.now();
|
|
24443
|
+
writeStatusFile(statusPath, { writtenAt: nowMs, agents: manager.statusProjection(nowMs) });
|
|
24444
|
+
};
|
|
24032
24445
|
writeStatus();
|
|
24033
24446
|
statusTimer = setInterval(writeStatus, STATUS_WRITE_INTERVAL_MS);
|
|
24034
24447
|
statusTimer.unref?.();
|
|
@@ -24075,11 +24488,11 @@ async function createDaemon(opts) {
|
|
|
24075
24488
|
handleDiagnosticCommand: opts.handleDiagnosticCommand,
|
|
24076
24489
|
reportDiagnosticFailure: opts.reportDiagnosticFailure
|
|
24077
24490
|
}));
|
|
24491
|
+
channel2.onWakeDesiredAdvance((cmd) => {
|
|
24492
|
+
reminderSchedulerRef?.observe(cmd.agentId, cmd.unreadNotice.channel, cmd.unreadNotice.latestSeq);
|
|
24493
|
+
});
|
|
24078
24494
|
channel2.onCommand((cmd) => {
|
|
24079
24495
|
switch (cmd.type) {
|
|
24080
|
-
case "agent:wake":
|
|
24081
|
-
reminderSchedulerRef?.observe(cmd.agentId, cmd.unreadNotice.channel, cmd.unreadNotice.latestSeq);
|
|
24082
|
-
break;
|
|
24083
24496
|
case "agent:stop":
|
|
24084
24497
|
reminderSchedulerRef?.clearAgent(cmd.agentId);
|
|
24085
24498
|
break;
|
|
@@ -24096,6 +24509,7 @@ async function createDaemon(opts) {
|
|
|
24096
24509
|
channel2.onOpen(() => {
|
|
24097
24510
|
coldStartWarmup();
|
|
24098
24511
|
resyncPendingWakes();
|
|
24512
|
+
resyncPendingDiagnostics();
|
|
24099
24513
|
});
|
|
24100
24514
|
channel2.connect();
|
|
24101
24515
|
await router.start();
|