@newheap/platform-ai-chat 0.11.0 → 0.13.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.
- package/README.md +3 -1
- package/admin/index.d.ts +31 -2
- package/fesm2022/newheap-platform-ai-chat-admin.mjs +85 -7
- package/fesm2022/newheap-platform-ai-chat-admin.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat-agent-runs.mjs +2 -2
- package/fesm2022/newheap-platform-ai-chat-agent-runs.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat-testing.mjs +139 -4
- package/fesm2022/newheap-platform-ai-chat-testing.mjs.map +1 -1
- package/fesm2022/newheap-platform-ai-chat.mjs +138 -9
- package/fesm2022/newheap-platform-ai-chat.mjs.map +1 -1
- package/i18n/en.json +52 -3
- package/i18n/nl.json +52 -3
- package/index.d.ts +83 -4
- package/package.json +1 -1
- package/testing/index.d.ts +6 -1
|
@@ -37,11 +37,16 @@ class NhAssistantMockAdmin {
|
|
|
37
37
|
this.contextVersions.push({ version: 1, hash: hashText(admin.context ?? ''), updatedAt: now(), updatedBy: null, text: admin.context ?? '' });
|
|
38
38
|
const agents = admin.agents
|
|
39
39
|
?? scenario.agents.map(agent => ({ ...codeAgentFromSummary(agent), source: 'code' }));
|
|
40
|
-
for (const { source, skills, shadowOf, ...input } of agents) {
|
|
40
|
+
for (const { source, skills, shadowOf, shadow, serviceAccount, ...input } of agents) {
|
|
41
|
+
const agentShadow = shadowOf !== undefined || shadow === true;
|
|
41
42
|
this.agents.set(input.id, {
|
|
42
43
|
agent: {
|
|
43
44
|
...this.toAgent(input, source, 1, false),
|
|
44
45
|
shadowOf: shadowOf ?? null,
|
|
46
|
+
shadow: shadowState(agentShadow, shadowOf !== undefined || shadow === true, null, shadowOf !== undefined),
|
|
47
|
+
serviceAccount: serviceAccount === undefined
|
|
48
|
+
? null
|
|
49
|
+
: { actorId: serviceAccount, configuredActorId: serviceAccount, overridden: false, changedAt: null, changedBy: null, reason: null },
|
|
45
50
|
skills: (skills ?? []).map((skill) => ({
|
|
46
51
|
skillId: skill.skillId,
|
|
47
52
|
description: skill.description,
|
|
@@ -55,7 +60,8 @@ class NhAssistantMockAdmin {
|
|
|
55
60
|
dailyToolCalls: null,
|
|
56
61
|
dailyTokens: null,
|
|
57
62
|
cancelledRuns: 0,
|
|
58
|
-
startedRuns: 0
|
|
63
|
+
startedRuns: 0,
|
|
64
|
+
shadow: shadowState(agentShadow || skill.shadow === true, skill.shadow === true, null, shadowOf !== undefined)
|
|
59
65
|
}))
|
|
60
66
|
},
|
|
61
67
|
codeDefinition: source === 'code' ? structuredClone(input) : null
|
|
@@ -148,6 +154,9 @@ class NhAssistantMockAdmin {
|
|
|
148
154
|
if (id !== undefined && action === 'skills' && child !== undefined && segments[5] === 'state' && segments.length === 6) {
|
|
149
155
|
return this.skillStateEndpoint(method, id, child, body);
|
|
150
156
|
}
|
|
157
|
+
if (id !== undefined && action === 'skills' && child !== undefined && segments[5] === 'shadow' && segments.length === 6) {
|
|
158
|
+
return this.skillShadowEndpoint(method, id, child, body);
|
|
159
|
+
}
|
|
151
160
|
return this.agentsEndpoint(method, id, action, body, segments.length);
|
|
152
161
|
case 'mcp-servers':
|
|
153
162
|
return this.serversEndpoint(method, id, action, child, body, segments.length);
|
|
@@ -228,6 +237,12 @@ class NhAssistantMockAdmin {
|
|
|
228
237
|
if (length === 4 && action === 'state') {
|
|
229
238
|
return this.agentStateEndpoint(stored, method, body);
|
|
230
239
|
}
|
|
240
|
+
if (length === 4 && action === 'shadow' && method === 'POST') {
|
|
241
|
+
return this.agentShadowEndpoint(stored, body);
|
|
242
|
+
}
|
|
243
|
+
if (length === 4 && action === 'service-account' && method === 'POST') {
|
|
244
|
+
return this.serviceAccountEndpoint(stored, body);
|
|
245
|
+
}
|
|
231
246
|
if (length === 4 && action === 'kill-switch' && method === 'POST') {
|
|
232
247
|
const engaged = body?.engaged;
|
|
233
248
|
if (typeof engaged !== 'boolean') {
|
|
@@ -286,6 +301,106 @@ class NhAssistantMockAdmin {
|
|
|
286
301
|
stored.agent = { ...stored.agent, skills: stored.agent.skills.map(item => item.skillId === skillId ? changed : item) };
|
|
287
302
|
return { status: 200, body: changed };
|
|
288
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* `POST admin/agents/{id}/shadow`: the agent's shadow mode as an override of the code. A
|
|
306
|
+
* variant always works in shadow; the skills' effective modes follow the agent's.
|
|
307
|
+
*/
|
|
308
|
+
agentShadowEndpoint(stored, body) {
|
|
309
|
+
const request = shadowRequest(body);
|
|
310
|
+
if (request === null) {
|
|
311
|
+
return validationFailure();
|
|
312
|
+
}
|
|
313
|
+
const current = stored.agent.shadow ?? shadowState(false, false, null, false);
|
|
314
|
+
if (current.locked) {
|
|
315
|
+
return failure(409, 'assistant-shadow-variant');
|
|
316
|
+
}
|
|
317
|
+
const override = request.mode === 'code' ? null : request.mode === 'shadow';
|
|
318
|
+
if (current.override !== override) {
|
|
319
|
+
const shadow = override ?? current.configured;
|
|
320
|
+
stored.agent = {
|
|
321
|
+
...stored.agent,
|
|
322
|
+
shadow: { ...current, shadow, override, changedAt: this.now(), changedBy: 'current-user', reason: request.reason },
|
|
323
|
+
skills: (stored.agent.skills ?? []).map(skill => ({ ...skill, shadow: withAgentShadow(skill.shadow, shadow) }))
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
return { status: 200, body: toAgentState(stored.agent) };
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* `POST admin/agents/{id}/skills/{skillId}/shadow`: one skill's shadow mode; a skill of an agent
|
|
330
|
+
* in shadow works in shadow whatever its own mode.
|
|
331
|
+
*/
|
|
332
|
+
skillShadowEndpoint(method, agentId, skillId, body) {
|
|
333
|
+
const stored = this.agents.get(agentId);
|
|
334
|
+
const skill = stored?.agent.skills?.find(item => item.skillId === skillId);
|
|
335
|
+
if (!stored || !skill) {
|
|
336
|
+
return failure(404, 'assistant-skill-not-found');
|
|
337
|
+
}
|
|
338
|
+
if (method !== 'POST') {
|
|
339
|
+
return { status: 405 };
|
|
340
|
+
}
|
|
341
|
+
const request = shadowRequest(body);
|
|
342
|
+
if (request === null) {
|
|
343
|
+
return validationFailure();
|
|
344
|
+
}
|
|
345
|
+
const agentShadow = stored.agent.shadow ?? shadowState(false, false, null, false);
|
|
346
|
+
if (agentShadow.locked) {
|
|
347
|
+
return failure(409, 'assistant-shadow-variant');
|
|
348
|
+
}
|
|
349
|
+
const current = skill.shadow ?? shadowState(agentShadow.shadow, false, null, false);
|
|
350
|
+
const override = request.mode === 'code' ? null : request.mode === 'shadow';
|
|
351
|
+
const changed = current.override === override
|
|
352
|
+
? skill
|
|
353
|
+
: {
|
|
354
|
+
...skill,
|
|
355
|
+
shadow: {
|
|
356
|
+
...current,
|
|
357
|
+
shadow: agentShadow.shadow || (override ?? current.configured),
|
|
358
|
+
override,
|
|
359
|
+
changedAt: this.now(),
|
|
360
|
+
changedBy: 'current-user',
|
|
361
|
+
reason: request.reason
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
stored.agent = { ...stored.agent, skills: stored.agent.skills.map(item => item.skillId === skillId ? changed : item) };
|
|
365
|
+
return { status: 200, body: changed };
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* `POST admin/agents/{id}/service-account`: the technical account of an agent that answers to
|
|
369
|
+
* one in code. The mock accepts every account id except those starting with `unknown`.
|
|
370
|
+
*/
|
|
371
|
+
serviceAccountEndpoint(stored, body) {
|
|
372
|
+
const current = stored.agent.serviceAccount;
|
|
373
|
+
if (!current) {
|
|
374
|
+
return failure(409, 'assistant-service-account-not-used');
|
|
375
|
+
}
|
|
376
|
+
const request = body;
|
|
377
|
+
if (request === undefined || (request.actorId !== null && request.actorId !== undefined && typeof request.actorId !== 'string')) {
|
|
378
|
+
return validationFailure();
|
|
379
|
+
}
|
|
380
|
+
const actorId = typeof request.actorId === 'string' && request.actorId.trim().length > 0 ? request.actorId.trim() : null;
|
|
381
|
+
if (actorId !== null && (actorId.length > 256 || actorId.startsWith('unknown'))) {
|
|
382
|
+
return actorId.length > 256 ? validationFailure() : failure(400, 'assistant-service-account-not-found');
|
|
383
|
+
}
|
|
384
|
+
const reason = typeof request.reason === 'string' && request.reason.trim().length > 0 ? request.reason.trim() : null;
|
|
385
|
+
if (reason !== null && reason.length > maxStateReason) {
|
|
386
|
+
return validationFailure();
|
|
387
|
+
}
|
|
388
|
+
const overridden = actorId !== null;
|
|
389
|
+
if ((current.overridden ? current.actorId : null) !== actorId) {
|
|
390
|
+
stored.agent = {
|
|
391
|
+
...stored.agent,
|
|
392
|
+
serviceAccount: {
|
|
393
|
+
...current,
|
|
394
|
+
actorId: actorId ?? current.configuredActorId,
|
|
395
|
+
overridden,
|
|
396
|
+
changedAt: this.now(),
|
|
397
|
+
changedBy: 'current-user',
|
|
398
|
+
reason
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
return { status: 200, body: toAgentState(stored.agent) };
|
|
403
|
+
}
|
|
289
404
|
/**
|
|
290
405
|
* `GET` and `POST admin/agents/{id}/state`. The mock runs no agents on their own, so a pause
|
|
291
406
|
* collects no waiting events and a stop cancels no runs; the version never changes.
|
|
@@ -631,7 +746,9 @@ class NhAssistantMockAdmin {
|
|
|
631
746
|
stateReason: previous?.stateReason ?? null,
|
|
632
747
|
waitingInputs: previous?.waitingInputs ?? 0,
|
|
633
748
|
skills: previous?.skills ?? [],
|
|
634
|
-
shadowOf: previous?.shadowOf ?? null
|
|
749
|
+
shadowOf: previous?.shadowOf ?? null,
|
|
750
|
+
shadow: previous?.shadow ?? shadowState(false, false, null, false),
|
|
751
|
+
serviceAccount: previous?.serviceAccount ?? null
|
|
635
752
|
};
|
|
636
753
|
}
|
|
637
754
|
toServer(stored) {
|
|
@@ -668,9 +785,27 @@ function toAgentState(agent) {
|
|
|
668
785
|
cancelledRuns: 0,
|
|
669
786
|
startedRuns: 0,
|
|
670
787
|
skills: agent.skills ?? [],
|
|
671
|
-
shadowOf: agent.shadowOf ?? null
|
|
788
|
+
shadowOf: agent.shadowOf ?? null,
|
|
789
|
+
shadow: agent.shadow ?? shadowState(false, false, null, false),
|
|
790
|
+
serviceAccount: agent.serviceAccount ?? null
|
|
672
791
|
};
|
|
673
792
|
}
|
|
793
|
+
function shadowState(shadow, configured, override, locked) {
|
|
794
|
+
return { shadow, configured, override, locked, changedAt: null, changedBy: null, reason: null };
|
|
795
|
+
}
|
|
796
|
+
/** A skill's mode after its agent's mode changed: the agent's shadow comes on top of its own. */
|
|
797
|
+
function withAgentShadow(skill, agentShadow) {
|
|
798
|
+
const own = skill?.override ?? skill?.configured ?? false;
|
|
799
|
+
return { ...(skill ?? shadowState(false, false, null, false)), shadow: agentShadow || own };
|
|
800
|
+
}
|
|
801
|
+
function shadowRequest(body) {
|
|
802
|
+
const request = body;
|
|
803
|
+
if (request?.mode !== 'shadow' && request?.mode !== 'live' && request?.mode !== 'code') {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
const reason = typeof request.reason === 'string' && request.reason.trim().length > 0 ? request.reason.trim() : null;
|
|
807
|
+
return reason !== null && reason.length > maxStateReason ? null : { mode: request.mode, reason };
|
|
808
|
+
}
|
|
674
809
|
function toServerFields(input) {
|
|
675
810
|
return {
|
|
676
811
|
id: input.id,
|