@letta-ai/letta-code 0.32.13 → 0.32.15

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 (156) hide show
  1. package/dist/agent-presets.js +1 -1
  2. package/dist/agent-presets.js.map +3 -3
  3. package/dist/app-server-client.cjs +2 -2
  4. package/dist/app-server-client.cjs.map +3 -3
  5. package/dist/app-server-client.js +2 -2
  6. package/dist/app-server-client.js.map +3 -3
  7. package/dist/channels-public.js +7 -7
  8. package/dist/channels-public.js.map +3 -3
  9. package/dist/channels-slack.js.map +2 -2
  10. package/dist/gateway-core.js +7 -7
  11. package/dist/gateway-core.js.map +3 -3
  12. package/dist/mcp-client.js +2 -2
  13. package/dist/mcp-client.js.map +1 -1
  14. package/dist/types/agent/approval-execution.d.ts.map +1 -1
  15. package/dist/types/agent/memory-filesystem.d.ts +3 -4
  16. package/dist/types/agent/memory-filesystem.d.ts.map +1 -1
  17. package/dist/types/agent/message.d.ts +3 -0
  18. package/dist/types/agent/message.d.ts.map +1 -1
  19. package/dist/types/agent/prompt-assets.d.ts +0 -1
  20. package/dist/types/agent/prompt-assets.d.ts.map +1 -1
  21. package/dist/types/agent/subagents/manager.d.ts.map +1 -1
  22. package/dist/types/agent/subagents/names.d.ts +1 -1
  23. package/dist/types/agent/subagents/names.d.ts.map +1 -1
  24. package/dist/types/agent/subagents/subagent-launcher.d.ts +2 -0
  25. package/dist/types/agent/subagents/subagent-launcher.d.ts.map +1 -1
  26. package/dist/types/agent/subagents/subagent-stream.d.ts +3 -0
  27. package/dist/types/agent/subagents/subagent-stream.d.ts.map +1 -1
  28. package/dist/types/backend/api/reflection-runs.d.ts +17 -0
  29. package/dist/types/backend/api/reflection-runs.d.ts.map +1 -0
  30. package/dist/types/backend/api/reflection.d.ts +22 -0
  31. package/dist/types/backend/api/reflection.d.ts.map +1 -0
  32. package/dist/types/backend/backend.d.ts +16 -0
  33. package/dist/types/backend/backend.d.ts.map +1 -1
  34. package/dist/types/backend/dev/headless-turn-executor.d.ts +8 -0
  35. package/dist/types/backend/dev/headless-turn-executor.d.ts.map +1 -1
  36. package/dist/types/backend/dev/pi-stream-adapter.d.ts.map +1 -1
  37. package/dist/types/backend/dev/pi-stream-output.d.ts +3 -0
  38. package/dist/types/backend/dev/pi-stream-output.d.ts.map +1 -0
  39. package/dist/types/backend/dev/provider-turn-executor.d.ts.map +1 -1
  40. package/dist/types/backend/local/local-backend.d.ts.map +1 -1
  41. package/dist/types/backend/local/local-executor-factory.d.ts +1 -1
  42. package/dist/types/backend/local/local-executor-factory.d.ts.map +1 -1
  43. package/dist/types/backend/local/local-message.d.ts +2 -1
  44. package/dist/types/backend/local/local-message.d.ts.map +1 -1
  45. package/dist/types/backend/local/local-store.d.ts.map +1 -1
  46. package/dist/types/backend/local/local-stream-chunks.d.ts +13 -0
  47. package/dist/types/backend/local/local-stream-chunks.d.ts.map +1 -1
  48. package/dist/types/channels/progress-formatting.d.ts.map +1 -1
  49. package/dist/types/cli/helpers/stream-processor.d.ts +7 -2
  50. package/dist/types/cli/helpers/stream-processor.d.ts.map +1 -1
  51. package/dist/types/cli/helpers/stream.d.ts +7 -5
  52. package/dist/types/cli/helpers/stream.d.ts.map +1 -1
  53. package/dist/types/cli/helpers/tool-name-mapping.d.ts +5 -2
  54. package/dist/types/cli/helpers/tool-name-mapping.d.ts.map +1 -1
  55. package/dist/types/hooks/executor.d.ts +5 -0
  56. package/dist/types/hooks/executor.d.ts.map +1 -1
  57. package/dist/types/hooks/index.d.ts.map +1 -1
  58. package/dist/types/permissions/canonical.d.ts.map +1 -1
  59. package/dist/types/permissions/checker.d.ts.map +1 -1
  60. package/dist/types/permissions/cross-agent-guard.d.ts +1 -1
  61. package/dist/types/permissions/cross-agent-guard.d.ts.map +1 -1
  62. package/dist/types/permissions/mode.d.ts.map +1 -1
  63. package/dist/types/permissions/workspace-sandbox.d.ts.map +1 -1
  64. package/dist/types/providers/byok-providers.d.ts +1 -0
  65. package/dist/types/providers/byok-providers.d.ts.map +1 -1
  66. package/dist/types/settings-manager.d.ts.map +1 -1
  67. package/dist/types/tools/filter.d.ts +0 -10
  68. package/dist/types/tools/filter.d.ts.map +1 -1
  69. package/dist/types/tools/impl/bash-output.d.ts.map +1 -1
  70. package/dist/types/tools/impl/bash.d.ts.map +1 -1
  71. package/dist/types/tools/impl/enter-worktree.d.ts.map +1 -1
  72. package/dist/types/tools/impl/exec-command.d.ts.map +1 -1
  73. package/dist/types/tools/impl/kill-bash.d.ts.map +1 -1
  74. package/dist/types/tools/impl/process_manager.d.ts +2 -1
  75. package/dist/types/tools/impl/process_manager.d.ts.map +1 -1
  76. package/dist/types/tools/impl/shell-command.d.ts.map +1 -1
  77. package/dist/types/tools/impl/shell-sandbox.d.ts +1 -2
  78. package/dist/types/tools/impl/shell-sandbox.d.ts.map +1 -1
  79. package/dist/types/tools/impl/tool-return-clamp.d.ts.map +1 -1
  80. package/dist/types/tools/impl/truncation.d.ts +5 -2
  81. package/dist/types/tools/impl/truncation.d.ts.map +1 -1
  82. package/dist/types/tools/impl/workflow.d.ts +55 -0
  83. package/dist/types/tools/impl/workflow.d.ts.map +1 -0
  84. package/dist/types/tools/impl/worktree-git.d.ts +14 -0
  85. package/dist/types/tools/impl/worktree-git.d.ts.map +1 -1
  86. package/dist/types/tools/manager.d.ts +6 -20
  87. package/dist/types/tools/manager.d.ts.map +1 -1
  88. package/dist/types/tools/tool-definitions.d.ts +1 -21
  89. package/dist/types/tools/tool-definitions.d.ts.map +1 -1
  90. package/dist/types/tools/tool-permissions.d.ts.map +1 -1
  91. package/dist/types/tools/toolset-catalog.d.ts +13 -0
  92. package/dist/types/tools/toolset-catalog.d.ts.map +1 -0
  93. package/dist/types/tools/toolset.d.ts +10 -27
  94. package/dist/types/tools/toolset.d.ts.map +1 -1
  95. package/dist/types/tools/workflow/execution-registry.d.ts +58 -0
  96. package/dist/types/tools/workflow/execution-registry.d.ts.map +1 -0
  97. package/dist/types/tools/workflow/format-stats.d.ts +23 -0
  98. package/dist/types/tools/workflow/format-stats.d.ts.map +1 -0
  99. package/dist/types/tools/workflow/journal.d.ts +25 -0
  100. package/dist/types/tools/workflow/journal.d.ts.map +1 -0
  101. package/dist/types/tools/workflow/meta.d.ts +14 -0
  102. package/dist/types/tools/workflow/meta.d.ts.map +1 -0
  103. package/dist/types/tools/workflow/sdk-loader.d.ts +33 -0
  104. package/dist/types/tools/workflow/sdk-loader.d.ts.map +1 -0
  105. package/dist/types/tools/workflow/sdk-spawner.d.ts +33 -0
  106. package/dist/types/tools/workflow/sdk-spawner.d.ts.map +1 -0
  107. package/dist/types/tools/workflow/types.d.ts +148 -0
  108. package/dist/types/tools/workflow/types.d.ts.map +1 -0
  109. package/dist/types/tools/workflow/workflow-engine.d.ts +20 -0
  110. package/dist/types/tools/workflow/workflow-engine.d.ts.map +1 -0
  111. package/dist/types/types/app-server-info.d.ts +1 -0
  112. package/dist/types/types/app-server-info.d.ts.map +1 -1
  113. package/dist/types/types/protocol_v2.d.ts +4 -7
  114. package/dist/types/types/protocol_v2.d.ts.map +1 -1
  115. package/dist/types/types/provider-oauth-config.d.ts +24 -0
  116. package/dist/types/types/provider-oauth-config.d.ts.map +1 -0
  117. package/dist/types/types/toolset-protocol.d.ts +1 -1
  118. package/dist/types/types/toolset-protocol.d.ts.map +1 -1
  119. package/dist/types/utils/frontmatter.d.ts.map +1 -1
  120. package/dist/types/websocket/listener/listener-constants.d.ts.map +1 -1
  121. package/dist/types/websocket/listener/types.d.ts +1 -0
  122. package/dist/types/websocket/listener/types.d.ts.map +1 -1
  123. package/docs/examples/mods/memory-citations.ts +0 -2
  124. package/letta.js +2 -2
  125. package/package.json +3 -2
  126. package/scripts/isolated-unit-tests.json +10 -5
  127. package/scripts/source-file-size-baseline.json +15 -15
  128. package/skills/creating-mods/references/plan-mode.md +3 -9
  129. package/skills/self-configuration/SKILL.md +1 -1
  130. package/skills/syncing-memory-filesystem/SKILL.md +2 -3
  131. package/skills/workflow-authoring/SKILL.md +217 -0
  132. package/vendor/ink-text-input/build/index.js +10 -2
  133. package/dist/types/tools/impl/glob-gemini.d.ts +0 -16
  134. package/dist/types/tools/impl/glob-gemini.d.ts.map +0 -1
  135. package/dist/types/tools/impl/list-directory-gemini.d.ts +0 -17
  136. package/dist/types/tools/impl/list-directory-gemini.d.ts.map +0 -1
  137. package/dist/types/tools/impl/read-file-gemini.d.ts +0 -14
  138. package/dist/types/tools/impl/read-file-gemini.d.ts.map +0 -1
  139. package/dist/types/tools/impl/read-many-files-gemini.d.ts +0 -19
  140. package/dist/types/tools/impl/read-many-files-gemini.d.ts.map +0 -1
  141. package/dist/types/tools/impl/replace-gemini.d.ts +0 -15
  142. package/dist/types/tools/impl/replace-gemini.d.ts.map +0 -1
  143. package/dist/types/tools/impl/run-shell-command-gemini.d.ts +0 -18
  144. package/dist/types/tools/impl/run-shell-command-gemini.d.ts.map +0 -1
  145. package/dist/types/tools/impl/search-file-content-gemini.d.ts +0 -14
  146. package/dist/types/tools/impl/search-file-content-gemini.d.ts.map +0 -1
  147. package/dist/types/tools/impl/write-file-gemini.d.ts +0 -13
  148. package/dist/types/tools/impl/write-file-gemini.d.ts.map +0 -1
  149. package/dist/types/tools/impl/write-todos-gemini.d.ts +0 -16
  150. package/dist/types/tools/impl/write-todos-gemini.d.ts.map +0 -1
  151. package/dist/types/tools/letta-toolset.d.ts +0 -10
  152. package/dist/types/tools/letta-toolset.d.ts.map +0 -1
  153. package/dist/types/tools/toolset-defaults.d.ts +0 -9
  154. package/dist/types/tools/toolset-defaults.d.ts.map +0 -1
  155. package/dist/types/tools/toolset-options.d.ts +0 -4
  156. package/dist/types/tools/toolset-options.d.ts.map +0 -1
@@ -0,0 +1,217 @@
1
+ ---
2
+ name: workflow-authoring
3
+ description: Reference for writing a Workflow tool script (script API and gotchas, pipeline-vs-barrier rules, quality patterns, worked examples). Load before authoring a script for a workflow the user already opted into; it does not itself authorize running one.
4
+ ---
5
+
6
+ # Workflow authoring reference
7
+
8
+ A workflow structures work across many subagents — to be comprehensive
9
+ (decompose and cover in parallel), to be confident (independent perspectives
10
+ and adversarial checks before committing), or to take on scale one context
11
+ can't hold (migrations, audits, broad sweeps). The script is where you encode
12
+ that structure: what fans out, what verifies, what synthesizes.
13
+
14
+ When you do call the Workflow tool, the right move is often **hybrid**: scout
15
+ inline first (list the files, scope the diff, find the modules) to discover
16
+ the work-list, then call Workflow to pipeline over it, passing the list via
17
+ `args`. You don't need to know the shape before the *task* — only before the
18
+ *orchestration step*.
19
+
20
+ Common single-phase workflows you can chain across turns:
21
+ - **Understand** — parallel readers over relevant subsystems → structured map
22
+ - **Design** — judge panel of N independent approaches → scored synthesis
23
+ - **Review** — dimensions → find → adversarially verify
24
+ - **Research** — multi-modal sweep → deep-read → synthesize
25
+ - **Migrate** — discover sites → transform each → verify
26
+
27
+ For larger work, run several in sequence — read each result before deciding
28
+ the next phase. You stay in the loop; each workflow is one well-scoped
29
+ fan-out.
30
+
31
+ Every script must begin with `export const meta = {...}`:
32
+
33
+ export const meta = {
34
+ name: 'find-flaky-tests', // kebab-case, required
35
+ description: 'Find flaky tests and propose fixes', // required
36
+ phases: [ // one entry per phase() call
37
+ { title: 'Scan', detail: 'grep test logs for retries' },
38
+ { title: 'Fix', detail: 'one agent per flaky test' },
39
+ ],
40
+ }
41
+ // script body starts here — use agent()/parallel()/pipeline()/phase()/log()
42
+
43
+ The `meta` object must be a PURE LITERAL — no variables, function calls,
44
+ spreads, or template interpolation.
45
+
46
+ ## What a subagent is
47
+
48
+ Every `agent()` call is one agent-free ephemeral conversation linked to the
49
+ invoking parent agent (`is_subagent: true`, named after the call's `label`).
50
+ It starts with nothing but its prompt: no memory, no conversation context, no
51
+ skills. Put ALL context a stage needs in the prompt — file paths, the rule it
52
+ should apply, what shape to return.
53
+
54
+ Subagents are told their final text IS the return value (not a human-facing
55
+ message), so they return raw data. Tools default to read-only (`Read`,
56
+ `Grep`, `Glob`); widen with `allowedTools` for stages that must write. For
57
+ stages whose input is entirely in the prompt (synthesis, judging, scoring)
58
+ pass `allowedTools: []` — a model that can still read files tends to wander,
59
+ and a subagent that re-issues an identical tool call three times is stopped
60
+ and resolves to `null`.
61
+
62
+ Their model defaults to the invoking conversation's model. `opts.model` (or
63
+ the tool's `model` input) accepts any handle or alias listed by
64
+ `letta model list`; an unknown value resolves that call to `null`. Use a
65
+ cheaper model for mechanical stages only when you know a valid handle.
66
+
67
+ Workflow subagents require the API backend.
68
+
69
+ ## Script body hooks
70
+
71
+ - `agent(prompt, opts?)` → Promise. Spawn one subagent. Resolves to its final
72
+ text, or with `json: true` to the parsed JSON value (say in the prompt what
73
+ shape to return — nothing validates it; a reply that is not JSON resolves to
74
+ `null`). Resolves to `null` on any failure — filter with `.filter(Boolean)`.
75
+ Options: `label` (display name), `phase` (progress group — use this inside
76
+ pipeline()/parallel() stages to avoid races on the global phase() state),
77
+ `json`, `model`, `effort` (`'low'` for mechanical stages, higher for the
78
+ hardest verify/judge stages), `allowedTools`, `systemPrompt` (extra system
79
+ prompt for this subagent), `timeoutMs` (default 10 minutes), `maxToolCalls`
80
+ (positive safe integer; default 1000 unique tool calls for this subagent).
81
+ - `pipeline(items, stage1, stage2, ...)` → run each item through all stages
82
+ independently, NO barrier between stages. Item A can be in stage 3 while
83
+ item B is still in stage 1. This is the DEFAULT for multi-stage work.
84
+ Wall-clock = slowest single-item chain, not sum-of-slowest-per-stage. Every
85
+ stage callback receives `(prevResult, originalItem, index)` — use
86
+ originalItem/index in later stages to label work without threading context
87
+ through stage 1's return value. A stage that throws drops that item to
88
+ `null` and skips its remaining stages.
89
+ - `parallel(thunks)` → run zero-arg functions concurrently. This is a
90
+ BARRIER: it awaits all thunks before returning. A thunk that throws
91
+ resolves to `null` in the result array — the call itself never rejects, so
92
+ `.filter(Boolean)` before using the results. Use ONLY when you genuinely
93
+ need all results together.
94
+ - `phase(title)` — start a new phase; subsequent agent() calls are grouped
95
+ under this title in progress output.
96
+ - `log(message)` — emit a progress message to the user.
97
+ - `args` — the value passed as the tool's `args` input, verbatim. Pass
98
+ arrays/objects as actual JSON values, NOT as a JSON-encoded string.
99
+
100
+ Scripts are plain JavaScript, NOT TypeScript — type annotations, interfaces,
101
+ and generics fail to parse. The script body runs in an async context — use
102
+ `await` directly and `return` the final result. Standard JS built-ins (JSON,
103
+ Math, Array, etc.) are available; the hooks are the only globals provided.
104
+ The script runs inside the CLI process with the CLI's own privileges (the
105
+ `vm` context is a scope, not a security boundary), and the user approves it
106
+ by reading it. Keep the script to orchestration: decide what runs and combine
107
+ results. All reading, searching, and writing belongs in subagents, where the
108
+ tool allowlist applies.
109
+
110
+ ## Pipeline vs barrier
111
+
112
+ DEFAULT TO pipeline(). Only reach for a barrier (parallel between stages)
113
+ when stage N needs cross-item context from all of stage N−1:
114
+ - Dedup/merge across the full result set before expensive downstream work
115
+ - Early-exit if the total count is zero ("0 bugs found → skip verification")
116
+ - Stage N's prompt references "the other findings" for comparison
117
+
118
+ A barrier is NOT justified by:
119
+ - "I need to flatten/map/filter first" — do it inside a pipeline stage:
120
+ `pipeline(items, stageA, r => transform([r]).flat(), stageB)`
121
+ - "The stages are conceptually separate" — that's what pipeline() models.
122
+ Separate stages ≠ synchronized stages.
123
+ - "It's cleaner code" — barrier latency is real. If 5 finders run and the
124
+ slowest takes 3× the fastest, a barrier wastes 2/3 of the fast finders'
125
+ idle time.
126
+
127
+ Concurrent agent() calls are capped per run (`maxConcurrent`, default 16) —
128
+ excess calls queue and run as slots free up, so passing 100 items is fine.
129
+ Total agent count across a run is capped at 1000 — a runaway-loop backstop.
130
+ A single parallel()/pipeline() call accepts at most 4096 items.
131
+
132
+ When a barrier IS correct — dedup across all findings before expensive
133
+ verification:
134
+
135
+ const all = await parallel(DIMENSIONS.map(d => () => agent(d.prompt, {json: true})))
136
+ const deduped = dedupeByFileAndLine(all.filter(Boolean).flatMap(r => r.findings ?? [])) // needs ALL at once
137
+ const verified = await parallel(deduped.map(f => () => agent(verifyPrompt(f), {json: true})))
138
+
139
+ Loop-until-count pattern — accumulate to a target:
140
+
141
+ const bugs = []
142
+ let rounds = 0
143
+ while (bugs.length < 10 && rounds++ < 5) {
144
+ const result = await agent('Find bugs in this codebase. Reply {"bugs": [{file, line, summary}]}', {json: true})
145
+ bugs.push(...(result?.bugs ?? []))
146
+ log(`${bugs.length}/10 found`)
147
+ }
148
+
149
+ Always bound a loop with a round counter as well as the target: a subagent
150
+ that keeps returning nothing would otherwise run to the 1000-agent cap.
151
+
152
+ Composing patterns — exhaustive review (find → dedup vs seen → diverse-lens
153
+ panel → loop-until-dry):
154
+
155
+ const seen = new Set(), confirmed = []
156
+ let dry = 0
157
+ while (dry < 2) { // loop-until-dry
158
+ const found = (await parallel(FINDERS.map(f => () => // barrier: collect all finders this round
159
+ agent(f.prompt, {phase: 'Find', json: true})))).filter(Boolean).flatMap(r => r.bugs ?? [])
160
+ const fresh = found.filter(b => !seen.has(key(b))) // dedup vs ALL seen — plain code, not an agent
161
+ if (!fresh.length) { dry++; continue }
162
+ dry = 0; fresh.forEach(b => seen.add(key(b)))
163
+ const judged = await parallel(fresh.map(b => () => // every fresh bug judged concurrently...
164
+ parallel(['correctness','security','repro'].map(lens => () => // ...each by 3 distinct lenses
165
+ agent(`Judge "${b.desc}" via the ${lens} lens — real? Reply {"real": boolean}`, {phase: 'Verify', json: true, allowedTools: []})))
166
+ .then(vs => ({ b, real: vs.filter(Boolean).filter(v => v.real).length >= 2 }))))
167
+ confirmed.push(...judged.filter(v => v.real).map(v => v.b))
168
+ }
169
+ return confirmed
170
+ // dedup vs `seen`, NOT `confirmed` — else judge-rejected findings reappear every round and it never converges.
171
+
172
+ ## Quality patterns — pick by task and compose freely
173
+
174
+ - **Adversarial verify**: spawn N independent skeptics per finding, each
175
+ prompted to REFUTE. Kill if ≥majority refute. Prevents plausible-but-wrong
176
+ findings from surviving.
177
+
178
+ const votes = await parallel(Array.from({length: 3}, () => () =>
179
+ agent(`Try to refute: ${claim}. Default to refuted=true if uncertain. Reply {"refuted": boolean}`, {json: true})))
180
+ const survives = votes.filter(Boolean).filter(v => !v.refuted).length >= 2
181
+
182
+ - **Perspective-diverse verify**: when a finding can fail in more than one
183
+ way, give each verifier a distinct lens (correctness, security, perf,
184
+ does-it-reproduce) instead of N identical refuters — diversity catches
185
+ failure modes redundancy can't.
186
+ - **Judge panel**: generate N independent attempts from different angles
187
+ (e.g. MVP-first, risk-first, user-first), score with parallel judges,
188
+ synthesize from the winner while grafting the best ideas from runners-up.
189
+ Beats one-attempt-iterated when the solution space is wide.
190
+ - **Loop-until-dry**: for unknown-size discovery (bugs, issues, edge cases),
191
+ keep spawning finders until K consecutive rounds return nothing new.
192
+ Simple counters (while count < N) miss the tail.
193
+ - **Multi-modal sweep**: parallel agents each searching a different way
194
+ (by-container, by-content, by-entity, by-time). Each is blind to what the
195
+ others surface; useful when one search angle won't find everything.
196
+ - **Completeness critic**: a final agent that asks "what's missing —
197
+ modality not run, claim unverified, source unread?" What it finds becomes
198
+ the next round of work.
199
+ - **No silent caps**: if a workflow bounds coverage (top-N, no-retry,
200
+ sampling), `log()` what was dropped — silent truncation reads as "covered
201
+ everything" when it didn't.
202
+
203
+ Scale to what the user asked for. "find any bugs" → a few finders,
204
+ single-vote verify. "thoroughly audit this" or "be comprehensive" → larger
205
+ finder pool, 3–5 vote adversarial pass, synthesis stage. When unsure, lean
206
+ toward thoroughness for research/review/audit requests and toward brevity for
207
+ quick checks.
208
+
209
+ ## Diagnosing a run
210
+
211
+ Every run persists its script, args, and a `journal.jsonl` with one line per
212
+ completed subagent call (prompt, outcome, conversation id) under
213
+ `~/.letta/workflows/executions/<id>/`; the tool result names the paths. Before
214
+ diagnosing why a workflow returned an empty or unexpected result, read that
215
+ journal — it records each agent's actual return value and, for a `null`,
216
+ which guard or error produced it. A failed run is not resumable: fix the
217
+ script and launch it again.
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { Text, Transform, useInput } from 'ink';
3
- import React, { useEffect, useState } from 'react';
3
+ import React, { useEffect, useRef, useState } from 'react';
4
4
 
5
5
  // Use a private-use sentinel while Ink/wrap-ansi measure and wrap text.
6
6
  // wrap-ansi with trim:true strips inverse ASCII spaces at line boundaries, but
@@ -54,12 +54,19 @@ export function isControlSequence(input, key) {
54
54
  function TextInput({ value: originalValue, placeholder = '', focus = true, mask, highlightPastedText = false, showCursor = true, onChange, onSubmit, externalCursorOffset, onCursorOffsetChange }) {
55
55
  const [state, setState] = useState({ cursorOffset: (originalValue || '').length, cursorWidth: 0, killBuffer: '' });
56
56
  const { cursorOffset, cursorWidth, killBuffer } = state;
57
+ // Latest value this input knows about: the rendered value, or the value the
58
+ // input handler just reported. Several input events can land in one tick (an
59
+ // IME commit split across stdin reads) before React flushes the effect
60
+ // below, so its closure's originalValue may already be older than the caret
61
+ // in previousState; clamping against it moved the caret backwards (#4493).
62
+ const latestValueRef = useRef(originalValue || '');
63
+ latestValueRef.current = originalValue || '';
57
64
  useEffect(() => {
58
65
  setState(previousState => {
59
66
  if (!focus || !showCursor) {
60
67
  return previousState;
61
68
  }
62
- const newValue = originalValue || '';
69
+ const newValue = latestValueRef.current;
63
70
  if (previousState.cursorOffset > newValue.length - 1) {
64
71
  return { ...previousState, cursorOffset: newValue.length, cursorWidth: 0 };
65
72
  }
@@ -179,6 +186,7 @@ function TextInput({ value: originalValue, placeholder = '', focus = true, mask,
179
186
  setState(prev => ({ ...prev, cursorOffset: nextCursorOffset, cursorWidth: nextCursorWidth, killBuffer: nextKillBuffer }));
180
187
  if (typeof onCursorOffsetChange === 'function') onCursorOffsetChange(nextCursorOffset);
181
188
  if (nextValue !== originalValue) {
189
+ latestValueRef.current = nextValue;
182
190
  onChange(nextValue);
183
191
  }
184
192
  }, { isActive: focus });
@@ -1,16 +0,0 @@
1
- /**
2
- * Gemini CLI glob tool - wrapper around Letta Code's Glob tool
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface GlobGeminiArgs {
6
- pattern: string;
7
- dir_path?: string;
8
- case_sensitive?: boolean;
9
- respect_git_ignore?: boolean;
10
- respect_gemini_ignore?: boolean;
11
- }
12
- export declare function glob_gemini(args: GlobGeminiArgs): Promise<{
13
- message: string;
14
- }>;
15
- export {};
16
- //# sourceMappingURL=glob-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"glob-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/glob-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAY9B"}
@@ -1,17 +0,0 @@
1
- /**
2
- * Gemini CLI list_directory tool - wrapper around Letta Code's LS tool
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface ListDirectoryGeminiArgs {
6
- dir_path: string;
7
- ignore?: string[];
8
- file_filtering_options?: {
9
- respect_git_ignore?: boolean;
10
- respect_gemini_ignore?: boolean;
11
- };
12
- }
13
- export declare function list_directory(args: ListDirectoryGeminiArgs): Promise<{
14
- message: string;
15
- }>;
16
- export {};
17
- //# sourceMappingURL=list-directory-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-directory-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/list-directory-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,sBAAsB,CAAC,EAAE;QACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC,CAAC;CACH;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAa9B"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Gemini CLI read_file tool - wrapper around Letta Code's Read tool
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface ReadFileGeminiArgs {
6
- file_path: string;
7
- offset?: number;
8
- limit?: number;
9
- }
10
- export declare function read_file_gemini(args: ReadFileGeminiArgs): Promise<{
11
- message: string;
12
- }>;
13
- export {};
14
- //# sourceMappingURL=read-file-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"read-file-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/read-file-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAa9B"}
@@ -1,19 +0,0 @@
1
- /**
2
- * Gemini CLI read_many_files tool - new implementation for Letta Code
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface ReadManyFilesGeminiArgs {
6
- include: string[];
7
- exclude?: string[];
8
- recursive?: boolean;
9
- useDefaultExcludes?: boolean;
10
- file_filtering_options?: {
11
- respect_git_ignore?: boolean;
12
- respect_gemini_ignore?: boolean;
13
- };
14
- }
15
- export declare function read_many_files(args: ReadManyFilesGeminiArgs): Promise<{
16
- message: string;
17
- }>;
18
- export {};
19
- //# sourceMappingURL=read-many-files-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"read-many-files-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/read-many-files-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,UAAU,uBAAuB;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sBAAsB,CAAC,EAAE;QACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC,CAAC;CACH;AAaD,wBAAsB,eAAe,CACnC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA8E9B"}
@@ -1,15 +0,0 @@
1
- /**
2
- * Gemini CLI replace tool - wrapper around Letta Code's Edit tool
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface ReplaceGeminiArgs {
6
- file_path: string;
7
- old_string: string;
8
- new_string: string;
9
- expected_replacements?: number;
10
- }
11
- export declare function replace(args: ReplaceGeminiArgs): Promise<{
12
- message: string;
13
- }>;
14
- export {};
15
- //# sourceMappingURL=replace-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"replace-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/replace-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,wBAAsB,OAAO,CAC3B,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAiB9B"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Gemini CLI run_shell_command tool - wrapper around Letta Code's Bash tool
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface RunShellCommandGeminiArgs {
6
- command: string;
7
- description?: string;
8
- dir_path?: string;
9
- timeout_ms?: number;
10
- signal?: AbortSignal;
11
- onOutput?: (chunk: string, stream: "stdout" | "stderr") => void;
12
- secretEnv?: Record<string, string>;
13
- }
14
- export declare function run_shell_command(args: RunShellCommandGeminiArgs): Promise<{
15
- message: string;
16
- }>;
17
- export {};
18
- //# sourceMappingURL=run-shell-command-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-shell-command-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/run-shell-command-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,yBAAyB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,QAAQ,KAAK,IAAI,CAAC;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAa9B"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Gemini CLI search_file_content tool - wrapper around Letta Code's Grep tool
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface SearchFileContentGeminiArgs {
6
- pattern: string;
7
- dir_path?: string;
8
- include?: string;
9
- }
10
- export declare function search_file_content(args: SearchFileContentGeminiArgs): Promise<{
11
- message: string;
12
- }>;
13
- export {};
14
- //# sourceMappingURL=search-file-content-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search-file-content-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/search-file-content-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,2BAA2B;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAa9B"}
@@ -1,13 +0,0 @@
1
- /**
2
- * Gemini CLI write_file tool - wrapper around Letta Code's Write tool
3
- * Uses Gemini's exact schema and description
4
- */
5
- interface WriteFileGeminiArgs {
6
- file_path: string;
7
- content: string;
8
- }
9
- export declare function write_file_gemini(args: WriteFileGeminiArgs): Promise<{
10
- message: string;
11
- }>;
12
- export {};
13
- //# sourceMappingURL=write-file-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"write-file-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/write-file-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAM9B"}
@@ -1,16 +0,0 @@
1
- /**
2
- * Gemini CLI write_todos tool - adapter for Letta Code's todo_write
3
- * Uses Gemini's exact schema and description but adapts the params
4
- */
5
- interface WriteTodosGeminiArgs {
6
- todos: Array<{
7
- description: string;
8
- status: "pending" | "in_progress" | "completed" | "cancelled";
9
- }>;
10
- }
11
- export declare function write_todos(args: WriteTodosGeminiArgs): Promise<{
12
- message: string;
13
- todos: typeof args.todos;
14
- }>;
15
- export {};
16
- //# sourceMappingURL=write-todos-gemini.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"write-todos-gemini.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/write-todos-gemini.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,UAAU,oBAAoB;IAC5B,KAAK,EAAE,KAAK,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC;KAC/D,CAAC,CAAC;CACJ;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,CAAA;CAAE,CAAC,CA6CxD"}
@@ -1,10 +0,0 @@
1
- import type { ToolName } from "./tool-definitions";
2
- export type StartupToolsetPreference = "auto" | "codex" | "default" | "gemini" | "letta";
3
- /** Letta's model-independent toolset with one preferred tool for each job. */
4
- export declare const LETTA_TOOLS: ToolName[];
5
- export declare function loadStartupTools(params: {
6
- modelIdentifier?: string;
7
- toolset?: StartupToolsetPreference;
8
- exclude?: ToolName[];
9
- }): Promise<void>;
10
- //# sourceMappingURL=letta-toolset.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"letta-toolset.d.ts","sourceRoot":"","sources":["../../../src/tools/letta-toolset.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,MAAM,wBAAwB,GAChC,MAAM,GACN,OAAO,GACP,SAAS,GACT,QAAQ,GACR,OAAO,CAAC;AAEZ,8EAA8E;AAC9E,eAAO,MAAM,WAAW,EAAE,QAAQ,EAmBjC,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB"}
@@ -1,9 +0,0 @@
1
- import type { ToolName } from "./tool-definitions";
2
- export declare const WORKTREE_TOOL_NAMES: Set<"memory" | "Write" | "Edit" | "MultiEdit" | "apply_patch" | "ApplyPatch" | "memory_apply_patch" | "replace" | "Replace" | "write_file_gemini" | "WriteFileGemini" | "read_file" | "Task" | "exec_command" | "shell_command" | "shell" | "grep_files" | "search_file_content" | "glob_gemini" | "read_file_gemini" | "Skill" | "Read" | "view_image" | "ViewImage" | "Bash" | "Grep" | "Glob" | "LS" | "TodoWrite" | "TaskCreate" | "TaskGet" | "TaskList" | "TaskUpdate" | "AskUserQuestion" | "update_plan" | "write_stdin" | "list_dir" | "UpdatePlan" | "ShellCommand" | "Shell" | "ReadFile" | "ListDir" | "GrepFiles" | "run_shell_command" | "list_directory" | "write_todos" | "read_many_files" | "RunShellCommand" | "ReadFileGemini" | "ListDirectory" | "GlobGemini" | "SearchFileContent" | "WriteTodos" | "ReadManyFiles" | "KillBash" | "BashOutput" | "TaskOutput" | "EnterWorktree" | "ExitWorktree" | "TaskStop" | "Monitor" | "read_artifact_file" | "ReadLSP" | "SendAgentMessage" | "SetWorkingDirectory" | "write_artifact_file">;
3
- /** Built-in tool presets. Availability filters and explicit allowlists apply afterward. */
4
- export declare const ANTHROPIC_DEFAULT_TOOLS: ToolName[];
5
- export declare const OPENAI_DEFAULT_TOOLS: ToolName[];
6
- export declare const GEMINI_DEFAULT_TOOLS: ToolName[];
7
- export declare const OPENAI_PASCAL_TOOLS: ToolName[];
8
- export declare const GEMINI_PASCAL_TOOLS: ToolName[];
9
- //# sourceMappingURL=toolset-defaults.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toolset-defaults.d.ts","sourceRoot":"","sources":["../../../src/tools/toolset-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,eAAO,MAAM,mBAAmB,4/BAG9B,CAAC;AAEH,2FAA2F;AAC3F,eAAO,MAAM,uBAAuB,EAAE,QAAQ,EAqB7C,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,QAAQ,EAU1C,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,QAAQ,EAgB1C,CAAC;AAGF,eAAO,MAAM,mBAAmB,EAAE,QAAQ,EAgBzC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,QAAQ,EAiBzC,CAAC"}
@@ -1,4 +0,0 @@
1
- import type { ToolsetOption } from "./toolset-types";
2
- /** Toolsets this Letta Code runtime can load and present to clients. */
3
- export declare const TOOLSET_OPTIONS: readonly ToolsetOption[];
4
- //# sourceMappingURL=toolset-options.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toolset-options.d.ts","sourceRoot":"","sources":["../../../src/tools/toolset-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,wEAAwE;AACxE,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAyDnD,CAAC"}