larkin 0.4.2 → 0.4.5
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 +5 -1
- package/artifacts/release/THIRD_PARTY_NOTICES.txt +218 -228
- package/assets/readme/larkin-github-cover.png +0 -0
- package/dist/agent/agent-state-store.cjs +1 -2
- package/dist/agent/agent-state-store.mjs +1 -2
- package/dist/app/agent-config.mjs +73 -6
- package/dist/app/agent-readiness.cjs +22 -2
- package/dist/app/agent-readiness.mjs +20 -2
- package/dist/app/binary-entry.mjs +6 -0
- package/dist/app/cli.mjs +4 -0
- package/dist/app/run.mjs +8 -0
- package/dist/app/runtime-process.mjs +13 -1
- package/dist/dashboard/dashboard-view-model.mjs +12 -3
- package/dist/feishu/host-shell.cjs +34 -10
- package/dist/feishu/host-shell.mjs +35 -11
- package/dist/platform/config.cjs +406 -33
- package/dist/platform/config.mjs +405 -33
- package/dist/platform/process-boundary-trace.cjs +108 -0
- package/dist/platform/process-boundary-trace.mjs +102 -0
- package/dist/runtime/pi-artifact-provenance.cjs +147 -0
- package/dist/runtime/pi-artifact-provenance.mjs +139 -0
- package/dist/runtime/pi-compaction-recovery.cjs +120 -40
- package/dist/runtime/pi-compaction-recovery.mjs +117 -40
- package/dist/runtime/pi-model-catalog.cjs +2 -2
- package/dist/runtime/pi-model-catalog.mjs +2 -2
- package/dist/runtime/pi-profile-migration.cjs +556 -0
- package/dist/runtime/pi-profile-migration.mjs +515 -0
- package/dist/runtime/pi-provider-config.cjs +1 -1
- package/dist/runtime/pi-provider-config.mjs +1 -1
- package/dist/runtime/runtime-adapters.mjs +97 -11
- package/dist/runtime/runtime-host.cjs +162 -39
- package/dist/runtime/runtime-host.mjs +163 -40
- package/dist/runtime/runtime-readiness.cjs +6 -4
- package/dist/runtime/runtime-readiness.mjs +6 -4
- package/package.json +3 -3
|
@@ -19,7 +19,7 @@ import { readDocumentCommentSubscription, verifyCallbackProbe } from "../platfor
|
|
|
19
19
|
import { loadConfig, resolveMentionPolicy } from "../platform/config.mjs";
|
|
20
20
|
import { processCommandToken } from "../app/internal-command.mjs";
|
|
21
21
|
import { managedOfficialLarkCli } from "../app/agent-lark-cli-workspace.mjs";
|
|
22
|
-
import { isChannelReconnecting } from "../app/agent-readiness.mjs";
|
|
22
|
+
import { isChannelReconnecting, isRuntimeReadinessCurrent } from "../app/agent-readiness.mjs";
|
|
23
23
|
import { documentCommentMessageId, documentCommentNoticeType, projectDocumentCommentEnvelope, resolveDocumentCommentContext, } from "./document-comment.mjs";
|
|
24
24
|
const PENDING_DOCUMENT_COMMENT_LIMIT = 256;
|
|
25
25
|
function isRecord(value) {
|
|
@@ -160,6 +160,11 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
160
160
|
return store;
|
|
161
161
|
};
|
|
162
162
|
const hostState = new HostStateProjection(stateStore, log);
|
|
163
|
+
const markRuntimeTransition = (agent, reason) => {
|
|
164
|
+
hostState.updateStatus(agent, {
|
|
165
|
+
runtimeReadiness: { runtime: agent.runtime, state: "unavailable", reason, nextAction: "Wait for the current daemon epoch to publish Runtime readiness.", observedAt: new Date().toISOString() },
|
|
166
|
+
});
|
|
167
|
+
};
|
|
163
168
|
const recordInboundDeliveryFailure = (agent, code) => {
|
|
164
169
|
const at = new Date().toISOString();
|
|
165
170
|
const reason = "Inbound Runtime delivery failed non-retryably; durable Inbox/ledger state is retained for recovery.";
|
|
@@ -1191,19 +1196,21 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1191
1196
|
return;
|
|
1192
1197
|
if (message.type === "agent-status") {
|
|
1193
1198
|
log("agent:status", message.agentId, message.status);
|
|
1199
|
+
const observedAt = new Date().toISOString();
|
|
1194
1200
|
if (message.status === "error" || message.status === "inactive")
|
|
1195
1201
|
hostState.updateStatus(agent, {
|
|
1196
|
-
runtimeReadiness: message.readiness?.state && message.readiness.state !== "ready" ? message.readiness : {
|
|
1202
|
+
runtimeReadiness: message.readiness?.state && message.readiness.state !== "ready" ? { ...message.readiness, observedAt } : {
|
|
1197
1203
|
runtime: agent.runtime,
|
|
1198
1204
|
state: message.status === "error" ? "incompatible" : "missing",
|
|
1199
1205
|
reason: message.status === "error" ? message.error || "Runtime entered an error state" : "Runtime is inactive",
|
|
1206
|
+
observedAt,
|
|
1200
1207
|
},
|
|
1201
1208
|
});
|
|
1202
1209
|
else if (message.readiness)
|
|
1203
|
-
hostState.updateStatus(agent, { runtimeReadiness: message.readiness });
|
|
1210
|
+
hostState.updateStatus(agent, { runtimeReadiness: { ...message.readiness, observedAt } });
|
|
1204
1211
|
else if (message.status === "active")
|
|
1205
1212
|
hostState.updateStatus(agent, { runtimeReadiness: {
|
|
1206
|
-
runtime: agent.runtime, state: "ready",
|
|
1213
|
+
runtime: agent.runtime, state: "ready", observedAt,
|
|
1207
1214
|
} });
|
|
1208
1215
|
if (message.status === "active") {
|
|
1209
1216
|
const redeliveryTimer = setTimeout(() => {
|
|
@@ -1335,8 +1342,10 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1335
1342
|
const status = hostState.readStatus(agent);
|
|
1336
1343
|
const turns = status.session && typeof status.session === "object"
|
|
1337
1344
|
? Math.max(0, Number(status.session.turns) || 0) : 0;
|
|
1338
|
-
const
|
|
1339
|
-
|
|
1345
|
+
const sessionStartedAt = status.session && typeof status.session === "object"
|
|
1346
|
+
? Date.parse(String(status.session.startedAt || "")) : Number.NaN;
|
|
1347
|
+
const sessionCurrent = Number.isFinite(sessionStartedAt) && sessionStartedAt >= Date.parse(daemonStartedAt);
|
|
1348
|
+
const runtimeReady = sessionCurrent && isRuntimeReadinessCurrent(status.runtimeReadiness, daemonStartedAt);
|
|
1340
1349
|
const pendingCount = stateStore(agent).withInboxTransaction(() => stateStore(agent).readNdjson("inbox").length);
|
|
1341
1350
|
return { turns, runtimeReady, ...connectionState(status), pendingCount };
|
|
1342
1351
|
};
|
|
@@ -1345,6 +1354,7 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1345
1354
|
throw Object.assign(new Error(`Agent ${agentId} channel is not connected`), { code: "channel_unavailable", ...initialProjection });
|
|
1346
1355
|
if (initialProjection.reconnecting)
|
|
1347
1356
|
throw Object.assign(new Error(`Agent ${agentId} channel is reconnecting`), { code: "channel_reconnecting", ...initialProjection });
|
|
1357
|
+
markRuntimeTransition(agent, "Runtime session reset in progress");
|
|
1348
1358
|
let reset;
|
|
1349
1359
|
try {
|
|
1350
1360
|
reset = await runtimeHost.resetSession(agentId);
|
|
@@ -1361,11 +1371,17 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1361
1371
|
delete record.state.sessions[agent.runtime];
|
|
1362
1372
|
record.store.writeJson("agentState", record.state);
|
|
1363
1373
|
}
|
|
1364
|
-
if (!reset.sessionId)
|
|
1374
|
+
if (!reset.sessionId) {
|
|
1375
|
+
const observedAt = new Date().toISOString();
|
|
1365
1376
|
hostState.updateStatus(agent, {
|
|
1366
|
-
session: { runtime: agent.runtime, id: null, launchId: null, startedAt:
|
|
1367
|
-
lastSeenAt: null, lastTurnAt: null, turns: 0 },
|
|
1377
|
+
session: { runtime: agent.runtime, id: null, launchId: null, startedAt: observedAt,
|
|
1378
|
+
lastSeenAt: null, lastTurnAt: null, turns: 0 },
|
|
1379
|
+
runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt },
|
|
1368
1380
|
});
|
|
1381
|
+
}
|
|
1382
|
+
else if (reset.runtimeReady) {
|
|
1383
|
+
hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt: new Date().toISOString() } });
|
|
1384
|
+
}
|
|
1369
1385
|
}
|
|
1370
1386
|
catch (error) {
|
|
1371
1387
|
const projection = readinessProjection();
|
|
@@ -1412,8 +1428,10 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1412
1428
|
const status = hostState.readStatus(agent);
|
|
1413
1429
|
const turns = status.session && typeof status.session === "object"
|
|
1414
1430
|
? Math.max(0, Number(status.session.turns) || 0) : 0;
|
|
1415
|
-
const
|
|
1416
|
-
|
|
1431
|
+
const sessionStartedAt = status.session && typeof status.session === "object"
|
|
1432
|
+
? Date.parse(String(status.session.startedAt || "")) : Number.NaN;
|
|
1433
|
+
const sessionCurrent = Number.isFinite(sessionStartedAt) && sessionStartedAt >= Date.parse(daemonStartedAt);
|
|
1434
|
+
const runtimeReady = sessionCurrent && isRuntimeReadinessCurrent(status.runtimeReadiness, daemonStartedAt);
|
|
1417
1435
|
const pendingCount = stateStore(agent).withInboxTransaction(() => stateStore(agent).readNdjson("inbox").length);
|
|
1418
1436
|
return { turns, runtimeReady, ...connectionState(status), pendingCount };
|
|
1419
1437
|
};
|
|
@@ -1422,6 +1440,7 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1422
1440
|
throw Object.assign(new Error(`Agent ${agentId} channel is not connected`), { code: "channel_unavailable", ...initialProjection });
|
|
1423
1441
|
if (initialProjection.reconnecting)
|
|
1424
1442
|
throw Object.assign(new Error(`Agent ${agentId} channel is reconnecting`), { code: "channel_reconnecting", ...initialProjection });
|
|
1443
|
+
markRuntimeTransition(agent, "Runtime session recovery in progress");
|
|
1425
1444
|
let recovery;
|
|
1426
1445
|
try {
|
|
1427
1446
|
recovery = await runtimeHost.recoverSession(agentId, reason);
|
|
@@ -1429,6 +1448,9 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1429
1448
|
catch (error) {
|
|
1430
1449
|
throw Object.assign(error instanceof Error ? error : new Error(String(error)), readinessProjection());
|
|
1431
1450
|
}
|
|
1451
|
+
if (recovery.runtimeReady) {
|
|
1452
|
+
hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt: new Date().toISOString() } });
|
|
1453
|
+
}
|
|
1432
1454
|
const record = agentStates.get(agentId);
|
|
1433
1455
|
try {
|
|
1434
1456
|
if (record) {
|
|
@@ -1466,6 +1488,8 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
|
|
|
1466
1488
|
async start() {
|
|
1467
1489
|
try {
|
|
1468
1490
|
fs.mkdirSync(larkinHome, { recursive: true });
|
|
1491
|
+
for (const agent of agents)
|
|
1492
|
+
markRuntimeTransition(agent, "Current daemon epoch starting");
|
|
1469
1493
|
fs.writeFileSync(path.join(larkinHome, "daemon-status.json"), JSON.stringify({
|
|
1470
1494
|
...currentProcessMetadata(processCommandToken("daemon", "app/runtime-process.mjs")), pid: process.pid, startedAt: daemonStartedAt,
|
|
1471
1495
|
agents: agents.map((agent) => agent.agentId),
|