@zhin.js/gateway 0.0.0-stage → 1.1.1

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 (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -2
  3. package/lib/config/ai-config-loader.d.ts +22 -0
  4. package/lib/config/ai-config-loader.js +96 -0
  5. package/lib/config/configuration-chat-policy.d.ts +57 -0
  6. package/lib/config/configuration-chat-policy.js +423 -0
  7. package/lib/config/configuration-patch.d.ts +16 -0
  8. package/lib/config/configuration-patch.js +105 -0
  9. package/lib/config/configuration-path.d.ts +6 -0
  10. package/lib/config/configuration-path.js +40 -0
  11. package/lib/config/configuration-projection.d.ts +6 -0
  12. package/lib/config/configuration-projection.js +28 -0
  13. package/lib/config/configuration-redaction.d.ts +24 -0
  14. package/lib/config/configuration-redaction.js +128 -0
  15. package/lib/config/configuration.d.ts +81 -0
  16. package/lib/config/configuration.js +686 -0
  17. package/lib/config/console-schema.d.ts +11 -0
  18. package/lib/config/console-schema.js +222 -0
  19. package/lib/config/environment-files.d.ts +2 -0
  20. package/lib/config/environment-files.js +21 -0
  21. package/lib/config/plugin-package-map.d.ts +2 -0
  22. package/lib/config/plugin-package-map.js +14 -0
  23. package/lib/config/plugin-schema-catalog.d.ts +22 -0
  24. package/lib/config/plugin-schema-catalog.js +262 -0
  25. package/lib/config.d.ts +12 -0
  26. package/lib/config.js +12 -0
  27. package/lib/database/config.d.ts +22 -0
  28. package/lib/database/config.js +159 -0
  29. package/lib/database/index.d.ts +2 -0
  30. package/lib/database/index.js +2 -0
  31. package/lib/database/project-database.d.ts +31 -0
  32. package/lib/database/project-database.js +130 -0
  33. package/lib/database.d.ts +2 -0
  34. package/lib/database.js +2 -0
  35. package/lib/http/console-rpc.d.ts +19 -0
  36. package/lib/http/console-rpc.js +51 -0
  37. package/lib/http/gateway-console.d.ts +63 -0
  38. package/lib/http/gateway-console.js +309 -0
  39. package/lib/http/gateway-events.d.ts +35 -0
  40. package/lib/http/gateway-events.js +172 -0
  41. package/lib/http/gateway-http-server.d.ts +95 -0
  42. package/lib/http/gateway-http-server.js +518 -0
  43. package/lib/http/local-principal.d.ts +2 -0
  44. package/lib/http/local-principal.js +16 -0
  45. package/lib/http/run-gateway.d.ts +43 -0
  46. package/lib/http/run-gateway.js +268 -0
  47. package/lib/http/start-gateway.d.ts +114 -0
  48. package/lib/http/start-gateway.js +220 -0
  49. package/lib/http-response.d.ts +6 -0
  50. package/lib/http-response.js +25 -0
  51. package/lib/http.d.ts +6 -0
  52. package/lib/http.js +6 -0
  53. package/lib/iam/crypto.d.ts +12 -0
  54. package/lib/iam/crypto.js +58 -0
  55. package/lib/iam/index.d.ts +8 -0
  56. package/lib/iam/index.js +8 -0
  57. package/lib/iam/install.d.ts +36 -0
  58. package/lib/iam/install.js +74 -0
  59. package/lib/iam/local-admin.d.ts +27 -0
  60. package/lib/iam/local-admin.js +102 -0
  61. package/lib/iam/rate-limit.d.ts +15 -0
  62. package/lib/iam/rate-limit.js +52 -0
  63. package/lib/iam/routes.d.ts +23 -0
  64. package/lib/iam/routes.js +157 -0
  65. package/lib/iam/rpc.d.ts +14 -0
  66. package/lib/iam/rpc.js +100 -0
  67. package/lib/iam/service.d.ts +203 -0
  68. package/lib/iam/service.js +784 -0
  69. package/lib/iam/setup-service.d.ts +83 -0
  70. package/lib/iam/setup-service.js +206 -0
  71. package/lib/iam/tables.d.ts +20 -0
  72. package/lib/iam/tables.js +82 -0
  73. package/lib/iam.d.ts +2 -0
  74. package/lib/iam.js +2 -0
  75. package/lib/index.d.ts +22 -0
  76. package/lib/index.js +22 -0
  77. package/lib/local/client.d.ts +71 -0
  78. package/lib/local/client.js +296 -0
  79. package/lib/local/handler.d.ts +30 -0
  80. package/lib/local/handler.js +86 -0
  81. package/lib/local/local-socket.d.ts +55 -0
  82. package/lib/local/local-socket.js +232 -0
  83. package/lib/local/paths.d.ts +34 -0
  84. package/lib/local/paths.js +58 -0
  85. package/lib/local/protocol.d.ts +140 -0
  86. package/lib/local/protocol.js +90 -0
  87. package/lib/local/state-file.d.ts +8 -0
  88. package/lib/local/state-file.js +45 -0
  89. package/lib/local.d.ts +10 -0
  90. package/lib/local.js +10 -0
  91. package/lib/onboarding/allowlist.d.ts +54 -0
  92. package/lib/onboarding/allowlist.js +106 -0
  93. package/lib/onboarding/errors.d.ts +7 -0
  94. package/lib/onboarding/errors.js +17 -0
  95. package/lib/onboarding/index.d.ts +6 -0
  96. package/lib/onboarding/index.js +6 -0
  97. package/lib/onboarding/install.d.ts +99 -0
  98. package/lib/onboarding/install.js +132 -0
  99. package/lib/onboarding/package-manager.d.ts +47 -0
  100. package/lib/onboarding/package-manager.js +179 -0
  101. package/lib/onboarding/service.d.ts +53 -0
  102. package/lib/onboarding/service.js +144 -0
  103. package/lib/onboarding/state-store.d.ts +26 -0
  104. package/lib/onboarding/state-store.js +97 -0
  105. package/lib/onboarding.d.ts +2 -0
  106. package/lib/onboarding.js +2 -0
  107. package/lib/packages/authorization.d.ts +23 -0
  108. package/lib/packages/authorization.js +109 -0
  109. package/lib/packages/errors.d.ts +11 -0
  110. package/lib/packages/errors.js +26 -0
  111. package/lib/packages/index.d.ts +5 -0
  112. package/lib/packages/index.js +5 -0
  113. package/lib/packages/rpc.d.ts +30 -0
  114. package/lib/packages/rpc.js +155 -0
  115. package/lib/packages/service.d.ts +121 -0
  116. package/lib/packages/service.js +441 -0
  117. package/lib/packages/snapshot.d.ts +14 -0
  118. package/lib/packages/snapshot.js +73 -0
  119. package/lib/packages.d.ts +2 -0
  120. package/lib/packages.js +2 -0
  121. package/lib/plugin-management/activity.d.ts +6 -0
  122. package/lib/plugin-management/activity.js +14 -0
  123. package/lib/plugin-management/config-explanation.d.ts +6 -0
  124. package/lib/plugin-management/config-explanation.js +113 -0
  125. package/lib/plugin-management/use-cases.d.ts +15 -0
  126. package/lib/plugin-management/use-cases.js +120 -0
  127. package/lib/plugin-management/workflow.d.ts +92 -0
  128. package/lib/plugin-management/workflow.js +772 -0
  129. package/lib/plugin-management.d.ts +5 -0
  130. package/lib/plugin-management.js +5 -0
  131. package/lib/project/config-file.d.ts +6 -0
  132. package/lib/project/config-file.js +58 -0
  133. package/lib/project/environment.d.ts +13 -0
  134. package/lib/project/environment.js +52 -0
  135. package/lib/project/instance-declarations.d.ts +55 -0
  136. package/lib/project/instance-declarations.js +542 -0
  137. package/lib/project/legacy-config.d.ts +25 -0
  138. package/lib/project/legacy-config.js +70 -0
  139. package/lib/project/node-requirements.d.ts +7 -0
  140. package/lib/project/node-requirements.js +20 -0
  141. package/lib/project/tsx-module-loader.d.ts +7 -0
  142. package/lib/project/tsx-module-loader.js +29 -0
  143. package/lib/project.d.ts +7 -0
  144. package/lib/project.js +7 -0
  145. package/lib/server.d.ts +11 -0
  146. package/lib/server.js +11 -0
  147. package/lib/supervisor/instance-logs.d.ts +39 -0
  148. package/lib/supervisor/instance-logs.js +152 -0
  149. package/lib/supervisor/instance-supervisor.d.ts +140 -0
  150. package/lib/supervisor/instance-supervisor.js +408 -0
  151. package/lib/supervisor/run-instance.d.ts +35 -0
  152. package/lib/supervisor/run-instance.js +161 -0
  153. package/lib/supervisor/terminal-state.d.ts +30 -0
  154. package/lib/supervisor/terminal-state.js +57 -0
  155. package/lib/supervisor.d.ts +4 -0
  156. package/lib/supervisor.js +4 -0
  157. package/lib/terminal/backends.d.ts +38 -0
  158. package/lib/terminal/backends.js +193 -0
  159. package/lib/terminal/config.d.ts +63 -0
  160. package/lib/terminal/config.js +237 -0
  161. package/lib/terminal/host.d.ts +26 -0
  162. package/lib/terminal/host.js +76 -0
  163. package/lib/terminal/index.d.ts +60 -0
  164. package/lib/terminal/index.js +135 -0
  165. package/lib/terminal/modules.d.ts +87 -0
  166. package/lib/terminal/modules.js +44 -0
  167. package/lib/terminal/service.d.ts +101 -0
  168. package/lib/terminal/service.js +455 -0
  169. package/lib/terminal/tickets.d.ts +46 -0
  170. package/lib/terminal/tickets.js +76 -0
  171. package/lib/terminal.d.ts +3 -0
  172. package/lib/terminal.js +3 -0
  173. package/lib/usage/aggregate.d.ts +87 -0
  174. package/lib/usage/aggregate.js +212 -0
  175. package/lib/usage.d.ts +2 -0
  176. package/lib/usage.js +2 -0
  177. package/package.json +116 -3
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Shared, read-only reader/aggregator over the Agent turn trace archive
3
+ * (`data/agent-traces/*.jsonl`, ADR 0043 §6). Used by `zhin usage report` and the
4
+ * Console RPC `plugin.root.usage-stats`. Streams files line by line and only
5
+ * looks at token counts, ids, session keys and provider/model names — never
6
+ * message text.
7
+ */
8
+ import { createReadStream } from 'node:fs';
9
+ import { readdir } from 'node:fs/promises';
10
+ import { join } from 'node:path';
11
+ import { createInterface } from 'node:readline';
12
+ export const DAY_MS = 86_400_000;
13
+ export const HOUR_MS = 3_600_000;
14
+ export const FIXED_SEGMENTS = new Set(['system', 'tool_schemas', 'output_schema', 'tool_index', 'skill_catalog', 'agent_catalog', 'memory', 'bootstrap']);
15
+ export function num(value) {
16
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;
17
+ }
18
+ export function sessionMatcher(pattern) {
19
+ if (!pattern)
20
+ return () => true;
21
+ if (!pattern.includes('*'))
22
+ return key => key.includes(pattern);
23
+ const re = new RegExp(`^${pattern.split('*').map(part => part.replace(/[.+?^${}()|[\]\\]/g, '\\$&')).join('.*')}$`);
24
+ return key => re.test(key);
25
+ }
26
+ /**
27
+ * Streams every valid trace record in range to `visit`. A missing dir yields an
28
+ * empty scan. A record is valid with a numeric `started_at` and a string `session_key`.
29
+ */
30
+ export async function scanTraces(dir, options, visit) {
31
+ let names = [];
32
+ try {
33
+ names = (await readdir(dir)).filter(name => name.endsWith('.jsonl')).sort();
34
+ }
35
+ catch {
36
+ names = [];
37
+ }
38
+ const matches = sessionMatcher(options.session);
39
+ let filesRead = 0;
40
+ let lines = 0;
41
+ let malformed = 0;
42
+ for (const name of names) {
43
+ // Files are named for their day; skip those clearly outside the window (slack for time zones).
44
+ const stamp = /^(\d{4}-\d{2}-\d{2})/.exec(name);
45
+ if (stamp) {
46
+ const fileStart = Date.parse(`${stamp[1]}T00:00:00Z`);
47
+ if (options.since !== undefined && fileStart + 2 * DAY_MS <= options.since)
48
+ continue;
49
+ if (options.until !== undefined && fileStart - DAY_MS >= options.until)
50
+ continue;
51
+ }
52
+ filesRead++;
53
+ const reader = createInterface({ input: createReadStream(join(dir, name), { encoding: 'utf8' }), crlfDelay: Infinity });
54
+ for await (const line of reader) {
55
+ if (line.trim() === '')
56
+ continue;
57
+ lines++;
58
+ let trace;
59
+ try {
60
+ trace = JSON.parse(line);
61
+ }
62
+ catch {
63
+ malformed++;
64
+ continue;
65
+ }
66
+ const startedAt = num(trace?.started_at);
67
+ if (!trace || typeof trace !== 'object' || startedAt === undefined || typeof trace.session_key !== 'string') {
68
+ malformed++;
69
+ continue;
70
+ }
71
+ if (options.since !== undefined && startedAt < options.since)
72
+ continue;
73
+ if (options.until !== undefined && startedAt >= options.until)
74
+ continue;
75
+ if (!matches(trace.session_key))
76
+ continue;
77
+ visit(trace, startedAt);
78
+ }
79
+ }
80
+ return { files: names.length, filesRead, lines, malformed };
81
+ }
82
+ export const USAGE_STATS_SESSION_LIMIT = 50;
83
+ /** Start of the local hour/day containing `ms`. */
84
+ export function bucketStartOf(ms, bucket) {
85
+ const d = new Date(ms);
86
+ return bucket === 'day'
87
+ ? new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime()
88
+ : new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours()).getTime();
89
+ }
90
+ function nextBucket(start, bucket) {
91
+ const d = new Date(start);
92
+ return bucket === 'day'
93
+ ? new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1).getTime()
94
+ : start + HOUR_MS;
95
+ }
96
+ /** `platform:endpoint:scope:sceneId`; other shapes keep whatever parts they have. */
97
+ export function parseSessionKey(key) {
98
+ const parts = key.split(':');
99
+ if (parts.length >= 4)
100
+ return { platform: parts[0], scope: parts[2], sceneId: parts.slice(3).join(':') };
101
+ if (parts.length === 3)
102
+ return { platform: parts[0], scope: parts[1], sceneId: parts[2] };
103
+ return parts[0] ? { platform: parts[0] } : {};
104
+ }
105
+ const tally = () => ({ calls: 0, input: 0, output: 0, cache: 0, cacheWrite: 0 });
106
+ function tokens(t) {
107
+ return {
108
+ calls: t.calls,
109
+ inputTokens: t.input,
110
+ outputTokens: t.output,
111
+ cacheReadTokens: t.cache,
112
+ cacheWriteTokens: t.cacheWrite,
113
+ cacheShare: t.input > 0 ? Math.min(1, t.cache / t.input) : 0,
114
+ };
115
+ }
116
+ function nearestRank(sorted, p) {
117
+ if (sorted.length === 0)
118
+ return 0;
119
+ return sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil((p / 100) * sorted.length) - 1))];
120
+ }
121
+ export async function buildUsageStats(dir, query) {
122
+ const { since, until, bucket } = query;
123
+ const total = tally();
124
+ let turns = 0;
125
+ const callShares = [];
126
+ const segments = { history: 0, fixed: 0, user: 0 };
127
+ const models = new Map();
128
+ const sessions = new Map();
129
+ const buckets = new Map();
130
+ for (let t = bucketStartOf(since, bucket); t < until; t = nextBucket(t, bucket)) {
131
+ buckets.set(t, { ...tally(), byModel: {} });
132
+ }
133
+ const scan = await scanTraces(dir, { since, until, session: query.session }, (trace, startedAt) => {
134
+ turns++;
135
+ const session = sessions.get(trace.session_key) ?? { ...tally(), turns: 0 };
136
+ session.turns++;
137
+ sessions.set(trace.session_key, session);
138
+ const calls = Array.isArray(trace.model_calls) ? trace.model_calls : [];
139
+ for (const raw of calls) {
140
+ const call = raw;
141
+ const prompt = num(call?.prompt_tokens);
142
+ if (prompt === undefined)
143
+ continue;
144
+ const output = num(call?.completion_tokens) ?? 0;
145
+ const cache = num(call?.cache_read_tokens) ?? 0;
146
+ const cacheWrite = num(call?.cache_write_tokens) ?? 0;
147
+ if (prompt > 0)
148
+ callShares.push(Math.min(1, cache / prompt));
149
+ const provider = typeof call?.provider === 'string' && call.provider ? call.provider : 'unknown';
150
+ const model = typeof call?.model === 'string' && call.model ? call.model : 'unknown';
151
+ const at = num(call?.started_at) ?? num(call?.at) ?? startedAt;
152
+ for (const t of [total, session]) {
153
+ t.calls++;
154
+ t.input += prompt;
155
+ t.output += output;
156
+ t.cache += cache;
157
+ t.cacheWrite += cacheWrite;
158
+ }
159
+ const modelKey = `${provider}/${model}`;
160
+ const m = models.get(modelKey) ?? { ...tally(), provider, model };
161
+ m.calls++;
162
+ m.input += prompt;
163
+ m.output += output;
164
+ m.cache += cache;
165
+ m.cacheWrite += cacheWrite;
166
+ models.set(modelKey, m);
167
+ const slot = buckets.get(bucketStartOf(at, bucket)) ?? buckets.get(bucketStartOf(startedAt, bucket));
168
+ if (slot) {
169
+ slot.calls++;
170
+ slot.input += prompt;
171
+ slot.output += output;
172
+ slot.cache += cache;
173
+ slot.cacheWrite += cacheWrite;
174
+ slot.byModel[modelKey] = (slot.byModel[modelKey] ?? 0) + prompt;
175
+ }
176
+ }
177
+ const budget = trace.context_budget?.segments;
178
+ if (budget && typeof budget === 'object') {
179
+ for (const [key, value] of Object.entries(budget)) {
180
+ const n = num(value) ?? 0;
181
+ if (key === 'history')
182
+ segments.history += n;
183
+ else if (key === 'user')
184
+ segments.user += n;
185
+ else if (FIXED_SEGMENTS.has(key))
186
+ segments.fixed += n;
187
+ }
188
+ }
189
+ });
190
+ callShares.sort((a, b) => a - b);
191
+ return {
192
+ range: { since, until, bucket, timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone },
193
+ totals: {
194
+ turns,
195
+ ...tokens(total),
196
+ cacheShareByCall: { p50: nearestRank(callShares, 50), p90: nearestRank(callShares, 90) },
197
+ },
198
+ byModel: [...models.values()]
199
+ .map(m => ({ provider: m.provider, model: m.model, ...tokens(m) }))
200
+ .sort((a, b) => b.inputTokens - a.inputTokens),
201
+ bySession: [...sessions.entries()]
202
+ .map(([sessionKey, s]) => ({ sessionKey, ...parseSessionKey(sessionKey), turns: s.turns, ...tokens(s) }))
203
+ .sort((a, b) => b.inputTokens - a.inputTokens)
204
+ .slice(0, USAGE_STATS_SESSION_LIMIT),
205
+ series: [...buckets.entries()]
206
+ .sort(([a], [b]) => a - b)
207
+ .map(([bucketStart, b]) => ({ bucketStart, ...tokens(b), byModel: b.byModel })),
208
+ segments,
209
+ filesRead: scan.filesRead,
210
+ malformedLines: scan.malformed,
211
+ };
212
+ }
package/lib/usage.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ /** `@zhin.js/gateway/usage` — usage statistics aggregation. */
2
+ export * from './usage/aggregate.js';
package/lib/usage.js ADDED
@@ -0,0 +1,2 @@
1
+ /** `@zhin.js/gateway/usage` — usage statistics aggregation. */
2
+ export * from './usage/aggregate.js';
package/package.json CHANGED
@@ -1,6 +1,119 @@
1
1
  {
2
2
  "name": "@zhin.js/gateway",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.1.1",
4
+ "description": "Zhin.js management gateway: Console access control, terminal, project configuration and instance supervision (ADR 0054)",
5
+ "type": "module",
6
+ "main": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "import": "./lib/index.js"
12
+ },
13
+ "./iam": {
14
+ "types": "./lib/iam.d.ts",
15
+ "import": "./lib/iam.js"
16
+ },
17
+ "./terminal": {
18
+ "types": "./lib/terminal.d.ts",
19
+ "import": "./lib/terminal.js"
20
+ },
21
+ "./config": {
22
+ "types": "./lib/config.d.ts",
23
+ "import": "./lib/config.js"
24
+ },
25
+ "./plugin-management": {
26
+ "types": "./lib/plugin-management.d.ts",
27
+ "import": "./lib/plugin-management.js"
28
+ },
29
+ "./project": {
30
+ "types": "./lib/project.d.ts",
31
+ "import": "./lib/project.js"
32
+ },
33
+ "./supervisor": {
34
+ "types": "./lib/supervisor.d.ts",
35
+ "import": "./lib/supervisor.js"
36
+ },
37
+ "./usage": {
38
+ "types": "./lib/usage.d.ts",
39
+ "import": "./lib/usage.js"
40
+ },
41
+ "./onboarding": {
42
+ "types": "./lib/onboarding.d.ts",
43
+ "import": "./lib/onboarding.js"
44
+ },
45
+ "./http": {
46
+ "types": "./lib/http.d.ts",
47
+ "import": "./lib/http.js"
48
+ },
49
+ "./packages": {
50
+ "types": "./lib/packages.d.ts",
51
+ "import": "./lib/packages.js"
52
+ },
53
+ "./server": {
54
+ "types": "./lib/server.d.ts",
55
+ "import": "./lib/server.js"
56
+ },
57
+ "./database": {
58
+ "types": "./lib/database.d.ts",
59
+ "import": "./lib/database.js"
60
+ },
61
+ "./local": {
62
+ "types": "./lib/local.d.ts",
63
+ "import": "./lib/local.js"
64
+ }
65
+ },
66
+ "files": [
67
+ "lib",
68
+ "README.md"
69
+ ],
70
+ "dependencies": {
71
+ "dotenv": "^17.4.2",
72
+ "fs-extra": "^11.4.0",
73
+ "tsx": "^4.23.1",
74
+ "yaml": "^2.9.0",
75
+ "@zhin.js/console-protocol": "1.2.0",
76
+ "@zhin.js/database": "1.1.8",
77
+ "@zhin.js/host-http": "1.2.0",
78
+ "@zhin.js/logger": "1.1.3",
79
+ "@zhin.js/plugin-runtime": "1.2.0",
80
+ "@zhin.js/runtime": "1.2.0",
81
+ "@zhin.js/scaffold-wizard": "1.1.19"
82
+ },
83
+ "optionalDependencies": {
84
+ "node-pty": "^1.0.0",
85
+ "ssh2": "^1.16.0"
86
+ },
87
+ "devDependencies": {
88
+ "@types/fs-extra": "^11.0.4",
89
+ "@types/node": "^26.1.2",
90
+ "@types/ssh2": "^1.15.5",
91
+ "@types/ws": "^8.18.1",
92
+ "typescript": "^6.0.3",
93
+ "ws": "^8.21.1"
94
+ },
95
+ "engines": {
96
+ "node": ">=22.19.0"
97
+ },
98
+ "repository": {
99
+ "type": "git",
100
+ "url": "git+https://github.com/zhinjs/zhin.git",
101
+ "directory": "packages/host/gateway"
102
+ },
103
+ "publishConfig": {
104
+ "access": "public",
105
+ "registry": "https://registry.npmjs.org"
106
+ },
107
+ "keywords": [
108
+ "zhin",
109
+ "gateway",
110
+ "console",
111
+ "rbac"
112
+ ],
113
+ "license": "MIT",
114
+ "scripts": {
115
+ "build": "tsc",
116
+ "clean": "rimraf lib",
117
+ "test": "vitest run --root ../../.. packages/host/gateway/tests"
118
+ }
6
119
  }