@vibe-lark/larkpal 0.1.68 → 0.1.70
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/bin/larkpal.js +0 -0
- package/dist/main.mjs +135 -56
- package/package.json +14 -15
package/bin/larkpal.js
CHANGED
|
File without changes
|
package/dist/main.mjs
CHANGED
|
@@ -3011,7 +3011,7 @@ function wrapLarkpalAgentAdapter(adapter) {
|
|
|
3011
3011
|
return adapter.name;
|
|
3012
3012
|
},
|
|
3013
3013
|
executePrompt(config, callbacks) {
|
|
3014
|
-
return adapter.executePrompt(
|
|
3014
|
+
return adapter.executePrompt(config, callbacks);
|
|
3015
3015
|
},
|
|
3016
3016
|
stopProcess(sessionId) {
|
|
3017
3017
|
return adapter.stopProcess(sessionId);
|
|
@@ -3030,59 +3030,6 @@ function wrapLarkpalAgentAdapter(adapter) {
|
|
|
3030
3030
|
}
|
|
3031
3031
|
};
|
|
3032
3032
|
}
|
|
3033
|
-
function normalizeLarkpalAgentConfig(config) {
|
|
3034
|
-
if (!Array.isArray(config.prompt)) return config;
|
|
3035
|
-
const textParts = [];
|
|
3036
|
-
const imageArtifacts = [];
|
|
3037
|
-
const imageLines = [];
|
|
3038
|
-
config.prompt.forEach((block, index) => {
|
|
3039
|
-
if (block.type === "text") {
|
|
3040
|
-
if (block.text.trim()) textParts.push(block.text);
|
|
3041
|
-
return;
|
|
3042
|
-
}
|
|
3043
|
-
if (block.type !== "image") return;
|
|
3044
|
-
const artifact = toAgentImageArtifact(block, index);
|
|
3045
|
-
const label = artifact?.assetId ?? block.fileKey ?? `image_${index + 1}`;
|
|
3046
|
-
if (artifact) imageArtifacts.push(artifact);
|
|
3047
|
-
imageLines.push(artifact ? `- ${label}: ${artifact.path} (${artifact.mimeType})` : `- ${label}: inline image omitted from text prompt (${block.source.media_type})`);
|
|
3048
|
-
});
|
|
3049
|
-
if (imageLines.length === 0) return config;
|
|
3050
|
-
const prompt = [
|
|
3051
|
-
textParts.join("\n\n").trim(),
|
|
3052
|
-
"[Images]",
|
|
3053
|
-
...imageLines,
|
|
3054
|
-
"The user is asking about these image attachments. Use visual or file tools to inspect the image pixels when needed; do not infer image content from the file name alone."
|
|
3055
|
-
].filter(Boolean).join("\n");
|
|
3056
|
-
return {
|
|
3057
|
-
...config,
|
|
3058
|
-
prompt,
|
|
3059
|
-
sourceArtifacts: mergeSourceArtifacts(config.sourceArtifacts, imageArtifacts),
|
|
3060
|
-
metadata: {
|
|
3061
|
-
...config.metadata,
|
|
3062
|
-
inboundImageCount: imageLines.length,
|
|
3063
|
-
visualAllowedDirs: [config.cwd]
|
|
3064
|
-
}
|
|
3065
|
-
};
|
|
3066
|
-
}
|
|
3067
|
-
function toAgentImageArtifact(block, index) {
|
|
3068
|
-
if (!block.filePath) return null;
|
|
3069
|
-
return {
|
|
3070
|
-
type: "image_asset",
|
|
3071
|
-
assetId: block.fileKey ?? `inbound_image_${index + 1}`,
|
|
3072
|
-
path: block.filePath,
|
|
3073
|
-
mimeType: block.source.media_type.split(";", 1)[0] || "image/png",
|
|
3074
|
-
metadata: {
|
|
3075
|
-
source: "feishu-message",
|
|
3076
|
-
fileKey: block.fileKey
|
|
3077
|
-
}
|
|
3078
|
-
};
|
|
3079
|
-
}
|
|
3080
|
-
function mergeSourceArtifacts(existing, imageArtifacts) {
|
|
3081
|
-
if (imageArtifacts.length === 0) return existing;
|
|
3082
|
-
if (existing === void 0) return imageArtifacts;
|
|
3083
|
-
if (Array.isArray(existing)) return [...existing, ...imageArtifacts];
|
|
3084
|
-
return [existing, ...imageArtifacts];
|
|
3085
|
-
}
|
|
3086
3033
|
function getArtifactId(artifact) {
|
|
3087
3034
|
const artifactId = typeof artifact.artifactId === "string" ? artifact.artifactId.trim() : "";
|
|
3088
3035
|
if (artifactId.startsWith("art_")) return artifactId;
|
|
@@ -3724,6 +3671,8 @@ function summarizeString(value) {
|
|
|
3724
3671
|
*
|
|
3725
3672
|
* 路由:
|
|
3726
3673
|
* POST /api/chat/stream — SSE 流式对话
|
|
3674
|
+
* POST /api/chat/runs/:runId/cancel — 取消运行中的 Web Chat run
|
|
3675
|
+
* POST /api/chat/sessions/:id/cancel-active-run — 取消会话中的 active run
|
|
3727
3676
|
* GET /api/chat/history — 分页获取会话历史
|
|
3728
3677
|
* GET /api/chat/sessions — 列出当前用户的所有会话
|
|
3729
3678
|
* POST /api/chat/sessions — 创建新会话
|
|
@@ -3754,6 +3703,9 @@ function getActiveChatRun(sessionId) {
|
|
|
3754
3703
|
const run = chatRunsBySession.get(sessionId);
|
|
3755
3704
|
return run?.status === "running" ? run : void 0;
|
|
3756
3705
|
}
|
|
3706
|
+
function findChatRunByRunId(runId) {
|
|
3707
|
+
for (const run of chatRunsBySession.values()) if (run.runId === runId) return run;
|
|
3708
|
+
}
|
|
3757
3709
|
function serializeChatRun(run) {
|
|
3758
3710
|
const idleSeconds = Math.max(0, Math.floor((Date.now() - run.lastEventAt) / 1e3));
|
|
3759
3711
|
return {
|
|
@@ -3944,6 +3896,34 @@ async function cleanupTerminalRunProcess(run, processManager, reason) {
|
|
|
3944
3896
|
});
|
|
3945
3897
|
}
|
|
3946
3898
|
}
|
|
3899
|
+
async function cancelChatRun(run, messageStore, processManager) {
|
|
3900
|
+
if (run.status !== "running") return {
|
|
3901
|
+
cancelled: false,
|
|
3902
|
+
run: serializeChatRun(run)
|
|
3903
|
+
};
|
|
3904
|
+
const processInfo = processManager.getProcessInfo(run.sessionId);
|
|
3905
|
+
run.adapterBusy = processManager.isSessionBusy?.(run.sessionId) ?? processInfo?.status === "running";
|
|
3906
|
+
run.processStatus = processInfo?.status;
|
|
3907
|
+
await processManager.stopProcess(run.sessionId);
|
|
3908
|
+
const stoppedInfo = processManager.getProcessInfo(run.sessionId);
|
|
3909
|
+
run.adapterBusy = processManager.isSessionBusy?.(run.sessionId) ?? false;
|
|
3910
|
+
run.processStatus = stoppedInfo?.status ?? "stopped";
|
|
3911
|
+
const marked = await markRunTerminal(run, messageStore, "cancelled", {
|
|
3912
|
+
finalStatus: "user_cancelled",
|
|
3913
|
+
error: "Chat run cancelled by user"
|
|
3914
|
+
});
|
|
3915
|
+
if (marked) {
|
|
3916
|
+
broadcastRunEvent(run, "cancelled", {
|
|
3917
|
+
runId: run.runId,
|
|
3918
|
+
sessionId: run.sessionId
|
|
3919
|
+
});
|
|
3920
|
+
endRunClients(run);
|
|
3921
|
+
}
|
|
3922
|
+
return {
|
|
3923
|
+
cancelled: marked,
|
|
3924
|
+
run: serializeChatRun(run)
|
|
3925
|
+
};
|
|
3926
|
+
}
|
|
3947
3927
|
async function reconcileRunWithAdapter(run, messageStore, processManager) {
|
|
3948
3928
|
if (run.status !== "running") return;
|
|
3949
3929
|
const processInfo = processManager.getProcessInfo(run.sessionId);
|
|
@@ -4028,6 +4008,8 @@ function buildRuntimeEventMessageMetadata(event, runtimeConfig) {
|
|
|
4028
4008
|
*
|
|
4029
4009
|
* 路由:
|
|
4030
4010
|
* POST /api/chat/stream — SSE 流式对话
|
|
4011
|
+
* POST /api/chat/runs/:runId/cancel — 取消运行中的 Web Chat run
|
|
4012
|
+
* POST /api/chat/sessions/:id/cancel-active-run — 取消会话中的 active run
|
|
4031
4013
|
* GET /api/chat/history — 分页获取会话历史
|
|
4032
4014
|
* GET /api/chat/sessions — 列出当前用户的所有会话
|
|
4033
4015
|
* POST /api/chat/sessions — 创建新会话
|
|
@@ -4188,6 +4170,7 @@ function createChatRouter(config) {
|
|
|
4188
4170
|
}, 15e3);
|
|
4189
4171
|
const handleBlockedEvent = (event) => {
|
|
4190
4172
|
const sanitized = sanitizeBlockedEvent(event);
|
|
4173
|
+
if (run.status !== "running") return;
|
|
4191
4174
|
recordRunEvent(run, "blocked", { toolName: sanitized.name });
|
|
4192
4175
|
log$30.warn("[stream] Agent blocked event", { ...sanitized });
|
|
4193
4176
|
if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, sanitized.type, {
|
|
@@ -4219,6 +4202,7 @@ function createChatRouter(config) {
|
|
|
4219
4202
|
broadcastRunEvent(run, "blocked", { event: sanitized });
|
|
4220
4203
|
};
|
|
4221
4204
|
const handleRuntimeEvent = (event) => {
|
|
4205
|
+
if (run.status !== "running") return;
|
|
4222
4206
|
const dedupeKey = getRuntimeEventDedupeKey(event);
|
|
4223
4207
|
if (dedupeKey) {
|
|
4224
4208
|
if (run.seenRuntimeEventIds.has(dedupeKey)) {
|
|
@@ -4260,15 +4244,18 @@ function createChatRouter(config) {
|
|
|
4260
4244
|
};
|
|
4261
4245
|
const callbacks = {
|
|
4262
4246
|
onTextDelta: (text) => {
|
|
4247
|
+
if (run.status !== "running") return;
|
|
4263
4248
|
recordRunEvent(run, "text-delta");
|
|
4264
4249
|
run.text += text;
|
|
4265
4250
|
broadcastRunEvent(run, "text-delta", { text });
|
|
4266
4251
|
},
|
|
4267
4252
|
onThinkingDelta: (text) => {
|
|
4253
|
+
if (run.status !== "running") return;
|
|
4268
4254
|
recordRunEvent(run, "thinking-delta");
|
|
4269
4255
|
broadcastRunEvent(run, "thinking-delta", { text });
|
|
4270
4256
|
},
|
|
4271
4257
|
onToolUseStart: (toolName, toolInput) => {
|
|
4258
|
+
if (run.status !== "running") return;
|
|
4272
4259
|
recordRunEvent(run, "tool-use-start", { toolName });
|
|
4273
4260
|
if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "tool_call_started", {
|
|
4274
4261
|
toolName,
|
|
@@ -4297,6 +4284,7 @@ function createChatRouter(config) {
|
|
|
4297
4284
|
});
|
|
4298
4285
|
},
|
|
4299
4286
|
onToolResult: (toolUseId, result) => {
|
|
4287
|
+
if (run.status !== "running") return;
|
|
4300
4288
|
recordRunEvent(run, "tool-result");
|
|
4301
4289
|
const resultSummary = summarizeForAudit(result);
|
|
4302
4290
|
if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "tool_call_finished", {
|
|
@@ -4328,6 +4316,7 @@ function createChatRouter(config) {
|
|
|
4328
4316
|
});
|
|
4329
4317
|
},
|
|
4330
4318
|
onToolProgress: (toolName, elapsedSeconds) => {
|
|
4319
|
+
if (run.status !== "running") return;
|
|
4331
4320
|
recordRunEvent(run, "tool-progress", { toolName });
|
|
4332
4321
|
broadcastRunEvent(run, "tool-progress", {
|
|
4333
4322
|
toolName,
|
|
@@ -4335,11 +4324,13 @@ function createChatRouter(config) {
|
|
|
4335
4324
|
});
|
|
4336
4325
|
},
|
|
4337
4326
|
onTurnEnd: (stopReason) => {
|
|
4327
|
+
if (run.status !== "running") return;
|
|
4338
4328
|
recordRunEvent(run, "turn-end");
|
|
4339
4329
|
if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "turn_finished", { metadata: { stopReason } }));
|
|
4340
4330
|
broadcastRunEvent(run, "turn-end", { stopReason });
|
|
4341
4331
|
},
|
|
4342
4332
|
onResult: async (result) => {
|
|
4333
|
+
if (run.status !== "running") return;
|
|
4343
4334
|
recordRunEvent(run, "result");
|
|
4344
4335
|
const finalText = run.text.trim() ? run.text : result.result || "";
|
|
4345
4336
|
run.text = finalText;
|
|
@@ -4395,6 +4386,7 @@ function createChatRouter(config) {
|
|
|
4395
4386
|
}));
|
|
4396
4387
|
},
|
|
4397
4388
|
onError: async (error) => {
|
|
4389
|
+
if (run.status !== "running") return;
|
|
4398
4390
|
recordRunEvent(run, "error");
|
|
4399
4391
|
log$30.error("[stream] Runtime 执行出错", {
|
|
4400
4392
|
sessionId,
|
|
@@ -4445,6 +4437,7 @@ function createChatRouter(config) {
|
|
|
4445
4437
|
});
|
|
4446
4438
|
},
|
|
4447
4439
|
onVerifierResult: (result) => {
|
|
4440
|
+
if (run.status !== "running") return;
|
|
4448
4441
|
recordRunEvent(run, "verifier-result");
|
|
4449
4442
|
const resultSummary = summarizeForAudit(result);
|
|
4450
4443
|
if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "verifier_result", {
|
|
@@ -4519,6 +4512,84 @@ function createChatRouter(config) {
|
|
|
4519
4512
|
if (run.status === "running") await callbacks.onError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
4520
4513
|
}
|
|
4521
4514
|
});
|
|
4515
|
+
router.post("/api/chat/runs/:runId/cancel", chatAuthMiddleware, async (req, res) => {
|
|
4516
|
+
const chatUser = res.locals.chatUser;
|
|
4517
|
+
const runId = String(req.params.runId);
|
|
4518
|
+
const run = findChatRunByRunId(runId);
|
|
4519
|
+
if (!run) {
|
|
4520
|
+
res.json({
|
|
4521
|
+
success: true,
|
|
4522
|
+
cancelled: false,
|
|
4523
|
+
run: null
|
|
4524
|
+
});
|
|
4525
|
+
return;
|
|
4526
|
+
}
|
|
4527
|
+
if (!isRunVisibleToUser(run, {
|
|
4528
|
+
tenantKey: chatUser.tenantKey,
|
|
4529
|
+
openId: chatUser.openId
|
|
4530
|
+
})) {
|
|
4531
|
+
res.status(403).json({ error: "Forbidden" });
|
|
4532
|
+
return;
|
|
4533
|
+
}
|
|
4534
|
+
try {
|
|
4535
|
+
const result = await cancelChatRun(run, messageStore, processManager);
|
|
4536
|
+
res.json({
|
|
4537
|
+
success: true,
|
|
4538
|
+
...result
|
|
4539
|
+
});
|
|
4540
|
+
} catch (err) {
|
|
4541
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
4542
|
+
log$30.error("[runs] 取消 run 失败", {
|
|
4543
|
+
runId,
|
|
4544
|
+
sessionId: run.sessionId,
|
|
4545
|
+
error: errorMessage
|
|
4546
|
+
});
|
|
4547
|
+
res.status(500).json({
|
|
4548
|
+
error: "Failed to cancel chat run",
|
|
4549
|
+
run: serializeChatRun(run)
|
|
4550
|
+
});
|
|
4551
|
+
}
|
|
4552
|
+
});
|
|
4553
|
+
router.post("/api/chat/sessions/:id/cancel-active-run", chatAuthMiddleware, async (req, res) => {
|
|
4554
|
+
const chatUser = res.locals.chatUser;
|
|
4555
|
+
const sessionId = String(req.params.id);
|
|
4556
|
+
const run = chatRunsBySession.get(sessionId);
|
|
4557
|
+
if (!run) {
|
|
4558
|
+
res.json({
|
|
4559
|
+
success: true,
|
|
4560
|
+
cancelled: false,
|
|
4561
|
+
sessionId,
|
|
4562
|
+
run: null
|
|
4563
|
+
});
|
|
4564
|
+
return;
|
|
4565
|
+
}
|
|
4566
|
+
if (!isRunVisibleToUser(run, {
|
|
4567
|
+
tenantKey: chatUser.tenantKey,
|
|
4568
|
+
openId: chatUser.openId
|
|
4569
|
+
})) {
|
|
4570
|
+
res.status(403).json({ error: "Forbidden" });
|
|
4571
|
+
return;
|
|
4572
|
+
}
|
|
4573
|
+
try {
|
|
4574
|
+
const result = await cancelChatRun(run, messageStore, processManager);
|
|
4575
|
+
res.json({
|
|
4576
|
+
success: true,
|
|
4577
|
+
sessionId,
|
|
4578
|
+
...result
|
|
4579
|
+
});
|
|
4580
|
+
} catch (err) {
|
|
4581
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
4582
|
+
log$30.error("[sessions] 取消 active run 失败", {
|
|
4583
|
+
sessionId,
|
|
4584
|
+
runId: run.runId,
|
|
4585
|
+
error: errorMessage
|
|
4586
|
+
});
|
|
4587
|
+
res.status(500).json({
|
|
4588
|
+
error: "Failed to cancel active chat run",
|
|
4589
|
+
run: serializeChatRun(run)
|
|
4590
|
+
});
|
|
4591
|
+
}
|
|
4592
|
+
});
|
|
4522
4593
|
router.get("/api/chat/history", chatAuthMiddleware, async (req, res) => {
|
|
4523
4594
|
const chatUser = res.locals.chatUser;
|
|
4524
4595
|
const sessionId = req.query.session_id;
|
|
@@ -8997,6 +9068,7 @@ function getUserFacingErrorMessage(error) {
|
|
|
8997
9068
|
const log$21 = larkLogger("card/cc-stream-bridge");
|
|
8998
9069
|
const CC_INTERNAL_PLACEHOLDER = "No response requested.";
|
|
8999
9070
|
const CLAUDE_INVALID_PARAMETER_PATTERN = /API Error:\s*400\b.*parameter specified in the request is not valid/i;
|
|
9071
|
+
const TOOL_PROGRESS_CARD_REFRESH_INTERVAL_MS = 15e3;
|
|
9000
9072
|
function buildClaudeCodeUserFacingError(errorMessage, hasImages) {
|
|
9001
9073
|
if (hasImages && CLAUDE_INVALID_PARAMETER_PATTERN.test(errorMessage)) return createUserFacingError([
|
|
9002
9074
|
"当前运行时无法处理这条图片消息。",
|
|
@@ -9020,6 +9092,8 @@ var CCStreamBridge = class {
|
|
|
9020
9092
|
activeTools = /* @__PURE__ */ new Map();
|
|
9021
9093
|
/** 最近一次 toolUseStart 的工具名(用于 toolResult 时查找) */
|
|
9022
9094
|
lastToolName = null;
|
|
9095
|
+
/** 最近一次由 tool_progress 推动卡片刷新的时间 */
|
|
9096
|
+
lastToolProgressCardRefreshAt = 0;
|
|
9023
9097
|
controller;
|
|
9024
9098
|
options;
|
|
9025
9099
|
constructor(controller, options) {
|
|
@@ -9108,13 +9182,18 @@ var CCStreamBridge = class {
|
|
|
9108
9182
|
});
|
|
9109
9183
|
this.controller.onToolPayload({ text: `✅ ${displayName} 完成` });
|
|
9110
9184
|
}
|
|
9111
|
-
/** 工具执行进度 →
|
|
9185
|
+
/** 工具执行进度 → 节流刷新卡片,避免长工具执行期间卡片长时间无可见更新 */
|
|
9112
9186
|
onToolProgress(toolName, elapsedSeconds) {
|
|
9187
|
+
const displayName = getToolDisplayName(toolName);
|
|
9113
9188
|
log$21.debug("toolProgress 事件", {
|
|
9114
9189
|
toolName,
|
|
9115
|
-
displayName
|
|
9190
|
+
displayName,
|
|
9116
9191
|
elapsedSeconds
|
|
9117
9192
|
});
|
|
9193
|
+
const now = Date.now();
|
|
9194
|
+
if (now - this.lastToolProgressCardRefreshAt < TOOL_PROGRESS_CARD_REFRESH_INTERVAL_MS) return;
|
|
9195
|
+
this.lastToolProgressCardRefreshAt = now;
|
|
9196
|
+
this.controller.onToolPayload({ text: `${displayName} running for ${Math.max(0, Math.floor(elapsedSeconds))}s` });
|
|
9118
9197
|
}
|
|
9119
9198
|
/** 轮次结束 → 仅在 end_turn 时标记完成 + 触发 onIdle */
|
|
9120
9199
|
onTurnEnd(stopReason) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-lark/larkpal",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.70",
|
|
4
4
|
"description": "LarkPal - Lark/Feishu bot service",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/main.mjs",
|
|
@@ -21,22 +21,9 @@
|
|
|
21
21
|
"registry": "https://registry.npmjs.org",
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
|
-
"packageManager": "pnpm@10.32.1",
|
|
25
24
|
"engines": {
|
|
26
25
|
"node": ">=22"
|
|
27
26
|
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"start": "node --env-file=.env bin/larkpal.js",
|
|
30
|
-
"build": "tsdown",
|
|
31
|
-
"test": "vitest run",
|
|
32
|
-
"test:watch": "vitest",
|
|
33
|
-
"lint": "eslint src/",
|
|
34
|
-
"lint:fix": "eslint src/ --fix",
|
|
35
|
-
"sit:larkpal-agent": "node scripts/sit/larkpal-agent-0.1.9-sit.mjs",
|
|
36
|
-
"typecheck": "tsc --noEmit",
|
|
37
|
-
"format": "prettier --write src/**/*.ts",
|
|
38
|
-
"format:check": "prettier --check src/**/*.ts"
|
|
39
|
-
},
|
|
40
27
|
"dependencies": {
|
|
41
28
|
"@larksuiteoapi/node-sdk": "^1.60.0",
|
|
42
29
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
@@ -69,5 +56,17 @@
|
|
|
69
56
|
"typescript": "^5.9.3",
|
|
70
57
|
"typescript-eslint": "^8.32.1",
|
|
71
58
|
"vitest": "^4.1.1"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"start": "node --env-file=.env bin/larkpal.js",
|
|
62
|
+
"build": "tsdown",
|
|
63
|
+
"test": "vitest run",
|
|
64
|
+
"test:watch": "vitest",
|
|
65
|
+
"lint": "eslint src/",
|
|
66
|
+
"lint:fix": "eslint src/ --fix",
|
|
67
|
+
"sit:larkpal-agent": "node scripts/sit/larkpal-agent-0.1.9-sit.mjs",
|
|
68
|
+
"typecheck": "tsc --noEmit",
|
|
69
|
+
"format": "prettier --write src/**/*.ts",
|
|
70
|
+
"format:check": "prettier --check src/**/*.ts"
|
|
72
71
|
}
|
|
73
|
-
}
|
|
72
|
+
}
|