@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.
Files changed (54) hide show
  1. package/dist/agent-definitions/auth.d.ts.map +1 -1
  2. package/dist/agent-definitions/auth.js +16 -3
  3. package/dist/agent-definitions/auth.js.map +1 -1
  4. package/dist/agent-definitions/integrations.d.ts +162 -0
  5. package/dist/agent-definitions/integrations.d.ts.map +1 -0
  6. package/dist/agent-definitions/integrations.js +861 -0
  7. package/dist/agent-definitions/integrations.js.map +1 -0
  8. package/dist/agent-definitions/secrets.d.ts +26 -3
  9. package/dist/agent-definitions/secrets.d.ts.map +1 -1
  10. package/dist/agent-definitions/secrets.js +34 -28
  11. package/dist/agent-definitions/secrets.js.map +1 -1
  12. package/dist/agent-definitions/users.d.ts +80 -0
  13. package/dist/agent-definitions/users.d.ts.map +1 -0
  14. package/dist/agent-definitions/users.js +397 -0
  15. package/dist/agent-definitions/users.js.map +1 -0
  16. package/dist/crypto.d.ts.map +1 -1
  17. package/dist/crypto.js.map +1 -1
  18. package/dist/define.d.ts +6 -1
  19. package/dist/define.d.ts.map +1 -1
  20. package/dist/define.js +1 -0
  21. package/dist/define.js.map +1 -1
  22. package/dist/index.d.ts +8 -4
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +6 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/jwt.d.ts.map +1 -1
  27. package/dist/jwt.js.map +1 -1
  28. package/dist/server.d.ts +28 -1
  29. package/dist/server.d.ts.map +1 -1
  30. package/dist/server.js +477 -26
  31. package/dist/server.js.map +1 -1
  32. package/dist/slack-oauth.d.ts +27 -0
  33. package/dist/slack-oauth.d.ts.map +1 -0
  34. package/dist/slack-oauth.js +48 -0
  35. package/dist/slack-oauth.js.map +1 -0
  36. package/dist/types.d.ts +66 -0
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/web-pages.d.ts +8 -0
  39. package/dist/web-pages.d.ts.map +1 -0
  40. package/dist/web-pages.js +169 -0
  41. package/dist/web-pages.js.map +1 -0
  42. package/package.json +2 -1
  43. package/src/agent-definitions/auth.ts +37 -14
  44. package/src/agent-definitions/integrations.ts +1209 -0
  45. package/src/agent-definitions/secrets.ts +85 -36
  46. package/src/agent-definitions/users.ts +533 -0
  47. package/src/crypto.ts +3 -1
  48. package/src/define.ts +8 -0
  49. package/src/index.ts +57 -3
  50. package/src/jwt.ts +7 -5
  51. package/src/server.ts +565 -33
  52. package/src/slack-oauth.ts +66 -0
  53. package/src/types.ts +83 -0
  54. 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 { encryptSecret, decryptSecret } from "../crypto.js";
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++) id += chars[Math.floor(Math.random() * chars.length)];
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: "Store secret values. Returns secret:<id> refs for each value.",
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 (input: { secrets: Record<string, string> }, ctx: ToolContext) => {
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: "Secret storage agent. Stores, resolves, and manages encrypted secrets.",
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: [storeSecretTool, resolveSecretTool, revokeSecretTool] as ToolDefinition<ToolContext>[],
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<{ resolved: Record<string, unknown>; redacted: Record<string, unknown> }> {
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 (schemaProp.type === "object" && typeof value === "object" && !Array.isArray(value)) {
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