@agentforge-io/core 1.0.0 → 2.0.1

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.
@@ -26,9 +26,17 @@ export declare class AgentRunnerService {
26
26
  * - `extras`: a name→definition map so `dispatchTool` can route execution
27
27
  * for tools that aren't in the global registry
28
28
  *
29
- * Extras with the same name as a global tool shadow the global one — useful
30
- * when a connector wants to override the built-in `http_request`, for
31
- * example. The shadowing only lasts for this call.
29
+ * **Connector tools follow the same whitelist as global tools.** An extra
30
+ * is only injected if its name appears in `agent.tools[]`. That keeps
31
+ * "an agent only sees what its definition declares" — a single contract
32
+ * for built-ins, MCP tools, and connector tools alike. Without this
33
+ * filter, any agent run by a user with Gmail/Drive/... connected would
34
+ * silently gain access to those APIs, which is both a security hole and
35
+ * makes curation impossible.
36
+ *
37
+ * Extras with the same name as a global tool shadow the global one —
38
+ * useful when a connector wants to override the built-in `http_request`,
39
+ * for example. The shadowing only lasts for this call.
32
40
  */
33
41
  private buildToolList;
34
42
  private dispatchTool;
@@ -193,17 +193,28 @@ class AgentRunnerService {
193
193
  * - `extras`: a name→definition map so `dispatchTool` can route execution
194
194
  * for tools that aren't in the global registry
195
195
  *
196
- * Extras with the same name as a global tool shadow the global one — useful
197
- * when a connector wants to override the built-in `http_request`, for
198
- * example. The shadowing only lasts for this call.
196
+ * **Connector tools follow the same whitelist as global tools.** An extra
197
+ * is only injected if its name appears in `agent.tools[]`. That keeps
198
+ * "an agent only sees what its definition declares" — a single contract
199
+ * for built-ins, MCP tools, and connector tools alike. Without this
200
+ * filter, any agent run by a user with Gmail/Drive/... connected would
201
+ * silently gain access to those APIs, which is both a security hole and
202
+ * makes curation impossible.
203
+ *
204
+ * Extras with the same name as a global tool shadow the global one —
205
+ * useful when a connector wants to override the built-in `http_request`,
206
+ * for example. The shadowing only lasts for this call.
199
207
  */
200
208
  buildToolList(agent, overrides) {
201
209
  const fromRegistry = agent.tools?.length
202
210
  ? this.toolRegistry.getToolsForAgent(agent.id, agent.tools)
203
211
  : [];
212
+ const allowed = new Set(agent.tools ?? []);
204
213
  const extras = new Map();
205
214
  const extrasSchema = [];
206
215
  for (const t of overrides?.extraTools ?? []) {
216
+ if (!allowed.has(t.name))
217
+ continue;
207
218
  extras.set(t.name, t);
208
219
  extrasSchema.push({
209
220
  name: t.name,
@@ -143,6 +143,23 @@ export declare class ConnectorRegistryService {
143
143
  }>;
144
144
  listForUser(userId: string): Promise<ConnectorStatus[]>;
145
145
  disconnect(userId: string, connectorId: string): Promise<void>;
146
+ /**
147
+ * Returns the full catalog of tool *definitions* across every registered
148
+ * connector, regardless of whether any user has authorized them. Used by
149
+ * the agent-editor UI so an operator can whitelist connector tools per
150
+ * agent the same way they whitelist built-ins — the runner enforces the
151
+ * whitelist via `agent.tools[]`, so listing here doesn't grant access.
152
+ *
153
+ * No tokens are surfaced and no `execute` is returned: this view is
154
+ * deliberately metadata-only.
155
+ */
156
+ availableTools(): Array<{
157
+ name: string;
158
+ description: string;
159
+ connectorId: string;
160
+ connectorName: string;
161
+ inputSchema: unknown;
162
+ }>;
146
163
  /**
147
164
  * Returns the toolbelt for `userId`: one `AgentToolDefinition` per tool
148
165
  * of every connector the user has authorized. Each handler is bound to a
@@ -179,6 +179,32 @@ class ConnectorRegistryService {
179
179
  throw new ConnectorError('not_connected', 'No active auth row');
180
180
  await this.deps.authRepo.delete(a.id);
181
181
  }
182
+ // ─── Catalog (no auth) ───────────────────────────────────────────────────
183
+ /**
184
+ * Returns the full catalog of tool *definitions* across every registered
185
+ * connector, regardless of whether any user has authorized them. Used by
186
+ * the agent-editor UI so an operator can whitelist connector tools per
187
+ * agent the same way they whitelist built-ins — the runner enforces the
188
+ * whitelist via `agent.tools[]`, so listing here doesn't grant access.
189
+ *
190
+ * No tokens are surfaced and no `execute` is returned: this view is
191
+ * deliberately metadata-only.
192
+ */
193
+ availableTools() {
194
+ const out = [];
195
+ for (const def of this.defs.values()) {
196
+ for (const factory of def.tools) {
197
+ out.push({
198
+ name: factory.definition.name,
199
+ description: factory.definition.description,
200
+ connectorId: def.id,
201
+ connectorName: def.name,
202
+ inputSchema: factory.definition.inputSchema,
203
+ });
204
+ }
205
+ }
206
+ return out;
207
+ }
182
208
  // ─── Per-user tool synthesis ─────────────────────────────────────────────
183
209
  /**
184
210
  * Returns the toolbelt for `userId`: one `AgentToolDefinition` per tool
@@ -1,4 +1,4 @@
1
- export { ToolRegistryService, type Logger } from './tool-registry.service';
1
+ export { ToolRegistryService, type Logger, type ToolDescription, } from './tool-registry.service';
2
2
  export { AgentRunnerService } from './agent-runner.service';
3
3
  export { PreparedStreamService, PreparedStreamError, } from './prepared-stream.service';
4
4
  export { InMemoryPreparedStreamStore } from './in-memory-prepared-stream.store';
@@ -39,4 +39,13 @@ export interface ToolDescription {
39
39
  description: string;
40
40
  inputSchema: Record<string, unknown>;
41
41
  agents?: string[];
42
+ /**
43
+ * Set when this tool comes from an OAuth connector (Gmail, Drive, …)
44
+ * rather than the global built-in registry. The UI groups the picker
45
+ * by this id so operators can see at a glance which provider each
46
+ * tool belongs to. Built-in tools leave this undefined.
47
+ */
48
+ connectorId?: string;
49
+ /** Human-readable connector label paired with `connectorId`. */
50
+ connectorName?: string;
42
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge-io/core",
3
- "version": "1.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Framework-free AI runtime SDK. Owns: agent loop (Anthropic), conversations, tools, streaming, agent-job queue, SdkHooks. Identity, billing, infra (email/uploads/secrets) live in the host's modules — not here.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",