@poncho-ai/cli 0.36.9 → 0.37.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @poncho-ai/cli@0.36.9 build /home/runner/work/poncho-ai/poncho-ai/packages/cli
2
+ > @poncho-ai/cli@0.37.0 build /home/runner/work/poncho-ai/poncho-ai/packages/cli
3
3
  > tsup src/index.ts src/cli.ts --format esm --dts
4
4
 
5
5
  CLI Building entry: src/cli.ts, src/index.ts
@@ -9,10 +9,10 @@
9
9
  ESM Build start
10
10
  ESM dist/cli.js 94.00 B
11
11
  ESM dist/index.js 917.00 B
12
- ESM dist/run-interactive-ink-KDWRD7FT.js 56.86 KB
13
- ESM dist/chunk-IZLDZWPA.js 572.09 KB
14
- ESM ⚡️ Build success in 69ms
12
+ ESM dist/run-interactive-ink-75GKYSEC.js 56.86 KB
13
+ ESM dist/chunk-GUGBKAIM.js 572.60 KB
14
+ ESM ⚡️ Build success in 68ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 4212ms
16
+ DTS ⚡️ Build success in 4119ms
17
17
  DTS dist/cli.d.ts 20.00 B
18
18
  DTS dist/index.d.ts 7.07 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @poncho-ai/cli
2
2
 
3
+ ## 0.37.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`620a0c8`](https://github.com/cesr/poncho-ai/commit/620a0c89efaafce28968fca5cbde2e2b19bd1595) Thanks [@cesr](https://github.com/cesr)! - feat: add recurrent reminders (daily, weekly, monthly, cron)
8
+
9
+ The `set_reminder` tool now accepts an optional `recurrence` parameter that makes reminders repeat on a schedule instead of firing once. Supports daily, weekly (with specific days-of-week), monthly, and cron expressions. Recurring reminders are rescheduled after each firing and can be bounded by `maxOccurrences` or `endsAt`. Cancel a recurring reminder to stop all future occurrences.
10
+
11
+ ### Patch Changes
12
+
13
+ - [`6486de2`](https://github.com/cesr/poncho-ai/commit/6486de2242a2976068e4bd09f7c0f2d978c35c96) Thanks [@cesr](https://github.com/cesr)! - fix: persist subagent `parentConversationId` atomically so children never appear top-level in the sidebar.
14
+
15
+ `SubagentManager.spawn` previously did a two-step write: `conversationStore.create(...)` followed by `conversationStore.update(...)` to attach `parentConversationId`, `subagentMeta`, and the initial user message. If the follow-up update was interrupted (serverless timeout, transient DB error), the child row was left in the database with `parent_conversation_id = NULL`, so it slipped past the `!c.parentConversationId` filter on `/api/conversations` and showed up as a top-level conversation. This was especially visible with cron-driven research subagents.
16
+
17
+ `ConversationStore.create` now accepts an optional `init` bag (`parentConversationId`, `subagentMeta`, `messages`, `channelMeta`) that is written in the single INSERT — both into the `data` blob and into the dedicated `parent_conversation_id` column. `spawn` passes those fields through and drops the redundant update, eliminating the orphan window. All existing `create(ownerId, title, tenantId)` callers keep working since `init` is optional.
18
+
19
+ - Updated dependencies [[`6486de2`](https://github.com/cesr/poncho-ai/commit/6486de2242a2976068e4bd09f7c0f2d978c35c96), [`0d0578f`](https://github.com/cesr/poncho-ai/commit/0d0578fbc97a3d2644c4e22cab14ff02a79f805f), [`620a0c8`](https://github.com/cesr/poncho-ai/commit/620a0c89efaafce28968fca5cbde2e2b19bd1595)]:
20
+ - @poncho-ai/harness@0.38.0
21
+
3
22
  ## 0.36.9
4
23
 
5
24
  ### Patch Changes
@@ -22,7 +22,8 @@ import {
22
22
  parseAgentMarkdown,
23
23
  resolveStateConfig,
24
24
  verifyTenantToken,
25
- createSecretsStore
25
+ createSecretsStore,
26
+ computeNextOccurrence
26
27
  } from "@poncho-ai/harness";
27
28
  import { getTextContent } from "@poncho-ai/sdk";
28
29
  import {
@@ -10612,12 +10613,16 @@ ${resultBody}`,
10612
10613
  if (getRunningSubagentCountForParent(opts.parentConversationId) >= MAX_CONCURRENT_SUBAGENTS) {
10613
10614
  throw new Error(`Maximum concurrent subagents (${MAX_CONCURRENT_SUBAGENTS}) per parent reached. Wait for running subagents to complete or stop some first.`);
10614
10615
  }
10615
- const conversation = await conversationStore.create(opts.ownerId, opts.task.slice(0, 80), opts.tenantId ?? null);
10616
- conversation.parentConversationId = opts.parentConversationId;
10617
- conversation.subagentMeta = { task: opts.task, status: "running" };
10618
- conversation.messages = [{ role: "user", content: opts.task }];
10619
- conversation.updatedAt = Date.now();
10620
- await conversationStore.update(conversation);
10616
+ const conversation = await conversationStore.create(
10617
+ opts.ownerId,
10618
+ opts.task.slice(0, 80),
10619
+ opts.tenantId ?? null,
10620
+ {
10621
+ parentConversationId: opts.parentConversationId,
10622
+ subagentMeta: { task: opts.task, status: "running" },
10623
+ messages: [{ role: "user", content: opts.task }]
10624
+ }
10625
+ );
10621
10626
  recentlySpawnedParents.set(
10622
10627
  opts.parentConversationId,
10623
10628
  (recentlySpawnedParents.get(opts.parentConversationId) ?? 0) + 1
@@ -13594,13 +13599,24 @@ ${cronJob.task}`;
13594
13599
  const due = reminders.filter((r) => r.status === "pending" && r.scheduledAt <= cutoff);
13595
13600
  for (const reminder of due) {
13596
13601
  try {
13597
- await reminderStore.delete(reminder.id);
13602
+ const nextScheduledAt = computeNextOccurrence(reminder);
13603
+ if (nextScheduledAt) {
13604
+ await reminderStore.update(reminder.id, {
13605
+ scheduledAt: nextScheduledAt,
13606
+ occurrenceCount: (reminder.occurrenceCount ?? 0) + 1
13607
+ });
13608
+ } else {
13609
+ await reminderStore.delete(reminder.id);
13610
+ }
13598
13611
  const originConv = reminder.conversationId ? await conversationStore.get(reminder.conversationId) : void 0;
13599
13612
  const channelMeta = originConv?.channelMeta;
13613
+ const isRecurring = !!reminder.recurrence;
13614
+ const recurrenceNote = isRecurring && nextScheduledAt ? `
13615
+ Next occurrence: ${new Date(nextScheduledAt).toISOString()}` : isRecurring ? "\nThis was the final occurrence." : "";
13600
13616
  const framedMessage = `[Reminder] A reminder you previously set has fired.
13601
13617
  Task: "${reminder.task}"
13602
13618
  Originally set at: ${new Date(reminder.createdAt).toISOString()}
13603
- Scheduled for: ${new Date(reminder.scheduledAt).toISOString()}`;
13619
+ Scheduled for: ${new Date(reminder.scheduledAt).toISOString()}` + recurrenceNote;
13604
13620
  if (channelMeta) {
13605
13621
  const adapter = messagingAdapters.get(channelMeta.platform);
13606
13622
  if (adapter && originConv) {
@@ -14048,7 +14064,7 @@ var runInteractive = async (workingDir, params) => {
14048
14064
  await harness.initialize();
14049
14065
  const identity = await ensureAgentIdentity2(workingDir);
14050
14066
  try {
14051
- const { runInteractiveInk } = await import("./run-interactive-ink-KDWRD7FT.js");
14067
+ const { runInteractiveInk } = await import("./run-interactive-ink-75GKYSEC.js");
14052
14068
  await runInteractiveInk({
14053
14069
  harness,
14054
14070
  params,
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  main
4
- } from "./chunk-IZLDZWPA.js";
4
+ } from "./chunk-GUGBKAIM.js";
5
5
 
6
6
  // src/cli.ts
7
7
  void main();
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  runTests,
25
25
  startDevServer,
26
26
  updateAgentGuidance
27
- } from "./chunk-IZLDZWPA.js";
27
+ } from "./chunk-GUGBKAIM.js";
28
28
  export {
29
29
  __internalRunOrchestration,
30
30
  addSkill,
@@ -2,7 +2,7 @@ import {
2
2
  consumeFirstRunIntro,
3
3
  inferConversationTitle,
4
4
  resolveHarnessEnvironment
5
- } from "./chunk-IZLDZWPA.js";
5
+ } from "./chunk-GUGBKAIM.js";
6
6
 
7
7
  // src/run-interactive-ink.ts
8
8
  import * as readline from "readline";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/cli",
3
- "version": "0.36.9",
3
+ "version": "0.37.0",
4
4
  "description": "CLI for building and deploying AI agents",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,8 +28,8 @@
28
28
  "react": "^19.2.4",
29
29
  "react-devtools-core": "^6.1.5",
30
30
  "yaml": "^2.8.1",
31
+ "@poncho-ai/harness": "0.38.0",
31
32
  "@poncho-ai/messaging": "0.8.3",
32
- "@poncho-ai/harness": "0.37.2",
33
33
  "@poncho-ai/sdk": "1.8.1"
34
34
  },
35
35
  "devDependencies": {
package/src/index.ts CHANGED
@@ -35,6 +35,7 @@ import {
35
35
  type UploadStore,
36
36
  verifyTenantToken,
37
37
  createSecretsStore,
38
+ computeNextOccurrence,
38
39
  } from "@poncho-ai/harness";
39
40
  import type { AgentEvent, FileInput, Message, RunInput } from "@poncho-ai/sdk";
40
41
  import { getTextContent } from "@poncho-ai/sdk";
@@ -3110,12 +3111,19 @@ export const createRequestHandler = async (options?: {
3110
3111
  throw new Error(`Maximum concurrent subagents (${MAX_CONCURRENT_SUBAGENTS}) per parent reached. Wait for running subagents to complete or stop some first.`);
3111
3112
  }
3112
3113
 
3113
- const conversation = await conversationStore.create(opts.ownerId, opts.task.slice(0, 80), opts.tenantId ?? null);
3114
- conversation.parentConversationId = opts.parentConversationId;
3115
- conversation.subagentMeta = { task: opts.task, status: "running" };
3116
- conversation.messages = [{ role: "user", content: opts.task }];
3117
- conversation.updatedAt = Date.now();
3118
- await conversationStore.update(conversation);
3114
+ // Atomic create: parent_conversation_id and initial state are persisted
3115
+ // in the single INSERT. This prevents orphaned top-level-looking
3116
+ // subagents if a follow-up update is interrupted.
3117
+ const conversation = await conversationStore.create(
3118
+ opts.ownerId,
3119
+ opts.task.slice(0, 80),
3120
+ opts.tenantId ?? null,
3121
+ {
3122
+ parentConversationId: opts.parentConversationId,
3123
+ subagentMeta: { task: opts.task, status: "running" },
3124
+ messages: [{ role: "user", content: opts.task }],
3125
+ },
3126
+ );
3119
3127
 
3120
3128
  // Register this parent as having a pending spawn BEFORE the async
3121
3129
  // runSubagent starts, so hasPendingSubagentWorkForParent sees it
@@ -6486,18 +6494,36 @@ export const createRequestHandler = async (options?: {
6486
6494
 
6487
6495
  for (const reminder of due) {
6488
6496
  try {
6489
- await reminderStore.delete(reminder.id);
6497
+ // For recurring reminders, compute the next occurrence before any
6498
+ // state changes so we can reschedule. For one-off reminders, delete.
6499
+ const nextScheduledAt = computeNextOccurrence(reminder);
6500
+ if (nextScheduledAt) {
6501
+ await reminderStore.update(reminder.id, {
6502
+ scheduledAt: nextScheduledAt,
6503
+ occurrenceCount: (reminder.occurrenceCount ?? 0) + 1,
6504
+ });
6505
+ } else {
6506
+ await reminderStore.delete(reminder.id);
6507
+ }
6490
6508
 
6491
6509
  const originConv = reminder.conversationId
6492
6510
  ? await conversationStore.get(reminder.conversationId)
6493
6511
  : undefined;
6494
6512
  const channelMeta = originConv?.channelMeta;
6495
6513
 
6514
+ const isRecurring = !!reminder.recurrence;
6515
+ const recurrenceNote = isRecurring && nextScheduledAt
6516
+ ? `\nNext occurrence: ${new Date(nextScheduledAt).toISOString()}`
6517
+ : isRecurring
6518
+ ? "\nThis was the final occurrence."
6519
+ : "";
6520
+
6496
6521
  const framedMessage =
6497
6522
  `[Reminder] A reminder you previously set has fired.\n` +
6498
6523
  `Task: "${reminder.task}"\n` +
6499
6524
  `Originally set at: ${new Date(reminder.createdAt).toISOString()}\n` +
6500
- `Scheduled for: ${new Date(reminder.scheduledAt).toISOString()}`;
6525
+ `Scheduled for: ${new Date(reminder.scheduledAt).toISOString()}` +
6526
+ recurrenceNote;
6501
6527
 
6502
6528
  if (channelMeta) {
6503
6529
  const adapter = messagingAdapters.get(channelMeta.platform);