larkway 0.3.9 → 0.3.11

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 CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  You @ the bot in a Feishu thread. It runs on your machine — reading your real codebase, executing commands, opening MRs — and posts the result back. You define what the agent knows and what it can do. Larkway just carries the messages.
10
10
 
11
- **Current release: v0.3.9**
11
+ **Current release: v0.3.11**
12
12
 
13
13
  ---
14
14
 
package/README.zh.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  你在飞书话题里 @ bot,它在你的机器上运行——读真实代码库、执行命令、开 MR——把结果贴回飞书。你定义 agent 知道什么、能做什么。Larkway 只负责传递消息。
10
10
 
11
- **当前版本:v0.3.9**
11
+ **当前版本:v0.3.11**
12
12
 
13
13
  ---
14
14
 
package/dist/cli/index.js CHANGED
@@ -107597,6 +107597,10 @@ function stringField(obj, key) {
107597
107597
  const value = obj[key];
107598
107598
  return typeof value === "string" ? value : void 0;
107599
107599
  }
107600
+ function nonEmptyStringField(obj, key) {
107601
+ const value = stringField(obj, key);
107602
+ return value && value.length > 0 ? value : void 0;
107603
+ }
107600
107604
  function parseLarkCliMessages(stdout2) {
107601
107605
  const parsed = JSON.parse(stdout2);
107602
107606
  if (Array.isArray(parsed)) return parsed;
@@ -107610,6 +107614,25 @@ function parseLarkCliMessages(stdout2) {
107610
107614
  }
107611
107615
  return null;
107612
107616
  }
107617
+ function expandMessagesWithThreadReplies(messages) {
107618
+ const expanded = [];
107619
+ for (const raw of messages) {
107620
+ expanded.push(raw);
107621
+ if (!raw || typeof raw !== "object") continue;
107622
+ const parent = raw;
107623
+ const parentRootId = nonEmptyStringField(parent, "root_id") ?? nonEmptyStringField(parent, "message_id");
107624
+ const replies = arrayField(parent, "thread_replies") ?? [];
107625
+ for (const replyRaw of replies) {
107626
+ if (!replyRaw || typeof replyRaw !== "object") continue;
107627
+ const reply = replyRaw;
107628
+ expanded.push({
107629
+ ...reply,
107630
+ root_id: nonEmptyStringField(reply, "root_id") ?? parentRootId
107631
+ });
107632
+ }
107633
+ }
107634
+ return expanded;
107635
+ }
107613
107636
  function cardActionChoice(value) {
107614
107637
  if (value && typeof value === "object") {
107615
107638
  const choice = value["larkway_choice"];
@@ -107942,8 +107965,9 @@ var init_channelClient = __esm({
107942
107965
  log(`gap-fill: failed to parse lark-cli output for chat ${chatId}`);
107943
107966
  continue;
107944
107967
  }
107945
- totalFetched += messages.length;
107946
- for (const raw of messages) {
107968
+ const messagesWithReplies = expandMessagesWithThreadReplies(messages);
107969
+ totalFetched += messagesWithReplies.length;
107970
+ for (const raw of messagesWithReplies) {
107947
107971
  if (this.closed) break;
107948
107972
  const m = raw;
107949
107973
  const messageId = m["message_id"];
@@ -124006,24 +124030,16 @@ import { spawn as spawn4 } from "node:child_process";
124006
124030
  import { readFile as readFile10, access as access9 } from "node:fs/promises";
124007
124031
  import "node:module";
124008
124032
  import path17 from "node:path";
124009
- var DEFAULT_GITLAB_HOST = "github.com";
124010
- var DEFAULT_RELEASE_REPO = "chuckwu0/larkway";
124011
- var LATEST_TGZ_NAME = "larkway-latest.tgz";
124012
- function buildLatestUrl(gitlabHost, repo) {
124013
- return `https://${gitlabHost}/git/${repo}/-/releases/permalink/latest/downloads/${LATEST_TGZ_NAME}`;
124014
- }
124015
- function resolveReleaseCoords() {
124016
- const gitlabHost = process.env["GITLAB_HOST"] ?? DEFAULT_GITLAB_HOST;
124017
- const repo = process.env["LARKWAY_RELEASE_REPO"] ?? DEFAULT_RELEASE_REPO;
124018
- const latestUrl = process.env["LARKWAY_UPDATE_URL"] ?? buildLatestUrl(gitlabHost, repo);
124019
- return { gitlabHost, repo, latestUrl };
124033
+ var DEFAULT_NPM_PACKAGE_SPEC = "larkway@latest";
124034
+ function resolveNpmPackageSpec() {
124035
+ return process.env["LARKWAY_UPDATE_URL"] ?? DEFAULT_NPM_PACKAGE_SPEC;
124020
124036
  }
124021
- function buildReleaseSteps(latestUrl, cwd) {
124037
+ function buildNpmSteps(packageSpec, cwd) {
124022
124038
  return [
124023
124039
  {
124024
- label: `npm i -g ${latestUrl}`,
124040
+ label: `npm i -g ${packageSpec}`,
124025
124041
  cmd: "npm",
124026
- args: ["i", "-g", latestUrl],
124042
+ args: ["i", "-g", packageSpec],
124027
124043
  cwd
124028
124044
  },
124029
124045
  {
@@ -124177,24 +124193,24 @@ async function run7(ctx, args) {
124177
124193
  const { ui, flags, cwd } = ctx;
124178
124194
  const isDryRun = args.includes("--dry-run");
124179
124195
  const forceGitPull = args.includes("--git-pull");
124180
- const { latestUrl } = resolveReleaseCoords();
124196
+ const packageSpec = resolveNpmPackageSpec();
124181
124197
  if (!forceGitPull) {
124182
- const releaseSteps = buildReleaseSteps(latestUrl, cwd);
124198
+ const npmSteps = buildNpmSteps(packageSpec, cwd);
124183
124199
  const lifecycleLabels2 = /* @__PURE__ */ new Set(["larkway stop (bridge lifecycle)", "larkway start (bridge lifecycle)"]);
124184
124200
  if (isDryRun) {
124185
124201
  if (flags.json) {
124186
124202
  ui.emitJson({
124187
124203
  ok: true,
124188
124204
  dryRun: true,
124189
- mode: "release",
124190
- latestUrl,
124191
- steps: releaseSteps.map((s) => ({ label: s.label, cmd: s.cmd, args: s.args, cwd: s.cwd }))
124205
+ mode: "npm",
124206
+ packageSpec,
124207
+ steps: npmSteps.map((s) => ({ label: s.label, cmd: s.cmd, args: s.args, cwd: s.cwd }))
124192
124208
  });
124193
124209
  } else {
124194
- ui.print(ui.bold("larkway update --dry-run (release \u6E90\u6A21\u5F0F)"));
124195
- ui.print(ui.dim(` latest url: ${latestUrl}`));
124210
+ ui.print(ui.bold("larkway update --dry-run (npm \u6E90\u6A21\u5F0F)"));
124211
+ ui.print(ui.dim(` package: ${packageSpec}`));
124196
124212
  ui.print("");
124197
- releaseSteps.forEach((s, i) => {
124213
+ npmSteps.forEach((s, i) => {
124198
124214
  ui.print(` ${ui.cyan(String(i + 1) + ".")} ${s.label}`);
124199
124215
  ui.print(ui.dim(` $ ${s.cmd} ${s.args.join(" ")}`));
124200
124216
  });
@@ -124205,14 +124221,14 @@ async function run7(ctx, args) {
124205
124221
  return 0;
124206
124222
  }
124207
124223
  if (flags.json) {
124208
- ui.emitJson({ ok: true, status: "starting", mode: "release", latestUrl, stepCount: releaseSteps.length });
124224
+ ui.emitJson({ ok: true, status: "starting", mode: "npm", packageSpec, stepCount: npmSteps.length });
124209
124225
  } else {
124210
- ui.print(ui.bold("larkway update (release \u6E90)"));
124211
- ui.print(ui.dim(` latest: ${latestUrl}`));
124226
+ ui.print(ui.bold("larkway update (npm \u6E90)"));
124227
+ ui.print(ui.dim(` package: ${packageSpec}`));
124212
124228
  }
124213
- const { ok: ok3, lifecycleWarnings: lifecycleWarnings2 } = await runSteps(releaseSteps, lifecycleLabels2, flags, ui);
124229
+ const { ok: ok3, lifecycleWarnings: lifecycleWarnings2 } = await runSteps(npmSteps, lifecycleLabels2, flags, ui);
124214
124230
  if (!ok3) {
124215
- const fallbackMsg = "release \u5347\u7EA7\u5931\u8D25\u3002\u82E5\u7F51\u7EDC\u4E0D\u901A\u6216 latest \u94FE\u63A5\u672A\u5C31\u7EEA,\u53EF\u6539\u7528 `larkway update --git-pull` \u8D70 git pull + build \u8DEF\u5F84\u3002";
124231
+ const fallbackMsg = "npm \u5347\u7EA7\u5931\u8D25\u3002\u82E5\u7F51\u7EDC\u4E0D\u901A\u3001npm \u6743\u9650\u4E0D\u8DB3\u6216\u6E90\u4E0D\u53EF\u7528,\u53EF\u6539\u7528 `larkway update --git-pull` \u8D70 git pull + build \u8DEF\u5F84\u3002";
124216
124232
  if (flags.json) {
124217
124233
  ui.emitJson({ ok: false, hint: fallbackMsg });
124218
124234
  } else {
@@ -124226,14 +124242,14 @@ async function run7(ctx, args) {
124226
124242
  if (hadWarning2) {
124227
124243
  ui.emitJson({ ok: true, status: "complete_with_warnings", warning: lifecycleWarnings2.join("; ") });
124228
124244
  } else {
124229
- ui.emitJson({ ok: true, status: "complete", mode: "release" });
124245
+ ui.emitJson({ ok: true, status: "complete", mode: "npm" });
124230
124246
  }
124231
124247
  } else {
124232
124248
  ui.print("");
124233
124249
  if (hadWarning2) {
124234
124250
  ui.success("larkway update \u5B8C\u6210,\u4F46 bridge \u9700\u624B\u52A8\u91CD\u542F(\u8BF7\u8FD0\u884C `larkway start`)\u3002");
124235
124251
  } else {
124236
- ui.success("larkway update \u5B8C\u6210\u3002\u5DF2\u5347\u7EA7\u5230\u6700\u65B0 release,bridge \u5DF2\u91CD\u542F\u3002");
124252
+ ui.success("larkway update \u5B8C\u6210\u3002\u5DF2\u5347\u7EA7\u5230\u6700\u65B0 npm \u7248\u672C,bridge \u5DF2\u91CD\u542F\u3002");
124237
124253
  }
124238
124254
  }
124239
124255
  return 0;
package/dist/main.js CHANGED
@@ -111823,6 +111823,10 @@ function stringField(obj, key) {
111823
111823
  const value = obj[key];
111824
111824
  return typeof value === "string" ? value : void 0;
111825
111825
  }
111826
+ function nonEmptyStringField(obj, key) {
111827
+ const value = stringField(obj, key);
111828
+ return value && value.length > 0 ? value : void 0;
111829
+ }
111826
111830
  function parseLarkCliMessages(stdout) {
111827
111831
  const parsed = JSON.parse(stdout);
111828
111832
  if (Array.isArray(parsed)) return parsed;
@@ -111836,6 +111840,25 @@ function parseLarkCliMessages(stdout) {
111836
111840
  }
111837
111841
  return null;
111838
111842
  }
111843
+ function expandMessagesWithThreadReplies(messages) {
111844
+ const expanded = [];
111845
+ for (const raw of messages) {
111846
+ expanded.push(raw);
111847
+ if (!raw || typeof raw !== "object") continue;
111848
+ const parent = raw;
111849
+ const parentRootId = nonEmptyStringField(parent, "root_id") ?? nonEmptyStringField(parent, "message_id");
111850
+ const replies = arrayField(parent, "thread_replies") ?? [];
111851
+ for (const replyRaw of replies) {
111852
+ if (!replyRaw || typeof replyRaw !== "object") continue;
111853
+ const reply = replyRaw;
111854
+ expanded.push({
111855
+ ...reply,
111856
+ root_id: nonEmptyStringField(reply, "root_id") ?? parentRootId
111857
+ });
111858
+ }
111859
+ }
111860
+ return expanded;
111861
+ }
111839
111862
  function cardActionChoice(value) {
111840
111863
  if (value && typeof value === "object") {
111841
111864
  const choice = value["larkway_choice"];
@@ -112154,8 +112177,9 @@ var ChannelClient = class {
112154
112177
  log(`gap-fill: failed to parse lark-cli output for chat ${chatId}`);
112155
112178
  continue;
112156
112179
  }
112157
- totalFetched += messages.length;
112158
- for (const raw of messages) {
112180
+ const messagesWithReplies = expandMessagesWithThreadReplies(messages);
112181
+ totalFetched += messagesWithReplies.length;
112182
+ for (const raw of messagesWithReplies) {
112159
112183
  if (this.closed) break;
112160
112184
  const m = raw;
112161
112185
  const messageId = m["message_id"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "larkway",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "description": "Thin bridge: Feishu thread to local Claude Code CLI",
5
5
  "license": "MIT",
6
6
  "author": "Chuck Wu (chuckwu0)",