@onkeiki/agents 0.1.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 (111) hide show
  1. package/dist/Alert.d.ts +56 -0
  2. package/dist/Alert.d.ts.map +1 -0
  3. package/dist/Alert.js +8 -0
  4. package/dist/Alert.js.map +1 -0
  5. package/dist/Entity.d.ts +158 -0
  6. package/dist/Entity.d.ts.map +1 -0
  7. package/dist/Entity.js +289 -0
  8. package/dist/Entity.js.map +1 -0
  9. package/dist/Kit.d.ts +138 -0
  10. package/dist/Kit.d.ts.map +1 -0
  11. package/dist/Kit.js +517 -0
  12. package/dist/Kit.js.map +1 -0
  13. package/dist/OpenApi.d.ts +151 -0
  14. package/dist/OpenApi.d.ts.map +1 -0
  15. package/dist/OpenApi.js +222 -0
  16. package/dist/OpenApi.js.map +1 -0
  17. package/dist/Plugin.d.ts +183 -0
  18. package/dist/Plugin.d.ts.map +1 -0
  19. package/dist/Plugin.js +10 -0
  20. package/dist/Plugin.js.map +1 -0
  21. package/dist/Server.d.ts +71 -0
  22. package/dist/Server.d.ts.map +1 -0
  23. package/dist/Server.js +476 -0
  24. package/dist/Server.js.map +1 -0
  25. package/dist/Tool.d.ts +86 -0
  26. package/dist/Tool.d.ts.map +1 -0
  27. package/dist/Tool.js +27 -0
  28. package/dist/Tool.js.map +1 -0
  29. package/dist/bundle.d.ts +17 -0
  30. package/dist/bundle.d.ts.map +1 -0
  31. package/dist/bundle.js +101 -0
  32. package/dist/bundle.js.map +1 -0
  33. package/dist/index.d.ts +19 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +18 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/services/Blackboard.d.ts +18 -0
  38. package/dist/services/Blackboard.d.ts.map +1 -0
  39. package/dist/services/Blackboard.js +4 -0
  40. package/dist/services/Blackboard.js.map +1 -0
  41. package/dist/services/Observability.d.ts +102 -0
  42. package/dist/services/Observability.d.ts.map +1 -0
  43. package/dist/services/Observability.js +238 -0
  44. package/dist/services/Observability.js.map +1 -0
  45. package/dist/services/Platform.d.ts +112 -0
  46. package/dist/services/Platform.d.ts.map +1 -0
  47. package/dist/services/Platform.js +13 -0
  48. package/dist/services/Platform.js.map +1 -0
  49. package/dist/services/PluginDb.d.ts +44 -0
  50. package/dist/services/PluginDb.d.ts.map +1 -0
  51. package/dist/services/PluginDb.js +5 -0
  52. package/dist/services/PluginDb.js.map +1 -0
  53. package/dist/services/Sandbox.d.ts +68 -0
  54. package/dist/services/Sandbox.d.ts.map +1 -0
  55. package/dist/services/Sandbox.js +4 -0
  56. package/dist/services/Sandbox.js.map +1 -0
  57. package/dist/services/Steering.d.ts +46 -0
  58. package/dist/services/Steering.d.ts.map +1 -0
  59. package/dist/services/Steering.js +4 -0
  60. package/dist/services/Steering.js.map +1 -0
  61. package/dist/services/Storage.d.ts +63 -0
  62. package/dist/services/Storage.d.ts.map +1 -0
  63. package/dist/services/Storage.js +13 -0
  64. package/dist/services/Storage.js.map +1 -0
  65. package/dist/services/Transport.d.ts +19 -0
  66. package/dist/services/Transport.d.ts.map +1 -0
  67. package/dist/services/Transport.js +4 -0
  68. package/dist/services/Transport.js.map +1 -0
  69. package/dist/services/index.d.ts +9 -0
  70. package/dist/services/index.d.ts.map +1 -0
  71. package/dist/services/index.js +9 -0
  72. package/dist/services/index.js.map +1 -0
  73. package/dist/types/config.d.ts +526 -0
  74. package/dist/types/config.d.ts.map +1 -0
  75. package/dist/types/config.js +2 -0
  76. package/dist/types/config.js.map +1 -0
  77. package/dist/types/index.d.ts +4 -0
  78. package/dist/types/index.d.ts.map +1 -0
  79. package/dist/types/index.js +4 -0
  80. package/dist/types/index.js.map +1 -0
  81. package/dist/types/message.d.ts +54 -0
  82. package/dist/types/message.d.ts.map +1 -0
  83. package/dist/types/message.js +47 -0
  84. package/dist/types/message.js.map +1 -0
  85. package/dist/types/user.d.ts +16 -0
  86. package/dist/types/user.d.ts.map +1 -0
  87. package/dist/types/user.js +14 -0
  88. package/dist/types/user.js.map +1 -0
  89. package/package.json +39 -0
  90. package/src/Alert.ts +51 -0
  91. package/src/Entity.ts +543 -0
  92. package/src/Kit.ts +705 -0
  93. package/src/OpenApi.ts +343 -0
  94. package/src/Plugin.ts +209 -0
  95. package/src/Server.ts +618 -0
  96. package/src/Tool.ts +110 -0
  97. package/src/bundle.ts +114 -0
  98. package/src/index.ts +209 -0
  99. package/src/services/Blackboard.ts +19 -0
  100. package/src/services/Observability.ts +320 -0
  101. package/src/services/Platform.ts +125 -0
  102. package/src/services/PluginDb.ts +48 -0
  103. package/src/services/Sandbox.ts +74 -0
  104. package/src/services/Steering.ts +45 -0
  105. package/src/services/Storage.ts +76 -0
  106. package/src/services/Transport.ts +21 -0
  107. package/src/services/index.ts +8 -0
  108. package/src/types/config.ts +531 -0
  109. package/src/types/index.ts +3 -0
  110. package/src/types/message.ts +60 -0
  111. package/src/types/user.ts +17 -0
package/src/Tool.ts ADDED
@@ -0,0 +1,110 @@
1
+ import { Effect, Schema } from 'effect'
2
+ import { fileURLToPath } from 'node:url'
3
+ import type { UserProfile } from './types/index.js'
4
+ import type { BlackboardService } from './services/Blackboard.js'
5
+ import type { PlatformService } from './services/Platform.js'
6
+ import type { PluginDbService } from './services/PluginDb.js'
7
+ import type { SandboxHandle } from './services/Sandbox.js'
8
+ import type { EntityStore } from './Entity.js'
9
+
10
+ /**
11
+ * Per-user KV state backed by a Rivet UserState actor.
12
+ * One instance per (apiKey, phone) pair.
13
+ */
14
+ export interface UserStateService {
15
+ readonly get: (key: string) => Effect.Effect<unknown>
16
+ readonly set: (key: string, value: unknown) => Effect.Effect<void>
17
+ readonly delete: (key: string) => Effect.Effect<boolean>
18
+ readonly getAll: () => Effect.Effect<Record<string, unknown>>
19
+ readonly setMany: (entries: Record<string, unknown>) => Effect.Effect<void>
20
+ }
21
+
22
+ /**
23
+ * Developer secrets — encrypted KV stored on the platform.
24
+ * Synced via kit.sync() and accessible at runtime.
25
+ */
26
+ export interface SecretsService {
27
+ readonly get: (name: string) => Effect.Effect<string | null>
28
+ readonly getAll: () => Effect.Effect<Record<string, string>>
29
+ }
30
+
31
+ /**
32
+ * Where the turn calling a tool came from: the channel plus the provider ids
33
+ * naming the sender and the thread. Flat so it reads the same on a trace and in
34
+ * a tool. `userId` is the sender in the channel's own terms — a Slack user id,
35
+ * an email address, a phone number, a Telegram chat id.
36
+ */
37
+ export type ChannelEnvelope = {
38
+ readonly channel: 'sms' | 'telegram' | 'whatsapp' | 'xchat' | 'slack' | 'agentmail' | 'api' | 'agent' | 'synthetic'
39
+ /** Text of the messages a person sent this turn, joined; platform notices excluded. */
40
+ readonly inboundText: string
41
+ /** Provider id of the last inbound message (Slack `ts`, email `message_id`, …). */
42
+ readonly messageId?: string
43
+ readonly userId?: string
44
+ readonly teamId?: string
45
+ readonly channelId?: string
46
+ readonly threadTs?: string
47
+ readonly threadId?: string
48
+ readonly inboxId?: string
49
+ /** WhatsApp: Meta's phone number id the conversation runs on. */
50
+ readonly phoneNumberId?: string
51
+ /** X Chat: the canonical conversation id. */
52
+ readonly chatConversationId?: string
53
+ /** `ask_agent`: the agent asking. */
54
+ readonly fromAgentId?: string
55
+ }
56
+
57
+ export type ToolContext = {
58
+ readonly phone: string
59
+ readonly user: UserProfile
60
+ /** Set when the tool runs on the platform for a turn; absent in a local runtime. */
61
+ readonly channel?: ChannelEnvelope
62
+ readonly blackboard: BlackboardService
63
+ readonly platform: PlatformService
64
+ readonly userState: UserStateService
65
+ readonly secrets: SecretsService
66
+ readonly db: PluginDbService
67
+ /**
68
+ * Entity persistence bridge for cloud (actor) execution, where `db` is not
69
+ * reachable. Entity helpers use `contextEntityStore(ctx)`, which prefers
70
+ * this and falls back to SQL over `db`.
71
+ */
72
+ readonly entityStore?: EntityStore
73
+ readonly sandbox: SandboxHandle
74
+ }
75
+
76
+ export type ToolDefinition<I = unknown, O = unknown> = {
77
+ readonly name: string
78
+ readonly description: string
79
+ readonly input: Schema.Schema<I>
80
+ readonly execute: (input: I, ctx: ToolContext) => Effect.Effect<O>
81
+ /**
82
+ * Absolute path to the module that defined this tool. Captured automatically
83
+ * by {@link defineTool} so `kit.sync()` can bundle the tool into a standalone
84
+ * actor artifact. Not set by hand.
85
+ */
86
+ readonly sourceFile?: string
87
+ }
88
+
89
+ /**
90
+ * Define a type-safe tool for your agent.
91
+ */
92
+ export function defineTool<I, O>(def: ToolDefinition<I, O>): ToolDefinition<I, O> {
93
+ return { ...def, sourceFile: def.sourceFile ?? captureSourceFile() }
94
+ }
95
+
96
+ const THIS_FILE = import.meta.url
97
+
98
+ function captureSourceFile(): string | undefined {
99
+ const stack = new Error().stack
100
+ if (!stack) return undefined
101
+ for (const line of stack.split('\n').slice(1)) {
102
+ const match = line.match(/(?:\(|@|\s)((?:file:\/\/)?\/[^\s()]+?\.[cm]?[jt]sx?):\d+:\d+/)
103
+ if (!match) continue
104
+ let file = match[1]!
105
+ if (file.startsWith('file://')) file = fileURLToPath(file)
106
+ if (file === fileURLToPath(THIS_FILE)) continue
107
+ return file
108
+ }
109
+ return undefined
110
+ }
package/src/bundle.ts ADDED
@@ -0,0 +1,114 @@
1
+ import { writeFile, rm } from 'node:fs/promises'
2
+ import { dirname, join } from 'node:path'
3
+ import { randomUUID } from 'node:crypto'
4
+ import type { ToolDefinition } from './Tool.js'
5
+
6
+ /**
7
+ * Bundle a single tool into a standalone, dependency-free ESM artifact that the
8
+ * platform deploys and runs as a per-tool actor.
9
+ *
10
+ * The artifact exports `__run(input, host)`:
11
+ * - `input` — raw tool arguments (validated against the tool's Schema here)
12
+ * - `host` — actor-provided bridge: `{ phone, user, channel, userState, secrets, entities }`
13
+ * with async methods backed by the platform's Rivet UserState
14
+ * actor, developer secrets, and entity storage.
15
+ *
16
+ * Bundling requires Bun (developers run `kit.sync()` under Bun) and the tool's
17
+ * captured `sourceFile`, since `execute` is a live closure that imports helpers
18
+ * and cannot be serialized from the tool object alone.
19
+ */
20
+ export async function bundleTool(tool: ToolDefinition): Promise<string> {
21
+ const bun = (globalThis as { Bun?: { build: (opts: unknown) => Promise<BunBuildOutput> } }).Bun
22
+ if (!bun) {
23
+ throw new Error(
24
+ `kit.sync() must run under Bun to bundle tool "${tool.name}" into an actor artifact.`
25
+ )
26
+ }
27
+ if (!tool.sourceFile) {
28
+ throw new Error(
29
+ `Cannot bundle tool "${tool.name}": its source file was not captured. ` +
30
+ `Define it with defineTool() from '@onkeiki/agents'.`
31
+ )
32
+ }
33
+
34
+ const entryDir = dirname(tool.sourceFile)
35
+ const entryPath = join(entryDir, `.smskit-actor-${sanitize(tool.name)}-${randomUUID()}.mjs`)
36
+
37
+ await writeFile(entryPath, buildEntrySource(tool.name, tool.sourceFile), 'utf8')
38
+ try {
39
+ const built = await bun.build({
40
+ entrypoints: [entryPath],
41
+ target: 'node',
42
+ format: 'esm',
43
+ minify: true,
44
+ })
45
+ if (!built.success) {
46
+ const detail = built.logs.map((l) => String(l)).join('\n')
47
+ throw new Error(`Failed to bundle tool "${tool.name}":\n${detail}`)
48
+ }
49
+ const output = built.outputs[0]
50
+ if (!output) throw new Error(`Bundling tool "${tool.name}" produced no output`)
51
+ return await output.text()
52
+ } finally {
53
+ await rm(entryPath, { force: true })
54
+ }
55
+ }
56
+
57
+ function buildEntrySource(toolName: string, sourceFile: string): string {
58
+ const name = JSON.stringify(toolName)
59
+ const source = JSON.stringify(sourceFile)
60
+ return `import { Effect, Schema } from 'effect'
61
+ import * as __mod from ${source}
62
+
63
+ const __toolName = ${name}
64
+ const __isTool = (t) => t && typeof t === 'object' && typeof t.execute === 'function' && t.name === __toolName
65
+ const __exports = Object.values(__mod)
66
+ const __tool =
67
+ __exports.find(__isTool)
68
+ ?? __exports.flatMap((e) => (e && typeof e === 'object' && Array.isArray(e.tools) ? e.tools : [])).find(__isTool)
69
+ if (!__tool) throw new Error('Tool ' + __toolName + ' not found in ' + ${source})
70
+
71
+ const fromPromise = (run) => Effect.tryPromise({ try: run, catch: (e) => e })
72
+
73
+ function buildContext(host) {
74
+ const unavailable = (what) => {
75
+ throw new Error(what + ' is not available in actor tool execution')
76
+ }
77
+ return {
78
+ phone: host.phone,
79
+ user: host.user,
80
+ channel: host.channel,
81
+ get blackboard() { return unavailable('ctx.blackboard') },
82
+ get platform() { return unavailable('ctx.platform') },
83
+ userState: {
84
+ get: (k) => fromPromise(() => host.userState.get(k)),
85
+ set: (k, v) => fromPromise(() => host.userState.set(k, v)),
86
+ delete: (k) => fromPromise(() => host.userState.delete(k)),
87
+ getAll: () => fromPromise(() => host.userState.getAll()),
88
+ setMany: (e) => fromPromise(() => host.userState.setMany(e)),
89
+ },
90
+ secrets: {
91
+ get: (n) => fromPromise(() => host.secrets.get(n)),
92
+ getAll: () => fromPromise(() => host.secrets.getAll()),
93
+ },
94
+ get db() { return unavailable('ctx.db (use entity helpers, which route through ctx.entityStore)') },
95
+ entityStore: host.entities,
96
+ }
97
+ }
98
+
99
+ export async function __run(input, host) {
100
+ const decoded = Schema.decodeUnknownSync(__tool.input)(input)
101
+ return await Effect.runPromise(__tool.execute(decoded, buildContext(host)))
102
+ }
103
+ `
104
+ }
105
+
106
+ function sanitize(name: string): string {
107
+ return name.replace(/[^a-zA-Z0-9_-]/g, '_')
108
+ }
109
+
110
+ type BunBuildOutput = {
111
+ success: boolean
112
+ logs: unknown[]
113
+ outputs: Array<{ text: () => Promise<string> }>
114
+ }
package/src/index.ts ADDED
@@ -0,0 +1,209 @@
1
+ // Main entry point for @onkeiki/agents
2
+ export {
3
+ AgentKit,
4
+ SmsKit,
5
+ create,
6
+ type ResolvedPlugins,
7
+ type AgentKitInstance,
8
+ type SmsKitInstance,
9
+ } from './Kit.js'
10
+ export {
11
+ defineTool,
12
+ type ToolDefinition,
13
+ type ToolContext,
14
+ type ChannelEnvelope,
15
+ type UserStateService,
16
+ type SecretsService,
17
+ } from './Tool.js'
18
+ export {
19
+ defineAlert,
20
+ type AlertDefinition,
21
+ type AlertSchedule,
22
+ type AlertContent,
23
+ type AlertContext,
24
+ type AlertMedia,
25
+ type AlertMessage,
26
+ type AlertStateService,
27
+ } from './Alert.js'
28
+ export {
29
+ defineEntity,
30
+ entityMigrations,
31
+ entityTools,
32
+ createEntityDb,
33
+ contextEntityStore,
34
+ sqlEntityStore,
35
+ EntityError,
36
+ type EntityStore,
37
+ type EntityStoreRow,
38
+ type EntityDefinition,
39
+ type EntityRow,
40
+ type EntityAccessor,
41
+ type EntityDb,
42
+ } from './Entity.js'
43
+ export {
44
+ definePlugin,
45
+ type AgentKitPlugin,
46
+ type SmsKitPlugin,
47
+ type Plugin,
48
+ type TurnEvent,
49
+ type TurnResult,
50
+ type ToolCallEvent,
51
+ type ToolCallResult,
52
+ type RouteContext,
53
+ type PluginContext,
54
+ type SyncPayload,
55
+ type PluginInitResult,
56
+ } from './Plugin.js'
57
+ export {
58
+ oauthOpenApiSpec,
59
+ googleOpenApiSpec,
60
+ microsoftOpenApiSpec,
61
+ OpenApiSpecError,
62
+ GOOGLE_AUTHORIZATION_URL,
63
+ GOOGLE_TOKEN_URL,
64
+ MICROSOFT_AUTHORIZATION_URL,
65
+ MICROSOFT_TOKEN_URL,
66
+ type OpenApiMethod,
67
+ type OpenApiOperation,
68
+ type OpenApiParameter,
69
+ type OpenApiParameterRef,
70
+ type OAuthOpenApiSpec,
71
+ type OAuthOpenApiSpecInput,
72
+ } from './OpenApi.js'
73
+ export {
74
+ createServer,
75
+ executeAlert,
76
+ type TurnRequest,
77
+ type TurnResponse,
78
+ type AlertDelivery,
79
+ type AlertExecuteBody,
80
+ } from './Server.js'
81
+
82
+ // Services (for advanced use / custom adapters)
83
+ export {
84
+ Storage,
85
+ StorageError,
86
+ type StorageService,
87
+ type NewMessage,
88
+ type DeliveryClaim,
89
+ type UsageEvent,
90
+ type BillingPeriod,
91
+ type UsageSummary,
92
+ } from './services/Storage.js'
93
+
94
+ export {
95
+ Transport,
96
+ type TransportService,
97
+ } from './services/Transport.js'
98
+
99
+ export {
100
+ Platform,
101
+ PlatformError,
102
+ type PlatformService,
103
+ type MemoryFact,
104
+ type BrowseResult,
105
+ type SandboxExecResult,
106
+ type HandoffResult,
107
+ type EscalationResult,
108
+ type BackgroundJobResult,
109
+ } from './services/Platform.js'
110
+
111
+ export {
112
+ Steering,
113
+ type SteeringService,
114
+ type SteeringDecision,
115
+ type TurnState,
116
+ } from './services/Steering.js'
117
+
118
+ export {
119
+ Blackboard,
120
+ type BlackboardService,
121
+ } from './services/Blackboard.js'
122
+
123
+ export {
124
+ Observability,
125
+ ObservabilityError,
126
+ braintrustExporter,
127
+ axiomExporter,
128
+ otelExporter,
129
+ customExporter,
130
+ type TraceExporter,
131
+ type TraceEvent,
132
+ type SpanEvent,
133
+ type SpanKind,
134
+ type SpanStatus,
135
+ } from './services/Observability.js'
136
+
137
+ export {
138
+ SandboxProvider,
139
+ type SandboxProviderService,
140
+ type SandboxHandle,
141
+ } from './services/Sandbox.js'
142
+
143
+ export {
144
+ PluginDb,
145
+ type PluginDbService,
146
+ type PluginMigration,
147
+ } from './services/PluginDb.js'
148
+
149
+ // Types
150
+ export type {
151
+ AgentKitConfig,
152
+ SmsKitConfig,
153
+ AgentConfig,
154
+ MemoryConfig,
155
+ BrowserConfig,
156
+ SandboxConfig,
157
+ ExecutorConfig,
158
+ SteeringConfig,
159
+ MediaConfig,
160
+ MediaActionConfig,
161
+ EscalationConfig,
162
+ EscalationRoute,
163
+ EventHandlers,
164
+ ObservabilityConfig,
165
+ PromptContext,
166
+ TurnHooks,
167
+ TurnHookState,
168
+ TurnReviewState,
169
+ RetrievedContext,
170
+ ResolveNumberContext,
171
+ AcquireLineOpts,
172
+ PhoneLine,
173
+ DurationInput,
174
+ HarnessConfig,
175
+ StorageBundle,
176
+ ChannelType,
177
+ ChannelConfig,
178
+ SmsChannelConfig,
179
+ TelegramChannelConfig,
180
+ CapabilityRef,
181
+ CapabilityManifest,
182
+ CapabilityRuntime,
183
+ CapabilityNamespace,
184
+ CapabilitySecret,
185
+ CapabilityField,
186
+ CapabilityTool,
187
+ CapabilityToolRun,
188
+ CapabilityTemplate,
189
+ CapabilityEntity,
190
+ CapabilityLoop,
191
+ CapabilityLoopProbe,
192
+ CapabilityLoopTrigger,
193
+ CapabilityInput,
194
+ } from './types/config.js'
195
+
196
+ export type {
197
+ InboundMessage,
198
+ OutboundMessage,
199
+ StoredMessage,
200
+ MediaPayload,
201
+ SendResult,
202
+ DeliveryStatus,
203
+ Direction,
204
+ } from './types/message.js'
205
+
206
+ export type {
207
+ UserProfile,
208
+ Subscriber,
209
+ } from './types/user.js'
@@ -0,0 +1,19 @@
1
+ import { Context, Effect } from 'effect'
2
+
3
+ /**
4
+ * Cross-step key-value scratchpad within a single turn.
5
+ * Tools can read/write state that persists across tool steps
6
+ * but is cleared when the turn ends.
7
+ */
8
+ export interface BlackboardService {
9
+ readonly read: (key: string) => Effect.Effect<unknown | null>
10
+ readonly write: (key: string, value: unknown) => Effect.Effect<void>
11
+ readonly delete: (key: string) => Effect.Effect<void>
12
+ readonly entries: () => Effect.Effect<ReadonlyArray<[string, unknown]>>
13
+ readonly clear: () => Effect.Effect<void>
14
+ }
15
+
16
+ export class Blackboard extends Context.Tag('@onkeiki/agents/Blackboard')<
17
+ Blackboard,
18
+ BlackboardService
19
+ >() {}