@slashfi/agents-sdk 0.77.0 → 0.77.2
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/adk-tools.d.ts +2 -2
- package/dist/adk-tools.d.ts.map +1 -1
- package/dist/adk-tools.js +258 -118
- package/dist/adk-tools.js.map +1 -1
- package/dist/adk.js +7 -9
- package/dist/adk.js.map +1 -1
- package/dist/agent-definitions/config.d.ts.map +1 -1
- package/dist/agent-definitions/config.js +12 -14
- package/dist/agent-definitions/config.js.map +1 -1
- package/dist/cjs/adk-tools.js +258 -118
- package/dist/cjs/adk-tools.js.map +1 -1
- package/dist/cjs/agent-definitions/config.js +12 -14
- package/dist/cjs/agent-definitions/config.js.map +1 -1
- package/dist/cjs/config-store.js +34 -17
- package/dist/cjs/config-store.js.map +1 -1
- package/dist/cjs/define-config.js +5 -7
- package/dist/cjs/define-config.js.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/materialize.js +1 -1
- package/dist/cjs/materialize.js.map +1 -1
- package/dist/cjs/registry-consumer.js +1 -1
- package/dist/cjs/registry.js +33 -2
- package/dist/cjs/registry.js.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/config-store.d.ts +3 -3
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +34 -17
- package/dist/config-store.js.map +1 -1
- package/dist/define-config.d.ts +11 -18
- package/dist/define-config.d.ts.map +1 -1
- package/dist/define-config.js +5 -7
- package/dist/define-config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/materialize.js +1 -1
- package/dist/materialize.js.map +1 -1
- package/dist/registry-consumer.d.ts +1 -1
- package/dist/registry-consumer.js +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +33 -2
- package/dist/registry.js.map +1 -1
- package/dist/types.d.ts +5 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +8 -8
- package/package.json +1 -1
- package/src/adk-tools.ts +289 -127
- package/src/adk.ts +7 -8
- package/src/agent-definitions/config.ts +15 -16
- package/src/config-store.ts +43 -19
- package/src/consumer.test.ts +7 -7
- package/src/define-config.ts +11 -20
- package/src/index.ts +1 -0
- package/src/materialize.ts +1 -1
- package/src/ref-naming.test.ts +164 -91
- package/src/registry-consumer.ts +1 -1
- package/src/registry.ts +40 -2
- package/src/types.ts +21 -6
package/src/adk-tools.ts
CHANGED
|
@@ -17,10 +17,252 @@
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import { AdkError } from "./adk-error.js";
|
|
22
|
+
import { zodToOpenAiJsonSchema } from "./call-agent-schema.js";
|
|
20
23
|
import type { Adk } from "./config-store.js";
|
|
21
24
|
import type { RefEntry, RegistryEntry } from "./define-config.js";
|
|
22
25
|
import { defineTool } from "./define.js";
|
|
23
|
-
import type { ToolContext, ToolDefinition } from "./types.js";
|
|
26
|
+
import type { JsonSchema, ToolContext, ToolDefinition } from "./types.js";
|
|
27
|
+
|
|
28
|
+
const objectRecordSchema = z.record(z.unknown());
|
|
29
|
+
const sourceRegistrySchema = z
|
|
30
|
+
.object({
|
|
31
|
+
url: z.string().min(1).describe("Registry MCP URL."),
|
|
32
|
+
agentPath: z.string().optional().describe("Agent path on that registry."),
|
|
33
|
+
})
|
|
34
|
+
.passthrough();
|
|
35
|
+
const refScopeSchema = z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("Config scope to operate on.");
|
|
39
|
+
const refNameSchema = z.string().min(1).describe("Local connection name.");
|
|
40
|
+
|
|
41
|
+
const refAddOperationSchema = z
|
|
42
|
+
.object({
|
|
43
|
+
operation: z.literal("add"),
|
|
44
|
+
scope: refScopeSchema,
|
|
45
|
+
ref: z
|
|
46
|
+
.string()
|
|
47
|
+
.min(1)
|
|
48
|
+
.optional()
|
|
49
|
+
.describe(
|
|
50
|
+
"Canonical agent path, e.g. 'google-calendar'. Defaults to name when omitted.",
|
|
51
|
+
),
|
|
52
|
+
name: refNameSchema
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("Local connection name. Defaults to ref when omitted."),
|
|
55
|
+
scheme: z
|
|
56
|
+
.enum(["registry", "mcp", "https"])
|
|
57
|
+
.optional()
|
|
58
|
+
.describe(
|
|
59
|
+
"Connection type. Usually inferred from sourceRegistry or url.",
|
|
60
|
+
),
|
|
61
|
+
url: z
|
|
62
|
+
.string()
|
|
63
|
+
.min(1)
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Direct MCP/HTTPS URL. Required for direct mcp/https refs."),
|
|
66
|
+
sourceRegistry: sourceRegistrySchema
|
|
67
|
+
.optional()
|
|
68
|
+
.describe(
|
|
69
|
+
"Registry that serves this agent. Required for registry-backed refs.",
|
|
70
|
+
),
|
|
71
|
+
config: objectRecordSchema
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Optional per-instance config."),
|
|
74
|
+
})
|
|
75
|
+
.passthrough()
|
|
76
|
+
.superRefine((input, ctx) => {
|
|
77
|
+
if (!input.ref && !input.name) {
|
|
78
|
+
ctx.addIssue({
|
|
79
|
+
code: z.ZodIssueCode.custom,
|
|
80
|
+
path: ["ref"],
|
|
81
|
+
message: "Either ref or name is required.",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (input.scheme === "registry" && !input.sourceRegistry?.url) {
|
|
85
|
+
ctx.addIssue({
|
|
86
|
+
code: z.ZodIssueCode.custom,
|
|
87
|
+
path: ["sourceRegistry", "url"],
|
|
88
|
+
message: "scheme=registry requires sourceRegistry.url.",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if ((input.scheme === "mcp" || input.scheme === "https") && !input.url) {
|
|
92
|
+
ctx.addIssue({
|
|
93
|
+
code: z.ZodIssueCode.custom,
|
|
94
|
+
path: ["url"],
|
|
95
|
+
message: `scheme=${input.scheme} requires url.`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (!input.url && !input.sourceRegistry?.url) {
|
|
99
|
+
ctx.addIssue({
|
|
100
|
+
code: z.ZodIssueCode.custom,
|
|
101
|
+
path: ["sourceRegistry"],
|
|
102
|
+
message:
|
|
103
|
+
"Connection target is required: provide sourceRegistry.url for a registry ref, or url for a direct mcp/https ref.",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const refOperationSchemas = {
|
|
109
|
+
add: refAddOperationSchema,
|
|
110
|
+
remove: z
|
|
111
|
+
.object({
|
|
112
|
+
operation: z.literal("remove"),
|
|
113
|
+
scope: refScopeSchema,
|
|
114
|
+
name: refNameSchema,
|
|
115
|
+
})
|
|
116
|
+
.passthrough(),
|
|
117
|
+
list: z
|
|
118
|
+
.object({ operation: z.literal("list"), scope: refScopeSchema })
|
|
119
|
+
.passthrough(),
|
|
120
|
+
update: z
|
|
121
|
+
.object({
|
|
122
|
+
operation: z.literal("update"),
|
|
123
|
+
scope: refScopeSchema,
|
|
124
|
+
name: refNameSchema,
|
|
125
|
+
ref: z.string().optional(),
|
|
126
|
+
scheme: z.enum(["registry", "mcp", "https"]).optional(),
|
|
127
|
+
url: z.string().optional(),
|
|
128
|
+
sourceRegistry: sourceRegistrySchema.optional(),
|
|
129
|
+
config: objectRecordSchema.optional(),
|
|
130
|
+
})
|
|
131
|
+
.passthrough(),
|
|
132
|
+
inspect: z
|
|
133
|
+
.object({
|
|
134
|
+
operation: z.literal("inspect"),
|
|
135
|
+
scope: refScopeSchema,
|
|
136
|
+
name: refNameSchema,
|
|
137
|
+
full: z.boolean().optional(),
|
|
138
|
+
})
|
|
139
|
+
.passthrough(),
|
|
140
|
+
call: z
|
|
141
|
+
.object({
|
|
142
|
+
operation: z.literal("call"),
|
|
143
|
+
scope: refScopeSchema,
|
|
144
|
+
name: refNameSchema,
|
|
145
|
+
tool: z.string().min(1),
|
|
146
|
+
params: objectRecordSchema.optional(),
|
|
147
|
+
})
|
|
148
|
+
.passthrough(),
|
|
149
|
+
auth: z
|
|
150
|
+
.object({
|
|
151
|
+
operation: z.literal("auth"),
|
|
152
|
+
scope: refScopeSchema,
|
|
153
|
+
name: refNameSchema,
|
|
154
|
+
ref: z.string().optional(),
|
|
155
|
+
apiKey: z.string().optional(),
|
|
156
|
+
credentials: z.record(z.string()).optional(),
|
|
157
|
+
sourceRegistry: sourceRegistrySchema.optional(),
|
|
158
|
+
})
|
|
159
|
+
.passthrough(),
|
|
160
|
+
"auth-status": z
|
|
161
|
+
.object({
|
|
162
|
+
operation: z.literal("auth-status"),
|
|
163
|
+
scope: refScopeSchema,
|
|
164
|
+
name: refNameSchema,
|
|
165
|
+
})
|
|
166
|
+
.passthrough(),
|
|
167
|
+
"refresh-token": z
|
|
168
|
+
.object({
|
|
169
|
+
operation: z.literal("refresh-token"),
|
|
170
|
+
scope: refScopeSchema,
|
|
171
|
+
name: refNameSchema,
|
|
172
|
+
})
|
|
173
|
+
.passthrough(),
|
|
174
|
+
resources: z
|
|
175
|
+
.object({
|
|
176
|
+
operation: z.literal("resources"),
|
|
177
|
+
scope: refScopeSchema,
|
|
178
|
+
name: refNameSchema,
|
|
179
|
+
})
|
|
180
|
+
.passthrough(),
|
|
181
|
+
read: z
|
|
182
|
+
.object({
|
|
183
|
+
operation: z.literal("read"),
|
|
184
|
+
scope: refScopeSchema,
|
|
185
|
+
name: refNameSchema,
|
|
186
|
+
uris: z.array(z.string()),
|
|
187
|
+
})
|
|
188
|
+
.passthrough(),
|
|
189
|
+
} as const;
|
|
190
|
+
|
|
191
|
+
const refToolInputSchema = z.union([
|
|
192
|
+
refOperationSchemas.add,
|
|
193
|
+
refOperationSchemas.remove,
|
|
194
|
+
refOperationSchemas.list,
|
|
195
|
+
refOperationSchemas.update,
|
|
196
|
+
refOperationSchemas.inspect,
|
|
197
|
+
refOperationSchemas.call,
|
|
198
|
+
refOperationSchemas.auth,
|
|
199
|
+
refOperationSchemas["auth-status"],
|
|
200
|
+
refOperationSchemas["refresh-token"],
|
|
201
|
+
refOperationSchemas.resources,
|
|
202
|
+
refOperationSchemas.read,
|
|
203
|
+
]);
|
|
204
|
+
const refToolInputJsonSchema = zodToOpenAiJsonSchema(
|
|
205
|
+
refToolInputSchema,
|
|
206
|
+
) as JsonSchema;
|
|
207
|
+
|
|
208
|
+
function parseRefToolInput(
|
|
209
|
+
input: Record<string, unknown>,
|
|
210
|
+
): Record<string, unknown> {
|
|
211
|
+
const op = typeof input.operation === "string" ? input.operation : undefined;
|
|
212
|
+
const schema =
|
|
213
|
+
op && op in refOperationSchemas
|
|
214
|
+
? refOperationSchemas[op as keyof typeof refOperationSchemas]
|
|
215
|
+
: refToolInputSchema;
|
|
216
|
+
const result = schema.safeParse(input);
|
|
217
|
+
if (result.success) return result.data as Record<string, unknown>;
|
|
218
|
+
|
|
219
|
+
const operation = op ? `ref.${op}` : "ref";
|
|
220
|
+
throw new AdkError({
|
|
221
|
+
code: "TOOL_INPUT_INVALID",
|
|
222
|
+
message: `Invalid ${operation} input`,
|
|
223
|
+
hint: "The expected input schema is serialized in details.schema; operation-specific schema is in details.operationSchema.",
|
|
224
|
+
details: {
|
|
225
|
+
operation,
|
|
226
|
+
issues: result.error.issues.map((issue) => ({
|
|
227
|
+
path: issue.path.join("."),
|
|
228
|
+
message: issue.message,
|
|
229
|
+
})),
|
|
230
|
+
received: input,
|
|
231
|
+
schema: refToolInputJsonSchema,
|
|
232
|
+
...(op &&
|
|
233
|
+
op in refOperationSchemas && {
|
|
234
|
+
operationSchema: zodToOpenAiJsonSchema(
|
|
235
|
+
refOperationSchemas[op as keyof typeof refOperationSchemas],
|
|
236
|
+
),
|
|
237
|
+
}),
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function withScopeSchema(
|
|
243
|
+
schema: JsonSchema,
|
|
244
|
+
scopeSchema: JsonSchema,
|
|
245
|
+
): JsonSchema {
|
|
246
|
+
const clone = JSON.parse(JSON.stringify(schema)) as JsonSchema;
|
|
247
|
+
const visit = (value: unknown) => {
|
|
248
|
+
if (!value || typeof value !== "object") return;
|
|
249
|
+
if (Array.isArray(value)) {
|
|
250
|
+
for (const item of value) visit(item);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const record = value as Record<string, unknown>;
|
|
255
|
+
const properties = record.properties as Record<string, unknown> | undefined;
|
|
256
|
+
if (properties?.scope) {
|
|
257
|
+
properties.scope = scopeSchema;
|
|
258
|
+
}
|
|
259
|
+
for (const child of Object.values(record)) {
|
|
260
|
+
visit(child);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
visit(clone);
|
|
264
|
+
return clone;
|
|
265
|
+
}
|
|
24
266
|
|
|
25
267
|
export interface AdkToolsHooks<TCtx extends ToolContext = ToolContext> {
|
|
26
268
|
/**
|
|
@@ -30,10 +272,11 @@ export interface AdkToolsHooks<TCtx extends ToolContext = ToolContext> {
|
|
|
30
272
|
*
|
|
31
273
|
* @example
|
|
32
274
|
* ```ts
|
|
33
|
-
* getAuthStateContext: async (ctx) => ({ tid: ctx.tenantId, uid: ctx.userId })
|
|
275
|
+
* getAuthStateContext: async (input, ctx) => ({ tid: ctx.tenantId, uid: ctx.userId, name: input.name })
|
|
34
276
|
* ```
|
|
35
277
|
*/
|
|
36
278
|
getAuthStateContext?: (
|
|
279
|
+
input: Record<string, unknown>,
|
|
37
280
|
ctx: TCtx,
|
|
38
281
|
) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
39
282
|
}
|
|
@@ -66,154 +309,68 @@ export function createAdkTools<TCtx extends ToolContext = ToolContext>(
|
|
|
66
309
|
const refTool = defineTool({
|
|
67
310
|
name: "ref",
|
|
68
311
|
description:
|
|
69
|
-
"Manage agent refs. Operations: add, remove, list, update, inspect, call, auth, auth-status, refresh-token, resources, read. For `add`, supply `ref` (canonical agent path, e.g. 'notion') and
|
|
70
|
-
inputSchema:
|
|
71
|
-
type: "object" as const,
|
|
72
|
-
properties: {
|
|
73
|
-
operation: {
|
|
74
|
-
type: "string",
|
|
75
|
-
enum: [
|
|
76
|
-
"add",
|
|
77
|
-
"remove",
|
|
78
|
-
"list",
|
|
79
|
-
"update",
|
|
80
|
-
"inspect",
|
|
81
|
-
"call",
|
|
82
|
-
"auth",
|
|
83
|
-
"auth-status",
|
|
84
|
-
"refresh-token",
|
|
85
|
-
"resources",
|
|
86
|
-
"read",
|
|
87
|
-
],
|
|
88
|
-
},
|
|
89
|
-
scope: scopeSchema,
|
|
90
|
-
ref: {
|
|
91
|
-
type: "string",
|
|
92
|
-
description:
|
|
93
|
-
"Canonical agent path on the remote registry (e.g. 'notion', 'linear', 'github'). Used by `add` to identify which agent definition to connect to. Other operations use `name` instead. If you call `add` with only `name` and no `ref`, `ref` defaults to `name`.",
|
|
94
|
-
},
|
|
95
|
-
name: {
|
|
96
|
-
type: "string",
|
|
97
|
-
description:
|
|
98
|
-
"Local identifier for this ref, used by all operations except `add` to look up the entry. On `add`, `name` is optional — it only needs to differ from `ref` when you want multiple local instances of the same agent (e.g. `{ ref: 'notion', name: 'work-notion' }`). Omit it and the ref is identified by its canonical path.",
|
|
99
|
-
},
|
|
100
|
-
scheme: {
|
|
101
|
-
type: "string",
|
|
102
|
-
description:
|
|
103
|
-
"Connection scheme: 'mcp' (direct MCP server), 'https' (REST proxy), or 'registry' (discovered via a registry). Auto-inferred from `url` or `sourceRegistry` when omitted.",
|
|
104
|
-
},
|
|
105
|
-
url: {
|
|
106
|
-
type: "string",
|
|
107
|
-
description:
|
|
108
|
-
"Direct URL to the agent (e.g. https://mcp.notion.com/mcp). Required for 'mcp' and 'https' schemes.",
|
|
109
|
-
},
|
|
110
|
-
sourceRegistry: {
|
|
111
|
-
type: "object",
|
|
112
|
-
properties: {
|
|
113
|
-
url: { type: "string" },
|
|
114
|
-
agentPath: { type: "string" },
|
|
115
|
-
},
|
|
116
|
-
description:
|
|
117
|
-
"When scheme is 'registry', the registry + agent path to resolve through.",
|
|
118
|
-
},
|
|
119
|
-
config: {
|
|
120
|
-
type: "object",
|
|
121
|
-
description:
|
|
122
|
-
"Per-instance config passed to the agent (headers, credentials, etc.). Supports `{{secret-uri}}` templates.",
|
|
123
|
-
},
|
|
124
|
-
tool: {
|
|
125
|
-
type: "string",
|
|
126
|
-
description:
|
|
127
|
-
"For `call` operation: the tool name on the ref to invoke.",
|
|
128
|
-
},
|
|
129
|
-
params: {
|
|
130
|
-
type: "object",
|
|
131
|
-
description: "For `call` operation: arguments to pass to the tool.",
|
|
132
|
-
},
|
|
133
|
-
full: {
|
|
134
|
-
type: "boolean",
|
|
135
|
-
description:
|
|
136
|
-
"For `inspect` operation: include full agent definition.",
|
|
137
|
-
},
|
|
138
|
-
uris: {
|
|
139
|
-
type: "array",
|
|
140
|
-
items: { type: "string" },
|
|
141
|
-
description: "For `read` operation: the resource URIs to read.",
|
|
142
|
-
},
|
|
143
|
-
apiKey: {
|
|
144
|
-
type: "string",
|
|
145
|
-
description: "For `auth` operation: pre-provisioned API key.",
|
|
146
|
-
},
|
|
147
|
-
credentials: {
|
|
148
|
-
type: "object",
|
|
149
|
-
description:
|
|
150
|
-
"For `auth` operation: key-value map of credential fields (keys match field names from the auth challenge).",
|
|
151
|
-
},
|
|
152
|
-
},
|
|
153
|
-
required: ["operation"],
|
|
154
|
-
},
|
|
312
|
+
"Manage agent refs. Operations: add, remove, list, update, inspect, call, auth, auth-status, refresh-token, resources, read. For `add`, supply `ref` (canonical agent path, e.g. 'notion') and `name` (local identifier). If `name` is omitted on add, it defaults to `ref`. For every other operation, pass `name`.",
|
|
313
|
+
inputSchema: withScopeSchema(refToolInputJsonSchema, scopeSchema),
|
|
155
314
|
execute: async (input: Record<string, unknown>, ctx) => {
|
|
315
|
+
const parsedInput = parseRefToolInput(input);
|
|
156
316
|
const adk = await resolveScope(
|
|
157
|
-
|
|
317
|
+
parsedInput.scope as string | undefined,
|
|
158
318
|
ctx as TCtx,
|
|
159
319
|
);
|
|
160
|
-
const op =
|
|
320
|
+
const op = parsedInput.operation as string;
|
|
161
321
|
|
|
162
322
|
switch (op) {
|
|
163
323
|
case "add": {
|
|
164
324
|
// Accept `ref` or `name` (or both). If only one is given, the
|
|
165
|
-
// other defaults to it.
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const refValue = (input.ref ?? input.name) as string | undefined;
|
|
325
|
+
// other defaults to it. The stored entry always has an explicit
|
|
326
|
+
// `name`, so downstream auth/callback state can distinguish the
|
|
327
|
+
// canonical ref from the local connection handle.
|
|
328
|
+
const refValue = (parsedInput.ref ?? parsedInput.name) as
|
|
329
|
+
| string
|
|
330
|
+
| undefined;
|
|
172
331
|
if (!refValue) {
|
|
173
332
|
throw new Error(
|
|
174
333
|
"ref.add: must supply either 'ref' (canonical agent path) or 'name' (local identifier); both may be the same string for the common single-instance case.",
|
|
175
334
|
);
|
|
176
335
|
}
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (
|
|
185
|
-
entry.
|
|
186
|
-
|
|
187
|
-
if (input.sourceRegistry) entry.sourceRegistry = input.sourceRegistry;
|
|
188
|
-
if (input.config) entry.config = input.config;
|
|
336
|
+
const nameValue = (parsedInput.name ?? refValue) as string;
|
|
337
|
+
const entry: Record<string, unknown> = {
|
|
338
|
+
ref: refValue,
|
|
339
|
+
name: nameValue,
|
|
340
|
+
};
|
|
341
|
+
if (parsedInput.scheme) entry.scheme = parsedInput.scheme;
|
|
342
|
+
if (parsedInput.url) entry.url = parsedInput.url;
|
|
343
|
+
if (parsedInput.sourceRegistry)
|
|
344
|
+
entry.sourceRegistry = parsedInput.sourceRegistry;
|
|
345
|
+
if (parsedInput.config) entry.config = parsedInput.config;
|
|
189
346
|
const { security } = await adk.ref.add(entry as unknown as RefEntry);
|
|
190
347
|
return {
|
|
191
348
|
added: true,
|
|
192
349
|
ref: refValue,
|
|
193
|
-
name:
|
|
350
|
+
name: nameValue,
|
|
194
351
|
security,
|
|
195
352
|
};
|
|
196
353
|
}
|
|
197
354
|
case "remove":
|
|
198
|
-
return { removed: await adk.ref.remove(
|
|
355
|
+
return { removed: await adk.ref.remove(parsedInput.name as string) };
|
|
199
356
|
case "list":
|
|
200
357
|
return { refs: await adk.ref.list() };
|
|
201
358
|
case "update":
|
|
202
359
|
return {
|
|
203
360
|
updated: await adk.ref.update(
|
|
204
|
-
|
|
205
|
-
|
|
361
|
+
parsedInput.name as string,
|
|
362
|
+
parsedInput as unknown as Partial<RefEntry>,
|
|
206
363
|
),
|
|
207
364
|
};
|
|
208
365
|
case "inspect":
|
|
209
|
-
return await adk.ref.inspect(
|
|
210
|
-
full:
|
|
366
|
+
return await adk.ref.inspect(parsedInput.name as string, {
|
|
367
|
+
full: parsedInput.full as boolean,
|
|
211
368
|
});
|
|
212
369
|
case "call":
|
|
213
370
|
return await adk.ref.call(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
371
|
+
parsedInput.name as string,
|
|
372
|
+
parsedInput.tool as string,
|
|
373
|
+
parsedInput.params as Record<string, unknown>,
|
|
217
374
|
);
|
|
218
375
|
case "auth": {
|
|
219
376
|
const authOpts: {
|
|
@@ -221,26 +378,31 @@ export function createAdkTools<TCtx extends ToolContext = ToolContext>(
|
|
|
221
378
|
credentials?: Record<string, string>;
|
|
222
379
|
stateContext?: Record<string, unknown>;
|
|
223
380
|
} = {};
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
381
|
+
if (parsedInput.apiKey)
|
|
382
|
+
authOpts.apiKey = parsedInput.apiKey as string;
|
|
383
|
+
if (parsedInput.credentials)
|
|
384
|
+
authOpts.credentials = parsedInput.credentials as Record<
|
|
385
|
+
string,
|
|
386
|
+
string
|
|
387
|
+
>;
|
|
227
388
|
if (opts.hooks?.getAuthStateContext) {
|
|
228
389
|
authOpts.stateContext = await opts.hooks.getAuthStateContext(
|
|
390
|
+
parsedInput,
|
|
229
391
|
ctx as TCtx,
|
|
230
392
|
);
|
|
231
393
|
}
|
|
232
|
-
return await adk.ref.auth(
|
|
394
|
+
return await adk.ref.auth(parsedInput.name as string, authOpts);
|
|
233
395
|
}
|
|
234
396
|
case "auth-status":
|
|
235
|
-
return await adk.ref.authStatus(
|
|
397
|
+
return await adk.ref.authStatus(parsedInput.name as string);
|
|
236
398
|
case "refresh-token":
|
|
237
|
-
return await adk.ref.refreshToken(
|
|
399
|
+
return await adk.ref.refreshToken(parsedInput.name as string);
|
|
238
400
|
case "resources":
|
|
239
|
-
return await adk.ref.resources(
|
|
401
|
+
return await adk.ref.resources(parsedInput.name as string);
|
|
240
402
|
case "read":
|
|
241
403
|
return await adk.ref.read(
|
|
242
|
-
|
|
243
|
-
|
|
404
|
+
parsedInput.name as string,
|
|
405
|
+
parsedInput.uris as string[],
|
|
244
406
|
);
|
|
245
407
|
default:
|
|
246
408
|
throw new Error(`Unknown ref operation: ${op}`);
|
package/src/adk.ts
CHANGED
|
@@ -110,7 +110,7 @@ Registry operations:
|
|
|
110
110
|
adk registry auth <name> [--token <t>] [--api-key <k>] [--header <h>]
|
|
111
111
|
|
|
112
112
|
Ref operations:
|
|
113
|
-
adk ref add <ref> [--
|
|
113
|
+
adk ref add <ref> [--name <name>] [--registry <name>] [--url <url>] [--scheme mcp|https|registry]
|
|
114
114
|
adk ref remove <name>
|
|
115
115
|
adk ref list
|
|
116
116
|
adk ref inspect <name> [--full]
|
|
@@ -351,15 +351,14 @@ async function runRef() {
|
|
|
351
351
|
switch (op) {
|
|
352
352
|
case "add": {
|
|
353
353
|
const refArg = args[2];
|
|
354
|
-
if (!refArg) { console.error("Usage: adk ref add <ref> [--
|
|
355
|
-
const
|
|
356
|
-
const
|
|
354
|
+
if (!refArg) { console.error("Usage: adk ref add <ref> [--name <name>] [--registry <name>]"); process.exit(1); }
|
|
355
|
+
const name = getArg("--name") ?? refArg;
|
|
356
|
+
const entry: Record<string, unknown> = { ref: refArg, name };
|
|
357
357
|
const url = getArg("--url");
|
|
358
358
|
const registryName = getArg("--registry");
|
|
359
359
|
// Auto-detect: if no --registry and no --url, try default registry
|
|
360
360
|
const effectiveRegistry = registryName ?? (url ? undefined : "public");
|
|
361
361
|
const scheme = getArg("--scheme") ?? (effectiveRegistry ? "registry" : undefined);
|
|
362
|
-
if (alias) entry.as = alias;
|
|
363
362
|
if (url) entry.url = url;
|
|
364
363
|
if (scheme) entry.scheme = scheme;
|
|
365
364
|
if (effectiveRegistry) {
|
|
@@ -370,15 +369,15 @@ async function runRef() {
|
|
|
370
369
|
}
|
|
371
370
|
try {
|
|
372
371
|
const { security } = await adk.ref.add(entry as import("./define-config.js").RefEntry);
|
|
373
|
-
console.log(`Added ref: ${
|
|
372
|
+
console.log(`Added ref: ${name}`);
|
|
374
373
|
if (security && security.type !== "none") {
|
|
375
374
|
console.log(`\n Auth required: ${security.type}`);
|
|
376
|
-
console.log(` Run: adk ref auth ${
|
|
375
|
+
console.log(` Run: adk ref auth ${name}`);
|
|
377
376
|
}
|
|
378
377
|
|
|
379
378
|
// Materialize local docs
|
|
380
379
|
const configDir = process.env.ADK_CONFIG_DIR ?? join(homedir(), ".adk");
|
|
381
|
-
const refDisplayName =
|
|
380
|
+
const refDisplayName = name;
|
|
382
381
|
try {
|
|
383
382
|
const result = await materializeRef(adk, refDisplayName, configDir);
|
|
384
383
|
if (result.toolCount > 0) {
|
|
@@ -108,9 +108,9 @@ export function createConfigAgent(
|
|
|
108
108
|
type: "string",
|
|
109
109
|
description: 'Agent ref name (e.g. "notion", "linear")',
|
|
110
110
|
},
|
|
111
|
-
|
|
111
|
+
name: {
|
|
112
112
|
type: "string",
|
|
113
|
-
description: "Local
|
|
113
|
+
description: "Local ref name. Defaults to ref when omitted.",
|
|
114
114
|
},
|
|
115
115
|
url: {
|
|
116
116
|
type: "string",
|
|
@@ -132,7 +132,7 @@ export function createConfigAgent(
|
|
|
132
132
|
execute: async (
|
|
133
133
|
input: {
|
|
134
134
|
ref: string;
|
|
135
|
-
|
|
135
|
+
name?: string;
|
|
136
136
|
url?: string;
|
|
137
137
|
config?: Record<string, string>;
|
|
138
138
|
registry?: string;
|
|
@@ -141,28 +141,27 @@ export function createConfigAgent(
|
|
|
141
141
|
) => {
|
|
142
142
|
const fs = getStore(ctx);
|
|
143
143
|
const currentConfig = await readConfig(fs);
|
|
144
|
+
const name = input.name ?? input.ref;
|
|
144
145
|
|
|
145
|
-
const entry
|
|
146
|
+
const entry = {
|
|
146
147
|
ref: input.ref,
|
|
147
|
-
|
|
148
|
+
name,
|
|
148
149
|
...(input.url && { url: input.url }),
|
|
149
150
|
...(input.config && { config: input.config }),
|
|
150
151
|
...(input.registry && { registry: input.registry }),
|
|
151
|
-
};
|
|
152
|
+
} as RefEntry;
|
|
152
153
|
|
|
153
|
-
// Upsert: find existing ref by name/alias, replace or append
|
|
154
|
-
const name = input.as ?? input.ref;
|
|
155
154
|
const refs = currentConfig.refs ?? [];
|
|
156
|
-
const
|
|
155
|
+
const altName = name.startsWith("@") ? name.slice(1) : `@${name}`;
|
|
156
|
+
const duplicate = refs.some((r) => {
|
|
157
157
|
const normalized = normalizeRef(r);
|
|
158
|
-
return normalized.name === name;
|
|
158
|
+
return normalized.name === name || normalized.name === altName;
|
|
159
159
|
});
|
|
160
160
|
|
|
161
|
-
if (
|
|
162
|
-
|
|
163
|
-
} else {
|
|
164
|
-
refs.push(entry);
|
|
161
|
+
if (duplicate) {
|
|
162
|
+
throw new Error(`Cannot add ref "${input.ref}" as "${name}": a ref with that name already exists`);
|
|
165
163
|
}
|
|
164
|
+
refs.push(entry);
|
|
166
165
|
|
|
167
166
|
currentConfig.refs = refs;
|
|
168
167
|
await writeConfig(fs, currentConfig);
|
|
@@ -178,13 +177,13 @@ export function createConfigAgent(
|
|
|
178
177
|
// ---- remove_ref ----
|
|
179
178
|
const removeRefTool = defineTool({
|
|
180
179
|
name: "remove_ref",
|
|
181
|
-
description: "Remove an agent ref from the consumer config by name
|
|
180
|
+
description: "Remove an agent ref from the consumer config by name.",
|
|
182
181
|
inputSchema: {
|
|
183
182
|
type: "object" as const,
|
|
184
183
|
properties: {
|
|
185
184
|
name: {
|
|
186
185
|
type: "string",
|
|
187
|
-
description: "Ref name
|
|
186
|
+
description: "Ref name to remove",
|
|
188
187
|
},
|
|
189
188
|
},
|
|
190
189
|
required: ["name"],
|