@slashfi/agents-sdk 0.4.0 → 0.6.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 (65) hide show
  1. package/dist/{auth.d.ts → agent-definitions/auth.d.ts} +36 -2
  2. package/dist/agent-definitions/auth.d.ts.map +1 -0
  3. package/dist/{auth.js → agent-definitions/auth.js} +69 -8
  4. package/dist/agent-definitions/auth.js.map +1 -0
  5. package/dist/agent-definitions/integrations.d.ts +162 -0
  6. package/dist/agent-definitions/integrations.d.ts.map +1 -0
  7. package/dist/agent-definitions/integrations.js +861 -0
  8. package/dist/agent-definitions/integrations.js.map +1 -0
  9. package/dist/agent-definitions/secrets.d.ts +51 -0
  10. package/dist/agent-definitions/secrets.d.ts.map +1 -0
  11. package/dist/agent-definitions/secrets.js +165 -0
  12. package/dist/agent-definitions/secrets.js.map +1 -0
  13. package/dist/agent-definitions/users.d.ts +80 -0
  14. package/dist/agent-definitions/users.d.ts.map +1 -0
  15. package/dist/agent-definitions/users.js +397 -0
  16. package/dist/agent-definitions/users.js.map +1 -0
  17. package/dist/crypto.d.ts +14 -0
  18. package/dist/crypto.d.ts.map +1 -0
  19. package/dist/crypto.js +40 -0
  20. package/dist/crypto.js.map +1 -0
  21. package/dist/define.d.ts +6 -1
  22. package/dist/define.d.ts.map +1 -1
  23. package/dist/define.js +1 -0
  24. package/dist/define.js.map +1 -1
  25. package/dist/index.d.ts +10 -5
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +9 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/jwt.d.ts +2 -0
  30. package/dist/jwt.d.ts.map +1 -1
  31. package/dist/jwt.js.map +1 -1
  32. package/dist/server.d.ts +28 -1
  33. package/dist/server.d.ts.map +1 -1
  34. package/dist/server.js +478 -27
  35. package/dist/server.js.map +1 -1
  36. package/dist/slack-oauth.d.ts +27 -0
  37. package/dist/slack-oauth.d.ts.map +1 -0
  38. package/dist/slack-oauth.js +48 -0
  39. package/dist/slack-oauth.js.map +1 -0
  40. package/dist/types.d.ts +66 -0
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/web-pages.d.ts +8 -0
  43. package/dist/web-pages.d.ts.map +1 -0
  44. package/dist/web-pages.js +169 -0
  45. package/dist/web-pages.js.map +1 -0
  46. package/package.json +2 -1
  47. package/src/{auth.ts → agent-definitions/auth.ts} +134 -15
  48. package/src/agent-definitions/integrations.ts +1209 -0
  49. package/src/agent-definitions/secrets.ts +241 -0
  50. package/src/agent-definitions/users.ts +533 -0
  51. package/src/crypto.ts +71 -0
  52. package/src/define.ts +8 -0
  53. package/src/index.ts +62 -4
  54. package/src/jwt.ts +9 -5
  55. package/src/server.ts +567 -35
  56. package/src/slack-oauth.ts +66 -0
  57. package/src/types.ts +83 -0
  58. package/src/web-pages.ts +178 -0
  59. package/dist/auth.d.ts.map +0 -1
  60. package/dist/auth.js.map +0 -1
  61. package/dist/secrets.d.ts +0 -44
  62. package/dist/secrets.d.ts.map +0 -1
  63. package/dist/secrets.js +0 -106
  64. package/dist/secrets.js.map +0 -1
  65. package/src/secrets.ts +0 -154
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Secrets - encrypted secret storage and resolution for tool params.
3
+ *
4
+ * Provides:
5
+ * - SecretStore interface for pluggable storage backends
6
+ * - createSecretsAgent: built-in @secrets agent with store/resolve tools
7
+ * - processSecretParams: auto-resolve secret:xxx refs in tool params
8
+ * - AES-256-GCM encryption via crypto.ts
9
+ */
10
+
11
+ import { decryptSecret, encryptSecret } from "../crypto.js";
12
+ import { defineAgent, defineTool } from "../define.js";
13
+ import type { AgentDefinition, ToolContext, ToolDefinition } from "../types.js";
14
+
15
+ // ============================================
16
+ // SecretStore Interface
17
+ // ============================================
18
+
19
+ /**
20
+ * Pluggable secret storage backend.
21
+ * Stores encrypted values, resolves refs.
22
+ */
23
+ export interface SecretStore {
24
+ /** Store a secret. Returns the secret ID (without prefix). */
25
+ store(value: string, ownerId: string): Promise<string>;
26
+ /** Resolve a secret ID to its decrypted value. */
27
+ resolve(id: string, ownerId: string): Promise<string | null>;
28
+ /** Delete a secret. */
29
+ delete(id: string, ownerId: string): Promise<boolean>;
30
+ }
31
+
32
+ // ============================================
33
+ // Secret Ref Helpers
34
+ // ============================================
35
+
36
+ const SECRET_PREFIX = "secret:";
37
+
38
+ export function isSecretRef(value: unknown): value is string {
39
+ return typeof value === "string" && value.startsWith(SECRET_PREFIX);
40
+ }
41
+
42
+ export function getSecretId(ref: string): string {
43
+ return ref.slice(SECRET_PREFIX.length);
44
+ }
45
+
46
+ export function makeSecretRef(id: string): string {
47
+ return `${SECRET_PREFIX}${id}`;
48
+ }
49
+
50
+ function randomSecretId(): string {
51
+ const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
52
+ let id = "";
53
+ for (let i = 0; i < 24; i++)
54
+ id += chars[Math.floor(Math.random() * chars.length)];
55
+ return id;
56
+ }
57
+
58
+ // ============================================
59
+ // In-Memory SecretStore (default)
60
+ // ============================================
61
+
62
+ export function createInMemorySecretStore(encryptionKey: string): SecretStore {
63
+ const secrets = new Map<string, { encrypted: string; ownerId: string }>();
64
+
65
+ return {
66
+ async store(value, ownerId) {
67
+ const id = randomSecretId();
68
+ const encrypted = await encryptSecret(value, encryptionKey);
69
+ secrets.set(id, { encrypted, ownerId });
70
+ return id;
71
+ },
72
+
73
+ async resolve(id, ownerId) {
74
+ const entry = secrets.get(id);
75
+ if (!entry || entry.ownerId !== ownerId) return null;
76
+ return decryptSecret(entry.encrypted, encryptionKey);
77
+ },
78
+
79
+ async delete(id, ownerId) {
80
+ const entry = secrets.get(id);
81
+ if (!entry || entry.ownerId !== ownerId) return false;
82
+ secrets.delete(id);
83
+ return true;
84
+ },
85
+ };
86
+ }
87
+
88
+ // ============================================
89
+ // createSecretsAgent
90
+ // ============================================
91
+
92
+ export interface SecretsAgentOptions {
93
+ /** Secret store backend */
94
+ store: SecretStore;
95
+ }
96
+
97
+ /**
98
+ * Create the built-in @secrets agent.
99
+ * Provides tools for storing and resolving secrets via MCP.
100
+ */
101
+ export function createSecretsAgent(
102
+ options: SecretsAgentOptions,
103
+ ): AgentDefinition {
104
+ const { store } = options;
105
+
106
+ const storeSecretTool = defineTool({
107
+ name: "store",
108
+ description:
109
+ "Store secret values. Returns secret:<id> refs for each value.",
110
+ visibility: "internal" as const,
111
+ inputSchema: {
112
+ type: "object" as const,
113
+ properties: {
114
+ secrets: {
115
+ type: "object" as const,
116
+ description: "Key-value pairs to store as secrets",
117
+ additionalProperties: { type: "string" },
118
+ },
119
+ },
120
+ required: ["secrets"],
121
+ },
122
+ execute: async (
123
+ input: { secrets: Record<string, string> },
124
+ ctx: ToolContext,
125
+ ) => {
126
+ const ownerId = ctx.callerId ?? "anonymous";
127
+ const refs: Record<string, string> = {};
128
+ for (const [key, value] of Object.entries(input.secrets)) {
129
+ if (typeof value === "string" && value.length > 0) {
130
+ const id = await store.store(value, ownerId);
131
+ refs[key] = makeSecretRef(id);
132
+ }
133
+ }
134
+ return { refs };
135
+ },
136
+ });
137
+
138
+ const revokeSecretTool = defineTool({
139
+ name: "revoke",
140
+ description: "Delete a stored secret.",
141
+ visibility: "internal" as const,
142
+ inputSchema: {
143
+ type: "object" as const,
144
+ properties: {
145
+ ref: { type: "string" as const, description: "Secret ref to revoke" },
146
+ },
147
+ required: ["ref"],
148
+ },
149
+ execute: async (input: { ref: string }, ctx: ToolContext) => {
150
+ const ownerId = ctx.callerId ?? "anonymous";
151
+ const id = getSecretId(input.ref);
152
+ const deleted = await store.delete(id, ownerId);
153
+ return { deleted };
154
+ },
155
+ });
156
+
157
+ return defineAgent({
158
+ path: "@secrets",
159
+ entrypoint:
160
+ "Secret storage agent. Stores, resolves, and manages encrypted secrets.",
161
+ config: {
162
+ name: "Secrets",
163
+ description: "Encrypted secret storage and management",
164
+ visibility: "internal",
165
+ },
166
+ tools: [
167
+ storeSecretTool,
168
+ revokeSecretTool,
169
+ ] as ToolDefinition<ToolContext>[],
170
+ });
171
+ }
172
+
173
+ // ============================================
174
+ // Param Resolution (used by server)
175
+ // ============================================
176
+
177
+ interface SchemaProperty {
178
+ type?: string;
179
+ secret?: boolean;
180
+ properties?: Record<string, SchemaProperty>;
181
+ }
182
+
183
+ /**
184
+ * Process tool params: resolve secret:xxx refs and store raw secret values.
185
+ */
186
+ export async function processSecretParams(
187
+ params: Record<string, unknown>,
188
+ schema: { properties?: Record<string, SchemaProperty> } | undefined,
189
+ secretStore: SecretStore,
190
+ ownerId: string,
191
+ ): Promise<{
192
+ resolved: Record<string, unknown>;
193
+ redacted: Record<string, unknown>;
194
+ }> {
195
+ const resolved: Record<string, unknown> = { ...params };
196
+ const redacted: Record<string, unknown> = { ...params };
197
+
198
+ if (!schema?.properties) return { resolved, redacted };
199
+
200
+ for (const [key, schemaProp] of Object.entries(schema.properties)) {
201
+ const value = params[key];
202
+ if (value === undefined || value === null) continue;
203
+
204
+ if (
205
+ schemaProp.type === "object" &&
206
+ typeof value === "object" &&
207
+ !Array.isArray(value)
208
+ ) {
209
+ const nested = await processSecretParams(
210
+ value as Record<string, unknown>,
211
+ schemaProp,
212
+ secretStore,
213
+ ownerId,
214
+ );
215
+ resolved[key] = nested.resolved;
216
+ redacted[key] = nested.redacted;
217
+ continue;
218
+ }
219
+
220
+ if (typeof value !== "string") continue;
221
+
222
+ // Resolve secret refs
223
+ if (isSecretRef(value)) {
224
+ const id = getSecretId(value);
225
+ const realValue = await secretStore.resolve(id, ownerId);
226
+ if (realValue === null) throw new Error(`Secret not found: ${value}`);
227
+ resolved[key] = realValue;
228
+ redacted[key] = value;
229
+ continue;
230
+ }
231
+
232
+ // Auto-store raw values in secret: true fields
233
+ if (schemaProp.secret && (value as string).length > 0) {
234
+ const id = await secretStore.store(value, ownerId);
235
+ resolved[key] = value;
236
+ redacted[key] = makeSecretRef(id);
237
+ }
238
+ }
239
+
240
+ return { resolved, redacted };
241
+ }