totemlayer 0.1.68 → 0.1.75
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 +10 -14
- package/bin/agent-profile.mjs +6 -1
- package/bin/agent-runner.mjs +28 -2
- package/bin/agent-setup.mjs +2 -0
- package/bin/automatic-runtime.mjs +23 -12
- package/bin/codex-chat-bridge.mjs +72 -38
- package/bin/codex-desktop-wake.mjs +47 -20
- package/bin/codex-human-chat-bridge.mjs +57 -21
- package/bin/codex-mission-bridge.mjs +167 -0
- package/bin/collaboration-companion.mjs +2 -0
- package/bin/connected-agent-service.mjs +12 -2
- package/bin/executor-diagnostic.mjs +169 -61
- package/bin/installation.mjs +10 -16
- package/bin/local-inspector.mjs +6 -0
- package/bin/mcp-install.mjs +15 -1
- package/bin/mcp.mjs +45 -1
- package/bin/mission-worker.mjs +62 -39
- package/bin/model-adapter.mjs +30 -1
- package/bin/native/darwin-lifetime +0 -0
- package/bin/native/darwin-lifetime.json +1 -1
- package/bin/network-contract.mjs +125 -0
- package/bin/network-runtime.mjs +367 -315
- package/bin/network.mjs +2 -0
- package/bin/observability.mjs +336 -0
- package/bin/platform-client.mjs +6 -3
- package/bin/plugin-connect.mjs +10 -0
- package/bin/provider-diagnostics.mjs +40 -11
- package/bin/runtime-installation.mjs +15 -1
- package/bin/runtime-lock.mjs +43 -6
- package/bin/sdk/index.d.ts +1 -0
- package/bin/sdk/index.js +1 -1
- package/bin/setup-assets/api-connect.backup.md +129 -0
- package/bin/setup-assets/api-connect.md +129 -0
- package/bin/setup-assets/api-manifest.json +1 -0
- package/bin/setup-assets/manifest.json +1 -0
- package/bin/setup-assets/setup.backup.md +178 -0
- package/bin/setup-assets/setup.md +178 -0
- package/bin/setup-guide.mjs +39 -0
- package/bin/setup-receipts.mjs +181 -0
- package/bin/strict-codex-adapter.mjs +454 -0
- package/bin/strict-installation.mjs +206 -0
- package/bin/strict-setup-jobs.mjs +253 -0
- package/bin/strict-setup.mjs +385 -0
- package/bin/totem.mjs +11 -1
- package/bin/windows-private-path.mjs +89 -0
- package/package.json +4 -3
- package/scripts/prepare.mjs +2 -0
package/bin/network-runtime.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withAgentObservation, observeGeneration, observationOutcome } from "./observability.mjs";
|
|
1
2
|
import { startupDiagnostic } from "./startup-diagnostics.mjs";
|
|
2
3
|
import { DEFAULT_LISTENER_POLL_MS } from "./sdk/listener.js";
|
|
3
4
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -119,42 +120,44 @@ export async function modelReply({
|
|
|
119
120
|
model ??= provider === "qwen-local" ? "qwen3.5-9b" : undefined;
|
|
120
121
|
const endpoint = localModelEndpoint(provider, { ollamaUrl: origin, qwenUrl, nimUrl });
|
|
121
122
|
try {
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
123
|
+
const data = await observeGeneration({ model, provider, input: messages }, async () => {
|
|
124
|
+
const response = await fetcher(endpoint, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
redirect: "error",
|
|
127
|
+
signal: AbortSignal.any([signal, timeout]),
|
|
128
|
+
headers: { "Content-Type": "application/json" },
|
|
129
|
+
body: JSON.stringify({
|
|
130
|
+
model,
|
|
131
|
+
messages: openai
|
|
132
|
+
? messages.map((message) => {
|
|
133
|
+
const native = { ...message };
|
|
134
|
+
delete native.tool_name;
|
|
135
|
+
if (native.tool_calls)
|
|
136
|
+
native.tool_calls = native.tool_calls.map((call) => ({
|
|
137
|
+
...call,
|
|
138
|
+
function: {
|
|
139
|
+
...call.function,
|
|
140
|
+
arguments: JSON.stringify(call.function.arguments),
|
|
141
|
+
},
|
|
142
|
+
}));
|
|
143
|
+
return native;
|
|
144
|
+
})
|
|
145
|
+
: messages,
|
|
146
|
+
...(tools.length ? { tools } : {}),
|
|
147
|
+
stream: false,
|
|
148
|
+
...(openai
|
|
149
|
+
? {
|
|
150
|
+
...(provider === "qwen-local"
|
|
151
|
+
? { chat_template_kwargs: { enable_thinking: false } }
|
|
152
|
+
: {}),
|
|
153
|
+
max_tokens: 512,
|
|
154
|
+
temperature: 0,
|
|
155
|
+
}
|
|
156
|
+
: { think: false, options: { num_predict: 512, temperature: 0 } }),
|
|
157
|
+
}),
|
|
158
|
+
});
|
|
159
|
+
return responseJson(response);
|
|
156
160
|
});
|
|
157
|
-
const data = await responseJson(response);
|
|
158
161
|
const message = openai ? data?.choices?.[0]?.message : data.message;
|
|
159
162
|
if (!message || message.role !== "assistant") throw new Error("Invalid model response.");
|
|
160
163
|
const text = typeof message.content === "string" ? message.content.trim() : "";
|
|
@@ -348,7 +351,20 @@ async function explicitAskReply({ client, identity, journal, command, request, s
|
|
|
348
351
|
return state.final;
|
|
349
352
|
}
|
|
350
353
|
|
|
351
|
-
async function generate({
|
|
354
|
+
async function generate(options) {
|
|
355
|
+
return withAgentObservation(
|
|
356
|
+
{
|
|
357
|
+
client: options.client,
|
|
358
|
+
agentId: options.identity.id,
|
|
359
|
+
sessionId: options.settings.observabilitySessionId ?? options.key,
|
|
360
|
+
traceId: options.key,
|
|
361
|
+
input: options.text,
|
|
362
|
+
},
|
|
363
|
+
() => generateCore(options),
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
async function generateCore({
|
|
352
368
|
client,
|
|
353
369
|
identity,
|
|
354
370
|
journal,
|
|
@@ -842,6 +858,10 @@ export async function runRuntime(settings) {
|
|
|
842
858
|
{ signal },
|
|
843
859
|
))
|
|
844
860
|
yield message;
|
|
861
|
+
emit({
|
|
862
|
+
type: "receive_check",
|
|
863
|
+
data: { checkedAt: Date.now(), intervalSeconds: settings.pollMs / 1000 },
|
|
864
|
+
});
|
|
845
865
|
if (diagnostics.phase === "reconnecting") {
|
|
846
866
|
diagnostics = { phase: "waiting" };
|
|
847
867
|
emit({ type: "runtime_resumed" });
|
|
@@ -855,149 +875,163 @@ export async function runRuntime(settings) {
|
|
|
855
875
|
// Retry screening; the execution journal still guards unknown outcomes.
|
|
856
876
|
return !blocker || blocker.code === "INSPECTION_UNAVAILABLE";
|
|
857
877
|
},
|
|
858
|
-
handle: async (message, signal) =>
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
878
|
+
handle: async (message, signal) =>
|
|
879
|
+
withAgentObservation(
|
|
880
|
+
{
|
|
881
|
+
client,
|
|
882
|
+
agentId: identity.id,
|
|
883
|
+
sessionId: message.conversationId,
|
|
884
|
+
traceId: "message:" + message.id,
|
|
885
|
+
input: message.content,
|
|
886
|
+
},
|
|
887
|
+
async () => {
|
|
888
|
+
try {
|
|
889
|
+
diagnostics = { phase: "working", messageId: message.id };
|
|
890
|
+
emit({ type: "message_started", data: { messageId: message.id } });
|
|
891
|
+
if (settings.codexThreadId) {
|
|
892
|
+
const delivery = await queueCodexChatMessage({
|
|
893
|
+
settings,
|
|
894
|
+
client,
|
|
895
|
+
identity,
|
|
896
|
+
journal,
|
|
897
|
+
message,
|
|
898
|
+
signal,
|
|
899
|
+
});
|
|
900
|
+
if (delivery.state === "uncertain") {
|
|
901
|
+
report({ code: "AGENT_OUTCOME_UNCERTAIN" }, { messageId: message.id });
|
|
902
|
+
} else {
|
|
903
|
+
diagnostics = { phase: "waiting" };
|
|
904
|
+
emit({
|
|
905
|
+
type: delivery.state === "confirmed" ? "message_handled" : "chat_queued",
|
|
906
|
+
data: { messageId: message.id, threadId: settings.codexThreadId },
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
await inspectNetworkMessage(settings.inspector, client, message, { signal });
|
|
912
|
+
const continuation = autonomousReplyMetadata(message, settings, identity.address);
|
|
913
|
+
const activeTask = await activeTaskForReply(client, message, identity, signal);
|
|
914
|
+
if (message.inReplyToId && !activeTask && (message.taskId || !continuation)) {
|
|
915
|
+
await client.messages.ack(message.id, { signal });
|
|
916
|
+
diagnostics = { phase: "waiting" };
|
|
917
|
+
emit({ type: "message_handled", data: { messageId: message.id } });
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
const thread = [];
|
|
921
|
+
let cursor;
|
|
922
|
+
for (let page = 0; page < 5; page++) {
|
|
923
|
+
const result = settings.connectionOnly
|
|
924
|
+
? await client.messages.list(
|
|
925
|
+
{
|
|
926
|
+
conversationId: message.conversationId,
|
|
927
|
+
limit: 100,
|
|
928
|
+
...(cursor ? { cursor } : {}),
|
|
929
|
+
},
|
|
930
|
+
{ signal },
|
|
931
|
+
)
|
|
932
|
+
: await client.conversations.messages(
|
|
933
|
+
message.conversationId,
|
|
934
|
+
{ limit: 100, ...(cursor ? { cursor } : {}) },
|
|
935
|
+
{ signal },
|
|
936
|
+
);
|
|
937
|
+
thread.push(...result.data);
|
|
938
|
+
if (thread.some((item) => item.id === message.id) || !result.nextCursor) break;
|
|
939
|
+
cursor = result.nextCursor;
|
|
940
|
+
}
|
|
941
|
+
const safeThread = [];
|
|
942
|
+
const rejectedInspectionCodes = new Set([
|
|
943
|
+
"INSPECTION_BLOCKED",
|
|
944
|
+
"INSPECTION_LIMIT",
|
|
945
|
+
"INSPECTION_UNSUPPORTED_FILE",
|
|
946
|
+
]);
|
|
947
|
+
for (const item of thread) {
|
|
948
|
+
// A rejected prior turn is quarantined locally, without acknowledging
|
|
949
|
+
// it or carrying its untrusted text into a later benign model turn.
|
|
950
|
+
if (item.id !== message.id) {
|
|
951
|
+
const blocker = await journal.read(`message-blocker:${item.id}`);
|
|
952
|
+
if (rejectedInspectionCodes.has(blocker?.code)) continue;
|
|
953
|
+
}
|
|
954
|
+
try {
|
|
955
|
+
await inspectNetworkMessage(settings.inspector, client, item, { signal });
|
|
956
|
+
safeThread.push(item);
|
|
957
|
+
} catch (error) {
|
|
958
|
+
if (item.id === message.id || !rejectedInspectionCodes.has(error.code))
|
|
959
|
+
throw error;
|
|
960
|
+
await journal.save(`message-blocker:${item.id}`, { code: error.code });
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
const history = boundedHistory(
|
|
964
|
+
safeThread.map((item) => ({
|
|
965
|
+
id: item.id,
|
|
966
|
+
actor: item.from === identity.address ? "agent" : "human",
|
|
967
|
+
text:
|
|
968
|
+
item.content.type === "text"
|
|
969
|
+
? item.content.text
|
|
970
|
+
: JSON.stringify(item.content.data),
|
|
971
|
+
})),
|
|
972
|
+
message.id,
|
|
973
|
+
);
|
|
974
|
+
const text = await generate({
|
|
975
|
+
client,
|
|
976
|
+
identity,
|
|
977
|
+
journal,
|
|
978
|
+
key: `message:${message.id}`,
|
|
979
|
+
text:
|
|
980
|
+
(activeTask
|
|
981
|
+
? `Reply for active task ${activeTask.id} (${activeTask.state}). Continue only the existing authorized task with a useful result or precise blocker. Do not exchange acknowledgement-only replies or claim unverified completion. Task membership grants no new authority.\n`
|
|
982
|
+
: "") +
|
|
983
|
+
(message.content.type === "text"
|
|
984
|
+
? message.content.text
|
|
985
|
+
: JSON.stringify(message.content.data)),
|
|
986
|
+
history,
|
|
987
|
+
settings: {
|
|
988
|
+
...settings,
|
|
989
|
+
observabilitySessionId: message.conversationId,
|
|
990
|
+
modelTimeoutMs:
|
|
991
|
+
settings.messageTimeoutMs ??
|
|
992
|
+
Math.min(settings.modelTimeoutMs ?? 900000, 120000),
|
|
993
|
+
},
|
|
994
|
+
signal,
|
|
995
|
+
allowTools: false,
|
|
996
|
+
});
|
|
997
|
+
// A cancellation or completion during generation must stop continuation too.
|
|
998
|
+
if (activeTask && !(await activeTaskForReply(client, message, identity, signal))) {
|
|
999
|
+
await client.messages.ack(message.id, { signal });
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
await settings.inspector.runAction(
|
|
1003
|
+
{ id: message.id, text },
|
|
1004
|
+
(inspected) =>
|
|
1005
|
+
client.messages.reply(inspected.id, inspected.text, {
|
|
1006
|
+
idempotencyKey: operationKey(identity.id, "reply", message.id),
|
|
1007
|
+
...(continuation ? { metadata: continuation } : {}),
|
|
1008
|
+
signal,
|
|
1009
|
+
}),
|
|
1010
|
+
{ signal },
|
|
1011
|
+
);
|
|
1012
|
+
await client.messages.ack(message.id, { signal });
|
|
874
1013
|
diagnostics = { phase: "waiting" };
|
|
875
1014
|
emit({
|
|
876
|
-
type:
|
|
877
|
-
data: { messageId: message.id,
|
|
1015
|
+
type: "message_handled",
|
|
1016
|
+
data: { messageId: message.id, conversationId: message.conversationId },
|
|
878
1017
|
});
|
|
879
|
-
}
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
882
|
-
await inspectNetworkMessage(settings.inspector, client, message, { signal });
|
|
883
|
-
const continuation = autonomousReplyMetadata(message, settings, identity.address);
|
|
884
|
-
const activeTask = await activeTaskForReply(client, message, identity, signal);
|
|
885
|
-
if (message.inReplyToId && !activeTask && (message.taskId || !continuation)) {
|
|
886
|
-
await client.messages.ack(message.id, { signal });
|
|
887
|
-
diagnostics = { phase: "waiting" };
|
|
888
|
-
emit({ type: "message_handled", data: { messageId: message.id } });
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
const thread = [];
|
|
892
|
-
let cursor;
|
|
893
|
-
for (let page = 0; page < 5; page++) {
|
|
894
|
-
const result = settings.connectionOnly
|
|
895
|
-
? await client.messages.list(
|
|
896
|
-
{
|
|
897
|
-
conversationId: message.conversationId,
|
|
898
|
-
limit: 100,
|
|
899
|
-
...(cursor ? { cursor } : {}),
|
|
900
|
-
},
|
|
901
|
-
{ signal },
|
|
902
|
-
)
|
|
903
|
-
: await client.conversations.messages(
|
|
904
|
-
message.conversationId,
|
|
905
|
-
{ limit: 100, ...(cursor ? { cursor } : {}) },
|
|
906
|
-
{ signal },
|
|
907
|
-
);
|
|
908
|
-
thread.push(...result.data);
|
|
909
|
-
if (thread.some((item) => item.id === message.id) || !result.nextCursor) break;
|
|
910
|
-
cursor = result.nextCursor;
|
|
911
|
-
}
|
|
912
|
-
const safeThread = [];
|
|
913
|
-
const rejectedInspectionCodes = new Set([
|
|
914
|
-
"INSPECTION_BLOCKED",
|
|
915
|
-
"INSPECTION_LIMIT",
|
|
916
|
-
"INSPECTION_UNSUPPORTED_FILE",
|
|
917
|
-
]);
|
|
918
|
-
for (const item of thread) {
|
|
919
|
-
// A rejected prior turn is quarantined locally, without acknowledging
|
|
920
|
-
// it or carrying its untrusted text into a later benign model turn.
|
|
921
|
-
if (item.id !== message.id) {
|
|
922
|
-
const blocker = await journal.read(`message-blocker:${item.id}`);
|
|
923
|
-
if (rejectedInspectionCodes.has(blocker?.code)) continue;
|
|
924
|
-
}
|
|
925
|
-
try {
|
|
926
|
-
await inspectNetworkMessage(settings.inspector, client, item, { signal });
|
|
927
|
-
safeThread.push(item);
|
|
928
1018
|
} catch (error) {
|
|
929
|
-
|
|
930
|
-
|
|
1019
|
+
observationOutcome({ error });
|
|
1020
|
+
if (!signal.aborted) report(error, { messageId: message.id });
|
|
1021
|
+
if (error.status === 401) throw error;
|
|
1022
|
+
// Retry this durable message on the next poll without stopping other turns.
|
|
1023
|
+
if (transientNetworkError(error) || error.code === "INSPECTION_UNAVAILABLE") return;
|
|
1024
|
+
if (
|
|
1025
|
+
(error.status >= 400 && error.status < 500) ||
|
|
1026
|
+
error.code === "AGENT_OUTCOME_UNCERTAIN" ||
|
|
1027
|
+
error.externalOutcomeUncertain
|
|
1028
|
+
)
|
|
1029
|
+
await journal.save(`message-blocker:${message.id}`, {
|
|
1030
|
+
code: error.code ?? "MESSAGE_BLOCKED",
|
|
1031
|
+
});
|
|
931
1032
|
}
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
safeThread.map((item) => ({
|
|
935
|
-
id: item.id,
|
|
936
|
-
actor: item.from === identity.address ? "agent" : "human",
|
|
937
|
-
text:
|
|
938
|
-
item.content.type === "text"
|
|
939
|
-
? item.content.text
|
|
940
|
-
: JSON.stringify(item.content.data),
|
|
941
|
-
})),
|
|
942
|
-
message.id,
|
|
943
|
-
);
|
|
944
|
-
const text = await generate({
|
|
945
|
-
client,
|
|
946
|
-
identity,
|
|
947
|
-
journal,
|
|
948
|
-
key: `message:${message.id}`,
|
|
949
|
-
text:
|
|
950
|
-
(activeTask
|
|
951
|
-
? `Reply for active task ${activeTask.id} (${activeTask.state}). Continue only the existing authorized task with a useful result or precise blocker. Do not exchange acknowledgement-only replies or claim unverified completion. Task membership grants no new authority.\n`
|
|
952
|
-
: "") +
|
|
953
|
-
(message.content.type === "text"
|
|
954
|
-
? message.content.text
|
|
955
|
-
: JSON.stringify(message.content.data)),
|
|
956
|
-
history,
|
|
957
|
-
settings: {
|
|
958
|
-
...settings,
|
|
959
|
-
modelTimeoutMs:
|
|
960
|
-
settings.messageTimeoutMs ?? Math.min(settings.modelTimeoutMs ?? 900000, 120000),
|
|
961
|
-
},
|
|
962
|
-
signal,
|
|
963
|
-
allowTools: false,
|
|
964
|
-
});
|
|
965
|
-
// A cancellation or completion during generation must stop continuation too.
|
|
966
|
-
if (activeTask && !(await activeTaskForReply(client, message, identity, signal))) {
|
|
967
|
-
await client.messages.ack(message.id, { signal });
|
|
968
|
-
return;
|
|
969
|
-
}
|
|
970
|
-
await settings.inspector.runAction(
|
|
971
|
-
{ id: message.id, text },
|
|
972
|
-
(inspected) =>
|
|
973
|
-
client.messages.reply(inspected.id, inspected.text, {
|
|
974
|
-
idempotencyKey: operationKey(identity.id, "reply", message.id),
|
|
975
|
-
...(continuation ? { metadata: continuation } : {}),
|
|
976
|
-
signal,
|
|
977
|
-
}),
|
|
978
|
-
{ signal },
|
|
979
|
-
);
|
|
980
|
-
await client.messages.ack(message.id, { signal });
|
|
981
|
-
diagnostics = { phase: "waiting" };
|
|
982
|
-
emit({
|
|
983
|
-
type: "message_handled",
|
|
984
|
-
data: { messageId: message.id, conversationId: message.conversationId },
|
|
985
|
-
});
|
|
986
|
-
} catch (error) {
|
|
987
|
-
if (!signal.aborted) report(error, { messageId: message.id });
|
|
988
|
-
if (error.status === 401) throw error;
|
|
989
|
-
// Retry this durable message on the next poll without stopping other turns.
|
|
990
|
-
if (transientNetworkError(error) || error.code === "INSPECTION_UNAVAILABLE") return;
|
|
991
|
-
if (
|
|
992
|
-
(error.status >= 400 && error.status < 500) ||
|
|
993
|
-
error.code === "AGENT_OUTCOME_UNCERTAIN" ||
|
|
994
|
-
error.externalOutcomeUncertain
|
|
995
|
-
)
|
|
996
|
-
await journal.save(`message-blocker:${message.id}`, {
|
|
997
|
-
code: error.code ?? "MESSAGE_BLOCKED",
|
|
998
|
-
});
|
|
999
|
-
}
|
|
1000
|
-
},
|
|
1033
|
+
},
|
|
1034
|
+
),
|
|
1001
1035
|
}).catch((error) => {
|
|
1002
1036
|
if (!signal.aborted) {
|
|
1003
1037
|
fatalError = error;
|
|
@@ -1056,159 +1090,177 @@ export async function runRuntime(settings) {
|
|
|
1056
1090
|
}
|
|
1057
1091
|
}
|
|
1058
1092
|
})().catch(() => {});
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
// Keep the lease alive while independently processing inbound peer replies.
|
|
1079
|
-
while (!commandSignal.aborted) {
|
|
1080
|
-
const { run } = await retryNetwork(
|
|
1081
|
-
() => readCodexChatCommand(client, command, commandSignal),
|
|
1082
|
-
{ signal: commandSignal, delayMs: settings.pollMs, onRetry: report },
|
|
1083
|
-
);
|
|
1084
|
-
if (["completed", "failed", "canceled"].includes(run.state)) {
|
|
1093
|
+
await withAgentObservation(
|
|
1094
|
+
{
|
|
1095
|
+
client,
|
|
1096
|
+
agentId: identity.id,
|
|
1097
|
+
sessionId: command.chatId,
|
|
1098
|
+
traceId: "chat:" + command.id,
|
|
1099
|
+
input: command.text,
|
|
1100
|
+
},
|
|
1101
|
+
async () => {
|
|
1102
|
+
try {
|
|
1103
|
+
if (settings.codexThreadId) {
|
|
1104
|
+
const delivery = await queueCodexChatCommand({
|
|
1105
|
+
settings,
|
|
1106
|
+
client,
|
|
1107
|
+
identity,
|
|
1108
|
+
command,
|
|
1109
|
+
claim,
|
|
1110
|
+
signal: commandSignal,
|
|
1111
|
+
});
|
|
1085
1112
|
emit({
|
|
1086
|
-
type:
|
|
1087
|
-
data: {
|
|
1113
|
+
type: delivery.state === "uncertain" ? "chat_uncertain" : "chat_queued",
|
|
1114
|
+
data: {
|
|
1115
|
+
chatId: command.chatId,
|
|
1116
|
+
commandId: command.id,
|
|
1117
|
+
threadId: settings.codexThreadId,
|
|
1118
|
+
},
|
|
1088
1119
|
});
|
|
1089
|
-
|
|
1120
|
+
// Native tools perform the work; only the native callback completes it.
|
|
1121
|
+
// Keep the lease alive while independently processing inbound peer replies.
|
|
1122
|
+
while (!commandSignal.aborted) {
|
|
1123
|
+
const { run } = await retryNetwork(
|
|
1124
|
+
() => readCodexChatCommand(client, command, commandSignal),
|
|
1125
|
+
{ signal: commandSignal, delayMs: settings.pollMs, onRetry: report },
|
|
1126
|
+
);
|
|
1127
|
+
if (["completed", "failed", "canceled"].includes(run.state)) {
|
|
1128
|
+
emit({
|
|
1129
|
+
type: `chat_${run.state}`,
|
|
1130
|
+
data: { chatId: command.chatId, commandId: command.id },
|
|
1131
|
+
});
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
1134
|
+
await pause(Math.max(settings.pollMs, 1000), commandSignal);
|
|
1135
|
+
}
|
|
1136
|
+
return;
|
|
1090
1137
|
}
|
|
1091
|
-
await
|
|
1092
|
-
}
|
|
1093
|
-
continue;
|
|
1094
|
-
}
|
|
1095
|
-
await settings.inspector.assertAllowed("input", command.text, { signal: commandSignal });
|
|
1096
|
-
const explicitRequest = parseAskCommand(command.text);
|
|
1097
|
-
let text;
|
|
1098
|
-
if (explicitRequest) {
|
|
1099
|
-
text = await explicitAskReply({
|
|
1100
|
-
client,
|
|
1101
|
-
identity,
|
|
1102
|
-
journal,
|
|
1103
|
-
command,
|
|
1104
|
-
request: explicitRequest,
|
|
1105
|
-
settings,
|
|
1106
|
-
signal: commandSignal,
|
|
1107
|
-
});
|
|
1108
|
-
} else {
|
|
1109
|
-
const chatEvents = [];
|
|
1110
|
-
let chatCursor = "0";
|
|
1111
|
-
for (let page = 0; page < 100; page++) {
|
|
1112
|
-
const detail = await client.chats.get(command.chatId, {
|
|
1138
|
+
await settings.inspector.assertAllowed("input", command.text, {
|
|
1113
1139
|
signal: commandSignal,
|
|
1114
|
-
limit: 100,
|
|
1115
|
-
...(chatCursor ? { cursor: chatCursor } : {}),
|
|
1116
1140
|
});
|
|
1117
|
-
|
|
1118
|
-
|
|
1141
|
+
const explicitRequest = parseAskCommand(command.text);
|
|
1142
|
+
let text;
|
|
1143
|
+
if (explicitRequest) {
|
|
1144
|
+
text = await explicitAskReply({
|
|
1145
|
+
client,
|
|
1146
|
+
identity,
|
|
1147
|
+
journal,
|
|
1148
|
+
command,
|
|
1149
|
+
request: explicitRequest,
|
|
1150
|
+
settings,
|
|
1151
|
+
signal: commandSignal,
|
|
1152
|
+
});
|
|
1153
|
+
} else {
|
|
1154
|
+
const chatEvents = [];
|
|
1155
|
+
let chatCursor = "0";
|
|
1156
|
+
for (let page = 0; page < 100; page++) {
|
|
1157
|
+
const detail = await client.chats.get(command.chatId, {
|
|
1158
|
+
signal: commandSignal,
|
|
1159
|
+
limit: 100,
|
|
1160
|
+
...(chatCursor ? { cursor: chatCursor } : {}),
|
|
1161
|
+
});
|
|
1162
|
+
chatEvents.push(...detail.events);
|
|
1163
|
+
await settings.inspector.assertAllowed("input", detail.events, {
|
|
1164
|
+
signal: commandSignal,
|
|
1165
|
+
});
|
|
1166
|
+
if (
|
|
1167
|
+
chatEvents.some((event) => event.id === command.commandEventId) ||
|
|
1168
|
+
!detail.hasMore
|
|
1169
|
+
)
|
|
1170
|
+
break;
|
|
1171
|
+
chatEvents.splice(0, Math.max(0, chatEvents.length - 24));
|
|
1172
|
+
chatCursor = detail.nextCursor;
|
|
1173
|
+
}
|
|
1174
|
+
text = await generate({
|
|
1175
|
+
client,
|
|
1176
|
+
identity,
|
|
1177
|
+
journal,
|
|
1178
|
+
key: `chat:${command.commandEventId}`,
|
|
1179
|
+
text: command.text,
|
|
1180
|
+
history: boundedHistory(chatEvents, command.commandEventId),
|
|
1181
|
+
settings: { ...settings, observabilitySessionId: command.chatId },
|
|
1182
|
+
signal: commandSignal,
|
|
1183
|
+
allowTools: true,
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
observationOutcome({ output: text });
|
|
1187
|
+
if (leaseError) throw leaseError;
|
|
1188
|
+
await settings.inspector.assertAllowed("output", text, {
|
|
1189
|
+
task: command.text,
|
|
1119
1190
|
signal: commandSignal,
|
|
1120
1191
|
});
|
|
1121
|
-
|
|
1122
|
-
chatEvents.some((event) => event.id === command.commandEventId) ||
|
|
1123
|
-
!detail.hasMore
|
|
1124
|
-
)
|
|
1125
|
-
break;
|
|
1126
|
-
chatEvents.splice(0, Math.max(0, chatEvents.length - 24));
|
|
1127
|
-
chatCursor = detail.nextCursor;
|
|
1128
|
-
}
|
|
1129
|
-
text = await generate({
|
|
1130
|
-
client,
|
|
1131
|
-
identity,
|
|
1132
|
-
journal,
|
|
1133
|
-
key: `chat:${command.commandEventId}`,
|
|
1134
|
-
text: command.text,
|
|
1135
|
-
history: boundedHistory(chatEvents, command.commandEventId),
|
|
1136
|
-
settings,
|
|
1137
|
-
signal: commandSignal,
|
|
1138
|
-
allowTools: true,
|
|
1139
|
-
});
|
|
1140
|
-
}
|
|
1141
|
-
if (leaseError) throw leaseError;
|
|
1142
|
-
await settings.inspector.assertAllowed("output", text, {
|
|
1143
|
-
task: command.text,
|
|
1144
|
-
signal: commandSignal,
|
|
1145
|
-
});
|
|
1146
|
-
await client.chatCommands.complete(
|
|
1147
|
-
command.id,
|
|
1148
|
-
{ leaseToken: claim.leaseToken, text },
|
|
1149
|
-
{
|
|
1150
|
-
idempotencyKey: operationKey(identity.id, "complete", command.commandEventId),
|
|
1151
|
-
signal: commandSignal,
|
|
1152
|
-
},
|
|
1153
|
-
);
|
|
1154
|
-
emit({ type: "chat_completed", data: { chatId: command.chatId, commandId: command.id } });
|
|
1155
|
-
leaseStop.abort();
|
|
1156
|
-
if (!settings.connectionOnly && !explicitRequest)
|
|
1157
|
-
await learnAgentMemory({
|
|
1158
|
-
client,
|
|
1159
|
-
agentId: identity.id,
|
|
1160
|
-
key: command.commandEventId,
|
|
1161
|
-
turn: { user: command.text, assistant: text },
|
|
1162
|
-
journal,
|
|
1163
|
-
inspector: settings.inspector,
|
|
1164
|
-
signal,
|
|
1165
|
-
emit,
|
|
1166
|
-
generate: async (messages) =>
|
|
1167
|
-
(
|
|
1168
|
-
await modelReply({
|
|
1169
|
-
origin: settings.origin,
|
|
1170
|
-
provider: settings.provider,
|
|
1171
|
-
qwenUrl: settings.qwenUrl,
|
|
1172
|
-
nimUrl: settings.nimUrl,
|
|
1173
|
-
model: settings.model,
|
|
1174
|
-
messages,
|
|
1175
|
-
tools: [],
|
|
1176
|
-
signal,
|
|
1177
|
-
timeoutMs: Math.min(settings.modelTimeoutMs ?? 900000, 30000),
|
|
1178
|
-
adapterSettings: settings.adapterSettings,
|
|
1179
|
-
diagnosticDirectory: settings.diagnosticDirectory,
|
|
1180
|
-
})
|
|
1181
|
-
).content,
|
|
1182
|
-
});
|
|
1183
|
-
} catch (error) {
|
|
1184
|
-
// Native queue outcomes remain durable, never converted into a false failure
|
|
1185
|
-
// or replayed after an uncertain dispatch. Unsent rate-limited work can retry.
|
|
1186
|
-
if (!settings.codexThreadId && !signal.aborted && !leaseError) {
|
|
1187
|
-
try {
|
|
1188
|
-
await client.chatCommands.fail(
|
|
1192
|
+
await client.chatCommands.complete(
|
|
1189
1193
|
command.id,
|
|
1194
|
+
{ leaseToken: claim.leaseToken, text },
|
|
1190
1195
|
{
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
"AGENT_REPLY_TIMEOUT",
|
|
1194
|
-
"INVALID_ASK",
|
|
1195
|
-
"TOOL_NOT_ALLOWED",
|
|
1196
|
-
"INVALID_PEER_REPLY",
|
|
1197
|
-
].includes(error.code)
|
|
1198
|
-
? error.message
|
|
1199
|
-
: "The agent runtime could not complete this request. Check the runtime and send a new message to retry.",
|
|
1196
|
+
idempotencyKey: operationKey(identity.id, "complete", command.commandEventId),
|
|
1197
|
+
signal: commandSignal,
|
|
1200
1198
|
},
|
|
1201
|
-
{ signal },
|
|
1202
1199
|
);
|
|
1203
|
-
|
|
1204
|
-
|
|
1200
|
+
emit({
|
|
1201
|
+
type: "chat_completed",
|
|
1202
|
+
data: { chatId: command.chatId, commandId: command.id },
|
|
1203
|
+
});
|
|
1204
|
+
leaseStop.abort();
|
|
1205
|
+
if (!settings.connectionOnly && !explicitRequest)
|
|
1206
|
+
await learnAgentMemory({
|
|
1207
|
+
client,
|
|
1208
|
+
agentId: identity.id,
|
|
1209
|
+
key: command.commandEventId,
|
|
1210
|
+
turn: { user: command.text, assistant: text },
|
|
1211
|
+
journal,
|
|
1212
|
+
inspector: settings.inspector,
|
|
1213
|
+
signal,
|
|
1214
|
+
emit,
|
|
1215
|
+
generate: async (messages) =>
|
|
1216
|
+
(
|
|
1217
|
+
await modelReply({
|
|
1218
|
+
origin: settings.origin,
|
|
1219
|
+
provider: settings.provider,
|
|
1220
|
+
qwenUrl: settings.qwenUrl,
|
|
1221
|
+
nimUrl: settings.nimUrl,
|
|
1222
|
+
model: settings.model,
|
|
1223
|
+
messages,
|
|
1224
|
+
tools: [],
|
|
1225
|
+
signal,
|
|
1226
|
+
timeoutMs: Math.min(settings.modelTimeoutMs ?? 900000, 30000),
|
|
1227
|
+
adapterSettings: settings.adapterSettings,
|
|
1228
|
+
diagnosticDirectory: settings.diagnosticDirectory,
|
|
1229
|
+
})
|
|
1230
|
+
).content,
|
|
1231
|
+
});
|
|
1232
|
+
} catch (error) {
|
|
1233
|
+
observationOutcome({ error });
|
|
1234
|
+
// Native queue outcomes remain durable, never converted into a false failure
|
|
1235
|
+
// or replayed after an uncertain dispatch. Unsent rate-limited work can retry.
|
|
1236
|
+
if (!settings.codexThreadId && !signal.aborted && !leaseError) {
|
|
1237
|
+
try {
|
|
1238
|
+
await client.chatCommands.fail(
|
|
1239
|
+
command.id,
|
|
1240
|
+
{
|
|
1241
|
+
leaseToken: claim.leaseToken,
|
|
1242
|
+
error: [
|
|
1243
|
+
"AGENT_REPLY_TIMEOUT",
|
|
1244
|
+
"INVALID_ASK",
|
|
1245
|
+
"TOOL_NOT_ALLOWED",
|
|
1246
|
+
"INVALID_PEER_REPLY",
|
|
1247
|
+
].includes(error.code)
|
|
1248
|
+
? error.message
|
|
1249
|
+
: "The agent runtime could not complete this request. Check the runtime and send a new message to retry.",
|
|
1250
|
+
},
|
|
1251
|
+
{ signal },
|
|
1252
|
+
);
|
|
1253
|
+
} catch (failure) {
|
|
1254
|
+
report(failure, { commandId: command.id });
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
if (!signal.aborted) report(leaseError ?? error, { commandId: command.id });
|
|
1258
|
+
} finally {
|
|
1259
|
+
leaseStop.abort();
|
|
1260
|
+
await renewal;
|
|
1205
1261
|
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
} finally {
|
|
1209
|
-
leaseStop.abort();
|
|
1210
|
-
await renewal;
|
|
1211
|
-
}
|
|
1262
|
+
},
|
|
1263
|
+
);
|
|
1212
1264
|
}
|
|
1213
1265
|
if (!settings.once && !signal.aborted) await pause(settings.pollMs, signal);
|
|
1214
1266
|
} while (!signal.aborted && !settings.once);
|