larkway 0.3.29 → 0.3.30
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 +1 -1
- package/README.zh.md +1 -1
- package/dist/cli/index.js +26 -6
- package/dist/main.js +135 -22
- package/package.json +1 -1
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.
|
|
11
|
+
**Current release: v0.3.30**
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
package/README.zh.md
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -124829,6 +124829,9 @@ import path from "node:path";
|
|
|
124829
124829
|
|
|
124830
124830
|
// src/responseSurface.ts
|
|
124831
124831
|
var NonEmptyString = external_exports.string().trim().min(1);
|
|
124832
|
+
var CardKitMentionUserIdSchema = NonEmptyString.max(128).regex(/^[A-Za-z0-9_:-]+$/, {
|
|
124833
|
+
message: "mention user_id must contain only letters, numbers, underscore, colon, or hyphen"
|
|
124834
|
+
});
|
|
124832
124835
|
function defaultResponseSurfacePrototypeConfig() {
|
|
124833
124836
|
return {
|
|
124834
124837
|
enabled: true,
|
|
@@ -124838,6 +124841,7 @@ function defaultResponseSurfacePrototypeConfig() {
|
|
|
124838
124841
|
post_outbound_enabled: true,
|
|
124839
124842
|
cardkit_streaming_enabled: true,
|
|
124840
124843
|
allow_agent_mentions: true,
|
|
124844
|
+
denied_mention_open_ids: [],
|
|
124841
124845
|
allowed_mention_open_ids: []
|
|
124842
124846
|
};
|
|
124843
124847
|
}
|
|
@@ -124850,6 +124854,7 @@ var responseSurfacePrototypeConfigDefaults = () => ({
|
|
|
124850
124854
|
post_outbound_enabled: true,
|
|
124851
124855
|
cardkit_streaming_enabled: true,
|
|
124852
124856
|
allow_agent_mentions: true,
|
|
124857
|
+
denied_mention_open_ids: [],
|
|
124853
124858
|
allowed_mention_open_ids: []
|
|
124854
124859
|
});
|
|
124855
124860
|
var ResponseSurfaceModeSchema = external_exports.enum(["card", "post", "hybrid"]);
|
|
@@ -124862,7 +124867,7 @@ var ResponseSurfaceCapabilitySchema = external_exports.enum([
|
|
|
124862
124867
|
"audit"
|
|
124863
124868
|
]);
|
|
124864
124869
|
var MentionTargetSchema = external_exports.object({
|
|
124865
|
-
user_id:
|
|
124870
|
+
user_id: CardKitMentionUserIdSchema,
|
|
124866
124871
|
label: external_exports.string().trim().min(1).max(80).optional()
|
|
124867
124872
|
});
|
|
124868
124873
|
var ResponseSurfacePostSchema = external_exports.object({
|
|
@@ -124873,7 +124878,7 @@ var ResponseSurfaceCardSchema = external_exports.object({
|
|
|
124873
124878
|
capabilities: external_exports.array(ResponseSurfaceCapabilitySchema).max(8).default([])
|
|
124874
124879
|
});
|
|
124875
124880
|
var StrictResponseSurfaceStateSchema = external_exports.object({
|
|
124876
|
-
mode: ResponseSurfaceModeSchema,
|
|
124881
|
+
mode: ResponseSurfaceModeSchema.optional().default("card"),
|
|
124877
124882
|
primary: ResponseSurfacePrimarySchema.optional(),
|
|
124878
124883
|
post: ResponseSurfacePostSchema.optional(),
|
|
124879
124884
|
card: ResponseSurfaceCardSchema.optional()
|
|
@@ -124888,9 +124893,18 @@ var StrictResponseSurfaceStateSchema = external_exports.object({
|
|
|
124888
124893
|
});
|
|
124889
124894
|
var ResponseSurfaceStateSchema = external_exports.preprocess((value) => {
|
|
124890
124895
|
if (value === void 0) return void 0;
|
|
124891
|
-
|
|
124892
|
-
return result.success ? result.data : void 0;
|
|
124896
|
+
return parseResponseSurfaceState(value).state;
|
|
124893
124897
|
}, StrictResponseSurfaceStateSchema.optional());
|
|
124898
|
+
function parseResponseSurfaceState(value) {
|
|
124899
|
+
const result = StrictResponseSurfaceStateSchema.safeParse(value);
|
|
124900
|
+
if (result.success) return { state: result.data, diagnostics: [] };
|
|
124901
|
+
return {
|
|
124902
|
+
diagnostics: result.error.issues.map((issue) => {
|
|
124903
|
+
const path25 = issue.path.length > 0 ? issue.path.join(".") : "<root>";
|
|
124904
|
+
return `${path25}: ${issue.message}`;
|
|
124905
|
+
})
|
|
124906
|
+
};
|
|
124907
|
+
}
|
|
124894
124908
|
var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
124895
124909
|
/**
|
|
124896
124910
|
* Master gate. Default true makes response surfaces available unless the
|
|
@@ -124931,10 +124945,16 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
124931
124945
|
*/
|
|
124932
124946
|
allow_agent_mentions: external_exports.boolean().default(true),
|
|
124933
124947
|
/**
|
|
124934
|
-
* Optional
|
|
124935
|
-
* may choose mention targets
|
|
124948
|
+
* Optional deny-list for Agent-authored @ mentions. Empty means the Agent
|
|
124949
|
+
* may choose mention targets, except broadcast aliases such as @all.
|
|
124936
124950
|
* Keep real IDs in private bot config, never in public docs/tests.
|
|
124937
124951
|
*/
|
|
124952
|
+
denied_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([]),
|
|
124953
|
+
/**
|
|
124954
|
+
* Deprecated compatibility field. It is still parsed so older private
|
|
124955
|
+
* configs do not fail, but mention policy is deny-list/default-allow.
|
|
124956
|
+
* Use denied_mention_open_ids for new restrictions.
|
|
124957
|
+
*/
|
|
124938
124958
|
allowed_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([])
|
|
124939
124959
|
}).default(responseSurfacePrototypeConfigDefaults);
|
|
124940
124960
|
|
package/dist/main.js
CHANGED
|
@@ -118687,7 +118687,7 @@ function renderStateContract(stateFilePath) {
|
|
|
118687
118687
|
"- card_title/card_color: \u517C\u5BB9\u5B57\u6BB5; \u9ED8\u8BA4 CardKit \u4E0D\u6E32\u67D3\u9876\u90E8\u6807\u9898\u8272\u6761,legacy/fallback \u5361\u7247\u8DEF\u5F84\u53EF\u80FD\u4F7F\u7528",
|
|
118688
118688
|
"- image_blocks: \u53EF\u9009\u56FE\u7247\u9884\u89C8\u5757\u6570\u7EC4,\u6700\u591A 4 \u4E2A\u3002\u6BCF\u9879 `{img_key, alt?, title?, mode?, preview?}`; `img_key` \u5FC5\u987B\u662F\u5DF2\u4E0A\u4F20/\u53EF\u7528\u4E8E\u5361\u7247\u7684 Feishu \u56FE\u7247 key,`alt` \u7701\u7565\u65F6 bridge \u9ED8\u8BA4\u201C\u56FE\u7247\u9884\u89C8\u201D,`mode` \u53EA\u5141\u8BB8 `crop_center`/`fit_horizontal` \u5E76\u6620\u5C04\u5230 Card JSON 2.0 `scale_type`,`preview` \u9ED8\u8BA4 true\u3002bridge \u4E0D\u8D1F\u8D23\u4E0B\u8F7D/\u4E0A\u4F20/\u9009\u62E9\u56FE\u7247;\u8FD9\u4E9B\u7531\u4F60\u7528 lark-cli \u7B49\u5DE5\u5177\u5148\u5B8C\u6210\u3002",
|
|
118689
118689
|
'- content_blocks: \u53EF\u9009\u6709\u5E8F\u6B63\u6587\u5757\u6570\u7EC4,\u6700\u591A 12 \u4E2A block\u3001\u6700\u591A 4 \u4E2A image block\u3002\u53EA\u652F\u6301\u7A84 union:`{type:"markdown", content}` \u548C `{type:"image", img_key, alt?, title?, mode?, preview?}`;\u4E0D\u652F\u6301 raw card JSON\u3002\u7528\u4E8E\u6B63\u6587\u4E0E\u56FE\u7247\u4EA4\u9519\u6392\u7248,\u4F8B\u5982 markdown -> image -> markdown -> image\u3002\u82E5 `content_blocks` \u975E\u7A7A,bridge \u4EE5\u5B83\u4F5C\u4E3A\u4E3B\u6B63\u6587\u5E76\u5FFD\u7565 `last_message` + `image_blocks` \u7684\u6B63\u6587\u6E32\u67D3,\u907F\u514D\u91CD\u590D;\u82E5\u7701\u7565\u5219\u4FDD\u6301\u65E7 `last_message` + `image_blocks` \u884C\u4E3A\u3002',
|
|
118690
|
-
"- response_surface: \u53EF\u9009\u8986\u76D6\u5B57\u6BB5,\u4E3B\u8981\u7528\u4E8E `{post:{mentions:[{user_id,label?}]}}` late peer @\u3002\u9ED8\u8BA4\u53EF\u4E0D\u5199;bridge \u6309 CardKit \u6D41\u5F0F\u5361\u7247\u5904\u7406,\u6700\u7EC8\u6536\u6210\u5E72\u51C0\u603B\u7ED3\u5361\u3002\u65E7 `mode`/`primary` \u4EC5\u517C\u5BB9\u89E3\u6790,\u4E0D\u518D\u9009\u62E9 post-only/hybrid \u4E3B\u54CD\u5E94\u9762\u3002\u9700\u8981\
|
|
118690
|
+
"- response_surface: \u53EF\u9009\u8986\u76D6\u5B57\u6BB5,\u4E3B\u8981\u7528\u4E8E `{post:{mentions:[{user_id,label?}]}}` late peer @\u3002\u9ED8\u8BA4\u53EF\u4E0D\u5199;bridge \u6309 CardKit \u6D41\u5F0F\u5361\u7247\u5904\u7406,\u6700\u7EC8\u6536\u6210\u5E72\u51C0\u603B\u7ED3\u5361\u3002\u65E7 `mode`/`primary` \u4EC5\u517C\u5BB9\u89E3\u6790,\u4E0D\u518D\u9009\u62E9 post-only/hybrid \u4E3B\u54CD\u5E94\u9762\u3002\u8FD9\u91CC\u7684 late @ \u53EA\u662F\u6700\u7EC8\u5361\u7247\u91CC\u7684\u89C6\u89C9\u63D0\u793A;\u9700\u8981 peer bot \u6D88\u8D39\u6B63\u6587\u7684 handoff \u5FC5\u987B\u7531 Agent/\u56E2\u961F\u5DE5\u4F5C\u6D41\u53D1\u9001\u771F\u5B9E Feishu post + at \u6807\u7B7E\u3002\u4E0D\u8981\u5199 raw Feishu post/card JSON\u3002",
|
|
118691
118691
|
"- scheduled reply / daily social ops review card \u7B49\u9700\u8981\u201C\u5E73\u53F0\u6B63\u6587 + \u5339\u914D\u56FE\u7247\u201D\u540C\u6BB5\u76F8\u90BB\u5C55\u793A\u7684\u573A\u666F,\u5E94\u5148\u53D6\u5F97\u5404\u56FE\u7247 `img_key`,\u518D\u5199 `content_blocks` \u4E3A `\u5E73\u53F0 markdown -> \u5BF9\u5E94 image -> \u4E0B\u4E2A\u5E73\u53F0 markdown -> \u5BF9\u5E94 image`;\u4E0D\u8981\u7528\u5355\u72EC\u8BDD\u9898\u56FE\u7247\u6D88\u606F\u6216\u5C3E\u90E8 `image_blocks` \u4EE3\u66FF\u9A8C\u6536\u9762\u3002",
|
|
118692
118692
|
"- dev_url / mr_url / \u5176\u4F59\u4E1A\u52A1\u5B57\u6BB5:\u81EA\u7531\u5199\u5165,bridge \u4E0D\u611F\u77E5\u5176\u4E1A\u52A1\u542B\u4E49;\u8981\u8BA9\u8FD0\u8425\u770B\u5230,\u8BF7\u5199\u8FDB last_message",
|
|
118693
118693
|
"- updated_at: ISO 8601 timestamp",
|
|
@@ -118738,6 +118738,9 @@ function renderPeersBlock(peers) {
|
|
|
118738
118738
|
"- \u4E0D\u8981\u628A\u540C\u4E00\u4EFB\u52A1\u540C\u65F6\u8F6C\u53D1\u7ED9\u591A\u4E2A peer",
|
|
118739
118739
|
'- @ peer \u5FC5\u987B\u7528 **post \u6D88\u606F** + at \u6807\u7B7E `{"tag":"at","user_id":"ou_xxx"}`(\u7528\u4E0A\u9762\u7684 open_id),',
|
|
118740
118740
|
" **\u4E25\u7981\u7528\u7EAF text \u7684 @xxx**(\u7EAF\u6587\u672C @ \u4E0D\u4F1A\u771F\u6B63\u89E6\u8FBE\u5BF9\u65B9 bot)",
|
|
118741
|
+
"- \u53D1\u8D77 peer handoff \u540E,\u5728\u4F60\u7684\u534F\u8C03\u5C42/\u5DE5\u4F5C\u533A\u53F0\u8D26\u8BB0\u5F55 task_id\u3001assignee\u3001\u6765\u6E90\u3001\u671F\u671B\u4EA7\u51FA\u3001deadline \u548C\u5347\u7EA7\u4EBA;\u6CA1\u6709\u4E13\u7528 skill \u65F6\u81F3\u5C11\u5199\u5165\u672C session summary\u3002",
|
|
118742
|
+
"- \u6536\u5230 peer handoff \u540E,\u5148\u7528\u771F\u5B9E post \u8F7B\u91CF ack(\u6536\u5230/\u5F00\u59CB)\u518D\u505A\u957F\u4EFB\u52A1;\u5B8C\u6210\u3001\u5931\u8D25\u6216\u963B\u585E\u65F6\u5FC5\u987B\u7528\u771F\u5B9E post \u56DE\u62A5\u7EC8\u6001,\u4E0D\u8981\u8BA9\u94FE\u8DEF\u9759\u9ED8\u505C\u5728\u4F60\u8FD9\u91CC\u3002",
|
|
118743
|
+
"- \u9ED8\u8BA4 deadline \u53EF\u6309\u56E2\u961F\u5DE5\u4F5C\u6D41\u8BBE\u7F6E(\u5E38\u89C1\u9ED8\u8BA4 15 \u5206\u949F);\u8D85\u65F6\u68C0\u6D4B\u3001\u91CD\u8BD5/\u91CD\u6D3E/\u5347\u7EA7\u5C5E\u4E8E\u534F\u8C03\u5C42 skill/workspace \u903B\u8F91,\u4E0D\u8981\u671F\u5F85 bridge \u66FF\u4F60\u7F16\u6392\u3002",
|
|
118741
118744
|
"</peer-bots>"
|
|
118742
118745
|
];
|
|
118743
118746
|
}
|
|
@@ -119494,6 +119497,9 @@ import path6 from "node:path";
|
|
|
119494
119497
|
|
|
119495
119498
|
// src/responseSurface.ts
|
|
119496
119499
|
var NonEmptyString = external_exports.string().trim().min(1);
|
|
119500
|
+
var CardKitMentionUserIdSchema = NonEmptyString.max(128).regex(/^[A-Za-z0-9_:-]+$/, {
|
|
119501
|
+
message: "mention user_id must contain only letters, numbers, underscore, colon, or hyphen"
|
|
119502
|
+
});
|
|
119497
119503
|
function defaultResponseSurfacePrototypeConfig() {
|
|
119498
119504
|
return {
|
|
119499
119505
|
enabled: true,
|
|
@@ -119503,6 +119509,7 @@ function defaultResponseSurfacePrototypeConfig() {
|
|
|
119503
119509
|
post_outbound_enabled: true,
|
|
119504
119510
|
cardkit_streaming_enabled: true,
|
|
119505
119511
|
allow_agent_mentions: true,
|
|
119512
|
+
denied_mention_open_ids: [],
|
|
119506
119513
|
allowed_mention_open_ids: []
|
|
119507
119514
|
};
|
|
119508
119515
|
}
|
|
@@ -119515,6 +119522,7 @@ var responseSurfacePrototypeConfigDefaults = () => ({
|
|
|
119515
119522
|
post_outbound_enabled: true,
|
|
119516
119523
|
cardkit_streaming_enabled: true,
|
|
119517
119524
|
allow_agent_mentions: true,
|
|
119525
|
+
denied_mention_open_ids: [],
|
|
119518
119526
|
allowed_mention_open_ids: []
|
|
119519
119527
|
});
|
|
119520
119528
|
var ResponseSurfaceModeSchema = external_exports.enum(["card", "post", "hybrid"]);
|
|
@@ -119527,7 +119535,7 @@ var ResponseSurfaceCapabilitySchema = external_exports.enum([
|
|
|
119527
119535
|
"audit"
|
|
119528
119536
|
]);
|
|
119529
119537
|
var MentionTargetSchema = external_exports.object({
|
|
119530
|
-
user_id:
|
|
119538
|
+
user_id: CardKitMentionUserIdSchema,
|
|
119531
119539
|
label: external_exports.string().trim().min(1).max(80).optional()
|
|
119532
119540
|
});
|
|
119533
119541
|
var ResponseSurfacePostSchema = external_exports.object({
|
|
@@ -119538,7 +119546,7 @@ var ResponseSurfaceCardSchema = external_exports.object({
|
|
|
119538
119546
|
capabilities: external_exports.array(ResponseSurfaceCapabilitySchema).max(8).default([])
|
|
119539
119547
|
});
|
|
119540
119548
|
var StrictResponseSurfaceStateSchema = external_exports.object({
|
|
119541
|
-
mode: ResponseSurfaceModeSchema,
|
|
119549
|
+
mode: ResponseSurfaceModeSchema.optional().default("card"),
|
|
119542
119550
|
primary: ResponseSurfacePrimarySchema.optional(),
|
|
119543
119551
|
post: ResponseSurfacePostSchema.optional(),
|
|
119544
119552
|
card: ResponseSurfaceCardSchema.optional()
|
|
@@ -119553,9 +119561,18 @@ var StrictResponseSurfaceStateSchema = external_exports.object({
|
|
|
119553
119561
|
});
|
|
119554
119562
|
var ResponseSurfaceStateSchema = external_exports.preprocess((value) => {
|
|
119555
119563
|
if (value === void 0) return void 0;
|
|
119556
|
-
|
|
119557
|
-
return result.success ? result.data : void 0;
|
|
119564
|
+
return parseResponseSurfaceState(value).state;
|
|
119558
119565
|
}, StrictResponseSurfaceStateSchema.optional());
|
|
119566
|
+
function parseResponseSurfaceState(value) {
|
|
119567
|
+
const result = StrictResponseSurfaceStateSchema.safeParse(value);
|
|
119568
|
+
if (result.success) return { state: result.data, diagnostics: [] };
|
|
119569
|
+
return {
|
|
119570
|
+
diagnostics: result.error.issues.map((issue) => {
|
|
119571
|
+
const path16 = issue.path.length > 0 ? issue.path.join(".") : "<root>";
|
|
119572
|
+
return `${path16}: ${issue.message}`;
|
|
119573
|
+
})
|
|
119574
|
+
};
|
|
119575
|
+
}
|
|
119559
119576
|
var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
119560
119577
|
/**
|
|
119561
119578
|
* Master gate. Default true makes response surfaces available unless the
|
|
@@ -119596,10 +119613,16 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
119596
119613
|
*/
|
|
119597
119614
|
allow_agent_mentions: external_exports.boolean().default(true),
|
|
119598
119615
|
/**
|
|
119599
|
-
* Optional
|
|
119600
|
-
* may choose mention targets
|
|
119616
|
+
* Optional deny-list for Agent-authored @ mentions. Empty means the Agent
|
|
119617
|
+
* may choose mention targets, except broadcast aliases such as @all.
|
|
119601
119618
|
* Keep real IDs in private bot config, never in public docs/tests.
|
|
119602
119619
|
*/
|
|
119620
|
+
denied_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([]),
|
|
119621
|
+
/**
|
|
119622
|
+
* Deprecated compatibility field. It is still parsed so older private
|
|
119623
|
+
* configs do not fail, but mention policy is deny-list/default-allow.
|
|
119624
|
+
* Use denied_mention_open_ids for new restrictions.
|
|
119625
|
+
*/
|
|
119603
119626
|
allowed_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([])
|
|
119604
119627
|
}).default(responseSurfacePrototypeConfigDefaults);
|
|
119605
119628
|
function isResponseSurfacePrototypeAllowlisted(config, facts) {
|
|
@@ -119611,12 +119634,30 @@ function isResponseSurfacePrototypeAllowlisted(config, facts) {
|
|
|
119611
119634
|
const threadAllowed = config.allowed_threads.length > 0 && config.allowed_threads.includes(facts.threadId);
|
|
119612
119635
|
return chatAllowed || threadAllowed;
|
|
119613
119636
|
}
|
|
119614
|
-
function
|
|
119615
|
-
if (!config?.allow_agent_mentions)
|
|
119637
|
+
function evaluateResponseSurfaceMentionPolicy(config, userId) {
|
|
119638
|
+
if (!config?.allow_agent_mentions) {
|
|
119639
|
+
return {
|
|
119640
|
+
allowed: false,
|
|
119641
|
+
rule: "agent_mentions_disabled",
|
|
119642
|
+
reason: "Agent-authored mentions are disabled by allow_agent_mentions=false."
|
|
119643
|
+
};
|
|
119644
|
+
}
|
|
119616
119645
|
const normalized = userId.trim().toLowerCase();
|
|
119617
|
-
if (normalized === "all" || normalized === "@all")
|
|
119618
|
-
|
|
119619
|
-
|
|
119646
|
+
if (normalized === "all" || normalized === "@all") {
|
|
119647
|
+
return {
|
|
119648
|
+
allowed: false,
|
|
119649
|
+
rule: "broadcast_blocked",
|
|
119650
|
+
reason: "Broadcast mentions such as @all are blocked."
|
|
119651
|
+
};
|
|
119652
|
+
}
|
|
119653
|
+
if (config.denied_mention_open_ids.includes(userId)) {
|
|
119654
|
+
return {
|
|
119655
|
+
allowed: false,
|
|
119656
|
+
rule: "denied_target",
|
|
119657
|
+
reason: "Mention target is denied by denied_mention_open_ids."
|
|
119658
|
+
};
|
|
119659
|
+
}
|
|
119660
|
+
return { allowed: true, rule: "allowed" };
|
|
119620
119661
|
}
|
|
119621
119662
|
function shouldProvideResponseSurfacePostClient(config) {
|
|
119622
119663
|
return !!(config?.enabled && !config.kill_switch && config.post_outbound_enabled);
|
|
@@ -119801,14 +119842,19 @@ async function ensureStateFile(worktreePath) {
|
|
|
119801
119842
|
await fs3.writeFile(file, JSON.stringify(initial, null, 2), "utf8");
|
|
119802
119843
|
}
|
|
119803
119844
|
async function readStateFile(worktreePath) {
|
|
119845
|
+
return (await readStateFileDetailed(worktreePath)).state;
|
|
119846
|
+
}
|
|
119847
|
+
async function readStateFileDetailed(worktreePath) {
|
|
119804
119848
|
const file = stateFilePathOf(worktreePath);
|
|
119805
119849
|
let raw;
|
|
119806
119850
|
try {
|
|
119807
119851
|
raw = await fs3.readFile(file, "utf8");
|
|
119808
119852
|
} catch (err) {
|
|
119809
|
-
if (err.code === "ENOENT")
|
|
119853
|
+
if (err.code === "ENOENT") {
|
|
119854
|
+
return { state: null, diagnostics: [] };
|
|
119855
|
+
}
|
|
119810
119856
|
console.warn(`[stateFile] read ${file} failed:`, err);
|
|
119811
|
-
return null;
|
|
119857
|
+
return { state: null, diagnostics: [] };
|
|
119812
119858
|
}
|
|
119813
119859
|
let parsed;
|
|
119814
119860
|
try {
|
|
@@ -119826,11 +119872,11 @@ async function readStateFile(worktreePath) {
|
|
|
119826
119872
|
`[stateFile] ${file} not valid JSON (repair also failed):`,
|
|
119827
119873
|
err2
|
|
119828
119874
|
);
|
|
119829
|
-
return null;
|
|
119875
|
+
return { state: null, diagnostics: [] };
|
|
119830
119876
|
}
|
|
119831
119877
|
} else {
|
|
119832
119878
|
console.warn(`[stateFile] ${file} not valid JSON:`, err);
|
|
119833
|
-
return null;
|
|
119879
|
+
return { state: null, diagnostics: [] };
|
|
119834
119880
|
}
|
|
119835
119881
|
}
|
|
119836
119882
|
const result = StateFileSchema.safeParse(parsed);
|
|
@@ -119839,9 +119885,22 @@ async function readStateFile(worktreePath) {
|
|
|
119839
119885
|
`[stateFile] ${file} failed schema validation:`,
|
|
119840
119886
|
result.error.issues
|
|
119841
119887
|
);
|
|
119842
|
-
return null;
|
|
119888
|
+
return { state: null, diagnostics: [] };
|
|
119843
119889
|
}
|
|
119844
|
-
|
|
119890
|
+
const diagnostics = diagnoseStateFile(parsed, result.data);
|
|
119891
|
+
for (const diagnostic of diagnostics) {
|
|
119892
|
+
console.warn(`[stateFile] ${file}: ${diagnostic}`);
|
|
119893
|
+
}
|
|
119894
|
+
return { state: result.data, diagnostics };
|
|
119895
|
+
}
|
|
119896
|
+
function diagnoseStateFile(parsed, state) {
|
|
119897
|
+
if (parsed === null || typeof parsed !== "object") return [];
|
|
119898
|
+
if (!Object.prototype.hasOwnProperty.call(parsed, "response_surface")) return [];
|
|
119899
|
+
const rawSurface = parsed.response_surface;
|
|
119900
|
+
if (rawSurface === void 0 || state.response_surface !== void 0) return [];
|
|
119901
|
+
const parsedSurface = parseResponseSurfaceState(rawSurface);
|
|
119902
|
+
const details = parsedSurface.diagnostics.length > 0 ? parsedSurface.diagnostics.join("; ") : "unknown parse failure";
|
|
119903
|
+
return [`response_surface ignored: ${details}`];
|
|
119845
119904
|
}
|
|
119846
119905
|
function tryRepairBareQuotesInLastMessage(raw) {
|
|
119847
119906
|
const startRe = /"last_message"\s*:\s*"/;
|
|
@@ -120664,6 +120723,13 @@ function derivePostIdempotencyKey(input) {
|
|
|
120664
120723
|
|
|
120665
120724
|
// src/bridge/handler.ts
|
|
120666
120725
|
var DEFAULT_CARDKIT_RESPONSE_SURFACE_TIMEOUT_MS = 20 * 60 * 1e3;
|
|
120726
|
+
function summarizeMentionPolicyRules(rules) {
|
|
120727
|
+
const counts = /* @__PURE__ */ new Map();
|
|
120728
|
+
for (const rule of rules) {
|
|
120729
|
+
counts.set(rule, (counts.get(rule) ?? 0) + 1);
|
|
120730
|
+
}
|
|
120731
|
+
return Array.from(counts.entries()).map(([rule, count]) => `${rule}=${count}`).join(", ");
|
|
120732
|
+
}
|
|
120667
120733
|
function execGit(cwd, args) {
|
|
120668
120734
|
return new Promise((resolve2, reject) => {
|
|
120669
120735
|
const child = child_process.spawn("git", args, {
|
|
@@ -121426,8 +121492,23 @@ var BridgeHandler = class {
|
|
|
121426
121492
|
}
|
|
121427
121493
|
const result = await handle.done;
|
|
121428
121494
|
const cardKitTurnTimedOut = cardKitProgress != null && result.exitCode !== 0 && Date.now() - runnerStartedAt >= timeoutMs;
|
|
121429
|
-
const
|
|
121495
|
+
const reportedStateRead = await readStateFileDetailed(worktreePath);
|
|
121496
|
+
const rawReportedState = reportedStateRead.state;
|
|
121430
121497
|
const reportedState = rawReportedState?.updated_at != null && rawReportedState.updated_at !== preRunUpdatedAt ? rawReportedState : null;
|
|
121498
|
+
if (reportedStateRead.diagnostics.length > 0 && reportedState !== null) {
|
|
121499
|
+
await recordEvent({
|
|
121500
|
+
status: "running",
|
|
121501
|
+
appendPath: "state \u8BCA\u65AD",
|
|
121502
|
+
reason: reportedStateRead.diagnostics.join("; ")
|
|
121503
|
+
});
|
|
121504
|
+
}
|
|
121505
|
+
if (reportedState === null) {
|
|
121506
|
+
await recordEvent({
|
|
121507
|
+
status: "running",
|
|
121508
|
+
appendPath: "\u672A\u66F4\u65B0 state.json",
|
|
121509
|
+
reason: rawReportedState === null ? "\u672C\u8F6E\u7ED3\u675F\u65F6\u672A\u8BFB\u53D6\u5230 state.json\u3002" : "\u672C\u8F6E state.json \u6CA1\u6709 fresh updated_at\uFF0C\u5DF2\u5FFD\u7565\u65E7\u72B6\u6001\u3002"
|
|
121510
|
+
});
|
|
121511
|
+
}
|
|
121431
121512
|
const now = Date.now();
|
|
121432
121513
|
if (sessionId !== void 0 && currentExisting === void 0) {
|
|
121433
121514
|
await this.deps.sessionStore.put({
|
|
@@ -121466,11 +121547,21 @@ var BridgeHandler = class {
|
|
|
121466
121547
|
} else if (cardKitTimeoutFailure) {
|
|
121467
121548
|
success = false;
|
|
121468
121549
|
failureReason = `agent turn timed out after ${timeoutMs}ms; CardKit running card was finalized as interrupted`;
|
|
121550
|
+
await recordEvent({
|
|
121551
|
+
status: "running",
|
|
121552
|
+
appendPath: "Agent \u8D85\u65F6",
|
|
121553
|
+
reason: failureReason
|
|
121554
|
+
});
|
|
121469
121555
|
} else if (result.exitCode === 0) {
|
|
121470
121556
|
success = true;
|
|
121471
121557
|
} else {
|
|
121472
121558
|
success = false;
|
|
121473
121559
|
failureReason = `claude exited ${result.exitCode} \u4E14 bot \u672A\u66F4\u65B0 state.json status \u2014 \u53EF\u80FD\u5D29\u6E83`;
|
|
121560
|
+
await recordEvent({
|
|
121561
|
+
status: "running",
|
|
121562
|
+
appendPath: "Agent \u5F02\u5E38\u9000\u51FA",
|
|
121563
|
+
reason: failureReason
|
|
121564
|
+
});
|
|
121474
121565
|
}
|
|
121475
121566
|
const fallbackAnswer = trustedAnswerText.trim() || cardKitProgress?.answerText.trim() || "";
|
|
121476
121567
|
const cardBody = cardKitTimeoutFailure ? "\u26A0\uFE0F \u672C\u8F6E\u5904\u7406\u8D85\u65F6\uFF0C\u5DF2\u4E2D\u65AD\u3002\u8BF7\u518D @ \u6211\u4E00\u6B21\u91CD\u8BD5\u3002" : reportedState?.last_message ?? (fallbackAnswer ? fallbackAnswer : "\u26A0\uFE0F \u672C\u8F6E\u6CA1\u6709\u62FF\u5230 agent \u7684\u65B0\u56DE\u590D(\u53EF\u80FD\u88AB\u4E2D\u65AD\u6216\u672A\u66F4\u65B0\u72B6\u6001),\u518D @ \u6211\u4E00\u6B21\u91CD\u8BD5\u3002");
|
|
@@ -121491,9 +121582,31 @@ var BridgeHandler = class {
|
|
|
121491
121582
|
contentBlocks: reportedState?.content_blocks
|
|
121492
121583
|
};
|
|
121493
121584
|
if (cardKitProgress) {
|
|
121494
|
-
const
|
|
121495
|
-
|
|
121496
|
-
)
|
|
121585
|
+
const declaredMentions = reportedState?.response_surface?.post?.mentions ?? [];
|
|
121586
|
+
const responseSurfacePostDeclared = reportedState?.response_surface?.post !== void 0;
|
|
121587
|
+
const mentionPolicyResults = declaredMentions.map((mention) => ({
|
|
121588
|
+
mention,
|
|
121589
|
+
policy: evaluateResponseSurfaceMentionPolicy(prototypeConfig, mention.user_id)
|
|
121590
|
+
}));
|
|
121591
|
+
const mentions = mentionPolicyResults.filter(({ policy }) => policy.allowed).map(({ mention }) => mention);
|
|
121592
|
+
const blockedMentionRules = mentionPolicyResults.filter(({ policy }) => !policy.allowed).map(({ policy }) => policy.rule);
|
|
121593
|
+
if (responseSurfacePostDeclared && declaredMentions.length === 0) {
|
|
121594
|
+
const reason = "response_surface.post was declared with an empty mentions array.";
|
|
121595
|
+
console.warn("[bridge.handler] response_surface post has no mentions");
|
|
121596
|
+
await recordEvent({
|
|
121597
|
+
status: "running",
|
|
121598
|
+
appendPath: "mention \u8BCA\u65AD",
|
|
121599
|
+
reason
|
|
121600
|
+
});
|
|
121601
|
+
} else if (declaredMentions.length > mentions.length) {
|
|
121602
|
+
const reason = `response_surface mentions filtered by policy: ${mentions.length}/${declaredMentions.length} allowed; blocked rules: ${summarizeMentionPolicyRules(blockedMentionRules)}.`;
|
|
121603
|
+
console.warn("[bridge.handler] response_surface mention policy filtered targets");
|
|
121604
|
+
await recordEvent({
|
|
121605
|
+
status: "running",
|
|
121606
|
+
appendPath: "mention \u8BCA\u65AD",
|
|
121607
|
+
reason
|
|
121608
|
+
});
|
|
121609
|
+
}
|
|
121497
121610
|
try {
|
|
121498
121611
|
await cardKitProgress.finalize({
|
|
121499
121612
|
title: baseCardPayload.titleOverride,
|