@primo-ai/sdk 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -12,8 +12,9 @@ This package contains all shared types used across the AgentForge monorepo. It h
12
12
 
13
13
  | Type | Description |
14
14
  |------|-------------|
15
- | `PipelineStage` | Union of all 13 stage names |
16
- | `StageName` | `PipelineStage` plus arbitrary plugin-defined strings |
15
+ | `PipelineStage` | Union of 10 main agent lifecycle stages |
16
+ | `ToolExecutionStage` | Sub-pipeline stages: `beforeTool`, `execute`, `afterTool` |
17
+ | `StageName` | `PipelineStage \| ToolExecutionStage` plus arbitrary plugin-defined strings |
17
18
  | `Processor` | `{ stage, execute(context) => Promise<ProcessorResult> }` |
18
19
  | `ProcessorResult` | `PipelineContext \| AbortSignal \| SuspensionSignal` |
19
20
  | `PipelineContext` | Container with `request`, `agent`, `iteration`, `session` regions |
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
- /** The agent lifecycle stages + gate stages + tool sub-pipeline stages. */
2
- export type PipelineStage = 'processInput' | 'buildContext' | 'prepareStep' | 'gateLLM' | 'invokeLLM' | 'processStepOutput' | 'gateTool' | 'executeTools' | 'evaluateIteration' | 'processOutput' | 'beforeTool' | 'execute' | 'afterTool';
1
+ /** Agent lifecycle stages: pre-loop setup, agentic loop, and post-loop output. */
2
+ export type PipelineStage = 'processInput' | 'buildContext' | 'prepareStep' | 'gateLLM' | 'invokeLLM' | 'processStepOutput' | 'gateTool' | 'executeTools' | 'evaluateIteration' | 'processOutput';
3
+ /** Tool execution sub-pipeline stages — internal to ToolRegistry. */
4
+ export type ToolExecutionStage = 'beforeTool' | 'execute' | 'afterTool';
3
5
  /** Stage name that accepts built-in stages AND arbitrary plugin-defined strings. */
4
- export type StageName = PipelineStage | (string & {});
6
+ export type StageName = PipelineStage | ToolExecutionStage | (string & {});
5
7
  /** A mutation operation applied to a pipeline phase's stage list. */
6
8
  export type StageMutation = {
7
9
  type: 'insert';
@@ -106,11 +108,11 @@ export interface IterationRegion {
106
108
  loopDirective?: LoopDirective;
107
109
  /** AI SDK fullStream yielding text-delta, tool-call, finish-step, error events. */
108
110
  fullStream?: AsyncIterable<unknown>;
109
- usagePromise?: Promise<TokenUsage>;
111
+ usagePromise?: Promise<TokenUsage | null>;
110
112
  /** Promise resolving to reasoning text from the model (e.g. DeepSeek reasoning_content). */
111
113
  reasoningPromise?: Promise<string | undefined>;
112
114
  response?: string;
113
- tokenUsage?: TokenUsage;
115
+ tokenUsage?: TokenUsage | null;
114
116
  /** Tool calls extracted from the LLM response by PipelineRunner stream consumption. */
115
117
  pendingToolCalls?: ToolCall[];
116
118
  /** Reasoning content from thinking-mode models (e.g. DeepSeek). Must be passed back on subsequent turns. */
@@ -124,7 +126,10 @@ export interface IterationRegion {
124
126
  export interface SessionRegion {
125
127
  messageHistory?: Message[];
126
128
  totalTokenUsage?: TokenUsage;
127
- /** Plugin extension point. Namespaced by plugin ID. */
129
+ /**
130
+ * Plugin extension point. Use plugin ID as key name to avoid collisions.
131
+ * Type-safe usage: SimpleProcessorContext.getState<MyPluginState>('myPlugin')
132
+ */
128
133
  custom: Record<string, unknown>;
129
134
  }
130
135
  export interface PipelineContext {
@@ -156,7 +161,25 @@ export interface SuspensionSignal {
156
161
  checkpoint: PipelineCheckpoint;
157
162
  expiresAt?: string;
158
163
  }
159
- export type ProcessorResult = PipelineContext | AbortSignal | SuspensionSignal;
164
+ export interface ErrorResult {
165
+ type: 'error';
166
+ error: Error;
167
+ stage: StageName;
168
+ recoverable?: boolean;
169
+ }
170
+ export type ProcessorResult = PipelineContext | AbortSignal | SuspensionSignal | ErrorResult;
171
+ /**
172
+ * Processor -- Business logic unit in the pipeline. CAN read and modify PipelineContext.
173
+ * Use for: context assembly, LLM calls, tool execution, iteration evaluation.
174
+ *
175
+ * Hook -- Observation/interception point in the pipeline. CANNOT modify Context.
176
+ * Use for: logging, metrics, event emission, permission checks (allow/deny).
177
+ *
178
+ * Boundary rules:
179
+ * - Need to modify ctx -> Use Processor
180
+ * - Need to intercept/deny -> Use Hook
181
+ * - Only need to observe -> Use Event (subscribe/on)
182
+ */
160
183
  export interface Processor {
161
184
  stage: StageName;
162
185
  execute(context: PipelineContext): Promise<ProcessorResult>;
@@ -282,7 +305,36 @@ export type StreamEvent = {
282
305
  suspensionId: string;
283
306
  reason: string;
284
307
  checkpoint: PipelineCheckpoint;
308
+ } | {
309
+ type: 'error';
310
+ error: Error;
311
+ stage: StageName;
312
+ recoverable?: boolean;
313
+ } | {
314
+ type: 'session.started';
315
+ sessionId: string;
316
+ } | {
317
+ type: 'session.completed';
318
+ sessionId: string;
319
+ tokenUsage: TokenUsage;
320
+ } | {
321
+ type: 'session.aborted';
322
+ sessionId: string;
323
+ } | {
324
+ type: 'permission.request';
325
+ sessionId: string;
326
+ permissionId: string;
327
+ toolName: string;
328
+ args: Record<string, unknown>;
329
+ reason: string;
330
+ } | {
331
+ type: 'permission.resolved';
332
+ sessionId: string;
333
+ permissionId: string;
334
+ decision: 'allow' | 'deny';
285
335
  };
336
+ /** @deprecated Use StreamEvent — the union now includes all event types */
337
+ export type ServerStreamEvent = StreamEvent;
286
338
  export type EventType = 'agent:start' | 'agent:end' | 'tool:before' | 'tool:after' | string;
287
339
  export type HookPoint = 'agent.start' | 'agent.end' | 'stage.before' | 'stage.after' | 'llm.before' | 'llm.after' | 'tool.before' | 'tool.after' | 'iteration.end' | 'error';
288
340
  export type HookProfile = 'minimal' | 'standard' | 'strict';
@@ -324,21 +376,38 @@ export interface ResourceDeclaration {
324
376
  start: () => Promise<unknown>;
325
377
  stop: (instance: unknown) => Promise<void>;
326
378
  }
327
- export interface HarnessAPI {
379
+ /** Pipeline extension: register Processors */
380
+ export interface PipelineRegistry {
328
381
  registerProcessor(stage: StageName, processor: Processor): void;
382
+ }
383
+ /** Tool registration */
384
+ export interface ToolRegistryAPI {
329
385
  registerTool(tool: ToolDefinition): void;
330
386
  unregisterTool(name: string): boolean;
331
- registerCommand(name: string, handler: (args: string) => Promise<void>): void;
387
+ }
388
+ /** Interception & events */
389
+ export interface InterceptionAPI {
332
390
  registerHook(hook: Hook): void;
333
391
  subscribe(eventType: string, handler: (data?: unknown) => void): () => void;
334
- registerResource(declaration: ResourceDeclaration): void;
335
- registerProvider(name: string, factory: unknown): void;
336
- registerCompressionStrategy(strategy: CompressionStrategy): void;
337
392
  emit(eventType: string, data?: unknown): void;
393
+ }
394
+ /** Pipeline stage mutation (frozen after agent starts) */
395
+ export interface StageMutationAPI {
338
396
  insertStage(phase: 'preLoop' | 'loop' | 'postLoop', after: StageName, newStage: StageName): void;
339
397
  removeStage(phase: 'preLoop' | 'loop' | 'postLoop', stage: StageName): void;
340
398
  replaceStages(phase: 'preLoop' | 'loop' | 'postLoop', stages: StageName[]): void;
341
399
  }
400
+ /** Lifecycle & model providers */
401
+ export interface LifecycleAPI {
402
+ registerResource(declaration: ResourceDeclaration): void;
403
+ registerProvider(name: string, factory: unknown): void;
404
+ registerCompressionStrategy(strategy: CompressionStrategy): void;
405
+ registerCommand(name: string, handler: (args: string) => Promise<void>): void;
406
+ }
407
+ /** Full Harness API — composes all sub-interfaces.
408
+ * Plugin devs can depend on individual sub-interfaces for selective dependency. */
409
+ export interface HarnessAPI extends PipelineRegistry, ToolRegistryAPI, InterceptionAPI, StageMutationAPI, LifecycleAPI {
410
+ }
342
411
  export interface PluginRegistration {
343
412
  processors?: Processor[];
344
413
  tools?: ToolDefinition[];
@@ -373,6 +442,13 @@ export interface AgentConfig {
373
442
  */
374
443
  requiredToolPolicy?: 'advise' | 'enforce';
375
444
  }
445
+ /** Convenience config for single-agent usage. Static fields only — no Dynamic<T> or advanced options. */
446
+ export interface AgentSimpleConfig {
447
+ model: string;
448
+ systemPrompt?: string;
449
+ maxIterations?: number;
450
+ tools?: Tool[];
451
+ }
376
452
  /** Context passed to Dynamic<T> resolver functions at processInput stage. */
377
453
  export interface ResolveContext {
378
454
  input: string;
@@ -438,6 +514,7 @@ export interface GatewayConfig {
438
514
  }
439
515
  /**
440
516
  * Top-level framework configuration.
517
+ * @internal For multi-agent and server deployments. For single-agent usage, use `AgentSimpleConfig` or `createAgent()`.
441
518
  * Merged from multiple layers (highest priority first):
442
519
  * 1. Session-level — runtime parameters passed to agent.run()
443
520
  * 2. Project-level — .agentforge/config.jsonc in project root
@@ -483,7 +560,7 @@ export interface HarnessConfig {
483
560
  facts: string[] | ((ctx: PipelineContext) => string[] | Promise<string[]>);
484
561
  };
485
562
  }
486
- export type SessionStatus = 'active' | 'completed' | 'suspended' | 'error';
563
+ export type SessionStatus = 'active' | 'completed' | 'suspended' | 'cancelled' | 'error';
487
564
  export interface SessionRecord {
488
565
  sessionId: string;
489
566
  parentSessionId?: string;
@@ -507,6 +584,12 @@ export interface SessionStorage {
507
584
  status?: SessionStatus;
508
585
  }): Promise<SessionRecord[]>;
509
586
  updateMeta(sessionId: string, meta: Partial<SessionRecord>): Promise<void>;
587
+ get(sessionId: string): Promise<SessionRecord | undefined>;
588
+ delete(sessionId: string): Promise<void>;
589
+ getMessages(sessionId: string, options?: {
590
+ limit?: number;
591
+ before?: string;
592
+ }): Promise<Message[]>;
510
593
  }
511
594
  export interface CheckpointStore<T = unknown> {
512
595
  save(sessionId: string, data: T): Promise<void>;
@@ -621,3 +704,4 @@ export interface AgentProfile {
621
704
  model?: string;
622
705
  maxIterations?: number;
623
706
  }
707
+ export { SimpleProcessorContext } from './simple-context.js';
package/dist/index.js CHANGED
@@ -62,3 +62,7 @@ export const SpanAttributeKeys = {
62
62
  // ---------------------------------------------------------------------------
63
63
  export { AgentForgeClient } from './client.js';
64
64
  export { parseSSE } from './client.js';
65
+ // ---------------------------------------------------------------------------
66
+ // SimpleProcessorContext -- flat PipelineContext convenience wrapper
67
+ // ---------------------------------------------------------------------------
68
+ export { SimpleProcessorContext } from './simple-context.js';
@@ -0,0 +1,23 @@
1
+ import type { PipelineContext, AgentConfig, LoopDirective, Message, TokenUsage } from './index.js';
2
+ /**
3
+ * Flat wrapper for PipelineContext.
4
+ * Provides direct access to common fields without deep nesting.
5
+ * Wraps by reference -- no data copying.
6
+ */
7
+ export declare class SimpleProcessorContext {
8
+ private ctx;
9
+ constructor(ctx: PipelineContext);
10
+ get input(): string;
11
+ get sessionId(): string;
12
+ get model(): string;
13
+ get systemPrompt(): string | undefined;
14
+ getConfig<T = AgentConfig>(): T;
15
+ get step(): number;
16
+ get response(): string | undefined;
17
+ get loopDirective(): LoopDirective | undefined;
18
+ get messages(): Message[];
19
+ get totalTokens(): TokenUsage | undefined;
20
+ getState<T = unknown>(namespace: string): T | undefined;
21
+ setState(namespace: string, value: unknown): void;
22
+ get raw(): PipelineContext;
23
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Flat wrapper for PipelineContext.
3
+ * Provides direct access to common fields without deep nesting.
4
+ * Wraps by reference -- no data copying.
5
+ */
6
+ export class SimpleProcessorContext {
7
+ ctx;
8
+ constructor(ctx) {
9
+ this.ctx = ctx;
10
+ }
11
+ // Request region (immutable)
12
+ get input() { return this.ctx.request.input; }
13
+ get sessionId() { return this.ctx.request.sessionId; }
14
+ // Agent region
15
+ get model() { return this.ctx.agent.config.model; }
16
+ get systemPrompt() { return this.ctx.agent.systemPrompt; }
17
+ getConfig() { return this.ctx.agent.config; }
18
+ // Iteration region
19
+ get step() { return this.ctx.iteration.step; }
20
+ get response() { return this.ctx.iteration.response; }
21
+ get loopDirective() { return this.ctx.iteration.loopDirective; }
22
+ // Session region
23
+ get messages() { return this.ctx.session.messageHistory ?? []; }
24
+ get totalTokens() { return this.ctx.session.totalTokenUsage; }
25
+ // Plugin namespace data (type-safe access)
26
+ getState(namespace) {
27
+ return this.ctx.session.custom[namespace];
28
+ }
29
+ setState(namespace, value) {
30
+ this.ctx.session.custom[namespace] = value;
31
+ }
32
+ // Raw Context access (escape hatch for advanced use)
33
+ get raw() { return this.ctx; }
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primo-ai/sdk",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",