zcode-acp-server 0.50.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/code-fingerprint.json +2 -2
- package/dist/config/user-config.d.ts +39 -2
- package/dist/config/user-config.d.ts.map +1 -1
- package/dist/config/user-config.js +79 -2
- package/dist/config/user-config.js.map +1 -1
- package/dist/goal-loop/driver.d.ts.map +1 -1
- package/dist/goal-loop/driver.js +9 -0
- package/dist/goal-loop/driver.js.map +1 -1
- package/dist/handlers/background-tasks.d.ts +8 -0
- package/dist/handlers/background-tasks.d.ts.map +1 -1
- package/dist/handlers/background-tasks.js +30 -1
- package/dist/handlers/background-tasks.js.map +1 -1
- package/dist/handlers/server-requests.d.ts +26 -1
- package/dist/handlers/server-requests.d.ts.map +1 -1
- package/dist/handlers/server-requests.js +14 -1
- package/dist/handlers/server-requests.js.map +1 -1
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +34 -12
- package/dist/handlers/session.js.map +1 -1
- package/dist/push/config.d.ts +47 -0
- package/dist/push/config.d.ts.map +1 -0
- package/dist/push/config.js +82 -0
- package/dist/push/config.js.map +1 -0
- package/dist/push/push.d.ts +77 -0
- package/dist/push/push.d.ts.map +1 -0
- package/dist/push/push.js +131 -0
- package/dist/push/push.js.map +1 -0
- package/dist/push/wecom.d.ts +45 -0
- package/dist/push/wecom.d.ts.map +1 -0
- package/dist/push/wecom.js +91 -0
- package/dist/push/wecom.js.map +1 -0
- package/dist/remote/broadcast.d.ts +15 -0
- package/dist/remote/broadcast.d.ts.map +1 -1
- package/dist/remote/broadcast.js +22 -1
- package/dist/remote/broadcast.js.map +1 -1
- package/dist/remote/config.d.ts +2 -1
- package/dist/remote/config.d.ts.map +1 -1
- package/dist/remote/config.js +4 -3
- package/dist/remote/config.js.map +1 -1
- package/dist/remote/endpoint.d.ts.map +1 -1
- package/dist/remote/endpoint.js +4 -0
- package/dist/remote/endpoint.js.map +1 -1
- package/dist/remote/hub-server.d.ts.map +1 -1
- package/dist/remote/hub-server.js +46 -0
- package/dist/remote/hub-server.js.map +1 -1
- package/dist/remote/push-test-endpoint.d.ts +12 -0
- package/dist/remote/push-test-endpoint.d.ts.map +1 -0
- package/dist/remote/push-test-endpoint.js +67 -0
- package/dist/remote/push-test-endpoint.js.map +1 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -0
- package/dist/server.js.map +1 -1
- package/dist/settings/workflow.d.ts.map +1 -1
- package/dist/settings/workflow.js +7 -0
- package/dist/settings/workflow.js.map +1 -1
- package/dist/workflow/poller.d.ts +1 -0
- package/dist/workflow/poller.d.ts.map +1 -1
- package/dist/workflow/poller.js +20 -0
- package/dist/workflow/poller.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeCom push configuration + the single shared ACTIVE predicate
|
|
3
|
+
* (push-backend-requirements §6/§8/§10).
|
|
4
|
+
*
|
|
5
|
+
* Precedence mirrors `mergeCommon` (file > env): the `push` section of
|
|
6
|
+
* ~/.config/zcode-acp/config.json wins over the ZCODE_ACP_PUSH_* env vars.
|
|
7
|
+
* ACTIVE = enabled AND complete credentials (corpId/agentId/secret) — a push
|
|
8
|
+
* that cannot summon anyone must not hold an offline interaction either, so
|
|
9
|
+
* `pushIfOffline` and the interaction hold read the SAME predicate. An
|
|
10
|
+
* OPTIONAL relay (static-IP proxy for the WeCom API) rides along when both
|
|
11
|
+
* url+token are present; a half-configured relay warns once and pushes direct.
|
|
12
|
+
*
|
|
13
|
+
* Resolved lazily ONCE per process: an enabled-but-incomplete setup logs one
|
|
14
|
+
* warning at first resolution and every hook then no-ops (silent degradation).
|
|
15
|
+
*/
|
|
16
|
+
import { loadUserConfig } from "../config/user-config.js";
|
|
17
|
+
import { warn } from "../utils.js";
|
|
18
|
+
/** Same truthy set as `remoteEnabledLive` (remote/config.ts). */
|
|
19
|
+
const TRUTHY = ["1", "true", "yes", "on"];
|
|
20
|
+
export function resolvePushConfig(env) {
|
|
21
|
+
const file = loadUserConfig(env).push ?? {};
|
|
22
|
+
const enabled = file.enabled !== undefined
|
|
23
|
+
? file.enabled
|
|
24
|
+
: TRUTHY.includes((env.ZCODE_ACP_PUSH_ENABLED ?? "").trim().toLowerCase());
|
|
25
|
+
if (!enabled)
|
|
26
|
+
return null;
|
|
27
|
+
const corpId = file.corpId ?? (env.ZCODE_ACP_PUSH_CORP_ID ?? "").trim();
|
|
28
|
+
const secret = file.secret ?? (env.ZCODE_ACP_PUSH_SECRET ?? "").trim();
|
|
29
|
+
const toUser = file.toUser ?? ((env.ZCODE_ACP_PUSH_TO_USER ?? "").trim() || "@all");
|
|
30
|
+
const agentId = file.agentId ?? Number.parseInt((env.ZCODE_ACP_PUSH_AGENT_ID ?? "").trim(), 10);
|
|
31
|
+
if (!corpId || !Number.isInteger(agentId) || agentId < 1 || !secret) {
|
|
32
|
+
warn("push: enabled but corpId/agentId/secret incomplete " +
|
|
33
|
+
"(config file or ZCODE_ACP_PUSH_* env) — push stays inactive");
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const relayUrl = trimTrailingSlashes(file.relay?.url ?? env.ZCODE_ACP_PUSH_RELAY_URL ?? "");
|
|
37
|
+
const relayToken = file.relay?.token ?? (env.ZCODE_ACP_PUSH_RELAY_TOKEN ?? "").trim();
|
|
38
|
+
const notify = {
|
|
39
|
+
turn: file.notify?.turn !== false,
|
|
40
|
+
goal: file.notify?.goal !== false,
|
|
41
|
+
run: file.notify?.run !== false,
|
|
42
|
+
task: file.notify?.task !== false,
|
|
43
|
+
};
|
|
44
|
+
if (relayUrl && relayToken) {
|
|
45
|
+
return {
|
|
46
|
+
corpId,
|
|
47
|
+
agentId,
|
|
48
|
+
secret,
|
|
49
|
+
toUser,
|
|
50
|
+
contentDetail: file.contentDetail ?? "full",
|
|
51
|
+
relay: { url: relayUrl, token: relayToken },
|
|
52
|
+
notify,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (relayUrl || relayToken) {
|
|
56
|
+
warn("push: relay needs BOTH url and token (config file push.relay or " +
|
|
57
|
+
"ZCODE_ACP_PUSH_RELAY_* env) — pushing direct from this host");
|
|
58
|
+
}
|
|
59
|
+
return { corpId, agentId, secret, toUser, contentDetail: file.contentDetail ?? "full", notify };
|
|
60
|
+
}
|
|
61
|
+
function trimTrailingSlashes(s) {
|
|
62
|
+
return s.trim().replace(/\/+$/, "");
|
|
63
|
+
}
|
|
64
|
+
/** undefined = not yet resolved; null = resolved inactive. */
|
|
65
|
+
let cached;
|
|
66
|
+
/** The shared ACTIVE predicate (resolve-once per process). */
|
|
67
|
+
export function pushActive() {
|
|
68
|
+
if (cached === undefined)
|
|
69
|
+
cached = resolvePushConfig(process.env);
|
|
70
|
+
return cached !== null;
|
|
71
|
+
}
|
|
72
|
+
/** The resolved config when ACTIVE, null otherwise (resolves on first use). */
|
|
73
|
+
export function pushConfig() {
|
|
74
|
+
if (cached === undefined)
|
|
75
|
+
cached = resolvePushConfig(process.env);
|
|
76
|
+
return cached ?? null;
|
|
77
|
+
}
|
|
78
|
+
/** Test hook: forget the process-wide resolution. */
|
|
79
|
+
export function resetPushConfigForTests() {
|
|
80
|
+
cached = undefined;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/push/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline push dispatch (push-backend-requirements §5): one helper gates every
|
|
3
|
+
* event hook. Push fires only when the bridge has ZERO connected clients (an
|
|
4
|
+
* online client renders the event live) and push is ACTIVE — the single
|
|
5
|
+
* predicate from push/config.ts. Fire-and-forget: send failures warn and never
|
|
6
|
+
* reach the event path.
|
|
7
|
+
*/
|
|
8
|
+
import type { ZcodeAcpServer } from "../server.js";
|
|
9
|
+
import { type WeComSender } from "./wecom.js";
|
|
10
|
+
export type PushKind = "permission" | "question" | "run" | "task" | "test" | "turn" | "goal";
|
|
11
|
+
/** Settled kinds routed through {@link pushSettled} (§5.2 — per-kind switches). */
|
|
12
|
+
export type PushSettledKind = Extract<PushKind, "turn" | "goal" | "run" | "task">;
|
|
13
|
+
/**
|
|
14
|
+
* "<project> / <session-title>" source label for settled pushes. It rides the
|
|
15
|
+
* leading bracket (never the body — `contentDetail: "minimal"` strips bodies),
|
|
16
|
+
* replacing the kind prefix whose information the title tail already carries.
|
|
17
|
+
* TOTAL (never throws): the push path is fire-and-forget by contract, and the
|
|
18
|
+
* server handle may be a partial object in tests.
|
|
19
|
+
*/
|
|
20
|
+
export declare function pushSourceLabel(server: ZcodeAcpServer, acpSid?: string): string;
|
|
21
|
+
export interface PushEventData {
|
|
22
|
+
kind: PushKind;
|
|
23
|
+
title: string;
|
|
24
|
+
body?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Source label (`<project> / <session>`, see {@link pushSourceLabel}). When
|
|
27
|
+
* present it REPLACES the kind in the leading bracket — `[kind] title`
|
|
28
|
+
* would duplicate what the title tail already says (e.g. "turn completed"),
|
|
29
|
+
* and the bracket is the one slot minimal mode never strips.
|
|
30
|
+
*/
|
|
31
|
+
label?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Test hook: forget the process-wide sender. */
|
|
34
|
+
export declare function resetPushSenderForTests(): void;
|
|
35
|
+
/** Test hook: inject a fake sender (null = inactive). */
|
|
36
|
+
export declare function setPushSenderForTests(s: WeComSender | null): void;
|
|
37
|
+
/**
|
|
38
|
+
* Render the contracted WeCom text: `[<kind or label>] <title>` + optional
|
|
39
|
+
* body line. A `label` replaces the kind in the leading bracket (see
|
|
40
|
+
* {@link PushEventData.label}). Under `contentDetail: "minimal"` the body
|
|
41
|
+
* carries no business strings (§4 — content transits Tencent) — the bracket
|
|
42
|
+
* prefix + title identify the event.
|
|
43
|
+
*/
|
|
44
|
+
export declare function renderPushContent(cfg: {
|
|
45
|
+
contentDetail: "full" | "minimal";
|
|
46
|
+
}, data: PushEventData): string;
|
|
47
|
+
/** §5: the single gated dispatch helper — offline + ACTIVE or nothing. */
|
|
48
|
+
export declare function pushIfOffline(server: ZcodeAcpServer, data: PushEventData): void;
|
|
49
|
+
/**
|
|
50
|
+
* §5.2 settled-event dispatch (turn end / goal loop stop / workflow run /
|
|
51
|
+
* background task): NO client-presence gate — an online client renders the
|
|
52
|
+
* event live but cannot wake the user's phone, and the settled event itself
|
|
53
|
+
* IS the "come back" signal. Each kind is individually switchable via
|
|
54
|
+
* `push.notify.<kind>` (default on); the shared ACTIVE predicate still applies.
|
|
55
|
+
*/
|
|
56
|
+
export declare function pushSettled(server: ZcodeAcpServer, data: PushEventData & {
|
|
57
|
+
kind: PushSettledKind;
|
|
58
|
+
}): void;
|
|
59
|
+
/**
|
|
60
|
+
* §5.1: derive the permission/question payload at the zero-clients branch of
|
|
61
|
+
* `requestAny` (broadcast.ts) — the single hook covering permission requests,
|
|
62
|
+
* AskUserQuestion, and elicitation.
|
|
63
|
+
*/
|
|
64
|
+
export declare function pushInteractionIfOffline(server: ZcodeAcpServer, method: string, params?: unknown): void;
|
|
65
|
+
/**
|
|
66
|
+
* §7 test push — sends REGARDLESS of client presence (it verifies the channel,
|
|
67
|
+
* not an offline event). Structured result for the REST route.
|
|
68
|
+
*/
|
|
69
|
+
export declare function sendTestPush(title: string): Promise<{
|
|
70
|
+
ok: true;
|
|
71
|
+
sent: number;
|
|
72
|
+
} | {
|
|
73
|
+
ok: false;
|
|
74
|
+
error: "push_disabled" | "send_failed";
|
|
75
|
+
message?: string;
|
|
76
|
+
}>;
|
|
77
|
+
//# sourceMappingURL=push.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/push/push.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7F,mFAAmF;AACnF,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;AAElF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAI/E;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,iDAAiD;AACjD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED,yDAAyD;AACzD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE;IAAE,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EAC1C,IAAI,EAAE,aAAa,GAClB,MAAM,CAIR;AAWD,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAO/E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,aAAa,GAAG;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GAC9C,IAAI,CAON;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,OAAO,GACf,IAAI,CAiBN;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,GACZ,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,GAAG,aAAa,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAC1E,CAcA"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline push dispatch (push-backend-requirements §5): one helper gates every
|
|
3
|
+
* event hook. Push fires only when the bridge has ZERO connected clients (an
|
|
4
|
+
* online client renders the event live) and push is ACTIVE — the single
|
|
5
|
+
* predicate from push/config.ts. Fire-and-forget: send failures warn and never
|
|
6
|
+
* reach the event path.
|
|
7
|
+
*/
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { log, warn } from "../utils.js";
|
|
10
|
+
import { pushConfig } from "./config.js";
|
|
11
|
+
import { createWeComSender } from "./wecom.js";
|
|
12
|
+
/**
|
|
13
|
+
* "<project> / <session-title>" source label for settled pushes. It rides the
|
|
14
|
+
* leading bracket (never the body — `contentDetail: "minimal"` strips bodies),
|
|
15
|
+
* replacing the kind prefix whose information the title tail already carries.
|
|
16
|
+
* TOTAL (never throws): the push path is fire-and-forget by contract, and the
|
|
17
|
+
* server handle may be a partial object in tests.
|
|
18
|
+
*/
|
|
19
|
+
export function pushSourceLabel(server, acpSid) {
|
|
20
|
+
const project = path.basename(server.projectCwd?.() ?? process.cwd());
|
|
21
|
+
const title = acpSid !== undefined ? server.sessionTitles?.get(acpSid) : undefined;
|
|
22
|
+
return title ? `${project} / ${title}` : project;
|
|
23
|
+
}
|
|
24
|
+
/** undefined = not yet built; null = push inactive. */
|
|
25
|
+
let sender;
|
|
26
|
+
function pushSender() {
|
|
27
|
+
if (sender === undefined) {
|
|
28
|
+
const cfg = pushConfig();
|
|
29
|
+
sender = cfg ? createWeComSender(cfg) : null;
|
|
30
|
+
}
|
|
31
|
+
return sender;
|
|
32
|
+
}
|
|
33
|
+
/** Test hook: forget the process-wide sender. */
|
|
34
|
+
export function resetPushSenderForTests() {
|
|
35
|
+
sender = undefined;
|
|
36
|
+
}
|
|
37
|
+
/** Test hook: inject a fake sender (null = inactive). */
|
|
38
|
+
export function setPushSenderForTests(s) {
|
|
39
|
+
sender = s;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Render the contracted WeCom text: `[<kind or label>] <title>` + optional
|
|
43
|
+
* body line. A `label` replaces the kind in the leading bracket (see
|
|
44
|
+
* {@link PushEventData.label}). Under `contentDetail: "minimal"` the body
|
|
45
|
+
* carries no business strings (§4 — content transits Tencent) — the bracket
|
|
46
|
+
* prefix + title identify the event.
|
|
47
|
+
*/
|
|
48
|
+
export function renderPushContent(cfg, data) {
|
|
49
|
+
const body = cfg.contentDetail === "minimal" ? undefined : data.body;
|
|
50
|
+
const prefix = `[${data.label ?? data.kind}]`;
|
|
51
|
+
return body ? `${prefix} ${data.title}\n${body}` : `${prefix} ${data.title}`;
|
|
52
|
+
}
|
|
53
|
+
/** Fire-and-forget send tail shared by both dispatch helpers. */
|
|
54
|
+
function dispatchPush(cfg, s, data) {
|
|
55
|
+
const content = renderPushContent(cfg, data);
|
|
56
|
+
s.sendText(content).then(() => log(`push: ${data.kind} "${data.title}" sent via WeCom`), (e) => warn(`push: WeCom send failed: ${e instanceof Error ? e.message : String(e)}`));
|
|
57
|
+
}
|
|
58
|
+
/** §5: the single gated dispatch helper — offline + ACTIVE or nothing. */
|
|
59
|
+
export function pushIfOffline(server, data) {
|
|
60
|
+
if (server.clients.size > 0)
|
|
61
|
+
return;
|
|
62
|
+
const cfg = pushConfig();
|
|
63
|
+
if (!cfg)
|
|
64
|
+
return;
|
|
65
|
+
const s = pushSender();
|
|
66
|
+
if (!s)
|
|
67
|
+
return;
|
|
68
|
+
dispatchPush(cfg, s, data);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* §5.2 settled-event dispatch (turn end / goal loop stop / workflow run /
|
|
72
|
+
* background task): NO client-presence gate — an online client renders the
|
|
73
|
+
* event live but cannot wake the user's phone, and the settled event itself
|
|
74
|
+
* IS the "come back" signal. Each kind is individually switchable via
|
|
75
|
+
* `push.notify.<kind>` (default on); the shared ACTIVE predicate still applies.
|
|
76
|
+
*/
|
|
77
|
+
export function pushSettled(server, data) {
|
|
78
|
+
void server; // presence deliberately NOT checked (see above)
|
|
79
|
+
const cfg = pushConfig();
|
|
80
|
+
if (!cfg || !cfg.notify[data.kind])
|
|
81
|
+
return;
|
|
82
|
+
const s = pushSender();
|
|
83
|
+
if (!s)
|
|
84
|
+
return;
|
|
85
|
+
dispatchPush(cfg, s, data);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* §5.1: derive the permission/question payload at the zero-clients branch of
|
|
89
|
+
* `requestAny` (broadcast.ts) — the single hook covering permission requests,
|
|
90
|
+
* AskUserQuestion, and elicitation.
|
|
91
|
+
*/
|
|
92
|
+
export function pushInteractionIfOffline(server, method, params) {
|
|
93
|
+
const p = (params ?? {});
|
|
94
|
+
if (method === "session/request_permission") {
|
|
95
|
+
const detail = typeof p.toolCall?.title === "string" ? p.toolCall.title.trim() : "";
|
|
96
|
+
pushIfOffline(server, {
|
|
97
|
+
kind: "permission",
|
|
98
|
+
title: "Approval requested",
|
|
99
|
+
body: detail || undefined,
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const question = typeof p.message === "string" ? p.message.trim() : "";
|
|
104
|
+
pushIfOffline(server, {
|
|
105
|
+
kind: "question",
|
|
106
|
+
title: "Agent question",
|
|
107
|
+
body: question || undefined,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* §7 test push — sends REGARDLESS of client presence (it verifies the channel,
|
|
112
|
+
* not an offline event). Structured result for the REST route.
|
|
113
|
+
*/
|
|
114
|
+
export async function sendTestPush(title) {
|
|
115
|
+
const cfg = pushConfig();
|
|
116
|
+
const s = pushSender();
|
|
117
|
+
if (!cfg || !s)
|
|
118
|
+
return { ok: false, error: "push_disabled" };
|
|
119
|
+
try {
|
|
120
|
+
await s.sendText(renderPushContent(cfg, { kind: "test", title }));
|
|
121
|
+
return { ok: true, sent: 1 };
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
error: "send_failed",
|
|
127
|
+
message: e instanceof Error ? e.message : String(e),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/push/push.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeCom (企业微信) self-built-app push client — the whole outbound surface is
|
|
3
|
+
* two HTTP endpoints (push-backend-requirements §9):
|
|
4
|
+
*
|
|
5
|
+
* GET /cgi-bin/gettoken?corpid=&corpsecret= → {access_token, expires_in}
|
|
6
|
+
* POST /cgi-bin/message/send?access_token= → {errcode: 0}
|
|
7
|
+
*
|
|
8
|
+
* Zero dependencies: platform `fetch`, injectable for tests. The access token
|
|
9
|
+
* is cached with a 5-minute expiry margin; errcode 40014/42001 (invalid /
|
|
10
|
+
* expired token) triggers ONE refresh + ONE send retry — a second failure is
|
|
11
|
+
* final for that push. Callers are fire-and-forget and only warn.
|
|
12
|
+
*
|
|
13
|
+
* With `relay` configured both calls go through that base URL instead (with an
|
|
14
|
+
* `x-relay-token` header) — a reverse proxy on a static-IP host, so WeCom's
|
|
15
|
+
* 企业可信IP check (errcode 60020) only ever sees that host's egress IP.
|
|
16
|
+
*/
|
|
17
|
+
export interface WeComSender {
|
|
18
|
+
sendText(content: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/** Minimal fetch surface — the platform fetch satisfies it; tests fake it. */
|
|
21
|
+
export interface WeComFetch {
|
|
22
|
+
(url: string, init?: {
|
|
23
|
+
method?: string;
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
body?: string;
|
|
26
|
+
}): Promise<{
|
|
27
|
+
ok: boolean;
|
|
28
|
+
status: number;
|
|
29
|
+
json(): Promise<unknown>;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
export declare function createWeComSender(cfg: {
|
|
33
|
+
corpId: string;
|
|
34
|
+
agentId: number;
|
|
35
|
+
secret: string;
|
|
36
|
+
toUser: string;
|
|
37
|
+
/** Route both API calls through a static-IP relay (see file header). */
|
|
38
|
+
relay?: {
|
|
39
|
+
url: string;
|
|
40
|
+
token: string;
|
|
41
|
+
};
|
|
42
|
+
}, fetchImpl?: WeComFetch): WeComSender;
|
|
43
|
+
/** Truncate to a byte cap without splitting a UTF-8 sequence. */
|
|
44
|
+
export declare function truncateUtf8(s: string, maxBytes: number): string;
|
|
45
|
+
//# sourceMappingURL=wecom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wecom.d.ts","sourceRoot":"","sources":["../../src/push/wecom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,CACE,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1E,OAAO,CAAC;QACT,EAAE,EAAE,OAAO,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;KAC1B,CAAC,CAAC;CACJ;AAUD,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE;IACH,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACxC,EACD,SAAS,GAAE,UAAgC,GAC1C,WAAW,CA2Eb;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKhE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeCom (企业微信) self-built-app push client — the whole outbound surface is
|
|
3
|
+
* two HTTP endpoints (push-backend-requirements §9):
|
|
4
|
+
*
|
|
5
|
+
* GET /cgi-bin/gettoken?corpid=&corpsecret= → {access_token, expires_in}
|
|
6
|
+
* POST /cgi-bin/message/send?access_token= → {errcode: 0}
|
|
7
|
+
*
|
|
8
|
+
* Zero dependencies: platform `fetch`, injectable for tests. The access token
|
|
9
|
+
* is cached with a 5-minute expiry margin; errcode 40014/42001 (invalid /
|
|
10
|
+
* expired token) triggers ONE refresh + ONE send retry — a second failure is
|
|
11
|
+
* final for that push. Callers are fire-and-forget and only warn.
|
|
12
|
+
*
|
|
13
|
+
* With `relay` configured both calls go through that base URL instead (with an
|
|
14
|
+
* `x-relay-token` header) — a reverse proxy on a static-IP host, so WeCom's
|
|
15
|
+
* 企业可信IP check (errcode 60020) only ever sees that host's egress IP.
|
|
16
|
+
*/
|
|
17
|
+
const API_BASE = "https://qyapi.weixin.qq.com";
|
|
18
|
+
/** Refresh before expiry so a send never rides a token about to die. */
|
|
19
|
+
const TOKEN_MARGIN_MS = 5 * 60_000;
|
|
20
|
+
/** errcode 40014 = invalid token, 42001 = expired — both mean "refresh once". */
|
|
21
|
+
const INVALID_TOKEN_CODES = new Set([40014, 42001]);
|
|
22
|
+
/** WeCom text content cap — truncate from the end of the body. */
|
|
23
|
+
const MAX_CONTENT_BYTES = 2048;
|
|
24
|
+
export function createWeComSender(cfg, fetchImpl = fetch) {
|
|
25
|
+
const base = cfg.relay?.url ?? API_BASE;
|
|
26
|
+
const relayHeaders = cfg.relay ? { "x-relay-token": cfg.relay.token } : undefined;
|
|
27
|
+
let token = null;
|
|
28
|
+
async function readJson(resp) {
|
|
29
|
+
try {
|
|
30
|
+
return (await resp.json());
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return { errcode: resp.status, errmsg: `HTTP ${resp.status} (non-JSON body)` };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function fetchToken() {
|
|
37
|
+
const url = `${base}/cgi-bin/gettoken?corpid=${encodeURIComponent(cfg.corpId)}` +
|
|
38
|
+
`&corpsecret=${encodeURIComponent(cfg.secret)}`;
|
|
39
|
+
const body = await readJson(await fetchImpl(url, { headers: relayHeaders }));
|
|
40
|
+
if (body.errcode !== undefined && body.errcode !== 0) {
|
|
41
|
+
throw new Error(`wecom gettoken failed: ${body.errcode} ${body.errmsg ?? ""}`.trim());
|
|
42
|
+
}
|
|
43
|
+
if (!body.access_token)
|
|
44
|
+
throw new Error("wecom gettoken returned no access_token");
|
|
45
|
+
const ttl = typeof body.expires_in === "number" ? body.expires_in * 1000 : 7200_000;
|
|
46
|
+
token = {
|
|
47
|
+
value: body.access_token,
|
|
48
|
+
expiresAt: Date.now() + Math.max(ttl - TOKEN_MARGIN_MS, 60_000),
|
|
49
|
+
};
|
|
50
|
+
return body.access_token;
|
|
51
|
+
}
|
|
52
|
+
async function currentToken(force = false) {
|
|
53
|
+
if (!force && token && Date.now() < token.expiresAt)
|
|
54
|
+
return token.value;
|
|
55
|
+
return fetchToken();
|
|
56
|
+
}
|
|
57
|
+
async function postSend(t, content) {
|
|
58
|
+
const resp = await fetchImpl(`${base}/cgi-bin/message/send?access_token=${encodeURIComponent(t)}`, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: relayHeaders,
|
|
61
|
+
body: JSON.stringify({
|
|
62
|
+
touser: cfg.toUser,
|
|
63
|
+
msgtype: "text",
|
|
64
|
+
agentid: cfg.agentId,
|
|
65
|
+
text: { content },
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
return readJson(resp);
|
|
69
|
+
}
|
|
70
|
+
async function sendText(content) {
|
|
71
|
+
const bounded = truncateUtf8(content, MAX_CONTENT_BYTES);
|
|
72
|
+
let resp = await postSend(await currentToken(), bounded);
|
|
73
|
+
if (resp.errcode !== undefined && INVALID_TOKEN_CODES.has(resp.errcode)) {
|
|
74
|
+
resp = await postSend(await currentToken(true), bounded);
|
|
75
|
+
}
|
|
76
|
+
if (resp.errcode !== undefined && resp.errcode !== 0) {
|
|
77
|
+
throw new Error(`wecom message/send failed: ${resp.errcode} ${resp.errmsg ?? ""}`.trim());
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { sendText };
|
|
81
|
+
}
|
|
82
|
+
/** Truncate to a byte cap without splitting a UTF-8 sequence. */
|
|
83
|
+
export function truncateUtf8(s, maxBytes) {
|
|
84
|
+
if (Buffer.byteLength(s, "utf8") <= maxBytes)
|
|
85
|
+
return s;
|
|
86
|
+
let chars = Math.floor(maxBytes / 4); // every char is at most 4 bytes
|
|
87
|
+
while (chars > 0 && Buffer.byteLength(s.slice(0, chars), "utf8") > maxBytes)
|
|
88
|
+
chars--;
|
|
89
|
+
return `${s.slice(0, chars)}…`;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=wecom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wecom.js","sourceRoot":"","sources":["../../src/push/wecom.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,13 @@ export interface ClientLike {
|
|
|
30
30
|
* BEFORE `connect()` so the stdio connection is captured too.
|
|
31
31
|
*/
|
|
32
32
|
export declare function trackConnections(app: acp.AgentApp, clients: ClientRegistry): void;
|
|
33
|
+
/**
|
|
34
|
+
* A request fired with zero connected clients. The offline-interaction hold
|
|
35
|
+
* (server-requests.ts §6) classifies on this type: with push ACTIVE the race
|
|
36
|
+
* stays pending instead of rejecting into the auto-decline path.
|
|
37
|
+
*/
|
|
38
|
+
export declare class NoClientsError extends Error {
|
|
39
|
+
}
|
|
33
40
|
/**
|
|
34
41
|
* Registry of connected ACP clients (stdio editor + remote WebSocket clients).
|
|
35
42
|
* Membership is managed by the entry point via the SDK's per-connection
|
|
@@ -43,6 +50,14 @@ export declare class ClientRegistry {
|
|
|
43
50
|
add(cx: ClientLike): void;
|
|
44
51
|
remove(cx: ClientLike): void;
|
|
45
52
|
get size(): number;
|
|
53
|
+
/**
|
|
54
|
+
* Fired when a request finds ZERO connected clients (just before the
|
|
55
|
+
* NoClientsError throw): the offline-push hook (§5.1). Wired by the server
|
|
56
|
+
* at construction — remote-layer code must not import the push module
|
|
57
|
+
* directly (keeps the layer cycle-free). Fire-and-forget: observer throws
|
|
58
|
+
* are swallowed, the throw path always proceeds.
|
|
59
|
+
*/
|
|
60
|
+
noClientsObserver?: (method: string, params?: unknown) => void;
|
|
46
61
|
/**
|
|
47
62
|
* Record a connection's `initialize` clientInfo name, keyed by the SDK's
|
|
48
63
|
* per-connection root (same identity `notifyOthers` filters on) so payloads
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../src/remote/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAIrD,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAKjF;AAQD;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,KAAK,CAAiC;IAC9C,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IAEvD,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI;IAIzB,MAAM,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI;IAI5B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKlD,uEAAuE;IACvE,MAAM,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI;IAOrC;;;;;OAKG;IACG,UAAU,CACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAC7D,OAAO,CAAC,IAAI,CAAC;IAUhB,yEAAyE;IACzE,SAAS,IAAI,GAAG,CAAC,YAAY;IAK7B;;;;;;;;;OASG;IACG,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9F,QAAQ,IAAI,UAAU,EAAE;CAGzB"}
|
|
1
|
+
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../src/remote/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAIrD,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAKjF;AAQD;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAE5C;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,KAAK,CAAiC;IAC9C,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IAEvD,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI;IAIzB,MAAM,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI;IAI5B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAE/D;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKlD,uEAAuE;IACvE,MAAM,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI;IAOrC;;;;;OAKG;IACG,UAAU,CACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAC7D,OAAO,CAAC,IAAI,CAAC;IAUhB,yEAAyE;IACzE,SAAS,IAAI,GAAG,CAAC,YAAY;IAK7B;;;;;;;;;OASG;IACG,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9F,QAAQ,IAAI,UAAU,EAAE;CAGzB"}
|
package/dist/remote/broadcast.js
CHANGED
|
@@ -30,6 +30,13 @@ export function trackConnections(app, clients) {
|
|
|
30
30
|
void conn.closed.then(() => clients.remove(conn.client));
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* A request fired with zero connected clients. The offline-interaction hold
|
|
35
|
+
* (server-requests.ts §6) classifies on this type: with push ACTIVE the race
|
|
36
|
+
* stays pending instead of rejecting into the auto-decline path.
|
|
37
|
+
*/
|
|
38
|
+
export class NoClientsError extends Error {
|
|
39
|
+
}
|
|
33
40
|
/**
|
|
34
41
|
* Registry of connected ACP clients (stdio editor + remote WebSocket clients).
|
|
35
42
|
* Membership is managed by the entry point via the SDK's per-connection
|
|
@@ -49,6 +56,14 @@ export class ClientRegistry {
|
|
|
49
56
|
get size() {
|
|
50
57
|
return this.clients.size;
|
|
51
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Fired when a request finds ZERO connected clients (just before the
|
|
61
|
+
* NoClientsError throw): the offline-push hook (§5.1). Wired by the server
|
|
62
|
+
* at construction — remote-layer code must not import the push module
|
|
63
|
+
* directly (keeps the layer cycle-free). Fire-and-forget: observer throws
|
|
64
|
+
* are swallowed, the throw path always proceeds.
|
|
65
|
+
*/
|
|
66
|
+
noClientsObserver;
|
|
52
67
|
/**
|
|
53
68
|
* Record a connection's `initialize` clientInfo name, keyed by the SDK's
|
|
54
69
|
* per-connection root (same identity `notifyOthers` filters on) so payloads
|
|
@@ -173,7 +188,13 @@ async function notifyAll(registry, method, params) {
|
|
|
173
188
|
async function requestAny(registry, method, params, options) {
|
|
174
189
|
const clients = registry.snapshot();
|
|
175
190
|
if (clients.length === 0) {
|
|
176
|
-
|
|
191
|
+
try {
|
|
192
|
+
registry.noClientsObserver?.(method, params);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// fire-and-forget hook; never block the throw
|
|
196
|
+
}
|
|
197
|
+
throw new NoClientsError(`broadcast: no connected clients (${method})`);
|
|
177
198
|
}
|
|
178
199
|
const controllers = clients.map(() => new AbortController());
|
|
179
200
|
// Link a caller-provided signal: aborting it cancels EVERY inner request.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.js","sourceRoot":"","sources":["../../src/remote/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAQzD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAiB,EAAE,OAAuB;IACzE,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzB,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC;AAQD;;;;GAIG;AACH,MAAM,OAAO,cAAc;IACR,OAAO,GAAG,IAAI,GAAG,EAAc,CAAC;IACzC,KAAK,GAA4B,IAAI,CAAC;IAC9C,kEAAkE;IACjD,KAAK,GAAG,IAAI,OAAO,EAAkB,CAAC;IAEvD,GAAG,CAAC,EAAc;QAChB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,EAAc;QACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACH,cAAc,CAAC,EAAc,EAAE,IAAY;QACzC,MAAM,IAAI,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5E,CAAC;IAED,uEAAuE;IACvE,MAAM,CAAC,EAAc;QACnB,MAAM,IAAI,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC3D,0EAA0E;QAC1E,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,UAAU,CACd,MAAc,EACd,KAA8D;QAE9D,mEAAmE;QACnE,MAAM,OAAO,CAAC,GAAG,CACf,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;YACzB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACtC,OAAO,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACzF,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,SAAS;QACP,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,YAAY,CAAC,OAAyB,EAAE,MAAc,EAAE,MAAgB;QAC5E,MAAM,IAAI,GAAI,OAA2C,CAAC,iBAAiB,CAAC;QAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CACpC,CAAC,EAAE,EAAE,EAAE,CAAE,EAAsC,CAAC,iBAAiB,KAAK,IAAI,CAC3E,CAAC;QACF,uEAAuE;QACvE,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,QAAQ;QACN,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;CACF;AAED,kFAAkF;AAClF,SAAS,oBAAoB,CAAC,QAAwB;IACpD,MAAM,KAAK,GAA4B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3D,KAAK,CAAC,MAAM,GAAG,CAAC,MAAc,EAAE,MAAgB,EAAiB,EAAE,CACjE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,CAAC,OAAO,GAAG,CACd,MAAc,EACd,MAAgB,EAChB,OAAgC,EACd,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACrE,OAAO,KAAoC,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC,yHAAyH;AACzH,MAAM,cAAc,GAAG,IAAI,OAAO,EAAc,CAAC;AAEjD,gFAAgF;AAChF,SAAS,WAAW,CAAC,EAAc,EAAE,MAAc,EAAE,IAAmB;IACtE,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC3B,wEAAwE;QACxE,yEAAyE;QACzE,wEAAwE;QACxE,mEAAmE;QACnE,IAAI,CAAC,IAAI,CACP,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,EAC/B,GAAG,EAAE,CAAC,SAAS,CAChB,CAAC;QACF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC5B,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACvB,IAAI,CACF,cAAc,MAAM,kBAAkB,sBAAsB,mBAAmB;oBAC7E,sEAAsE,CACzE,CAAC;YACJ,CAAC;YACD,IAAI,EAAE,CAAC;QACT,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3B,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,CACP,GAAG,EAAE;YACH,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,IAAI,EAAE,CAAC;QACT,CAAC,EACD,CAAC,CAAC,EAAE,EAAE;YACJ,IAAI,CACF,cAAc,MAAM,yBAAyB;gBAC3C,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAClD,CAAC;YACF,IAAI,EAAE,CAAC;QACT,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,QAAwB,EACxB,MAAc,EACd,MAAgB;IAEhB,MAAM,OAAO,CAAC,GAAG,CACf,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CACpF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,QAAwB,EACxB,MAAc,EACd,MAAgB,EAChB,OAAgC;IAEhC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"broadcast.js","sourceRoot":"","sources":["../../src/remote/broadcast.ts"],"names":[],"mappings":"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"}
|
package/dist/remote/config.d.ts
CHANGED
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* tried in order before going headless)
|
|
29
29
|
* ZCODE_ACP_HUB_TERMINAL_COMMAND=<sh> shell command template ({script})
|
|
30
30
|
* ZCODE_ACP_WEB_DIR=<abs path> web-client dist for same-origin hosting
|
|
31
|
-
* (file `remote.webDir` wins; empty = off
|
|
31
|
+
* (file `remote.webDir` wins; empty = off;
|
|
32
|
+
* a leading ~ is expanded to the home dir)
|
|
32
33
|
* 3. Built-in defaults.
|
|
33
34
|
*
|
|
34
35
|
* Process-role plumbing stays env-only by design (never file-configurable):
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/remote/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/remote/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9F,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC3B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAiC5C,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,YAAY,GAAG,IAAI,CAmB3F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAK/E;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,YAAY,GAAG,IAAI,CAexF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,aAAa,CAyBvF"}
|
package/dist/remote/config.js
CHANGED
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* tried in order before going headless)
|
|
29
29
|
* ZCODE_ACP_HUB_TERMINAL_COMMAND=<sh> shell command template ({script})
|
|
30
30
|
* ZCODE_ACP_WEB_DIR=<abs path> web-client dist for same-origin hosting
|
|
31
|
-
* (file `remote.webDir` wins; empty = off
|
|
31
|
+
* (file `remote.webDir` wins; empty = off;
|
|
32
|
+
* a leading ~ is expanded to the home dir)
|
|
32
33
|
* 3. Built-in defaults.
|
|
33
34
|
*
|
|
34
35
|
* Process-role plumbing stays env-only by design (never file-configurable):
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
* ZCODE_ACP_REMOTE_PIN_CWD=1 pin session roots to the process cwd
|
|
37
38
|
* ZCODE_ACP_RESUME_SESSION=<id> per-request boot-resume target (ADR-0017)
|
|
38
39
|
*/
|
|
39
|
-
import { loadUserConfig } from "../config/user-config.js";
|
|
40
|
+
import { expandHomePath, loadUserConfig } from "../config/user-config.js";
|
|
40
41
|
import { warn } from "../utils.js";
|
|
41
42
|
export const DEFAULT_HUB_PORT = 8377;
|
|
42
43
|
export const DEFAULT_BRIDGE_PORT = 8378;
|
|
@@ -60,7 +61,7 @@ function mergeCommon(env) {
|
|
|
60
61
|
hubHost: file.hubHost ?? ((env.ZCODE_ACP_HUB_HOST ?? "").trim() || DEFAULT_HUB_HOST),
|
|
61
62
|
bridgePort: file.bridgePort ??
|
|
62
63
|
parsePort(env.ZCODE_ACP_REMOTE_PORT, DEFAULT_BRIDGE_PORT, "ZCODE_ACP_REMOTE_PORT"),
|
|
63
|
-
webDir: file.webDir ?? (env.ZCODE_ACP_WEB_DIR ?? "").trim(),
|
|
64
|
+
webDir: file.webDir ?? expandHomePath((env.ZCODE_ACP_WEB_DIR ?? "").trim()),
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
67
|
/** Parse remote config; null = disabled (or misconfigured → warned). */
|