@zhin.js/gateway 1.2.0 → 1.4.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 (61) hide show
  1. package/README.md +1 -1
  2. package/lib/config/configuration.d.ts +32 -3
  3. package/lib/config/configuration.js +120 -25
  4. package/lib/config/environment-files.d.ts +42 -0
  5. package/lib/config/environment-files.js +347 -7
  6. package/lib/config/literal-secrets.d.ts +3 -0
  7. package/lib/config/literal-secrets.js +4 -1
  8. package/lib/config/patch-path-messages.d.ts +15 -0
  9. package/lib/config/patch-path-messages.js +71 -0
  10. package/lib/config/secret-storage.d.ts +42 -0
  11. package/lib/config/secret-storage.js +140 -0
  12. package/lib/config/validation-messages.d.ts +15 -0
  13. package/lib/config/validation-messages.js +66 -0
  14. package/lib/config.d.ts +1 -0
  15. package/lib/config.js +1 -0
  16. package/lib/database/console-role.js +2 -1
  17. package/lib/http/console-rpc.d.ts +3 -1
  18. package/lib/http/console-rpc.js +31 -4
  19. package/lib/http/gateway-console.d.ts +5 -0
  20. package/lib/http/gateway-console.js +31 -5
  21. package/lib/http/gateway-http-server.d.ts +2 -0
  22. package/lib/http/gateway-http-server.js +42 -1
  23. package/lib/http/local-principal.d.ts +1 -1
  24. package/lib/http/local-principal.js +3 -2
  25. package/lib/http/plugin-switch-rpc.js +7 -6
  26. package/lib/http/start-gateway.d.ts +1 -1
  27. package/lib/http/start-gateway.js +2 -0
  28. package/lib/iam/service.js +12 -0
  29. package/lib/iam/setup-service.d.ts +3 -1
  30. package/lib/iam/setup-service.js +2 -1
  31. package/lib/onboarding/ignored-builds.d.ts +18 -0
  32. package/lib/onboarding/ignored-builds.js +63 -0
  33. package/lib/onboarding/index.d.ts +1 -0
  34. package/lib/onboarding/index.js +1 -0
  35. package/lib/packages/errors.js +1 -0
  36. package/lib/packages/rpc.d.ts +6 -1
  37. package/lib/packages/rpc.js +28 -2
  38. package/lib/packages/service.d.ts +3 -1
  39. package/lib/packages/service.js +74 -9
  40. package/lib/plugin-management/plugin-candidates.d.ts +9 -0
  41. package/lib/plugin-management/plugin-candidates.js +55 -0
  42. package/lib/plugin-management/use-cases.js +8 -8
  43. package/lib/plugin-management/workflow.d.ts +13 -2
  44. package/lib/plugin-management/workflow.js +46 -13
  45. package/lib/plugin-management.d.ts +1 -0
  46. package/lib/plugin-management.js +1 -0
  47. package/lib/project/identity.d.ts +2 -0
  48. package/lib/project/identity.js +21 -0
  49. package/lib/project.d.ts +1 -0
  50. package/lib/project.js +1 -0
  51. package/lib/supervisor/instance-supervisor.d.ts +4 -1
  52. package/lib/supervisor/instance-supervisor.js +18 -1
  53. package/lib/terminal/modules.d.ts +12 -0
  54. package/lib/terminal/modules.js +38 -2
  55. package/lib/usage/aggregate.d.ts +64 -3
  56. package/lib/usage/aggregate.js +199 -26
  57. package/lib/usage/prompt-cache.d.ts +49 -0
  58. package/lib/usage/prompt-cache.js +113 -0
  59. package/lib/usage.d.ts +1 -0
  60. package/lib/usage.js +1 -0
  61. package/package.json +8 -8
@@ -0,0 +1,113 @@
1
+ /** Defaults: at least 20 consecutive zero-cache calls across at least 3 sessions. */
2
+ export const PROMPT_CACHE_HINT_MIN_CALLS = 20;
3
+ export const PROMPT_CACHE_HINT_MIN_SESSIONS = 3;
4
+ /** Share of adjacent same-session requests with an identical prefix needed as evidence. */
5
+ export const PROMPT_CACHE_HINT_MIN_SAME_PREFIX = 0.5;
6
+ function emptyStreak(label) {
7
+ return { ...(label ? { label } : {}), providerIds: new Set(), calls: 0, reportedZero: 0, sessions: new Set(), compared: 0, same: 0, lastPrefix: new Map() };
8
+ }
9
+ function num(value) {
10
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;
11
+ }
12
+ /**
13
+ * Feed trace records in chronological order ({@link visit}), then read {@link hints}.
14
+ * Sub-agent turns are included with their own session keys.
15
+ */
16
+ export class PromptCacheProbe {
17
+ #streaks = new Map();
18
+ #resolved = new Map();
19
+ #options;
20
+ constructor(options = {}) {
21
+ this.#options = options;
22
+ }
23
+ visit(trace) {
24
+ if (!trace || typeof trace !== 'object')
25
+ return;
26
+ const session = typeof trace.session_key === 'string' ? trace.session_key : '';
27
+ const calls = Array.isArray(trace.model_calls) ? trace.model_calls : [];
28
+ for (const raw of calls)
29
+ this.#call(raw, session);
30
+ const children = Array.isArray(trace.subagents) ? trace.subagents : [];
31
+ for (const child of children)
32
+ this.visit(child);
33
+ }
34
+ hints() {
35
+ const minCalls = this.#options.minCalls ?? PROMPT_CACHE_HINT_MIN_CALLS;
36
+ const minSessions = this.#options.minSessions ?? PROMPT_CACHE_HINT_MIN_SESSIONS;
37
+ const minRatio = this.#options.minSamePrefixRatio ?? PROMPT_CACHE_HINT_MIN_SAME_PREFIX;
38
+ const out = [];
39
+ for (const [provider, streak] of this.#streaks) {
40
+ if (streak.calls < minCalls || streak.sessions.size < minSessions || streak.compared === 0)
41
+ continue;
42
+ const ratio = streak.same / streak.compared;
43
+ if (ratio < minRatio)
44
+ continue;
45
+ const name = streak.label ?? provider;
46
+ const percent = Math.round(ratio * 100);
47
+ out.push(Object.freeze({
48
+ provider,
49
+ ...(streak.label ? { label: streak.label } : {}),
50
+ providerIds: Object.freeze([...streak.providerIds].sort()),
51
+ zeroCacheCalls: streak.calls,
52
+ sessions: streak.sessions.size,
53
+ reportedZeroCalls: streak.reportedZero,
54
+ comparedPairs: streak.compared,
55
+ samePrefixPairs: streak.same,
56
+ samePrefixRatio: ratio,
57
+ message: `${name}:最近连续 ${streak.calls} 次请求(${streak.sessions.size} 个会话)没有命中提示缓存,`
58
+ + `而相邻请求有 ${percent}%(${streak.same}/${streak.compared})前缀相同——该服务可能不支持或未透传 prompt 缓存。`,
59
+ }));
60
+ }
61
+ return out.sort((a, b) => b.zeroCacheCalls - a.zeroCacheCalls);
62
+ }
63
+ #resolve(recorded) {
64
+ const resolveProvider = this.#options.resolveProvider;
65
+ if (!resolveProvider)
66
+ return undefined;
67
+ if (!this.#resolved.has(recorded)) {
68
+ let value;
69
+ try {
70
+ value = resolveProvider(recorded);
71
+ }
72
+ catch {
73
+ value = undefined;
74
+ }
75
+ this.#resolved.set(recorded, value);
76
+ }
77
+ return this.#resolved.get(recorded);
78
+ }
79
+ #call(call, session) {
80
+ const prompt = num(call.prompt_tokens);
81
+ if (prompt === undefined || prompt === 0)
82
+ return;
83
+ const recorded = typeof call.provider === 'string' && call.provider ? call.provider : 'unknown';
84
+ const service = this.#resolve(recorded);
85
+ const key = service?.key ?? recorded;
86
+ const cacheRead = num(call.cache_read_tokens);
87
+ if (cacheRead !== undefined && cacheRead > 0) {
88
+ // A cache hit ends the run: this provider does cache.
89
+ this.#streaks.set(key, emptyStreak(service?.label));
90
+ return;
91
+ }
92
+ let streak = this.#streaks.get(key);
93
+ if (!streak) {
94
+ streak = emptyStreak(service?.label);
95
+ this.#streaks.set(key, streak);
96
+ }
97
+ streak.providerIds.add(recorded);
98
+ streak.calls += 1;
99
+ if (cacheRead === 0)
100
+ streak.reportedZero += 1;
101
+ streak.sessions.add(session);
102
+ const prefix = typeof call.prefix_hash === 'string' && call.prefix_hash ? call.prefix_hash : undefined;
103
+ if (prefix) {
104
+ const previous = streak.lastPrefix.get(session);
105
+ if (previous !== undefined) {
106
+ streak.compared += 1;
107
+ if (previous === prefix)
108
+ streak.same += 1;
109
+ }
110
+ streak.lastPrefix.set(session, prefix);
111
+ }
112
+ }
113
+ }
package/lib/usage.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  /** `@zhin.js/gateway/usage` — usage statistics aggregation. */
2
2
  export * from './usage/aggregate.js';
3
+ export * from './usage/prompt-cache.js';
package/lib/usage.js CHANGED
@@ -1,2 +1,3 @@
1
1
  /** `@zhin.js/gateway/usage` — usage statistics aggregation. */
2
2
  export * from './usage/aggregate.js';
3
+ export * from './usage/prompt-cache.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/gateway",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Zhin.js management gateway: Console access control, terminal, project configuration and instance supervision (ADR 0054)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -72,13 +72,13 @@
72
72
  "fs-extra": "^11.4.0",
73
73
  "tsx": "^4.23.1",
74
74
  "yaml": "^2.9.0",
75
- "@zhin.js/console-protocol": "1.2.2",
76
- "@zhin.js/database": "1.2.0",
77
- "@zhin.js/host-http": "1.2.2",
78
- "@zhin.js/logger": "1.1.3",
79
- "@zhin.js/plugin-runtime": "1.2.1",
80
- "@zhin.js/runtime": "1.2.2",
81
- "@zhin.js/scaffold-wizard": "1.1.21"
75
+ "@zhin.js/console-protocol": "1.4.0",
76
+ "@zhin.js/database": "1.2.1",
77
+ "@zhin.js/host-http": "1.4.0",
78
+ "@zhin.js/logger": "1.2.0",
79
+ "@zhin.js/plugin-runtime": "1.3.0",
80
+ "@zhin.js/runtime": "1.4.0",
81
+ "@zhin.js/scaffold-wizard": "1.3.0"
82
82
  },
83
83
  "optionalDependencies": {
84
84
  "node-pty": "^1.0.0",