larkin 0.4.28 → 0.5.0

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 (55) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +5 -9
  3. package/artifacts/release/THIRD_PARTY_NOTICES.txt +751 -4425
  4. package/dist/app/agent-cli.mjs +14 -2
  5. package/dist/app/agent-config.mjs +26 -84
  6. package/dist/app/binary-entry.mjs +0 -20
  7. package/dist/app/cli.mjs +8 -14
  8. package/dist/app/internal-command.cjs +0 -2
  9. package/dist/app/internal-command.mjs +0 -2
  10. package/dist/app/local-control.mjs +16 -3
  11. package/dist/app/runtime-model-directory.mjs +2 -16
  12. package/dist/app/runtime-process.mjs +42 -6
  13. package/dist/app/setup.mjs +52 -57
  14. package/dist/dashboard/dashboard-config-controller.mjs +83 -24
  15. package/dist/dashboard/dashboard-view-model.mjs +4 -7
  16. package/dist/dashboard/web/assets/dashboard.js +1 -1
  17. package/dist/feishu/host-shell.cjs +68 -17
  18. package/dist/feishu/host-shell.mjs +69 -18
  19. package/dist/platform/config.cjs +201 -138
  20. package/dist/platform/config.mjs +199 -138
  21. package/dist/runtime/pi-artifact-provenance.mjs +3 -3
  22. package/dist/runtime/pi-bash-timeout-extension.mjs +4 -5
  23. package/dist/runtime/pi-compaction-recovery.cjs +9 -11
  24. package/dist/runtime/pi-compaction-recovery.mjs +8 -10
  25. package/dist/runtime/pi-extension-api.mjs +1 -0
  26. package/dist/runtime/pi-model-catalog.cjs +7 -8
  27. package/dist/runtime/pi-model-catalog.mjs +7 -8
  28. package/dist/runtime/pi-subagent-injection.mjs +17 -4
  29. package/dist/runtime/runtime-adapters.mjs +41 -38
  30. package/dist/runtime/runtime-host.cjs +197 -20
  31. package/dist/runtime/runtime-host.mjs +198 -21
  32. package/dist/runtime/runtime-model-catalog.cjs +1 -1
  33. package/dist/runtime/runtime-model-catalog.mjs +1 -1
  34. package/dist/runtime/runtime-readiness.cjs +112 -49
  35. package/dist/runtime/runtime-readiness.mjs +103 -49
  36. package/dist/runtime/user-runtime.cjs +7 -24
  37. package/dist/runtime/user-runtime.mjs +7 -23
  38. package/dist/setup/bot-register.mjs +15 -123
  39. package/dist/setup/setup-agent-choice.mjs +48 -74
  40. package/dist/setup/setup-bind.mjs +51 -151
  41. package/dist/setup/setup-binding.mjs +6 -9
  42. package/package.json +3 -2
  43. package/dist/app/pi-auth-cli.mjs +0 -67
  44. package/dist/platform/process-boundary-trace.cjs +0 -108
  45. package/dist/runtime/builtin-pi-assets.cjs +0 -117
  46. package/dist/runtime/builtin-pi-assets.mjs +0 -105
  47. package/dist/runtime/pi-artifact-provenance.cjs +0 -147
  48. package/dist/runtime/pi-distribution-label.cjs +0 -6
  49. package/dist/runtime/pi-distribution-label.mjs +0 -3
  50. package/dist/runtime/pi-inline-extensions.mjs +0 -78
  51. package/dist/runtime/pi-official-auth.mjs +0 -491
  52. package/dist/runtime/pi-profile-migration.cjs +0 -764
  53. package/dist/runtime/pi-profile-migration.mjs +0 -719
  54. package/dist/runtime/pi-provider-config.cjs +0 -331
  55. package/dist/runtime/pi-provider-config.mjs +0 -314
@@ -121,7 +121,7 @@ function memberNamesFromPayloads(payloads) {
121
121
  function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
122
122
  function agentConfigSignature(agent) {
123
123
  return JSON.stringify({
124
- agentId: agent.agentId, runtime: agent.runtime, model: agent.model, piDistribution: agent.piDistribution ?? null, effort: agent.effort ?? null,
124
+ agentId: agent.agentId, runtime: agent.runtime, model: agent.model, effort: agent.effort ?? null,
125
125
  feishuAppId: agent.feishuAppId, feishuProfile: agent.feishuProfile,
126
126
  larkConfigDir: agent.larkConfigDir, feishuDomain: agent.feishuDomain,
127
127
  feishuAppSecret: agent.feishuAppSecret, workspaceDir: agent.workspaceDir, stateDir: agent.stateDir,
@@ -208,26 +208,71 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
208
208
  runtimeReadiness: { runtime: agent.runtime, state: "unavailable", reason, nextAction: "Wait for the current daemon epoch to publish Runtime readiness.", observedAt: new Date().toISOString() },
209
209
  });
210
210
  };
211
+ const unresolvedCurrentAuth = (agent) => {
212
+ try {
213
+ const persisted = (0, runtime_readiness_js_1.parsePersistedAuthFailure)(stateStore(agent).readJson("agentState", {}));
214
+ if (!persisted)
215
+ return null;
216
+ // 只使用当前 agentState 作用域标记,不扫描历史 delivery 的 authProvider。
217
+ return (0, runtime_readiness_js_1.authFailureAppliesTo)({
218
+ runtime: agent.runtime,
219
+ model: agent.model,
220
+ }, persisted) ? persisted : null;
221
+ }
222
+ catch {
223
+ return null;
224
+ }
225
+ };
226
+ const projectReadyUnlessUnresolvedAuth = (agent, observedAt) => {
227
+ const failure = unresolvedCurrentAuth(agent);
228
+ if (failure) {
229
+ hostState.updateStatus(agent, {
230
+ runtimeReadiness: { ...(0, runtime_readiness_js_1.readinessForPersistedAuthFailure)(failure), observedAt },
231
+ });
232
+ return;
233
+ }
234
+ hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt } });
235
+ };
211
236
  const recordInboundDeliveryFailure = (agent, code) => {
212
237
  const at = new Date().toISOString();
213
238
  const reason = "Inbound Runtime delivery failed non-retryably; durable Inbox/ledger state is retained for recovery.";
214
239
  const nextAction = "Inspect the delivery/status error, correct the Runtime or canonical Inbox state, then restart to replay safely.";
240
+ const currentReadiness = hostState.readStatus(agent).runtimeReadiness;
215
241
  hostState.updateStatus(agent, {
216
242
  inboundDeliveryHealth: { state: "error", code, at, reason, nextAction },
217
- runtimeReadiness: { runtime: agent.runtime, state: "incompatible", reason, nextAction },
243
+ ...(currentReadiness?.state === "unauthenticated" ? {} : {
244
+ runtimeReadiness: { runtime: agent.runtime, state: "incompatible", reason, nextAction },
245
+ }),
218
246
  });
219
247
  hostState.recordStatusError(agent, `${reason} ${nextAction} code=${code}`);
220
248
  };
221
249
  const agentStates = new Map();
250
+ const mergePersistedAgentState = (record) => {
251
+ const latest = record.store.readJson("agentState", {});
252
+ if (isRecord(latest.previousSessions)) {
253
+ record.state.previousSessions = {
254
+ ...latest.previousSessions,
255
+ ...(record.state.previousSessions ?? {}),
256
+ };
257
+ }
258
+ const persisted = (0, runtime_readiness_js_1.parsePersistedAuthFailure)(latest);
259
+ if (persisted) {
260
+ record.state.authFailure = persisted;
261
+ if (persisted.kind === "missing-provider" && persisted.provider) {
262
+ record.state.authFailureProvider = persisted.provider;
263
+ }
264
+ else {
265
+ delete record.state.authFailureProvider;
266
+ }
267
+ }
268
+ else {
269
+ delete record.state.authFailure;
270
+ delete record.state.authFailureProvider;
271
+ }
272
+ };
222
273
  const saveAgentState = (record) => {
223
274
  try {
224
- const latest = record.store.readJson("agentState", {});
225
- if (isRecord(latest.previousSessions)) {
226
- record.state.previousSessions = {
227
- ...latest.previousSessions,
228
- ...(record.state.previousSessions ?? {}),
229
- };
230
- }
275
+ mergePersistedAgentState(record);
231
276
  record.store.writeJson("agentState", record.state);
232
277
  }
233
278
  catch (error) {
@@ -1276,12 +1321,16 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
1276
1321
  observedAt,
1277
1322
  },
1278
1323
  });
1279
- else if (message.readiness)
1280
- hostState.updateStatus(agent, { runtimeReadiness: { ...message.readiness, observedAt } });
1324
+ else if (message.readiness) {
1325
+ if (message.readiness.state === "ready" && unresolvedCurrentAuth(agent)) {
1326
+ projectReadyUnlessUnresolvedAuth(agent, observedAt);
1327
+ }
1328
+ else {
1329
+ hostState.updateStatus(agent, { runtimeReadiness: { ...message.readiness, observedAt } });
1330
+ }
1331
+ }
1281
1332
  else if (message.status === "active")
1282
- hostState.updateStatus(agent, { runtimeReadiness: {
1283
- runtime: agent.runtime, state: "ready", observedAt,
1284
- } });
1333
+ projectReadyUnlessUnresolvedAuth(agent, observedAt);
1285
1334
  if (message.status === "active") {
1286
1335
  const redeliveryTimer = setTimeout(() => {
1287
1336
  void reminder.redeliverUnread(agent).catch((error) => log("启动补投失败", errorMessage(error)));
@@ -1448,6 +1497,7 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
1448
1497
  record.state.sessions[agent.runtime] = reset.sessionId;
1449
1498
  else
1450
1499
  delete record.state.sessions[agent.runtime];
1500
+ mergePersistedAgentState(record);
1451
1501
  record.store.writeJson("agentState", record.state);
1452
1502
  }
1453
1503
  if (!reset.sessionId) {
@@ -1455,11 +1505,11 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
1455
1505
  hostState.updateStatus(agent, {
1456
1506
  session: { runtime: agent.runtime, id: null, launchId: null, startedAt: observedAt,
1457
1507
  lastSeenAt: null, lastTurnAt: null, turns: 0 },
1458
- runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt },
1459
1508
  });
1509
+ projectReadyUnlessUnresolvedAuth(agent, observedAt);
1460
1510
  }
1461
1511
  else if (reset.runtimeReady) {
1462
- hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt: new Date().toISOString() } });
1512
+ projectReadyUnlessUnresolvedAuth(agent, new Date().toISOString());
1463
1513
  }
1464
1514
  }
1465
1515
  catch (error) {
@@ -1527,7 +1577,7 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
1527
1577
  throw Object.assign(error instanceof Error ? error : new Error(String(error)), readinessProjection());
1528
1578
  }
1529
1579
  if (recovery.runtimeReady) {
1530
- hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt: new Date().toISOString() } });
1580
+ projectReadyUnlessUnresolvedAuth(agent, new Date().toISOString());
1531
1581
  }
1532
1582
  const record = agentStates.get(agentId);
1533
1583
  try {
@@ -1536,6 +1586,7 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
1536
1586
  record.state.sessions[agent.runtime] = recovery.sessionId;
1537
1587
  else
1538
1588
  delete record.state.sessions[agent.runtime];
1589
+ mergePersistedAgentState(record);
1539
1590
  record.store.writeJson("agentState", record.state);
1540
1591
  }
1541
1592
  }
@@ -16,7 +16,7 @@ import { inboxAuditRegistryFile, observeInboxAuditTarget } from "../agent/missed
16
16
  import { HostChannelBusiness } from "./host-channel-business.mjs";
17
17
  import { HostInteractionOrchestrator } from "./interaction-orchestrator.mjs";
18
18
  import { targetFor } from "./message-policy.mjs";
19
- import { providerAuthenticationFailureReadiness, RuntimePrerequisiteError } from "../runtime/runtime-readiness.mjs";
19
+ import { authFailureAppliesTo, parsePersistedAuthFailure, providerAuthenticationFailureReadiness, readinessForPersistedAuthFailure, RuntimePrerequisiteError, } from "../runtime/runtime-readiness.mjs";
20
20
  import { readDocumentCommentSubscription, verifyCallbackProbe } from "../platform/callback-capability.mjs";
21
21
  import { loadConfig, resolveMentionPolicy } from "../platform/config.mjs";
22
22
  import { processCommandToken } from "../app/internal-command.mjs";
@@ -81,7 +81,7 @@ export function memberNamesFromPayloads(payloads) {
81
81
  function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
82
82
  function agentConfigSignature(agent) {
83
83
  return JSON.stringify({
84
- agentId: agent.agentId, runtime: agent.runtime, model: agent.model, piDistribution: agent.piDistribution ?? null, effort: agent.effort ?? null,
84
+ agentId: agent.agentId, runtime: agent.runtime, model: agent.model, effort: agent.effort ?? null,
85
85
  feishuAppId: agent.feishuAppId, feishuProfile: agent.feishuProfile,
86
86
  larkConfigDir: agent.larkConfigDir, feishuDomain: agent.feishuDomain,
87
87
  feishuAppSecret: agent.feishuAppSecret, workspaceDir: agent.workspaceDir, stateDir: agent.stateDir,
@@ -168,26 +168,71 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
168
168
  runtimeReadiness: { runtime: agent.runtime, state: "unavailable", reason, nextAction: "Wait for the current daemon epoch to publish Runtime readiness.", observedAt: new Date().toISOString() },
169
169
  });
170
170
  };
171
+ const unresolvedCurrentAuth = (agent) => {
172
+ try {
173
+ const persisted = parsePersistedAuthFailure(stateStore(agent).readJson("agentState", {}));
174
+ if (!persisted)
175
+ return null;
176
+ // 只使用当前 agentState 作用域标记,不扫描历史 delivery 的 authProvider。
177
+ return authFailureAppliesTo({
178
+ runtime: agent.runtime,
179
+ model: agent.model,
180
+ }, persisted) ? persisted : null;
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ };
186
+ const projectReadyUnlessUnresolvedAuth = (agent, observedAt) => {
187
+ const failure = unresolvedCurrentAuth(agent);
188
+ if (failure) {
189
+ hostState.updateStatus(agent, {
190
+ runtimeReadiness: { ...readinessForPersistedAuthFailure(failure), observedAt },
191
+ });
192
+ return;
193
+ }
194
+ hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt } });
195
+ };
171
196
  const recordInboundDeliveryFailure = (agent, code) => {
172
197
  const at = new Date().toISOString();
173
198
  const reason = "Inbound Runtime delivery failed non-retryably; durable Inbox/ledger state is retained for recovery.";
174
199
  const nextAction = "Inspect the delivery/status error, correct the Runtime or canonical Inbox state, then restart to replay safely.";
200
+ const currentReadiness = hostState.readStatus(agent).runtimeReadiness;
175
201
  hostState.updateStatus(agent, {
176
202
  inboundDeliveryHealth: { state: "error", code, at, reason, nextAction },
177
- runtimeReadiness: { runtime: agent.runtime, state: "incompatible", reason, nextAction },
203
+ ...(currentReadiness?.state === "unauthenticated" ? {} : {
204
+ runtimeReadiness: { runtime: agent.runtime, state: "incompatible", reason, nextAction },
205
+ }),
178
206
  });
179
207
  hostState.recordStatusError(agent, `${reason} ${nextAction} code=${code}`);
180
208
  };
181
209
  const agentStates = new Map();
210
+ const mergePersistedAgentState = (record) => {
211
+ const latest = record.store.readJson("agentState", {});
212
+ if (isRecord(latest.previousSessions)) {
213
+ record.state.previousSessions = {
214
+ ...latest.previousSessions,
215
+ ...(record.state.previousSessions ?? {}),
216
+ };
217
+ }
218
+ const persisted = parsePersistedAuthFailure(latest);
219
+ if (persisted) {
220
+ record.state.authFailure = persisted;
221
+ if (persisted.kind === "missing-provider" && persisted.provider) {
222
+ record.state.authFailureProvider = persisted.provider;
223
+ }
224
+ else {
225
+ delete record.state.authFailureProvider;
226
+ }
227
+ }
228
+ else {
229
+ delete record.state.authFailure;
230
+ delete record.state.authFailureProvider;
231
+ }
232
+ };
182
233
  const saveAgentState = (record) => {
183
234
  try {
184
- const latest = record.store.readJson("agentState", {});
185
- if (isRecord(latest.previousSessions)) {
186
- record.state.previousSessions = {
187
- ...latest.previousSessions,
188
- ...(record.state.previousSessions ?? {}),
189
- };
190
- }
235
+ mergePersistedAgentState(record);
191
236
  record.store.writeJson("agentState", record.state);
192
237
  }
193
238
  catch (error) {
@@ -1236,12 +1281,16 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
1236
1281
  observedAt,
1237
1282
  },
1238
1283
  });
1239
- else if (message.readiness)
1240
- hostState.updateStatus(agent, { runtimeReadiness: { ...message.readiness, observedAt } });
1284
+ else if (message.readiness) {
1285
+ if (message.readiness.state === "ready" && unresolvedCurrentAuth(agent)) {
1286
+ projectReadyUnlessUnresolvedAuth(agent, observedAt);
1287
+ }
1288
+ else {
1289
+ hostState.updateStatus(agent, { runtimeReadiness: { ...message.readiness, observedAt } });
1290
+ }
1291
+ }
1241
1292
  else if (message.status === "active")
1242
- hostState.updateStatus(agent, { runtimeReadiness: {
1243
- runtime: agent.runtime, state: "ready", observedAt,
1244
- } });
1293
+ projectReadyUnlessUnresolvedAuth(agent, observedAt);
1245
1294
  if (message.status === "active") {
1246
1295
  const redeliveryTimer = setTimeout(() => {
1247
1296
  void reminder.redeliverUnread(agent).catch((error) => log("启动补投失败", errorMessage(error)));
@@ -1408,6 +1457,7 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
1408
1457
  record.state.sessions[agent.runtime] = reset.sessionId;
1409
1458
  else
1410
1459
  delete record.state.sessions[agent.runtime];
1460
+ mergePersistedAgentState(record);
1411
1461
  record.store.writeJson("agentState", record.state);
1412
1462
  }
1413
1463
  if (!reset.sessionId) {
@@ -1415,11 +1465,11 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
1415
1465
  hostState.updateStatus(agent, {
1416
1466
  session: { runtime: agent.runtime, id: null, launchId: null, startedAt: observedAt,
1417
1467
  lastSeenAt: null, lastTurnAt: null, turns: 0 },
1418
- runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt },
1419
1468
  });
1469
+ projectReadyUnlessUnresolvedAuth(agent, observedAt);
1420
1470
  }
1421
1471
  else if (reset.runtimeReady) {
1422
- hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt: new Date().toISOString() } });
1472
+ projectReadyUnlessUnresolvedAuth(agent, new Date().toISOString());
1423
1473
  }
1424
1474
  }
1425
1475
  catch (error) {
@@ -1487,7 +1537,7 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
1487
1537
  throw Object.assign(error instanceof Error ? error : new Error(String(error)), readinessProjection());
1488
1538
  }
1489
1539
  if (recovery.runtimeReady) {
1490
- hostState.updateStatus(agent, { runtimeReadiness: { runtime: agent.runtime, state: "ready", observedAt: new Date().toISOString() } });
1540
+ projectReadyUnlessUnresolvedAuth(agent, new Date().toISOString());
1491
1541
  }
1492
1542
  const record = agentStates.get(agentId);
1493
1543
  try {
@@ -1496,6 +1546,7 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
1496
1546
  record.state.sessions[agent.runtime] = recovery.sessionId;
1497
1547
  else
1498
1548
  delete record.state.sessions[agent.runtime];
1549
+ mergePersistedAgentState(record);
1499
1550
  record.store.writeJson("agentState", record.state);
1500
1551
  }
1501
1552
  }