@zhin.js/host-http 1.0.14 → 1.0.15

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.
@@ -55,6 +55,18 @@ export interface ConsoleRpcExtendedCtx {
55
55
  workroomKnowledgeControl?: ConsoleWorkroomKnowledgeControlPort;
56
56
  }
57
57
  export interface ConsoleWorkroomProfileControlPort {
58
+ getPlanningStatus(projectId: string, authenticatedPrincipal?: Readonly<{
59
+ principalId: string;
60
+ }>): Promise<unknown>;
61
+ bootstrapPlanning(command: Readonly<{
62
+ operationId: string;
63
+ projectId: string;
64
+ expectedRegistryRevision: number;
65
+ includeTools?: readonly string[];
66
+ includeSkills?: readonly string[];
67
+ }>, authenticatedPrincipal: Readonly<{
68
+ principalId: string;
69
+ }>): Promise<unknown>;
58
70
  publishPack(command: Readonly<{
59
71
  operationId: string;
60
72
  pack: unknown;
@@ -95,6 +95,8 @@ export async function dispatchExtendedConsoleRpc(type, data, ctx) {
95
95
  });
96
96
  case 'endpoint.delete_friend':
97
97
  return deleteFriend(d, ctx);
98
+ case 'workroom.profile.status':
99
+ case 'workroom.profile.bootstrap':
98
100
  case 'workroom.profile.pack.publish':
99
101
  case 'workroom.profile.publish':
100
102
  case 'workroom.profile.rollback':
@@ -118,11 +120,31 @@ async function mutateWorkroomProfile(type, data, ctx) {
118
120
  if (forbidden in data)
119
121
  return { error: `Console Workroom Profile request cannot carry ${forbidden}` };
120
122
  }
123
+ if (type === 'workroom.profile.status') {
124
+ try {
125
+ return { data: await control.getPlanningStatus(requiredRpcText(data.projectId, 'projectId'), ctx.authenticatedPrincipal) };
126
+ }
127
+ catch (error) {
128
+ return { error: errorMessage(error) };
129
+ }
130
+ }
121
131
  const principal = ctx.authenticatedPrincipal;
122
132
  if (!principal)
123
133
  return { error: 'Workroom Profile control requires an authenticated principal' };
124
134
  try {
125
135
  const operationId = requiredRpcText(data.operationId, 'operationId');
136
+ if (type === 'workroom.profile.bootstrap') {
137
+ const projectId = requiredRpcText(data.projectId, 'projectId');
138
+ const includeTools = optionalRpcTextArray(data.includeTools, 'includeTools');
139
+ const includeSkills = optionalRpcTextArray(data.includeSkills, 'includeSkills');
140
+ return { data: await control.bootstrapPlanning(Object.freeze({
141
+ operationId,
142
+ projectId,
143
+ expectedRegistryRevision: requiredRpcInteger(data.expectedRegistryRevision, 'expectedRegistryRevision', -1),
144
+ ...(includeTools ? { includeTools } : {}),
145
+ ...(includeSkills ? { includeSkills } : {}),
146
+ }), principal) };
147
+ }
126
148
  if (type === 'workroom.profile.pack.publish') {
127
149
  return { data: await control.publishPack(Object.freeze({ operationId, pack: requiredRpcValue(data.pack, 'pack') }), principal) };
128
150
  }
@@ -205,6 +227,16 @@ function requiredRpcText(value, name) {
205
227
  function optionalRpcText(value, name) {
206
228
  return value === undefined ? undefined : requiredRpcText(value, name);
207
229
  }
230
+ function optionalRpcTextArray(value, name) {
231
+ if (value === undefined)
232
+ return undefined;
233
+ if (!Array.isArray(value))
234
+ throw new Error(`${name} is invalid`);
235
+ const result = value.map((item, index) => requiredRpcText(item, `${name}.${index}`));
236
+ if (new Set(result).size !== result.length)
237
+ throw new Error(`${name} contains duplicates`);
238
+ return Object.freeze(result);
239
+ }
208
240
  function requiredRpcInteger(value, name, minimum = 1) {
209
241
  if (!Number.isSafeInteger(value) || Number(value) < minimum)
210
242
  throw new Error(`${name} is invalid`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/host-http",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "Minimal HTTP and WebSocket host for Plugin Runtime (no Koa)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -66,6 +66,15 @@ export interface ConsoleRpcExtendedCtx {
66
66
  }
67
67
 
68
68
  export interface ConsoleWorkroomProfileControlPort {
69
+ getPlanningStatus(projectId: string,
70
+ authenticatedPrincipal?: Readonly<{ principalId: string }>): Promise<unknown>;
71
+ bootstrapPlanning(command: Readonly<{
72
+ operationId: string;
73
+ projectId: string;
74
+ expectedRegistryRevision: number;
75
+ includeTools?: readonly string[];
76
+ includeSkills?: readonly string[];
77
+ }>, authenticatedPrincipal: Readonly<{ principalId: string }>): Promise<unknown>;
69
78
  publishPack(command: Readonly<{ operationId: string; pack: unknown }>,
70
79
  authenticatedPrincipal: Readonly<{ principalId: string }>): Promise<unknown>;
71
80
  publishProfile(command: Readonly<{
@@ -258,6 +267,8 @@ export async function dispatchExtendedConsoleRpc(
258
267
  case 'endpoint.delete_friend':
259
268
  return deleteFriend(d, ctx);
260
269
 
270
+ case 'workroom.profile.status':
271
+ case 'workroom.profile.bootstrap':
261
272
  case 'workroom.profile.pack.publish':
262
273
  case 'workroom.profile.publish':
263
274
  case 'workroom.profile.rollback':
@@ -275,7 +286,8 @@ export async function dispatchExtendedConsoleRpc(
275
286
  }
276
287
 
277
288
  async function mutateWorkroomProfile(
278
- type: 'workroom.profile.pack.publish' | 'workroom.profile.publish'
289
+ type: 'workroom.profile.status' | 'workroom.profile.bootstrap'
290
+ | 'workroom.profile.pack.publish' | 'workroom.profile.publish'
279
291
  | 'workroom.profile.rollback' | 'workroom.profile.policy.publish',
280
292
  data: Record<string, unknown>,
281
293
  ctx: ConsoleRpcExtendedCtx,
@@ -287,10 +299,36 @@ async function mutateWorkroomProfile(
287
299
  ]) {
288
300
  if (forbidden in data) return { error: `Console Workroom Profile request cannot carry ${forbidden}` };
289
301
  }
302
+ if (type === 'workroom.profile.status') {
303
+ try {
304
+ return { data: await control.getPlanningStatus(
305
+ requiredRpcText(data.projectId, 'projectId'),
306
+ ctx.authenticatedPrincipal,
307
+ ) };
308
+ } catch (error) {
309
+ return { error: errorMessage(error) };
310
+ }
311
+ }
290
312
  const principal = ctx.authenticatedPrincipal;
291
313
  if (!principal) return { error: 'Workroom Profile control requires an authenticated principal' };
292
314
  try {
293
315
  const operationId = requiredRpcText(data.operationId, 'operationId');
316
+ if (type === 'workroom.profile.bootstrap') {
317
+ const projectId = requiredRpcText(data.projectId, 'projectId');
318
+ const includeTools = optionalRpcTextArray(data.includeTools, 'includeTools');
319
+ const includeSkills = optionalRpcTextArray(data.includeSkills, 'includeSkills');
320
+ return { data: await control.bootstrapPlanning(Object.freeze({
321
+ operationId,
322
+ projectId,
323
+ expectedRegistryRevision: requiredRpcInteger(
324
+ data.expectedRegistryRevision,
325
+ 'expectedRegistryRevision',
326
+ -1,
327
+ ),
328
+ ...(includeTools ? { includeTools } : {}),
329
+ ...(includeSkills ? { includeSkills } : {}),
330
+ }), principal) };
331
+ }
294
332
  if (type === 'workroom.profile.pack.publish') {
295
333
  return { data: await control.publishPack(Object.freeze({ operationId, pack: requiredRpcValue(data.pack, 'pack') }), principal) };
296
334
  }
@@ -374,6 +412,14 @@ function optionalRpcText(value: unknown, name: string): string | undefined {
374
412
  return value === undefined ? undefined : requiredRpcText(value, name);
375
413
  }
376
414
 
415
+ function optionalRpcTextArray(value: unknown, name: string): readonly string[] | undefined {
416
+ if (value === undefined) return undefined;
417
+ if (!Array.isArray(value)) throw new Error(`${name} is invalid`);
418
+ const result = value.map((item, index) => requiredRpcText(item, `${name}.${index}`));
419
+ if (new Set(result).size !== result.length) throw new Error(`${name} contains duplicates`);
420
+ return Object.freeze(result);
421
+ }
422
+
377
423
  function requiredRpcInteger(value: unknown, name: string, minimum = 1): number {
378
424
  if (!Number.isSafeInteger(value) || Number(value) < minimum) throw new Error(`${name} is invalid`);
379
425
  return Number(value);