@rivus/agent 0.6.1 → 0.6.2

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/dist/index.d.ts CHANGED
@@ -222,6 +222,7 @@ type FeishuStreamAction = {
222
222
  } | {
223
223
  readonly type: "handoff";
224
224
  readonly runId: AgentRunId;
225
+ readonly text?: string;
225
226
  } | {
226
227
  readonly type: "finish";
227
228
  readonly runId: AgentRunId;
@@ -234,6 +235,7 @@ type FeishuStreamAction = {
234
235
  readonly type: "cancel";
235
236
  readonly runId: AgentRunId;
236
237
  readonly reason?: string;
238
+ readonly text?: string;
237
239
  };
238
240
  interface FeishuStreamProjector {
239
241
  apply(event: AgentDomainEvent): ReadonlyArray<FeishuStreamAction>;
@@ -1355,6 +1357,7 @@ interface FeishuCardRolloverSuccessorRequest {
1355
1357
  readonly generation: number;
1356
1358
  readonly presentationId: string;
1357
1359
  readonly run: FeishuAgentRunPreparation;
1360
+ readonly text?: string;
1358
1361
  }
1359
1362
  interface FeishuCardRolloverStreamPublisher {
1360
1363
  flush(runId?: string): Effect.Effect<void, unknown>;
@@ -2080,10 +2083,12 @@ interface FeishuCardKitCancel {
2080
2083
  readonly cardId: string;
2081
2084
  readonly reason?: string;
2082
2085
  readonly sequence: number;
2086
+ readonly text?: string;
2083
2087
  }
2084
2088
  interface FeishuCardKitHandoff {
2085
2089
  readonly cardId: string;
2086
2090
  readonly sequence: number;
2091
+ readonly text?: string;
2087
2092
  }
2088
2093
  interface FeishuCardKitClient {
2089
2094
  cancel(request: FeishuCardKitCancel): Effect.Effect<void, unknown>;
@@ -2494,6 +2499,7 @@ declare function createFeishuCotPublisher(options: FeishuCotPublisherOptions): F
2494
2499
  //#region src/infrastructure/feishu/feishu-cardkit-target-preparation.d.ts
2495
2500
  interface FeishuCardTargetCreateOptions {
2496
2501
  readonly generation?: number;
2502
+ readonly initialContent?: string;
2497
2503
  }
2498
2504
  interface FeishuCardTargetCreator {
2499
2505
  createTarget(run: FeishuAgentRunPreparation, options?: FeishuCardTargetCreateOptions): Effect.Effect<FeishuCardTarget, unknown>;
@@ -3110,7 +3116,16 @@ type FeishuAgentRunCardInput = {
3110
3116
  readonly text: string;
3111
3117
  } | {
3112
3118
  readonly agentName: string;
3113
- readonly status: "cancelled" | "failed" | "handoff";
3119
+ readonly reason?: string;
3120
+ readonly status: "cancelled";
3121
+ readonly text?: string;
3122
+ } | {
3123
+ readonly agentName: string;
3124
+ readonly status: "failed";
3125
+ } | {
3126
+ readonly agentName: string;
3127
+ readonly status: "handoff";
3128
+ readonly text?: string;
3114
3129
  };
3115
3130
  declare function createFeishuAgentRunCard(input: FeishuAgentRunCardInput): FeishuRawCardJson;
3116
3131
  //#endregion
package/dist/index.js CHANGED
@@ -2866,8 +2866,8 @@ function resolveRunPresentation(input) {
2866
2866
  title: input.generation ? "正在处理(续)" : "正在处理"
2867
2867
  };
2868
2868
  case "handoff": return {
2869
- content: "任务仍在后台处理,进度将继续显示在下一条消息。",
2870
- note: "本卡片的流式窗口已交接",
2869
+ content: input.text || "任务仍在后台处理,进度将继续显示在下一条消息。",
2870
+ note: "本卡片已停止更新;后续进度见下一条消息",
2871
2871
  template: "blue",
2872
2872
  title: "已转到新消息"
2873
2873
  };
@@ -2883,14 +2883,35 @@ function resolveRunPresentation(input) {
2883
2883
  template: "red",
2884
2884
  title: "处理失败"
2885
2885
  };
2886
- case "cancelled": return {
2887
- content: "已停止生成。",
2888
- note: "本次运行已取消",
2889
- template: "grey",
2890
- title: "已取消"
2891
- };
2886
+ case "cancelled": return resolveCancellationPresentation(input.reason, input.text);
2892
2887
  }
2893
2888
  }
2889
+ function resolveCancellationPresentation(reason, text) {
2890
+ const timeoutMs = readRunTimeoutMs(reason);
2891
+ if (timeoutMs !== void 0) return {
2892
+ content: text || `任务执行超过 ${formatDuration(timeoutMs)},已停止。本次没有形成最终结论。`,
2893
+ note: `达到 ${formatDuration(timeoutMs)}运行时限;以上是超时前进度,不是最终结论`,
2894
+ template: "orange",
2895
+ title: "执行超时"
2896
+ };
2897
+ return {
2898
+ content: text || "已停止生成。",
2899
+ note: "本次运行已取消",
2900
+ template: "grey",
2901
+ title: "已取消"
2902
+ };
2903
+ }
2904
+ function readRunTimeoutMs(reason) {
2905
+ const match = /^run timed out after (\d+)ms$/.exec(reason ?? "");
2906
+ if (!match) return void 0;
2907
+ const milliseconds = Number(match[1]);
2908
+ return Number.isSafeInteger(milliseconds) && milliseconds > 0 ? milliseconds : void 0;
2909
+ }
2910
+ function formatDuration(milliseconds) {
2911
+ if (milliseconds % 36e5 === 0) return `${milliseconds / 36e5} 小时`;
2912
+ if (milliseconds % 6e4 === 0) return `${milliseconds / 6e4} 分钟`;
2913
+ return `${Math.ceil(milliseconds / 1e3)} 秒`;
2914
+ }
2894
2915
  //#endregion
2895
2916
  //#region src/infrastructure/feishu/feishu-tenant-token-provider.ts
2896
2917
  var FeishuTenantAccessTokenError = class {
@@ -3004,10 +3025,20 @@ function isStreamingClosed(error) {
3004
3025
  return error instanceof FeishuOpenApiError && (error.code === 200850 || error.code === 300309);
3005
3026
  }
3006
3027
  function updateWholeCard(baseUrl, agentName, request, status, call) {
3028
+ const requestText = "text" in request ? request.text : void 0;
3007
3029
  const card = status === "completed" ? createFeishuAgentRunCard({
3008
3030
  agentName,
3009
3031
  status,
3010
- text: "text" in request ? request.text : ""
3032
+ text: requestText ?? ""
3033
+ }) : status === "cancelled" ? createFeishuAgentRunCard({
3034
+ agentName,
3035
+ ..."reason" in request && request.reason ? { reason: request.reason } : {},
3036
+ status,
3037
+ ...requestText === void 0 ? {} : { text: requestText }
3038
+ }) : status === "handoff" ? createFeishuAgentRunCard({
3039
+ agentName,
3040
+ status,
3041
+ ...requestText === void 0 ? {} : { text: requestText }
3011
3042
  }) : createFeishuAgentRunCard({
3012
3043
  agentName,
3013
3044
  status
@@ -3040,7 +3071,8 @@ function createFeishuCardKitPublisher(options) {
3040
3071
  });
3041
3072
  case "handoff": return yield* options.client.handoff({
3042
3073
  cardId: target.cardId,
3043
- sequence
3074
+ sequence,
3075
+ ...action.text === void 0 ? {} : { text: action.text }
3044
3076
  });
3045
3077
  case "finish":
3046
3078
  yield* options.client.finish({
@@ -3060,7 +3092,8 @@ function createFeishuCardKitPublisher(options) {
3060
3092
  yield* options.client.cancel({
3061
3093
  cardId: target.cardId,
3062
3094
  ...action.reason ? { reason: action.reason } : {},
3063
- sequence
3095
+ sequence,
3096
+ ...action.text === void 0 ? {} : { text: action.text }
3064
3097
  });
3065
3098
  return yield* ledger.markTerminal(action.runId);
3066
3099
  }
@@ -3168,7 +3201,7 @@ function createFeishuCardKitOpenApiTargetCreator(options) {
3168
3201
  runId: run.runId,
3169
3202
  sessionKey: run.sessionKey,
3170
3203
  status: "running",
3171
- text: initialContent
3204
+ text: createOptions?.initialContent ?? initialContent
3172
3205
  })),
3173
3206
  type: "card_json"
3174
3207
  },
@@ -3225,7 +3258,10 @@ function createConfiguredFeishuCardRolloverRuntime(options) {
3225
3258
  });
3226
3259
  const cardRollover = createFeishuCardRollover({
3227
3260
  clock: options.clock,
3228
- createSuccessor: ({ generation, run }) => creator.createTarget(run, { generation }),
3261
+ createSuccessor: ({ generation, run, text }) => creator.createTarget(run, {
3262
+ generation,
3263
+ ...text === void 0 ? {} : { initialContent: text }
3264
+ }),
3229
3265
  leaseMs,
3230
3266
  ...options.observe ? { observe: options.observe } : {},
3231
3267
  publisher,
@@ -433,6 +433,7 @@ function createFeishuCardRollover(options) {
433
433
  const leaseMs = options.leaseMs ?? 51e4;
434
434
  if (!Number.isSafeInteger(leaseMs) || leaseMs < 1) throw new Error("Feishu card stream lease must be a positive integer");
435
435
  const counters = createCounters();
436
+ const latestTextByRun = /* @__PURE__ */ new Map();
436
437
  const liveRuns = /* @__PURE__ */ new Map();
437
438
  const semaphore = Effect.unsafeMakeSemaphore(1);
438
439
  const exclusive = (effect) => semaphore.withPermits(1)(effect);
@@ -448,7 +449,7 @@ function createFeishuCardRollover(options) {
448
449
  const presentationId = (runId, generation) => `${runId}#${generation}`;
449
450
  const publishProgress = (action) => Effect.suspend(() => {
450
451
  const chain = options.store.chain(action.runId);
451
- if (chain && acceptsCardPresentationProgress(chain)) return options.publisher.publish(action);
452
+ if (chain && acceptsCardPresentationProgress(chain)) return options.publisher.publish(action).pipe(Effect.tap(() => Effect.sync(() => latestTextByRun.set(action.runId, action.text))));
452
453
  return recordNow({
453
454
  ...chain ? {
454
455
  generation: chain.activeGeneration,
@@ -458,20 +459,28 @@ function createFeishuCardRollover(options) {
458
459
  type: "stale_update_dropped"
459
460
  });
460
461
  });
461
- const publishTerminal = (action) => options.publisher.publish(action).pipe(Effect.tapError((error) => recordNow({
462
- error,
463
- runId: action.runId,
464
- type: "terminal_delivery_failed"
465
- })), Effect.tap(() => options.store.markTerminal({
466
- runId: action.runId,
467
- terminalReceiptId: `${action.runId}:${action.type}`
468
- }).pipe(Effect.catchAll((error) => recordNow({
469
- error,
470
- runId: action.runId,
471
- type: "presentation_write_failed"
472
- })))), Effect.ensuring(Effect.sync(() => {
473
- liveRuns.delete(action.runId);
474
- })));
462
+ const publishTerminal = (action) => {
463
+ const latestText = latestTextByRun.get(action.runId);
464
+ const resolvedAction = action.type === "cancel" && action.text === void 0 && latestText !== void 0 ? {
465
+ ...action,
466
+ text: latestText
467
+ } : action;
468
+ return options.publisher.publish(resolvedAction).pipe(Effect.tapError((error) => recordNow({
469
+ error,
470
+ runId: action.runId,
471
+ type: "terminal_delivery_failed"
472
+ })), Effect.tap(() => options.store.markTerminal({
473
+ runId: action.runId,
474
+ terminalReceiptId: `${action.runId}:${action.type}`
475
+ }).pipe(Effect.catchAll((error) => recordNow({
476
+ error,
477
+ runId: action.runId,
478
+ type: "presentation_write_failed"
479
+ })))), Effect.ensuring(Effect.sync(() => {
480
+ latestTextByRun.delete(action.runId);
481
+ liveRuns.delete(action.runId);
482
+ })));
483
+ };
475
484
  const publishAction = (action) => {
476
485
  switch (action.type) {
477
486
  case "update_text": return publishProgress(action);
@@ -505,6 +514,7 @@ function createFeishuCardRollover(options) {
505
514
  };
506
515
  const predecessor = start.presentation;
507
516
  const generation = predecessor.generation + 1;
517
+ const text = latestTextByRun.get(runId);
508
518
  record({
509
519
  cardId: predecessor.cardId,
510
520
  generation,
@@ -517,7 +527,8 @@ function createFeishuCardRollover(options) {
517
527
  const created = yield* options.createSuccessor({
518
528
  generation,
519
529
  presentationId: successorId,
520
- run
530
+ run,
531
+ ...text === void 0 ? {} : { text }
521
532
  }).pipe(Effect.map((target) => ({ target })), Effect.catchAll((error) => options.store.failHandoff({
522
533
  failedAt: startedAt.toISOString(),
523
534
  runId
@@ -539,6 +550,7 @@ function createFeishuCardRollover(options) {
539
550
  };
540
551
  yield* options.publisher.publish({
541
552
  runId,
553
+ ...text === void 0 ? {} : { text },
542
554
  type: "handoff"
543
555
  }).pipe(Effect.catchAll((error) => recordNow({
544
556
  cardId: predecessor.cardId,
@@ -584,6 +596,7 @@ function createFeishuCardRollover(options) {
584
596
  runId: run.runId,
585
597
  sourceMessageId: run.messageId
586
598
  });
599
+ latestTextByRun.delete(run.runId);
587
600
  liveRuns.set(run.runId, run);
588
601
  return presentation;
589
602
  })),
@@ -605,6 +618,7 @@ function createFeishuCardRollover(options) {
605
618
  },
606
619
  publish: (action) => exclusive(publishAction(action)),
607
620
  releaseRun: (runId) => Effect.sync(() => {
621
+ latestTextByRun.delete(runId);
608
622
  liveRuns.delete(runId);
609
623
  }),
610
624
  recover: () => exclusive(Effect.gen(function* () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivus/agent",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "A local agent daemon core built around a usable agent harness and domain events.",
5
5
  "type": "module",
6
6
  "license": "MIT",