@modelzen/feishu-codex-bridge 0.6.7-test.4 → 0.6.8

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 (2) hide show
  1. package/dist/cli.js +74 -30
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -4111,6 +4111,7 @@ ${b.thinking}` : b.thinking;
4111
4111
 
4112
4112
  // src/agent/claude-agent/thread.ts
4113
4113
  init_logger();
4114
+ import { readFile as readFile5 } from "fs/promises";
4114
4115
  var COMPACT_TIMEOUT_MS2 = 12e4;
4115
4116
  var ABORT_ESCALATE_MS = 4e3;
4116
4117
  var Inbox = class {
@@ -4160,13 +4161,50 @@ function toSdkEffort(e) {
4160
4161
  if (e === "none" || e === "minimal") return "low";
4161
4162
  return e;
4162
4163
  }
4163
- function toUserMessage(input2) {
4164
+ var MAX_IMAGE_BYTES = 20 * 1024 * 1024;
4165
+ function sniffImageType(b) {
4166
+ if (b.length >= 8 && b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71) return "image/png";
4167
+ if (b.length >= 3 && b[0] === 255 && b[1] === 216 && b[2] === 255) return "image/jpeg";
4168
+ if (b.length >= 6 && b[0] === 71 && b[1] === 73 && b[2] === 70 && b[3] === 56) return "image/gif";
4169
+ if (b.length >= 12 && b.toString("ascii", 0, 4) === "RIFF" && b.toString("ascii", 8, 12) === "WEBP") return "image/webp";
4170
+ return void 0;
4171
+ }
4172
+ async function toImageBlock(path) {
4173
+ let bytes;
4174
+ try {
4175
+ bytes = await readFile5(path);
4176
+ } catch (err) {
4177
+ log.warn("agent", "image-read-failed", { backend: "claude-agent", err: String(err) });
4178
+ return void 0;
4179
+ }
4180
+ if (bytes.byteLength === 0 || bytes.byteLength > MAX_IMAGE_BYTES) {
4181
+ log.warn("agent", "image-skip-size", { backend: "claude-agent", bytes: bytes.byteLength });
4182
+ return void 0;
4183
+ }
4184
+ const mediaType = sniffImageType(bytes);
4185
+ if (!mediaType) {
4186
+ log.info("agent", "image-skip-unsupported", { backend: "claude-agent", head: bytes.toString("hex", 0, 4) });
4187
+ return void 0;
4188
+ }
4189
+ return { type: "image", source: { type: "base64", media_type: mediaType, data: bytes.toString("base64") } };
4190
+ }
4191
+ function textUserMessage(text) {
4192
+ return { type: "user", message: { role: "user", content: text }, parent_tool_use_id: null };
4193
+ }
4194
+ async function toUserMessage(input2) {
4164
4195
  const text = input2.text ?? "";
4165
- return {
4166
- type: "user",
4167
- message: { role: "user", content: text },
4168
- parent_tool_use_id: null
4169
- };
4196
+ const paths2 = input2.images ?? [];
4197
+ if (paths2.length === 0) return textUserMessage(text);
4198
+ const blocks = [];
4199
+ if (text) blocks.push({ type: "text", text });
4200
+ for (const path of paths2) {
4201
+ const block = await toImageBlock(path);
4202
+ if (block) blocks.push(block);
4203
+ }
4204
+ const imageCount = blocks.filter((b) => b.type === "image").length;
4205
+ if (imageCount === 0) return textUserMessage(text);
4206
+ log.info("agent", "images-attached", { backend: "claude-agent", count: imageCount, of: paths2.length });
4207
+ return { type: "user", message: { role: "user", content: blocks }, parent_tool_use_id: null };
4170
4208
  }
4171
4209
  function goalPrompt(objective) {
4172
4210
  return [
@@ -4253,7 +4291,13 @@ var ClaudeAgentThread = class {
4253
4291
  const inbox = new Inbox();
4254
4292
  const mySink = (item) => inbox.push(item);
4255
4293
  this.sink = mySink;
4256
- this.input.push(toUserMessage(input2));
4294
+ void toUserMessage(input2).then(
4295
+ (m) => this.input.push(m),
4296
+ (err) => {
4297
+ log.fail("agent", err, { backend: "claude-agent", phase: "build-user-message" });
4298
+ this.input.push(textUserMessage(input2.text ?? ""));
4299
+ }
4300
+ );
4257
4301
  const self = this;
4258
4302
  async function* gen() {
4259
4303
  yield { type: "turn_started", turnId };
@@ -4334,7 +4378,7 @@ var ClaudeAgentThread = class {
4334
4378
  const inbox = new Inbox();
4335
4379
  const mySink = (item) => inbox.push(item);
4336
4380
  this.sink = mySink;
4337
- this.input.push(toUserMessage({ text: goalPrompt(objective) }));
4381
+ this.input.push(textUserMessage(goalPrompt(objective)));
4338
4382
  const self = this;
4339
4383
  async function* gen() {
4340
4384
  yield { type: "goal_update", status: "active", objective, tokensUsed: 0, timeUsedSeconds: 0, tokenBudget: null };
@@ -4430,7 +4474,7 @@ var ClaudeAgentThread = class {
4430
4474
  });
4431
4475
  let compacted = false;
4432
4476
  try {
4433
- this.input.push(toUserMessage({ text: "/compact" }));
4477
+ this.input.push(textUserMessage("/compact"));
4434
4478
  while (true) {
4435
4479
  const step = await Promise.race([inbox.next(), timeout]);
4436
4480
  if (step === "timeout") throw new Error(`\u538B\u7F29\u8D85\u65F6\uFF08Claude \u672A\u5728 ${COMPACT_TIMEOUT_MS2 / 1e3}s \u5185\u5B8C\u6210\uFF09`);
@@ -4683,7 +4727,7 @@ async function effectiveDefaultBackend(opts) {
4683
4727
  }
4684
4728
 
4685
4729
  // src/agent/installer.ts
4686
- import { mkdir as mkdir4, rm as rm2, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
4730
+ import { mkdir as mkdir4, rm as rm2, readFile as readFile6, writeFile as writeFile4 } from "fs/promises";
4687
4731
  import { existsSync as existsSync4 } from "fs";
4688
4732
  import { join as join8 } from "path";
4689
4733
  init_paths();
@@ -4872,7 +4916,7 @@ async function rollback(bareName) {
4872
4916
  async function removeBackendsDep(bareName) {
4873
4917
  const pkgFile = join8(paths.backendsDir, "package.json");
4874
4918
  try {
4875
- const raw = await readFile5(pkgFile, "utf8");
4919
+ const raw = await readFile6(pkgFile, "utf8");
4876
4920
  const json = JSON.parse(raw);
4877
4921
  if (json.dependencies && bareName in json.dependencies) {
4878
4922
  delete json.dependencies[bareName];
@@ -5371,7 +5415,7 @@ init_schema();
5371
5415
 
5372
5416
  // src/project/registry.ts
5373
5417
  init_paths();
5374
- import { mkdir as mkdir5, readFile as readFile6, rename as rename4, writeFile as writeFile5 } from "fs/promises";
5418
+ import { mkdir as mkdir5, readFile as readFile7, rename as rename4, writeFile as writeFile5 } from "fs/promises";
5375
5419
  import { randomUUID as randomUUID3 } from "crypto";
5376
5420
  import { dirname as dirname5 } from "path";
5377
5421
  function defaultNoMention(p) {
@@ -5398,7 +5442,7 @@ async function read() {
5398
5442
  }
5399
5443
  async function listProjectsIn(file) {
5400
5444
  try {
5401
- const text = await readFile6(file, "utf8");
5445
+ const text = await readFile7(file, "utf8");
5402
5446
  const parsed = JSON.parse(text);
5403
5447
  return Array.isArray(parsed.projects) ? parsed.projects : [];
5404
5448
  } catch (err) {
@@ -8221,7 +8265,7 @@ function structureSig(card2, eid) {
8221
8265
 
8222
8266
  // src/card/outbound-images.ts
8223
8267
  init_logger();
8224
- import { readFile as readFile7, stat as stat2 } from "fs/promises";
8268
+ import { readFile as readFile8, stat as stat2 } from "fs/promises";
8225
8269
  import { extname as extname2, isAbsolute, resolve as resolve2, sep } from "path";
8226
8270
  var MAX_IMAGES = 9;
8227
8271
  var MAX_BYTES = 10 * 1024 * 1024;
@@ -8308,7 +8352,7 @@ async function loadLocal(src, cwd) {
8308
8352
  log.warn("outbound", "image-size", { size, src: src.slice(0, 80) });
8309
8353
  return { cacheKey: `local:${abs}:${size}` };
8310
8354
  }
8311
- const buffer = await readFile7(abs);
8355
+ const buffer = await readFile8(abs);
8312
8356
  return { buffer, cacheKey: `local:${abs}:${mtimeMs}:${size}` };
8313
8357
  }
8314
8358
  async function loadRemote(url) {
@@ -8361,7 +8405,7 @@ init_logger();
8361
8405
  init_cards2();
8362
8406
 
8363
8407
  // src/cli-bridge/hooks.ts
8364
- import { mkdir as mkdir6, readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
8408
+ import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile6 } from "fs/promises";
8365
8409
  import { homedir as homedir3 } from "os";
8366
8410
  import { join as join10, resolve as resolve3 } from "path";
8367
8411
  var AGENT2LARK_MARKER = "agent2lark-hook";
@@ -8382,7 +8426,7 @@ async function inspectCliBridgeHooks(opts = {}) {
8382
8426
  const codex = await readJson(join10(home, ".codex", "hooks.json"));
8383
8427
  let codexStatus = inspectAgent("codex", codex, [...CODEX_EVENTS]);
8384
8428
  if (codexStatus.status === "installed") {
8385
- const toml = await readFile8(join10(home, ".codex", "config.toml"), "utf8").catch(() => "");
8429
+ const toml = await readFile9(join10(home, ".codex", "config.toml"), "utf8").catch(() => "");
8386
8430
  if (!hasCodexHooksFeature(toml)) {
8387
8431
  codexStatus = {
8388
8432
  agent: "codex",
@@ -8410,7 +8454,7 @@ async function installCliBridgeHooks(opts) {
8410
8454
  json.hooks = installAgentGroups(json.hooks, "codex", [...CODEX_EVENTS], opts.command);
8411
8455
  await writeJson(file, json);
8412
8456
  const tomlPath = join10(home, ".codex", "config.toml");
8413
- const existing = await readFile8(tomlPath, "utf8").catch(() => "");
8457
+ const existing = await readFile9(tomlPath, "utf8").catch(() => "");
8414
8458
  await mkdir6(join10(home, ".codex"), { recursive: true });
8415
8459
  await writeFile6(tomlPath, withCodexHooksFeature(existing), "utf8");
8416
8460
  }
@@ -8419,7 +8463,7 @@ function resolveHome(homeDir) {
8419
8463
  return homeDir ?? homedir3();
8420
8464
  }
8421
8465
  async function readJson(path) {
8422
- const text = await readFile8(path, "utf8").catch(() => "{}");
8466
+ const text = await readFile9(path, "utf8").catch(() => "{}");
8423
8467
  const parsed = JSON.parse(text || "{}");
8424
8468
  return typeof parsed === "object" && parsed ? parsed : {};
8425
8469
  }
@@ -8556,7 +8600,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
8556
8600
  // src/service/common.ts
8557
8601
  init_paths();
8558
8602
  import { appendFileSync, createReadStream, statSync as statSync2 } from "fs";
8559
- import { appendFile, mkdir as mkdir7, readFile as readFile9 } from "fs/promises";
8603
+ import { appendFile, mkdir as mkdir7, readFile as readFile10 } from "fs/promises";
8560
8604
  import { dirname as dirname6, join as join11, resolve as resolve4 } from "path";
8561
8605
  import { fileURLToPath as fileURLToPath2 } from "url";
8562
8606
  function serviceStdoutPath() {
@@ -8625,7 +8669,7 @@ function fileSize(file) {
8625
8669
  }
8626
8670
  async function lastLines(file, n) {
8627
8671
  try {
8628
- const text = await readFile9(file, "utf8");
8672
+ const text = await readFile10(file, "utf8");
8629
8673
  return text.split("\n").slice(-n - 1).join("\n").trimEnd();
8630
8674
  } catch {
8631
8675
  return "";
@@ -9435,7 +9479,7 @@ async function restartDaemon() {
9435
9479
 
9436
9480
  // src/agent/codex-appserver/usage.ts
9437
9481
  init_logger();
9438
- import { readFile as readFile10 } from "fs/promises";
9482
+ import { readFile as readFile11 } from "fs/promises";
9439
9483
  import { homedir as homedir6 } from "os";
9440
9484
  import { join as join16 } from "path";
9441
9485
  var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
@@ -9453,7 +9497,7 @@ async function readCodexAuth() {
9453
9497
  for (let i = 0; i < 3; i++) {
9454
9498
  let raw;
9455
9499
  try {
9456
- raw = await readFile10(file, "utf8");
9500
+ raw = await readFile11(file, "utf8");
9457
9501
  } catch (err) {
9458
9502
  throw new UsageError("no-auth", `\u8BFB\u4E0D\u5230 ${file}\uFF1A${err instanceof Error ? err.message : String(err)}`);
9459
9503
  }
@@ -9482,7 +9526,7 @@ function jwtExpMs(token) {
9482
9526
  }
9483
9527
  async function chatgptBaseUrl() {
9484
9528
  try {
9485
- const raw = await readFile10(join16(resolveCodexHome(), "config.toml"), "utf8");
9529
+ const raw = await readFile11(join16(resolveCodexHome(), "config.toml"), "utf8");
9486
9530
  for (const line of raw.split("\n")) {
9487
9531
  const t = line.trim();
9488
9532
  if (t.startsWith("[")) break;
@@ -10367,7 +10411,7 @@ async function leaveChat(channel, chatId) {
10367
10411
 
10368
10412
  // src/bot/session-store.ts
10369
10413
  init_paths();
10370
- import { mkdir as mkdir12, readFile as readFile11, rename as rename5, writeFile as writeFile10 } from "fs/promises";
10414
+ import { mkdir as mkdir12, readFile as readFile12, rename as rename5, writeFile as writeFile10 } from "fs/promises";
10371
10415
  import { randomUUID as randomUUID5 } from "crypto";
10372
10416
  import { dirname as dirname12 } from "path";
10373
10417
  var FILE_VERSION3 = 2;
@@ -10386,7 +10430,7 @@ async function read2() {
10386
10430
  }
10387
10431
  async function listSessionsIn(file) {
10388
10432
  try {
10389
- const text = await readFile11(file, "utf8");
10433
+ const text = await readFile12(file, "utf8");
10390
10434
  const parsed = JSON.parse(text);
10391
10435
  if (!Array.isArray(parsed.sessions)) return [];
10392
10436
  return parsed.sessions.map(migrate);
@@ -11020,7 +11064,7 @@ function weaveSender(text, sender) {
11020
11064
 
11021
11065
  // src/bot/comments.ts
11022
11066
  init_logger();
11023
- import { mkdir as mkdir14, readdir as readdir4, readFile as readFile12, writeFile as writeFile11 } from "fs/promises";
11067
+ import { mkdir as mkdir14, readdir as readdir4, readFile as readFile13, writeFile as writeFile11 } from "fs/promises";
11024
11068
  import { dirname as dirname13, join as join19 } from "path";
11025
11069
  var SUPPORTED_FILE_TYPES = /* @__PURE__ */ new Set(["doc", "docx", "sheet", "bitable"]);
11026
11070
  var REPLY_MAX_CHARS = 2e3;
@@ -11149,7 +11193,7 @@ function commentCwd(projectsRoot, fileType, fileToken) {
11149
11193
  }
11150
11194
  async function loadCommentInstructions(masterFile) {
11151
11195
  try {
11152
- const existing = await readFile12(masterFile, "utf8");
11196
+ const existing = await readFile13(masterFile, "utf8");
11153
11197
  return existing.trim() ? existing : DEFAULT_COMMENT_INSTRUCTIONS;
11154
11198
  } catch {
11155
11199
  }
@@ -14398,7 +14442,7 @@ function createAdminIpcResponder(execute, send) {
14398
14442
  // src/admin/service.ts
14399
14443
  init_bots();
14400
14444
  init_paths();
14401
- import { readFile as readFile13, rm as rm7 } from "fs/promises";
14445
+ import { readFile as readFile14, rm as rm7 } from "fs/promises";
14402
14446
  init_schema();
14403
14447
  init_store();
14404
14448
  init_schema();
@@ -14571,7 +14615,7 @@ function createAdminService(deps = {}) {
14571
14615
  }
14572
14616
  async function lockFileRunState(botId) {
14573
14617
  try {
14574
- const raw = await readFile13(botPaths(botId).processesFile, "utf8");
14618
+ const raw = await readFile14(botPaths(botId).processesFile, "utf8");
14575
14619
  const rec = JSON.parse(raw);
14576
14620
  if (typeof rec.pid === "number" && isAlive2(rec.pid)) {
14577
14621
  return { running: true, pid: rec.pid, startedAt: rec.startedAt };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelzen/feishu-codex-bridge",
3
- "version": "0.6.7-test.4",
3
+ "version": "0.6.8",
4
4
  "description": "Bridge Feishu/Lark messenger with local Codex via app-server (project=group, thread=session)",
5
5
  "type": "module",
6
6
  "bin": {