@evomap/evolver-proxy 2.0.0-beta.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.
Files changed (82) hide show
  1. package/README.md +49 -0
  2. package/dist/bin/envFile.d.ts +10 -0
  3. package/dist/bin/envFile.js +68 -0
  4. package/dist/bin/evolver-llm-proxy.d.ts +2 -0
  5. package/dist/bin/evolver-llm-proxy.js +111 -0
  6. package/dist/bin/evolver-proxy.d.ts +83 -0
  7. package/dist/bin/evolver-proxy.js +511 -0
  8. package/dist/bin/proxySettings.d.ts +15 -0
  9. package/dist/bin/proxySettings.js +84 -0
  10. package/dist/bin/proxyStorePath.d.ts +1 -0
  11. package/dist/bin/proxyStorePath.js +16 -0
  12. package/dist/daemon/atpConsent.d.ts +13 -0
  13. package/dist/daemon/atpConsent.js +60 -0
  14. package/dist/daemon/ipcConfig.d.ts +1 -0
  15. package/dist/daemon/ipcConfig.js +13 -0
  16. package/dist/daemon/proxyDaemon.d.ts +191 -0
  17. package/dist/daemon/proxyDaemon.js +1015 -0
  18. package/dist/daemon/selectHub.d.ts +16 -0
  19. package/dist/daemon/selectHub.js +30 -0
  20. package/dist/index.d.ts +8 -0
  21. package/dist/index.js +8 -0
  22. package/dist/lifecycle/deployGuard.d.ts +46 -0
  23. package/dist/lifecycle/deployGuard.js +53 -0
  24. package/dist/lifecycle/legacyNodeId.d.ts +96 -0
  25. package/dist/lifecycle/legacyNodeId.js +163 -0
  26. package/dist/lifecycle/manager.d.ts +106 -0
  27. package/dist/lifecycle/manager.js +390 -0
  28. package/dist/llm/bodyCapture.d.ts +31 -0
  29. package/dist/llm/bodyCapture.js +293 -0
  30. package/dist/llm/index.d.ts +3 -0
  31. package/dist/llm/index.js +3 -0
  32. package/dist/llm/server.d.ts +35 -0
  33. package/dist/llm/server.js +359 -0
  34. package/dist/llm/traceBackfill.d.ts +53 -0
  35. package/dist/llm/traceBackfill.js +525 -0
  36. package/dist/llm/traceConfig.d.ts +7 -0
  37. package/dist/llm/traceConfig.js +44 -0
  38. package/dist/llm/traceControl.d.ts +16 -0
  39. package/dist/llm/traceControl.js +85 -0
  40. package/dist/llm/traceEnvelope.d.ts +75 -0
  41. package/dist/llm/traceEnvelope.js +286 -0
  42. package/dist/llm/traceSink.d.ts +61 -0
  43. package/dist/llm/traceSink.js +278 -0
  44. package/dist/llm/traceUploadPayload.d.ts +14 -0
  45. package/dist/llm/traceUploadPayload.js +27 -0
  46. package/dist/llm/upstream.d.ts +68 -0
  47. package/dist/llm/upstream.js +491 -0
  48. package/dist/private/adapterLoader.d.ts +46 -0
  49. package/dist/private/adapterLoader.js +62 -0
  50. package/dist/private/privateRuntimeSmokeOptions.d.ts +15 -0
  51. package/dist/private/privateRuntimeSmokeOptions.js +132 -0
  52. package/dist/router/cachePassthrough.d.ts +3 -0
  53. package/dist/router/cachePassthrough.js +13 -0
  54. package/dist/router/features.d.ts +9 -0
  55. package/dist/router/features.js +52 -0
  56. package/dist/router/index.d.ts +6 -0
  57. package/dist/router/index.js +6 -0
  58. package/dist/router/messagesRoute.d.ts +138 -0
  59. package/dist/router/messagesRoute.js +753 -0
  60. package/dist/router/modelRouter.d.ts +49 -0
  61. package/dist/router/modelRouter.js +66 -0
  62. package/dist/router/providerRoutes.d.ts +42 -0
  63. package/dist/router/providerRoutes.js +1579 -0
  64. package/dist/router/sseScan.d.ts +56 -0
  65. package/dist/router/sseScan.js +543 -0
  66. package/dist/selfUpdate/executor.d.ts +90 -0
  67. package/dist/selfUpdate/executor.js +179 -0
  68. package/dist/selfUpdate/failureCodes.d.ts +33 -0
  69. package/dist/selfUpdate/failureCodes.js +84 -0
  70. package/dist/selfUpdate/index.d.ts +5 -0
  71. package/dist/selfUpdate/index.js +5 -0
  72. package/dist/selfUpdate/lastUpdate.d.ts +43 -0
  73. package/dist/selfUpdate/lastUpdate.js +195 -0
  74. package/dist/selfUpdate/policy.d.ts +3 -0
  75. package/dist/selfUpdate/policy.js +9 -0
  76. package/dist/selfUpdate/releaseBinary.d.ts +56 -0
  77. package/dist/selfUpdate/releaseBinary.js +498 -0
  78. package/dist/selfUpdate/version.d.ts +2 -0
  79. package/dist/selfUpdate/version.js +14 -0
  80. package/dist/sync/engine.d.ts +65 -0
  81. package/dist/sync/engine.js +461 -0
  82. package/package.json +41 -0
@@ -0,0 +1,60 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { events } from '@evomap/evolver-core';
4
+ export class AtpProxySpendConsentError extends Error {
5
+ source;
6
+ constructor(source) {
7
+ super(`autonomous ATP order refused: auto-spend consent is disabled (source: ${source})`);
8
+ this.source = source;
9
+ this.name = 'AtpProxySpendConsentError';
10
+ }
11
+ }
12
+ function atpProxyConsentPath(env = process.env) {
13
+ const home = env['EVOMAP_DIR'] ?? env['EVOLVER_HOME'] ?? env['EVOMAP_HOME'] ?? events.evomapHome();
14
+ return join(home, 'evolution', 'atp-autobuy-ack.json');
15
+ }
16
+ export function getAtpProxyConsent(env = process.env, ackPath = atpProxyConsentPath(env)) {
17
+ const override = envOverride(env);
18
+ if (override !== null)
19
+ return { enabled: override, source: 'env' };
20
+ const ack = readAck(ackPath);
21
+ if (typeof ack === 'boolean')
22
+ return { enabled: ack, source: 'ack' };
23
+ return { enabled: false, source: 'default' };
24
+ }
25
+ export function createAtpOrderConsentGate(env = process.env, ackPath = atpProxyConsentPath(env)) {
26
+ return {
27
+ assertAllowed() {
28
+ const consent = getAtpProxyConsent(env, ackPath);
29
+ if (!consent.enabled)
30
+ throw new AtpProxySpendConsentError(consent.source);
31
+ },
32
+ };
33
+ }
34
+ function readAck(path) {
35
+ try {
36
+ if (!existsSync(path))
37
+ return null;
38
+ const raw = JSON.parse(readFileSync(path, 'utf8'));
39
+ if (raw && typeof raw === 'object' && typeof raw.enabled === 'boolean') {
40
+ return raw.enabled;
41
+ }
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ return null;
47
+ }
48
+ function envOverride(env) {
49
+ const raw = env['EVOLVER_ATP_AUTOBUY'];
50
+ if (typeof raw !== 'string')
51
+ return null;
52
+ const s = raw.trim().toLowerCase();
53
+ if (!s)
54
+ return null;
55
+ if (s === 'on' || s === '1' || s === 'true' || s === 'yes' || s === 'enable' || s === 'enabled')
56
+ return true;
57
+ if (s === 'off' || s === '0' || s === 'false' || s === 'no' || s === 'disable' || s === 'disabled' || s === 'none')
58
+ return false;
59
+ return false;
60
+ }
@@ -0,0 +1 @@
1
+ export declare function resolveIpcPort(env: Record<string, string | undefined>): number | undefined;
@@ -0,0 +1,13 @@
1
+ export function resolveIpcPort(env) {
2
+ const explicitRaw = env['EVOLVER_IPC_PORT']?.trim();
3
+ const legacyRaw = env['EVOMAP_PROXY_PORT']?.trim();
4
+ const raw = explicitRaw || legacyRaw;
5
+ if (!raw)
6
+ return undefined;
7
+ const port = Number(raw);
8
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
9
+ const key = explicitRaw ? 'EVOLVER_IPC_PORT' : 'EVOMAP_PROXY_PORT';
10
+ throw new Error(`${key} invalid: ${raw} (expected integer 0..65535)`);
11
+ }
12
+ return port;
13
+ }
@@ -0,0 +1,191 @@
1
+ import { mailbox, hub as hubNs, shadow as shadow_, assetstore } from '@evomap/evolver-core';
2
+ import { SyncEngine, type OutboundResult, type InboundResult } from '../sync/engine.js';
3
+ import { LifecycleManager, type HelloLifecycleMode, type HelloResult, type HeartbeatOptions, type HeartbeatResult, type HeartbeatTickResult } from '../lifecycle/manager.js';
4
+ import { type SelfUpdateDeps } from '../selfUpdate/executor.js';
5
+ import type { AtpOrderConsentGate } from './atpConsent.js';
6
+ type HubCapability = hubNs.HubCapability;
7
+ type AssetStoreProvider = assetstore.AssetStoreProvider;
8
+ export declare const DEFAULT_IPC_PORT = 19820;
9
+ export interface ProxyDaemonDeps {
10
+ hub: HubCapability;
11
+ /** 二选一: 传 storePath 让 ProxyDaemon 建 store, 或传已建 store(供 hub senderId 共享同一 node_id). */
12
+ storePath?: string;
13
+ store?: mailbox.MailboxStore;
14
+ ipcToken: string;
15
+ ipcPort?: number;
16
+ ipcHost?: string;
17
+ runtimeNamespace?: string;
18
+ now?: () => number;
19
+ /** Random source for heartbeat force_update staggering. Defaults to Math.random; tests inject a deterministic value. */
20
+ random?: () => number;
21
+ /** 注入 adapter 的 /a2a/hello + heartbeat wire 调用(M6-6 提供; M6-4 测试用 fake). evolverVersion 随报供 hub 观测. */
22
+ hello: (opts: {
23
+ rotate: boolean;
24
+ evolverVersion?: string;
25
+ }) => Promise<HelloResult>;
26
+ heartbeat: (opts?: HeartbeatOptions) => Promise<HeartbeatResult>;
27
+ helloMode?: HelloLifecycleMode;
28
+ lockPath?: string;
29
+ /** M8 shadow: 'shadow'=publish/settle/push/complete/fail 只记录不执行(默认 enforce 正常). */
30
+ shadowMode?: shadow_.ShadowMode;
31
+ shadowSink?: shadow_.ShadowSink;
32
+ /** 本地资产库: 支撑 /asset/* 与 /conversation/distill 的 Proxy MCP 兼容端点. */
33
+ assetStore?: AssetStoreProvider;
34
+ /** 未显式传 assetStore 时, 用该目录创建 LocalJsonlProvider; 缺省跟随 storePath 同目录. */
35
+ assetStoreDir?: string;
36
+ /** 可选 ATP 兼容路由实现. ProxyDaemon 只依赖窄接口; public/private adapter 在 bin 层装配. */
37
+ atp?: AtpProxyClient;
38
+ /** Consent gate for local /atp/order spend attempts. Missing gate fails closed. */
39
+ atpOrderConsent?: AtpOrderConsentGate;
40
+ /**
41
+ * #108 自更新执行配置. 缺省 = 不接(force_update 入站只标完成, 不下载/不重启 — 半成品通道默认 OFF 的风险闸).
42
+ * 提供时, force_update 入站经 core handler → executeForceUpdate(decide→verify→replace→restart).
43
+ * download/atomicReplace/restart 是注入 I/O seam(bin 接真实, 测试用 fake); policy=off 时永不落地.
44
+ */
45
+ selfUpdate?: Omit<SelfUpdateDeps, 'currentVersion'> & {
46
+ currentVersion?: string;
47
+ };
48
+ /** 当前 evolver 版本(getCurrentVersion); 随 hello/heartbeat 上报 hub(fleet 观测) + 喂 decideUpdate 的 current. */
49
+ evolverVersion?: string;
50
+ /** Best-effort hook for repairing local discovery state after a failed IPC auth attempt. */
51
+ onIpcAuthFailure?: () => void;
52
+ /** Best-effort hook after IPC is listening but before initial hello can block on Hub I/O. */
53
+ onIpcListen?: (port: number) => void;
54
+ /** Optional LLM trace backfill source. The daemon uses the shared mailbox store to continue bounded drains after outbound capacity frees. */
55
+ traceBackfill?: {
56
+ dir: string;
57
+ env?: NodeJS.ProcessEnv;
58
+ };
59
+ }
60
+ export interface ProxyTickReport {
61
+ outbound: OutboundResult;
62
+ inbound: InboundResult;
63
+ heartbeat?: HeartbeatTickResult;
64
+ errors?: ProxyTickError[];
65
+ failedPhases?: ProxyTickPhase[];
66
+ fatalCandidate?: boolean;
67
+ }
68
+ export type ProxyTickPhase = 'core' | 'outbound' | 'inbound' | 'heartbeat';
69
+ export interface ProxyTickError {
70
+ phase: ProxyTickPhase;
71
+ message: string;
72
+ }
73
+ export interface ProxyHealth {
74
+ running: boolean;
75
+ ipcListening: boolean;
76
+ nodeId?: string;
77
+ lastWriteAt: number;
78
+ }
79
+ export interface AtpProxyClient {
80
+ placeOrder(opts: {
81
+ capabilities: readonly string[];
82
+ budget?: number;
83
+ routingMode?: string;
84
+ verifyMode?: string;
85
+ question?: string;
86
+ signals?: readonly string[];
87
+ minReputation?: number;
88
+ }): Promise<unknown>;
89
+ submitDelivery(orderId: string, proofPayload?: unknown): Promise<unknown>;
90
+ verifyDelivery(orderId: string, action?: string): Promise<unknown>;
91
+ settleOrder(orderId: string): Promise<unknown>;
92
+ disputeOrder(orderId: string, reason: string): Promise<unknown>;
93
+ getMerchantTier(nodeId?: string): Promise<unknown>;
94
+ getOrderStatus(orderId: string): Promise<unknown>;
95
+ listProofs(opts?: {
96
+ nodeId?: string;
97
+ role?: string;
98
+ status?: string;
99
+ limit?: number;
100
+ }): Promise<unknown>;
101
+ getAtpPolicy(): Promise<unknown>;
102
+ }
103
+ /**
104
+ * ProxyDaemon(M6-4) 装配层: 把 core(MailboxStore/Dispatcher/MailboxDaemon/IpcServer) +
105
+ * HubBindings(M6-1) + SyncEngine(M6-2) + LifecycleManager(M6-3) 拼成系统级 proxy.
106
+ * 职责分工(避免双 claim): MailboxDaemon 只 pump 'core'(本地确定性); proxy 出站归 SyncEngine.syncOutbound;
107
+ * inbound 由 SyncEngine.syncInbound 从 hub 拉; agent 消息留给 runtime 经 IPC claim.
108
+ */
109
+ export declare class ProxyDaemon {
110
+ private readonly deps;
111
+ readonly store: mailbox.MailboxStore;
112
+ readonly dispatcher: mailbox.Dispatcher;
113
+ readonly daemon: mailbox.MailboxDaemon;
114
+ readonly sync: SyncEngine;
115
+ readonly lifecycle: LifecycleManager;
116
+ private readonly assetStore;
117
+ private readonly remoteAssetById;
118
+ private readonly reuseResultReporter;
119
+ private readonly validator;
120
+ private readonly atp;
121
+ private ipc;
122
+ private readonly now;
123
+ private readonly random;
124
+ private nextHeartbeatAt;
125
+ private heartbeatFailures;
126
+ private heartbeatGeneration;
127
+ /** Resolver for an in-flight runner sleep(); set while sleeping, called to wake early on poke. */
128
+ private wakeRunnerResolve;
129
+ /** A poke that arrived between ticks (no sleep in flight) parks the wake here so it is not lost. */
130
+ private wakeRunnerPending;
131
+ private started;
132
+ private storeClosed;
133
+ private forceUpdateTriggerInFlight;
134
+ private forceUpdateLastTriggeredAt;
135
+ private forceUpdateLastTriggeredKey;
136
+ private pendingForceUpdateDirective;
137
+ private forceUpdateTimer;
138
+ private scheduledForceUpdateKey;
139
+ private traceBackfillDraining;
140
+ private loopWakeHandler;
141
+ constructor(deps: ProxyDaemonDeps);
142
+ /**
143
+ * core handler(确定性, 不经 agent): 目前只接 force_update(#108). 其他 core 类型(asset_publish_result/
144
+ * feature_flag_update)仍由 Material/上层处理, 这里 no-op 标完成. force_update 仅当装配了 selfUpdate 才执行;
145
+ * 否则只标完成(不下载/不重启 — 默认 OFF 风险闸). 永不抛: 失败转结构化 telemetry, daemon 续跑旧版本.
146
+ */
147
+ private handleCore;
148
+ private recordTickError;
149
+ /** 启动: 锁 + IPC 监听 + 初次 hello. 返回 IPC 端口. */
150
+ start(): Promise<number>;
151
+ /** 单轮: core pump/TTL/wake + proxy 出站 + hub 入站 + 到点心跳. */
152
+ tick(): Promise<ProxyTickReport>;
153
+ /** 下一轮建议延时: inbound 背压/idle 与 outbound pending cadence 取更快者. */
154
+ nextDelay(last: InboundResult): number;
155
+ setWakeHandler(wake: (() => void) | undefined): void;
156
+ notifyNewOutbound(): void;
157
+ /**
158
+ * Expedite the next heartbeat: clear the failure backoff, mark the heartbeat due now, and wake an
159
+ * in-flight runner sleep() so the next tick runs immediately. Wake-on-event for the pull-based
160
+ * loop — the interruptible sleep() lets this preempt a long backoff wait the way V1's timer-driven
161
+ * loop did (which armed a 0ms timer). The generation bump prevents a tick that was already in
162
+ * flight from overwriting this reschedule. No-op until the daemon is started.
163
+ */
164
+ pokeHeartbeatLoop(): void;
165
+ /**
166
+ * Interruptible delay for the resident runner loop (bin/evolver-proxy.ts): resolves after `ms`, OR
167
+ * immediately when pokeHeartbeatLoop() fires while sleeping. A poke that lands between ticks (before
168
+ * the next sleep starts) sets wakeRunnerPending so the wake is not lost. The timer is unref'd so it
169
+ * never keeps the process alive on its own.
170
+ */
171
+ sleep(ms: number): Promise<void>;
172
+ private wakeRunner;
173
+ health(): ProxyHealth;
174
+ stop(): Promise<void>;
175
+ private closeIpc;
176
+ private closeIpcBestEffort;
177
+ private closeStoreOnce;
178
+ private drainProxyTraceBackfill;
179
+ private recordHeartbeatResult;
180
+ private recordHeartbeatTickException;
181
+ private executeAndReportForceUpdate;
182
+ private triggerForceUpdateFromHeartbeat;
183
+ private startForceUpdateExecution;
184
+ private reportPendingForceUpdate;
185
+ private stateNumber;
186
+ private handleProxyRoute;
187
+ private searchAssets;
188
+ private handleAtpRoute;
189
+ private writeAtpJson;
190
+ }
191
+ export {};