@adminforth/agent 2.8.1 → 2.9.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 CHANGED
@@ -115,7 +115,7 @@ sequenceDiagram
115
115
  M-->>LLM: reasoning and text deltas
116
116
  LLM-->>UI: reasoning-delta and text-delta frames
117
117
  M-->>LLM: tool call
118
- alt tool has agent.isDangerous
118
+ alt tool has agent.requiresHumanApproval
119
119
  LLM-->>UI: data-interrupt, generation pauses
120
120
  U->>UI: approve or reject
121
121
  UI->>EP: POST /agent/approval
@@ -152,7 +152,7 @@ flowchart LR
152
152
  C -- yes --> E["fetch_skill returns the SKILL.md<br/>for the matching skill"]
153
153
  E --> F["fetch_tool_schema loads one<br/>API tool schema by name"]
154
154
  F --> G["ApiBasedToolsMiddleware sees the<br/>status 200 tool message and adds that<br/>tool to the next model call"]
155
- G --> H{"agent.isDangerous?"}
155
+ G --> H{"agent.requiresHumanApproval?"}
156
156
  H -- yes --> I["humanInTheLoopMiddleware interrupt,<br/>approve or reject in the UI"]
157
157
  H -- no --> J["Execute through the AdminForth API layer"]
158
158
  I -- approved --> J
@@ -419,7 +419,7 @@ directories are also discovered.
419
419
 
420
420
  ## Human-in-the-loop approvals
421
421
 
422
- Tools whose definition marks them dangerous (`agent.isDangerous === true`) trigger an
422
+ Tools whose endpoint sets `agent.requiresHumanApproval` (or the older `agent.isDangerous`) trigger an
423
423
  approval interrupt: generation pauses and the UI shows an approve/reject prompt. The client
424
424
  resolves it via `POST /agent/approval`, and the run resumes (or, on reject, the model is
425
425
  told the action was declined).
@@ -19,7 +19,7 @@
19
19
  class="flex gap-2"
20
20
  >
21
21
  <span class="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-lightListTableHeadingText dark:bg-darkListTableHeadingText" />
22
- <span class="min-w-0 break-words">{{ message }}</span>
22
+ <span class="min-w-0 whitespace-pre-line break-words">{{ message }}</span>
23
23
  </li>
24
24
  </ul>
25
25
  <div class="mt-4 flex flex-wrap gap-2">
@@ -17,7 +17,7 @@ import { createLegacySystemMessagesMiddleware } from "./middleware/legacySystemM
17
17
  import { buildDynamicSystemPrompt } from "../domain/systemPrompt.js";
18
18
  function createHumanInTheLoopInterrupts(apiBasedTools) {
19
19
  return Object.fromEntries(Object.entries(apiBasedTools)
20
- .filter(([, apiBasedTool]) => { var _a; return ((_a = apiBasedTool.agent) === null || _a === void 0 ? void 0 : _a.isDangerous) === true; })
20
+ .filter(([, { agent }]) => (agent === null || agent === void 0 ? void 0 : agent.requiresHumanApproval) || (agent === null || agent === void 0 ? void 0 : agent.isDangerous))
21
21
  .map(([toolName]) => [
22
22
  toolName,
23
23
  {
@@ -1,6 +1,9 @@
1
1
  import { type AdminUser, type IAdminForth } from 'adminforth';
2
2
  type AgentToolMeta = {
3
+ requiresHumanApproval?: boolean;
4
+ /** @deprecated Older name of `requiresHumanApproval`, still set by endpoints built for earlier AdminForth versions. */
3
5
  isDangerous?: boolean;
6
+ hiddenFromAgents?: boolean;
4
7
  };
5
8
  export type ApiBasedToolCallParams = {
6
9
  adminUser?: AdminUser;
@@ -438,13 +438,14 @@ function attachDurationMs(output, durationMs) {
438
438
  return { result: output, durationMs };
439
439
  }
440
440
  export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
441
+ var _a;
441
442
  const apiBasedTools = {};
442
443
  const openApiSchemas = adminforth.openApi.registeredSchemas;
443
444
  const openApiSchemasByToolName = new Map();
444
445
  const hiddenResourceIdSet = new Set(hiddenResourceIds);
445
446
  for (const schema of openApiSchemas) {
446
447
  const toolName = openApiSchemaPathToToolName(schema.path, adminforth);
447
- if (hasRegisteredApiToolHandler(schema)) {
448
+ if (hasRegisteredApiToolHandler(schema) && !((_a = schema.agent) === null || _a === void 0 ? void 0 : _a.hiddenFromAgents)) {
448
449
  openApiSchemasByToolName.set(toolName, schema);
449
450
  }
450
451
  }
@@ -59,7 +59,9 @@ function formatRecord(record, resource) {
59
59
  return `${(column === null || column === void 0 ? void 0 : column.label) || humanize(name)}: ${formatValue(value, column)}`;
60
60
  });
61
61
  const hidden = entries.length - shown.length;
62
- return hidden > 0 ? `${shown.join(", ")} and ${hidden} more` : shown.join(", ");
62
+ const lines = hidden > 0 ? [...shown, `and ${hidden} more`] : shown;
63
+ // One field per line: a wide record is unreadable as a single run-on sentence.
64
+ return lines.join(",\n");
63
65
  }
64
66
  function actionLabel(resource, actionId) {
65
67
  var _a, _b;
@@ -81,11 +83,11 @@ export function formatApprovalRequest(adminforth, request) {
81
83
  switch (toolName) {
82
84
  case "create_record": {
83
85
  const fields = formatRecord(args.record, resource);
84
- return `Create a new record in ${label}${fields ? ` — ${fields}` : ""}`;
86
+ return `Create a new record in ${label}${fields ? `:\n${fields}` : ""}`;
85
87
  }
86
88
  case "update_record": {
87
89
  const fields = formatRecord(args.record, resource);
88
- return `Update record with id:${formatValue(args.recordId)} in ${label}${fields ? ` — set ${fields}` : ""}`;
90
+ return `Update record with id:${formatValue(args.recordId)} in ${label}${fields ? `, set:\n${fields}` : ""}`;
89
91
  }
90
92
  case "delete_record":
91
93
  return `Delete record with id:${formatValue(args.primaryKey)} from ${label} — this cannot be undone`;
@@ -98,7 +100,7 @@ export function formatApprovalRequest(adminforth, request) {
98
100
  }
99
101
  default: {
100
102
  const fields = formatRecord(args, resource);
101
- return `${humanize(toolName)}${fields ? ` — ${fields}` : ""}`;
103
+ return `${humanize(toolName)}${fields ? `:\n${fields}` : ""}`;
102
104
  }
103
105
  }
104
106
  }
@@ -33,6 +33,9 @@ export function setupChatSurfaceEndpoints(ctx, server) {
33
33
  method: "POST",
34
34
  noAuth: true,
35
35
  path: `/agent/surface/${adapter.name}/webhook`,
36
+ agent: {
37
+ hiddenFromAgents: true,
38
+ },
36
39
  handler: (endpointInput) => __awaiter(this, void 0, void 0, function* () {
37
40
  var _a;
38
41
  const surfaceContext = {
@@ -71,6 +71,9 @@ export function setupCoreEndpoints(ctx, server) {
71
71
  server.endpoint({
72
72
  method: 'POST',
73
73
  path: `/agent/get-placeholder-messages`,
74
+ agent: {
75
+ hiddenFromAgents: true,
76
+ },
74
77
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ headers, adminUser }) {
75
78
  if (!ctx.options.placeholderMessages) {
76
79
  return {
@@ -89,6 +92,9 @@ export function setupCoreEndpoints(ctx, server) {
89
92
  server.endpoint({
90
93
  method: 'POST',
91
94
  path: `/agent/response`,
95
+ agent: {
96
+ hiddenFromAgents: true,
97
+ },
92
98
  request_schema: agentResponseBodySchema,
93
99
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, _raw_express_res, abortSignal }) {
94
100
  var _b;
@@ -115,6 +121,9 @@ export function setupCoreEndpoints(ctx, server) {
115
121
  server.endpoint({
116
122
  method: 'POST',
117
123
  path: `/agent/edit`,
124
+ agent: {
125
+ hiddenFromAgents: true,
126
+ },
118
127
  request_schema: agentEditBodySchema,
119
128
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, _raw_express_res, abortSignal }) {
120
129
  var _b;
@@ -142,6 +151,9 @@ export function setupCoreEndpoints(ctx, server) {
142
151
  server.endpoint({
143
152
  method: 'POST',
144
153
  path: `/agent/approval`,
154
+ agent: {
155
+ hiddenFromAgents: true,
156
+ },
145
157
  request_schema: agentApprovalBodySchema,
146
158
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, _raw_express_res, abortSignal }) {
147
159
  const data = body;
@@ -166,6 +178,9 @@ export function setupCoreEndpoints(ctx, server) {
166
178
  server.endpoint({
167
179
  method: 'POST',
168
180
  path: `/agent/steer`,
181
+ agent: {
182
+ hiddenFromAgents: true,
183
+ },
169
184
  request_schema: agentSteerBodySchema,
170
185
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser }) {
171
186
  const data = body;
@@ -183,6 +198,9 @@ export function setupCoreEndpoints(ctx, server) {
183
198
  server.endpoint({
184
199
  method: 'POST',
185
200
  path: `/agent/speech-response`,
201
+ agent: {
202
+ hiddenFromAgents: true,
203
+ },
186
204
  target: 'upload',
187
205
  request_schema: agentSpeechResponseShapeSchema,
188
206
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_req, _raw_express_res, abortSignal }) {
@@ -32,6 +32,9 @@ export function setupSessionEndpoints(ctx, server) {
32
32
  server.endpoint({
33
33
  method: 'POST',
34
34
  path: `/agent/get-sessions`,
35
+ agent: {
36
+ hiddenFromAgents: true,
37
+ },
35
38
  request_schema: getSessionsBodySchema,
36
39
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
37
40
  var _b;
@@ -51,6 +54,9 @@ export function setupSessionEndpoints(ctx, server) {
51
54
  server.endpoint({
52
55
  method: 'POST',
53
56
  path: `/agent/get-session-info`,
57
+ agent: {
58
+ hiddenFromAgents: true,
59
+ },
54
60
  request_schema: sessionIdBodySchema,
55
61
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
56
62
  const data = body;
@@ -114,6 +120,9 @@ export function setupSessionEndpoints(ctx, server) {
114
120
  server.endpoint({
115
121
  method: 'POST',
116
122
  path: `/agent/create-session`,
123
+ agent: {
124
+ hiddenFromAgents: true,
125
+ },
117
126
  request_schema: createSessionBodySchema,
118
127
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
119
128
  const data = body;
@@ -137,6 +146,9 @@ export function setupSessionEndpoints(ctx, server) {
137
146
  server.endpoint({
138
147
  method: 'POST',
139
148
  path: `/agent/delete-session`,
149
+ agent: {
150
+ hiddenFromAgents: true,
151
+ },
140
152
  request_schema: sessionIdBodySchema,
141
153
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
142
154
  const data = body;
@@ -166,6 +178,9 @@ export function setupSessionEndpoints(ctx, server) {
166
178
  server.endpoint({
167
179
  method: 'POST',
168
180
  path: `/agent/add-system-message-to-turns`,
181
+ agent: {
182
+ hiddenFromAgents: true,
183
+ },
169
184
  request_schema: addSystemMessageBodySchema,
170
185
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
171
186
  const data = body;
@@ -191,6 +206,9 @@ export function setupSessionEndpoints(ctx, server) {
191
206
  server.endpoint({
192
207
  method: 'POST',
193
208
  path: `/agent/append-steer-to-turn`,
209
+ agent: {
210
+ hiddenFromAgents: true,
211
+ },
194
212
  request_schema: appendSteerBodySchema,
195
213
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
196
214
  const data = body;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/agent",
3
- "version": "2.8.1",
3
+ "version": "2.9.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -36,7 +36,7 @@
36
36
  "devDependencies": {
37
37
  "@types/jest": "^30.0.0",
38
38
  "@types/node": "latest",
39
- "adminforth": "^3.8.2",
39
+ "adminforth": "^3.32.0",
40
40
  "jest": "^30.3.0",
41
41
  "semantic-release": "^24.2.1",
42
42
  "semantic-release-slack-bot": "^4.0.2",
@@ -80,6 +80,6 @@
80
80
  }
81
81
  ],
82
82
  "peerDependencies": {
83
- "adminforth": "^3.8.2"
83
+ "adminforth": "^3.32.0"
84
84
  }
85
85
  }