@keyou007/agent-bot 0.1.15-alpha.0 → 0.1.15-alpha.2
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/CHANGELOG.md +14 -0
- package/README.md +23 -20
- package/README.zh.md +23 -20
- package/config.example.yaml +1 -0
- package/dist/cli/FeishuAppConfiguration.js +42 -3
- package/dist/cli/FeishuAppConfiguration.js.map +1 -1
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/feishu/CardRenderer.js +114 -16
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuConnector.js +21 -6
- package/dist/feishu/FeishuConnector.js.map +1 -1
- package/dist/feishu/FeishuMarkdown.js +58 -6
- package/dist/feishu/FeishuMarkdown.js.map +1 -1
- package/dist/feishu/FeishuMessageClient.js +33 -4
- package/dist/feishu/FeishuMessageClient.js.map +1 -1
- package/dist/feishu/FeishuTurnPresenter.js +7 -6
- package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
- package/dist/feishu/FinalResponseBranding.js +15 -0
- package/dist/feishu/FinalResponseBranding.js.map +1 -0
- package/dist/logging/DailyLogStream.js +73 -0
- package/dist/logging/DailyLogStream.js.map +1 -0
- package/dist/logging/logger.js +2 -1
- package/dist/logging/logger.js.map +1 -1
- package/dist/proxy/ProxySessionController.js +270 -40
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/state/StateStore.js +126 -0
- package/dist/state/StateStore.js.map +1 -1
- package/dist/state/migrations.js +11 -0
- package/dist/state/migrations.js.map +1 -1
- package/dist/supervision/SupervisorDiagnostics.js +37 -21
- package/dist/supervision/SupervisorDiagnostics.js.map +1 -1
- package/dist/supervisor.js +11 -4
- package/dist/supervisor.js.map +1 -1
- package/dist/utils/executeShellCommand.js +83 -16
- package/dist/utils/executeShellCommand.js.map +1 -1
- package/docs/technical-reference.md +9 -8
- package/docs/technical-reference.zh.md +9 -8
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/src/cli/FeishuAppConfiguration.ts +76 -3
- package/src/cli.ts +6 -1
- package/src/feishu/CardRenderer.ts +150 -17
- package/src/feishu/FeishuConnector.ts +32 -7
- package/src/feishu/FeishuMarkdown.ts +64 -5
- package/src/feishu/FeishuMessageClient.ts +41 -12
- package/src/feishu/FeishuTurnPresenter.ts +9 -6
- package/src/feishu/FinalResponseBranding.ts +18 -0
- package/src/logging/DailyLogStream.ts +88 -0
- package/src/logging/logger.ts +2 -1
- package/src/proxy/ProxySessionController.ts +292 -39
- package/src/state/StateStore.ts +180 -0
- package/src/state/migrations.ts +11 -0
- package/src/supervision/SupervisorDiagnostics.ts +41 -25
- package/src/supervisor.ts +10 -4
- package/src/utils/executeShellCommand.ts +103 -15
|
@@ -18,8 +18,17 @@ export function executeShellCommand(command, cwd, options = {}) {
|
|
|
18
18
|
timedOut = true;
|
|
19
19
|
child.kill();
|
|
20
20
|
}, timeoutMs);
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const appendOutput = (stream, chunk) => {
|
|
22
|
+
output.append(stream, chunk);
|
|
23
|
+
try {
|
|
24
|
+
options.onOutput?.(output.result());
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Output presentation must never interrupt the child process.
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
child.stdout.on("data", (chunk) => appendOutput("stdout", chunk));
|
|
31
|
+
child.stderr.on("data", (chunk) => appendOutput("stderr", chunk));
|
|
23
32
|
child.once("error", (error) => {
|
|
24
33
|
clearTimeout(timeout);
|
|
25
34
|
reject(error);
|
|
@@ -45,32 +54,90 @@ function prepareShellCommand(command, platform) {
|
|
|
45
54
|
};
|
|
46
55
|
}
|
|
47
56
|
class BoundedOutput {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
retained = [];
|
|
58
|
+
seenBytes = { stdout: 0, stderr: 0 };
|
|
59
|
+
headBytes;
|
|
60
|
+
tailBytes;
|
|
52
61
|
truncated = false;
|
|
53
62
|
constructor(maxBytes) {
|
|
54
|
-
|
|
63
|
+
const normalizedMaxBytes = Math.max(1, Math.floor(maxBytes));
|
|
64
|
+
this.headBytes = Math.ceil(normalizedMaxBytes / 3);
|
|
65
|
+
this.tailBytes = normalizedMaxBytes - this.headBytes;
|
|
55
66
|
}
|
|
56
67
|
append(stream, chunk) {
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
if (chunk.length === 0)
|
|
69
|
+
return;
|
|
70
|
+
this.seenBytes[stream] += chunk.length;
|
|
71
|
+
if (!this.truncated) {
|
|
72
|
+
const next = [...this.retained, { stream, data: chunk }];
|
|
73
|
+
if (outputChunksLength(next) <= this.headBytes + this.tailBytes) {
|
|
74
|
+
this.retained = next;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
59
77
|
this.truncated = true;
|
|
78
|
+
this.retained = [
|
|
79
|
+
...takeOutputChunkHead(next, this.headBytes),
|
|
80
|
+
...takeOutputChunkTail(next, this.tailBytes),
|
|
81
|
+
];
|
|
60
82
|
return;
|
|
61
83
|
}
|
|
62
|
-
const
|
|
63
|
-
this
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.truncated = true;
|
|
84
|
+
const head = takeOutputChunkHead(this.retained, this.headBytes);
|
|
85
|
+
const previousTail = takeOutputChunkTail(this.retained, this.tailBytes);
|
|
86
|
+
const tail = takeOutputChunkTail([...previousTail, { stream, data: chunk }], this.tailBytes);
|
|
87
|
+
this.retained = [...head, ...tail];
|
|
67
88
|
}
|
|
68
89
|
result() {
|
|
69
90
|
return {
|
|
70
|
-
stdout:
|
|
71
|
-
stderr:
|
|
91
|
+
stdout: this.streamResult("stdout"),
|
|
92
|
+
stderr: this.streamResult("stderr"),
|
|
72
93
|
outputTruncated: this.truncated,
|
|
73
94
|
};
|
|
74
95
|
}
|
|
96
|
+
streamResult(stream) {
|
|
97
|
+
if (!this.truncated) {
|
|
98
|
+
return Buffer.concat(this.retained.filter((chunk) => chunk.stream === stream).map((chunk) => chunk.data)).toString("utf8");
|
|
99
|
+
}
|
|
100
|
+
const head = takeOutputChunkHead(this.retained, this.headBytes)
|
|
101
|
+
.filter((chunk) => chunk.stream === stream);
|
|
102
|
+
const tail = takeOutputChunkTail(this.retained, this.tailBytes)
|
|
103
|
+
.filter((chunk) => chunk.stream === stream);
|
|
104
|
+
const retainedBytes = outputChunksLength([...head, ...tail]);
|
|
105
|
+
const marker = this.seenBytes[stream] > retainedBytes
|
|
106
|
+
? Buffer.from("\n... output truncated ...\n", "utf8")
|
|
107
|
+
: Buffer.alloc(0);
|
|
108
|
+
return Buffer.concat([
|
|
109
|
+
...head.map((chunk) => chunk.data),
|
|
110
|
+
marker,
|
|
111
|
+
...tail.map((chunk) => chunk.data),
|
|
112
|
+
]).toString("utf8");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function outputChunksLength(chunks) {
|
|
116
|
+
return chunks.reduce((total, chunk) => total + chunk.data.length, 0);
|
|
117
|
+
}
|
|
118
|
+
function takeOutputChunkHead(chunks, maxBytes) {
|
|
119
|
+
const retained = [];
|
|
120
|
+
let remaining = maxBytes;
|
|
121
|
+
for (const chunk of chunks) {
|
|
122
|
+
if (remaining <= 0)
|
|
123
|
+
break;
|
|
124
|
+
const data = chunk.data.length <= remaining ? chunk.data : chunk.data.subarray(0, remaining);
|
|
125
|
+
retained.push({ stream: chunk.stream, data });
|
|
126
|
+
remaining -= data.length;
|
|
127
|
+
}
|
|
128
|
+
return retained;
|
|
129
|
+
}
|
|
130
|
+
function takeOutputChunkTail(chunks, maxBytes) {
|
|
131
|
+
const retained = [];
|
|
132
|
+
let remaining = maxBytes;
|
|
133
|
+
for (let index = chunks.length - 1; index >= 0 && remaining > 0; index -= 1) {
|
|
134
|
+
const chunk = chunks[index];
|
|
135
|
+
const data = chunk.data.length <= remaining
|
|
136
|
+
? chunk.data
|
|
137
|
+
: chunk.data.subarray(chunk.data.length - remaining);
|
|
138
|
+
retained.unshift({ stream: chunk.stream, data });
|
|
139
|
+
remaining -= data.length;
|
|
140
|
+
}
|
|
141
|
+
return retained;
|
|
75
142
|
}
|
|
76
143
|
//# sourceMappingURL=executeShellCommand.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executeShellCommand.js","sourceRoot":"","sources":["../../src/utils/executeShellCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,kBAAkB,GAAG,OAAO,CAAC;AACnC,MAAM,wBAAwB,GAAG,EAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"executeShellCommand.js","sourceRoot":"","sources":["../../src/utils/executeShellCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,kBAAkB,GAAG,OAAO,CAAC;AACnC,MAAM,wBAAwB,GAAG,EAAE,GAAG,IAAI,CAAC;AAsB3C,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,GAAW,EACX,OAAO,GAAwB,EAAE;IAEjC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,wBAAwB,CAAC;IAC1E,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEpF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;YACnD,GAAG;YACH,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,MAAM,YAAY,GAAG,CAAC,MAA2B,EAAE,KAAa,EAAQ,EAAE;YACxE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7B,IAAI,CAAC;gBACH,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,8DAA8D;YAChE,CAAC;QACH,CAAC,CAAC;QACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAC1E,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAC1E,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC5B,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC/B,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,OAAO,CAAC;gBACN,GAAG,MAAM,CAAC,MAAM,EAAE;gBAClB,QAAQ;gBACR,QAAQ;aACT,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe,EAAE,QAAyB;IACrE,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;IAChF,MAAM,MAAM,GAAG,4GAA4G,OAAO,EAAE,CAAC;IACrI,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClE,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,IAAI,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,CAAC;KACxG,CAAC;AACJ,CAAC;AAED,MAAM,aAAa;IACT,QAAQ,GAAkB,EAAE,CAAC;IACpB,SAAS,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACrC,SAAS,CAAS;IAClB,SAAS,CAAS;IAC3B,SAAS,GAAG,KAAK,CAAC;IAE1B,YAAY,QAAgB;QAC1B,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,SAAS,GAAG,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC;IACvD,CAAC;IAED,MAAM,CAAC,MAA2B,EAAE,KAAa;QAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC;QAEvC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACzD,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;gBAChE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,QAAQ,GAAG;gBACd,GAAG,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBAC5C,GAAG,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;aAC7C,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAChE,MAAM,YAAY,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACxE,MAAM,IAAI,GAAG,mBAAmB,CAAC,CAAC,GAAG,YAAY,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7F,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,MAAM;QACJ,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;YACnC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;YACnC,eAAe,EAAE,IAAI,CAAC,SAAS;SAChC,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,MAA2B;QAC9C,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC,MAAM,CAClB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CACpF,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;QACD,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;aAC5D,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;aAC5D,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QAE9C,MAAM,aAAa,GAAG,kBAAkB,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,aAAa;YACnD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,MAAM,CAAC;YACrD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;YAClC,MAAM;YACN,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SACnC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;CACF;AAOD,SAAS,kBAAkB,CAAC,MAAqB;IAC/C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAqB,EAAE,QAAgB;IAClE,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,IAAI,SAAS,GAAG,QAAQ,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,SAAS,IAAI,CAAC;YAAE,MAAM;QAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAC7F,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAqB,EAAE,QAAgB;IAClE,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,IAAI,SAAS,GAAG,QAAQ,CAAC;IACzB,KAAK,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,SAAS;YACzC,CAAC,CAAC,KAAK,CAAC,IAAI;YACZ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;QACvD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -43,7 +43,7 @@ The CLI reads the system locale through Node.js internationalization support. Lo
|
|
|
43
43
|
| `~/.agent-bot/.env` | Feishu credentials |
|
|
44
44
|
| `~/.agent-bot/data/agent-bot.sqlite` | Persistent task and delivery state |
|
|
45
45
|
| `~/.agent-bot/data/inbound-images/` | Cached incoming images |
|
|
46
|
-
| `~/.agent-bot/logs/agent-bot.log`
|
|
46
|
+
| `~/.agent-bot/logs/agent-bot.YYYY-MM-DD.log` | Daily structured runtime logs |
|
|
47
47
|
|
|
48
48
|
Configuration path precedence:
|
|
49
49
|
|
|
@@ -84,18 +84,19 @@ Initialization holds `~/.agent-bot/init.lock` so concurrent commands cannot crea
|
|
|
84
84
|
|
|
85
85
|
When complete credentials are absent, initialization uses Feishu one-click registration and reports its verification URL as text and a QR code. In-progress registration codes are not resumed: if the process exits before the complete credential pair is persisted, the next run starts a new app registration. After credentials are persisted, initialization audits the currently published app version and can safely resume that audit after interruption.
|
|
86
86
|
|
|
87
|
-
Missing app configuration is handled in
|
|
87
|
+
Missing app configuration is handled in three stages:
|
|
88
88
|
|
|
89
|
-
1. Core configuration is requested and polled until
|
|
89
|
+
1. Core configuration is requested and polled until basic messaging becomes available.
|
|
90
90
|
2. Remaining optional configuration is requested. The CLI prints its QR code followed by the authorization URL, then immediately polls for up to five minutes. An interactive terminal offers only `Y` to skip optional authorization and continue; otherwise the user completes authorization in the browser while polling continues.
|
|
91
|
+
3. Only in all-group-message mode, the manually configured and published `im:message.group_msg` scope is requested last. Entering `Y` skips this step, and a timeout returns a partial result instead of failing initialization. Mention-only mode excludes the permission entirely.
|
|
91
92
|
|
|
92
|
-
Configuration supported by the one-click launcher is encoded in its `addons` manifest. When all-group-message mode is selected, the
|
|
93
|
+
Configuration supported by the one-click launcher is encoded in its `addons` manifest. When all-group-message mode is selected, the manual `im:message.group_msg` scope is excluded from that manifest because Feishu does not add it through one-click configuration. Instead, the CLI prints a QR code and this app-specific, pre-filtered Developer Console URL during the final stage:
|
|
93
94
|
|
|
94
95
|
```text
|
|
95
96
|
https://open.feishu.cn/app/<appId>/auth?q=im%3Amessage.group_msg&op_from=openapi&token_type=tenant
|
|
96
97
|
```
|
|
97
98
|
|
|
98
|
-
The user must add the permission, publish the app version, and complete tenant approval when required.
|
|
99
|
+
The user must add the permission, publish the app version, and complete tenant approval when required. The final stage waits for up to five minutes for the permission to appear in the published version. Entering `Y`, reaching the timeout, or leaving the version unpublished returns a partial configuration result and warns that ordinary group messages which do not mention the bot are unavailable.
|
|
99
100
|
|
|
100
101
|
Optional polling failures and timeouts return a partial configuration result instead of failing initialization. When stdin is not an interactive terminal, no skip input is available and polling continues until configuration becomes active or times out. Verification URLs and prompts use stderr, so `--json` keeps its final stdout machine-readable.
|
|
101
102
|
|
|
@@ -223,7 +224,7 @@ The message route determines the current task:
|
|
|
223
224
|
|
|
224
225
|
Commands, card callbacks, progress cards, and final responses stay on the originating route.
|
|
225
226
|
|
|
226
|
-
Starting a Feishu thread from a mapped user message, progress card, or final response forks from the associated completed App Server turn. If no reliable
|
|
227
|
+
Starting a Feishu thread from a mapped user message, progress card, or final response does not immediately create a task. Slash commands execute while the thread remains unbound; commands that require a current task return binding guidance instead of targeting the parent conversation. The first ordinary Prompt lazily forks from the associated completed App Server turn. If no reliable source turn exists, it starts a fresh task. `/new` also starts a fresh task directly, and `/sessions` or `/switch` can bind an existing task without creating an intermediate fork.
|
|
227
228
|
|
|
228
229
|
`/forkgroup` has thread-aware source selection. An unbound thread, or a bound thread task with no completed turn of its own, forks directly from the thread's original anchor turn without creating an intermediate thread task. Once the thread task has completed a turn, `/forkgroup` uses its latest locally persisted completed turn. A newer active turn does not block the command and is excluded from the fork point.
|
|
229
230
|
|
|
@@ -303,8 +304,8 @@ On Windows, the CLI refreshes Machine and User environment variables before the
|
|
|
303
304
|
|
|
304
305
|
Supervisor crash diagnostics are isolated to the selected profile:
|
|
305
306
|
|
|
306
|
-
- `logs/supervisor.log` permanently records worker PIDs, exit codes, uptime, restart delays, and diagnostic artifact paths.
|
|
307
|
-
- `logs/worker.stderr.log` captures Node/V8 fatal output that would otherwise be lost by the detached process. Both diagnostic logs
|
|
307
|
+
- `logs/supervisor.YYYY-MM-DD.log` permanently records worker PIDs, exit codes, uptime, restart delays, and diagnostic artifact paths.
|
|
308
|
+
- `logs/worker.stderr.YYYY-MM-DD.log` captures Node/V8 fatal output that would otherwise be lost by the detached process. Both diagnostic logs are split by local calendar day and retain the existing 10 MiB backup rotation within a day.
|
|
308
309
|
- `data/last-crash.json` points to the latest unexpected worker exit, while timestamped `data/crash-reports/crash-*.json` files preserve the history.
|
|
309
310
|
- `data/crash-reports/report.*.json` contains Node diagnostic reports when Node can generate one.
|
|
310
311
|
|
|
@@ -43,7 +43,7 @@ CLI 通过 Node.js 国际化能力读取系统 Locale。以 `zh` 开头的 Local
|
|
|
43
43
|
| `~/.agent-bot/.env` | 飞书凭据 |
|
|
44
44
|
| `~/.agent-bot/data/agent-bot.sqlite` | 任务和投递持久化状态 |
|
|
45
45
|
| `~/.agent-bot/data/inbound-images/` | 接收图片缓存 |
|
|
46
|
-
| `~/.agent-bot/logs/agent-bot.log`
|
|
46
|
+
| `~/.agent-bot/logs/agent-bot.YYYY-MM-DD.log` | 按天切分的结构化运行日志 |
|
|
47
47
|
|
|
48
48
|
配置文件优先级:
|
|
49
49
|
|
|
@@ -84,18 +84,19 @@ CLI 通过 Node.js 国际化能力读取系统 Locale。以 `zh` 开头的 Local
|
|
|
84
84
|
|
|
85
85
|
没有完整凭据时,初始化会启动飞书一键创建流程,并以文本和二维码显示验证链接。注册中的设备码不会恢复:如果进程在完整凭据持久化前退出,下次会重新创建应用。凭据持久化后会检查应用当前已发布版本;这一权限审计阶段中断后可以安全继续。
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
缺失配置分三阶段处理:
|
|
88
88
|
|
|
89
|
-
1.
|
|
89
|
+
1. 请求核心配置并轮询,直到基础消息能力生效
|
|
90
90
|
2. 请求其余可选配置。CLI 会先显示二维码,随后显示授权链接,然后立即开始最多 5 分钟的轮询。交互式终端只提供 `Y` 选项,用于跳过可选授权并继续;否则用户直接在浏览器中完成授权,轮询会持续进行
|
|
91
|
+
3. 仅在选择接收所有群消息时,最后请求需要手动配置并发布的 `im:message.group_msg`。这一步可输入 `Y` 跳过,等待超时也只返回部分配置结果,不会让初始化失败;仅 @ 响应模式会完全排除该权限
|
|
91
92
|
|
|
92
|
-
一键配置支持的内容会编码到 launcher 的 `addons`
|
|
93
|
+
一键配置支持的内容会编码到 launcher 的 `addons` 清单中。选择接收所有群消息时,手动权限 `im:message.group_msg` 不会放入该清单,因为飞书无法通过一键配置新增它。CLI 会在最后阶段显示二维码,以及当前应用已筛选该权限的开发者后台直达链接:
|
|
93
94
|
|
|
94
95
|
```text
|
|
95
96
|
https://open.feishu.cn/app/<appId>/auth?q=im%3Amessage.group_msg&op_from=openapi&token_type=tenant
|
|
96
97
|
```
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
用户需要手动新增权限、发布应用版本,并在需要时完成租户管理员审批。最后阶段会等待最多 5 分钟,在已发布版本中检测到该权限后完成;输入 `Y`、等待超时或没有完成发布都会返回部分配置结果,并提示机器人无法响应未 @ 它的普通群消息。
|
|
99
100
|
|
|
100
101
|
可选配置轮询失败或超时会返回部分配置结果,不会导致初始化失败。stdin 不是交互式终端时无法输入跳过指令,轮询会持续到配置生效或超时。验证链接和提示写入 stderr,因此 `--json` 的最终 stdout 仍可直接供程序读取。
|
|
101
102
|
|
|
@@ -223,7 +224,7 @@ AGENT_BOT_LARK_USER_OPEN_ID=<已保存的授权用户 open_id,可用时提供>
|
|
|
223
224
|
|
|
224
225
|
命令、卡片回调、进度卡和最终回答都保留在来源路由。
|
|
225
226
|
|
|
226
|
-
|
|
227
|
+
从已映射的用户消息、进度卡或最终回答创建飞书话题时,不会立即创建任务。斜杠命令可以在话题保持未绑定状态时执行;依赖当前任务的命令会返回绑定指引,不会操作父会话任务。收到第一条普通 Prompt 后,才会从关联的已完成 App Server turn 延迟创建分支;无法可靠确定来源 turn 时则创建全新任务。`/new` 也会直接创建全新任务,`/sessions` 或 `/switch` 可以绑定现有任务,均不会产生中间分支。
|
|
227
228
|
|
|
228
229
|
`/forkgroup` 会根据话题状态选择来源。话题尚未绑定任务,或者已绑定任务但尚未完成过自己的 turn 时,直接从话题原始锚点 turn fork,不创建中间话题任务。话题任务完成过 turn 后,使用本地持久化的最近完成 turn;更晚的执行中 turn 不会阻塞命令,也不会成为 fork 点。
|
|
229
230
|
|
|
@@ -303,8 +304,8 @@ Windows 下,CLI 在首次启动 Supervisor 前、Worker 在启动替换 Superv
|
|
|
303
304
|
|
|
304
305
|
Supervisor 的崩溃诊断文件按当前 Profile 隔离:
|
|
305
306
|
|
|
306
|
-
- `logs/supervisor.log` 持久记录 Worker PID、退出码、运行时长、重启延迟和诊断文件路径
|
|
307
|
-
- `logs/worker.stderr.log` 保存后台进程原本会丢失的 Node/V8 fatal
|
|
307
|
+
- `logs/supervisor.YYYY-MM-DD.log` 持久记录 Worker PID、退出码、运行时长、重启延迟和诊断文件路径
|
|
308
|
+
- `logs/worker.stderr.YYYY-MM-DD.log` 保存后台进程原本会丢失的 Node/V8 fatal 输出;两类诊断日志会按本地自然日切分,并在单日文件达到 10 MiB 时继续使用原有备份轮转
|
|
308
309
|
- `data/last-crash.json` 指向最近一次 Worker 异常退出,带时间戳的 `data/crash-reports/crash-*.json` 保留历史记录
|
|
309
310
|
- Node 能生成报告时,写入 `data/crash-reports/report.*.json`
|
|
310
311
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keyou007/agent-bot",
|
|
3
|
-
"version": "0.1.15-alpha.
|
|
3
|
+
"version": "0.1.15-alpha.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@keyou007/agent-bot",
|
|
9
|
-
"version": "0.1.15-alpha.
|
|
9
|
+
"version": "0.1.15-alpha.2",
|
|
10
10
|
"license": "GPL-3.0-only",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@agentclientprotocol/sdk": "1.2.1",
|
package/package.json
CHANGED
|
@@ -71,7 +71,6 @@ export const REQUIRED_FEISHU_CALLBACKS = ["card.action.trigger"] as const;
|
|
|
71
71
|
|
|
72
72
|
const CORE_FEISHU_SCOPES = new Set([
|
|
73
73
|
"application:application:self_manage",
|
|
74
|
-
"im:message.group_msg",
|
|
75
74
|
"im:message.p2p_msg:readonly",
|
|
76
75
|
"im:message:send_as_bot",
|
|
77
76
|
]);
|
|
@@ -287,7 +286,8 @@ async function completeOptionalFeishuConfiguration(
|
|
|
287
286
|
): Promise<EnsureFeishuAppConfigurationResult> {
|
|
288
287
|
let configuration = initialConfiguration;
|
|
289
288
|
let remaining = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
|
|
290
|
-
const
|
|
289
|
+
const launcherIgnoredScopes = new Set([...ignoredScopes, ...MANUAL_FEISHU_SCOPES]);
|
|
290
|
+
const requested = withoutIgnoredScopes(remaining, launcherIgnoredScopes);
|
|
291
291
|
if (hasMissingConfiguration(requested)) {
|
|
292
292
|
await requestMissingFeishuConfiguration(
|
|
293
293
|
credentials.appId,
|
|
@@ -305,7 +305,32 @@ async function completeOptionalFeishuConfiguration(
|
|
|
305
305
|
timeoutMs,
|
|
306
306
|
options.signal,
|
|
307
307
|
options.optionalSkipSignal,
|
|
308
|
-
|
|
308
|
+
launcherIgnoredScopes,
|
|
309
|
+
excludedScopes,
|
|
310
|
+
);
|
|
311
|
+
configuration = completed.configuration;
|
|
312
|
+
remaining = completed.remaining;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const manualMissing = manualMissingFeishuAppConfiguration(remaining);
|
|
317
|
+
if (hasMissingConfiguration(manualMissing)) {
|
|
318
|
+
await requestMissingFeishuConfiguration(
|
|
319
|
+
credentials.appId,
|
|
320
|
+
manualMissing,
|
|
321
|
+
true,
|
|
322
|
+
options.onVerification,
|
|
323
|
+
);
|
|
324
|
+
if (!options.manualPermissionSkipSignal?.aborted) {
|
|
325
|
+
const completed = await waitForManualFeishuConfiguration(
|
|
326
|
+
credentials,
|
|
327
|
+
configuration,
|
|
328
|
+
fetchImpl,
|
|
329
|
+
sleep,
|
|
330
|
+
pollIntervalMs,
|
|
331
|
+
timeoutMs,
|
|
332
|
+
options.signal,
|
|
333
|
+
options.manualPermissionSkipSignal,
|
|
309
334
|
excludedScopes,
|
|
310
335
|
);
|
|
311
336
|
configuration = completed.configuration;
|
|
@@ -320,6 +345,44 @@ async function completeOptionalFeishuConfiguration(
|
|
|
320
345
|
};
|
|
321
346
|
}
|
|
322
347
|
|
|
348
|
+
async function waitForManualFeishuConfiguration(
|
|
349
|
+
credentials: FeishuAppCredentials,
|
|
350
|
+
initialConfiguration: FeishuAppConfiguration,
|
|
351
|
+
fetchImpl: typeof globalThis.fetch,
|
|
352
|
+
sleep: (milliseconds: number) => Promise<void>,
|
|
353
|
+
pollIntervalMs: number,
|
|
354
|
+
timeoutMs: number,
|
|
355
|
+
signal?: AbortSignal,
|
|
356
|
+
manualPermissionSkipSignal?: AbortSignal,
|
|
357
|
+
excludedScopes: ReadonlySet<string> = new Set(),
|
|
358
|
+
): Promise<{
|
|
359
|
+
configuration: FeishuAppConfiguration;
|
|
360
|
+
remaining: MissingFeishuAppConfiguration;
|
|
361
|
+
}> {
|
|
362
|
+
let configuration = initialConfiguration;
|
|
363
|
+
let remaining = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
|
|
364
|
+
let remainingMs = timeoutMs;
|
|
365
|
+
while (remainingMs > 0 && hasMissingConfiguration(manualMissingFeishuAppConfiguration(remaining))) {
|
|
366
|
+
if (manualPermissionSkipSignal?.aborted) break;
|
|
367
|
+
const waitMs = Math.min(pollIntervalMs, remainingMs);
|
|
368
|
+
const waitResult = await sleepWithOptionalSkip(
|
|
369
|
+
sleep,
|
|
370
|
+
waitMs,
|
|
371
|
+
signal,
|
|
372
|
+
manualPermissionSkipSignal,
|
|
373
|
+
);
|
|
374
|
+
if (waitResult === "skipped") break;
|
|
375
|
+
remainingMs -= waitMs;
|
|
376
|
+
try {
|
|
377
|
+
configuration = await readFeishuAppConfiguration(credentials, fetchImpl, signal);
|
|
378
|
+
remaining = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
|
|
379
|
+
} catch (error) {
|
|
380
|
+
if (signal?.aborted) throw abortError(signal);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return { configuration, remaining };
|
|
384
|
+
}
|
|
385
|
+
|
|
323
386
|
async function waitForOptionalFeishuConfiguration(
|
|
324
387
|
credentials: FeishuAppCredentials,
|
|
325
388
|
initialConfiguration: FeishuAppConfiguration,
|
|
@@ -621,6 +684,16 @@ function coreMissingFeishuAppConfiguration(missing: MissingFeishuAppConfiguratio
|
|
|
621
684
|
};
|
|
622
685
|
}
|
|
623
686
|
|
|
687
|
+
function manualMissingFeishuAppConfiguration(
|
|
688
|
+
missing: MissingFeishuAppConfiguration,
|
|
689
|
+
): MissingFeishuAppConfiguration {
|
|
690
|
+
return {
|
|
691
|
+
scopes: missing.scopes.filter((scope) => MANUAL_FEISHU_SCOPES.has(scope)),
|
|
692
|
+
events: [],
|
|
693
|
+
callbacks: [],
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
|
|
624
697
|
function resolvedMissingConfiguration(
|
|
625
698
|
initial: MissingFeishuAppConfiguration,
|
|
626
699
|
remaining: MissingFeishuAppConfiguration,
|
package/src/cli.ts
CHANGED
|
@@ -2044,7 +2044,12 @@ function printFeishuConfigurationVerification(
|
|
|
2044
2044
|
"请添加已筛选的权限、发布应用版本,并在需要时完成租户管理员审批。\n",
|
|
2045
2045
|
));
|
|
2046
2046
|
}
|
|
2047
|
-
if (challenge.
|
|
2047
|
+
if (challenge.kind === "manual_scope") {
|
|
2048
|
+
process.stderr.write(cliText(
|
|
2049
|
+
"Waiting up to 5 minutes for this permission to appear in the published app version...\n",
|
|
2050
|
+
"将等待最多 5 分钟,直到该权限出现在已发布的应用版本中...\n",
|
|
2051
|
+
));
|
|
2052
|
+
} else if (challenge.blocking) {
|
|
2048
2053
|
process.stderr.write(cliText(
|
|
2049
2054
|
"Waiting for the core scopes and message event to become active...\n",
|
|
2050
2055
|
"正在等待核心权限和消息事件生效...\n",
|