copilotkit 4.23.1 → 4.24.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 (94) hide show
  1. package/README.md +91 -5
  2. package/cli-build-info.json +8 -8
  3. package/exporters/langgraph/README.md +33 -0
  4. package/exporters/langgraph/export_checkpointer.py +16 -0
  5. package/index.js +4380 -3586
  6. package/onboarding/index.json +2 -1
  7. package/onboarding/prompts/authenticate/start.md +15 -12
  8. package/onboarding/prompts/conversion/plan.md +3 -3
  9. package/onboarding/prompts/credentials/finalize-plan.md +8 -8
  10. package/onboarding/prompts/credentials/plan.md +23 -23
  11. package/onboarding/prompts/credentials/settle-credentials.md +14 -5
  12. package/onboarding/prompts/credentials/write-plan.md +6 -6
  13. package/onboarding/prompts/deployment/choose-local.md +24 -13
  14. package/onboarding/prompts/deployment/local-evaluation.md +31 -7
  15. package/onboarding/prompts/fallback/best-effort.md +8 -8
  16. package/onboarding/prompts/feature/a2ui/implement.md +6 -6
  17. package/onboarding/prompts/feature/a2ui/plan.md +4 -4
  18. package/onboarding/prompts/feature/a2ui/proof.md +5 -5
  19. package/onboarding/prompts/feature/a2ui/start.md +25 -8
  20. package/onboarding/prompts/feature/channels/implement.md +7 -7
  21. package/onboarding/prompts/feature/channels/plan.md +4 -4
  22. package/onboarding/prompts/feature/channels/proof.md +5 -5
  23. package/onboarding/prompts/feature/channels/start.md +23 -19
  24. package/onboarding/prompts/feature/chat-suggestions/implement.md +6 -6
  25. package/onboarding/prompts/feature/chat-suggestions/plan.md +4 -4
  26. package/onboarding/prompts/feature/chat-suggestions/proof.md +5 -5
  27. package/onboarding/prompts/feature/chat-suggestions/start.md +25 -8
  28. package/onboarding/prompts/feature/complete.md +2 -2
  29. package/onboarding/prompts/feature/learning/implement.md +13 -13
  30. package/onboarding/prompts/feature/learning/plan.md +4 -4
  31. package/onboarding/prompts/feature/learning/proof.md +49 -6
  32. package/onboarding/prompts/feature/learning/start.md +25 -8
  33. package/onboarding/prompts/feature/open-generative-ui/implement.md +6 -6
  34. package/onboarding/prompts/feature/open-generative-ui/plan.md +4 -4
  35. package/onboarding/prompts/feature/open-generative-ui/proof.md +5 -5
  36. package/onboarding/prompts/feature/open-generative-ui/start.md +25 -8
  37. package/onboarding/prompts/feature/realtime-sync/implement.md +7 -7
  38. package/onboarding/prompts/feature/realtime-sync/plan.md +4 -4
  39. package/onboarding/prompts/feature/realtime-sync/proof.md +5 -5
  40. package/onboarding/prompts/feature/realtime-sync/start.md +24 -7
  41. package/onboarding/prompts/feature/rich-threads/implement.md +8 -8
  42. package/onboarding/prompts/feature/rich-threads/plan.md +4 -4
  43. package/onboarding/prompts/feature/rich-threads/proof.md +5 -5
  44. package/onboarding/prompts/feature/rich-threads/start.md +24 -7
  45. package/onboarding/prompts/feature/stop.md +3 -3
  46. package/onboarding/prompts/feature/voice/implement.md +6 -6
  47. package/onboarding/prompts/feature/voice/plan.md +5 -5
  48. package/onboarding/prompts/feature/voice/proof.md +5 -5
  49. package/onboarding/prompts/feature/voice/start.md +25 -8
  50. package/onboarding/prompts/framework/ag2.md +2 -2
  51. package/onboarding/prompts/framework/agno.md +2 -2
  52. package/onboarding/prompts/framework/built-in.md +2 -2
  53. package/onboarding/prompts/framework/claude-sdk-python.md +2 -2
  54. package/onboarding/prompts/framework/claude-sdk-typescript.md +2 -2
  55. package/onboarding/prompts/framework/crewai-flows.md +2 -2
  56. package/onboarding/prompts/framework/custom-ag-ui.md +2 -2
  57. package/onboarding/prompts/framework/deep-agents.md +2 -2
  58. package/onboarding/prompts/framework/google-adk.md +2 -2
  59. package/onboarding/prompts/framework/langgraph-fastapi.md +2 -2
  60. package/onboarding/prompts/framework/langgraph-python.md +2 -2
  61. package/onboarding/prompts/framework/langgraph-typescript.md +2 -2
  62. package/onboarding/prompts/framework/llamaindex.md +2 -2
  63. package/onboarding/prompts/framework/mastra.md +2 -2
  64. package/onboarding/prompts/framework/ms-agent-dotnet.md +3 -3
  65. package/onboarding/prompts/framework/ms-agent-harness-dotnet.md +3 -3
  66. package/onboarding/prompts/framework/ms-agent-python.md +2 -2
  67. package/onboarding/prompts/framework/pydantic-ai.md +2 -2
  68. package/onboarding/prompts/framework/strands-python.md +2 -2
  69. package/onboarding/prompts/framework/strands-typescript.md +2 -2
  70. package/onboarding/prompts/frontend/angular.md +3 -3
  71. package/onboarding/prompts/frontend/nextjs.md +3 -3
  72. package/onboarding/prompts/frontend/plan.md +7 -7
  73. package/onboarding/prompts/frontend/react-native.md +2 -2
  74. package/onboarding/prompts/frontend/react-spa.md +2 -2
  75. package/onboarding/prompts/frontend/vue.md +2 -2
  76. package/onboarding/prompts/implementation/build-and-validate.md +16 -14
  77. package/onboarding/prompts/proof/complete.md +3 -3
  78. package/onboarding/prompts/proof/oss-baseline.md +5 -5
  79. package/onboarding/prompts/proof/round-trip.md +8 -8
  80. package/onboarding/prompts/research/gather.md +5 -5
  81. package/onboarding/prompts/research/merge.md +2 -2
  82. package/onboarding/prompts/research/preflight.md +2 -2
  83. package/onboarding/prompts/research/route.md +5 -5
  84. package/onboarding/prompts/starter/clone.md +92 -7
  85. package/onboarding/prompts/stopped/run-failed.md +2 -2
  86. package/onboarding/prompts/subagent/create-plan.md +2 -2
  87. package/onboarding/prompts/subagent/implement-and-validate.md +2 -2
  88. package/onboarding/prompts/subagent/inspect-repository.md +1 -1
  89. package/onboarding/prompts/subagent/prove-oss-baseline.md +1 -1
  90. package/onboarding/prompts/subagent/prove-round-trip.md +8 -6
  91. package/onboarding/prompts/unsupported/no-validated-path.md +2 -2
  92. package/package.json +1 -1
  93. package/release/release-tool.js +12 -1
  94. package/services/local-auth-worker.js +175 -159
package/README.md CHANGED
@@ -321,12 +321,43 @@ folder and paste the prompt that they copied. It also gives a line to paste
321
321
  that continues the same run. An agent that the CLI does not detect reads the
322
322
  full prompt above the note, so the note does not block it.
323
323
 
324
+ ### Where a run keeps its state
325
+
326
+ The run keeps its state in `.copilotkit/onboarding/` in the folder where
327
+ `onboard start` ran. The state is the run id, the route, the proof results and
328
+ the coding agent. The folder holds a `.gitignore` that contains `*`, so git
329
+ never lists it. Delete the folder to forget the run.
330
+
331
+ If the project folder cannot be written, the CLI keeps the state in its config
332
+ store in your home folder instead. A run started by an earlier CLI version is
333
+ read from there too.
334
+
335
+ The sign-in, the telemetry install id and the protected-path baseline stay in
336
+ the config store in your home folder. A rebuilt devcontainer gets a fresh home
337
+ folder, so it keeps the run but loses the sign-in and counts as a new install.
338
+ To keep them, set `COPILOTKIT_CONFIG_DIR` to an absolute path on a mounted
339
+ volume, in the devcontainer configuration or your shell profile:
340
+
341
+ ```json
342
+ {
343
+ "containerEnv": { "COPILOTKIT_CONFIG_DIR": "/workspaces/.copilotkit-home" }
344
+ }
345
+ ```
346
+
347
+ The CLI then keeps its stores in `auth/` and `config/` under that folder, and
348
+ its log in `logs/`. On Linux, `XDG_CONFIG_HOME` also moves the stores.
349
+
350
+ Do not point `COPILOTKIT_CONFIG_DIR` inside the project. The sign-in token
351
+ would sit where a coding agent can read it or commit it.
352
+
324
353
  ## Feature onboarding for existing apps
325
354
 
326
355
  Use the optional `--intent` flag when an existing CopilotKit app needs one
327
356
  specific feature. The CLI prints a feature-specific Markdown path; the coding
328
357
  agent follows its inspection, plan, implementation, and visible-proof steps.
329
358
  Without `--intent`, `onboard start` keeps the generic onboarding path unchanged.
359
+ Each feature path starts with `onboard identify`, as the generic path does, because
360
+ the environment can detect only some coding agents.
330
361
 
331
362
  ```bash
332
363
  npx --yes copilotkit@latest onboard start \
@@ -365,10 +396,47 @@ from the declared one. `cli.onboarding.started` also carries
365
396
  `detected_coding_agent`, because a run that stops before `onboard identify` sends
366
397
  no identify event. It also carries `audience`: `detected-agent` when the
367
398
  environment shows an agent, `human-terminal` for a terminal with no detected
368
- agent, and `non-tty` otherwise. Channel setup stage events include
399
+ agent, and `non-tty` otherwise. Before sign-in, the first prompt records where the
400
+ app stores data with `onboard deployment --choice <managed|local>`. The
401
+ `cli.onboarding.deployment_chosen` event carries that `deployment` and
402
+ `local_offered`, which this CLI release reads from its local evaluation flag. A
403
+ managed run with `local_offered: false` was never offered local. Channel setup stage events include
369
404
  the existing `onboarding_run_id` when the command runs inside an onboarding run;
370
405
  standalone commands omit it. These events use the CLI's existing telemetry consent gate.
371
406
 
407
+ Local setup reports how long each phase took, while it runs. During `init --local`,
408
+ `local setup`, or `local update`, the CLI sends these events:
409
+
410
+ - `cli.local.setup_phase_started` when a phase begins.
411
+ - `cli.local.setup_phase_completed` when the phase ends.
412
+ - `cli.local.setup_completed` once, for the whole setup.
413
+
414
+ The fields:
415
+
416
+ - A phase event carries `setup_phase`, a fixed slug such as `images-download` or
417
+ `services-start`, and `phase_visit`. The installer returns to some phases, so each
418
+ visit sends its own event with only that visit's `duration_ms`. Add the visits to get
419
+ the phase's time for one setup.
420
+ - A finished phase event carries `duration_ms` and `outcome`. The image download phase
421
+ adds `bytes_downloaded` and `image_count`.
422
+ - `release` is present only after setup knows the installed release, so early phase
423
+ events do not have it. The total always has it when setup finished.
424
+ - The total carries `duration_ms`, `outcome`, and `phase_count`. A failed setup adds
425
+ `failed_setup_phase`.
426
+ - On Ctrl-C or SIGTERM, the open phase and the total send `outcome: abandoned` before
427
+ the CLI exits. The total adds `abandoned_setup_phase` and the `bytes_downloaded` so
428
+ far. The CLI waits at most 2 seconds for these sends, then exits with the signal's
429
+ usual status.
430
+ - Every event carries `onboarding_run_id` when the app belongs to an onboarding run.
431
+ For `init --dir <target>`, the CLI reads the run from the current directory first,
432
+ then from the target directory.
433
+
434
+ The events carry no path, label text, or credential.
435
+
436
+ Outside a terminal, for example in a coding agent's shell, a long phase prints one
437
+ progress line at most every 15 seconds, such as
438
+ `Downloading container images… 4 of 11 · 1.2 GB`. With `--json`, nothing extra is printed.
439
+
372
440
  The intent describes the developer's requested outcome, not a claim about the
373
441
  current project state. Each path inspects the app first: it preserves a proven
374
442
  existing configuration, stops rather than inventing credentials or identities,
@@ -950,8 +1018,8 @@ Inside a git repository, the first `onboard protect` records the files that git
950
1018
  lists as changed or untracked. Git can restore committed files, so the baseline
951
1019
  leaves them out. Outside a repository, the baseline records every file under the
952
1020
  run's folder, except in `node_modules`, `dist`, `build`, `out`, `coverage`,
953
- `.next`, `venv` and `__pycache__`. The capture report says which of the two it
954
- used.
1021
+ `.next`, `venv`, `__pycache__` and the run's own state in
1022
+ `.copilotkit/onboarding/`. The capture report says which of the two it used.
955
1023
 
956
1024
  A git repository at your home directory, or above it, does not count as the
957
1025
  repository of a project below it. It is usually a dotfiles or accidental
@@ -1279,7 +1347,7 @@ copilotkit logs --tail
1279
1347
  copilotkit logs --tail --lines 100
1280
1348
  ```
1281
1349
 
1282
- With no flags, `copilotkit logs` prints the log file path. The log lives in `~/.copilotkit/cli.log` (or `$XDG_STATE_HOME/copilotkit/cli.log`). If a sandbox refuses writes there, the CLI logs to `$TMPDIR/copilotkit-<uid>/cli.log` instead, and if that also fails, the CLI runs with no log file. `--tail` prints recent structured log lines. Add `--verbose` to a CLI command when you need high-signal diagnostics mirrored to stderr during the run.
1350
+ With no flags, `copilotkit logs` prints the log file path. The log lives in `~/.copilotkit/cli.log` (or `$XDG_STATE_HOME/copilotkit/cli.log`, or `$COPILOTKIT_CONFIG_DIR/logs/cli.log`). If a sandbox refuses writes there, the CLI logs to `$TMPDIR/copilotkit-<uid>/cli.log` instead, and if that also fails, the CLI runs with no log file. `--tail` prints recent structured log lines. Add `--verbose` to a CLI command when you need high-signal diagnostics mirrored to stderr during the run.
1283
1351
 
1284
1352
  Project creation (`init`/`create`) connects to and revalidates the live Clerk
1285
1353
  workspace before scaffolding. License commands, including `license list`,
@@ -1430,11 +1498,29 @@ copilotkit onboard credentials --model-key OPENAI_API_KEY \
1430
1498
  The step copies each key into that `.env` file and protects it with the other
1431
1499
  credential paths. `copiedKeys` gives the outcome for each copy. A file that
1432
1500
  already holds another real value keeps it. The step stops when git does not
1433
- ignore the file, because the key would then be committed.
1501
+ ignore the file, because the key would then be committed. A `--copy-to` file
1502
+ outside the repository is refused, because no baseline can protect it.
1503
+
1504
+ When the developer keeps the key in a file outside the project, name that file
1505
+ with `--env-path`, and copy the key into the app's own `.env`:
1506
+
1507
+ ```bash
1508
+ copilotkit onboard credentials --model-key OPENAI_API_KEY \
1509
+ --env-path ~/keys/.env --copy-to .env --json
1510
+ ```
1511
+
1512
+ Without `--copy-to`, the `next` field of the answer names this command for the
1513
+ outside file.
1434
1514
 
1435
1515
  It needs a bound run and exits zero for every answer. A `stopped` answer files
1436
1516
  the stop report itself. It never prints a key.
1437
1517
 
1518
+ `--model-key`, and `--key` for `onboard model-key`, take an environment
1519
+ variable name: letters, digits, and underscores, not starting with a digit.
1520
+ Mixed case is allowed, for example `GitHubToken`. Any other value is a usage
1521
+ error, and the step checks and copies nothing. The step copies a valid name the
1522
+ CLI cannot probe too, because the vendor is the developer's choice.
1523
+
1438
1524
  ### A command, subcommand, or flag that should exist is rejected
1439
1525
 
1440
1526
  `npx` keys its cache on the spec string, so `copilotkit@latest` can keep serving
@@ -2,20 +2,20 @@
2
2
  "schemaVersion": 1,
3
3
  "package": {
4
4
  "name": "copilotkit",
5
- "version": "4.23.1"
5
+ "version": "4.24.0"
6
6
  },
7
7
  "intelligence": {
8
- "commit": "84454c6457dc7f0bca01f5f04ff52b2c1abec0e2"
8
+ "commit": "414f50da283d14f22e2b350dff662b4b18cb1017"
9
9
  },
10
10
  "copilotKit": {
11
- "submittedInput": "f835ce816112541654ded07162c2cc8ddf4f3f2c",
12
- "commit": "f835ce816112541654ded07162c2cc8ddf4f3f2c"
11
+ "submittedInput": "c88a2dd2a4c0",
12
+ "commit": "c88a2dd2a4c024e956e3f88b6b86d5715951e284"
13
13
  },
14
14
  "channel": "production",
15
- "triggeringActor": "dustywusty",
15
+ "triggeringActor": "BenTaylorDev",
16
16
  "workflow": {
17
- "runId": "36956555306",
18
- "runUrl": "https://github.com/CopilotKit/Intelligence/actions/runs/36956555306"
17
+ "runId": "37064724012",
18
+ "runUrl": "https://github.com/CopilotKit/Intelligence/actions/runs/37064724012"
19
19
  },
20
20
  "validationResult": "passed",
21
21
  "ag2": {
@@ -24,5 +24,5 @@
24
24
  "revision": "main",
25
25
  "pinned": false
26
26
  },
27
- "builtAt": "2026-10-02T02:40:10Z"
27
+ "builtAt": "2026-10-02T21:07:52Z"
28
28
  }
@@ -86,6 +86,27 @@ and integers outside the JavaScript safe range fail export instead of silently
86
86
  changing their values. Task exceptions are exported as their Python `repr`
87
87
  (type and message), matching persisted LangGraph task errors.
88
88
 
89
+ Pydantic v2 models, including AG-UI `Context`, export through their Python-mode
90
+ serialization contract with wire aliases and subclass fields. Nested models,
91
+ extra fields, and meaningful nulls survive; a model's own serializers still
92
+ control its representation (AG-UI omits unset optional fields). The resulting
93
+ tree must contain supported JSON values. Bytes, dates, sets, arbitrary objects,
94
+ non-string keys, non-finite numbers, and unsafe integers are rejected rather than
95
+ coerced. This does not add model deserialization permissions to the checkpointer.
96
+ Use the application's existing trusted deserialization configuration.
97
+ Pydantic 2.12 or later is required for reliable nested model serialization.
98
+ Older versions can reject acyclic recursive models or AG-UI Context inside
99
+ `Any` fields. If model serialization fails on those versions, export stops with
100
+ an upgrade message and retains the original exception as its cause; it does not
101
+ retry with a lossy representation. Errors from application model serializers
102
+ still require fixing the serializer if they persist after upgrading.
103
+
104
+ Export fidelity and replay support are separate: native LangChain `file` and
105
+ `audio` blocks remain intact in the export, but the current importer renders
106
+ them as unresolved placeholders. Inline `image_url` data retains its bytes and
107
+ MIME type through replay. Export success alone does not establish full media
108
+ parity or correct routing when resuming an imported conversation.
109
+
89
110
  ## Tests
90
111
 
91
112
  ```sh
@@ -104,6 +125,18 @@ snapshot equality and database bytes. It makes no model/provider calls. The
104
125
  captured synthetic native snapshot in `fixtures/langgraph/checkpointer-native.jsonl`
105
126
  is consumed by TypeScript contract tests.
106
127
 
128
+ `python/context_fixture.py` creates real AG-UI models in SQLite, reopens the
129
+ store, and exports pending frontend, pending native, and completed interactions.
130
+ The native test checks source rows and file bytes; the loader's
131
+ `langgraph-context.spec.ts` checks the captured snapshots through database import,
132
+ state/message replay, checkpoint provenance, and repeat-import deduplication.
133
+ Regenerate that capture with:
134
+
135
+ ```sh
136
+ python libs/import-langgraph/python/context_fixture.py libs/import-langgraph/fixtures/context.jsonl
137
+ pnpm nx test @cpki/import-loader -- src/langgraph-context.spec.ts
138
+ ```
139
+
107
140
  ## Replay an application’s custom A2UI catalog
108
141
 
109
142
  When native `render_a2ui` calls omit `catalogId`, supply the original application catalog explicitly:
@@ -7,6 +7,7 @@ from dataclasses import asdict, is_dataclass
7
7
  from math import isfinite
8
8
 
9
9
  from langchain_core.messages import BaseMessage
10
+ from pydantic import BaseModel, VERSION as PYDANTIC_VERSION
10
11
 
11
12
 
12
13
  def json_value(value):
@@ -24,6 +25,21 @@ def json_value(value):
24
25
  return repr(value)
25
26
  if isinstance(value, BaseMessage):
26
27
  return json_value(value.model_dump(mode='json'))
28
+ if isinstance(value, BaseModel):
29
+ # AG-UI Context and other framework models use Pydantic's wire aliases.
30
+ # Python mode leaves non-JSON values intact for the strict checks below
31
+ # (JSON mode can coerce bytes, dates, sets and non-string keys).
32
+ try:
33
+ dumped = value.model_dump(mode='python', by_alias=True, serialize_as_any=True)
34
+ except (ValueError, TypeError, AttributeError) as error:
35
+ if tuple(map(int, PYDANTIC_VERSION.split('.')[:2])) < (2, 12):
36
+ raise ValueError(
37
+ f'Cannot export {type(value).__name__} with Pydantic {PYDANTIC_VERSION}. '
38
+ 'Upgrade to Pydantic 2.12 or later for nested model serialization; '
39
+ 'if the error persists, check the model serializer.'
40
+ ) from error
41
+ raise
42
+ return json_value(dumped)
27
43
  if is_dataclass(value) and not isinstance(value, type):
28
44
  return json_value(asdict(value))
29
45
  if hasattr(value, '_asdict'):