substrai-lambdallm 1.0.0 → 1.2.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 (86) hide show
  1. package/README.md +64 -24
  2. package/dist/agents/agent.d.ts +57 -0
  3. package/dist/agents/agent.d.ts.map +1 -0
  4. package/dist/agents/agent.js +93 -0
  5. package/dist/agents/agent.js.map +1 -0
  6. package/dist/agents/extras.d.ts +59 -0
  7. package/dist/agents/extras.d.ts.map +1 -0
  8. package/dist/agents/extras.js +152 -0
  9. package/dist/agents/extras.js.map +1 -0
  10. package/dist/chains/chain.d.ts +51 -0
  11. package/dist/chains/chain.d.ts.map +1 -0
  12. package/dist/chains/chain.js +103 -0
  13. package/dist/chains/chain.js.map +1 -0
  14. package/dist/core/context.d.ts +34 -0
  15. package/dist/core/context.d.ts.map +1 -0
  16. package/dist/core/context.js +186 -0
  17. package/dist/core/context.js.map +1 -0
  18. package/dist/core/exceptions.d.ts +20 -0
  19. package/dist/core/exceptions.d.ts.map +1 -0
  20. package/dist/core/exceptions.js +43 -0
  21. package/dist/core/exceptions.js.map +1 -0
  22. package/dist/core/handler.d.ts +37 -0
  23. package/dist/core/handler.d.ts.map +1 -0
  24. package/dist/core/handler.js +74 -0
  25. package/dist/core/handler.js.map +1 -0
  26. package/dist/core/models.d.ts +34 -0
  27. package/dist/core/models.d.ts.map +1 -0
  28. package/dist/core/models.js +33 -0
  29. package/dist/core/models.js.map +1 -0
  30. package/dist/core/prompt.d.ts +29 -0
  31. package/dist/core/prompt.d.ts.map +1 -0
  32. package/dist/core/prompt.js +50 -0
  33. package/dist/core/prompt.js.map +1 -0
  34. package/dist/index.d.ts +25 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +71 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/middleware/base.d.ts +10 -0
  39. package/dist/middleware/base.d.ts.map +1 -0
  40. package/dist/middleware/base.js +17 -0
  41. package/dist/middleware/base.js.map +1 -0
  42. package/dist/middleware/logging.d.ts +25 -0
  43. package/dist/middleware/logging.d.ts.map +1 -0
  44. package/dist/middleware/logging.js +62 -0
  45. package/dist/middleware/logging.js.map +1 -0
  46. package/dist/observability/index.d.ts +138 -0
  47. package/dist/observability/index.d.ts.map +1 -0
  48. package/dist/observability/index.js +221 -0
  49. package/dist/observability/index.js.map +1 -0
  50. package/dist/state/contextWindow.d.ts +24 -0
  51. package/dist/state/contextWindow.d.ts.map +1 -0
  52. package/dist/state/contextWindow.js +70 -0
  53. package/dist/state/contextWindow.js.map +1 -0
  54. package/dist/state/session.d.ts +40 -0
  55. package/dist/state/session.d.ts.map +1 -0
  56. package/dist/state/session.js +52 -0
  57. package/dist/state/session.js.map +1 -0
  58. package/dist/state/store.d.ts +28 -0
  59. package/dist/state/store.d.ts.map +1 -0
  60. package/dist/state/store.js +97 -0
  61. package/dist/state/store.js.map +1 -0
  62. package/dist/testing/index.d.ts +48 -0
  63. package/dist/testing/index.d.ts.map +1 -0
  64. package/dist/testing/index.js +92 -0
  65. package/dist/testing/index.js.map +1 -0
  66. package/jest.config.js +6 -0
  67. package/package.json +26 -10
  68. package/src/agents/agent.ts +137 -0
  69. package/src/agents/extras.ts +185 -0
  70. package/src/chains/chain.ts +145 -0
  71. package/src/core/context.ts +211 -0
  72. package/src/core/exceptions.ts +41 -0
  73. package/src/core/handler.ts +95 -0
  74. package/src/core/models.ts +47 -0
  75. package/src/core/prompt.ts +71 -0
  76. package/src/index.ts +39 -0
  77. package/src/middleware/base.ts +17 -0
  78. package/src/middleware/logging.ts +69 -0
  79. package/src/observability/index.ts +261 -0
  80. package/src/state/contextWindow.ts +76 -0
  81. package/src/state/session.ts +73 -0
  82. package/src/state/store.ts +98 -0
  83. package/src/testing/index.ts +114 -0
  84. package/tsconfig.json +27 -0
  85. package/index.d.ts +0 -24
  86. package/index.js +0 -57
package/README.md CHANGED
@@ -1,41 +1,83 @@
1
1
  # substrai-lambdallm
2
2
 
3
- **Serverless-native LLM orchestration framework for AWS Lambda.**
3
+ **Serverless-native LLM orchestration framework for AWS Lambda (TypeScript)**
4
4
 
5
- [![PyPI](https://badge.fury.io/py/substrai-lambdallm.svg)](https://pypi.org/project/substrai-lambdallm/)
5
+ [![npm](https://badge.fury.io/js/substrai-lambdallm.svg)](https://www.npmjs.com/package/substrai-lambdallm)
6
6
  [![GitHub](https://img.shields.io/github/stars/substrai/lambdallm)](https://github.com/substrai/lambdallm)
7
- [![Docs](https://img.shields.io/badge/docs-substrai.github.io-blue)](https://substrai.github.io/lambdallm)
8
7
 
9
- > **Note:** The primary implementation is in Python. TypeScript SDK coming soon.
10
-
11
- ## Install (Python)
8
+ ## Install
12
9
 
13
10
  ```bash
14
- pip install substrai-lambdallm[bedrock]
11
+ npm install substrai-lambdallm @aws-sdk/client-bedrock-runtime
15
12
  ```
16
13
 
17
14
  ## Quick Start
18
15
 
19
- ```python
20
- from lambdallm import handler, Prompt, Model
16
+ ```typescript
17
+ import { handler, Model } from 'substrai-lambdallm';
21
18
 
22
- @handler(model=Model.CLAUDE_3_HAIKU)
23
- def lambda_handler(event, context):
24
- result = context.invoke("Summarize: {text}", text=event["body"]["text"])
25
- return {"statusCode": 200, "body": result}
19
+ export const lambdaHandler = handler(
20
+ { model: Model.CLAUDE_3_HAIKU, maxRetries: 3 },
21
+ async (event, context) => {
22
+ const result = await context.invoke('Summarize: {text}', { text: event.body.text });
23
+ return { statusCode: 200, body: { result, cost: context.totalCost } };
24
+ }
25
+ );
26
26
  ```
27
27
 
28
28
  ## Features
29
29
 
30
- - < 5MB package (vs 400MB+ for LangChain)
31
- - Cold-start optimized (lazy imports, connection pooling)
32
- - DynamoDB-native state (conversation memory persists)
33
- - Multi-step chains with checkpoint/resume
34
- - AI Agents with tool sandboxing
35
- - Cost-aware model routing
36
- - One-command deploy
37
- - A/B testing for prompts
38
- - Full observability (X-Ray + CloudWatch)
30
+ - **< 50KB** package size
31
+ - **TypeScript-first** with full type safety
32
+ - **Bedrock provider** (Claude, Titan, Llama)
33
+ - **Retry with backoff** and fallback models
34
+ - **Prompt templates** with variable validation
35
+ - **Multi-step chains** with checkpoint/resume
36
+ - **AI Agents** with ReAct loop and tools
37
+ - **Session state** with sliding window memory
38
+ - **Cost tracking** per request
39
+
40
+ ## Chains
41
+
42
+ ```typescript
43
+ import { Chain, Step } from 'substrai-lambdallm';
44
+
45
+ const pipeline = new Chain({
46
+ name: 'analysis',
47
+ steps: [
48
+ new Step({ name: 'extract', prompt: 'Extract entities: {input}' }),
49
+ new Step({ name: 'classify', prompt: 'Classify: {extract.output}' }),
50
+ ],
51
+ timeoutStrategy: 'checkpoint',
52
+ });
53
+
54
+ const result = await pipeline.run(context, { input: 'document text' });
55
+ ```
56
+
57
+ ## Agents
58
+
59
+ ```typescript
60
+ import { Agent, Tool } from 'substrai-lambdallm';
61
+
62
+ const search = Tool({ description: 'Search docs' })(
63
+ (input: any) => `Results for ${input.query}`
64
+ );
65
+
66
+ const agent = new Agent({
67
+ name: 'researcher',
68
+ systemPrompt: 'You are a research assistant.',
69
+ tools: [search],
70
+ maxIterations: 5,
71
+ });
72
+
73
+ const result = await agent.run('What is LambdaLLM?', context);
74
+ ```
75
+
76
+ ## Also Available in Python
77
+
78
+ ```bash
79
+ pip install substrai-lambdallm[bedrock]
80
+ ```
39
81
 
40
82
  ## Links
41
83
 
@@ -46,5 +88,3 @@ def lambda_handler(event, context):
46
88
  ## Author
47
89
 
48
90
  **Gaurav Kumar Sinha** — Founder, [SubstrAI](https://github.com/substrai)
49
-
50
- Email: gaurav@substrai.dev
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Agent and Tool system for LambdaLLM.
3
+ */
4
+ import { LambdaLLMContext } from '../core/context';
5
+ export interface ToolDefinition {
6
+ name: string;
7
+ description: string;
8
+ parameters: Array<{
9
+ name: string;
10
+ type: string;
11
+ description: string;
12
+ required: boolean;
13
+ }>;
14
+ func: (...args: any[]) => any;
15
+ }
16
+ /**
17
+ * Decorator-like function to define a tool.
18
+ */
19
+ export declare function Tool(options: {
20
+ description: string;
21
+ name?: string;
22
+ }): (func: Function) => ToolDefinition;
23
+ export interface AgentResult {
24
+ answer: string;
25
+ status: 'completed' | 'max_iterations' | 'timeout' | 'cost_limit';
26
+ totalIterations: number;
27
+ totalToolCalls: number;
28
+ totalCostUsd: number;
29
+ totalLatencyMs: number;
30
+ steps: Array<{
31
+ thought: string;
32
+ toolName?: string;
33
+ toolOutput?: string;
34
+ isFinal: boolean;
35
+ }>;
36
+ }
37
+ export interface AgentOptions {
38
+ name: string;
39
+ systemPrompt: string;
40
+ tools: ToolDefinition[];
41
+ maxIterations?: number;
42
+ timeoutBuffer?: number;
43
+ maxCostUsd?: number;
44
+ }
45
+ export declare class Agent {
46
+ name: string;
47
+ systemPrompt: string;
48
+ tools: ToolDefinition[];
49
+ maxIterations: number;
50
+ timeoutBuffer: number;
51
+ maxCostUsd?: number;
52
+ constructor(options: AgentOptions);
53
+ run(query: string, context: LambdaLLMContext): Promise<AgentResult>;
54
+ private parseDecision;
55
+ private buildResult;
56
+ }
57
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agents/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1F,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,IACjD,MAAM,QAAQ,KAAG,cAAc,CAQjD;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,GAAG,gBAAgB,GAAG,SAAS,GAAG,YAAY,CAAC;IAClE,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC7F;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,KAAK;IACT,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,YAAY;IAS3B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IA+CzE,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,WAAW;CAYpB"}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ /**
3
+ * Agent and Tool system for LambdaLLM.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Agent = void 0;
7
+ exports.Tool = Tool;
8
+ /**
9
+ * Decorator-like function to define a tool.
10
+ */
11
+ function Tool(options) {
12
+ return function (func) {
13
+ return {
14
+ name: options.name || func.name,
15
+ description: options.description,
16
+ parameters: [],
17
+ func: func,
18
+ };
19
+ };
20
+ }
21
+ class Agent {
22
+ constructor(options) {
23
+ this.name = options.name;
24
+ this.systemPrompt = options.systemPrompt;
25
+ this.tools = options.tools;
26
+ this.maxIterations = options.maxIterations || 10;
27
+ this.timeoutBuffer = options.timeoutBuffer || 30;
28
+ this.maxCostUsd = options.maxCostUsd;
29
+ }
30
+ async run(query, context) {
31
+ const startTime = Date.now();
32
+ const steps = [];
33
+ let toolCalls = 0;
34
+ const toolDescriptions = this.tools.map(t => `- ${t.name}: ${t.description}`).join('\n');
35
+ const systemContent = `${this.systemPrompt}\n\nTools available:\n${toolDescriptions}\n\nRespond with JSON: {"thought": "...", "tool_name": "...", "tool_input": {...}} or {"thought": "...", "final_answer": "..."}`;
36
+ let messages = `System: ${systemContent}\n\nUser: ${query}\n\nAssistant:`;
37
+ for (let i = 0; i < this.maxIterations; i++) {
38
+ if (context.remainingTimeMs < this.timeoutBuffer * 1000) {
39
+ return this.buildResult(steps, 'timeout', startTime, toolCalls, context.totalCost, 'Approaching timeout.');
40
+ }
41
+ if (this.maxCostUsd && context.totalCost >= this.maxCostUsd) {
42
+ return this.buildResult(steps, 'cost_limit', startTime, toolCalls, context.totalCost, 'Cost limit reached.');
43
+ }
44
+ const response = await context.invoke(messages);
45
+ const decision = this.parseDecision(response);
46
+ if (decision.final_answer) {
47
+ steps.push({ thought: decision.thought || '', isFinal: true });
48
+ return this.buildResult(steps, 'completed', startTime, toolCalls, context.totalCost, decision.final_answer);
49
+ }
50
+ if (decision.tool_name) {
51
+ const tool = this.tools.find(t => t.name === decision.tool_name);
52
+ let toolOutput = 'Tool not found';
53
+ if (tool) {
54
+ try {
55
+ toolOutput = String(tool.func(decision.tool_input || {}));
56
+ toolCalls++;
57
+ }
58
+ catch (e) {
59
+ toolOutput = `Error: ${e.message}`;
60
+ }
61
+ }
62
+ steps.push({ thought: decision.thought || '', toolName: decision.tool_name, toolOutput, isFinal: false });
63
+ messages += `\n${response}\nUser: Tool '${decision.tool_name}' returned: ${toolOutput}\nContinue.\nAssistant:`;
64
+ }
65
+ }
66
+ return this.buildResult(steps, 'max_iterations', startTime, toolCalls, context.totalCost, 'Max iterations reached.');
67
+ }
68
+ parseDecision(response) {
69
+ try {
70
+ if (response.trim().startsWith('{'))
71
+ return JSON.parse(response.trim());
72
+ if (response.includes('```json')) {
73
+ const json = response.split('```json')[1].split('```')[0];
74
+ return JSON.parse(json.trim());
75
+ }
76
+ return { thought: 'Direct response', final_answer: response };
77
+ }
78
+ catch {
79
+ return { thought: 'Could not parse', final_answer: response };
80
+ }
81
+ }
82
+ buildResult(steps, status, startTime, toolCalls, cost, answer) {
83
+ return {
84
+ answer, status, steps,
85
+ totalIterations: steps.length,
86
+ totalToolCalls: toolCalls,
87
+ totalCostUsd: cost,
88
+ totalLatencyMs: Date.now() - startTime,
89
+ };
90
+ }
91
+ }
92
+ exports.Agent = Agent;
93
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agents/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Multi-agent router, tool sandboxing, and async tool dispatch.
3
+ */
4
+ import { Agent, AgentResult } from './agent';
5
+ import { LambdaLLMContext } from '../core/context';
6
+ export interface RouteConfig {
7
+ agent: Agent;
8
+ description: string;
9
+ keywords: string[];
10
+ priority?: number;
11
+ }
12
+ export declare class AgentRouter {
13
+ private routes;
14
+ private fallback?;
15
+ private strategy;
16
+ constructor(options: {
17
+ routes: RouteConfig[];
18
+ fallback?: Agent;
19
+ strategy?: 'keyword' | 'llm';
20
+ });
21
+ route(query: string, context: LambdaLLMContext): Promise<AgentResult>;
22
+ private routeByKeyword;
23
+ private routeByLLM;
24
+ }
25
+ export interface SandboxPolicy {
26
+ allowedActions: string[];
27
+ deniedActions: string[];
28
+ maxExecutionTimeMs: number;
29
+ }
30
+ export declare class ToolSandbox {
31
+ private policy;
32
+ constructor(policy?: Partial<SandboxPolicy>);
33
+ execute<T>(fn: () => T | Promise<T>): Promise<T>;
34
+ validateAction(action: string): boolean;
35
+ }
36
+ export interface AsyncToolRequest {
37
+ requestId: string;
38
+ toolName: string;
39
+ toolInput: Record<string, any>;
40
+ }
41
+ export declare class AsyncToolDispatcher {
42
+ private queueUrl?;
43
+ private client;
44
+ constructor(options?: {
45
+ queueUrl?: string;
46
+ });
47
+ dispatch(toolName: string, toolInput: Record<string, any>): Promise<AsyncToolRequest>;
48
+ private sendToSQS;
49
+ private generateId;
50
+ }
51
+ export declare class StreamingResponse {
52
+ private chunks;
53
+ private generator;
54
+ constructor(generator: AsyncGenerator<string>);
55
+ [Symbol.asyncIterator](): AsyncGenerator<string>;
56
+ getFullText(): Promise<string>;
57
+ toLambdaStream(): AsyncGenerator<Buffer>;
58
+ }
59
+ //# sourceMappingURL=extras.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extras.d.ts","sourceRoot":"","sources":["../../src/agents/extras.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAkB,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAInD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAC,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAoB;gBAExB,OAAO,EAAE;QAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,CAAA;KAAE;IAMxF,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAe3E,OAAO,CAAC,cAAc;YAUR,UAAU;CAUzB;AAID,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAQrC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAWtD,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAUxC;AAID,MAAM,WAAW,gBAAgB;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAAE;AAE1G,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAa;gBAEf,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO;IAIzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC;YAY7E,SAAS;IAavB,OAAO,CAAC,UAAU;CAMnB;AAID,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,SAAS,CAAyB;gBAE9B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC;IAItC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC;IAOjD,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAKpC,cAAc,IAAI,cAAc,CAAC,MAAM,CAAC;CAWzC"}
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ /**
3
+ * Multi-agent router, tool sandboxing, and async tool dispatch.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.StreamingResponse = exports.AsyncToolDispatcher = exports.ToolSandbox = exports.AgentRouter = void 0;
7
+ class AgentRouter {
8
+ constructor(options) {
9
+ this.routes = options.routes.sort((a, b) => (b.priority || 0) - (a.priority || 0));
10
+ this.fallback = options.fallback;
11
+ this.strategy = options.strategy || 'keyword';
12
+ }
13
+ async route(query, context) {
14
+ let agent;
15
+ if (this.strategy === 'keyword') {
16
+ agent = this.routeByKeyword(query);
17
+ }
18
+ else {
19
+ agent = await this.routeByLLM(query, context);
20
+ }
21
+ if (!agent)
22
+ agent = this.fallback;
23
+ if (!agent)
24
+ throw new Error('No agent matched and no fallback configured');
25
+ return agent.run(query, context);
26
+ }
27
+ routeByKeyword(query) {
28
+ const lower = query.toLowerCase();
29
+ for (const route of this.routes) {
30
+ for (const keyword of route.keywords) {
31
+ if (lower.includes(keyword.toLowerCase()))
32
+ return route.agent;
33
+ }
34
+ }
35
+ return undefined;
36
+ }
37
+ async routeByLLM(query, context) {
38
+ const descriptions = this.routes.map(r => `- ${r.agent.name}: ${r.description}`).join('\n');
39
+ const prompt = `Classify this query into one of these categories:\n${descriptions}\n\nQuery: ${query}\n\nRespond with ONLY the agent name.`;
40
+ try {
41
+ const response = await context.invoke(prompt);
42
+ const name = response.trim().toLowerCase();
43
+ const match = this.routes.find(r => r.agent.name.toLowerCase() === name);
44
+ return match?.agent;
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ }
51
+ exports.AgentRouter = AgentRouter;
52
+ class ToolSandbox {
53
+ constructor(policy) {
54
+ this.policy = {
55
+ allowedActions: policy?.allowedActions || [],
56
+ deniedActions: policy?.deniedActions || [],
57
+ maxExecutionTimeMs: policy?.maxExecutionTimeMs || 30000,
58
+ };
59
+ }
60
+ async execute(fn) {
61
+ const start = Date.now();
62
+ const result = await Promise.race([
63
+ Promise.resolve(fn()),
64
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Tool execution exceeded timeout (${this.policy.maxExecutionTimeMs}ms)`)), this.policy.maxExecutionTimeMs)),
65
+ ]);
66
+ return result;
67
+ }
68
+ validateAction(action) {
69
+ if (this.policy.deniedActions.includes(action))
70
+ return false;
71
+ if (this.policy.allowedActions.length === 0)
72
+ return true;
73
+ for (const allowed of this.policy.allowedActions) {
74
+ if (allowed === '*')
75
+ return true;
76
+ if (allowed.endsWith('*') && action.startsWith(allowed.slice(0, -1)))
77
+ return true;
78
+ if (action === allowed)
79
+ return true;
80
+ }
81
+ return false;
82
+ }
83
+ }
84
+ exports.ToolSandbox = ToolSandbox;
85
+ class AsyncToolDispatcher {
86
+ constructor(options = {}) {
87
+ this.client = null;
88
+ this.queueUrl = options.queueUrl;
89
+ }
90
+ async dispatch(toolName, toolInput) {
91
+ const requestId = this.generateId();
92
+ const request = { requestId, toolName, toolInput };
93
+ if (this.queueUrl) {
94
+ await this.sendToSQS(request);
95
+ }
96
+ console.log(JSON.stringify({ event: 'async_tool.dispatched', ...request }));
97
+ return request;
98
+ }
99
+ async sendToSQS(request) {
100
+ try {
101
+ const { SQSClient, SendMessageCommand } = require('@aws-sdk/client-sqs');
102
+ if (!this.client)
103
+ this.client = new SQSClient({});
104
+ await this.client.send(new SendMessageCommand({
105
+ QueueUrl: this.queueUrl,
106
+ MessageBody: JSON.stringify(request),
107
+ }));
108
+ }
109
+ catch (e) {
110
+ throw new Error(`Failed to dispatch async tool: ${e.message}`);
111
+ }
112
+ }
113
+ generateId() {
114
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
115
+ const r = Math.random() * 16 | 0;
116
+ return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
117
+ });
118
+ }
119
+ }
120
+ exports.AsyncToolDispatcher = AsyncToolDispatcher;
121
+ // ===== STREAMING =====
122
+ class StreamingResponse {
123
+ constructor(generator) {
124
+ this.chunks = [];
125
+ this.generator = generator;
126
+ }
127
+ async *[Symbol.asyncIterator]() {
128
+ for await (const chunk of this.generator) {
129
+ this.chunks.push(chunk);
130
+ yield chunk;
131
+ }
132
+ }
133
+ async getFullText() {
134
+ for await (const chunk of this.generator) {
135
+ this.chunks.push(chunk);
136
+ }
137
+ return this.chunks.join('');
138
+ }
139
+ toLambdaStream() {
140
+ const self = this;
141
+ return (async function* () {
142
+ yield Buffer.from(JSON.stringify({ type: 'metadata' }) + '\n');
143
+ for await (const chunk of self.generator) {
144
+ self.chunks.push(chunk);
145
+ yield Buffer.from(JSON.stringify({ type: 'content', text: chunk }) + '\n');
146
+ }
147
+ yield Buffer.from(JSON.stringify({ type: 'complete' }) + '\n');
148
+ })();
149
+ }
150
+ }
151
+ exports.StreamingResponse = StreamingResponse;
152
+ //# sourceMappingURL=extras.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extras.js","sourceRoot":"","sources":["../../src/agents/extras.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Multi-step chain pipeline for LambdaLLM.
3
+ */
4
+ import { LambdaLLMContext } from '../core/context';
5
+ export interface StepOptions {
6
+ name: string;
7
+ prompt?: string;
8
+ func?: (outputs: Record<string, any>) => any;
9
+ condition?: (outputs: Record<string, any>) => boolean;
10
+ }
11
+ export declare class Step {
12
+ name: string;
13
+ prompt?: string;
14
+ func?: (outputs: Record<string, any>) => any;
15
+ condition?: (outputs: Record<string, any>) => boolean;
16
+ constructor(options: StepOptions);
17
+ get isLlmStep(): boolean;
18
+ get isTransformStep(): boolean;
19
+ }
20
+ export interface ChainResult {
21
+ chainName: string;
22
+ status: 'completed' | 'checkpointed' | 'failed' | 'truncated';
23
+ steps: Array<{
24
+ name: string;
25
+ output: any;
26
+ costUsd: number;
27
+ latencyMs: number;
28
+ skipped: boolean;
29
+ }>;
30
+ finalOutput: any;
31
+ totalCostUsd: number;
32
+ totalLatencyMs: number;
33
+ completedSteps: number;
34
+ checkpoint?: any;
35
+ }
36
+ export interface ChainOptions {
37
+ name: string;
38
+ steps: Step[];
39
+ timeoutStrategy?: 'fail-fast' | 'checkpoint' | 'truncate';
40
+ maxTotalCost?: number;
41
+ }
42
+ export declare class Chain {
43
+ name: string;
44
+ steps: Step[];
45
+ timeoutStrategy: string;
46
+ maxTotalCost?: number;
47
+ constructor(options: ChainOptions);
48
+ run(context: LambdaLLMContext, variables: Record<string, any>): Promise<ChainResult>;
49
+ private resolveVariables;
50
+ }
51
+ //# sourceMappingURL=chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../src/chains/chain.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC;IAC7C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;CACvD;AAED,qBAAa,IAAI;IACR,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC;IAC7C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;gBAEjD,OAAO,EAAE,WAAW;IAUhC,IAAI,SAAS,IAAI,OAAO,CAA0B;IAClD,IAAI,eAAe,IAAI,OAAO,CAAwB;CACvD;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC9D,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClG,WAAW,EAAE,GAAG,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,GAAG,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,eAAe,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,KAAK;IACT,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,YAAY;IAQ3B,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAyE1F,OAAO,CAAC,gBAAgB;CAKzB"}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * Multi-step chain pipeline for LambdaLLM.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Chain = exports.Step = void 0;
7
+ class Step {
8
+ constructor(options) {
9
+ if (!options.prompt && !options.func) {
10
+ throw new Error(`Step '${options.name}' must have either prompt or func`);
11
+ }
12
+ this.name = options.name;
13
+ this.prompt = options.prompt;
14
+ this.func = options.func;
15
+ this.condition = options.condition;
16
+ }
17
+ get isLlmStep() { return !!this.prompt; }
18
+ get isTransformStep() { return !!this.func; }
19
+ }
20
+ exports.Step = Step;
21
+ class Chain {
22
+ constructor(options) {
23
+ if (!options.steps.length)
24
+ throw new Error('Chain must have at least one step');
25
+ this.name = options.name;
26
+ this.steps = options.steps;
27
+ this.timeoutStrategy = options.timeoutStrategy || 'fail-fast';
28
+ this.maxTotalCost = options.maxTotalCost;
29
+ }
30
+ async run(context, variables) {
31
+ const startTime = Date.now();
32
+ const outputs = { ...variables };
33
+ const stepResults = [];
34
+ let totalCost = 0;
35
+ for (let i = 0; i < this.steps.length; i++) {
36
+ const step = this.steps[i];
37
+ // Check timeout
38
+ if (this.timeoutStrategy === 'checkpoint' && context.shouldCheckpoint) {
39
+ return {
40
+ chainName: this.name, status: 'checkpointed', steps: stepResults,
41
+ finalOutput: stepResults[stepResults.length - 1]?.output,
42
+ totalCostUsd: totalCost, totalLatencyMs: Date.now() - startTime,
43
+ completedSteps: stepResults.filter(s => !s.skipped).length,
44
+ checkpoint: { nextStepIndex: i, outputs },
45
+ };
46
+ }
47
+ // Check cost
48
+ if (this.maxTotalCost && totalCost >= this.maxTotalCost) {
49
+ return {
50
+ chainName: this.name, status: 'truncated', steps: stepResults,
51
+ finalOutput: stepResults[stepResults.length - 1]?.output,
52
+ totalCostUsd: totalCost, totalLatencyMs: Date.now() - startTime,
53
+ completedSteps: stepResults.filter(s => !s.skipped).length,
54
+ };
55
+ }
56
+ // Check condition
57
+ if (step.condition && !step.condition(outputs)) {
58
+ stepResults.push({ name: step.name, output: null, costUsd: 0, latencyMs: 0, skipped: true });
59
+ continue;
60
+ }
61
+ const stepStart = Date.now();
62
+ try {
63
+ let output;
64
+ if (step.isLlmStep) {
65
+ const resolved = this.resolveVariables(step.prompt, outputs);
66
+ output = await context.invoke(resolved);
67
+ }
68
+ else if (step.func) {
69
+ output = step.func(outputs);
70
+ }
71
+ const stepCost = context.totalCost - totalCost;
72
+ totalCost = context.totalCost;
73
+ outputs[step.name] = output;
74
+ outputs[`${step.name}.output`] = output;
75
+ stepResults.push({
76
+ name: step.name, output, costUsd: stepCost,
77
+ latencyMs: Date.now() - stepStart, skipped: false,
78
+ });
79
+ }
80
+ catch (e) {
81
+ stepResults.push({ name: step.name, output: null, costUsd: 0, latencyMs: Date.now() - stepStart, skipped: false });
82
+ return {
83
+ chainName: this.name, status: 'failed', steps: stepResults,
84
+ finalOutput: null, totalCostUsd: totalCost, totalLatencyMs: Date.now() - startTime,
85
+ completedSteps: stepResults.filter(s => !s.skipped).length,
86
+ };
87
+ }
88
+ }
89
+ return {
90
+ chainName: this.name, status: 'completed', steps: stepResults,
91
+ finalOutput: stepResults[stepResults.length - 1]?.output,
92
+ totalCostUsd: totalCost, totalLatencyMs: Date.now() - startTime,
93
+ completedSteps: stepResults.filter(s => !s.skipped).length,
94
+ };
95
+ }
96
+ resolveVariables(template, outputs) {
97
+ return template.replace(/\{([a-zA-Z_][a-zA-Z0-9_.]*)\}/g, (_, key) => {
98
+ return key in outputs ? String(outputs[key]) : `{${key}}`;
99
+ });
100
+ }
101
+ }
102
+ exports.Chain = Chain;
103
+ //# sourceMappingURL=chain.js.map