larkway 0.3.28 → 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 +242 -35
- 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
|
@@ -115875,6 +115875,10 @@ function resolveAgentWorkspacePath(agentId) {
|
|
|
115875
115875
|
function resolveAgentWorkspaceSessionsDir(agentId) {
|
|
115876
115876
|
return join(resolveAgentWorkspacePath(agentId), "sessions");
|
|
115877
115877
|
}
|
|
115878
|
+
function resolveAgentSessionPath(agentId, threadId) {
|
|
115879
|
+
assertSafePathSegment("threadId", threadId);
|
|
115880
|
+
return join(resolveAgentWorkspaceSessionsDir(agentId), threadId);
|
|
115881
|
+
}
|
|
115878
115882
|
function resolveAgentWorkspaceReposDir(agentId) {
|
|
115879
115883
|
return join(resolveAgentWorkspacePath(agentId), "repos");
|
|
115880
115884
|
}
|
|
@@ -118683,7 +118687,7 @@ function renderStateContract(stateFilePath) {
|
|
|
118683
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",
|
|
118684
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",
|
|
118685
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',
|
|
118686
|
-
"- 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",
|
|
118687
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",
|
|
118688
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",
|
|
118689
118693
|
"- updated_at: ISO 8601 timestamp",
|
|
@@ -118734,6 +118738,9 @@ function renderPeersBlock(peers) {
|
|
|
118734
118738
|
"- \u4E0D\u8981\u628A\u540C\u4E00\u4EFB\u52A1\u540C\u65F6\u8F6C\u53D1\u7ED9\u591A\u4E2A peer",
|
|
118735
118739
|
'- @ peer \u5FC5\u987B\u7528 **post \u6D88\u606F** + at \u6807\u7B7E `{"tag":"at","user_id":"ou_xxx"}`(\u7528\u4E0A\u9762\u7684 open_id),',
|
|
118736
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",
|
|
118737
118744
|
"</peer-bots>"
|
|
118738
118745
|
];
|
|
118739
118746
|
}
|
|
@@ -119490,6 +119497,9 @@ import path6 from "node:path";
|
|
|
119490
119497
|
|
|
119491
119498
|
// src/responseSurface.ts
|
|
119492
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
|
+
});
|
|
119493
119503
|
function defaultResponseSurfacePrototypeConfig() {
|
|
119494
119504
|
return {
|
|
119495
119505
|
enabled: true,
|
|
@@ -119499,6 +119509,7 @@ function defaultResponseSurfacePrototypeConfig() {
|
|
|
119499
119509
|
post_outbound_enabled: true,
|
|
119500
119510
|
cardkit_streaming_enabled: true,
|
|
119501
119511
|
allow_agent_mentions: true,
|
|
119512
|
+
denied_mention_open_ids: [],
|
|
119502
119513
|
allowed_mention_open_ids: []
|
|
119503
119514
|
};
|
|
119504
119515
|
}
|
|
@@ -119511,6 +119522,7 @@ var responseSurfacePrototypeConfigDefaults = () => ({
|
|
|
119511
119522
|
post_outbound_enabled: true,
|
|
119512
119523
|
cardkit_streaming_enabled: true,
|
|
119513
119524
|
allow_agent_mentions: true,
|
|
119525
|
+
denied_mention_open_ids: [],
|
|
119514
119526
|
allowed_mention_open_ids: []
|
|
119515
119527
|
});
|
|
119516
119528
|
var ResponseSurfaceModeSchema = external_exports.enum(["card", "post", "hybrid"]);
|
|
@@ -119523,7 +119535,7 @@ var ResponseSurfaceCapabilitySchema = external_exports.enum([
|
|
|
119523
119535
|
"audit"
|
|
119524
119536
|
]);
|
|
119525
119537
|
var MentionTargetSchema = external_exports.object({
|
|
119526
|
-
user_id:
|
|
119538
|
+
user_id: CardKitMentionUserIdSchema,
|
|
119527
119539
|
label: external_exports.string().trim().min(1).max(80).optional()
|
|
119528
119540
|
});
|
|
119529
119541
|
var ResponseSurfacePostSchema = external_exports.object({
|
|
@@ -119534,7 +119546,7 @@ var ResponseSurfaceCardSchema = external_exports.object({
|
|
|
119534
119546
|
capabilities: external_exports.array(ResponseSurfaceCapabilitySchema).max(8).default([])
|
|
119535
119547
|
});
|
|
119536
119548
|
var StrictResponseSurfaceStateSchema = external_exports.object({
|
|
119537
|
-
mode: ResponseSurfaceModeSchema,
|
|
119549
|
+
mode: ResponseSurfaceModeSchema.optional().default("card"),
|
|
119538
119550
|
primary: ResponseSurfacePrimarySchema.optional(),
|
|
119539
119551
|
post: ResponseSurfacePostSchema.optional(),
|
|
119540
119552
|
card: ResponseSurfaceCardSchema.optional()
|
|
@@ -119549,9 +119561,18 @@ var StrictResponseSurfaceStateSchema = external_exports.object({
|
|
|
119549
119561
|
});
|
|
119550
119562
|
var ResponseSurfaceStateSchema = external_exports.preprocess((value) => {
|
|
119551
119563
|
if (value === void 0) return void 0;
|
|
119552
|
-
|
|
119553
|
-
return result.success ? result.data : void 0;
|
|
119564
|
+
return parseResponseSurfaceState(value).state;
|
|
119554
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
|
+
}
|
|
119555
119576
|
var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
119556
119577
|
/**
|
|
119557
119578
|
* Master gate. Default true makes response surfaces available unless the
|
|
@@ -119592,10 +119613,16 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
119592
119613
|
*/
|
|
119593
119614
|
allow_agent_mentions: external_exports.boolean().default(true),
|
|
119594
119615
|
/**
|
|
119595
|
-
* Optional
|
|
119596
|
-
* 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.
|
|
119597
119618
|
* Keep real IDs in private bot config, never in public docs/tests.
|
|
119598
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
|
+
*/
|
|
119599
119626
|
allowed_mention_open_ids: external_exports.array(external_exports.string().min(1)).default([])
|
|
119600
119627
|
}).default(responseSurfacePrototypeConfigDefaults);
|
|
119601
119628
|
function isResponseSurfacePrototypeAllowlisted(config, facts) {
|
|
@@ -119607,12 +119634,30 @@ function isResponseSurfacePrototypeAllowlisted(config, facts) {
|
|
|
119607
119634
|
const threadAllowed = config.allowed_threads.length > 0 && config.allowed_threads.includes(facts.threadId);
|
|
119608
119635
|
return chatAllowed || threadAllowed;
|
|
119609
119636
|
}
|
|
119610
|
-
function
|
|
119611
|
-
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
|
+
}
|
|
119612
119645
|
const normalized = userId.trim().toLowerCase();
|
|
119613
|
-
if (normalized === "all" || normalized === "@all")
|
|
119614
|
-
|
|
119615
|
-
|
|
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" };
|
|
119616
119661
|
}
|
|
119617
119662
|
function shouldProvideResponseSurfacePostClient(config) {
|
|
119618
119663
|
return !!(config?.enabled && !config.kill_switch && config.post_outbound_enabled);
|
|
@@ -119797,14 +119842,19 @@ async function ensureStateFile(worktreePath) {
|
|
|
119797
119842
|
await fs3.writeFile(file, JSON.stringify(initial, null, 2), "utf8");
|
|
119798
119843
|
}
|
|
119799
119844
|
async function readStateFile(worktreePath) {
|
|
119845
|
+
return (await readStateFileDetailed(worktreePath)).state;
|
|
119846
|
+
}
|
|
119847
|
+
async function readStateFileDetailed(worktreePath) {
|
|
119800
119848
|
const file = stateFilePathOf(worktreePath);
|
|
119801
119849
|
let raw;
|
|
119802
119850
|
try {
|
|
119803
119851
|
raw = await fs3.readFile(file, "utf8");
|
|
119804
119852
|
} catch (err) {
|
|
119805
|
-
if (err.code === "ENOENT")
|
|
119853
|
+
if (err.code === "ENOENT") {
|
|
119854
|
+
return { state: null, diagnostics: [] };
|
|
119855
|
+
}
|
|
119806
119856
|
console.warn(`[stateFile] read ${file} failed:`, err);
|
|
119807
|
-
return null;
|
|
119857
|
+
return { state: null, diagnostics: [] };
|
|
119808
119858
|
}
|
|
119809
119859
|
let parsed;
|
|
119810
119860
|
try {
|
|
@@ -119822,11 +119872,11 @@ async function readStateFile(worktreePath) {
|
|
|
119822
119872
|
`[stateFile] ${file} not valid JSON (repair also failed):`,
|
|
119823
119873
|
err2
|
|
119824
119874
|
);
|
|
119825
|
-
return null;
|
|
119875
|
+
return { state: null, diagnostics: [] };
|
|
119826
119876
|
}
|
|
119827
119877
|
} else {
|
|
119828
119878
|
console.warn(`[stateFile] ${file} not valid JSON:`, err);
|
|
119829
|
-
return null;
|
|
119879
|
+
return { state: null, diagnostics: [] };
|
|
119830
119880
|
}
|
|
119831
119881
|
}
|
|
119832
119882
|
const result = StateFileSchema.safeParse(parsed);
|
|
@@ -119835,9 +119885,22 @@ async function readStateFile(worktreePath) {
|
|
|
119835
119885
|
`[stateFile] ${file} failed schema validation:`,
|
|
119836
119886
|
result.error.issues
|
|
119837
119887
|
);
|
|
119838
|
-
return null;
|
|
119888
|
+
return { state: null, diagnostics: [] };
|
|
119839
119889
|
}
|
|
119840
|
-
|
|
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}`];
|
|
119841
119904
|
}
|
|
119842
119905
|
function tryRepairBareQuotesInLastMessage(raw) {
|
|
119843
119906
|
const startRe = /"last_message"\s*:\s*"/;
|
|
@@ -120660,6 +120723,13 @@ function derivePostIdempotencyKey(input) {
|
|
|
120660
120723
|
|
|
120661
120724
|
// src/bridge/handler.ts
|
|
120662
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
|
+
}
|
|
120663
120733
|
function execGit(cwd, args) {
|
|
120664
120734
|
return new Promise((resolve2, reject) => {
|
|
120665
120735
|
const child = child_process.spawn("git", args, {
|
|
@@ -121398,6 +121468,13 @@ var BridgeHandler = class {
|
|
|
121398
121468
|
botGitIdentity: this.deps.botConfig?.git_identity,
|
|
121399
121469
|
gitlabToken: this.deps.gitlabToken
|
|
121400
121470
|
});
|
|
121471
|
+
if (isAgentWorkspace && handle.pid != null) {
|
|
121472
|
+
const sessionPidFile = path9.join(worktreePath, ".larkway", "runner.pid");
|
|
121473
|
+
void fs6.mkdir(path9.dirname(sessionPidFile), { recursive: true }).then(
|
|
121474
|
+
() => fs6.writeFile(sessionPidFile, JSON.stringify({ pid: handle.pid }), "utf8")
|
|
121475
|
+
).catch(() => {
|
|
121476
|
+
});
|
|
121477
|
+
}
|
|
121401
121478
|
let sessionId;
|
|
121402
121479
|
let trustedAnswerText = "";
|
|
121403
121480
|
try {
|
|
@@ -121415,8 +121492,23 @@ var BridgeHandler = class {
|
|
|
121415
121492
|
}
|
|
121416
121493
|
const result = await handle.done;
|
|
121417
121494
|
const cardKitTurnTimedOut = cardKitProgress != null && result.exitCode !== 0 && Date.now() - runnerStartedAt >= timeoutMs;
|
|
121418
|
-
const
|
|
121495
|
+
const reportedStateRead = await readStateFileDetailed(worktreePath);
|
|
121496
|
+
const rawReportedState = reportedStateRead.state;
|
|
121419
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
|
+
}
|
|
121420
121512
|
const now = Date.now();
|
|
121421
121513
|
if (sessionId !== void 0 && currentExisting === void 0) {
|
|
121422
121514
|
await this.deps.sessionStore.put({
|
|
@@ -121455,11 +121547,21 @@ var BridgeHandler = class {
|
|
|
121455
121547
|
} else if (cardKitTimeoutFailure) {
|
|
121456
121548
|
success = false;
|
|
121457
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
|
+
});
|
|
121458
121555
|
} else if (result.exitCode === 0) {
|
|
121459
121556
|
success = true;
|
|
121460
121557
|
} else {
|
|
121461
121558
|
success = false;
|
|
121462
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
|
+
});
|
|
121463
121565
|
}
|
|
121464
121566
|
const fallbackAnswer = trustedAnswerText.trim() || cardKitProgress?.answerText.trim() || "";
|
|
121465
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");
|
|
@@ -121480,9 +121582,31 @@ var BridgeHandler = class {
|
|
|
121480
121582
|
contentBlocks: reportedState?.content_blocks
|
|
121481
121583
|
};
|
|
121482
121584
|
if (cardKitProgress) {
|
|
121483
|
-
const
|
|
121484
|
-
|
|
121485
|
-
)
|
|
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
|
+
}
|
|
121486
121610
|
try {
|
|
121487
121611
|
await cardKitProgress.finalize({
|
|
121488
121612
|
title: baseCardPayload.titleOverride,
|
|
@@ -121793,7 +121917,7 @@ function isRuntimeEventRecord(value) {
|
|
|
121793
121917
|
|
|
121794
121918
|
// src/housekeeping/gc.ts
|
|
121795
121919
|
import { spawn } from "node:child_process";
|
|
121796
|
-
import { readFile as readFile4, readdir, stat } from "node:fs/promises";
|
|
121920
|
+
import { readFile as readFile4, readdir, rm, stat } from "node:fs/promises";
|
|
121797
121921
|
import { join as pathJoin } from "node:path";
|
|
121798
121922
|
var DEFAULT_SCAN_INTERVAL_MS = 30 * 60 * 1e3;
|
|
121799
121923
|
var DEFAULT_IDLE_NOTIFY_MS = 4 * 60 * 60 * 1e3;
|
|
@@ -121805,12 +121929,20 @@ var Housekeeping = class {
|
|
|
121805
121929
|
#idleCleanupMs;
|
|
121806
121930
|
/** This housekeeping's bot scope — resolves which worktrees dir to sweep. */
|
|
121807
121931
|
#botId;
|
|
121932
|
+
/**
|
|
121933
|
+
* Bot runtime. "agent_workspace" reclaims per-thread session dirs under
|
|
121934
|
+
* agents/<id>/workspace/sessions/ via rm -rf (they are plain dirs / full
|
|
121935
|
+
* clones, not git worktrees). Anything else (legacy) reclaims git worktrees
|
|
121936
|
+
* under <botId>/worktrees/ via `git worktree remove`.
|
|
121937
|
+
*/
|
|
121938
|
+
#runtime;
|
|
121808
121939
|
/** thread_ids that have already received an idle-notify warn this session */
|
|
121809
121940
|
#notified = /* @__PURE__ */ new Set();
|
|
121810
121941
|
#timer;
|
|
121811
121942
|
constructor(deps, opts) {
|
|
121812
121943
|
this.#sessionStore = deps.sessionStore;
|
|
121813
121944
|
this.#botId = deps.botId;
|
|
121945
|
+
this.#runtime = deps.runtime;
|
|
121814
121946
|
this.#scanIntervalMs = opts?.scanIntervalMs ?? DEFAULT_SCAN_INTERVAL_MS;
|
|
121815
121947
|
this.#idleNotifyMs = opts?.idleNotifyMs ?? DEFAULT_IDLE_NOTIFY_MS;
|
|
121816
121948
|
this.#idleCleanupMs = opts?.idleCleanupMs ?? DEFAULT_IDLE_CLEANUP_MS;
|
|
@@ -121855,9 +121987,9 @@ var Housekeeping = class {
|
|
|
121855
121987
|
if (idleMs >= this.#idleCleanupMs) {
|
|
121856
121988
|
const idleHours = Math.floor(idleMs / (60 * 60 * 1e3));
|
|
121857
121989
|
console.warn(
|
|
121858
|
-
`[housekeeping] \u8BDD\u9898 ${tid} idle ${idleHours}h
|
|
121990
|
+
`[housekeeping] \u8BDD\u9898 ${tid} idle ${idleHours}h+,\u5DE5\u4F5C\u76EE\u5F55\u53EF\u6E05\u7406`
|
|
121859
121991
|
);
|
|
121860
|
-
void
|
|
121992
|
+
void this.#cleanupThread(tid, record.botId, dryRun);
|
|
121861
121993
|
this.#notified.delete(tid);
|
|
121862
121994
|
continue;
|
|
121863
121995
|
}
|
|
@@ -121878,32 +122010,46 @@ var Housekeeping = class {
|
|
|
121878
122010
|
* cleanupWorktree (kill PIDs → git worktree remove --force).
|
|
121879
122011
|
*/
|
|
121880
122012
|
async #sweepOrphans(liveThreadIds, now, dryRun) {
|
|
121881
|
-
const
|
|
122013
|
+
const reclaimDir = this.#runtime === "agent_workspace" ? resolveAgentWorkspaceSessionsDir(this.#botId ?? "") : resolveWorktreesDir(this.#botId);
|
|
121882
122014
|
let dirNames;
|
|
121883
122015
|
try {
|
|
121884
|
-
const entries = await readdir(
|
|
122016
|
+
const entries = await readdir(reclaimDir, { withFileTypes: true });
|
|
121885
122017
|
dirNames = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
121886
122018
|
} catch (err) {
|
|
121887
122019
|
if (err.code !== "ENOENT") {
|
|
121888
|
-
console.error(`[gc] orphan sweep: cannot read ${
|
|
122020
|
+
console.error(`[gc] orphan sweep: cannot read ${reclaimDir}:`, err);
|
|
121889
122021
|
}
|
|
121890
122022
|
return;
|
|
121891
122023
|
}
|
|
121892
122024
|
for (const name of selectOrphanWorktreeNames(dirNames, liveThreadIds)) {
|
|
121893
|
-
|
|
122025
|
+
if (name.startsWith("_")) continue;
|
|
122026
|
+
const dirPath = pathJoin(reclaimDir, name);
|
|
121894
122027
|
let ageMs;
|
|
121895
122028
|
try {
|
|
121896
|
-
ageMs = now - (await stat(
|
|
122029
|
+
ageMs = now - (await stat(dirPath)).mtimeMs;
|
|
121897
122030
|
} catch {
|
|
121898
122031
|
continue;
|
|
121899
122032
|
}
|
|
121900
122033
|
if (ageMs < this.#idleCleanupMs) continue;
|
|
121901
122034
|
const ageHours = Math.floor(ageMs / (60 * 60 * 1e3));
|
|
121902
122035
|
console.warn(
|
|
121903
|
-
`[housekeeping] orphan
|
|
122036
|
+
`[housekeeping] orphan ${name}(\u65E0 session \u8BB0\u5F55, idle ${ageHours}h+)\u2014 \u6E05\u7406`
|
|
121904
122037
|
);
|
|
121905
|
-
await
|
|
122038
|
+
await this.#cleanupThread(name, this.#botId, dryRun);
|
|
122039
|
+
}
|
|
122040
|
+
}
|
|
122041
|
+
/**
|
|
122042
|
+
* Runtime-aware reclaim of one thread's working dir.
|
|
122043
|
+
* - agent_workspace: rm -rf agents/<id>/workspace/sessions/<tid> (plain dir /
|
|
122044
|
+
* full clones — `git worktree remove` cannot reclaim these).
|
|
122045
|
+
* - legacy: git worktree remove --force <botId>/worktrees/<tid>.
|
|
122046
|
+
* Both kill any lingering runner PIDs first (idle >24h → normally dead).
|
|
122047
|
+
*/
|
|
122048
|
+
#cleanupThread(threadId, botId, dryRun) {
|
|
122049
|
+
if (this.#runtime === "agent_workspace") {
|
|
122050
|
+
return cleanupAgentSession(threadId, botId ?? this.#botId, dryRun);
|
|
121906
122051
|
}
|
|
122052
|
+
return cleanupWorktree(threadId, botId, dryRun);
|
|
121907
122053
|
}
|
|
121908
122054
|
};
|
|
121909
122055
|
function selectOrphanWorktreeNames(dirNames, liveThreadIds) {
|
|
@@ -122034,6 +122180,61 @@ async function cleanupWorktree(threadId, botId, dryRun) {
|
|
|
122034
122180
|
console.error(`[gc] worktree remove failed for path=${worktreePath}:`, err);
|
|
122035
122181
|
}
|
|
122036
122182
|
}
|
|
122183
|
+
function isReclaimableSessionPath(p) {
|
|
122184
|
+
const m = /[/\\]workspace[/\\]sessions[/\\]([^/\\]+)[/\\]?$/.exec(p);
|
|
122185
|
+
if (m === null) return false;
|
|
122186
|
+
const seg = m[1];
|
|
122187
|
+
return seg !== "." && seg !== "..";
|
|
122188
|
+
}
|
|
122189
|
+
async function removeSessionDir(sessionPath, dryRun) {
|
|
122190
|
+
if (!isReclaimableSessionPath(sessionPath)) {
|
|
122191
|
+
console.error(`[gc] refusing to rm -rf non-session path: ${sessionPath}`);
|
|
122192
|
+
return;
|
|
122193
|
+
}
|
|
122194
|
+
if (dryRun) {
|
|
122195
|
+
console.log(`[gc] dry-run: would rm -rf ${sessionPath}`);
|
|
122196
|
+
return;
|
|
122197
|
+
}
|
|
122198
|
+
console.log(`[gc] rm -rf ${sessionPath}`);
|
|
122199
|
+
try {
|
|
122200
|
+
await rm(sessionPath, { recursive: true, force: true });
|
|
122201
|
+
} catch (err) {
|
|
122202
|
+
console.error(`[gc] rm -rf failed for ${sessionPath}:`, err);
|
|
122203
|
+
}
|
|
122204
|
+
}
|
|
122205
|
+
async function cleanupAgentSession(threadId, agentId, dryRun) {
|
|
122206
|
+
if (!agentId) {
|
|
122207
|
+
console.error(
|
|
122208
|
+
`[gc] cleanupAgentSession: missing agentId for thread=${threadId}`
|
|
122209
|
+
);
|
|
122210
|
+
return;
|
|
122211
|
+
}
|
|
122212
|
+
let sessionPath;
|
|
122213
|
+
try {
|
|
122214
|
+
sessionPath = resolveAgentSessionPath(agentId, threadId);
|
|
122215
|
+
} catch (err) {
|
|
122216
|
+
console.error(`[gc] invalid session threadId=${threadId}:`, err);
|
|
122217
|
+
return;
|
|
122218
|
+
}
|
|
122219
|
+
console.log(
|
|
122220
|
+
`[gc] cleanup session thread=${threadId} path=${sessionPath} dryRun=${dryRun}`
|
|
122221
|
+
);
|
|
122222
|
+
let pids;
|
|
122223
|
+
try {
|
|
122224
|
+
pids = await findPidsByWorktree(sessionPath);
|
|
122225
|
+
} catch (err) {
|
|
122226
|
+
console.error(`[gc] pid lookup failed for path=${sessionPath}:`, err);
|
|
122227
|
+
pids = [];
|
|
122228
|
+
}
|
|
122229
|
+
const alivePids = pids.filter(isPidAlive);
|
|
122230
|
+
if (alivePids.length > 0) {
|
|
122231
|
+
console.warn(
|
|
122232
|
+
`[gc] skip live session thread=${threadId} path=${sessionPath}: runner pid(s) [${alivePids.join(", ")}] still alive \u2014 not reclaiming in-flight work`
|
|
122233
|
+
);
|
|
122234
|
+
return;
|
|
122235
|
+
}
|
|
122236
|
+
await removeSessionDir(sessionPath, dryRun);
|
|
122237
|
+
}
|
|
122037
122238
|
|
|
122038
122239
|
// src/config/botLoader.ts
|
|
122039
122240
|
import { readdir as readdir2, readFile as readFile5 } from "node:fs/promises";
|
|
@@ -126008,7 +126209,8 @@ stderr: ${stderr}` : "")
|
|
|
126008
126209
|
return {
|
|
126009
126210
|
events: generateEvents(),
|
|
126010
126211
|
done,
|
|
126011
|
-
kill: doKill
|
|
126212
|
+
kill: doKill,
|
|
126213
|
+
pid: child.pid ?? void 0
|
|
126012
126214
|
};
|
|
126013
126215
|
}
|
|
126014
126216
|
var ClaudeRunner = class {
|
|
@@ -126365,7 +126567,8 @@ stderr: ${stderr}` : "")
|
|
|
126365
126567
|
return {
|
|
126366
126568
|
events: generateEvents(),
|
|
126367
126569
|
done,
|
|
126368
|
-
kill: doKill
|
|
126570
|
+
kill: doKill,
|
|
126571
|
+
pid: child.pid ?? void 0
|
|
126369
126572
|
};
|
|
126370
126573
|
}
|
|
126371
126574
|
var CodexRunner = class {
|
|
@@ -126839,7 +127042,11 @@ async function runV2Mode({
|
|
|
126839
127042
|
await upsertRuntimeEvent(larkwayHome(), bot.id, patch);
|
|
126840
127043
|
}
|
|
126841
127044
|
});
|
|
126842
|
-
const housekeeping = new Housekeeping({
|
|
127045
|
+
const housekeeping = new Housekeeping({
|
|
127046
|
+
sessionStore,
|
|
127047
|
+
botId: bot.id,
|
|
127048
|
+
runtime: bot.runtime
|
|
127049
|
+
});
|
|
126843
127050
|
const inst = {
|
|
126844
127051
|
bot,
|
|
126845
127052
|
client,
|