shennian 0.2.108 → 0.2.110
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/dist/publish-build-manifest.json +63 -58
- package/dist/src/agents/model-registry/discovery.js +2 -2
- package/dist/src/agents/pi-context.d.ts +1 -1
- package/dist/src/agents/pi-context.js +3 -3
- package/dist/src/channels/runtime.d.ts +2 -0
- package/dist/src/channels/runtime.js +1 -1
- package/dist/src/channels/secret-registry.d.ts +2 -0
- package/dist/src/channels/wechat-channel/automation-lane.d.ts +12 -0
- package/dist/src/channels/wechat-channel/automation-lane.js +2 -1
- package/dist/src/channels/wechat-channel/client.d.ts +25 -2
- package/dist/src/channels/wechat-channel/client.js +1 -1
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +1 -1
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -1
- package/dist/src/channels/wechat-channel/helper-client.d.ts +2 -0
- package/dist/src/channels/wechat-channel/helper-client.js +3 -3
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +1 -1
- package/dist/src/channels/wechat-channel/observer.d.ts +9 -1
- package/dist/src/channels/wechat-channel/observer.js +7 -6
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +8 -0
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -1
- package/dist/src/channels/wechat-channel/runner.js +1 -1
- package/dist/src/channels/wechat-channel/runtime.d.ts +1 -0
- package/dist/src/channels/wechat-channel/runtime.js +1 -1
- package/dist/src/channels/wechat-channel/scheduler.d.ts +1 -1
- package/dist/src/channels/wechat-channel/scheduler.js +1 -1
- package/dist/src/channels/wechat-rpa/product-channel.d.ts +1 -0
- package/dist/src/channels/wechat-rpa/product-channel.js +4 -4
- package/dist/src/channels/wechat-rpa.d.ts +2 -0
- package/dist/src/channels/wechat-rpa.js +2 -2
- package/dist/src/commands/helper-runtime-official-download.d.ts +80 -0
- package/dist/src/commands/helper-runtime-official-download.js +1 -0
- package/dist/src/commands/runtime.d.ts +24 -0
- package/dist/src/commands/runtime.js +1 -1
- package/dist/src/commands/wechat/command.d.ts +1 -0
- package/dist/src/commands/wechat/command.js +1 -1
- package/dist/src/commands/wechat/ipc.js +1 -1
- package/dist/src/commands/wechat/output.js +3 -3
- package/dist/src/commands/wechat.d.ts +1 -1
- package/dist/src/commands/wechat.js +1 -1
- package/dist/src/devtools/wechat-channel-action-smoke.d.ts +3 -1
- package/dist/src/devtools/wechat-channel-action-smoke.js +9 -9
- package/dist/src/index.js +2 -2
- package/dist/src/manager/runtime.js +10 -10
- package/dist/src/native-fusion/service.d.ts +0 -10
- package/dist/src/native-fusion/service.js +2 -2
- package/dist/src/session/handlers/chat.js +2 -2
- package/dist/src/session/handlers/session-refresh.js +1 -1
- package/dist/src/session/handlers/wechat-helper-runtime.d.ts +31 -0
- package/dist/src/session/handlers/wechat-helper-runtime.js +1 -0
- package/dist/src/session/manager.d.ts +4 -1
- package/dist/src/session/manager.js +1 -1
- package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
- package/node_modules/@shennian/wire/dist/methods.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/src/agents/codex-control.d.ts +0 -35
- package/dist/src/agents/codex-control.js +0 -2
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 133,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian.js",
|
|
@@ -29,11 +29,6 @@
|
|
|
29
29
|
"beforeBytes": 11638,
|
|
30
30
|
"afterBytes": 6020
|
|
31
31
|
},
|
|
32
|
-
{
|
|
33
|
-
"file": "src/agents/codex-control.js",
|
|
34
|
-
"beforeBytes": 6674,
|
|
35
|
-
"afterBytes": 3673
|
|
36
|
-
},
|
|
37
32
|
{
|
|
38
33
|
"file": "src/agents/codex-utils.js",
|
|
39
34
|
"beforeBytes": 7479,
|
|
@@ -91,8 +86,8 @@
|
|
|
91
86
|
},
|
|
92
87
|
{
|
|
93
88
|
"file": "src/agents/model-registry/discovery.js",
|
|
94
|
-
"beforeBytes":
|
|
95
|
-
"afterBytes":
|
|
89
|
+
"beforeBytes": 6870,
|
|
90
|
+
"afterBytes": 3204
|
|
96
91
|
},
|
|
97
92
|
{
|
|
98
93
|
"file": "src/agents/model-registry/parsers.js",
|
|
@@ -131,8 +126,8 @@
|
|
|
131
126
|
},
|
|
132
127
|
{
|
|
133
128
|
"file": "src/agents/pi-context.js",
|
|
134
|
-
"beforeBytes":
|
|
135
|
-
"afterBytes":
|
|
129
|
+
"beforeBytes": 8076,
|
|
130
|
+
"afterBytes": 4816
|
|
136
131
|
},
|
|
137
132
|
{
|
|
138
133
|
"file": "src/agents/pi.js",
|
|
@@ -161,8 +156,8 @@
|
|
|
161
156
|
},
|
|
162
157
|
{
|
|
163
158
|
"file": "src/channels/runtime.js",
|
|
164
|
-
"beforeBytes":
|
|
165
|
-
"afterBytes":
|
|
159
|
+
"beforeBytes": 30001,
|
|
160
|
+
"afterBytes": 16436
|
|
166
161
|
},
|
|
167
162
|
{
|
|
168
163
|
"file": "src/channels/secret-registry.js",
|
|
@@ -181,13 +176,13 @@
|
|
|
181
176
|
},
|
|
182
177
|
{
|
|
183
178
|
"file": "src/channels/wechat-channel/automation-lane.js",
|
|
184
|
-
"beforeBytes":
|
|
185
|
-
"afterBytes":
|
|
179
|
+
"beforeBytes": 4299,
|
|
180
|
+
"afterBytes": 2233
|
|
186
181
|
},
|
|
187
182
|
{
|
|
188
183
|
"file": "src/channels/wechat-channel/client.js",
|
|
189
|
-
"beforeBytes":
|
|
190
|
-
"afterBytes":
|
|
184
|
+
"beforeBytes": 8067,
|
|
185
|
+
"afterBytes": 4463
|
|
191
186
|
},
|
|
192
187
|
{
|
|
193
188
|
"file": "src/channels/wechat-channel/cooldown.js",
|
|
@@ -221,13 +216,13 @@
|
|
|
221
216
|
},
|
|
222
217
|
{
|
|
223
218
|
"file": "src/channels/wechat-channel/helper-assets.js",
|
|
224
|
-
"beforeBytes":
|
|
225
|
-
"afterBytes":
|
|
219
|
+
"beforeBytes": 17193,
|
|
220
|
+
"afterBytes": 9150
|
|
226
221
|
},
|
|
227
222
|
{
|
|
228
223
|
"file": "src/channels/wechat-channel/helper-client.js",
|
|
229
|
-
"beforeBytes":
|
|
230
|
-
"afterBytes":
|
|
224
|
+
"beforeBytes": 31826,
|
|
225
|
+
"afterBytes": 16459
|
|
231
226
|
},
|
|
232
227
|
{
|
|
233
228
|
"file": "src/channels/wechat-channel/helper-protocol.js",
|
|
@@ -266,8 +261,8 @@
|
|
|
266
261
|
},
|
|
267
262
|
{
|
|
268
263
|
"file": "src/channels/wechat-channel/observer.js",
|
|
269
|
-
"beforeBytes":
|
|
270
|
-
"afterBytes":
|
|
264
|
+
"beforeBytes": 102627,
|
|
265
|
+
"afterBytes": 47836
|
|
271
266
|
},
|
|
272
267
|
{
|
|
273
268
|
"file": "src/channels/wechat-channel/outbound-ledger.js",
|
|
@@ -276,8 +271,8 @@
|
|
|
276
271
|
},
|
|
277
272
|
{
|
|
278
273
|
"file": "src/channels/wechat-channel/outbound-sender.js",
|
|
279
|
-
"beforeBytes":
|
|
280
|
-
"afterBytes":
|
|
274
|
+
"beforeBytes": 21306,
|
|
275
|
+
"afterBytes": 10998
|
|
281
276
|
},
|
|
282
277
|
{
|
|
283
278
|
"file": "src/channels/wechat-channel/pacing.js",
|
|
@@ -291,18 +286,18 @@
|
|
|
291
286
|
},
|
|
292
287
|
{
|
|
293
288
|
"file": "src/channels/wechat-channel/runner.js",
|
|
294
|
-
"beforeBytes":
|
|
295
|
-
"afterBytes":
|
|
289
|
+
"beforeBytes": 14776,
|
|
290
|
+
"afterBytes": 7286
|
|
296
291
|
},
|
|
297
292
|
{
|
|
298
293
|
"file": "src/channels/wechat-channel/runtime.js",
|
|
299
|
-
"beforeBytes":
|
|
300
|
-
"afterBytes":
|
|
294
|
+
"beforeBytes": 3768,
|
|
295
|
+
"afterBytes": 1755
|
|
301
296
|
},
|
|
302
297
|
{
|
|
303
298
|
"file": "src/channels/wechat-channel/scheduler.js",
|
|
304
|
-
"beforeBytes":
|
|
305
|
-
"afterBytes":
|
|
299
|
+
"beforeBytes": 24204,
|
|
300
|
+
"afterBytes": 10896
|
|
306
301
|
},
|
|
307
302
|
{
|
|
308
303
|
"file": "src/channels/wechat-channel/vector-store.js",
|
|
@@ -326,13 +321,13 @@
|
|
|
326
321
|
},
|
|
327
322
|
{
|
|
328
323
|
"file": "src/channels/wechat-rpa/product-channel.js",
|
|
329
|
-
"beforeBytes":
|
|
330
|
-
"afterBytes":
|
|
324
|
+
"beforeBytes": 17962,
|
|
325
|
+
"afterBytes": 9649
|
|
331
326
|
},
|
|
332
327
|
{
|
|
333
328
|
"file": "src/channels/wechat-rpa.js",
|
|
334
|
-
"beforeBytes":
|
|
335
|
-
"afterBytes":
|
|
329
|
+
"beforeBytes": 55613,
|
|
330
|
+
"afterBytes": 29151
|
|
336
331
|
},
|
|
337
332
|
{
|
|
338
333
|
"file": "src/channels/wecom.js",
|
|
@@ -364,6 +359,11 @@
|
|
|
364
359
|
"beforeBytes": 6503,
|
|
365
360
|
"afterBytes": 4455
|
|
366
361
|
},
|
|
362
|
+
{
|
|
363
|
+
"file": "src/commands/helper-runtime-official-download.js",
|
|
364
|
+
"beforeBytes": 12608,
|
|
365
|
+
"afterBytes": 6718
|
|
366
|
+
},
|
|
367
367
|
{
|
|
368
368
|
"file": "src/commands/manager.js",
|
|
369
369
|
"beforeBytes": 17401,
|
|
@@ -381,8 +381,8 @@
|
|
|
381
381
|
},
|
|
382
382
|
{
|
|
383
383
|
"file": "src/commands/runtime.js",
|
|
384
|
-
"beforeBytes":
|
|
385
|
-
"afterBytes":
|
|
384
|
+
"beforeBytes": 34179,
|
|
385
|
+
"afterBytes": 19155
|
|
386
386
|
},
|
|
387
387
|
{
|
|
388
388
|
"file": "src/commands/tools.js",
|
|
@@ -396,8 +396,8 @@
|
|
|
396
396
|
},
|
|
397
397
|
{
|
|
398
398
|
"file": "src/commands/wechat/command.js",
|
|
399
|
-
"beforeBytes":
|
|
400
|
-
"afterBytes":
|
|
399
|
+
"beforeBytes": 7941,
|
|
400
|
+
"afterBytes": 4755
|
|
401
401
|
},
|
|
402
402
|
{
|
|
403
403
|
"file": "src/commands/wechat/direct.js",
|
|
@@ -411,8 +411,8 @@
|
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
413
|
"file": "src/commands/wechat/ipc.js",
|
|
414
|
-
"beforeBytes":
|
|
415
|
-
"afterBytes":
|
|
414
|
+
"beforeBytes": 8947,
|
|
415
|
+
"afterBytes": 4830
|
|
416
416
|
},
|
|
417
417
|
{
|
|
418
418
|
"file": "src/commands/wechat/operations.js",
|
|
@@ -421,8 +421,8 @@
|
|
|
421
421
|
},
|
|
422
422
|
{
|
|
423
423
|
"file": "src/commands/wechat/output.js",
|
|
424
|
-
"beforeBytes":
|
|
425
|
-
"afterBytes":
|
|
424
|
+
"beforeBytes": 14154,
|
|
425
|
+
"afterBytes": 8863
|
|
426
426
|
},
|
|
427
427
|
{
|
|
428
428
|
"file": "src/commands/wechat/types.js",
|
|
@@ -436,8 +436,8 @@
|
|
|
436
436
|
},
|
|
437
437
|
{
|
|
438
438
|
"file": "src/commands/wechat.js",
|
|
439
|
-
"beforeBytes":
|
|
440
|
-
"afterBytes":
|
|
439
|
+
"beforeBytes": 429,
|
|
440
|
+
"afterBytes": 325
|
|
441
441
|
},
|
|
442
442
|
{
|
|
443
443
|
"file": "src/config/index.js",
|
|
@@ -451,8 +451,8 @@
|
|
|
451
451
|
},
|
|
452
452
|
{
|
|
453
453
|
"file": "src/devtools/wechat-channel-action-smoke.js",
|
|
454
|
-
"beforeBytes":
|
|
455
|
-
"afterBytes":
|
|
454
|
+
"beforeBytes": 74169,
|
|
455
|
+
"afterBytes": 38722
|
|
456
456
|
},
|
|
457
457
|
{
|
|
458
458
|
"file": "src/devtools/wechat-channel-download-report.js",
|
|
@@ -496,8 +496,8 @@
|
|
|
496
496
|
},
|
|
497
497
|
{
|
|
498
498
|
"file": "src/index.js",
|
|
499
|
-
"beforeBytes":
|
|
500
|
-
"afterBytes":
|
|
499
|
+
"beforeBytes": 17034,
|
|
500
|
+
"afterBytes": 8527
|
|
501
501
|
},
|
|
502
502
|
{
|
|
503
503
|
"file": "src/log-reporter.js",
|
|
@@ -516,8 +516,8 @@
|
|
|
516
516
|
},
|
|
517
517
|
{
|
|
518
518
|
"file": "src/manager/runtime.js",
|
|
519
|
-
"beforeBytes":
|
|
520
|
-
"afterBytes":
|
|
519
|
+
"beforeBytes": 60524,
|
|
520
|
+
"afterBytes": 31029
|
|
521
521
|
},
|
|
522
522
|
{
|
|
523
523
|
"file": "src/native-fusion/config.js",
|
|
@@ -541,8 +541,8 @@
|
|
|
541
541
|
},
|
|
542
542
|
{
|
|
543
543
|
"file": "src/native-fusion/service.js",
|
|
544
|
-
"beforeBytes":
|
|
545
|
-
"afterBytes":
|
|
544
|
+
"beforeBytes": 7549,
|
|
545
|
+
"afterBytes": 3456
|
|
546
546
|
},
|
|
547
547
|
{
|
|
548
548
|
"file": "src/native-fusion/state.js",
|
|
@@ -581,8 +581,8 @@
|
|
|
581
581
|
},
|
|
582
582
|
{
|
|
583
583
|
"file": "src/session/handlers/chat.js",
|
|
584
|
-
"beforeBytes":
|
|
585
|
-
"afterBytes":
|
|
584
|
+
"beforeBytes": 30739,
|
|
585
|
+
"afterBytes": 13936
|
|
586
586
|
},
|
|
587
587
|
{
|
|
588
588
|
"file": "src/session/handlers/control.js",
|
|
@@ -596,8 +596,8 @@
|
|
|
596
596
|
},
|
|
597
597
|
{
|
|
598
598
|
"file": "src/session/handlers/session-refresh.js",
|
|
599
|
-
"beforeBytes":
|
|
600
|
-
"afterBytes":
|
|
599
|
+
"beforeBytes": 963,
|
|
600
|
+
"afterBytes": 451
|
|
601
601
|
},
|
|
602
602
|
{
|
|
603
603
|
"file": "src/session/handlers/skills.js",
|
|
@@ -614,10 +614,15 @@
|
|
|
614
614
|
"beforeBytes": 8800,
|
|
615
615
|
"afterBytes": 4161
|
|
616
616
|
},
|
|
617
|
+
{
|
|
618
|
+
"file": "src/session/handlers/wechat-helper-runtime.js",
|
|
619
|
+
"beforeBytes": 6999,
|
|
620
|
+
"afterBytes": 3768
|
|
621
|
+
},
|
|
617
622
|
{
|
|
618
623
|
"file": "src/session/manager.js",
|
|
619
|
-
"beforeBytes":
|
|
620
|
-
"afterBytes":
|
|
624
|
+
"beforeBytes": 15312,
|
|
625
|
+
"afterBytes": 7880
|
|
621
626
|
},
|
|
622
627
|
{
|
|
623
628
|
"file": "src/session/projection.js",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createInterface as
|
|
2
|
-
`,p=>{p&&(clearTimeout(u),r.delete(o),s(p))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function
|
|
1
|
+
import{createInterface as f}from"node:readline";import{resolveBuiltinCommand as c,spawnResolvedCommand as v}from"../command-spec.js";import{fallbackClaudeAliasModels as M,discoverClaudeAliasModelsFromEnv as w,fallbackGeminiModels as C,parseCodexAppServerModels as y,parseCursorModels as h,parseOpenCodeModels as g}from"./parsers.js";import{runResolvedCommand as m}from"./runner.js";import{DISCOVERY_WORKDIR as E}from"./types.js";import{buildAgentProcessEnv as x,readLatestUserEnv as O}from"../../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as R}from"../codex-utils.js";function l(e,r,o,i,a,n){return e.stdin?new Promise((t,s)=>{const u=setTimeout(()=>{r.delete(o),s(new Error(`codex app-server request timed out: ${i}`))},n);r.set(o,{resolve:t,reject:s,timer:u}),e.stdin.write(`${JSON.stringify({id:o,method:i,params:a})}
|
|
2
|
+
`,p=>{p&&(clearTimeout(u),r.delete(o),s(p))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function S(e){const r=v(e,["app-server","--listen","stdio://"],{cwd:E,stdio:["pipe","pipe","pipe"],env:x({NO_COLOR:"1"})}),o=new Map;let i=1;f({input:r.stdout}).on("line",n=>{if(!n.trim())return;let t;try{t=JSON.parse(n)}catch{return}if(t.id==null)return;const s=o.get(t.id);s&&(clearTimeout(s.timer),o.delete(t.id),t.error?s.reject(new Error(t.error.message||`codex app-server error ${t.error.code??""}`.trim())):s.resolve(t.result))});try{await l(r,o,i++,"initialize",{clientInfo:R,capabilities:{experimentalApi:!0}},1e4);const[n,t]=await Promise.all([l(r,o,i++,"model/list",{},15e3),l(r,o,i++,"config/read",{},15e3).catch(()=>null)]),s=typeof t=="object"&&t!==null&&"config"in t?t.config:void 0;return y({...typeof n=="object"&&n!==null?n:{},config:s})}finally{for(const[n,t]of o)clearTimeout(t.timer),t.reject(new Error("codex app-server stopped")),o.delete(n);r.kill("SIGTERM"),setTimeout(()=>r.kill("SIGKILL"),1e3).unref()}}async function A(){const e=c("cursor");if(!e)return[];const r=await m(e,["--list-models"]);return h(r.stdout)}async function I(){const e=c("opencode");if(!e)return[];const r=await m(e,["models"]);return g(r.stdout)}async function T(){if(!c("claude"))return[];const e=w(O());return e.length>0?e:M()}async function _(){const e=c("codex");return e?await S(e).catch(()=>[]):[]}async function b(){return c("gemini")?C():[]}const d=[{id:"qwen3.7-max",name:"Qwen 3.7 Max",provider:"dashscope",isDefault:!0}],k=[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}];async function P(e){if(!e.serverUrl||!e.authToken)return d;try{const r=await fetch(`${e.serverUrl.replace(/\/$/,"")}/api/models`,{headers:{Authorization:`Bearer ${e.authToken}`}});if(!r.ok)return d;const o=await r.json(),i=(o.models??[]).map(a=>({id:a.id,name:a.name?.trim()||a.id,provider:a.provider,isDefault:a.id===o.default}));return i.length>0?i:d}catch{return d}}async function D(e,r){switch(e){case"claude":return T();case"codex":return _();case"gemini":return b();case"cursor":return A();case"openclaw":return[];case"opencode":return I();case"pi":return P(r);case"manager":return k}}async function F(e,r){return e.type.startsWith("custom:")?e.models??[]:D(e.type,r)}export{F as discoverModelsForAgent};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentMessage } from '@mariozechner/pi-agent-core';
|
|
2
2
|
import type { Model } from '@mariozechner/pi-ai';
|
|
3
|
-
export declare const PI_DEFAULT_MODEL_ID = "qwen3.
|
|
3
|
+
export declare const PI_DEFAULT_MODEL_ID = "qwen3.7-max";
|
|
4
4
|
type ShellCommandSpec = {
|
|
5
5
|
file: string;
|
|
6
6
|
args: string[];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import u from"node:fs";import l from"node:path";import{resolveShennianPath as
|
|
1
|
+
import u from"node:fs";import l from"node:path";import{resolveShennianPath as h}from"../config/index.js";const S="qwen3.7-max";function w(e,t=process.platform){return t==="win32"?{file:"powershell.exe",args:["-NoLogo","-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command",e],shell:"powershell"}:{file:"bash",args:["-c",e],shell:"bash"}}function d(e=S,t={}){return{id:e,name:e,api:"openai-completions",provider:t.provider??"shennian-proxy",baseUrl:t.baseUrl??"",reasoning:!1,input:["text","image"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:128e3,maxTokens:8192,...t.compat?{compat:t.compat}:{}}}const O=`\u4F60\u662F\u795E\u5FF5\u5185\u7F6E\u7F16\u7A0B\u52A9\u624B\uFF0C\u8FD0\u884C\u5728\u7528\u6237\u672C\u5730\u673A\u5668\u4E0A\u3002
|
|
2
2
|
\u4F60\u53EF\u4EE5\u8BFB\u5199\u6587\u4EF6\u3001\u6267\u884C shell \u547D\u4EE4\u3001\u5E2E\u52A9\u7528\u6237\u5B8C\u6210\u7F16\u7A0B\u548C\u7CFB\u7EDF\u7BA1\u7406\u4EFB\u52A1\u3002
|
|
3
3
|
\u5DE5\u4F5C\u76EE\u5F55\u5DF2\u8BBE\u7F6E\uFF0C\u64CD\u4F5C\u6587\u4EF6\u65F6\u4F7F\u7528\u76F8\u5BF9\u8DEF\u5F84\u6216\u7EDD\u5BF9\u8DEF\u5F84\u5747\u53EF\u3002
|
|
4
4
|
\u5F53\u524D shell \u4F1A\u968F\u64CD\u4F5C\u7CFB\u7EDF\u9009\u62E9\uFF1AWindows \u4F7F\u7528 PowerShell\uFF0CmacOS/Linux \u4F7F\u7528 bash\u3002Windows \u4E0B\u9700\u8981\u771F\u5B9E curl \u65F6\u4F7F\u7528 curl.exe\uFF0C\u907F\u514D PowerShell \u7684 curl \u522B\u540D\u3002
|
|
5
|
-
\u4FDD\u6301\u56DE\u590D\u7B80\u6D01\u3001\u51C6\u786E\uFF0C\u4E2D\u6587\u56DE\u590D\u3002`,
|
|
5
|
+
\u4FDD\u6301\u56DE\u590D\u7B80\u6D01\u3001\u51C6\u786E\uFF0C\u4E2D\u6587\u56DE\u590D\u3002`,x=24e3;function E(e){let t=l.resolve(e||process.cwd());try{const n=u.existsSync(t)?u.statSync(t):null;n&&!n.isDirectory()&&(t=l.dirname(t))}catch{}for(;;){const n=l.join(t,"AGENTS.md");if(u.existsSync(n))return n;const o=l.dirname(t);if(o===t)return null;t=o}}function $(e){const t=E(e);if(!t)return null;try{const n=u.readFileSync(t,"utf-8").trim();if(!n)return null;const o=n.length>x?`${n.slice(0,x)}
|
|
6
6
|
|
|
7
7
|
...\uFF08AGENTS.md \u5DF2\u622A\u65AD\uFF09`:n;return`# AGENTS.md instructions for ${l.dirname(t)}
|
|
8
8
|
|
|
9
|
-
${o}`}catch{return null}}const P=9e4,b=6,N=
|
|
9
|
+
${o}`}catch{return null}}const P=9e4,b=6,N=h("sessions"),k="summary.json",C="snapshot.json",L="messages.jsonl",j="pi-context.json";function R(e){let t=0;for(const n of e)t+=JSON.stringify(n).length;return Math.ceil(t/3)}function D(e){const t=[];for(const n of e){const o=n,s=String(o.role??"unknown");if(Array.isArray(o.content)){for(const r of o.content)if(r.type==="text"&&typeof r.text=="string")t.push(`[${s}] ${r.text.slice(0,500)}`);else if(r.type==="toolCall"){const c=typeof r.name=="string"?r.name:typeof r.toolName=="string"?r.toolName:"tool",i=r.arguments??r.args??{};t.push(`[${s}] tool:${c}(${JSON.stringify(i).slice(0,200)})`)}}}return t.join(`
|
|
10
10
|
`)}function I(e){return JSON.parse(JSON.stringify(e))}function J(e){return l.join(N,e)}function A(e){if(!e||typeof e!="object")return null;const t=e;if(t.type==="text"&&typeof t.text=="string")return t.text;if(t.type==="thinking"&&typeof t.thinking=="string")return`[thinking] ${t.thinking}`;if(t.type==="toolCall"){const n=typeof t.name=="string"?t.name:typeof t.toolName=="string"?t.toolName:"tool",o=t.arguments??t.args??{};return`[toolCall] ${n}(${JSON.stringify(o).slice(0,300)})`}return t.type==="image"&&typeof t.mimeType=="string"?`[image] ${t.mimeType}`:null}function G(e,t){const n=[];for(const r of t){const c=String(r.role??"unknown"),i=Array.isArray(r.content)?r.content:[];for(const p of i){const a=A(p);a&&n.push(`[${c}] ${a}`)}}const s=n.slice(-8).join(`
|
|
11
11
|
`).trim()||e?.trim()||null;return s?s.length>2e3?s.slice(s.length-2e3):s:null}function F(e,t){const n=Math.min(e.length,t.length);for(let o=0;o<n;o++)if(JSON.stringify(e[o])!==JSON.stringify(t[o]))return o;return n}async function U(e,t,n){const o=await fetch(`${e}/api/stream`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({model:d("qwen-plus"),context:{messages:[{role:"user",content:[{type:"text",text:n}]}]},options:{temperature:.3,maxTokens:500}})});if(!o.ok||!o.body)return null;const s=o.body.getReader(),r=new TextDecoder,c=[];let i="";for(;;){const{done:p,value:a}=await s.read();if(p)break;i+=r.decode(a,{stream:!0});const m=i.split(`
|
|
12
12
|
`);i=m.pop()??"";for(const g of m){if(!g.startsWith("data: "))continue;const y=g.slice(6).trim();if(!y)continue;const f=JSON.parse(y);f.type==="text_delta"&&typeof f.delta=="string"&&c.push(f.delta)}}return c.join("").trim()||null}export{P as CONTEXT_TOKEN_THRESHOLD,b as KEEP_RECENT_MESSAGES,j as LEGACY_SUMMARY_FILENAME,L as MESSAGES_FILENAME,S as PI_DEFAULT_MODEL_ID,C as SNAPSHOT_FILENAME,k as SUMMARY_FILENAME,O as SYSTEM_PROMPT,G as buildRollingSummary,w as buildShellCommandSpec,I as cloneMessages,d as createPiModel,R as estimateTokens,E as findAgentsMd,J as getSessionDir,$ as loadAgentsMdInstructions,F as longestCommonPrefixLength,D as messagesToText,U as requestProxySummary};
|
|
@@ -117,6 +117,8 @@ export declare class ChannelRuntime {
|
|
|
117
117
|
downloadAttachments?: boolean;
|
|
118
118
|
downloadAttachmentsDir?: string;
|
|
119
119
|
selfNickname?: string;
|
|
120
|
+
selfTriggerMarker?: string;
|
|
121
|
+
deferInitialPoll?: boolean;
|
|
120
122
|
privacyConsentAccepted?: boolean;
|
|
121
123
|
flowScriptPath?: string;
|
|
122
124
|
}): Promise<ExternalChannelView>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import v from"node:crypto";import g from"node:fs";import u from"node:path";import{ChannelConfigRegistry as M}from"./registry.js";import{ChannelSecretRegistry as N}from"./secret-registry.js";import{WeComChannelAdapter as D}from"./wecom.js";import{WeChatRpaChannelAdapter as B}from"./wechat-rpa.js";import{ExternalWebSocketChannelAdapter as x}from"./websocket.js";import{splitExternalReplyText as F}from"./reply-split.js";class J{onExternalMessage;createReplyTarget;configs=new M;secrets=new N;adapters=new Map;completedReplyKeys=new Map;recentMessages=new Map;constructor(e,t,s={}){this.onExternalMessage=e,this.createReplyTarget=t;const o=new D(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(o.type,o);const r=new x(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(r.type,r);const i=new B(a=>this.ingest(a),{createProductRunner:s.createWeChatRpaProductRunner,automationLane:s.weChatAutomationLane});this.adapters.set(i.type,i)}async start(){for(const e of this.configs.list().filter(t=>t.enabled))await this.adapters.get(e.type)?.connect(e).catch(()=>{})}async stop(){for(const e of this.configs.list())await this.adapters.get(e.type)?.disconnect(e).catch(()=>{})}ingest(e){const t=this.findRecentMessageDuplicate(e);if(t)return t;const s=this.configs.get(e.channelId),o=e.managerSessionId??s?.sessionId??s?.managerSessionId;if(!o)throw new Error(`No session bound for channel ${e.channelId}`);const r=e.replyTarget||this.createReplyTarget({managerSessionId:o,channelId:e.channelId,conversationId:e.conversationId,messageId:e.messageId}),i={...e,replyTarget:r};return this.onExternalMessage(o,i),this.recordRecentMessage(i),i}async reply(e){const t=this.configs.get(e.channelId);if(!t)return{ok:!1,error:`Unknown channel: ${e.channelId}`};if((t.sessionId??t.managerSessionId)!==e.managerSessionId)return{ok:!1,error:"Channel is not bound to this session"};const s=this.adapters.get(t.type);if(!s)return{ok:!1,error:`Unsupported channel type: ${t.type}`};try{const o=W(t.type,e);if(!o.length)return{ok:!1,error:"Reply text or attachment is required"};let r=!1;for(const i of o){const a=i.idempotencyKey;if(a&&this.isReplyCompleted(t,e.conversationId,a))continue;const c=await s.send(t,{...e,...i});if(c?.status==="queued"){r=!0;continue}if(c?.status==="manual-review")return{ok:!1,error:c.reason||"Reply requires manual review before retry"};a&&this.markReplyCompleted(t,e.conversationId,a)}return r?{ok:!0,pending:!0}:{ok:!0}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}}isReplyCompleted(e,t,s){return this.loadReplyCompletionSet(e).has(A(e.id,t,s))}markReplyCompleted(e,t,s){const o=this.loadReplyCompletionSet(e);o.add(A(e.id,t,s));try{$(e.workDir,o)}catch{}}loadReplyCompletionSet(e){const t=u.resolve(e.workDir),s=this.completedReplyKeys.get(t);if(s)return s;const o=T(e.workDir);return this.completedReplyKeys.set(t,o),o}async getDefaultReplyTarget(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)throw new Error("No enabled external channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.defaultConversation)throw new Error(`External channel ${t.type} has no default conversation`);const o=await s.defaultConversation(t);return{channelId:t.id,conversationId:o.conversationId}}getManagerChannel(e,t,s={}){const o=this.configs.list().filter(c=>(c.sessionId??c.managerSessionId)===e&&c.type===t),r=o.find(c=>c.enabled)??o.at(-1);if(!r)return null;const i=this.secrets.get(r.secretRef),a=this.adapters.get(r.type)?.runtimeStatus?.(r)??{};return{id:r.id,type:r.type,name:r.name,sessionId:r.sessionId??r.managerSessionId,managerSessionId:r.managerSessionId,workDir:r.workDir,agentType:r.agentType,agentSessionId:r.agentSessionId,modelId:r.modelId,enabled:r.enabled,wsUrl:i?.wsUrl??"",token:s.includeSecret?i?.token??"":"",tokenConfigured:!!i?.token,canReply:!!i?.canReply,systemPrompt:typeof i?.systemPrompt=="string"?i.systemPrompt:"",...C(i),...a}}getChannelById(e,t={}){const s=this.configs.get(e);if(!s)return null;const o=this.secrets.get(s.secretRef),r=this.adapters.get(s.type)?.runtimeStatus?.(s)??{};return{id:s.id,type:s.type,name:s.name,sessionId:s.sessionId??s.managerSessionId,managerSessionId:s.managerSessionId,workDir:s.workDir,agentType:s.agentType,agentSessionId:s.agentSessionId,modelId:s.modelId,enabled:s.enabled,wsUrl:o?.wsUrl??"",token:t.includeSecret?o?.token??"":"",tokenConfigured:!!o?.token,canReply:!!o?.canReply,systemPrompt:typeof o?.systemPrompt=="string"?o.systemPrompt:"",...C(o),...r}}getChannelStatusById(e){const t=this.configs.get(e);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}getManagerChannelStatus(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}listManagerChannelStatuses(){return this.configs.list().filter(e=>e.enabled).map(e=>({managerSessionId:e.sessionId??e.managerSessionId,status:this.getManagerChannelStatus(e.sessionId??e.managerSessionId)})).filter(e=>!!e.status)}listManagerExternalChannels(e){return this.configs.list().filter(t=>t.enabled&&(t.sessionId??t.managerSessionId)===e).map(t=>{const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}})}async syncManagerWeChatRpaChannel(e){const t=this.configs.list().find(i=>i.enabled&&i.type==="wechat-rpa"&&(i.sessionId??i.managerSessionId)===e);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.syncNow)throw new Error("WeChat RPA channel does not support manual sync");const o=Date.now()-120*1e3,r=K(await s.syncNow(t)??[],this.getRecentMessages(t.id,o));return{channel:this.getManagerChannel(e,"wechat-rpa",{includeSecret:!0}),messages:r}}async cancelManagerWeChatRpaOutbound(e){const t=this.configs.list().find(r=>r.enabled&&r.type==="wechat-rpa"&&(r.sessionId??r.managerSessionId)===e.managerSessionId);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.cancelOutbound)throw new Error("WeChat RPA channel does not support outbound cancellation");const o=await s.cancelOutbound(t,{idempotencyKey:e.idempotencyKey,replyId:e.replyId,reason:e.reason});return{cancelled:o.cancelled,status:o.status,channel:this.getManagerChannel(e.managerSessionId,"wechat-rpa",{includeSecret:!0})}}recordRecentMessage(e){const t=this.recentMessages.get(e.channelId)??[];this.findRecentMessageDuplicate(e)||(t.push(e),this.recentMessages.set(e.channelId,t.slice(-50)))}findRecentMessageDuplicate(e){const t=I(e);return t?(this.recentMessages.get(e.channelId)??[]).find(o=>I(o)===t)??null:null}getRecentMessages(e,t){return(this.recentMessages.get(e)??[]).filter(o=>{const r=Date.parse(o.receivedAt);return!Number.isFinite(r)||r>=t})}async upsertManagerChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r={id:e.id,type:e.type,name:e.name?.trim()||t?.name||"\u5916\u90E8\u6D88\u606F\u901A\u9053",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},i=this.secrets.get(r.secretRef),a=e.wsUrl?.trim()||i?.wsUrl||"",c=e.token?.trim()||i?.token||"",p=e.canReply??i?.canReply??!1,m=e.systemPrompt??(typeof i?.systemPrompt=="string"?i.systemPrompt:"");if(r.enabled&&(!a||!c))throw new Error("WebSocket \u5730\u5740\u548C Token \u5FC5\u586B");const f=s.filter(l=>l.id!==r.id).map(l=>(l.sessionId??l.managerSessionId)===o&&l.type===e.type?{...l,enabled:!1}:l);f.push(r),this.configs.replaceAll(f),(a||c)&&this.secrets.upsert(r.secretRef,{type:"websocket",wsUrl:a,token:c,canReply:p,systemPrompt:m});const d=this.adapters.get(r.type);for(const l of s)(l.sessionId??l.managerSessionId)===o&&l.type===e.type&&l.enabled&&await this.adapters.get(l.type)?.disconnect(l).catch(()=>{});return r.enabled&&d?.connect(r).catch(()=>{}),this.getManagerChannel(o,e.type,{includeSecret:!0})}async upsertManagerWeChatRpaChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r=w(e.groups);if(e.enabled&&!r.length)throw new Error("WeChat RPA \u81F3\u5C11\u9700\u8981\u914D\u7F6E\u4E00\u4E2A\u7FA4");if(e.enabled&&r.length>1)throw new Error("WeChat RPA \u6BCF\u4E2A\u5BF9\u8BDD\u53EA\u80FD\u7ED1\u5B9A\u4E00\u4E2A\u7FA4");const i={id:e.id,type:"wechat-rpa",name:e.name?.trim()||t?.name||"\u672C\u673A\u5FAE\u4FE1 RPA",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},a=this.secrets.get(i.secretRef),c=e.source||(a?.source==="wechat-channel"||a?.source==="macos-probe"||a?.source==="fixture-jsonl"||a?.source==="macos-flow"||a?.source==="windows-visual-flow"||a?.source==="wechat-rpa-lab"?a.source:E());if(e.enabled&&c==="windows-visual-flow")throw new Error("\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF1BmacOS \u548C Windows \u6B63\u5F0F\u901A\u9053\u90FD\u4F7F\u7528 wechat-channel");const p=e.privacyConsentAccepted??!!a?.privacyConsentAccepted;if(e.enabled&&!p)throw new Error("\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743");const m=s.filter(d=>d.id!==i.id).map(d=>(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"?{...d,enabled:!1}:d);m.push(i),this.configs.replaceAll(m),this.secrets.upsert(i.secretRef,{type:"wechat-rpa",source:c,groups:r,pollIntervalMs:R(e.pollIntervalMs,a?.pollIntervalMs),recentLimit:R(e.recentLimit,a?.recentLimit),idleSeconds:R(e.idleSeconds,a?.idleSeconds),forceForeground:e.forceForeground??(a?.forceForeground===void 0?!0:!!a.forceForeground),noRestore:e.noRestore??(a?.noRestore===void 0?!0:!!a.noRestore),downloadAttachments:e.downloadAttachments??(a?.downloadAttachments===void 0?!0:!!a.downloadAttachments),downloadAttachmentsDir:e.downloadAttachmentsDir?.trim()||b(a?.downloadAttachmentsDir),selfNickname:e.selfNickname?.trim()||b(a?.selfNickname),privacyConsentAccepted:p,flowScriptPath:e.flowScriptPath?.trim()||b(a?.flowScriptPath),canReply:e.canReply??a?.canReply??!1,systemPrompt:e.systemPrompt??(typeof a?.systemPrompt=="string"?a.systemPrompt:"")});const f=this.adapters.get(i.type);for(const d of s)(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"&&d.enabled&&await this.adapters.get(d.type)?.disconnect(d).catch(()=>{});return i.enabled&&f?.connect(i).catch(()=>{}),this.getManagerChannel(o,"wechat-rpa",{includeSecret:!0})}}function y(n,e){return!e||e.type!==n.type?!1:n.type==="wechat-rpa"?!0:n.type==="websocket"?!!(e.wsUrl&&e.token):n.type==="wecom"?!!(e.token||e.botId||e.secret):!!e.token}function C(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:"",wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):void 0,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):void 0,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):void 0,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?void 0:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:"",selfNickname:typeof n.selfNickname=="string"?n.selfNickname:"",wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:k(n)}}function h(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:null,wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):null,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):null,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):null,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?null:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:null,selfNickname:typeof n.selfNickname=="string"?n.selfNickname:null,wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:k(n)}}function w(n){const e=new Set,t=[];for(const s of n){const o=String(s?.name||"").replace(/\s+/g," ").trim();!o||e.has(o)||(e.add(o),t.push({name:o}))}return t}function E(){return"wechat-channel"}function k(n){const e=[];if(n.lastHelperPermissions&&typeof n.lastHelperPermissions=="object"){const t=n.lastHelperPermissions;e.push({code:"wechat_window_unavailable",ok:t.wechatWindowAvailable!==!1,severity:"blocking",message:t.wechatWindowAvailable===!1?"\u5FAE\u4FE1\u7A97\u53E3\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6253\u5F00\u5E76\u767B\u5F55\u5FAE\u4FE1\u540E\u518D\u8BD5\u3002":"\u5FAE\u4FE1\u7A97\u53E3\u53EF\u7528\u3002"})}return e.push({code:"platform_unsupported",ok:n.source!=="windows-visual-flow",severity:"blocking",message:n.source==="windows-visual-flow"?"\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF0C\u8BF7\u6539\u7528 wechat-channel\u3002":"\u5F53\u524D\u914D\u7F6E\u4F7F\u7528\u8DE8\u5E73\u53F0\u5FAE\u4FE1\u901A\u9053\u3002"}),e.push({code:"privacy_consent_required",ok:!!n.privacyConsentAccepted,severity:"blocking",message:n.privacyConsentAccepted?"\u5DF2\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002":"\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002"}),e.push({code:"server_decision_unavailable",ok:!0,severity:"blocking",message:"\u670D\u52A1\u7AEF\u5224\u65AD\u80FD\u529B\u53EF\u7528\u3002"}),e}function W(n,e){const t=F(e.text);if(!t.length&&!e.attachment)return[];if(n==="wechat-rpa"&&e.attachment&&t.length<=1)return[{text:t[0]??"",attachment:e.attachment,idempotencyKey:e.idempotencyKey}];const s=t.map((o,r)=>({text:o,attachment:void 0,idempotencyKey:t.length>1&&e.idempotencyKey?`${e.idempotencyKey}:${r+1}`:e.idempotencyKey}));return e.attachment&&s.push({text:"",attachment:e.attachment,idempotencyKey:t.length&&e.idempotencyKey?`${e.idempotencyKey}:attachment`:e.idempotencyKey}),s}function K(...n){const e=new Set,t=[];for(const s of n.flat()){const o=I(s);if(!o){t.push(s);continue}e.has(o)||(e.add(o),t.push(s))}return t}function I(n){const e=S(n.channelId),t=S(n.conversationId),s=S(n.messageId);return!e||!t||!s?null:`${e}
|
|
1
|
+
import v from"node:crypto";import g from"node:fs";import u from"node:path";import{ChannelConfigRegistry as M}from"./registry.js";import{ChannelSecretRegistry as N}from"./secret-registry.js";import{WeComChannelAdapter as D}from"./wecom.js";import{WeChatRpaChannelAdapter as B}from"./wechat-rpa.js";import{ExternalWebSocketChannelAdapter as x}from"./websocket.js";import{splitExternalReplyText as F}from"./reply-split.js";class J{onExternalMessage;createReplyTarget;configs=new M;secrets=new N;adapters=new Map;completedReplyKeys=new Map;recentMessages=new Map;constructor(e,t,s={}){this.onExternalMessage=e,this.createReplyTarget=t;const o=new D(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(o.type,o);const r=new x(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(r.type,r);const i=new B(a=>this.ingest(a),{createProductRunner:s.createWeChatRpaProductRunner,automationLane:s.weChatAutomationLane});this.adapters.set(i.type,i)}async start(){for(const e of this.configs.list().filter(t=>t.enabled))await this.adapters.get(e.type)?.connect(e).catch(()=>{})}async stop(){for(const e of this.configs.list())await this.adapters.get(e.type)?.disconnect(e).catch(()=>{})}ingest(e){const t=this.findRecentMessageDuplicate(e);if(t)return t;const s=this.configs.get(e.channelId),o=e.managerSessionId??s?.sessionId??s?.managerSessionId;if(!o)throw new Error(`No session bound for channel ${e.channelId}`);const r=e.replyTarget||this.createReplyTarget({managerSessionId:o,channelId:e.channelId,conversationId:e.conversationId,messageId:e.messageId}),i={...e,replyTarget:r};return this.onExternalMessage(o,i),this.recordRecentMessage(i),i}async reply(e){const t=this.configs.get(e.channelId);if(!t)return{ok:!1,error:`Unknown channel: ${e.channelId}`};if((t.sessionId??t.managerSessionId)!==e.managerSessionId)return{ok:!1,error:"Channel is not bound to this session"};const s=this.adapters.get(t.type);if(!s)return{ok:!1,error:`Unsupported channel type: ${t.type}`};try{const o=W(t.type,e);if(!o.length)return{ok:!1,error:"Reply text or attachment is required"};let r=!1;for(const i of o){const a=i.idempotencyKey;if(a&&this.isReplyCompleted(t,e.conversationId,a))continue;const c=await s.send(t,{...e,...i});if(c?.status==="queued"){r=!0;continue}if(c?.status==="manual-review")return{ok:!1,error:c.reason||"Reply requires manual review before retry"};a&&this.markReplyCompleted(t,e.conversationId,a)}return r?{ok:!0,pending:!0}:{ok:!0}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}}isReplyCompleted(e,t,s){return this.loadReplyCompletionSet(e).has(A(e.id,t,s))}markReplyCompleted(e,t,s){const o=this.loadReplyCompletionSet(e);o.add(A(e.id,t,s));try{$(e.workDir,o)}catch{}}loadReplyCompletionSet(e){const t=u.resolve(e.workDir),s=this.completedReplyKeys.get(t);if(s)return s;const o=T(e.workDir);return this.completedReplyKeys.set(t,o),o}async getDefaultReplyTarget(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)throw new Error("No enabled external channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.defaultConversation)throw new Error(`External channel ${t.type} has no default conversation`);const o=await s.defaultConversation(t);return{channelId:t.id,conversationId:o.conversationId}}getManagerChannel(e,t,s={}){const o=this.configs.list().filter(c=>(c.sessionId??c.managerSessionId)===e&&c.type===t),r=o.find(c=>c.enabled)??o.at(-1);if(!r)return null;const i=this.secrets.get(r.secretRef),a=this.adapters.get(r.type)?.runtimeStatus?.(r)??{};return{id:r.id,type:r.type,name:r.name,sessionId:r.sessionId??r.managerSessionId,managerSessionId:r.managerSessionId,workDir:r.workDir,agentType:r.agentType,agentSessionId:r.agentSessionId,modelId:r.modelId,enabled:r.enabled,wsUrl:i?.wsUrl??"",token:s.includeSecret?i?.token??"":"",tokenConfigured:!!i?.token,canReply:!!i?.canReply,systemPrompt:typeof i?.systemPrompt=="string"?i.systemPrompt:"",...k(i),...a}}getChannelById(e,t={}){const s=this.configs.get(e);if(!s)return null;const o=this.secrets.get(s.secretRef),r=this.adapters.get(s.type)?.runtimeStatus?.(s)??{};return{id:s.id,type:s.type,name:s.name,sessionId:s.sessionId??s.managerSessionId,managerSessionId:s.managerSessionId,workDir:s.workDir,agentType:s.agentType,agentSessionId:s.agentSessionId,modelId:s.modelId,enabled:s.enabled,wsUrl:o?.wsUrl??"",token:t.includeSecret?o?.token??"":"",tokenConfigured:!!o?.token,canReply:!!o?.canReply,systemPrompt:typeof o?.systemPrompt=="string"?o.systemPrompt:"",...k(o),...r}}getChannelStatusById(e){const t=this.configs.get(e);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}getManagerChannelStatus(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}listManagerChannelStatuses(){return this.configs.list().filter(e=>e.enabled).map(e=>({managerSessionId:e.sessionId??e.managerSessionId,status:this.getManagerChannelStatus(e.sessionId??e.managerSessionId)})).filter(e=>!!e.status)}listManagerExternalChannels(e){return this.configs.list().filter(t=>t.enabled&&(t.sessionId??t.managerSessionId)===e).map(t=>{const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}})}async syncManagerWeChatRpaChannel(e){const t=this.configs.list().find(i=>i.enabled&&i.type==="wechat-rpa"&&(i.sessionId??i.managerSessionId)===e);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.syncNow)throw new Error("WeChat RPA channel does not support manual sync");const o=Date.now()-120*1e3,r=K(await s.syncNow(t)??[],this.getRecentMessages(t.id,o));return{channel:this.getManagerChannel(e,"wechat-rpa",{includeSecret:!0}),messages:r}}async cancelManagerWeChatRpaOutbound(e){const t=this.configs.list().find(r=>r.enabled&&r.type==="wechat-rpa"&&(r.sessionId??r.managerSessionId)===e.managerSessionId);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.cancelOutbound)throw new Error("WeChat RPA channel does not support outbound cancellation");const o=await s.cancelOutbound(t,{idempotencyKey:e.idempotencyKey,replyId:e.replyId,reason:e.reason});return{cancelled:o.cancelled,status:o.status,channel:this.getManagerChannel(e.managerSessionId,"wechat-rpa",{includeSecret:!0})}}recordRecentMessage(e){const t=this.recentMessages.get(e.channelId)??[];this.findRecentMessageDuplicate(e)||(t.push(e),this.recentMessages.set(e.channelId,t.slice(-50)))}findRecentMessageDuplicate(e){const t=I(e);return t?(this.recentMessages.get(e.channelId)??[]).find(o=>I(o)===t)??null:null}getRecentMessages(e,t){return(this.recentMessages.get(e)??[]).filter(o=>{const r=Date.parse(o.receivedAt);return!Number.isFinite(r)||r>=t})}async upsertManagerChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r={id:e.id,type:e.type,name:e.name?.trim()||t?.name||"\u5916\u90E8\u6D88\u606F\u901A\u9053",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},i=this.secrets.get(r.secretRef),a=e.wsUrl?.trim()||i?.wsUrl||"",c=e.token?.trim()||i?.token||"",p=e.canReply??i?.canReply??!1,m=e.systemPrompt??(typeof i?.systemPrompt=="string"?i.systemPrompt:"");if(r.enabled&&(!a||!c))throw new Error("WebSocket \u5730\u5740\u548C Token \u5FC5\u586B");const f=s.filter(l=>l.id!==r.id).map(l=>(l.sessionId??l.managerSessionId)===o&&l.type===e.type?{...l,enabled:!1}:l);f.push(r),this.configs.replaceAll(f),(a||c)&&this.secrets.upsert(r.secretRef,{type:"websocket",wsUrl:a,token:c,canReply:p,systemPrompt:m});const d=this.adapters.get(r.type);for(const l of s)(l.sessionId??l.managerSessionId)===o&&l.type===e.type&&l.enabled&&await this.adapters.get(l.type)?.disconnect(l).catch(()=>{});return r.enabled&&d?.connect(r).catch(()=>{}),this.getManagerChannel(o,e.type,{includeSecret:!0})}async upsertManagerWeChatRpaChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r=w(e.groups);if(e.enabled&&!r.length)throw new Error("WeChat RPA \u81F3\u5C11\u9700\u8981\u914D\u7F6E\u4E00\u4E2A\u7FA4");if(e.enabled&&r.length>1)throw new Error("WeChat RPA \u6BCF\u4E2A\u5BF9\u8BDD\u53EA\u80FD\u7ED1\u5B9A\u4E00\u4E2A\u7FA4");const i={id:e.id,type:"wechat-rpa",name:e.name?.trim()||t?.name||"\u672C\u673A\u5FAE\u4FE1 RPA",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},a=this.secrets.get(i.secretRef),c=e.source||(a?.source==="wechat-channel"||a?.source==="macos-probe"||a?.source==="fixture-jsonl"||a?.source==="macos-flow"||a?.source==="windows-visual-flow"||a?.source==="wechat-rpa-lab"?a.source:E());if(e.enabled&&c==="windows-visual-flow")throw new Error("\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF1BmacOS \u548C Windows \u6B63\u5F0F\u901A\u9053\u90FD\u4F7F\u7528 wechat-channel");const p=e.privacyConsentAccepted??!!a?.privacyConsentAccepted;if(e.enabled&&!p)throw new Error("\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743");const m=s.filter(d=>d.id!==i.id).map(d=>(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"?{...d,enabled:!1}:d);m.push(i),this.configs.replaceAll(m),this.secrets.upsert(i.secretRef,{type:"wechat-rpa",source:c,groups:r,pollIntervalMs:R(e.pollIntervalMs,a?.pollIntervalMs),recentLimit:R(e.recentLimit,a?.recentLimit),idleSeconds:R(e.idleSeconds,a?.idleSeconds),forceForeground:e.forceForeground??(a?.forceForeground===void 0?!0:!!a.forceForeground),noRestore:e.noRestore??(a?.noRestore===void 0?!0:!!a.noRestore),downloadAttachments:e.downloadAttachments??(a?.downloadAttachments===void 0?!0:!!a.downloadAttachments),downloadAttachmentsDir:e.downloadAttachmentsDir?.trim()||b(a?.downloadAttachmentsDir),selfNickname:e.selfNickname?.trim()||b(a?.selfNickname),selfTriggerMarker:e.selfTriggerMarker?.trim()||void 0,deferInitialPoll:e.deferInitialPoll===!0?!0:void 0,privacyConsentAccepted:p,flowScriptPath:e.flowScriptPath?.trim()||b(a?.flowScriptPath),canReply:e.canReply??a?.canReply??!1,systemPrompt:e.systemPrompt??(typeof a?.systemPrompt=="string"?a.systemPrompt:"")});const f=this.adapters.get(i.type);for(const d of s)(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"&&d.enabled&&await this.adapters.get(d.type)?.disconnect(d).catch(()=>{});return i.enabled&&f?.connect(i).catch(()=>{}),this.getManagerChannel(o,"wechat-rpa",{includeSecret:!0})}}function y(n,e){return!e||e.type!==n.type?!1:n.type==="wechat-rpa"?!0:n.type==="websocket"?!!(e.wsUrl&&e.token):n.type==="wecom"?!!(e.token||e.botId||e.secret):!!e.token}function k(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:"",wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):void 0,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):void 0,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):void 0,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?void 0:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:"",selfNickname:typeof n.selfNickname=="string"?n.selfNickname:"",wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:C(n)}}function h(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:null,wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):null,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):null,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):null,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?null:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:null,selfNickname:typeof n.selfNickname=="string"?n.selfNickname:null,wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:C(n)}}function w(n){const e=new Set,t=[];for(const s of n){const o=String(s?.name||"").replace(/\s+/g," ").trim();!o||e.has(o)||(e.add(o),t.push({name:o}))}return t}function E(){return"wechat-channel"}function C(n){const e=[];if(n.lastHelperPermissions&&typeof n.lastHelperPermissions=="object"){const t=n.lastHelperPermissions;e.push({code:"wechat_window_unavailable",ok:t.wechatWindowAvailable!==!1,severity:"blocking",message:t.wechatWindowAvailable===!1?"\u5FAE\u4FE1\u7A97\u53E3\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6253\u5F00\u5E76\u767B\u5F55\u5FAE\u4FE1\u540E\u518D\u8BD5\u3002":"\u5FAE\u4FE1\u7A97\u53E3\u53EF\u7528\u3002"})}return e.push({code:"platform_unsupported",ok:n.source!=="windows-visual-flow",severity:"blocking",message:n.source==="windows-visual-flow"?"\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF0C\u8BF7\u6539\u7528 wechat-channel\u3002":"\u5F53\u524D\u914D\u7F6E\u4F7F\u7528\u8DE8\u5E73\u53F0\u5FAE\u4FE1\u901A\u9053\u3002"}),e.push({code:"privacy_consent_required",ok:!!n.privacyConsentAccepted,severity:"blocking",message:n.privacyConsentAccepted?"\u5DF2\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002":"\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002"}),e.push({code:"server_decision_unavailable",ok:!0,severity:"blocking",message:"\u670D\u52A1\u7AEF\u5224\u65AD\u80FD\u529B\u53EF\u7528\u3002"}),e}function W(n,e){const t=F(e.text);if(!t.length&&!e.attachment)return[];if(n==="wechat-rpa"&&e.attachment&&t.length<=1)return[{text:t[0]??"",attachment:e.attachment,idempotencyKey:e.idempotencyKey}];const s=t.map((o,r)=>({text:o,attachment:void 0,idempotencyKey:t.length>1&&e.idempotencyKey?`${e.idempotencyKey}:${r+1}`:e.idempotencyKey}));return e.attachment&&s.push({text:"",attachment:e.attachment,idempotencyKey:t.length&&e.idempotencyKey?`${e.idempotencyKey}:attachment`:e.idempotencyKey}),s}function K(...n){const e=new Set,t=[];for(const s of n.flat()){const o=I(s);if(!o){t.push(s);continue}e.has(o)||(e.add(o),t.push(s))}return t}function I(n){const e=S(n.channelId),t=S(n.conversationId),s=S(n.messageId);return!e||!t||!s?null:`${e}
|
|
2
2
|
${t}
|
|
3
3
|
${s}`}function S(n){return typeof n=="string"?n.trim():""}function A(n,e,t){return v.createHash("sha256").update(`${n}
|
|
4
4
|
${e}
|
|
@@ -17,6 +17,8 @@ type ChannelSecretRecord = {
|
|
|
17
17
|
downloadAttachments?: boolean;
|
|
18
18
|
downloadAttachmentsDir?: string;
|
|
19
19
|
selfNickname?: string;
|
|
20
|
+
selfTriggerMarker?: string;
|
|
21
|
+
deferInitialPoll?: boolean;
|
|
20
22
|
privacyConsentAccepted?: boolean;
|
|
21
23
|
idleSeconds?: number;
|
|
22
24
|
recentLimit?: number;
|
|
@@ -6,13 +6,25 @@ export type WeChatAutomationLaneSnapshot = {
|
|
|
6
6
|
active: boolean;
|
|
7
7
|
queued: number;
|
|
8
8
|
lastLabel: string | null;
|
|
9
|
+
lockPath?: string;
|
|
10
|
+
};
|
|
11
|
+
export type WeChatAutomationLaneOptions = {
|
|
12
|
+
lockPath?: string;
|
|
13
|
+
staleMs?: number;
|
|
14
|
+
owner?: string;
|
|
9
15
|
};
|
|
10
16
|
export declare class SerialWeChatAutomationLane implements WeChatAutomationLane {
|
|
11
17
|
private tail;
|
|
12
18
|
private active;
|
|
13
19
|
private queued;
|
|
14
20
|
private lastLabel;
|
|
21
|
+
private readonly lockPath?;
|
|
22
|
+
private readonly staleMs;
|
|
23
|
+
private readonly owner;
|
|
24
|
+
constructor(options?: WeChatAutomationLaneOptions);
|
|
15
25
|
run<T>(label: string, operation: () => Promise<T>): Promise<T>;
|
|
16
26
|
snapshot(): WeChatAutomationLaneSnapshot;
|
|
27
|
+
private acquireLock;
|
|
17
28
|
}
|
|
18
29
|
export declare function createWeChatAutomationLane(): WeChatAutomationLane;
|
|
30
|
+
export declare function defaultWeChatAutomationLockPath(): string;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import r from"node:fs";import l from"node:os";import s from"node:path";import{resolveShennianPath as u}from"../../config/index.js";const h=900*1e3;class f{tail=Promise.resolve();active=!1;queued=0;lastLabel=null;lockPath;staleMs;owner;constructor(t={}){this.lockPath=t.lockPath,this.staleMs=t.staleMs??h,this.owner=t.owner??`${process.platform}:${process.pid}`}async run(t,a){this.queued+=1;const i=this.tail;let o;this.tail=new Promise(c=>{o=c}),await i.catch(()=>{}),this.queued-=1,this.active=!0,this.lastLabel=t;let n=null;try{return n=this.acquireLock(t),await a()}finally{n?.release(),this.active=!1,o()}}snapshot(){return{active:this.active,queued:this.queued,lastLabel:this.lastLabel,lockPath:this.lockPath}}acquireLock(t){if(!this.lockPath)return null;r.mkdirSync(s.dirname(this.lockPath),{recursive:!0});try{r.mkdirSync(this.lockPath)}catch(a){if(!w(a))throw a;const i=d(this.lockPath);if(p(this.lockPath,i,this.staleMs))r.rmSync(this.lockPath,{recursive:!0,force:!0}),r.mkdirSync(this.lockPath);else throw new Error(P(this.lockPath,i))}return k(this.lockPath,{pid:process.pid,label:t,owner:this.owner,hostname:l.hostname(),startedAt:new Date().toISOString()}),{release:()=>{r.rmSync(this.lockPath,{recursive:!0,force:!0})}}}}function b(){return new f({lockPath:m()})}function m(){return u("runtime","wechat-automation.lock")}function k(e,t){r.writeFileSync(s.join(e,"owner.json"),`${JSON.stringify(t,null,2)}
|
|
2
|
+
`,"utf8")}function d(e){try{const t=JSON.parse(r.readFileSync(s.join(e,"owner.json"),"utf8"));return t&&typeof t=="object"?t:null}catch{return null}}function p(e,t,a){if(t?.pid&&y(t.pid))return!1;try{return Date.now()-r.statSync(e).mtimeMs>a}catch{return!0}}function y(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch{return!1}}function P(e,t){return`wechat_automation_busy: another WeChat automation run is active (${[`lock=${e}`,t?.pid?`pid=${t.pid}`:"",t?.label?`label=${t.label}`:"",t?.startedAt?`startedAt=${t.startedAt}`:"",t?.owner?`owner=${t.owner}`:""].filter(Boolean).join(" ")})`}function w(e){return typeof e=="object"&&e!==null&&"code"in e&&e.code==="EEXIST"}export{f as SerialWeChatAutomationLane,b as createWeChatAutomationLane,m as defaultWeChatAutomationLockPath};
|
|
@@ -84,6 +84,22 @@ export type WeChatChannelClassifyWindowResponse = {
|
|
|
84
84
|
conversationTitle?: string | null;
|
|
85
85
|
isTargetConversation?: boolean;
|
|
86
86
|
confidence?: number;
|
|
87
|
+
layout?: {
|
|
88
|
+
messageInputRect?: {
|
|
89
|
+
x?: number;
|
|
90
|
+
y?: number;
|
|
91
|
+
width?: number;
|
|
92
|
+
height?: number;
|
|
93
|
+
coordinateSpace?: string;
|
|
94
|
+
} | null;
|
|
95
|
+
searchInputRect?: {
|
|
96
|
+
x?: number;
|
|
97
|
+
y?: number;
|
|
98
|
+
width?: number;
|
|
99
|
+
height?: number;
|
|
100
|
+
coordinateSpace?: string;
|
|
101
|
+
} | null;
|
|
102
|
+
} | null;
|
|
87
103
|
reasonCode?: string;
|
|
88
104
|
warnings?: string[];
|
|
89
105
|
usageRefId?: string;
|
|
@@ -94,7 +110,8 @@ export type WeChatChannelApiClient = ReturnType<typeof createWeChatChannelApiCli
|
|
|
94
110
|
export declare class WeChatChannelApiError extends Error {
|
|
95
111
|
readonly reasonCode: string;
|
|
96
112
|
readonly statusCode: number;
|
|
97
|
-
|
|
113
|
+
readonly details?: unknown | undefined;
|
|
114
|
+
constructor(message: string, reasonCode: string, statusCode: number, details?: unknown | undefined);
|
|
98
115
|
}
|
|
99
116
|
export type WeChatChannelObserveInput = {
|
|
100
117
|
screenshots: Array<{
|
|
@@ -107,6 +124,7 @@ export type WeChatChannelObserveInput = {
|
|
|
107
124
|
edgeOcrBlocks?: unknown[];
|
|
108
125
|
visibleConversationFingerprints?: unknown[];
|
|
109
126
|
localLedgerTailAnchors?: unknown[];
|
|
127
|
+
traceId?: string;
|
|
110
128
|
};
|
|
111
129
|
export type WeChatChannelObserveResponse = {
|
|
112
130
|
ok: true;
|
|
@@ -203,9 +221,14 @@ export type WeChatChannelRunStatusInput = {
|
|
|
203
221
|
helperReady?: boolean;
|
|
204
222
|
};
|
|
205
223
|
};
|
|
224
|
+
export type WeChatChannelRuntimePreflightInput = WeChatChannelRunStatusInput['preflight'];
|
|
206
225
|
export declare function createWeChatChannelApiClient(options?: WeChatChannelApiClientOptions): {
|
|
207
226
|
getRuntimePolicy: () => Promise<WeChatChannelRuntimePolicyResponse>;
|
|
208
|
-
upsertRuntime: (runtime: WeChatChannelRuntime, binding?: WeChatChannelBindingConfig
|
|
227
|
+
upsertRuntime: (runtime: WeChatChannelRuntime, binding?: WeChatChannelBindingConfig, input?: {
|
|
228
|
+
preflight?: WeChatChannelRuntimePreflightInput;
|
|
229
|
+
helperVersion?: string;
|
|
230
|
+
clientRuntimeVersion?: string;
|
|
231
|
+
}) => Promise<unknown>;
|
|
209
232
|
observe: (runtime: WeChatChannelRuntime, binding: WeChatChannelBindingConfig, input: WeChatChannelObserveInput) => Promise<WeChatChannelObserveResponse>;
|
|
210
233
|
structureWindow: (runtime: WeChatChannelRuntime, binding: WeChatChannelBindingConfig, input: WeChatChannelStructureWindowInput) => Promise<WeChatChannelStructureWindowResponse>;
|
|
211
234
|
embedVisual: (runtime: WeChatChannelRuntime, binding: WeChatChannelBindingConfig, input: WeChatChannelEmbedVisualInput) => Promise<WeChatChannelEmbedVisualResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SERVERS as
|
|
1
|
+
import{SERVERS as f}from"../../region.js";import{loadConfig as y}from"../../config/index.js";class h extends Error{reasonCode;statusCode;details;constructor(o,d,c,I){super(o),this.reasonCode=d,this.statusCode=c,this.details=I,this.name="WeChatChannelApiError"}}function S(r={}){const o=y(),d=v(r.serverUrl||o.serverUrl||f.cn.url),c=r.machineToken||o.machineToken,I=r.fetchImpl||fetch;if(!c)throw new Error("WeChat channel requires a paired machine token");async function t(s,n){const e=C(n);let a;try{a=await I(`${d}/api/channels/wechat${s}`,{method:n===void 0?"GET":"POST",headers:{authorization:`Bearer ${c}`,...n===void 0?{}:{"content-type":"application/json"},...e?{"x-trace-id":e}:{}},body:n===void 0?void 0:JSON.stringify(n)})}catch(i){const u=i instanceof Error?i.message:String(i||"network request failed");throw new h(`WeChat channel API ${s} network failed: ${u}`,"wechat_channel_network_failed",0,{path:s,traceId:e||null,cause:u})}const m=await a.text();let l=null;try{l=m?JSON.parse(m):null}catch{throw new h(`WeChat channel API ${s} returned invalid JSON`,"wechat_channel_invalid_response",a.status,{path:s,traceId:e||null,text:m.slice(0,200)})}if(!a.ok||l?.ok===!1){const i=p(l?.reasonCode)||a.statusText||"request_failed";throw new h(`WeChat channel API ${s} failed: ${i}`,i,a.status,{path:s,traceId:e||null,statusCode:a.status})}return l}return{getRuntimePolicy:()=>t("/runtime-policy"),upsertRuntime:(s,n,e)=>t("/runtime",{runtimeId:s.runtimeId,machineId:s.machineId,pollIntervalSeconds:Math.round(s.policy.pollIntervalMs/1e3),foregroundPolicy:s.foregroundPolicy,clientRuntimeVersion:e?.clientRuntimeVersion??String(s.policy.runtimeVersion),helperVersion:e?.helperVersion,preflight:e?.preflight,...n?g(n):{}}),observe:(s,n,e)=>t("/observe",{runtimeId:s.runtimeId,bindingId:n.bindingId,sessionId:n.sessionId,machineId:s.machineId,conversationName:n.conversationDisplayName,schemaVersion:s.policy.runtimeVersion,screenshots:e.screenshots,edgeOcrBlocks:e.edgeOcrBlocks??[],visibleConversationFingerprints:e.visibleConversationFingerprints??[],localLedgerTailAnchors:e.localLedgerTailAnchors??[],traceId:e.traceId}),structureWindow:(s,n,e)=>t("/structure-window",{runtimeId:s.runtimeId,bindingId:n.bindingId,sessionId:n.sessionId,machineId:s.machineId,conversationName:n.conversationDisplayName,schemaVersion:s.policy.runtimeVersion,screenshots:e.screenshots,edgeOcrBlocks:e.edgeOcrBlocks??[],visibleConversationFingerprints:e.visibleConversationFingerprints??[],localLedgerTailAnchors:e.localLedgerTailAnchors??[],traceId:e.traceId}),embedVisual:(s,n,e)=>t("/embed-visual",{runtimeId:s.runtimeId,bindingId:n.bindingId,sessionId:n.sessionId,machineId:s.machineId,conversationName:n.conversationDisplayName,schemaVersion:s.policy.runtimeVersion,screenshots:e.screenshots??[],visualBlocks:e.visualBlocks,traceId:e.traceId}),classifyWindow:(s,n,e)=>t("/classify-window",{runtimeId:s.runtimeId,bindingId:n.bindingId,sessionId:n.sessionId,machineId:s.machineId,conversationName:n.conversationDisplayName,screenshot:e.screenshot,traceId:e.traceId}),ingest:(s,n,e)=>t("/ingest",{runtimeId:s.runtimeId,idempotencyKey:e.idempotencyKey,bindingId:n.bindingId,sessionId:n.sessionId,machineId:s.machineId,messages:e.messages}),reportOutboundStatus:(s,n,e)=>t("/outbound-status",{runtimeId:s.runtimeId,replyId:e.replyId,idempotencyKey:e.idempotencyKey,bindingId:n.bindingId,sessionId:n.sessionId,machineId:s.machineId,status:e.status,replyBaseRevision:e.replyBaseRevision,sentAt:e.sentAt,confirmedAt:e.confirmedAt,failureCode:e.failureCode,lastErrorSummary:e.lastErrorSummary,nextAttemptAt:e.nextAttemptAt,attemptCount:e.attemptCount,commitStage:e.commitStage,copyableContentRef:e.copyableContentRef,copyableText:e.copyableText,agentVisible:e.agentVisible}),reportRunStatus:(s,n,e)=>t("/run-status",{runtimeId:s.runtimeId,bindingId:n.bindingId,sessionId:n.sessionId,machineId:s.machineId,status:e.status,reasonCode:e.reasonCode,traceId:e.traceId,lastErrorSummary:e.lastErrorSummary,preflight:e.preflight})}}function g(r){return{bindingId:r.bindingId,sessionId:r.sessionId,conversationName:r.conversationDisplayName,enabled:r.enabled,allowReply:r.allowReply,downloadMedia:r.downloadMedia}}function v(r){return r.replace(/\/+$/,"")}function C(r){if(!r||typeof r!="object")return;const o=r.traceId;return(typeof o=="string"?o.trim():"")||void 0}function p(r){return typeof r=="string"?r.trim():""}export{h as WeChatChannelApiError,S as createWeChatChannelApiClient};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const WECHAT_CHANNEL_HELPER_VERSION = "0.1.
|
|
1
|
+
export declare const WECHAT_CHANNEL_HELPER_VERSION = "0.1.10";
|
|
2
2
|
export declare const WECHAT_CHANNEL_HELPER_DIR_ENV = "SHENNIAN_WECHAT_CHANNEL_HELPER_DIR";
|
|
3
3
|
export declare const SHENNIAN_HELPER_RUNTIME_DIR_ENV = "SHENNIAN_HELPER_RUNTIME_DIR";
|
|
4
4
|
export declare const WECHAT_CHANNEL_HELPER_RUNTIME_REQUIRED_REASON = "helper_runtime_required";
|