@townco/agent 0.1.44 → 0.1.45

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 (52) hide show
  1. package/dist/acp-server/adapter.d.ts +1 -0
  2. package/dist/acp-server/adapter.js +130 -9
  3. package/dist/acp-server/cli.d.ts +3 -1
  4. package/dist/acp-server/session-storage.d.ts +21 -1
  5. package/dist/acp-server/session-storage.js +19 -1
  6. package/dist/bin.js +0 -0
  7. package/dist/definition/index.d.ts +19 -0
  8. package/dist/definition/index.js +11 -0
  9. package/dist/definition/mcp.js +0 -1
  10. package/dist/definition/tools/todo.d.ts +49 -0
  11. package/dist/definition/tools/todo.js +80 -0
  12. package/dist/definition/tools/web_search.d.ts +4 -0
  13. package/dist/definition/tools/web_search.js +26 -0
  14. package/dist/dev-agent/index.d.ts +2 -0
  15. package/dist/dev-agent/index.js +18 -0
  16. package/dist/example.d.ts +2 -0
  17. package/dist/example.js +19 -0
  18. package/dist/index.js +13 -2
  19. package/dist/runner/agent-runner.d.ts +28 -2
  20. package/dist/runner/agent-runner.js +2 -1
  21. package/dist/runner/hooks/constants.d.ts +9 -0
  22. package/dist/runner/hooks/constants.js +19 -0
  23. package/dist/runner/hooks/executor.d.ts +23 -0
  24. package/dist/runner/hooks/executor.js +163 -0
  25. package/dist/runner/hooks/index.d.ts +5 -0
  26. package/dist/runner/hooks/index.js +5 -0
  27. package/dist/runner/hooks/loader.d.ts +5 -0
  28. package/dist/runner/hooks/loader.js +49 -0
  29. package/dist/runner/hooks/predefined/compaction-tool.d.ts +6 -0
  30. package/dist/runner/hooks/predefined/compaction-tool.js +42 -0
  31. package/dist/runner/hooks/registry.d.ts +14 -0
  32. package/dist/runner/hooks/registry.js +20 -0
  33. package/dist/runner/hooks/types.d.ts +144 -0
  34. package/dist/runner/hooks/types.js +33 -0
  35. package/dist/runner/index.d.ts +3 -1
  36. package/dist/runner/langchain/index.js +16 -10
  37. package/dist/runner/langchain/model-factory.js +3 -1
  38. package/dist/scaffold/claude-scaffold.js +8 -6
  39. package/dist/storage/index.js +3 -1
  40. package/dist/templates/index.d.ts +7 -0
  41. package/dist/templates/index.js +7 -2
  42. package/dist/test-script.js +3 -1
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/index.ts +14 -2
  45. package/package.json +5 -5
  46. package/templates/index.ts +14 -2
  47. package/dist/acp-server/test-acp-summarize.d.ts +0 -7
  48. package/dist/acp-server/test-acp-summarize.js +0 -127
  49. package/dist/acp-server/test-summarizer.d.ts +0 -7
  50. package/dist/acp-server/test-summarizer.js +0 -170
  51. package/dist/acp-server/tool-summarizer.d.ts +0 -125
  52. package/dist/acp-server/tool-summarizer.js +0 -182
@@ -30,6 +30,15 @@ export declare const zAgentRunnerParams: z.ZodObject<{
30
30
  url: z.ZodString;
31
31
  headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
32
32
  }, z.core.$strip>]>>>;
33
+ hooks: z.ZodOptional<z.ZodArray<z.ZodObject<{
34
+ type: z.ZodEnum<{
35
+ context_size: "context_size";
36
+ }>;
37
+ setting: z.ZodOptional<z.ZodObject<{
38
+ threshold: z.ZodNumber;
39
+ }, z.core.$strip>>;
40
+ callback: z.ZodString;
41
+ }, z.core.$strip>>>;
33
42
  }, z.core.$strip>;
34
43
  export type CreateAgentRunnerParams = z.infer<typeof zAgentRunnerParams>;
35
44
  export interface SessionMessage {
@@ -40,7 +49,7 @@ export interface SessionMessage {
40
49
  export type InvokeRequest = Omit<PromptRequest, "_meta"> & {
41
50
  messageId: string;
42
51
  sessionMeta?: Record<string, unknown>;
43
- sessionMessages?: SessionMessage[];
52
+ contextMessages?: SessionMessage[];
44
53
  };
45
54
  export interface TokenUsage {
46
55
  inputTokens?: number;
@@ -58,6 +67,23 @@ export interface AgentMessageChunkWithTokens {
58
67
  [key: string]: unknown;
59
68
  };
60
69
  }
70
+ export type HookNotificationUpdate = {
71
+ sessionUpdate: "hook_triggered";
72
+ hookType: string;
73
+ threshold: number;
74
+ currentPercentage: number;
75
+ callback: string;
76
+ } | {
77
+ sessionUpdate: "hook_completed";
78
+ hookType: string;
79
+ callback: string;
80
+ metadata?: Record<string, unknown>;
81
+ } | {
82
+ sessionUpdate: "hook_error";
83
+ hookType: string;
84
+ callback: string;
85
+ error: string;
86
+ };
61
87
  export type ExtendedSessionUpdate = (SessionNotification["update"] & {
62
88
  prettyName?: string;
63
89
  icon?: string;
@@ -72,7 +98,7 @@ export type ExtendedSessionUpdate = (SessionNotification["update"] & {
72
98
  _meta?: {
73
99
  messageId?: string;
74
100
  };
75
- } | AgentMessageChunkWithTokens;
101
+ } | AgentMessageChunkWithTokens | HookNotificationUpdate;
76
102
  /** Describes an object that can run an agent definition */
77
103
  export interface AgentRunner {
78
104
  definition: CreateAgentRunnerParams;
@@ -1,9 +1,10 @@
1
1
  import { z } from "zod";
2
- import { McpConfigSchema } from "../definition";
2
+ import { HookConfigSchema, McpConfigSchema } from "../definition";
3
3
  import { zToolType } from "./tools";
4
4
  export const zAgentRunnerParams = z.object({
5
5
  systemPrompt: z.string().nullable(),
6
6
  model: z.string(),
7
7
  tools: z.array(zToolType).optional(),
8
8
  mcps: z.array(McpConfigSchema).optional(),
9
+ hooks: z.array(HookConfigSchema).optional(),
9
10
  });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Model context window sizes in tokens
3
+ * Add more models as needed
4
+ */
5
+ export declare const MODEL_CONTEXT_WINDOWS: Record<string, number>;
6
+ /**
7
+ * Default context size for unknown models
8
+ */
9
+ export declare const DEFAULT_CONTEXT_SIZE = 200000;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Model context window sizes in tokens
3
+ * Add more models as needed
4
+ */
5
+ export const MODEL_CONTEXT_WINDOWS = {
6
+ // Claude 3.5 Sonnet
7
+ "claude-sonnet-4-5-20250929": 200000,
8
+ "claude-sonnet-4-20250514": 200000,
9
+ "claude-3-5-sonnet-20241022": 200000,
10
+ "claude-3-5-sonnet-20240620": 200000,
11
+ // Claude 3 Opus
12
+ "claude-3-opus-20240229": 200000,
13
+ // Claude 3 Haiku
14
+ "claude-3-haiku-20240307": 200000,
15
+ };
16
+ /**
17
+ * Default context size for unknown models
18
+ */
19
+ export const DEFAULT_CONTEXT_SIZE = 200000;
@@ -0,0 +1,23 @@
1
+ import type { ContextEntry } from "../../acp-server/session-storage";
2
+ import type { HookCallback, HookConfig, HookNotification, ReadonlySession } from "./types";
3
+ /**
4
+ * Hook executor manages hook lifecycle
5
+ */
6
+ export declare class HookExecutor {
7
+ private hooks;
8
+ private model;
9
+ private loadCallback;
10
+ constructor(hooks: HookConfig[], model: string, loadCallback: (callbackRef: string) => Promise<HookCallback>);
11
+ /**
12
+ * Execute hooks before agent invocation
13
+ * Returns new context entries to append and any notifications to send
14
+ */
15
+ executeHooks(session: ReadonlySession): Promise<{
16
+ newContextEntries: ContextEntry[];
17
+ notifications: HookNotification[];
18
+ }>;
19
+ /**
20
+ * Execute a context_size hook
21
+ */
22
+ private executeContextSizeHook;
23
+ }
@@ -0,0 +1,163 @@
1
+ import { createLogger } from "@townco/core";
2
+ import { DEFAULT_CONTEXT_SIZE, MODEL_CONTEXT_WINDOWS } from "./constants";
3
+ const logger = createLogger("hook-executor");
4
+ /**
5
+ * Get max context size for a model
6
+ */
7
+ function getModelMaxTokens(model) {
8
+ return MODEL_CONTEXT_WINDOWS[model] ?? DEFAULT_CONTEXT_SIZE;
9
+ }
10
+ /**
11
+ * Estimate token count for session messages
12
+ * This is a rough estimate: ~4 characters per token
13
+ */
14
+ function estimateTokens(messages) {
15
+ let totalChars = 0;
16
+ for (const message of messages) {
17
+ // Count characters in content blocks
18
+ for (const block of message.content) {
19
+ if (block.type === "text") {
20
+ totalChars += block.text.length;
21
+ }
22
+ else if (block.type === "tool_call") {
23
+ // Estimate tool call size (title + inputs/outputs)
24
+ totalChars += block.title.length;
25
+ if (block.rawInput) {
26
+ totalChars += JSON.stringify(block.rawInput).length;
27
+ }
28
+ if (block.rawOutput) {
29
+ totalChars += JSON.stringify(block.rawOutput).length;
30
+ }
31
+ }
32
+ }
33
+ }
34
+ // Rough estimate: 4 characters per token
35
+ return Math.ceil(totalChars / 4);
36
+ }
37
+ /**
38
+ * Resolve context entries to session messages
39
+ */
40
+ function resolveContextToMessages(context, allMessages) {
41
+ if (context.length === 0) {
42
+ return [];
43
+ }
44
+ const latestContext = context[context.length - 1];
45
+ if (!latestContext) {
46
+ return [];
47
+ }
48
+ const resolved = [];
49
+ for (const entry of latestContext.messages) {
50
+ if (entry.type === "pointer") {
51
+ const message = allMessages[entry.index];
52
+ if (message) {
53
+ resolved.push(message);
54
+ }
55
+ }
56
+ else if (entry.type === "full") {
57
+ resolved.push(entry.message);
58
+ }
59
+ }
60
+ return resolved;
61
+ }
62
+ /**
63
+ * Hook executor manages hook lifecycle
64
+ */
65
+ export class HookExecutor {
66
+ hooks;
67
+ model;
68
+ loadCallback;
69
+ constructor(hooks, model, loadCallback) {
70
+ this.hooks = hooks;
71
+ this.model = model;
72
+ this.loadCallback = loadCallback;
73
+ }
74
+ /**
75
+ * Execute hooks before agent invocation
76
+ * Returns new context entries to append and any notifications to send
77
+ */
78
+ async executeHooks(session) {
79
+ logger.info(`Executing hooks - found ${this.hooks.length} hook(s)`, {
80
+ hooks: this.hooks.map((h) => h.type),
81
+ contextEntries: session.context.length,
82
+ totalMessages: session.messages.length,
83
+ });
84
+ const newContextEntries = [];
85
+ const notifications = [];
86
+ for (const hook of this.hooks) {
87
+ if (hook.type === "context_size") {
88
+ const result = await this.executeContextSizeHook(hook, session);
89
+ if (result) {
90
+ notifications.push(...result.notifications);
91
+ if (result.newContextEntry) {
92
+ newContextEntries.push(result.newContextEntry);
93
+ }
94
+ }
95
+ }
96
+ }
97
+ return { newContextEntries, notifications };
98
+ }
99
+ /**
100
+ * Execute a context_size hook
101
+ */
102
+ async executeContextSizeHook(hook, session) {
103
+ // Resolve context to messages for token estimation
104
+ const resolvedMessages = resolveContextToMessages(session.context, session.messages);
105
+ const maxTokens = getModelMaxTokens(this.model);
106
+ const currentTokens = estimateTokens(resolvedMessages);
107
+ const percentage = (currentTokens / maxTokens) * 100;
108
+ // Default threshold is 95%
109
+ const threshold = hook.setting?.threshold ?? 95;
110
+ // Check if threshold exceeded
111
+ if (percentage < threshold) {
112
+ logger.info(`Context hook not triggered: ${currentTokens} tokens (${percentage.toFixed(1)}%) < threshold ${threshold}%`);
113
+ return null; // No action needed
114
+ }
115
+ logger.info(`Context hook triggered: ${currentTokens} tokens (${percentage.toFixed(1)}%) exceeds threshold ${threshold}%`);
116
+ const notifications = [];
117
+ // Notify that hook is triggered
118
+ notifications.push({
119
+ type: "hook_triggered",
120
+ hookType: "context_size",
121
+ threshold,
122
+ currentPercentage: percentage,
123
+ callback: hook.callback,
124
+ });
125
+ try {
126
+ // Load and execute callback
127
+ const callback = await this.loadCallback(hook.callback);
128
+ const hookContext = {
129
+ session,
130
+ currentTokens,
131
+ maxTokens,
132
+ percentage,
133
+ model: this.model,
134
+ };
135
+ const result = await callback(hookContext);
136
+ // Notify completion
137
+ notifications.push({
138
+ type: "hook_completed",
139
+ hookType: "context_size",
140
+ callback: hook.callback,
141
+ metadata: result.metadata,
142
+ });
143
+ return {
144
+ newContextEntry: result.newContextEntry,
145
+ notifications,
146
+ };
147
+ }
148
+ catch (error) {
149
+ // Notify error
150
+ notifications.push({
151
+ type: "hook_error",
152
+ hookType: "context_size",
153
+ callback: hook.callback,
154
+ error: error instanceof Error ? error.message : String(error),
155
+ });
156
+ // Return no context entry on error
157
+ return {
158
+ newContextEntry: null,
159
+ notifications,
160
+ };
161
+ }
162
+ }
163
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./constants";
2
+ export * from "./executor";
3
+ export * from "./loader";
4
+ export * from "./registry";
5
+ export * from "./types";
@@ -0,0 +1,5 @@
1
+ export * from "./constants";
2
+ export * from "./executor";
3
+ export * from "./loader";
4
+ export * from "./registry";
5
+ export * from "./types";
@@ -0,0 +1,5 @@
1
+ import type { HookCallback } from "./types";
2
+ /**
3
+ * Load a hook callback from either registry or custom file
4
+ */
5
+ export declare function loadHookCallback(callbackRef: string, agentDir?: string): Promise<HookCallback>;
@@ -0,0 +1,49 @@
1
+ import { resolve } from "node:path";
2
+ import { createLogger } from "@townco/core";
3
+ import { getPredefinedHook, isPredefinedHook } from "./registry";
4
+ const logger = createLogger("hook-loader");
5
+ /**
6
+ * Load a hook callback from either registry or custom file
7
+ */
8
+ export async function loadHookCallback(callbackRef, agentDir) {
9
+ // Check if it's a predefined hook
10
+ if (isPredefinedHook(callbackRef)) {
11
+ const hook = getPredefinedHook(callbackRef);
12
+ if (!hook) {
13
+ throw new Error(`Predefined hook "${callbackRef}" not found`);
14
+ }
15
+ return hook;
16
+ }
17
+ // It's a file path - load custom hook
18
+ if (!agentDir) {
19
+ throw new Error(`Cannot load custom hook "${callbackRef}" without agent directory`);
20
+ }
21
+ try {
22
+ // Resolve path relative to agent directory
23
+ const hookPath = resolve(agentDir, callbackRef);
24
+ logger.debug(`Loading custom hook from ${hookPath}`);
25
+ // Dynamic import the module
26
+ const module = await import(hookPath);
27
+ // Type guard to check if module is an object
28
+ if (typeof module !== "object" || module === null) {
29
+ throw new Error(`Hook module at "${hookPath}" must export an object`);
30
+ }
31
+ // Look for default export or named export
32
+ const moduleObj = module;
33
+ const callback = moduleObj.default || moduleObj.hookCallback || moduleObj.callback;
34
+ if (!callback) {
35
+ throw new Error(`Hook module at "${hookPath}" must export a default function or "hookCallback"`);
36
+ }
37
+ if (typeof callback !== "function") {
38
+ throw new Error(`Hook at "${hookPath}" must export a function, got ${typeof callback}`);
39
+ }
40
+ return callback;
41
+ }
42
+ catch (error) {
43
+ const errorData = typeof error === "object" && error !== null
44
+ ? error
45
+ : undefined;
46
+ logger.error(`Failed to load custom hook "${callbackRef}"`, errorData);
47
+ throw new Error(`Failed to load custom hook "${callbackRef}": ${error instanceof Error ? error.message : String(error)}`);
48
+ }
49
+ }
@@ -0,0 +1,6 @@
1
+ import { type HookCallback } from "../types";
2
+ /**
3
+ * Placeholder compaction tool for testing hooks
4
+ * Logs the context and returns null (no new context entry)
5
+ */
6
+ export declare const compactionTool: HookCallback;
@@ -0,0 +1,42 @@
1
+ import { createLogger } from "@townco/core";
2
+ import { createContextEntry, createFullMessageEntry, } from "../types";
3
+ const logger = createLogger("compaction-tool");
4
+ /**
5
+ * Placeholder compaction tool for testing hooks
6
+ * Logs the context and returns null (no new context entry)
7
+ */
8
+ export const compactionTool = async (ctx) => {
9
+ logger.info("Compaction tool triggered", {
10
+ currentTokens: ctx.currentTokens,
11
+ maxTokens: ctx.maxTokens,
12
+ percentage: ctx.percentage.toFixed(2) + "%",
13
+ contextEntries: ctx.session.context.length,
14
+ totalMessages: ctx.session.messages.length,
15
+ model: ctx.model,
16
+ });
17
+ // TODO: Implement actual compaction logic
18
+ // Example: Create a new context entry with a summary message
19
+ // const summaryEntry = createFullMessageEntry(
20
+ // "assistant",
21
+ // "Summary of previous conversation: ..."
22
+ // );
23
+ //
24
+ // const newContextEntry = createContextEntry([summaryEntry]);
25
+ //
26
+ // return {
27
+ // newContextEntry,
28
+ // metadata: {
29
+ // action: "compacted",
30
+ // messagesRemoved: ctx.session.messages.length - 1,
31
+ // tokensSaved: 1000,
32
+ // },
33
+ // };
34
+ // For now, just return null (no new context entry)
35
+ return {
36
+ newContextEntry: null,
37
+ metadata: {
38
+ action: "placeholder",
39
+ message: "Compaction tool called but no action taken (placeholder)",
40
+ },
41
+ };
42
+ };
@@ -0,0 +1,14 @@
1
+ import type { HookCallback } from "./types";
2
+ /**
3
+ * Registry of predefined hook callbacks
4
+ * Maps callback names to their implementations
5
+ */
6
+ export declare const HOOK_REGISTRY: Record<string, HookCallback>;
7
+ /**
8
+ * Check if a callback name is a predefined hook
9
+ */
10
+ export declare function isPredefinedHook(callback: string): boolean;
11
+ /**
12
+ * Get a predefined hook callback by name
13
+ */
14
+ export declare function getPredefinedHook(callback: string): HookCallback | undefined;
@@ -0,0 +1,20 @@
1
+ import { compactionTool } from "./predefined/compaction-tool";
2
+ /**
3
+ * Registry of predefined hook callbacks
4
+ * Maps callback names to their implementations
5
+ */
6
+ export const HOOK_REGISTRY = {
7
+ compaction_tool: compactionTool,
8
+ };
9
+ /**
10
+ * Check if a callback name is a predefined hook
11
+ */
12
+ export function isPredefinedHook(callback) {
13
+ return callback in HOOK_REGISTRY;
14
+ }
15
+ /**
16
+ * Get a predefined hook callback by name
17
+ */
18
+ export function getPredefinedHook(callback) {
19
+ return HOOK_REGISTRY[callback];
20
+ }
@@ -0,0 +1,144 @@
1
+ import type { ContextEntry } from "../../acp-server/session-storage";
2
+ import type { SessionMessage } from "../agent-runner";
3
+ /**
4
+ * Hook types supported by the agent system
5
+ */
6
+ export type HookType = "context_size";
7
+ /**
8
+ * Settings for context_size hook
9
+ */
10
+ export interface ContextSizeSettings {
11
+ /**
12
+ * Threshold as percentage (0-100) of model's max context window
13
+ */
14
+ threshold: number;
15
+ }
16
+ /**
17
+ * Hook configuration in agent definition
18
+ */
19
+ export interface HookConfig {
20
+ /**
21
+ * Type of hook to trigger
22
+ */
23
+ type: HookType;
24
+ /**
25
+ * Optional hook-specific settings
26
+ */
27
+ setting?: ContextSizeSettings | undefined;
28
+ /**
29
+ * Callback reference - either a predefined hook name or a file path
30
+ * Examples: "compaction_tool" or "./hooks/my_compaction_tool.ts"
31
+ */
32
+ callback: string;
33
+ }
34
+ /**
35
+ * Read-only view of an agent session for hooks
36
+ */
37
+ export interface ReadonlySession {
38
+ /**
39
+ * All session messages
40
+ */
41
+ readonly messages: ReadonlyArray<Readonly<SessionMessage>>;
42
+ /**
43
+ * Current context entries (time-based snapshots)
44
+ */
45
+ readonly context: ReadonlyArray<Readonly<ContextEntry>>;
46
+ /**
47
+ * Original request parameters
48
+ */
49
+ readonly requestParams: Readonly<Record<string, unknown>>;
50
+ }
51
+ /**
52
+ * Context passed to hook callbacks
53
+ */
54
+ export interface HookContext {
55
+ /**
56
+ * Read-only access to the full session
57
+ */
58
+ session: ReadonlySession;
59
+ /**
60
+ * Current context size in tokens
61
+ */
62
+ currentTokens: number;
63
+ /**
64
+ * Maximum context size for the model in tokens
65
+ */
66
+ maxTokens: number;
67
+ /**
68
+ * Percentage of context used (0-100)
69
+ */
70
+ percentage: number;
71
+ /**
72
+ * The model being used
73
+ */
74
+ model: string;
75
+ }
76
+ /**
77
+ * Result returned by hook callbacks
78
+ */
79
+ export interface HookResult {
80
+ /**
81
+ * New context entry to append to session.context
82
+ * If null, no context change is made
83
+ */
84
+ newContextEntry: ContextEntry | null;
85
+ /**
86
+ * Optional metadata about what the hook did
87
+ */
88
+ metadata?: {
89
+ action?: string;
90
+ messagesRemoved?: number;
91
+ tokensSaved?: number;
92
+ [key: string]: unknown;
93
+ };
94
+ }
95
+ /**
96
+ * Hook callback function signature
97
+ */
98
+ export type HookCallback = (context: HookContext) => Promise<HookResult>;
99
+ /**
100
+ * Helper function to create a new context entry
101
+ * Use this when hooks want to create a new context snapshot
102
+ */
103
+ export declare function createContextEntry(messages: Array<{
104
+ type: "pointer";
105
+ index: number;
106
+ } | {
107
+ type: "full";
108
+ message: SessionMessage;
109
+ }>, timestamp?: string): ContextEntry;
110
+ /**
111
+ * Helper function to create a full message entry for context
112
+ * Use this when hooks need to inject new messages into context
113
+ */
114
+ export declare function createFullMessageEntry(role: "user" | "assistant", text: string): {
115
+ type: "full";
116
+ message: SessionMessage;
117
+ };
118
+ /**
119
+ * Helper function to create a pointer entry for context
120
+ */
121
+ export declare function createPointerEntry(index: number): {
122
+ type: "pointer";
123
+ index: number;
124
+ };
125
+ /**
126
+ * Hook notification events for GUI/TUI
127
+ */
128
+ export type HookNotification = {
129
+ type: "hook_triggered";
130
+ hookType: HookType;
131
+ threshold: number;
132
+ currentPercentage: number;
133
+ callback: string;
134
+ } | {
135
+ type: "hook_completed";
136
+ hookType: HookType;
137
+ callback: string;
138
+ metadata?: HookResult["metadata"];
139
+ } | {
140
+ type: "hook_error";
141
+ hookType: HookType;
142
+ callback: string;
143
+ error: string;
144
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Helper function to create a new context entry
3
+ * Use this when hooks want to create a new context snapshot
4
+ */
5
+ export function createContextEntry(messages, timestamp) {
6
+ return {
7
+ timestamp: timestamp || new Date().toISOString(),
8
+ messages,
9
+ };
10
+ }
11
+ /**
12
+ * Helper function to create a full message entry for context
13
+ * Use this when hooks need to inject new messages into context
14
+ */
15
+ export function createFullMessageEntry(role, text) {
16
+ return {
17
+ type: "full",
18
+ message: {
19
+ role,
20
+ content: [{ type: "text", text }],
21
+ timestamp: new Date().toISOString(),
22
+ },
23
+ };
24
+ }
25
+ /**
26
+ * Helper function to create a pointer entry for context
27
+ */
28
+ export function createPointerEntry(index) {
29
+ return {
30
+ type: "pointer",
31
+ index,
32
+ };
33
+ }
@@ -1,4 +1,6 @@
1
1
  import type { AgentDefinition } from "../definition";
2
2
  import { type AgentRunner } from "./agent-runner";
3
3
  export type { AgentRunner };
4
- export declare const makeRunnerFromDefinition: (definition: AgentDefinition) => AgentRunner;
4
+ export declare const makeRunnerFromDefinition: (
5
+ definition: AgentDefinition,
6
+ ) => AgentRunner;