dsh-lark-bot 0.19.3 → 0.19.4

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/cli.js CHANGED
@@ -2779,6 +2779,18 @@ function patchYamlFor(options) {
2779
2779
  "",
2780
2780
  "- id: hmr",
2781
2781
  " disabled: true",
2782
+ "",
2783
+ // Model-invocable channel skill: expose the dsh-lark-bot operations guide
2784
+ // to THIS agent session's skill catalog — the one the `skill` tool reads.
2785
+ // The bridge engine registers the same skill on its own cordis context
2786
+ // (plugin.ts), but that context is never the one the model reads. This row
2787
+ // ensures the skill also lands on the agent runtime's context so that
2788
+ // `skill("dsh-lark-bot")` resolves in a live SDK session. It is kept
2789
+ // outside the bridgeTools gate because it needs no callback endpoint and
2790
+ // is also useful to the guardian's core-only safe profile.
2791
+ "- insert:",
2792
+ " - id: lark-skill",
2793
+ ` name: '${own.name}/skill'`,
2782
2794
  ""
2783
2795
  ];
2784
2796
  if (bridgeTools) {
@@ -7314,7 +7326,11 @@ function processElements(state, locale, maxTools) {
7314
7326
  function thinkingPanel(state, locale, maxTools) {
7315
7327
  return {
7316
7328
  tag: "collapsible_panel",
7317
- expanded: state.terminal === "running",
7329
+ // Default to collapsed: the top-level compatibility snapshot already shows
7330
+ // the latest status and current tools, so keep the detailed per-tool list
7331
+ // collapsed to avoid two overlapping expanded surfaces. (Both sections are
7332
+ // retained for now.)
7333
+ expanded: false,
7318
7334
  header: {
7319
7335
  title: { tag: "plain_text", content: `\u2699\uFE0F ${locale === "zh_cn" ? "\u6267\u884C\u8FC7\u7A0B" : "Execution"} \xB7 ${summaryText(state, locale)}` },
7320
7336
  icon: { tag: "standard_icon", token: "down-small-ccm_outlined" },
@@ -8000,6 +8016,15 @@ async function runAttempt(input, cwd, workspaceCwd, sessionId, resuming, replyOp
8000
8016
  log.warn("run-flow", "card-update-failed", { scope: input.scope, error });
8001
8017
  }
8002
8018
  };
8019
+ const unregisterReanchor = input.runCardAnchors?.register(input.chatId, async () => {
8020
+ if (state.terminal !== "running") return;
8021
+ try {
8022
+ await controller.update(renderer(state, density, Date.now()));
8023
+ if (typeof controller.reanchor === "function") await controller.reanchor();
8024
+ } catch (error) {
8025
+ log.warn("run-flow", "card-reanchor-failed", { scope: input.scope, error });
8026
+ }
8027
+ });
8003
8028
  const showResumeRecovery = async (error) => {
8004
8029
  if (classifySessionError(errorMessage(error)) === void 0) throw error;
8005
8030
  resumeFailure = errorMessage(error);
@@ -8173,6 +8198,7 @@ async function runAttempt(input, cwd, workspaceCwd, sessionId, resuming, replyOp
8173
8198
  unsubscribeQuestion?.();
8174
8199
  unsubscribePlan?.();
8175
8200
  unsubscribeApproval?.();
8201
+ unregisterReanchor?.();
8176
8202
  }
8177
8203
  };
8178
8204
  let producerStarted = false;
@@ -11904,6 +11930,41 @@ var ResilientCardStreamController = class {
11904
11930
  });
11905
11931
  }
11906
11932
  }
11933
+ /**
11934
+ * Recall the current card and re-create it as the newest top-level message in
11935
+ * the chat, rebinding the controller to the fresh message id. Because Feishu
11936
+ * cannot reorder an existing message, this is the only way to keep an
11937
+ * in-progress process card visible at the tail while interim agent bubbles are
11938
+ * appended below. Best-effort: if the recall fails the card is left where it
11939
+ * is (no duplicate is created); if the controller is closed or failed the id
11940
+ * is left unchanged.
11941
+ */
11942
+ async reanchor() {
11943
+ if (this.closed || this.failed) return this.messageId;
11944
+ if (this.inFlight !== void 0) await this.inFlight;
11945
+ if (this.timer !== void 0) {
11946
+ clearTimeout(this.timer);
11947
+ this.timer = void 0;
11948
+ }
11949
+ const card = this.latest;
11950
+ if (card === void 0) return this.messageId;
11951
+ try {
11952
+ await this.channel.recallMessage(this.messageId);
11953
+ } catch (error) {
11954
+ log.warn("lark-card-stream", "reanchor-recall-failed", {
11955
+ messageId: this.messageId,
11956
+ error: error instanceof Error ? error.message : String(error)
11957
+ });
11958
+ return this.messageId;
11959
+ }
11960
+ const sent = await this.channel.send(this.chatId, { card }, {});
11961
+ if (!sent.messageId) throw new Error("Feishu card re-anchor returned no message_id");
11962
+ this.messageId = sent.messageId;
11963
+ this.latest = card;
11964
+ this.dirty = false;
11965
+ this.failed = false;
11966
+ return this.messageId;
11967
+ }
11907
11968
  };
11908
11969
  function adaptLarkChannel(channel) {
11909
11970
  const base = {
@@ -14147,6 +14208,63 @@ function wizardContextFor(event, deps, channel, scope) {
14147
14208
  };
14148
14209
  }
14149
14210
 
14211
+ // src/bridge/run-card-anchors.ts
14212
+ var RunCardAnchors = class {
14213
+ byChatId = /* @__PURE__ */ new Map();
14214
+ /**
14215
+ * Register a re-anchor callback for a chat. Returns a disposer; safe to call
14216
+ * more than once (idempotent).
14217
+ */
14218
+ register(chatId, reanchor) {
14219
+ const set = this.byChatId.get(chatId) ?? /* @__PURE__ */ new Set();
14220
+ set.add(reanchor);
14221
+ this.byChatId.set(chatId, set);
14222
+ let active = true;
14223
+ return () => {
14224
+ if (!active) return;
14225
+ active = false;
14226
+ set.delete(reanchor);
14227
+ if (set.size === 0) this.byChatId.delete(chatId);
14228
+ };
14229
+ }
14230
+ /** Notify that a new bubble was delivered to the chat. */
14231
+ async bubbleSent(chatId) {
14232
+ const set = this.byChatId.get(chatId);
14233
+ if (!set || set.size === 0) return;
14234
+ await Promise.allSettled([...set].map((reanchor) => reanchor()));
14235
+ }
14236
+ };
14237
+ function attachRunCardAnchors(channel, anchors) {
14238
+ const notify = (chatId) => {
14239
+ void anchors.bubbleSent(chatId).catch((error) => {
14240
+ log.warn("run-card-anchors", "bubble-sent-failed", {
14241
+ chatId,
14242
+ error: error instanceof Error ? error.message : String(error)
14243
+ });
14244
+ });
14245
+ };
14246
+ return {
14247
+ ...channel,
14248
+ async sendMarkdown(chatId, markdown2, options) {
14249
+ const result = await channel.sendMarkdown(chatId, markdown2, options);
14250
+ notify(chatId);
14251
+ return result;
14252
+ },
14253
+ async sendCard(chatId, card, options) {
14254
+ if (typeof channel.sendCard !== "function") return void 0;
14255
+ const result = await channel.sendCard(chatId, card, options);
14256
+ notify(chatId);
14257
+ return result;
14258
+ },
14259
+ async sendFile(chatId, fileName, content, options) {
14260
+ if (typeof channel.sendFile !== "function") return void 0;
14261
+ const result = await channel.sendFile(chatId, fileName, content, options);
14262
+ notify(chatId);
14263
+ return result;
14264
+ }
14265
+ };
14266
+ }
14267
+
14150
14268
  // src/notify/server.ts
14151
14269
  import { createServer } from "http";
14152
14270
  import { randomBytes as randomBytes2 } from "crypto";
@@ -17662,6 +17780,7 @@ async function startBridgeEngine(options) {
17662
17780
  const questions = new QuestionRegistry();
17663
17781
  const plans = new PlanApprovalRegistry();
17664
17782
  const densityStore = new DensityStore();
17783
+ const runCardAnchors = new RunCardAnchors();
17665
17784
  const models = new ModelStore();
17666
17785
  const wizardStore = new WizardStore();
17667
17786
  const dshConfig = new DshProviderManager({ env: process.env });
@@ -17892,6 +18011,7 @@ async function startBridgeEngine(options) {
17892
18011
  plans,
17893
18012
  densityStore,
17894
18013
  channel: streaming,
18014
+ runCardAnchors,
17895
18015
  defaultWorkspace,
17896
18016
  replyTo: first.messageId,
17897
18017
  deliverFinalReply: (replyScope, chatId, markdown2, options2) => replyDispatcher.deliver(replyScope, chatId, markdown2, options2),
@@ -18094,7 +18214,7 @@ async function startBridgeEngine(options) {
18094
18214
  error: "channel does not expose getBotIdentity"
18095
18215
  });
18096
18216
  }
18097
- streaming = adaptLarkChannel(bridge.channel);
18217
+ streaming = attachRunCardAnchors(adaptLarkChannel(bridge.channel), runCardAnchors);
18098
18218
  larkChannel = bridge.channel;
18099
18219
  const deliverUpdateResult = async () => {
18100
18220
  await updateHandoff.deliverResult(async (state) => {