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.
Files changed (35) hide show
  1. package/README.md +5 -1
  2. package/artifacts/release/THIRD_PARTY_NOTICES.txt +218 -228
  3. package/assets/readme/larkin-github-cover.png +0 -0
  4. package/dist/agent/agent-state-store.cjs +1 -2
  5. package/dist/agent/agent-state-store.mjs +1 -2
  6. package/dist/app/agent-config.mjs +73 -6
  7. package/dist/app/agent-readiness.cjs +22 -2
  8. package/dist/app/agent-readiness.mjs +20 -2
  9. package/dist/app/binary-entry.mjs +6 -0
  10. package/dist/app/cli.mjs +4 -0
  11. package/dist/app/run.mjs +8 -0
  12. package/dist/app/runtime-process.mjs +13 -1
  13. package/dist/dashboard/dashboard-view-model.mjs +12 -3
  14. package/dist/feishu/host-shell.cjs +34 -10
  15. package/dist/feishu/host-shell.mjs +35 -11
  16. package/dist/platform/config.cjs +406 -33
  17. package/dist/platform/config.mjs +405 -33
  18. package/dist/platform/process-boundary-trace.cjs +108 -0
  19. package/dist/platform/process-boundary-trace.mjs +102 -0
  20. package/dist/runtime/pi-artifact-provenance.cjs +147 -0
  21. package/dist/runtime/pi-artifact-provenance.mjs +139 -0
  22. package/dist/runtime/pi-compaction-recovery.cjs +120 -40
  23. package/dist/runtime/pi-compaction-recovery.mjs +117 -40
  24. package/dist/runtime/pi-model-catalog.cjs +2 -2
  25. package/dist/runtime/pi-model-catalog.mjs +2 -2
  26. package/dist/runtime/pi-profile-migration.cjs +556 -0
  27. package/dist/runtime/pi-profile-migration.mjs +515 -0
  28. package/dist/runtime/pi-provider-config.cjs +1 -1
  29. package/dist/runtime/pi-provider-config.mjs +1 -1
  30. package/dist/runtime/runtime-adapters.mjs +97 -11
  31. package/dist/runtime/runtime-host.cjs +162 -39
  32. package/dist/runtime/runtime-host.mjs +163 -40
  33. package/dist/runtime/runtime-readiness.cjs +6 -4
  34. package/dist/runtime/runtime-readiness.mjs +6 -4
  35. 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 runtimeReady = Boolean(status.runtimeReadiness && typeof status.runtimeReadiness === "object"
1339
- && status.runtimeReadiness.state === "ready");
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: new Date().toISOString(),
1367
- lastSeenAt: null, lastTurnAt: null, turns: 0 }, runtimeReadiness: { runtime: agent.runtime, state: "ready" },
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 runtimeReady = Boolean(status.runtimeReadiness && typeof status.runtimeReadiness === "object"
1416
- && status.runtimeReadiness.state === "ready");
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),