@newheap/platform-ai-chat 0.21.0 → 0.23.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.
@@ -65,7 +65,8 @@ const statusTable = {
65
65
  'assistant-forbidden',
66
66
  'assistant-mcp-credential-mismatch',
67
67
  'assistant-mcp-initiator-only',
68
- 'assistant-file-forbidden'
68
+ 'assistant-file-forbidden',
69
+ 'assistant-not-allowed-while-impersonating'
69
70
  ],
70
71
  404: [
71
72
  'assistant-disabled',
@@ -1687,6 +1688,10 @@ class NhAssistantMockAdminMcp {
1687
1688
  stored.organization?.status === 'issuer-changed') {
1688
1689
  stored.organization = { ...stored.organization, status: 'active' };
1689
1690
  }
1691
+ if (!keepsSecret(before, input)) {
1692
+ // As on the server: a stored secret never follows the server to another destination.
1693
+ stored.secret = null;
1694
+ }
1690
1695
  if (!secretModes.includes(input.authMode)) {
1691
1696
  stored.secret = null;
1692
1697
  stored.server.secretReference = null;
@@ -2247,17 +2252,20 @@ class NhAssistantMockAdminMcp {
2247
2252
  if (input.secret && input.secretReference) {
2248
2253
  add('secretReference', 'invalid');
2249
2254
  }
2255
+ // As on the server: a stored secret and reference serve only the destination they were given for.
2256
+ const keeps = keepsSecret(stored?.server, input);
2250
2257
  const reference = input.secretReference === undefined || input.secretReference === null
2251
- ? (input.secret ? null : stored?.server.secretReference ?? null)
2258
+ ? (input.secret || !keeps ? null : stored?.server.secretReference ?? null)
2252
2259
  : input.secretReference || null;
2253
2260
  if (reference !== null && (!secretReference.test(reference) || reference.includes('..'))) {
2254
2261
  add('secretReference', 'invalid');
2255
2262
  }
2256
2263
  if (secretModes.includes(input.authMode)) {
2257
2264
  // As on the server: bearer, api-key and basic need a stored secret or a reference. A new stored
2258
- // secret replaces a reference, a new reference a stored secret.
2265
+ // secret replaces a reference, a new reference a stored secret, and another destination needs
2266
+ // either again.
2259
2267
  const storedSecret = input.secret === undefined || input.secret === null
2260
- ? !!stored?.secret && !input.secretReference
2268
+ ? keeps && !!stored?.secret && !input.secretReference
2261
2269
  : input.secret.length > 0;
2262
2270
  if (!storedSecret && (reference === null || !!input.secret)) {
2263
2271
  add('secret', 'required');
@@ -2331,10 +2339,32 @@ class NhAssistantMockAdminMcp {
2331
2339
  };
2332
2340
  }
2333
2341
  }
2342
+ /**
2343
+ * Whether a stored secret and reference stay with the server after the input, as on the server: the
2344
+ * URL keeps its origin (scheme, host and port), and the authentication mode and the `api-key` header,
2345
+ * in any letter case, stay the same.
2346
+ */
2347
+ function keepsSecret(stored, input) {
2348
+ const before = stored ? originOf(stored.url) : null;
2349
+ if (!stored || before === null || stored.authMode !== input.authMode || before !== originOf(input.url)) {
2350
+ return false;
2351
+ }
2352
+ return input.authMode !== 'api-key'
2353
+ || (stored.headerName || 'X-Api-Key').toLowerCase() === (input.headerName || 'X-Api-Key').toLowerCase();
2354
+ }
2355
+ /** The origin of an absolute URL in lowercase, or `null` for an invalid one. */
2356
+ function originOf(url) {
2357
+ try {
2358
+ return new URL(url.trim()).origin.toLowerCase();
2359
+ }
2360
+ catch {
2361
+ return null;
2362
+ }
2363
+ }
2334
2364
  function toServerFields(input, stored) {
2335
2365
  const usesSecret = secretModes.includes(input.authMode);
2336
2366
  const reference = input.secretReference === undefined || input.secretReference === null
2337
- ? (input.secret ? null : stored?.secretReference ?? null)
2367
+ ? (input.secret || !keepsSecret(stored, input) ? null : stored?.secretReference ?? null)
2338
2368
  : input.secretReference || null;
2339
2369
  const certificate = input.clientCertificateReference === undefined || input.clientCertificateReference === null
2340
2370
  ? stored?.clientCertificateReference ?? null
@@ -3802,7 +3832,22 @@ class NhAssistantMockRunConfiguration {
3802
3832
  approvalPolicy: given.approvalPolicy ?? null,
3803
3833
  usesRules: given.usesRules ?? false,
3804
3834
  startsOff: given.startsOff ?? false,
3805
- acceptsFiles: given.acceptsFiles ?? false
3835
+ acceptsFiles: given.acceptsFiles ?? false,
3836
+ chatOnly: given.chatOnly ?? agent.chatOnly === true,
3837
+ skillsInChat: given.skillsInChat ?? false,
3838
+ allowQuestions: given.allowQuestions ?? false,
3839
+ usesMemory: given.usesMemory ?? false,
3840
+ triageProfile: given.triageProfile ?? null,
3841
+ // The platform's defaults, as an agent in code that sets none has them.
3842
+ retryCount: given.retryCount ?? 3,
3843
+ maxConcurrentRuns: given.maxConcurrentRuns ?? 4,
3844
+ maxRunsPerSubjectPerDay: given.maxRunsPerSubjectPerDay ?? 10,
3845
+ dailyToolCalls: given.dailyToolCalls ?? null,
3846
+ dailyTokens: given.dailyTokens ?? null,
3847
+ maxTokensPerRun: given.maxTokensPerRun ?? null,
3848
+ maxConsultationsPerTurn: given.maxConsultationsPerTurn ?? null,
3849
+ elevatedReads: given.elevatedReads ?? 'restricted',
3850
+ allowGatewayReads: given.allowGatewayReads ?? false
3806
3851
  };
3807
3852
  }
3808
3853
  /**
@@ -7224,8 +7269,9 @@ class NhAssistantMockAgentRuns {
7224
7269
  }
7225
7270
  /**
7226
7271
  * `POST runs/{id}/retry`: resumes a failed or cancelled run (`queued`), or restarts the agent in the
7227
- * same thread like a start by hand; needs the approver role on the thread. The mock's resumed
7228
- * attempt ends at once as the scenario's `runNow` says.
7272
+ * same thread like a start by hand; needs the approver role on the thread, and a restart also passes
7273
+ * the start checks of `POST threads/start`. The mock's resumed attempt ends at once as the
7274
+ * scenario's `runNow` says.
7229
7275
  */
7230
7276
  retry(runId, body, language) {
7231
7277
  const mode = body?.mode ?? 'resume';
@@ -7251,7 +7297,17 @@ class NhAssistantMockAgentRuns {
7251
7297
  return mockFailure('assistant-agent-not-found');
7252
7298
  }
7253
7299
  if (mode === 'restart') {
7254
- return this.startNow(agent, found.thread.subject);
7300
+ // A restart starts the agent again for the caller: the rule of a start by hand decides, with the
7301
+ // caller's live role.
7302
+ const subject = this.subjects.describe(found.thread.subject.subjectType, found.thread.subject.subjectId, language, this.context.administers());
7303
+ if (!subject) {
7304
+ return mockFailure('assistant-subject-access-denied');
7305
+ }
7306
+ const refusal = this.refusal(agent, subject);
7307
+ if (refusal) {
7308
+ return mockFailure(refusal);
7309
+ }
7310
+ return this.startNow(agent, subject);
7255
7311
  }
7256
7312
  const runNow = this.scenario.runNow?.[agent.id] ?? {};
7257
7313
  const status = runNow.status ?? 'completed';