lark-remote 0.3.0 → 0.4.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.
@@ -22,6 +22,9 @@
22
22
  * 以 `turn_diff` 快照发出——禁止把 delta 直接当快照或把全文当增量重复追加。
23
23
  * 4. `tool_call` 事件可能**没有 rawInput**(工具 lazy-create,参数在后续
24
24
  * tool_call_update 才补齐);translator 必须归一化为 `{}`,不得因缺失崩溃。
25
+ * 5. `session/request_permission` 的 toolCall **不一定带 rawInput**(kimi 实测:
26
+ * 审批门先于 tool.call.started,只有 title + content 截断摘要);完整命令
27
+ * 需按 toolCallId 关联审批前的流式 args 文本恢复(BaseAcpTranslator 追踪)。
25
28
  */
26
29
  export type { JsonRpcRequest, JsonRpcNotification, JsonRpcSuccessResponse, JsonRpcErrorResponse, } from '../jsonrpc/types.js';
27
30
  /** Standard JSON-RPC error codes. */
@@ -226,9 +229,20 @@ export interface PermissionOption {
226
229
  }
227
230
  export interface RequestPermissionParams {
228
231
  sessionId: string;
232
+ /**
233
+ * Approval target. Divergence by server (2026-09-13 live probes):
234
+ * - kimi 0.42: {toolCallId, title: toolName, content: [truncated summary
235
+ * text]} — NO rawInput; the approval gate fires BEFORE tool.call.started,
236
+ * so the full args only exist in the pre-approval tool_call/_update
237
+ * streaming deltas (correlate by toolCallId, see BaseAcpTranslator).
238
+ * - opencode: {toolCallId, title: full command for bash/shell, rawInput:
239
+ * full input object} — title/rawInput are directly usable.
240
+ */
229
241
  toolCall?: {
230
- title: string;
231
- rawInput: string;
242
+ toolCallId?: string;
243
+ title?: string;
244
+ rawInput?: unknown;
245
+ content?: unknown[];
232
246
  [key: string]: unknown;
233
247
  };
234
248
  options: PermissionOption[];
@@ -22,6 +22,9 @@
22
22
  * 以 `turn_diff` 快照发出——禁止把 delta 直接当快照或把全文当增量重复追加。
23
23
  * 4. `tool_call` 事件可能**没有 rawInput**(工具 lazy-create,参数在后续
24
24
  * tool_call_update 才补齐);translator 必须归一化为 `{}`,不得因缺失崩溃。
25
+ * 5. `session/request_permission` 的 toolCall **不一定带 rawInput**(kimi 实测:
26
+ * 审批门先于 tool.call.started,只有 title + content 截断摘要);完整命令
27
+ * 需按 toolCallId 关联审批前的流式 args 文本恢复(BaseAcpTranslator 追踪)。
25
28
  */
26
29
  /** Standard JSON-RPC error codes. */
27
30
  export const RpcErrorCode = {
@@ -120,13 +120,31 @@ export class KimiAcpTranslator extends BaseAcpTranslator {
120
120
  getLogger().info(`[kimi-acp-translator] permission request without toolCall, auto-responding cancelled (requestId=${requestId})`);
121
121
  return [];
122
122
  }
123
+ // 命令恢复(2026-09-13 对 kimi 0.42.0 实测):审批门在 tool.call.started
124
+ // 之前触发,request_permission 的 toolCall 只有 title("Bash")+ content
125
+ // 里一句截断摘要("Requesting approval to Running: <cmd>…"),无 rawInput;
126
+ // 完整命令只从审批前的 tool_call/tool_call_update 流式 args 累积文本拿到
127
+ // (基类按 toolCallId 追踪)。解析顺序:流式 args JSON 的 command 字段 →
128
+ // title;流式缺失时退回 content 摘要放进 reason(旧版 kimi 不推 delta)。
129
+ const tracked = typeof toolCall.toolCallId === 'string'
130
+ ? this.getTrackedToolCallArgs(toolCall.toolCallId)
131
+ : undefined;
132
+ const argsCommand = tracked ? extractCommandFromArgsText(tracked) : undefined;
133
+ const rawInput = typeof toolCall.rawInput === 'string' && toolCall.rawInput.length > 0
134
+ ? toolCall.rawInput
135
+ : undefined;
136
+ const summary = extractPermissionSummaryText(toolCall.content);
123
137
  const view = {
124
138
  requestId,
125
139
  kind: 'command',
126
- command: params.toolCall?.title ?? undefined,
127
- reason: params.toolCall?.rawInput
128
- ? truncateWithEllipsis(params.toolCall.rawInput, 200)
129
- : undefined,
140
+ command: argsCommand ?? toolCall.title ?? undefined,
141
+ reason: argsCommand
142
+ ? undefined
143
+ : rawInput
144
+ ? truncateWithEllipsis(rawInput, 200)
145
+ : summary
146
+ ? truncateWithEllipsis(summary, 200)
147
+ : undefined,
130
148
  // §P4: 从服务端 options kind 派生——带 approve_always(或 allow_always)
131
149
  // 才提供「本会话总是允许」(acceptForSession);否则与旧行为一致。
132
150
  availableDecisions: deriveAcpAvailableDecisions(params.options ?? []),
@@ -244,4 +262,42 @@ function extractQuestionText(toolCall) {
244
262
  }
245
263
  return toolCall?.title?.trim() || '请选择';
246
264
  }
265
+ /**
266
+ * 从流式累积的 args 文本恢复命令:完整 JSON 且含 string command 字段时取该
267
+ * 字段;否则(非 Bash 工具 / 防御性半截 JSON)返回原文。
268
+ */
269
+ function extractCommandFromArgsText(argsText) {
270
+ try {
271
+ const parsed = JSON.parse(argsText);
272
+ if (parsed && typeof parsed === 'object') {
273
+ const command = parsed.command;
274
+ if (typeof command === 'string' && command.length > 0)
275
+ return command;
276
+ }
277
+ }
278
+ catch {
279
+ // 半截 JSON(审批正常在 args 流式完成后才到,此处纯防御)——用原文。
280
+ }
281
+ return argsText;
282
+ }
283
+ /**
284
+ * request_permission toolCall.content 里的摘要文本(kimi 0.42:
285
+ * "Requesting approval to Running: <cmd>…",约 64 字符截断)。无文本返回
286
+ * undefined。
287
+ */
288
+ function extractPermissionSummaryText(content) {
289
+ if (!Array.isArray(content))
290
+ return undefined;
291
+ let text = '';
292
+ let found = false;
293
+ for (const block of content) {
294
+ const t = block?.content
295
+ ?.text;
296
+ if (typeof t === 'string' && t.length > 0) {
297
+ text += t;
298
+ found = true;
299
+ }
300
+ }
301
+ return found ? text : undefined;
302
+ }
247
303
  //# sourceMappingURL=translator.js.map
@@ -14,7 +14,7 @@ interface SessionEntry {
14
14
  /**
15
15
  * Per-user session store. Persists cwd + per-agent sessions to disk so that
16
16
  * the last workspace AND the last-used sessionId per agent are restored after
17
- * a bridge restart.
17
+ * a lark-remote restart.
18
18
  *
19
19
  * Persistence strategy:
20
20
  * - Persists `cwd`, `sessions` (per-agent sessionId), `previousSessions`
@@ -4,7 +4,7 @@ import { atomicWriteJson } from '../persistence/atomic-write.js';
4
4
  /**
5
5
  * Per-user session store. Persists cwd + per-agent sessions to disk so that
6
6
  * the last workspace AND the last-used sessionId per agent are restored after
7
- * a bridge restart.
7
+ * a lark-remote restart.
8
8
  *
9
9
  * Persistence strategy:
10
10
  * - Persists `cwd`, `sessions` (per-agent sessionId), `previousSessions`
@@ -9,7 +9,7 @@ export interface WorkspaceEntry {
9
9
  *
10
10
  * Atomic write (§9.10): writes a temp file then `fs.rename` so a crash
11
11
  * mid-write cannot leave a truncated JSON file. On load, a corrupt file
12
- * is treated as empty (with a warning) so the bridge can still start.
12
+ * is treated as empty (with a warning) so the lark-remote can still start.
13
13
  *
14
14
  * lastUsedAt 语义(2026-08-19 语义对齐):保存(save)与使用(use/touch)
15
15
  * 都会把时间戳更新为当前时间。save 内部调用 touch,保证「最近使用」排序
@@ -8,7 +8,7 @@ import { getLogger } from '../logger/index.js';
8
8
  *
9
9
  * Atomic write (§9.10): writes a temp file then `fs.rename` so a crash
10
10
  * mid-write cannot leave a truncated JSON file. On load, a corrupt file
11
- * is treated as empty (with a warning) so the bridge can still start.
11
+ * is treated as empty (with a warning) so the lark-remote can still start.
12
12
  *
13
13
  * lastUsedAt 语义(2026-08-19 语义对齐):保存(save)与使用(use/touch)
14
14
  * 都会把时间戳更新为当前时间。save 内部调用 touch,保证「最近使用」排序
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lark-remote",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Feishu (Lark) private-chat bridge to local coding agents — Claude Code / Codex / opencode / pi / kimi, with live-streaming CardKit 2.0 cards",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",