@poncho-ai/sdk 1.0.0 → 1.0.2

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @poncho-ai/sdk@1.0.0 build /home/runner/work/poncho-ai/poncho-ai/packages/sdk
2
+ > @poncho-ai/sdk@1.0.2 build /home/runner/work/poncho-ai/poncho-ai/packages/sdk
3
3
  > tsup src/index.ts --format esm --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -7,8 +7,8 @@
7
7
  CLI tsup v8.5.1
8
8
  CLI Target: es2022
9
9
  ESM Build start
10
- ESM dist/index.js 6.37 KB
11
- ESM ⚡️ Build success in 20ms
10
+ ESM dist/index.js 9.72 KB
11
+ ESM ⚡️ Build success in 17ms
12
12
  DTS Build start
13
- DTS ⚡️ Build success in 1218ms
14
- DTS dist/index.d.ts 13.27 KB
13
+ DTS ⚡️ Build success in 1275ms
14
+ DTS dist/index.d.ts 18.25 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @poncho-ai/sdk
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`e000b96`](https://github.com/cesr/poncho-ai/commit/e000b96837cbbb8d95c868c91a614f458868c444) Thanks [@cesr](https://github.com/cesr)! - Durable approval checkpoints, email conversation improvements, and web UI fixes
8
+ - Simplify approval system to checkpoint-only (remove legacy blocking approvalHandler)
9
+ - Optimize checkpoint storage with delta messages instead of full history
10
+ - Add sidebar sections for conversations awaiting approval with status indicator
11
+ - Fix nested checkpoint missing baseMessageCount in resumeRunFromCheckpoint
12
+ - Improve email conversation titles (sender email + subject)
13
+ - Remove email threading — each incoming email creates its own conversation
14
+ - Fix streaming after approval to preserve existing messages (liveOnly mode)
15
+ - Preserve newlines in user messages in web UI
16
+
17
+ ## 1.0.1
18
+
19
+ ### Patch Changes
20
+
21
+ - [#10](https://github.com/cesr/poncho-ai/pull/10) [`d5bce7b`](https://github.com/cesr/poncho-ai/commit/d5bce7be5890c657bea915eb0926feb6de66b218) Thanks [@cesr](https://github.com/cesr)! - Add generic messaging layer with Slack as the first adapter. Agents can now respond to @mentions in Slack by adding `messaging: [{ platform: 'slack' }]` to `poncho.config.js`. Includes signature verification, threaded conversations, processing indicators, and Vercel `waitUntil` support.
22
+
3
23
  ## 1.0.0
4
24
 
5
25
  ### Major Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  type OnboardingScope = "light" | "full";
2
- type FeatureDomain = "model" | "deploy" | "storage" | "memory" | "auth" | "telemetry" | "mcp";
2
+ type FeatureDomain = "model" | "deploy" | "storage" | "memory" | "auth" | "telemetry" | "mcp" | "messaging";
3
3
  type OnboardingFieldTarget = "agent" | "config" | "env";
4
4
  type OnboardingFieldKind = "select" | "boolean" | "string" | "number";
5
5
  type OnboardingFieldCondition = {
@@ -287,6 +287,140 @@ declare const ONBOARDING_FIELDS: readonly [{
287
287
  readonly fieldId: "telemetry.enabled";
288
288
  readonly equals: true;
289
289
  };
290
+ }, {
291
+ readonly id: "messaging.platform";
292
+ readonly domain: "messaging";
293
+ readonly target: "agent";
294
+ readonly path: "messaging.platform";
295
+ readonly kind: "select";
296
+ readonly scopes: ["full"];
297
+ readonly label: "Messaging platform";
298
+ readonly prompt: "Connect to a messaging platform? (optional)";
299
+ readonly defaultValue: "none";
300
+ readonly options: [{
301
+ readonly value: "none";
302
+ readonly label: "None";
303
+ }, {
304
+ readonly value: "slack";
305
+ readonly label: "Slack";
306
+ }, {
307
+ readonly value: "resend";
308
+ readonly label: "Email (Resend)";
309
+ }];
310
+ }, {
311
+ readonly id: "env.SLACK_BOT_TOKEN";
312
+ readonly domain: "messaging";
313
+ readonly target: "env";
314
+ readonly path: "SLACK_BOT_TOKEN";
315
+ readonly kind: "string";
316
+ readonly scopes: ["full"];
317
+ readonly label: "Slack Bot Token";
318
+ readonly prompt: "Slack Bot Token (from OAuth & Permissions)";
319
+ readonly defaultValue: "";
320
+ readonly placeholder: "xoxb-...";
321
+ readonly secret: true;
322
+ readonly dependsOn: {
323
+ readonly fieldId: "messaging.platform";
324
+ readonly equals: "slack";
325
+ };
326
+ }, {
327
+ readonly id: "env.SLACK_SIGNING_SECRET";
328
+ readonly domain: "messaging";
329
+ readonly target: "env";
330
+ readonly path: "SLACK_SIGNING_SECRET";
331
+ readonly kind: "string";
332
+ readonly scopes: ["full"];
333
+ readonly label: "Slack Signing Secret";
334
+ readonly prompt: "Slack Signing Secret (from Basic Information)";
335
+ readonly defaultValue: "";
336
+ readonly secret: true;
337
+ readonly dependsOn: {
338
+ readonly fieldId: "messaging.platform";
339
+ readonly equals: "slack";
340
+ };
341
+ }, {
342
+ readonly id: "env.RESEND_API_KEY";
343
+ readonly domain: "messaging";
344
+ readonly target: "env";
345
+ readonly path: "RESEND_API_KEY";
346
+ readonly kind: "string";
347
+ readonly scopes: ["full"];
348
+ readonly label: "Resend API Key";
349
+ readonly prompt: "Resend API Key (from resend.com/api-keys)";
350
+ readonly defaultValue: "";
351
+ readonly placeholder: "re_...";
352
+ readonly secret: true;
353
+ readonly dependsOn: {
354
+ readonly fieldId: "messaging.platform";
355
+ readonly equals: "resend";
356
+ };
357
+ }, {
358
+ readonly id: "env.RESEND_WEBHOOK_SECRET";
359
+ readonly domain: "messaging";
360
+ readonly target: "env";
361
+ readonly path: "RESEND_WEBHOOK_SECRET";
362
+ readonly kind: "string";
363
+ readonly scopes: ["full"];
364
+ readonly label: "Resend Webhook Secret";
365
+ readonly prompt: "Resend Webhook Signing Secret (from webhook details page)";
366
+ readonly defaultValue: "";
367
+ readonly placeholder: "whsec_...";
368
+ readonly secret: true;
369
+ readonly dependsOn: {
370
+ readonly fieldId: "messaging.platform";
371
+ readonly equals: "resend";
372
+ };
373
+ }, {
374
+ readonly id: "env.RESEND_FROM";
375
+ readonly domain: "messaging";
376
+ readonly target: "env";
377
+ readonly path: "RESEND_FROM";
378
+ readonly kind: "string";
379
+ readonly scopes: ["full"];
380
+ readonly label: "From Address";
381
+ readonly prompt: "Email address the agent sends from (e.g. Agent <agent@yourdomain.com>)";
382
+ readonly defaultValue: "";
383
+ readonly placeholder: "Agent <agent@yourdomain.com>";
384
+ readonly dependsOn: {
385
+ readonly fieldId: "messaging.platform";
386
+ readonly equals: "resend";
387
+ };
388
+ }, {
389
+ readonly id: "messaging.resend.mode";
390
+ readonly domain: "messaging";
391
+ readonly target: "agent";
392
+ readonly path: "messaging.resend.mode";
393
+ readonly kind: "select";
394
+ readonly scopes: ["full"];
395
+ readonly label: "Email response mode";
396
+ readonly prompt: "How should the agent respond to emails?";
397
+ readonly defaultValue: "auto-reply";
398
+ readonly options: [{
399
+ readonly value: "auto-reply";
400
+ readonly label: "Auto-reply (agent response sent as email reply)";
401
+ }, {
402
+ readonly value: "tool";
403
+ readonly label: "Tool (agent uses send_email tool for full control)";
404
+ }];
405
+ readonly dependsOn: {
406
+ readonly fieldId: "messaging.platform";
407
+ readonly equals: "resend";
408
+ };
409
+ }, {
410
+ readonly id: "messaging.resend.allowedRecipients";
411
+ readonly domain: "messaging";
412
+ readonly target: "agent";
413
+ readonly path: "messaging.resend.allowedRecipients";
414
+ readonly kind: "string";
415
+ readonly scopes: ["full"];
416
+ readonly label: "Allowed recipients";
417
+ readonly prompt: "Allowed recipient patterns for send_email tool (comma-separated, e.g. *@mycompany.com). Leave empty for no restrictions.";
418
+ readonly defaultValue: "";
419
+ readonly placeholder: "*@mycompany.com, partner@external.com";
420
+ readonly dependsOn: {
421
+ readonly fieldId: "messaging.resend.mode";
422
+ readonly equals: "tool";
423
+ };
290
424
  }];
291
425
  declare const FEATURE_DOMAIN_ORDER: readonly FeatureDomain[];
292
426
  declare const fieldsForScope: (scope: OnboardingScope) => OnboardingField[];
@@ -359,11 +493,13 @@ interface FileInput {
359
493
  filename?: string;
360
494
  }
361
495
  interface RunInput {
362
- task: string;
496
+ task?: string;
363
497
  parameters?: Record<string, unknown>;
364
498
  messages?: Message[];
365
499
  files?: FileInput[];
366
500
  abortSignal?: AbortSignal;
501
+ /** When set, Latitude telemetry groups all turns in this conversation under a single trace. */
502
+ conversationId?: string;
367
503
  }
368
504
  interface TokenUsage {
369
505
  input: number;
@@ -388,6 +524,7 @@ type AgentEvent = {
388
524
  type: "run:started";
389
525
  runId: string;
390
526
  agentId: string;
527
+ contextWindow?: number;
391
528
  } | {
392
529
  type: "run:completed";
393
530
  runId: string;
@@ -441,6 +578,18 @@ type AgentEvent = {
441
578
  type: "tool:approval:denied";
442
579
  approvalId: string;
443
580
  reason?: string;
581
+ } | {
582
+ type: "tool:approval:checkpoint";
583
+ approvalId: string;
584
+ tool: string;
585
+ toolCallId: string;
586
+ input: Record<string, unknown>;
587
+ checkpointMessages: Message[];
588
+ pendingToolCalls: Array<{
589
+ id: string;
590
+ name: string;
591
+ input: Record<string, unknown>;
592
+ }>;
444
593
  };
445
594
 
446
595
  export { type AgentEvent, type AgentFailure, type ContentPart, FEATURE_DOMAIN_ORDER, type FeatureDomain, type FileContentPart, type FileInput, type JsonSchema, type Message, ONBOARDING_FIELDS, type OnboardingField, type OnboardingFieldCondition, type OnboardingFieldKind, type OnboardingFieldTarget, type OnboardingOption, type OnboardingScope, type Role, type RunInput, type RunResult, type TextContentPart, type TokenUsage, type ToolContext, type ToolDefinition, type ToolHandler, defineTool, fieldsForScope, getTextContent };
package/dist/index.js CHANGED
@@ -220,6 +220,119 @@ var ONBOARDING_FIELDS = [
220
220
  prompt: "OTLP endpoint (optional)",
221
221
  defaultValue: "",
222
222
  dependsOn: { fieldId: "telemetry.enabled", equals: true }
223
+ },
224
+ {
225
+ id: "messaging.platform",
226
+ domain: "messaging",
227
+ target: "agent",
228
+ path: "messaging.platform",
229
+ kind: "select",
230
+ scopes: ["full"],
231
+ label: "Messaging platform",
232
+ prompt: "Connect to a messaging platform? (optional)",
233
+ defaultValue: "none",
234
+ options: [
235
+ { value: "none", label: "None" },
236
+ { value: "slack", label: "Slack" },
237
+ { value: "resend", label: "Email (Resend)" }
238
+ ]
239
+ },
240
+ {
241
+ id: "env.SLACK_BOT_TOKEN",
242
+ domain: "messaging",
243
+ target: "env",
244
+ path: "SLACK_BOT_TOKEN",
245
+ kind: "string",
246
+ scopes: ["full"],
247
+ label: "Slack Bot Token",
248
+ prompt: "Slack Bot Token (from OAuth & Permissions)",
249
+ defaultValue: "",
250
+ placeholder: "xoxb-...",
251
+ secret: true,
252
+ dependsOn: { fieldId: "messaging.platform", equals: "slack" }
253
+ },
254
+ {
255
+ id: "env.SLACK_SIGNING_SECRET",
256
+ domain: "messaging",
257
+ target: "env",
258
+ path: "SLACK_SIGNING_SECRET",
259
+ kind: "string",
260
+ scopes: ["full"],
261
+ label: "Slack Signing Secret",
262
+ prompt: "Slack Signing Secret (from Basic Information)",
263
+ defaultValue: "",
264
+ secret: true,
265
+ dependsOn: { fieldId: "messaging.platform", equals: "slack" }
266
+ },
267
+ {
268
+ id: "env.RESEND_API_KEY",
269
+ domain: "messaging",
270
+ target: "env",
271
+ path: "RESEND_API_KEY",
272
+ kind: "string",
273
+ scopes: ["full"],
274
+ label: "Resend API Key",
275
+ prompt: "Resend API Key (from resend.com/api-keys)",
276
+ defaultValue: "",
277
+ placeholder: "re_...",
278
+ secret: true,
279
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" }
280
+ },
281
+ {
282
+ id: "env.RESEND_WEBHOOK_SECRET",
283
+ domain: "messaging",
284
+ target: "env",
285
+ path: "RESEND_WEBHOOK_SECRET",
286
+ kind: "string",
287
+ scopes: ["full"],
288
+ label: "Resend Webhook Secret",
289
+ prompt: "Resend Webhook Signing Secret (from webhook details page)",
290
+ defaultValue: "",
291
+ placeholder: "whsec_...",
292
+ secret: true,
293
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" }
294
+ },
295
+ {
296
+ id: "env.RESEND_FROM",
297
+ domain: "messaging",
298
+ target: "env",
299
+ path: "RESEND_FROM",
300
+ kind: "string",
301
+ scopes: ["full"],
302
+ label: "From Address",
303
+ prompt: "Email address the agent sends from (e.g. Agent <agent@yourdomain.com>)",
304
+ defaultValue: "",
305
+ placeholder: "Agent <agent@yourdomain.com>",
306
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" }
307
+ },
308
+ {
309
+ id: "messaging.resend.mode",
310
+ domain: "messaging",
311
+ target: "agent",
312
+ path: "messaging.resend.mode",
313
+ kind: "select",
314
+ scopes: ["full"],
315
+ label: "Email response mode",
316
+ prompt: "How should the agent respond to emails?",
317
+ defaultValue: "auto-reply",
318
+ options: [
319
+ { value: "auto-reply", label: "Auto-reply (agent response sent as email reply)" },
320
+ { value: "tool", label: "Tool (agent uses send_email tool for full control)" }
321
+ ],
322
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" }
323
+ },
324
+ {
325
+ id: "messaging.resend.allowedRecipients",
326
+ domain: "messaging",
327
+ target: "agent",
328
+ path: "messaging.resend.allowedRecipients",
329
+ kind: "string",
330
+ scopes: ["full"],
331
+ label: "Allowed recipients",
332
+ prompt: "Allowed recipient patterns for send_email tool (comma-separated, e.g. *@mycompany.com). Leave empty for no restrictions.",
333
+ defaultValue: "",
334
+ placeholder: "*@mycompany.com, partner@external.com",
335
+ dependsOn: { fieldId: "messaging.resend.mode", equals: "tool" }
223
336
  }
224
337
  ];
225
338
  var FEATURE_DOMAIN_ORDER = [
@@ -229,7 +342,8 @@ var FEATURE_DOMAIN_ORDER = [
229
342
  "memory",
230
343
  "auth",
231
344
  "telemetry",
232
- "mcp"
345
+ "mcp",
346
+ "messaging"
233
347
  ];
234
348
  var fieldsForScope = (scope) => ONBOARDING_FIELDS.filter(
235
349
  (field) => field.scopes.includes(scope)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Core types and utilities for building Poncho skills",
5
5
  "repository": {
6
6
  "type": "git",
@@ -7,7 +7,8 @@ export type FeatureDomain =
7
7
  | "memory"
8
8
  | "auth"
9
9
  | "telemetry"
10
- | "mcp";
10
+ | "mcp"
11
+ | "messaging";
11
12
 
12
13
  export type OnboardingFieldTarget = "agent" | "config" | "env";
13
14
 
@@ -265,6 +266,119 @@ export const ONBOARDING_FIELDS = [
265
266
  defaultValue: "",
266
267
  dependsOn: { fieldId: "telemetry.enabled", equals: true },
267
268
  },
269
+ {
270
+ id: "messaging.platform",
271
+ domain: "messaging",
272
+ target: "agent",
273
+ path: "messaging.platform",
274
+ kind: "select",
275
+ scopes: ["full"],
276
+ label: "Messaging platform",
277
+ prompt: "Connect to a messaging platform? (optional)",
278
+ defaultValue: "none",
279
+ options: [
280
+ { value: "none", label: "None" },
281
+ { value: "slack", label: "Slack" },
282
+ { value: "resend", label: "Email (Resend)" },
283
+ ],
284
+ },
285
+ {
286
+ id: "env.SLACK_BOT_TOKEN",
287
+ domain: "messaging",
288
+ target: "env",
289
+ path: "SLACK_BOT_TOKEN",
290
+ kind: "string",
291
+ scopes: ["full"],
292
+ label: "Slack Bot Token",
293
+ prompt: "Slack Bot Token (from OAuth & Permissions)",
294
+ defaultValue: "",
295
+ placeholder: "xoxb-...",
296
+ secret: true,
297
+ dependsOn: { fieldId: "messaging.platform", equals: "slack" },
298
+ },
299
+ {
300
+ id: "env.SLACK_SIGNING_SECRET",
301
+ domain: "messaging",
302
+ target: "env",
303
+ path: "SLACK_SIGNING_SECRET",
304
+ kind: "string",
305
+ scopes: ["full"],
306
+ label: "Slack Signing Secret",
307
+ prompt: "Slack Signing Secret (from Basic Information)",
308
+ defaultValue: "",
309
+ secret: true,
310
+ dependsOn: { fieldId: "messaging.platform", equals: "slack" },
311
+ },
312
+ {
313
+ id: "env.RESEND_API_KEY",
314
+ domain: "messaging",
315
+ target: "env",
316
+ path: "RESEND_API_KEY",
317
+ kind: "string",
318
+ scopes: ["full"],
319
+ label: "Resend API Key",
320
+ prompt: "Resend API Key (from resend.com/api-keys)",
321
+ defaultValue: "",
322
+ placeholder: "re_...",
323
+ secret: true,
324
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" },
325
+ },
326
+ {
327
+ id: "env.RESEND_WEBHOOK_SECRET",
328
+ domain: "messaging",
329
+ target: "env",
330
+ path: "RESEND_WEBHOOK_SECRET",
331
+ kind: "string",
332
+ scopes: ["full"],
333
+ label: "Resend Webhook Secret",
334
+ prompt: "Resend Webhook Signing Secret (from webhook details page)",
335
+ defaultValue: "",
336
+ placeholder: "whsec_...",
337
+ secret: true,
338
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" },
339
+ },
340
+ {
341
+ id: "env.RESEND_FROM",
342
+ domain: "messaging",
343
+ target: "env",
344
+ path: "RESEND_FROM",
345
+ kind: "string",
346
+ scopes: ["full"],
347
+ label: "From Address",
348
+ prompt: "Email address the agent sends from (e.g. Agent <agent@yourdomain.com>)",
349
+ defaultValue: "",
350
+ placeholder: "Agent <agent@yourdomain.com>",
351
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" },
352
+ },
353
+ {
354
+ id: "messaging.resend.mode",
355
+ domain: "messaging",
356
+ target: "agent",
357
+ path: "messaging.resend.mode",
358
+ kind: "select",
359
+ scopes: ["full"],
360
+ label: "Email response mode",
361
+ prompt: "How should the agent respond to emails?",
362
+ defaultValue: "auto-reply",
363
+ options: [
364
+ { value: "auto-reply", label: "Auto-reply (agent response sent as email reply)" },
365
+ { value: "tool", label: "Tool (agent uses send_email tool for full control)" },
366
+ ],
367
+ dependsOn: { fieldId: "messaging.platform", equals: "resend" },
368
+ },
369
+ {
370
+ id: "messaging.resend.allowedRecipients",
371
+ domain: "messaging",
372
+ target: "agent",
373
+ path: "messaging.resend.allowedRecipients",
374
+ kind: "string",
375
+ scopes: ["full"],
376
+ label: "Allowed recipients",
377
+ prompt: "Allowed recipient patterns for send_email tool (comma-separated, e.g. *@mycompany.com). Leave empty for no restrictions.",
378
+ defaultValue: "",
379
+ placeholder: "*@mycompany.com, partner@external.com",
380
+ dependsOn: { fieldId: "messaging.resend.mode", equals: "tool" },
381
+ },
268
382
  ] as const satisfies readonly OnboardingField[];
269
383
 
270
384
  export const FEATURE_DOMAIN_ORDER: readonly FeatureDomain[] = [
@@ -275,6 +389,7 @@ export const FEATURE_DOMAIN_ORDER: readonly FeatureDomain[] = [
275
389
  "auth",
276
390
  "telemetry",
277
391
  "mcp",
392
+ "messaging",
278
393
  ] as const;
279
394
 
280
395
  export const fieldsForScope = (scope: OnboardingScope): OnboardingField[] =>
package/src/index.ts CHANGED
@@ -93,11 +93,13 @@ export interface FileInput {
93
93
  }
94
94
 
95
95
  export interface RunInput {
96
- task: string;
96
+ task?: string;
97
97
  parameters?: Record<string, unknown>;
98
98
  messages?: Message[];
99
99
  files?: FileInput[];
100
100
  abortSignal?: AbortSignal;
101
+ /** When set, Latitude telemetry groups all turns in this conversation under a single trace. */
102
+ conversationId?: string;
101
103
  }
102
104
 
103
105
  export interface TokenUsage {
@@ -123,7 +125,7 @@ export interface AgentFailure {
123
125
  }
124
126
 
125
127
  export type AgentEvent =
126
- | { type: "run:started"; runId: string; agentId: string }
128
+ | { type: "run:started"; runId: string; agentId: string; contextWindow?: number }
127
129
  | { type: "run:completed"; runId: string; result: RunResult }
128
130
  | { type: "run:cancelled"; runId: string }
129
131
  | { type: "run:error"; runId: string; error: AgentFailure }
@@ -142,4 +144,13 @@ export type AgentEvent =
142
144
  approvalId: string;
143
145
  }
144
146
  | { type: "tool:approval:granted"; approvalId: string }
145
- | { type: "tool:approval:denied"; approvalId: string; reason?: string };
147
+ | { type: "tool:approval:denied"; approvalId: string; reason?: string }
148
+ | {
149
+ type: "tool:approval:checkpoint";
150
+ approvalId: string;
151
+ tool: string;
152
+ toolCallId: string;
153
+ input: Record<string, unknown>;
154
+ checkpointMessages: Message[];
155
+ pendingToolCalls: Array<{ id: string; name: string; input: Record<string, unknown> }>;
156
+ };