@slashfi/agents-sdk 0.5.0 → 0.7.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/agent-definitions/auth.d.ts.map +1 -1
- package/dist/agent-definitions/auth.js +16 -3
- package/dist/agent-definitions/auth.js.map +1 -1
- package/dist/agent-definitions/integrations.d.ts +162 -0
- package/dist/agent-definitions/integrations.d.ts.map +1 -0
- package/dist/agent-definitions/integrations.js +861 -0
- package/dist/agent-definitions/integrations.js.map +1 -0
- package/dist/agent-definitions/secrets.d.ts +26 -3
- package/dist/agent-definitions/secrets.d.ts.map +1 -1
- package/dist/agent-definitions/secrets.js +34 -28
- package/dist/agent-definitions/secrets.js.map +1 -1
- package/dist/agent-definitions/users.d.ts +80 -0
- package/dist/agent-definitions/users.d.ts.map +1 -0
- package/dist/agent-definitions/users.js +397 -0
- package/dist/agent-definitions/users.js.map +1 -0
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js.map +1 -1
- package/dist/define.d.ts +6 -1
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +1 -0
- package/dist/define.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/jwt.d.ts.map +1 -1
- package/dist/jwt.js.map +1 -1
- package/dist/server.d.ts +28 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +477 -26
- package/dist/server.js.map +1 -1
- package/dist/slack-oauth.d.ts +27 -0
- package/dist/slack-oauth.d.ts.map +1 -0
- package/dist/slack-oauth.js +48 -0
- package/dist/slack-oauth.js.map +1 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/web-pages.d.ts +8 -0
- package/dist/web-pages.d.ts.map +1 -0
- package/dist/web-pages.js +169 -0
- package/dist/web-pages.js.map +1 -0
- package/package.json +2 -1
- package/src/agent-definitions/auth.ts +37 -14
- package/src/agent-definitions/integrations.ts +1209 -0
- package/src/agent-definitions/secrets.ts +85 -36
- package/src/agent-definitions/users.ts +533 -0
- package/src/crypto.ts +3 -1
- package/src/define.ts +8 -0
- package/src/index.ts +57 -3
- package/src/jwt.ts +7 -5
- package/src/server.ts +565 -33
- package/src/slack-oauth.ts +66 -0
- package/src/types.ts +83 -0
- package/src/web-pages.ts +178 -0
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - AES-256-GCM encryption via crypto.ts
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { decryptSecret, encryptSecret } from "../crypto.js";
|
|
12
12
|
import { defineAgent, defineTool } from "../define.js";
|
|
13
13
|
import type { AgentDefinition, ToolContext, ToolDefinition } from "../types.js";
|
|
14
14
|
|
|
@@ -20,13 +20,42 @@ import type { AgentDefinition, ToolContext, ToolDefinition } from "../types.js";
|
|
|
20
20
|
* Pluggable secret storage backend.
|
|
21
21
|
* Stores encrypted values, resolves refs.
|
|
22
22
|
*/
|
|
23
|
+
/**
|
|
24
|
+
* Scope for multi-tenant secret isolation.
|
|
25
|
+
* When provided, secrets are partitioned by tenant/instance.
|
|
26
|
+
*/
|
|
27
|
+
export interface SecretScope {
|
|
28
|
+
tenantId: string;
|
|
29
|
+
instanceKey?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
export interface SecretStore {
|
|
24
33
|
/** Store a secret. Returns the secret ID (without prefix). */
|
|
25
|
-
store(value: string, ownerId: string): Promise<string>;
|
|
34
|
+
store(value: string, ownerId: string, scope?: SecretScope): Promise<string>;
|
|
35
|
+
|
|
26
36
|
/** Resolve a secret ID to its decrypted value. */
|
|
27
|
-
resolve(id: string, ownerId: string): Promise<string | null>;
|
|
37
|
+
resolve(id: string, ownerId: string, scope?: SecretScope): Promise<string | null>;
|
|
38
|
+
|
|
28
39
|
/** Delete a secret. */
|
|
29
|
-
delete(id: string, ownerId: string): Promise<boolean>;
|
|
40
|
+
delete(id: string, ownerId: string, scope?: SecretScope): Promise<boolean>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Store multiple secrets in a single operation.
|
|
44
|
+
* Returns an array of secret IDs in the same order as the input values.
|
|
45
|
+
*/
|
|
46
|
+
storeBatch?(values: string[], ownerId: string, scope?: SecretScope): Promise<string[]>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Associate a secret with an entity (e.g., a provider config, a connection).
|
|
50
|
+
* Enables lookup of secrets by entity rather than by ID.
|
|
51
|
+
*/
|
|
52
|
+
associate?(secretId: string, entityType: string, entityId: string, scope?: SecretScope): Promise<void>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Resolve secrets associated with an entity.
|
|
56
|
+
* Returns all secret IDs linked to the given entity.
|
|
57
|
+
*/
|
|
58
|
+
resolveByEntity?(entityType: string, entityId: string, scope?: SecretScope): Promise<string[]>;
|
|
30
59
|
}
|
|
31
60
|
|
|
32
61
|
// ============================================
|
|
@@ -50,7 +79,8 @@ export function makeSecretRef(id: string): string {
|
|
|
50
79
|
function randomSecretId(): string {
|
|
51
80
|
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
52
81
|
let id = "";
|
|
53
|
-
for (let i = 0; i < 24; i++)
|
|
82
|
+
for (let i = 0; i < 24; i++)
|
|
83
|
+
id += chars[Math.floor(Math.random() * chars.length)];
|
|
54
84
|
return id;
|
|
55
85
|
}
|
|
56
86
|
|
|
@@ -60,27 +90,53 @@ function randomSecretId(): string {
|
|
|
60
90
|
|
|
61
91
|
export function createInMemorySecretStore(encryptionKey: string): SecretStore {
|
|
62
92
|
const secrets = new Map<string, { encrypted: string; ownerId: string }>();
|
|
93
|
+
const associations = new Map<string, string[]>(); // "entityType:entityId" -> secretIds
|
|
63
94
|
|
|
64
95
|
return {
|
|
65
|
-
async store(value, ownerId) {
|
|
96
|
+
async store(value, ownerId, _scope?) {
|
|
66
97
|
const id = randomSecretId();
|
|
67
98
|
const encrypted = await encryptSecret(value, encryptionKey);
|
|
68
99
|
secrets.set(id, { encrypted, ownerId });
|
|
69
100
|
return id;
|
|
70
101
|
},
|
|
71
102
|
|
|
72
|
-
async resolve(id, ownerId) {
|
|
103
|
+
async resolve(id, ownerId, _scope?) {
|
|
73
104
|
const entry = secrets.get(id);
|
|
74
105
|
if (!entry || entry.ownerId !== ownerId) return null;
|
|
75
106
|
return decryptSecret(entry.encrypted, encryptionKey);
|
|
76
107
|
},
|
|
77
108
|
|
|
78
|
-
async delete(id, ownerId) {
|
|
109
|
+
async delete(id, ownerId, _scope?) {
|
|
79
110
|
const entry = secrets.get(id);
|
|
80
111
|
if (!entry || entry.ownerId !== ownerId) return false;
|
|
81
112
|
secrets.delete(id);
|
|
82
113
|
return true;
|
|
83
114
|
},
|
|
115
|
+
|
|
116
|
+
async storeBatch(values, ownerId, _scope?) {
|
|
117
|
+
const ids: string[] = [];
|
|
118
|
+
for (const value of values) {
|
|
119
|
+
const id = randomSecretId();
|
|
120
|
+
const encrypted = await encryptSecret(value, encryptionKey);
|
|
121
|
+
secrets.set(id, { encrypted, ownerId });
|
|
122
|
+
ids.push(id);
|
|
123
|
+
}
|
|
124
|
+
return ids;
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
async associate(secretId, entityType, entityId, _scope?) {
|
|
128
|
+
const key = `${entityType}:${entityId}`;
|
|
129
|
+
const existing = associations.get(key) ?? [];
|
|
130
|
+
if (!existing.includes(secretId)) {
|
|
131
|
+
existing.push(secretId);
|
|
132
|
+
associations.set(key, existing);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
async resolveByEntity(entityType, entityId, _scope?) {
|
|
137
|
+
const key = `${entityType}:${entityId}`;
|
|
138
|
+
return associations.get(key) ?? [];
|
|
139
|
+
},
|
|
84
140
|
};
|
|
85
141
|
}
|
|
86
142
|
|
|
@@ -104,7 +160,8 @@ export function createSecretsAgent(
|
|
|
104
160
|
|
|
105
161
|
const storeSecretTool = defineTool({
|
|
106
162
|
name: "store",
|
|
107
|
-
description:
|
|
163
|
+
description:
|
|
164
|
+
"Store secret values. Returns secret:<id> refs for each value.",
|
|
108
165
|
visibility: "internal" as const,
|
|
109
166
|
inputSchema: {
|
|
110
167
|
type: "object" as const,
|
|
@@ -117,7 +174,10 @@ export function createSecretsAgent(
|
|
|
117
174
|
},
|
|
118
175
|
required: ["secrets"],
|
|
119
176
|
},
|
|
120
|
-
execute: async (
|
|
177
|
+
execute: async (
|
|
178
|
+
input: { secrets: Record<string, string> },
|
|
179
|
+
ctx: ToolContext,
|
|
180
|
+
) => {
|
|
121
181
|
const ownerId = ctx.callerId ?? "anonymous";
|
|
122
182
|
const refs: Record<string, string> = {};
|
|
123
183
|
for (const [key, value] of Object.entries(input.secrets)) {
|
|
@@ -130,27 +190,6 @@ export function createSecretsAgent(
|
|
|
130
190
|
},
|
|
131
191
|
});
|
|
132
192
|
|
|
133
|
-
const resolveSecretTool = defineTool({
|
|
134
|
-
name: "resolve",
|
|
135
|
-
description: "Resolve a secret ref to its value. Only accessible to the owner.",
|
|
136
|
-
visibility: "internal" as const,
|
|
137
|
-
inputSchema: {
|
|
138
|
-
type: "object" as const,
|
|
139
|
-
properties: {
|
|
140
|
-
ref: { type: "string" as const, description: "Secret ref (secret:xxx)" },
|
|
141
|
-
},
|
|
142
|
-
required: ["ref"],
|
|
143
|
-
},
|
|
144
|
-
execute: async (input: { ref: string }, ctx: ToolContext) => {
|
|
145
|
-
const ownerId = ctx.callerId ?? "anonymous";
|
|
146
|
-
const id = getSecretId(input.ref);
|
|
147
|
-
const value = await store.resolve(id, ownerId);
|
|
148
|
-
if (!value) throw new Error("Secret not found or unauthorized");
|
|
149
|
-
// Return wrapped so actor can handle it
|
|
150
|
-
return { value: { $agent_type: "secret", value } };
|
|
151
|
-
},
|
|
152
|
-
});
|
|
153
|
-
|
|
154
193
|
const revokeSecretTool = defineTool({
|
|
155
194
|
name: "revoke",
|
|
156
195
|
description: "Delete a stored secret.",
|
|
@@ -172,13 +211,17 @@ export function createSecretsAgent(
|
|
|
172
211
|
|
|
173
212
|
return defineAgent({
|
|
174
213
|
path: "@secrets",
|
|
175
|
-
entrypoint:
|
|
214
|
+
entrypoint:
|
|
215
|
+
"Secret storage agent. Stores, resolves, and manages encrypted secrets.",
|
|
176
216
|
config: {
|
|
177
217
|
name: "Secrets",
|
|
178
218
|
description: "Encrypted secret storage and management",
|
|
179
219
|
visibility: "internal",
|
|
180
220
|
},
|
|
181
|
-
tools: [
|
|
221
|
+
tools: [
|
|
222
|
+
storeSecretTool,
|
|
223
|
+
revokeSecretTool,
|
|
224
|
+
] as ToolDefinition<ToolContext>[],
|
|
182
225
|
});
|
|
183
226
|
}
|
|
184
227
|
|
|
@@ -200,7 +243,10 @@ export async function processSecretParams(
|
|
|
200
243
|
schema: { properties?: Record<string, SchemaProperty> } | undefined,
|
|
201
244
|
secretStore: SecretStore,
|
|
202
245
|
ownerId: string,
|
|
203
|
-
): Promise<{
|
|
246
|
+
): Promise<{
|
|
247
|
+
resolved: Record<string, unknown>;
|
|
248
|
+
redacted: Record<string, unknown>;
|
|
249
|
+
}> {
|
|
204
250
|
const resolved: Record<string, unknown> = { ...params };
|
|
205
251
|
const redacted: Record<string, unknown> = { ...params };
|
|
206
252
|
|
|
@@ -210,7 +256,11 @@ export async function processSecretParams(
|
|
|
210
256
|
const value = params[key];
|
|
211
257
|
if (value === undefined || value === null) continue;
|
|
212
258
|
|
|
213
|
-
if (
|
|
259
|
+
if (
|
|
260
|
+
schemaProp.type === "object" &&
|
|
261
|
+
typeof value === "object" &&
|
|
262
|
+
!Array.isArray(value)
|
|
263
|
+
) {
|
|
214
264
|
const nested = await processSecretParams(
|
|
215
265
|
value as Record<string, unknown>,
|
|
216
266
|
schemaProp,
|
|
@@ -239,7 +289,6 @@ export async function processSecretParams(
|
|
|
239
289
|
const id = await secretStore.store(value, ownerId);
|
|
240
290
|
resolved[key] = value;
|
|
241
291
|
redacted[key] = makeSecretRef(id);
|
|
242
|
-
continue;
|
|
243
292
|
}
|
|
244
293
|
}
|
|
245
294
|
|