@tai42/api-client 25.0.1 → 26.0.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/dist/agents.d.ts +1 -0
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js.map +1 -1
- package/dist/client/auth-client.d.ts +1 -0
- package/dist/client/auth-client.d.ts.map +1 -1
- package/dist/client/backup-client.d.ts +1 -0
- package/dist/client/backup-client.d.ts.map +1 -1
- package/dist/client/capabilities-client.d.ts +1 -0
- package/dist/client/capabilities-client.d.ts.map +1 -1
- package/dist/client/channels-client.d.ts +4 -1
- package/dist/client/channels-client.d.ts.map +1 -1
- package/dist/client/config-client.d.ts +1 -0
- package/dist/client/config-client.d.ts.map +1 -1
- package/dist/client/connectors-client.d.ts +7 -0
- package/dist/client/connectors-client.d.ts.map +1 -1
- package/dist/client/conversations-client.d.ts +9 -9
- package/dist/client/hooks-client.d.ts +1 -1
- package/dist/client/index.d.ts +529 -198
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +9 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/interactions-client.d.ts +1 -1
- package/dist/client/manifest-client.d.ts +161 -30
- package/dist/client/manifest-client.d.ts.map +1 -1
- package/dist/client/manifest-client.js +16 -5
- package/dist/client/manifest-client.js.map +1 -1
- package/dist/client/marketplace-client.d.ts +132 -83
- package/dist/client/marketplace-client.d.ts.map +1 -1
- package/dist/client/observability-client.d.ts +2 -2
- package/dist/client/presets-client.d.ts +113 -11
- package/dist/client/presets-client.d.ts.map +1 -1
- package/dist/client/presets-client.js +4 -3
- package/dist/client/presets-client.js.map +1 -1
- package/dist/client/profiles-client.d.ts +1 -0
- package/dist/client/profiles-client.d.ts.map +1 -1
- package/dist/client/states-client.d.ts +30 -21
- package/dist/client/states-client.d.ts.map +1 -1
- package/dist/client/states-client.js +5 -0
- package/dist/client/states-client.js.map +1 -1
- package/dist/client/storage-client.d.ts +19 -0
- package/dist/client/storage-client.d.ts.map +1 -1
- package/dist/client/storage-client.js +14 -17
- package/dist/client/storage-client.js.map +1 -1
- package/dist/client/templates-client.d.ts +20 -2
- package/dist/client/templates-client.d.ts.map +1 -1
- package/dist/client/templates-client.js +1 -1
- package/dist/client/templates-client.js.map +1 -1
- package/dist/client/tool-extensions-client.d.ts +3 -0
- package/dist/client/tool-extensions-client.d.ts.map +1 -1
- package/dist/client/transport.d.ts +2 -1
- package/dist/client/transport.d.ts.map +1 -1
- package/dist/client/transport.js.map +1 -1
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +31 -0
- package/dist/errors.js.map +1 -1
- package/dist/fleet-report.d.ts +14 -2
- package/dist/fleet-report.d.ts.map +1 -1
- package/dist/fleet-report.js +41 -10
- package/dist/fleet-report.js.map +1 -1
- package/dist/generated/api-routes.d.ts +17 -1
- package/dist/generated/api-routes.d.ts.map +1 -1
- package/dist/generated/api-routes.js +7 -2
- package/dist/generated/api-routes.js.map +1 -1
- package/dist/generated/openapi-schemas.d.ts +737 -160
- package/dist/generated/openapi-schemas.d.ts.map +1 -1
- package/dist/generated/openapi-schemas.js +46 -27
- package/dist/generated/openapi-schemas.js.map +1 -1
- package/dist/generated/served-schemas.d.ts +80 -16
- package/dist/generated/served-schemas.d.ts.map +1 -1
- package/dist/generated/served-schemas.js +64 -4
- package/dist/generated/served-schemas.js.map +1 -1
- package/dist/http.d.ts +6 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +11 -0
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/schemas/auth-routes.d.ts +34 -8
- package/dist/schemas/auth-routes.d.ts.map +1 -1
- package/dist/schemas/auth-routes.js +16 -8
- package/dist/schemas/auth-routes.js.map +1 -1
- package/dist/schemas/backup.d.ts +13 -0
- package/dist/schemas/backup.d.ts.map +1 -1
- package/dist/schemas/backup.js +5 -0
- package/dist/schemas/backup.js.map +1 -1
- package/dist/schemas/capabilities.d.ts +11 -6
- package/dist/schemas/capabilities.d.ts.map +1 -1
- package/dist/schemas/capabilities.js +10 -6
- package/dist/schemas/capabilities.js.map +1 -1
- package/dist/schemas/channels.d.ts +7 -1
- package/dist/schemas/channels.d.ts.map +1 -1
- package/dist/schemas/connectors.d.ts +6 -0
- package/dist/schemas/connectors.d.ts.map +1 -1
- package/dist/schemas/conversations.d.ts +11 -11
- package/dist/schemas/extensions.d.ts +8 -4
- package/dist/schemas/extensions.d.ts.map +1 -1
- package/dist/schemas/extensions.js +5 -4
- package/dist/schemas/extensions.js.map +1 -1
- package/dist/schemas/hooks.d.ts +1 -1
- package/dist/schemas/interactions.d.ts +3 -3
- package/dist/schemas/manifest-mcp.d.ts +79 -0
- package/dist/schemas/manifest-mcp.d.ts.map +1 -1
- package/dist/schemas/manifest-mcp.js +19 -0
- package/dist/schemas/manifest-mcp.js.map +1 -1
- package/dist/schemas/marketplace.d.ts +155 -84
- package/dist/schemas/marketplace.d.ts.map +1 -1
- package/dist/schemas/marketplace.js +7 -2
- package/dist/schemas/marketplace.js.map +1 -1
- package/dist/schemas/observability.d.ts +3 -3
- package/dist/schemas/presets.d.ts +107 -14
- package/dist/schemas/presets.d.ts.map +1 -1
- package/dist/schemas/presets.js +7 -5
- package/dist/schemas/presets.js.map +1 -1
- package/dist/schemas/profiles.d.ts +1 -0
- package/dist/schemas/profiles.d.ts.map +1 -1
- package/dist/schemas/served.d.ts +67 -13
- package/dist/schemas/served.d.ts.map +1 -1
- package/dist/schemas/states.d.ts +22 -22
- package/dist/schemas/storage.d.ts +30 -1
- package/dist/schemas/storage.d.ts.map +1 -1
- package/dist/schemas/storage.js +8 -1
- package/dist/schemas/storage.js.map +1 -1
- package/dist/schemas/system-kinds.d.ts +1 -0
- package/dist/schemas/system-kinds.d.ts.map +1 -1
- package/dist/schemas/templates.d.ts +110 -83
- package/dist/schemas/templates.d.ts.map +1 -1
- package/dist/schemas/templates.js +14 -2
- package/dist/schemas/templates.js.map +1 -1
- package/dist/schemas/tools.d.ts +1 -1
- package/package.json +1 -1
- package/src/agents.ts +1 -0
- package/src/client/index.ts +9 -2
- package/src/client/manifest-client.ts +39 -12
- package/src/client/presets-client.ts +20 -6
- package/src/client/states-client.ts +10 -0
- package/src/client/storage-client.ts +21 -17
- package/src/client/templates-client.ts +1 -1
- package/src/client/transport.ts +3 -1
- package/src/errors.ts +34 -0
- package/src/fleet-report.ts +46 -7
- package/src/generated/api-routes.ts +7 -2
- package/src/generated/openapi-schemas.ts +80 -31
- package/src/generated/served-schemas.ts +64 -4
- package/src/http.ts +12 -0
- package/src/index.ts +19 -2
- package/src/schemas/auth-routes.ts +18 -8
- package/src/schemas/backup.ts +7 -0
- package/src/schemas/capabilities.ts +10 -6
- package/src/schemas/channels.ts +2 -0
- package/src/schemas/extensions.ts +5 -4
- package/src/schemas/manifest-mcp.ts +25 -0
- package/src/schemas/marketplace.ts +7 -2
- package/src/schemas/presets.ts +13 -6
- package/src/schemas/storage.ts +10 -1
- package/src/schemas/templates.ts +17 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Manifest / MCP section, env-ref and config-reload sub-clients. */
|
|
1
|
+
/** Manifest / MCP section, per-server MCP ops, env-ref and config-reload sub-clients. */
|
|
2
2
|
import { apiRoutes, buildPath } from '../generated/api-routes';
|
|
3
3
|
import * as s from '../schemas';
|
|
4
4
|
import type { Transport } from './transport';
|
|
@@ -28,6 +28,12 @@ export interface SetMcpSecretEnvBody {
|
|
|
28
28
|
readonly manifest_pointer: string;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/** The include/exclude tool filter of one MCP entry (`PUT .../tool-filter`). */
|
|
32
|
+
export interface McpToolFilter {
|
|
33
|
+
readonly include: readonly string[];
|
|
34
|
+
readonly exclude: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
export function manifestClient(t: Transport) {
|
|
32
38
|
const { req } = t;
|
|
33
39
|
return {
|
|
@@ -38,17 +44,6 @@ export function manifestClient(t: Transport) {
|
|
|
38
44
|
method: 'POST',
|
|
39
45
|
body: { mcp },
|
|
40
46
|
}),
|
|
41
|
-
getMcpStatus: (signal?: AbortSignal) =>
|
|
42
|
-
req(apiRoutes.get_api_mcp_status.path, s.mcpStatus, { signal }),
|
|
43
|
-
reloadMcp: (title: string) =>
|
|
44
|
-
req(
|
|
45
|
-
buildPath(apiRoutes.post_api_mcp_status_title_reload.path, { title }),
|
|
46
|
-
s.mcpReloadResult,
|
|
47
|
-
{
|
|
48
|
-
method: 'POST',
|
|
49
|
-
},
|
|
50
|
-
),
|
|
51
|
-
|
|
52
47
|
// Granular manifest-section entry edits — add/replace or remove ONE entry by
|
|
53
48
|
// title, leaving the rest of the section untouched (the surgical counterpart to
|
|
54
49
|
// the whole-section `setMcpConfig`). Each crosses the config pipeline and returns
|
|
@@ -93,6 +88,38 @@ export function manifestClient(t: Transport) {
|
|
|
93
88
|
exclude_remove: body.exclude_remove ?? [],
|
|
94
89
|
},
|
|
95
90
|
}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Per-server MCP status reads and live ops: status, advertised tools, tool filter, reloads. */
|
|
95
|
+
export function mcpServersClient(t: Transport) {
|
|
96
|
+
const { req } = t;
|
|
97
|
+
return {
|
|
98
|
+
getMcpStatus: (signal?: AbortSignal) =>
|
|
99
|
+
req(apiRoutes.get_api_mcp_status.path, s.mcpStatus, { signal }),
|
|
100
|
+
// Every tool the server advertises, before the entry's tool filter. A POST: the
|
|
101
|
+
// read opens a session to the server.
|
|
102
|
+
listMcpAdvertisedTools: (title: string, signal?: AbortSignal) =>
|
|
103
|
+
req(
|
|
104
|
+
buildPath(apiRoutes.post_api_mcp_status_title_advertised_tools.path, { title }),
|
|
105
|
+
s.mcpAdvertisedTools,
|
|
106
|
+
{ method: 'POST', signal },
|
|
107
|
+
),
|
|
108
|
+
// Replace the entry's include/exclude tool filter; crosses the config pipeline.
|
|
109
|
+
setMcpToolFilter: (title: string, filter: McpToolFilter) =>
|
|
110
|
+
req(
|
|
111
|
+
buildPath(apiRoutes.put_api_mcp_config_entries_title_tool_filter.path, { title }),
|
|
112
|
+
s.reloadConfigResult,
|
|
113
|
+
{ method: 'PUT', body: filter },
|
|
114
|
+
),
|
|
115
|
+
reloadMcp: (title: string) =>
|
|
116
|
+
req(
|
|
117
|
+
buildPath(apiRoutes.post_api_mcp_status_title_reload.path, { title }),
|
|
118
|
+
s.mcpReloadResult,
|
|
119
|
+
{
|
|
120
|
+
method: 'POST',
|
|
121
|
+
},
|
|
122
|
+
),
|
|
96
123
|
|
|
97
124
|
// The MCP servers skipped by the viability check, plus their remediation ops. The
|
|
98
125
|
// LIST rides the fleet fan-out primitive (each worker's failed roster arrives as
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Preset CRUD, versioning and validation sub-client. */
|
|
2
2
|
import { apiRoutes, buildPath } from '../generated/api-routes';
|
|
3
|
+
import type { PresetHolderAction } from '../schemas';
|
|
3
4
|
import * as s from '../schemas';
|
|
4
5
|
import type { Transport } from './transport';
|
|
5
6
|
|
|
@@ -10,7 +11,11 @@ import type { Transport } from './transport';
|
|
|
10
11
|
* `extensions` is the combos list — the create flow OMITS it when there are no
|
|
11
12
|
* combos (the route rejects an explicit `extensions: []`). `output_schema` is the
|
|
12
13
|
* optional author-set output JSON Schema; `input_schema` is the optional author-set
|
|
13
|
-
* input JSON Schema, read by the router as a top-level version field.
|
|
14
|
+
* input JSON Schema, read by the router as a top-level version field. `input_map` is
|
|
15
|
+
* the optional jq program that turns the caller's input into the base tool's
|
|
16
|
+
* arguments (it needs an `input_schema`); `output_map` is the optional jq program that
|
|
17
|
+
* reshapes the base tool's result before the output schema is checked. Each map is
|
|
18
|
+
* inline `content` or a stored template `id` (a plain string is inline jq). Each combo
|
|
14
19
|
* element is a bare extension name or a `{ name, config }` mapping. Categorization
|
|
15
20
|
* tags live in the tool_meta overlay, written after a successful create — never in
|
|
16
21
|
* this body.
|
|
@@ -23,6 +28,8 @@ export interface CreatePresetBody {
|
|
|
23
28
|
readonly extensions?: readonly s.PresetExtensionElement[][];
|
|
24
29
|
readonly output_schema?: Record<string, unknown> | null;
|
|
25
30
|
readonly input_schema?: Record<string, unknown> | null;
|
|
31
|
+
readonly input_map?: s.TemplatedText | string | null;
|
|
32
|
+
readonly output_map?: s.TemplatedText | string | null;
|
|
26
33
|
// The optional door-layer state binding applied around every run of this preset.
|
|
27
34
|
readonly state_binding?: s.StateBinding | null;
|
|
28
35
|
}
|
|
@@ -35,7 +42,9 @@ export interface CreatePresetBody {
|
|
|
35
42
|
* or `input_schema`. `input_schema` is the optional author-set input JSON Schema and
|
|
36
43
|
* follows the same carry-forward sentinel as `output_schema`. `state_binding` is the
|
|
37
44
|
* optional door-layer binding and follows the same sentinel: omitted carries the active
|
|
38
|
-
* one forward, an explicit `null` clears it. `
|
|
45
|
+
* one forward, an explicit `null` clears it. `input_map` and `output_map` follow the same
|
|
46
|
+
* sentinel: omitted carries the active map forward, an explicit `null` clears it.
|
|
47
|
+
* `description` carries forward when omitted;
|
|
39
48
|
* an explicit non-empty string sets it (the API rejects an explicit empty one).
|
|
40
49
|
* Categorization tags are not a version field — they live in the tool_meta overlay.
|
|
41
50
|
*/
|
|
@@ -45,6 +54,8 @@ export interface SavePresetVersionBody {
|
|
|
45
54
|
readonly extensions?: readonly s.PresetExtensionElement[][];
|
|
46
55
|
readonly output_schema?: Record<string, unknown> | null;
|
|
47
56
|
readonly input_schema?: Record<string, unknown> | null;
|
|
57
|
+
readonly input_map?: s.TemplatedText | string | null;
|
|
58
|
+
readonly output_map?: s.TemplatedText | string | null;
|
|
48
59
|
readonly state_binding?: s.StateBinding | null;
|
|
49
60
|
}
|
|
50
61
|
|
|
@@ -63,6 +74,8 @@ export interface ValidatePresetBody {
|
|
|
63
74
|
readonly extensions?: readonly s.PresetExtensionElement[][];
|
|
64
75
|
readonly output_schema?: Record<string, unknown> | null;
|
|
65
76
|
readonly input_schema?: Record<string, unknown> | null;
|
|
77
|
+
readonly input_map?: s.TemplatedText | string | null;
|
|
78
|
+
readonly output_map?: s.TemplatedText | string | null;
|
|
66
79
|
// The optional door-layer state binding to dry-run — validated (never mounted) by the
|
|
67
80
|
// same checks the write would run. In VERSION mode it follows the save-version sentinel:
|
|
68
81
|
// omitted carries the active binding forward, an explicit `null` clears it.
|
|
@@ -112,10 +125,11 @@ export function presetsClient(t: Transport) {
|
|
|
112
125
|
method: 'POST',
|
|
113
126
|
body: { new_name: newName },
|
|
114
127
|
}),
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
getPresetReferees: (name: string, signal?: AbortSignal) =>
|
|
118
|
-
req(buildPath(apiRoutes.get_api_presets_name_referees.path, { name }), s.
|
|
128
|
+
// Every holder that would refuse this preset's rename or delete. A dialog
|
|
129
|
+
// preflights it to list the holders before the server's 409 backstop.
|
|
130
|
+
getPresetReferees: (name: string, action: PresetHolderAction, signal?: AbortSignal) =>
|
|
131
|
+
req(buildPath(apiRoutes.get_api_presets_name_referees.path, { name }), s.holdersPreview, {
|
|
132
|
+
query: { action },
|
|
119
133
|
signal,
|
|
120
134
|
}),
|
|
121
135
|
// The dry-run verdict for a draft (create OR version, mode-resolved server-side):
|
|
@@ -165,6 +165,16 @@ function stateAttachmentMethods(t: Transport) {
|
|
|
165
165
|
s.stateAttachmentUpdated,
|
|
166
166
|
{ method: 'PATCH', body },
|
|
167
167
|
),
|
|
168
|
+
// Every holder that would refuse detaching `template` from the state.
|
|
169
|
+
getStateTemplateReferees: (name: string, template: string, signal?: AbortSignal) =>
|
|
170
|
+
req(
|
|
171
|
+
buildPath(apiRoutes.get_api_states_name_attachments_template_referees.path, {
|
|
172
|
+
name,
|
|
173
|
+
template,
|
|
174
|
+
}),
|
|
175
|
+
s.holdersPreview,
|
|
176
|
+
{ signal },
|
|
177
|
+
),
|
|
168
178
|
detachStateTemplate: (name: string, template: string) =>
|
|
169
179
|
req(
|
|
170
180
|
buildPath(apiRoutes.delete_api_states_name_attachments_template.path, { name, template }),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Storage resource CRUD sub-client. */
|
|
2
2
|
import { apiRoutes, buildPath } from '../generated/api-routes';
|
|
3
|
-
import { apiDownload
|
|
3
|
+
import { apiDownload } from '../http';
|
|
4
4
|
import * as s from '../schemas';
|
|
5
5
|
import type { Transport } from './transport';
|
|
6
6
|
|
|
@@ -17,22 +17,17 @@ export interface StorageUploadBody {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* Dot segments (`.`, `..`), empty segments (a leading/trailing/doubled `/`, or an
|
|
26
|
-
* empty id) are REJECTED loudly rather than encoded: the browser's WHATWG URL parser
|
|
27
|
-
* removes dot-segments from a relative request path before it is sent — collapsing
|
|
28
|
-
* `..` even when percent-encoded — so such an id can never be faithfully transmitted.
|
|
29
|
-
* Left to encode, it would silently retarget the request at an unrelated same-origin
|
|
30
|
-
* route. The server enforces the same relative-path rule; failing fast here keeps a
|
|
31
|
-
* malformed id from ever leaving the client.
|
|
20
|
+
* A possibly-nested storage id for a `{resource_id:path}` route parameter. Only a `.`
|
|
21
|
+
* or `..` segment is refused here: the browser's URL parser removes those before the
|
|
22
|
+
* request is sent, so `./x` would silently reach `x`. Every other spelling (`a//b`,
|
|
23
|
+
* `x/`) is sent as typed, and the server refuses every non-canonical key, these
|
|
24
|
+
* included, with the same words.
|
|
32
25
|
*/
|
|
33
26
|
function storagePath(id: string): string {
|
|
34
|
-
if (id.split('/').some(
|
|
35
|
-
throw new Error(
|
|
27
|
+
if (id.split('/').some((segment) => segment === '.' || segment === '..')) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`non-canonical store key '${id}': a key is '/'-separated names with no empty, '.' or '..' segment`,
|
|
30
|
+
);
|
|
36
31
|
}
|
|
37
32
|
return id;
|
|
38
33
|
}
|
|
@@ -43,12 +38,21 @@ export function storageClient(t: Transport) {
|
|
|
43
38
|
// The content store a storage-provider plugin exposes. Dead by default:
|
|
44
39
|
// `getStorageInfo` reports `present: false` (a 200 empty state) and every other
|
|
45
40
|
// door answers a loud 501 when no provider is installed. Ids may be nested
|
|
46
|
-
// paths: `storagePath` refuses a dot
|
|
47
|
-
//
|
|
41
|
+
// paths: `storagePath` refuses a dot segment the browser would remove, and
|
|
42
|
+
// `buildPath` encodes each part of the route's `{…:path}` parameter with the `/`
|
|
43
|
+
// separators preserved; the server refuses every other non-canonical key.
|
|
48
44
|
getStorageInfo: (signal?: AbortSignal) =>
|
|
49
45
|
req(apiRoutes.get_api_storage.path, s.storageInfo, { signal }),
|
|
50
46
|
listStorageResources: (signal?: AbortSignal) =>
|
|
51
47
|
req(apiRoutes.get_api_storage_resources.path, s.storageResourceList, { signal }),
|
|
48
|
+
readStorageResource: (id: string, signal?: AbortSignal) =>
|
|
49
|
+
req(
|
|
50
|
+
buildPath(apiRoutes.get_api_storage_entries_resource_id.path, {
|
|
51
|
+
resource_id: storagePath(id),
|
|
52
|
+
}),
|
|
53
|
+
s.storedEntry,
|
|
54
|
+
{ signal },
|
|
55
|
+
),
|
|
52
56
|
statStorageResource: (id: string, signal?: AbortSignal) =>
|
|
53
57
|
req(
|
|
54
58
|
buildPath(apiRoutes.get_api_storage_resources_resource_id_stat.path, {
|
|
@@ -9,7 +9,7 @@ export function templatesClient(t: Transport) {
|
|
|
9
9
|
listTemplates: (signal?: AbortSignal) =>
|
|
10
10
|
req(apiRoutes.get_api_templates.path, s.templateNames, { signal }),
|
|
11
11
|
getTemplate: (templateId: string) =>
|
|
12
|
-
req(apiRoutes.post_api_template.path, s.
|
|
12
|
+
req(apiRoutes.post_api_template.path, s.templateEntry, {
|
|
13
13
|
method: 'POST',
|
|
14
14
|
body: { template_id: templateId },
|
|
15
15
|
}),
|
package/src/client/transport.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/** The shared transport seam every sub-client method flows through. */
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
|
|
2
4
|
import type { ApiConfig } from '../http';
|
|
3
5
|
import { apiRequest } from '../http';
|
|
4
6
|
|
|
@@ -11,7 +13,7 @@ export function makeTransport(config: ApiConfig) {
|
|
|
11
13
|
path: string,
|
|
12
14
|
schema: S,
|
|
13
15
|
options?: Parameters<typeof apiRequest>[3],
|
|
14
|
-
) => apiRequest(config, path, schema, options);
|
|
16
|
+
): Promise<z.output<S>> => apiRequest(config, path, schema, options);
|
|
15
17
|
return { config, req };
|
|
16
18
|
}
|
|
17
19
|
|
package/src/errors.ts
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* empty render.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
import { type ReferenceHolder, referenceHolder } from './generated/openapi-schemas';
|
|
10
|
+
|
|
7
11
|
/** The skeleton returned `{ "error": "<message>" }` (or a non-2xx status). */
|
|
8
12
|
export class ApiError extends Error {
|
|
9
13
|
readonly status: number;
|
|
@@ -102,3 +106,33 @@ export class ApiSchemaError extends Error {
|
|
|
102
106
|
this.issues = issues;
|
|
103
107
|
}
|
|
104
108
|
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The holders a refused rename or delete names: an `ApiError` whose body carries a
|
|
112
|
+
* `holders` list answers it, parsed (a malformed list throws). Any other error, or a
|
|
113
|
+
* body without `holders`, answers `null`.
|
|
114
|
+
*/
|
|
115
|
+
export function holdersFromError(error: unknown): ReferenceHolder[] | null {
|
|
116
|
+
if (!(error instanceof ApiError)) return null;
|
|
117
|
+
const body = error.body;
|
|
118
|
+
if (typeof body !== 'object' || body === null || !('holders' in body)) return null;
|
|
119
|
+
return z.array(referenceHolder).parse(body.holders);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const STORED_PRESET_UNREADABLE = 'stored-preset-unreadable';
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The stored preset a read could not walk: an `ApiError` with code
|
|
126
|
+
* `stored-preset-unreadable` answers the row's name from `body.preset`. That code without a
|
|
127
|
+
* non-empty string `preset` throws; any other error answers `null`.
|
|
128
|
+
*/
|
|
129
|
+
export function storedPresetFaultFromError(error: unknown): string | null {
|
|
130
|
+
if (!(error instanceof ApiError) || error.code !== STORED_PRESET_UNREADABLE) return null;
|
|
131
|
+
const body = error.body;
|
|
132
|
+
const preset =
|
|
133
|
+
typeof body === 'object' && body !== null && 'preset' in body ? body.preset : undefined;
|
|
134
|
+
if (typeof preset !== 'string' || preset === '') {
|
|
135
|
+
throw new Error(`a '${STORED_PRESET_UNREADABLE}' error carried no stored preset name`);
|
|
136
|
+
}
|
|
137
|
+
return preset;
|
|
138
|
+
}
|
package/src/fleet-report.ts
CHANGED
|
@@ -58,6 +58,12 @@ export interface FleetReportSummary {
|
|
|
58
58
|
readonly error: string | null;
|
|
59
59
|
/** The workers whose reload named recycle-class keys awaiting a respawn. */
|
|
60
60
|
readonly awaiting: readonly FleetWorkerAwaitingRespawn[];
|
|
61
|
+
/**
|
|
62
|
+
* The config store's error releasing its exclusive write span after the persist, or
|
|
63
|
+
* `null` when it released. Non-null means the change landed but the store may hold
|
|
64
|
+
* the span until the writer process exits, so a later write can block or be refused.
|
|
65
|
+
*/
|
|
66
|
+
readonly spanReleaseError: string | null;
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
/**
|
|
@@ -72,9 +78,12 @@ function awaitingKeys(payload: unknown): string[] {
|
|
|
72
78
|
return keys.filter((key): key is string => typeof key === 'string');
|
|
73
79
|
}
|
|
74
80
|
|
|
75
|
-
/**
|
|
81
|
+
/**
|
|
82
|
+
* True when a summary describes a failure the operator must be shown: a propagation
|
|
83
|
+
* that did not converge, or a write span the store did not release.
|
|
84
|
+
*/
|
|
76
85
|
export function isFleetReportFailure(summary: FleetReportSummary | null): boolean {
|
|
77
|
-
return summary !== null && summary.status !== 'converged';
|
|
86
|
+
return summary !== null && (summary.status !== 'converged' || summary.spanReleaseError !== null);
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
/**
|
|
@@ -88,15 +97,23 @@ export function summarizeFleetResult(result: Omit<FleetResult, 'ok'>): FleetRepo
|
|
|
88
97
|
const awaiting: FleetWorkerAwaitingRespawn[] = result.results
|
|
89
98
|
.map((entry) => ({ name: entry.name, keys: awaitingKeys(entry.payload) }))
|
|
90
99
|
.filter((entry) => entry.keys.length > 0);
|
|
91
|
-
return summarizeWith(result, awaiting);
|
|
100
|
+
return summarizeWith(result, awaiting, null);
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
function summarizeWith(
|
|
95
104
|
result: Omit<FleetResult, 'ok'>,
|
|
96
105
|
awaiting: readonly FleetWorkerAwaitingRespawn[],
|
|
106
|
+
spanReleaseError: string | null,
|
|
97
107
|
): FleetReportSummary {
|
|
98
108
|
if (!result.reachable) {
|
|
99
|
-
return {
|
|
109
|
+
return {
|
|
110
|
+
status: 'unreachable',
|
|
111
|
+
note: null,
|
|
112
|
+
failures: [],
|
|
113
|
+
error: result.error,
|
|
114
|
+
awaiting,
|
|
115
|
+
spanReleaseError,
|
|
116
|
+
};
|
|
100
117
|
}
|
|
101
118
|
const failures: FleetWorkerFailure[] = result.results
|
|
102
119
|
.filter((entry) => entry.outcome !== 'applied')
|
|
@@ -111,6 +128,7 @@ function summarizeWith(
|
|
|
111
128
|
failures,
|
|
112
129
|
error: null,
|
|
113
130
|
awaiting,
|
|
131
|
+
spanReleaseError,
|
|
114
132
|
};
|
|
115
133
|
}
|
|
116
134
|
|
|
@@ -122,16 +140,37 @@ function summarizeWith(
|
|
|
122
140
|
* `awaiting` is the mutation's own verdict (its response's `awaiting_respawn`, or `[]`
|
|
123
141
|
* for a mutation that states none): the operation knows whether its recycle roll
|
|
124
142
|
* carried a worker's moved env, so its per-worker rows are never re-read for it.
|
|
143
|
+
* `spanReleaseError` is the response's `span_release_error`: a non-null value makes the
|
|
144
|
+
* summary a failure ({@link isFleetReportFailure}) whatever the fan-out reports, and a
|
|
145
|
+
* response that mutated no manifest still yields a summary carrying it.
|
|
125
146
|
*/
|
|
126
147
|
export function summarizeFleetFanout(
|
|
127
148
|
fanout: FleetReportFanout | null | undefined,
|
|
128
149
|
awaiting: readonly FleetWorkerAwaitingRespawn[],
|
|
150
|
+
spanReleaseError: string | null,
|
|
129
151
|
): FleetReportSummary | null {
|
|
130
|
-
if (fanout === null || fanout === undefined)
|
|
152
|
+
if (fanout === null || fanout === undefined) {
|
|
153
|
+
if (spanReleaseError === null) return null;
|
|
154
|
+
return {
|
|
155
|
+
status: 'converged',
|
|
156
|
+
note: null,
|
|
157
|
+
failures: [],
|
|
158
|
+
error: null,
|
|
159
|
+
awaiting,
|
|
160
|
+
spanReleaseError,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
131
163
|
if (fanout.mode === 'local-only') {
|
|
132
|
-
return {
|
|
164
|
+
return {
|
|
165
|
+
status: 'converged',
|
|
166
|
+
note: fanout.note,
|
|
167
|
+
failures: [],
|
|
168
|
+
error: null,
|
|
169
|
+
awaiting,
|
|
170
|
+
spanReleaseError,
|
|
171
|
+
};
|
|
133
172
|
}
|
|
134
|
-
return summarizeWith(fanout, awaiting);
|
|
173
|
+
return summarizeWith(fanout, awaiting, spanReleaseError);
|
|
135
174
|
}
|
|
136
175
|
|
|
137
176
|
/** One MCP server skipped by the viability check — its title, a coarse status, and the
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
//
|
|
5
5
|
// The platform's core routes by operationId. A placeholder written `{name:path}` matches
|
|
6
6
|
// across `/` separators (the server names its converter on the parameter).
|
|
7
|
-
import { encodeSegment } from '../http';
|
|
7
|
+
import { encodePathPart, encodeSegment } from '../http';
|
|
8
8
|
|
|
9
9
|
export const apiRoutes = {
|
|
10
10
|
delete_api_agents_config_entries_title: { method: "DELETE", path: "/api/agents-config/entries/{title}" },
|
|
@@ -129,6 +129,7 @@ export const apiRoutes = {
|
|
|
129
129
|
get_api_states_name: { method: "GET", path: "/api/states/{name}" },
|
|
130
130
|
get_api_states_name_attachments: { method: "GET", path: "/api/states/{name}/attachments" },
|
|
131
131
|
get_api_states_name_attachments_template: { method: "GET", path: "/api/states/{name}/attachments/{template}" },
|
|
132
|
+
get_api_states_name_attachments_template_referees: { method: "GET", path: "/api/states/{name}/attachments/{template}/referees" },
|
|
132
133
|
get_api_states_name_consumers: { method: "GET", path: "/api/states/{name}/consumers" },
|
|
133
134
|
get_api_states_name_records_check: { method: "GET", path: "/api/states/{name}/records/check" },
|
|
134
135
|
get_api_states_name_records_target_kind_target_name_kind_key: { method: "GET", path: "/api/states/{name}/records/{target_kind}/{target_name}/{kind}/{key}" },
|
|
@@ -137,6 +138,7 @@ export const apiRoutes = {
|
|
|
137
138
|
get_api_states_name_stats: { method: "GET", path: "/api/states/{name}/stats" },
|
|
138
139
|
get_api_states_name_subjects: { method: "GET", path: "/api/states/{name}/subjects" },
|
|
139
140
|
get_api_storage: { method: "GET", path: "/api/storage" },
|
|
141
|
+
get_api_storage_entries_resource_id: { method: "GET", path: "/api/storage/entries/{resource_id:path}" },
|
|
140
142
|
get_api_storage_resources: { method: "GET", path: "/api/storage/resources" },
|
|
141
143
|
get_api_storage_resources_resource_id_content: { method: "GET", path: "/api/storage/resources/{resource_id:path}/content" },
|
|
142
144
|
get_api_storage_resources_resource_id_stat: { method: "GET", path: "/api/storage/resources/{resource_id:path}/stat" },
|
|
@@ -214,6 +216,7 @@ export const apiRoutes = {
|
|
|
214
216
|
post_api_mcp_config_entries: { method: "POST", path: "/api/mcp-config/entries" },
|
|
215
217
|
post_api_mcp_config_secret_env: { method: "POST", path: "/api/mcp-config/secret-env" },
|
|
216
218
|
post_api_mcp_status_reload_failed: { method: "POST", path: "/api/mcp-status/reload-failed" },
|
|
219
|
+
post_api_mcp_status_title_advertised_tools: { method: "POST", path: "/api/mcp-status/{title}/advertised-tools" },
|
|
217
220
|
post_api_mcp_status_title_deregister: { method: "POST", path: "/api/mcp-status/{title}/deregister" },
|
|
218
221
|
post_api_mcp_status_title_reload: { method: "POST", path: "/api/mcp-status/{title}/reload" },
|
|
219
222
|
post_api_notifications: { method: "POST", path: "/api/notifications" },
|
|
@@ -257,6 +260,7 @@ export const apiRoutes = {
|
|
|
257
260
|
put_api_conversations_persons_person_id_locale: { method: "PUT", path: "/api/conversations/persons/{person_id}/locale" },
|
|
258
261
|
put_api_conversations_route_name_thread_mode: { method: "PUT", path: "/api/conversations/{route_name}/thread/mode" },
|
|
259
262
|
put_api_hooks_topics_topic_verifier: { method: "PUT", path: "/api/hooks/topics/{topic}/verifier" },
|
|
263
|
+
put_api_mcp_config_entries_title_tool_filter: { method: "PUT", path: "/api/mcp-config/entries/{title}/tool-filter" },
|
|
260
264
|
put_api_presets_name_versions_version_tags: { method: "PUT", path: "/api/presets/{name}/versions/{version}/tags" },
|
|
261
265
|
put_api_state_templates_name: { method: "PUT", path: "/api/state-templates/{name}" },
|
|
262
266
|
put_api_states_name: { method: "PUT", path: "/api/states/{name}" },
|
|
@@ -310,6 +314,7 @@ export const apiPathPrefixes = [
|
|
|
310
314
|
"/api/states/{name}/records/{target_kind}/{target_name}/{kind}",
|
|
311
315
|
"/api/states/{name}/records/{target_kind}/{target_name}/{kind}/{key}/template-jq",
|
|
312
316
|
"/api/storage/dirs",
|
|
317
|
+
"/api/storage/entries",
|
|
313
318
|
"/api/system",
|
|
314
319
|
"/api/tool-meta/tools",
|
|
315
320
|
"/api/tools-config",
|
|
@@ -327,6 +332,6 @@ export function buildPath(template: ApiPathTemplate, params: Record<string, stri
|
|
|
327
332
|
return template.replace(/\{([^}:]+)(:path)?\}/g, (_match, name: string, multi?: string) => {
|
|
328
333
|
const value = params[name];
|
|
329
334
|
if (value === undefined) throw new Error(`buildPath: missing param ${name} for ${template}`);
|
|
330
|
-
return multi ? value.split('/').map(
|
|
335
|
+
return multi ? value.split('/').map(encodePathPart).join('/') : encodeSegment(value);
|
|
331
336
|
});
|
|
332
337
|
}
|