Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f27bcc1592 | |||
| 651c1a28b8 | |||
| e062f0d09a | |||
| 79ea865790 | |||
| e5d58c2b5a | |||
| 9455ecd78c | |||
| 0fd09e0150 | |||
| 9a7427197b | |||
| 33be30ab04 | |||
| 6c3a90645a | |||
| 32e61529f5 | |||
| 931e668b47 | |||
| 7989c28d2e | |||
| 2965c115f1 | |||
| 7d31d5f4ec | |||
| 1a7d4184cd | |||
| 7dce23e5d9 | |||
| 06a176e33e | |||
| 42d367d72f | |||
| 6f579934db | |||
| 6d607a5953 | |||
| 4669148a4c | |||
| 82316ef6e4 | |||
| 337e4bc8c6 | |||
| d97eaf3420 | |||
| 0452f787b2 | |||
| c1317aafb3 | |||
| f17f05373e | |||
| 6691fac50e | |||
| 35c1999341 | |||
| 5575c5ff66 | |||
| 0833aca64b | |||
| 509d4ae0a9 | |||
| 4d310dda68 | |||
| e7be0d7bcc | |||
| a8f507352b | |||
| 6aa6630137 | |||
| 7ec477d40d | |||
| 19c9508fd1 | |||
| e8bc7bea44 | |||
| 1ba9d71284 | |||
| 1aa4a32066 | |||
| 22d962e761 |
@@ -118,6 +118,8 @@ documentation.
|
||||
reflects existing code.
|
||||
- **Structure:** Apply "Structure (New Docs)" rules (BLUF, headings, etc.) when
|
||||
adding new sections to existing pages.
|
||||
- **Headers**: If you change a header, you must check for links that lead to
|
||||
that header and update them.
|
||||
- **Tone:** Ensure the tone is active and engaging. Use "you" and contractions.
|
||||
- **Clarity:** Correct awkward wording, spelling, and grammar. Rephrase
|
||||
sentences to make them easier for users to understand.
|
||||
@@ -133,7 +135,8 @@ and that all links are functional.
|
||||
technical behavior.
|
||||
2. **Self-review:** Re-read changes for formatting, correctness, and flow.
|
||||
3. **Link check:** Verify all new and existing links leading to or from modified
|
||||
pages.
|
||||
pages. If you changed a header, ensure that any links that lead to it are
|
||||
updated.
|
||||
4. **Format:** Once all changes are complete, ask to execute `npm run format`
|
||||
to ensure consistent formatting across the project. If the user confirms,
|
||||
execute the command.
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
name: string-reviewer
|
||||
description: >
|
||||
Use this skill when asked to review text and user-facing strings within the codebase. It ensures that these strings follow rules on clarity,
|
||||
usefulness, brevity and style.
|
||||
---
|
||||
|
||||
# String Reviewer
|
||||
|
||||
## Instructions
|
||||
|
||||
Act as a Senior UX Writer. Look for user-facing strings that are too long,
|
||||
unclear, or inconsistent. This includes inline text, error messages, and other
|
||||
user-facing text.
|
||||
|
||||
Do NOT automatically change strings without user approval. You must only suggest
|
||||
changes and do not attempt to rewrite them directly unless the user explicitly
|
||||
asks you to do so.
|
||||
|
||||
## Core voice principles
|
||||
|
||||
The system prioritizes deterministic clarity over conversational fluff. We
|
||||
provide telemetry, not etiquette, ensuring the user retains absolute agency..
|
||||
|
||||
1. **Deterministic clarity:** Distinguish between certain system/service states
|
||||
(Cloud Billing, IAM, the System) and probabilistic AI analysis (Gemini).
|
||||
2. **System transparency:** Replace "Loading..." with active technical telemetry
|
||||
(e.g., Tracing stack traces...). Keep status updates under 5 words.
|
||||
3. **Front-loaded actionability:** Always use the [Goal] + [Action] pattern.
|
||||
Lead with intent so users can scan left-to-right.
|
||||
4. **Agentic error recovery:** Every error must be a pivot point. Pair failures
|
||||
with one-click recovery commands or suggested prompts.
|
||||
5. **Contextual humility:** Reserve disclaimers and "be careful" warnings for P0
|
||||
(destructive/irreversible) tasks only. Stop warning-fatigue.
|
||||
|
||||
## The writing checklist
|
||||
|
||||
Use this checklist to audit UI strings and AI responses.
|
||||
|
||||
### Identity and voice
|
||||
- **Eliminate the "I":** Remove all first-person pronouns (I, me, my, mine).
|
||||
- **Subject attribution:** Refer to the AI as Gemini and the infrastructure as
|
||||
the - system or the CLI.
|
||||
- **Active voice:** Ensure the subject (Gemini or the system) is clearly
|
||||
performing the action.
|
||||
- **Ownership rule:** Use the system for execution (doing) and Gemini for
|
||||
analysis (thinking)
|
||||
|
||||
### Structural scannability
|
||||
- **The skip test:** Do the first 3 words describe the user’s intent? If not,
|
||||
rewrite.
|
||||
- **Goal-first sequence:** Use the template: [To Accomplish X] + [Do Y].
|
||||
- **The 5-word rule:** Keep status updates and loading states under 5 words.
|
||||
- **Telemetry over etiquette:** Remove polite filler (Please wait, Thank you,
|
||||
Certainly). Replace with raw data or progress indicators.
|
||||
- **Micro-state cycles:** For tasks $> 3$ seconds, cycle through specific
|
||||
sub-states (e.g., Parsing logs... ➔ Identifying patterns...) to show momentum.
|
||||
|
||||
|
||||
### Technical accuracy and humility
|
||||
- **Verb signal check:** Use deterministic verbs (is, will, must) for system
|
||||
state/infrastructure.
|
||||
- Use probabilistic verbs (suggests, appears, may, identifies) for AI output.
|
||||
- **No 100% certainty:** Never attribute absolute certainty to model-generated
|
||||
content.
|
||||
- **Precision over fuzziness:** Use technical metrics (latency, tokens, compute) instead of "speed" or "cost."
|
||||
- **Instructional warnings:** Every warning must include a specific corrective action (e.g., "Perform a dry-run first" or "Review line 42").
|
||||
|
||||
### Agentic error recovery
|
||||
- **The one-step rule:** Pair every error message with exactly one immediate
|
||||
path to a fix (command, link, or prompt).
|
||||
- **Human-first:** Provide a human-readable explanation before machine error
|
||||
codes (e.g., 404, 500).
|
||||
- **Suggested prompts:** Offer specific text for the user to copy/click like
|
||||
“Ask Gemini: 'Explain this port error.'”
|
||||
|
||||
### Use consistent terminology
|
||||
|
||||
Ensure all terminology aligns with the project [word
|
||||
list](./references/word-list.md).
|
||||
|
||||
If a string uses a term marked "do not use" or "use with caution," provide a
|
||||
correction based on the preferred terms.
|
||||
|
||||
## Ensure consistent style for settings
|
||||
|
||||
If `packages/cli/src/config/settingsSchema.ts` is modified, confirm labels and
|
||||
descriptions specifically follow the unique [Settings
|
||||
guidelines](./references/settings.md).
|
||||
|
||||
## Output format
|
||||
When suggesting changes, always present your review using the following list
|
||||
format. Do not provide suggestions outside of this list..
|
||||
|
||||
```
|
||||
1. **{Rationale/Principle Violated}**
|
||||
- ❌ "{incorrect phrase}"
|
||||
- ✅ `"{corrected phrase}"`
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
# Settings
|
||||
|
||||
## Noun-First Labeling (Scannability)
|
||||
|
||||
Labels must start with the subject of the setting, not the action. This allows
|
||||
users to scan for the feature they want to change.
|
||||
|
||||
- **Rule:** `[Noun]` `[Attribute/Action]`
|
||||
- **Example:** `Show line numbers` becomes simply `Line numbers`
|
||||
|
||||
## Positive Boolean Logic (Cognitive Ease)
|
||||
|
||||
Eliminate "double negatives." Booleans should represent the presence of a
|
||||
feature, not its absence.
|
||||
|
||||
- **Rule:** Replace `Disable {feature}` or `Hide {Feature}` with
|
||||
`{Feature} enabled` or simply `{Feature}`.
|
||||
- **Example:** Change "Disable auto update" to "Auto update".
|
||||
- **Implementation:** Invert the boolean value in your config loader so true
|
||||
always equals `On`
|
||||
|
||||
## Verb Stripping (Brevity)
|
||||
|
||||
Remove redundant leading verbs like "Enable," "Use," "Display," or "Show" unless
|
||||
they are part of a specific technical term.
|
||||
|
||||
- **Rule**: If the label works without the verb, remove it
|
||||
- **Example**: Change `Enable prompt completion` to `Prompt completion`
|
||||
@@ -0,0 +1,61 @@
|
||||
## Terms
|
||||
|
||||
### Preferred
|
||||
|
||||
- Use **create** when a user is creating or setting up something.
|
||||
- Use **allow** instead of **may** to indicate that permission has been granted
|
||||
to perform some action.
|
||||
- Use **canceled**, not **cancelled**.
|
||||
- Use **configure** to refer to the process of changing the attributes of a
|
||||
feature, even if that includes turning on or off the feature.
|
||||
- Use **delete** when the action being performed is destructive.
|
||||
- Use **enable** for binary operations that turn a feature or API on. Use "turn
|
||||
on" and "turn off" instead of "enable" and "disable" for other situations.
|
||||
- Use **key combination** to refer to pressing multiple keys simultaneously.
|
||||
- Use **key sequence** to refer to pressing multiple keys separately in order.
|
||||
- Use **modify** to refer to something that has changed vs obtaining the latest
|
||||
version of something.
|
||||
- Use **remove** when the action being performed takes an item out of a larger
|
||||
whole, but doesn't destroy the item itself.
|
||||
- Use **set up** as a verb. Use **setup** as a noun or adjective.
|
||||
- Use **show**. In general, use paired with **hide**.
|
||||
- Use **sign in**, **sign out** as a verb. Use **sign-in** or **sign-out** as a
|
||||
noun or adjective.
|
||||
- Use **update** when you mean to obtain the latest version of something.
|
||||
- Use **want** instead of **like** or **would like**.
|
||||
|
||||
#### Don't use
|
||||
|
||||
- Don't use **etc.** It's redundant. To convey that a series is incomplete,
|
||||
introduce it with "such as" instead.
|
||||
- Don't use **hostname**, use "host name" instead.
|
||||
- Don't use **in order to**. It's too formal. "Before you can" is usually better
|
||||
in UI text.
|
||||
- Don't use **one or more**. Specify the quantity where possible. Use "at least
|
||||
one" when the quantity is 1+ but you can't be sure of the number. Likewise,
|
||||
use "at least one" when the user must choose a quantity of 1+.
|
||||
- Don't use the terms **log in**, **log on**, **login**, **logout** or **log
|
||||
out**.
|
||||
- Don't use **like** or **would you like**. Use **want** instead. Better yet,
|
||||
rephrase so that it's not referring to the user's emotional state, but rather
|
||||
what is required.
|
||||
|
||||
#### Use with caution
|
||||
|
||||
- Avoid using **leverage**, especially as a verb. "Leverage" is considered a
|
||||
buzzword largely devoid of meaning apart from the simpler "use".
|
||||
- Avoid using **once** as a synonym for "after". Typically, when "once" is used
|
||||
in this way, it is followed by a verb in the perfect tense.
|
||||
- Don't use **e.g.** Use "example", "such as", "like", or "for example". The
|
||||
phrase is always followed by a comma.
|
||||
- Don't use **i.e.** unless absolutely essential to make text fit. Use "that is"
|
||||
instead.
|
||||
- Use **disable** for binary operations that turn a feature or API off. Use
|
||||
"turn on" and "turn off" instead of "enable" and "disable" for other
|
||||
situations. For UI elements that are not available, use "dimmed" instead of
|
||||
"disabled".
|
||||
- Use **please** only when you're asking the user to do something inconvenient,
|
||||
not just following the instructions in a typical flow.
|
||||
- Use **really** sparingly in such constructions as "Do you really want to..."
|
||||
Because of the weight it puts on the decision, it should be used to confirm
|
||||
actions that the user is extremely unlikely to make.
|
||||
@@ -320,11 +320,9 @@ npm run lint
|
||||
|
||||
- Please adhere to the coding style, patterns, and conventions used throughout
|
||||
the existing codebase.
|
||||
- Consult
|
||||
[GEMINI.md](https://github.com/google-gemini/gemini-cli/blob/main/GEMINI.md)
|
||||
(typically found in the project root) for specific instructions related to
|
||||
AI-assisted development, including conventions for React, comments, and Git
|
||||
usage.
|
||||
- Consult [GEMINI.md](../GEMINI.md) (typically found in the project root) for
|
||||
specific instructions related to AI-assisted development, including
|
||||
conventions for React, comments, and Git usage.
|
||||
- **Imports:** Pay special attention to import paths. The project uses ESLint to
|
||||
enforce restrictions on relative imports between packages.
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ See [Releases](./docs/releases.md) for more details.
|
||||
|
||||
### Preview
|
||||
|
||||
New preview releases will be published each week at UTC 2359 on Tuesdays. These
|
||||
New preview releases will be published each week at UTC 23:59 on Tuesdays. These
|
||||
releases will not have been fully vetted and may contain regressions or other
|
||||
outstanding issues. Please help us test and install with `preview` tag.
|
||||
|
||||
@@ -87,7 +87,7 @@ npm install -g @google/gemini-cli@preview
|
||||
|
||||
### Stable
|
||||
|
||||
- New stable releases will be published each week at UTC 2000 on Tuesdays, this
|
||||
- New stable releases will be published each week at UTC 20:00 on Tuesdays, this
|
||||
will be the full promotion of last week's `preview` release + any bug fixes
|
||||
and validations. Use `latest` tag.
|
||||
|
||||
@@ -97,7 +97,7 @@ npm install -g @google/gemini-cli@latest
|
||||
|
||||
### Nightly
|
||||
|
||||
- New releases will be published each day at UTC 0000. This will be all changes
|
||||
- New releases will be published each day at UTC 00:00. This will be all changes
|
||||
from the main branch as represented at time of release. It should be assumed
|
||||
there are pending validations and issues. Use `nightly` tag.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Preview release: v0.33.0-preview.1
|
||||
# Preview release: v0.33.0-preview.4
|
||||
|
||||
Released: March 04, 2026
|
||||
Released: March 06, 2026
|
||||
|
||||
Our preview release includes the latest, new, and experimental features. This
|
||||
release may not be as stable as our [latest weekly release](latest.md).
|
||||
@@ -29,159 +29,173 @@ npm install -g @google/gemini-cli@preview
|
||||
|
||||
## What's Changed
|
||||
|
||||
- fix(patch): cherry-pick 7ec477d to release/v0.33.0-preview.3-pr-21305 to patch
|
||||
version v0.33.0-preview.3 and create version 0.33.0-preview.4 by
|
||||
@gemini-cli-robot in
|
||||
[#21349](https://github.com/google-gemini/gemini-cli/pull/21349)
|
||||
- fix(patch): cherry-pick 0135b03 to release/v0.33.0-preview.2-pr-21171
|
||||
[CONFLICTS] by @gemini-cli-robot in
|
||||
[#21336](https://github.com/google-gemini/gemini-cli/pull/21336)
|
||||
- fix(patch): cherry-pick 173376b to release/v0.33.0-preview.1-pr-21157 to patch
|
||||
version v0.33.0-preview.1 and create version 0.33.0-preview.2 by
|
||||
@gemini-cli-robot in
|
||||
[#21300](https://github.com/google-gemini/gemini-cli/pull/21300)
|
||||
- fix(patch): cherry-pick 173376b to release/v0.33.0-preview.1-pr-21157 to patch
|
||||
version v0.33.0-preview.1 and create version 0.33.0-preview.2 by
|
||||
@gemini-cli-robot in
|
||||
[#21300](https://github.com/google-gemini/gemini-cli/pull/21300)
|
||||
- fix(patch): cherry-pick 0659ad1 to release/v0.33.0-preview.0-pr-21042 to patch
|
||||
version v0.33.0-preview.0 and create version 0.33.0-preview.1 by
|
||||
@gemini-cli-robot in
|
||||
[#21047](https://github.com/google-gemini/gemini-cli/pull/21047)
|
||||
|
||||
* Docs: Update model docs to remove Preview Features. by @jkcinouye in
|
||||
- Docs: Update model docs to remove Preview Features. by @jkcinouye in
|
||||
[#20084](https://github.com/google-gemini/gemini-cli/pull/20084)
|
||||
* docs: fix typo in installation documentation by @AdityaSharma-Git3207 in
|
||||
- docs: fix typo in installation documentation by @AdityaSharma-Git3207 in
|
||||
[#20153](https://github.com/google-gemini/gemini-cli/pull/20153)
|
||||
* docs: add Windows PowerShell equivalents for environments and scripting by
|
||||
- docs: add Windows PowerShell equivalents for environments and scripting by
|
||||
@scidomino in [#20333](https://github.com/google-gemini/gemini-cli/pull/20333)
|
||||
* fix(core): parse raw ASCII buffer strings in Gaxios errors by @sehoon38 in
|
||||
- fix(core): parse raw ASCII buffer strings in Gaxios errors by @sehoon38 in
|
||||
[#20626](https://github.com/google-gemini/gemini-cli/pull/20626)
|
||||
* chore(release): bump version to 0.33.0-nightly.20260227.ba149afa0 by @galz10
|
||||
- chore(release): bump version to 0.33.0-nightly.20260227.ba149afa0 by @galz10
|
||||
in [#20637](https://github.com/google-gemini/gemini-cli/pull/20637)
|
||||
* fix(github): use robot PAT for automated PRs to pass CLA check by @galz10 in
|
||||
- fix(github): use robot PAT for automated PRs to pass CLA check by @galz10 in
|
||||
[#20641](https://github.com/google-gemini/gemini-cli/pull/20641)
|
||||
* chore/release: bump version to 0.33.0-nightly.20260228.1ca5c05d0 by
|
||||
- chore/release: bump version to 0.33.0-nightly.20260228.1ca5c05d0 by
|
||||
@gemini-cli-robot in
|
||||
[#20644](https://github.com/google-gemini/gemini-cli/pull/20644)
|
||||
* Changelog for v0.31.0 by @gemini-cli-robot in
|
||||
- Changelog for v0.31.0 by @gemini-cli-robot in
|
||||
[#20634](https://github.com/google-gemini/gemini-cli/pull/20634)
|
||||
* fix: use full paths for ACP diff payloads by @JagjeevanAK in
|
||||
- fix: use full paths for ACP diff payloads by @JagjeevanAK in
|
||||
[#19539](https://github.com/google-gemini/gemini-cli/pull/19539)
|
||||
* Changelog for v0.32.0-preview.0 by @gemini-cli-robot in
|
||||
- Changelog for v0.32.0-preview.0 by @gemini-cli-robot in
|
||||
[#20627](https://github.com/google-gemini/gemini-cli/pull/20627)
|
||||
* fix: acp/zed race condition between MCP initialisation and prompt by
|
||||
- fix: acp/zed race condition between MCP initialisation and prompt by
|
||||
@kartikangiras in
|
||||
[#20205](https://github.com/google-gemini/gemini-cli/pull/20205)
|
||||
* fix(cli): reset themeManager between tests to ensure isolation by
|
||||
- fix(cli): reset themeManager between tests to ensure isolation by
|
||||
@NTaylorMullen in
|
||||
[#20598](https://github.com/google-gemini/gemini-cli/pull/20598)
|
||||
* refactor(core): Extract tool parameter names as constants by @SandyTao520 in
|
||||
- refactor(core): Extract tool parameter names as constants by @SandyTao520 in
|
||||
[#20460](https://github.com/google-gemini/gemini-cli/pull/20460)
|
||||
* fix(cli): resolve autoThemeSwitching when background hasn't changed but theme
|
||||
- fix(cli): resolve autoThemeSwitching when background hasn't changed but theme
|
||||
mismatches by @sehoon38 in
|
||||
[#20706](https://github.com/google-gemini/gemini-cli/pull/20706)
|
||||
* feat(skills): add github-issue-creator skill by @sehoon38 in
|
||||
- feat(skills): add github-issue-creator skill by @sehoon38 in
|
||||
[#20709](https://github.com/google-gemini/gemini-cli/pull/20709)
|
||||
* fix(cli): allow sub-agent confirmation requests in UI while preventing
|
||||
- fix(cli): allow sub-agent confirmation requests in UI while preventing
|
||||
background flicker by @abhipatel12 in
|
||||
[#20722](https://github.com/google-gemini/gemini-cli/pull/20722)
|
||||
* Merge User and Agent Card Descriptions #20849 by @adamfweidman in
|
||||
- Merge User and Agent Card Descriptions #20849 by @adamfweidman in
|
||||
[#20850](https://github.com/google-gemini/gemini-cli/pull/20850)
|
||||
* fix(core): reduce LLM-based loop detection false positives by @SandyTao520 in
|
||||
- fix(core): reduce LLM-based loop detection false positives by @SandyTao520 in
|
||||
[#20701](https://github.com/google-gemini/gemini-cli/pull/20701)
|
||||
* fix(plan): deflake plan mode integration tests by @Adib234 in
|
||||
- fix(plan): deflake plan mode integration tests by @Adib234 in
|
||||
[#20477](https://github.com/google-gemini/gemini-cli/pull/20477)
|
||||
* Add /unassign support by @scidomino in
|
||||
- Add /unassign support by @scidomino in
|
||||
[#20864](https://github.com/google-gemini/gemini-cli/pull/20864)
|
||||
* feat(core): implement HTTP authentication support for A2A remote agents by
|
||||
- feat(core): implement HTTP authentication support for A2A remote agents by
|
||||
@SandyTao520 in
|
||||
[#20510](https://github.com/google-gemini/gemini-cli/pull/20510)
|
||||
* feat(core): centralize read_file limits and update gemini-3 description by
|
||||
- feat(core): centralize read_file limits and update gemini-3 description by
|
||||
@aishaneeshah in
|
||||
[#20619](https://github.com/google-gemini/gemini-cli/pull/20619)
|
||||
* Do not block CI on evals by @gundermanc in
|
||||
- Do not block CI on evals by @gundermanc in
|
||||
[#20870](https://github.com/google-gemini/gemini-cli/pull/20870)
|
||||
* document node limitation for shift+tab by @scidomino in
|
||||
- document node limitation for shift+tab by @scidomino in
|
||||
[#20877](https://github.com/google-gemini/gemini-cli/pull/20877)
|
||||
* Add install as an option when extension is selected. by @DavidAPierce in
|
||||
- Add install as an option when extension is selected. by @DavidAPierce in
|
||||
[#20358](https://github.com/google-gemini/gemini-cli/pull/20358)
|
||||
* Update CODEOWNERS for README.md reviewers by @g-samroberts in
|
||||
- Update CODEOWNERS for README.md reviewers by @g-samroberts in
|
||||
[#20860](https://github.com/google-gemini/gemini-cli/pull/20860)
|
||||
* feat(core): truncate large MCP tool output by @SandyTao520 in
|
||||
- feat(core): truncate large MCP tool output by @SandyTao520 in
|
||||
[#19365](https://github.com/google-gemini/gemini-cli/pull/19365)
|
||||
* Subagent activity UX. by @gundermanc in
|
||||
- Subagent activity UX. by @gundermanc in
|
||||
[#17570](https://github.com/google-gemini/gemini-cli/pull/17570)
|
||||
* style(cli) : Dialog pattern for /hooks Command by @AbdulTawabJuly in
|
||||
- style(cli) : Dialog pattern for /hooks Command by @AbdulTawabJuly in
|
||||
[#17930](https://github.com/google-gemini/gemini-cli/pull/17930)
|
||||
* feat: redesign header to be compact with ASCII icon by @keithguerin in
|
||||
- feat: redesign header to be compact with ASCII icon by @keithguerin in
|
||||
[#18713](https://github.com/google-gemini/gemini-cli/pull/18713)
|
||||
* fix(core): ensure subagents use qualified MCP tool names by @abhipatel12 in
|
||||
- fix(core): ensure subagents use qualified MCP tool names by @abhipatel12 in
|
||||
[#20801](https://github.com/google-gemini/gemini-cli/pull/20801)
|
||||
* feat(core): support authenticated A2A agent card discovery by @SandyTao520 in
|
||||
- feat(core): support authenticated A2A agent card discovery by @SandyTao520 in
|
||||
[#20622](https://github.com/google-gemini/gemini-cli/pull/20622)
|
||||
* refactor(cli): fully remove React anti patterns, improve type safety and fix
|
||||
- refactor(cli): fully remove React anti patterns, improve type safety and fix
|
||||
UX oversights in SettingsDialog.tsx by @psinha40898 in
|
||||
[#18963](https://github.com/google-gemini/gemini-cli/pull/18963)
|
||||
* Adding MCPOAuthProvider implementing the MCPSDK OAuthClientProvider by
|
||||
- Adding MCPOAuthProvider implementing the MCPSDK OAuthClientProvider by
|
||||
@Nayana-Parameswarappa in
|
||||
[#20121](https://github.com/google-gemini/gemini-cli/pull/20121)
|
||||
* feat(core): add tool name validation in TOML policy files by @allenhutchison
|
||||
- feat(core): add tool name validation in TOML policy files by @allenhutchison
|
||||
in [#19281](https://github.com/google-gemini/gemini-cli/pull/19281)
|
||||
* docs: fix broken markdown links in main README.md by @Hamdanbinhashim in
|
||||
- docs: fix broken markdown links in main README.md by @Hamdanbinhashim in
|
||||
[#20300](https://github.com/google-gemini/gemini-cli/pull/20300)
|
||||
* refactor(core): replace manual syncPlanModeTools with declarative policy rules
|
||||
- refactor(core): replace manual syncPlanModeTools with declarative policy rules
|
||||
by @jerop in [#20596](https://github.com/google-gemini/gemini-cli/pull/20596)
|
||||
* fix(core): increase default headers timeout to 5 minutes by @gundermanc in
|
||||
- fix(core): increase default headers timeout to 5 minutes by @gundermanc in
|
||||
[#20890](https://github.com/google-gemini/gemini-cli/pull/20890)
|
||||
* feat(admin): enable 30 day default retention for chat history & remove warning
|
||||
- feat(admin): enable 30 day default retention for chat history & remove warning
|
||||
by @skeshive in
|
||||
[#20853](https://github.com/google-gemini/gemini-cli/pull/20853)
|
||||
* feat(plan): support annotating plans with feedback for iteration by @Adib234
|
||||
- feat(plan): support annotating plans with feedback for iteration by @Adib234
|
||||
in [#20876](https://github.com/google-gemini/gemini-cli/pull/20876)
|
||||
* Add some dos and don'ts to behavioral evals README. by @gundermanc in
|
||||
- Add some dos and don'ts to behavioral evals README. by @gundermanc in
|
||||
[#20629](https://github.com/google-gemini/gemini-cli/pull/20629)
|
||||
* fix(core): skip telemetry logging for AbortError exceptions by @yunaseoul in
|
||||
- fix(core): skip telemetry logging for AbortError exceptions by @yunaseoul in
|
||||
[#19477](https://github.com/google-gemini/gemini-cli/pull/19477)
|
||||
* fix(core): restrict "System: Please continue" invalid stream retry to Gemini 2
|
||||
- fix(core): restrict "System: Please continue" invalid stream retry to Gemini 2
|
||||
models by @SandyTao520 in
|
||||
[#20897](https://github.com/google-gemini/gemini-cli/pull/20897)
|
||||
* ci(evals): only run evals in CI if prompts or tools changed by @gundermanc in
|
||||
- ci(evals): only run evals in CI if prompts or tools changed by @gundermanc in
|
||||
[#20898](https://github.com/google-gemini/gemini-cli/pull/20898)
|
||||
* Build binary by @aswinashok44 in
|
||||
- Build binary by @aswinashok44 in
|
||||
[#18933](https://github.com/google-gemini/gemini-cli/pull/18933)
|
||||
* Code review fixes as a pr by @jacob314 in
|
||||
- Code review fixes as a pr by @jacob314 in
|
||||
[#20612](https://github.com/google-gemini/gemini-cli/pull/20612)
|
||||
* fix(ci): handle empty APP_ID in stale PR closer by @bdmorgan in
|
||||
- fix(ci): handle empty APP_ID in stale PR closer by @bdmorgan in
|
||||
[#20919](https://github.com/google-gemini/gemini-cli/pull/20919)
|
||||
* feat(cli): invert context window display to show usage by @keithguerin in
|
||||
- feat(cli): invert context window display to show usage by @keithguerin in
|
||||
[#20071](https://github.com/google-gemini/gemini-cli/pull/20071)
|
||||
* fix(plan): clean up session directories and plans on deletion by @jerop in
|
||||
- fix(plan): clean up session directories and plans on deletion by @jerop in
|
||||
[#20914](https://github.com/google-gemini/gemini-cli/pull/20914)
|
||||
* fix(core): enforce optionality for API response fields in code_assist by
|
||||
- fix(core): enforce optionality for API response fields in code_assist by
|
||||
@sehoon38 in [#20714](https://github.com/google-gemini/gemini-cli/pull/20714)
|
||||
* feat(extensions): add support for plan directory in extension manifest by
|
||||
- feat(extensions): add support for plan directory in extension manifest by
|
||||
@mahimashanware in
|
||||
[#20354](https://github.com/google-gemini/gemini-cli/pull/20354)
|
||||
* feat(plan): enable built-in research subagents in plan mode by @Adib234 in
|
||||
- feat(plan): enable built-in research subagents in plan mode by @Adib234 in
|
||||
[#20972](https://github.com/google-gemini/gemini-cli/pull/20972)
|
||||
* feat(agents): directly indicate auth required state by @adamfweidman in
|
||||
- feat(agents): directly indicate auth required state by @adamfweidman in
|
||||
[#20986](https://github.com/google-gemini/gemini-cli/pull/20986)
|
||||
* fix(cli): wait for background auto-update before relaunching by @scidomino in
|
||||
- fix(cli): wait for background auto-update before relaunching by @scidomino in
|
||||
[#20904](https://github.com/google-gemini/gemini-cli/pull/20904)
|
||||
* fix: pre-load @scripts/copy_files.js references from external editor prompts
|
||||
- fix: pre-load @scripts/copy_files.js references from external editor prompts
|
||||
by @kartikangiras in
|
||||
[#20963](https://github.com/google-gemini/gemini-cli/pull/20963)
|
||||
* feat(evals): add behavioral evals for ask_user tool by @Adib234 in
|
||||
- feat(evals): add behavioral evals for ask_user tool by @Adib234 in
|
||||
[#20620](https://github.com/google-gemini/gemini-cli/pull/20620)
|
||||
* refactor common settings logic for skills,agents by @ishaanxgupta in
|
||||
- refactor common settings logic for skills,agents by @ishaanxgupta in
|
||||
[#17490](https://github.com/google-gemini/gemini-cli/pull/17490)
|
||||
* Update docs-writer skill with new resource by @g-samroberts in
|
||||
- Update docs-writer skill with new resource by @g-samroberts in
|
||||
[#20917](https://github.com/google-gemini/gemini-cli/pull/20917)
|
||||
* fix(cli): pin clipboardy to ~5.2.x by @scidomino in
|
||||
- fix(cli): pin clipboardy to ~5.2.x by @scidomino in
|
||||
[#21009](https://github.com/google-gemini/gemini-cli/pull/21009)
|
||||
* feat: Implement slash command handling in ACP for
|
||||
- feat: Implement slash command handling in ACP for
|
||||
`/memory`,`/init`,`/extensions` and `/restore` by @sripasg in
|
||||
[#20528](https://github.com/google-gemini/gemini-cli/pull/20528)
|
||||
* Docs/add hooks reference by @AadithyaAle in
|
||||
- Docs/add hooks reference by @AadithyaAle in
|
||||
[#20961](https://github.com/google-gemini/gemini-cli/pull/20961)
|
||||
* feat(plan): add copy subcommand to plan (#20491) by @ruomengz in
|
||||
- feat(plan): add copy subcommand to plan (#20491) by @ruomengz in
|
||||
[#20988](https://github.com/google-gemini/gemini-cli/pull/20988)
|
||||
* fix(core): sanitize and length-check MCP tool qualified names by @abhipatel12
|
||||
- fix(core): sanitize and length-check MCP tool qualified names by @abhipatel12
|
||||
in [#20987](https://github.com/google-gemini/gemini-cli/pull/20987)
|
||||
* Format the quota/limit style guide. by @g-samroberts in
|
||||
- Format the quota/limit style guide. by @g-samroberts in
|
||||
[#21017](https://github.com/google-gemini/gemini-cli/pull/21017)
|
||||
* fix(core): send shell output to model on cancel by @devr0306 in
|
||||
- fix(core): send shell output to model on cancel by @devr0306 in
|
||||
[#20501](https://github.com/google-gemini/gemini-cli/pull/20501)
|
||||
* remove hardcoded tiername when missing tier by @sehoon38 in
|
||||
- remove hardcoded tiername when missing tier by @sehoon38 in
|
||||
[#21022](https://github.com/google-gemini/gemini-cli/pull/21022)
|
||||
* feat(acp): add set models interface by @skeshive in
|
||||
- feat(acp): add set models interface by @skeshive in
|
||||
[#20991](https://github.com/google-gemini/gemini-cli/pull/20991)
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.32.0-preview.0...v0.33.0-preview.1
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.32.0-preview.0...v0.33.0-preview.4
|
||||
|
||||
@@ -369,7 +369,7 @@ those files are not automatically deleted and must be managed manually.
|
||||
[model routing]: /docs/cli/telemetry.md#model-routing
|
||||
[preferred external editor]: /docs/reference/configuration.md#general
|
||||
[session retention]: /docs/cli/session-management.md#session-retention
|
||||
[extensions]: /docs/extensions/index.md
|
||||
[extensions]: /docs/extensions/
|
||||
[Conductor]: https://github.com/gemini-cli-extensions/conductor
|
||||
[open an issue]: https://github.com/google-gemini/gemini-cli/issues
|
||||
[Agent Skills]: /docs/cli/skills.md
|
||||
|
||||
@@ -147,7 +147,6 @@ they appear in the UI.
|
||||
| Plan | `experimental.plan` | Enable planning features (Plan Mode and tools). | `false` |
|
||||
| Model Steering | `experimental.modelSteering` | Enable model steering (user hints) to guide the model during tool execution. | `false` |
|
||||
| Direct Web Fetch | `experimental.directWebFetch` | Enable web fetch behavior that bypasses LLM summarization. | `false` |
|
||||
| Enable Gemma Model Router | `experimental.gemmaModelRouter.enabled` | Enable the Gemma Model Router. Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim. | `false` |
|
||||
|
||||
### Skills
|
||||
|
||||
|
||||
@@ -17,9 +17,10 @@ prefix.
|
||||
|
||||
**Example:** `!ls -la`
|
||||
|
||||
This executes `ls -la` immediately and prints the output to your terminal. The
|
||||
AI doesn't "see" this output unless you paste it back into the chat or use it in
|
||||
a prompt.
|
||||
This executes `ls -la` immediately and prints the output to your terminal.
|
||||
Gemini CLI also records the command and its output in the current session
|
||||
context, so the model can reference it in follow-up prompts. Very large outputs
|
||||
may be truncated.
|
||||
|
||||
### Scenario: Entering Shell mode
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ session's token usage, as well as your overall quota and usage for the supported
|
||||
models.
|
||||
|
||||
For more information on the `/stats` command and its subcommands, see the
|
||||
[Command Reference](../../reference/commands.md#stats).
|
||||
[Command Reference](../reference/commands.md#stats).
|
||||
|
||||
## Next steps
|
||||
|
||||
|
||||
@@ -175,6 +175,11 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Description:** Minimum retention period (safety limit, defaults to "1d")
|
||||
- **Default:** `"1d"`
|
||||
|
||||
- **`general.sessionRetention.warningAcknowledged`** (boolean):
|
||||
- **Description:** Whether the user has acknowledged the session retention
|
||||
warning
|
||||
- **Default:** `false`
|
||||
|
||||
#### `output`
|
||||
|
||||
- **`output.format`** (enum):
|
||||
@@ -1041,8 +1046,8 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`experimental.gemmaModelRouter.enabled`** (boolean):
|
||||
- **Description:** Enable the Gemma Model Router. Requires a local endpoint
|
||||
serving Gemma via the Gemini API using LiteRT-LM shim.
|
||||
- **Description:** Enable the Gemma Model Router (experimental). Requires a
|
||||
local endpoint serving Gemma via the Gemini API using LiteRT-LM shim.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
|
||||
@@ -8,119 +8,119 @@ available combinations.
|
||||
|
||||
#### Basic Controls
|
||||
|
||||
| Action | Keys |
|
||||
| --------------------------------------------------------------- | --------------------- |
|
||||
| Confirm the current selection or choice. | `Enter` |
|
||||
| Dismiss dialogs or cancel the current focus. | `Esc`<br />`Ctrl + [` |
|
||||
| Cancel the current request or quit the CLI when input is empty. | `Ctrl + C` |
|
||||
| Exit the CLI when the input buffer is empty. | `Ctrl + D` |
|
||||
| Action | Keys |
|
||||
| --------------------------------------------------------------- | ------------------- |
|
||||
| Confirm the current selection or choice. | `Enter` |
|
||||
| Dismiss dialogs or cancel the current focus. | `Esc`<br />`Ctrl+[` |
|
||||
| Cancel the current request or quit the CLI when input is empty. | `Ctrl+C` |
|
||||
| Exit the CLI when the input buffer is empty. | `Ctrl+D` |
|
||||
|
||||
#### Cursor Movement
|
||||
|
||||
| Action | Keys |
|
||||
| ------------------------------------------- | ------------------------------------------------------------ |
|
||||
| Move the cursor to the start of the line. | `Ctrl + A`<br />`Home (no Shift, Ctrl)` |
|
||||
| Move the cursor to the end of the line. | `Ctrl + E`<br />`End (no Shift, Ctrl)` |
|
||||
| Move the cursor up one line. | `Up Arrow (no Shift, Alt, Ctrl, Cmd)` |
|
||||
| Move the cursor down one line. | `Down Arrow (no Shift, Alt, Ctrl, Cmd)` |
|
||||
| Move the cursor one character to the left. | `Left Arrow (no Shift, Alt, Ctrl, Cmd)` |
|
||||
| Move the cursor one character to the right. | `Right Arrow (no Shift, Alt, Ctrl, Cmd)`<br />`Ctrl + F` |
|
||||
| Move the cursor one word to the left. | `Ctrl + Left Arrow`<br />`Alt + Left Arrow`<br />`Alt + B` |
|
||||
| Move the cursor one word to the right. | `Ctrl + Right Arrow`<br />`Alt + Right Arrow`<br />`Alt + F` |
|
||||
| Action | Keys |
|
||||
| ------------------------------------------- | ------------------------------------------ |
|
||||
| Move the cursor to the start of the line. | `Ctrl+A`<br />`Home` |
|
||||
| Move the cursor to the end of the line. | `Ctrl+E`<br />`End` |
|
||||
| Move the cursor up one line. | `Up` |
|
||||
| Move the cursor down one line. | `Down` |
|
||||
| Move the cursor one character to the left. | `Left` |
|
||||
| Move the cursor one character to the right. | `Right`<br />`Ctrl+F` |
|
||||
| Move the cursor one word to the left. | `Ctrl+Left`<br />`Alt+Left`<br />`Alt+B` |
|
||||
| Move the cursor one word to the right. | `Ctrl+Right`<br />`Alt+Right`<br />`Alt+F` |
|
||||
|
||||
#### Editing
|
||||
|
||||
| Action | Keys |
|
||||
| ------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| Delete from the cursor to the end of the line. | `Ctrl + K` |
|
||||
| Delete from the cursor to the start of the line. | `Ctrl + U` |
|
||||
| Clear all text in the input field. | `Ctrl + C` |
|
||||
| Delete the previous word. | `Ctrl + Backspace`<br />`Alt + Backspace`<br />`Ctrl + W` |
|
||||
| Delete the next word. | `Ctrl + Delete`<br />`Alt + Delete`<br />`Alt + D` |
|
||||
| Delete the character to the left. | `Backspace`<br />`Ctrl + H` |
|
||||
| Delete the character to the right. | `Delete`<br />`Ctrl + D` |
|
||||
| Undo the most recent text edit. | `Cmd + Z (no Shift)`<br />`Alt + Z (no Shift)` |
|
||||
| Redo the most recent undone text edit. | `Shift + Ctrl + Z`<br />`Shift + Cmd + Z`<br />`Shift + Alt + Z` |
|
||||
| Action | Keys |
|
||||
| ------------------------------------------------ | -------------------------------------------------------- |
|
||||
| Delete from the cursor to the end of the line. | `Ctrl+K` |
|
||||
| Delete from the cursor to the start of the line. | `Ctrl+U` |
|
||||
| Clear all text in the input field. | `Ctrl+C` |
|
||||
| Delete the previous word. | `Ctrl+Backspace`<br />`Alt+Backspace`<br />`Ctrl+W` |
|
||||
| Delete the next word. | `Ctrl+Delete`<br />`Alt+Delete`<br />`Alt+D` |
|
||||
| Delete the character to the left. | `Backspace`<br />`Ctrl+H` |
|
||||
| Delete the character to the right. | `Delete`<br />`Ctrl+D` |
|
||||
| Undo the most recent text edit. | `Cmd/Win+Z`<br />`Alt+Z` |
|
||||
| Redo the most recent undone text edit. | `Ctrl+Shift+Z`<br />`Shift+Cmd/Win+Z`<br />`Alt+Shift+Z` |
|
||||
|
||||
#### Scrolling
|
||||
|
||||
| Action | Keys |
|
||||
| ------------------------ | --------------------------------- |
|
||||
| Scroll content up. | `Shift + Up Arrow` |
|
||||
| Scroll content down. | `Shift + Down Arrow` |
|
||||
| Scroll to the top. | `Ctrl + Home`<br />`Shift + Home` |
|
||||
| Scroll to the bottom. | `Ctrl + End`<br />`Shift + End` |
|
||||
| Scroll up by one page. | `Page Up` |
|
||||
| Scroll down by one page. | `Page Down` |
|
||||
| Action | Keys |
|
||||
| ------------------------ | ----------------------------- |
|
||||
| Scroll content up. | `Shift+Up` |
|
||||
| Scroll content down. | `Shift+Down` |
|
||||
| Scroll to the top. | `Ctrl+Home`<br />`Shift+Home` |
|
||||
| Scroll to the bottom. | `Ctrl+End`<br />`Shift+End` |
|
||||
| Scroll up by one page. | `Page Up` |
|
||||
| Scroll down by one page. | `Page Down` |
|
||||
|
||||
#### History & Search
|
||||
|
||||
| Action | Keys |
|
||||
| -------------------------------------------- | --------------------- |
|
||||
| Show the previous entry in history. | `Ctrl + P (no Shift)` |
|
||||
| Show the next entry in history. | `Ctrl + N (no Shift)` |
|
||||
| Start reverse search through history. | `Ctrl + R` |
|
||||
| Submit the selected reverse-search match. | `Enter (no Ctrl)` |
|
||||
| Accept a suggestion while reverse searching. | `Tab (no Shift)` |
|
||||
| Browse and rewind previous interactions. | `Double Esc` |
|
||||
| Action | Keys |
|
||||
| -------------------------------------------- | ------------ |
|
||||
| Show the previous entry in history. | `Ctrl+P` |
|
||||
| Show the next entry in history. | `Ctrl+N` |
|
||||
| Start reverse search through history. | `Ctrl+R` |
|
||||
| Submit the selected reverse-search match. | `Enter` |
|
||||
| Accept a suggestion while reverse searching. | `Tab` |
|
||||
| Browse and rewind previous interactions. | `Double Esc` |
|
||||
|
||||
#### Navigation
|
||||
|
||||
| Action | Keys |
|
||||
| -------------------------------------------------- | ------------------------------------------- |
|
||||
| Move selection up in lists. | `Up Arrow (no Shift)` |
|
||||
| Move selection down in lists. | `Down Arrow (no Shift)` |
|
||||
| Move up within dialog options. | `Up Arrow (no Shift)`<br />`K (no Shift)` |
|
||||
| Move down within dialog options. | `Down Arrow (no Shift)`<br />`J (no Shift)` |
|
||||
| Move to the next item or question in a dialog. | `Tab (no Shift)` |
|
||||
| Move to the previous item or question in a dialog. | `Shift + Tab` |
|
||||
| Action | Keys |
|
||||
| -------------------------------------------------- | --------------- |
|
||||
| Move selection up in lists. | `Up` |
|
||||
| Move selection down in lists. | `Down` |
|
||||
| Move up within dialog options. | `Up`<br />`K` |
|
||||
| Move down within dialog options. | `Down`<br />`J` |
|
||||
| Move to the next item or question in a dialog. | `Tab` |
|
||||
| Move to the previous item or question in a dialog. | `Shift+Tab` |
|
||||
|
||||
#### Suggestions & Completions
|
||||
|
||||
| Action | Keys |
|
||||
| --------------------------------------- | -------------------------------------------------- |
|
||||
| Accept the inline suggestion. | `Tab (no Shift)`<br />`Enter (no Ctrl)` |
|
||||
| Move to the previous completion option. | `Up Arrow (no Shift)`<br />`Ctrl + P (no Shift)` |
|
||||
| Move to the next completion option. | `Down Arrow (no Shift)`<br />`Ctrl + N (no Shift)` |
|
||||
| Expand an inline suggestion. | `Right Arrow` |
|
||||
| Collapse an inline suggestion. | `Left Arrow` |
|
||||
| Action | Keys |
|
||||
| --------------------------------------- | -------------------- |
|
||||
| Accept the inline suggestion. | `Tab`<br />`Enter` |
|
||||
| Move to the previous completion option. | `Up`<br />`Ctrl+P` |
|
||||
| Move to the next completion option. | `Down`<br />`Ctrl+N` |
|
||||
| Expand an inline suggestion. | `Right` |
|
||||
| Collapse an inline suggestion. | `Left` |
|
||||
|
||||
#### Text Input
|
||||
|
||||
| Action | Keys |
|
||||
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| Submit the current prompt. | `Enter (no Shift, Alt, Ctrl, Cmd)` |
|
||||
| Insert a newline without submitting. | `Ctrl + Enter`<br />`Cmd + Enter`<br />`Alt + Enter`<br />`Shift + Enter`<br />`Ctrl + J` |
|
||||
| Open the current prompt or the plan in an external editor. | `Ctrl + X` |
|
||||
| Paste from the clipboard. | `Ctrl + V`<br />`Cmd + V`<br />`Alt + V` |
|
||||
| Action | Keys |
|
||||
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
||||
| Submit the current prompt. | `Enter` |
|
||||
| Insert a newline without submitting. | `Ctrl+Enter`<br />`Cmd/Win+Enter`<br />`Alt+Enter`<br />`Shift+Enter`<br />`Ctrl+J` |
|
||||
| Open the current prompt or the plan in an external editor. | `Ctrl+X` |
|
||||
| Paste from the clipboard. | `Ctrl+V`<br />`Cmd/Win+V`<br />`Alt+V` |
|
||||
|
||||
#### App Controls
|
||||
|
||||
| Action | Keys |
|
||||
| -------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
|
||||
| Toggle detailed error information. | `F12` |
|
||||
| Toggle the full TODO list. | `Ctrl + T` |
|
||||
| Show IDE context details. | `Ctrl + G` |
|
||||
| Toggle Markdown rendering. | `Alt + M` |
|
||||
| Toggle copy mode when in alternate buffer mode. | `Ctrl + S` |
|
||||
| Toggle YOLO (auto-approval) mode for tool calls. | `Ctrl + Y` |
|
||||
| Cycle through approval modes: default (prompt), auto_edit (auto-approve edits), and plan (read-only). Plan mode is skipped when the agent is busy. | `Shift + Tab` |
|
||||
| Expand and collapse blocks of content when not in alternate buffer mode. | `Ctrl + O` |
|
||||
| Expand or collapse a paste placeholder when cursor is over placeholder. | `Ctrl + O` |
|
||||
| Toggle current background shell visibility. | `Ctrl + B` |
|
||||
| Toggle background shell list. | `Ctrl + L` |
|
||||
| Kill the active background shell. | `Ctrl + K` |
|
||||
| Confirm selection in background shell list. | `Enter` |
|
||||
| Dismiss background shell list. | `Esc` |
|
||||
| Move focus from background shell to Gemini. | `Shift + Tab` |
|
||||
| Move focus from background shell list to Gemini. | `Tab (no Shift)` |
|
||||
| Show warning when trying to move focus away from background shell. | `Tab (no Shift)` |
|
||||
| Show warning when trying to move focus away from shell input. | `Tab (no Shift)` |
|
||||
| Move focus from Gemini to the active shell. | `Tab (no Shift)` |
|
||||
| Move focus from the shell back to Gemini. | `Shift + Tab` |
|
||||
| Clear the terminal screen and redraw the UI. | `Ctrl + L` |
|
||||
| Restart the application. | `R` |
|
||||
| Suspend the CLI and move it to the background. | `Ctrl + Z` |
|
||||
| Action | Keys |
|
||||
| -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
|
||||
| Toggle detailed error information. | `F12` |
|
||||
| Toggle the full TODO list. | `Ctrl+T` |
|
||||
| Show IDE context details. | `Ctrl+G` |
|
||||
| Toggle Markdown rendering. | `Alt+M` |
|
||||
| Toggle copy mode when in alternate buffer mode. | `Ctrl+S` |
|
||||
| Toggle YOLO (auto-approval) mode for tool calls. | `Ctrl+Y` |
|
||||
| Cycle through approval modes: default (prompt), auto_edit (auto-approve edits), and plan (read-only). Plan mode is skipped when the agent is busy. | `Shift+Tab` |
|
||||
| Expand and collapse blocks of content when not in alternate buffer mode. | `Ctrl+O` |
|
||||
| Expand or collapse a paste placeholder when cursor is over placeholder. | `Ctrl+O` |
|
||||
| Toggle current background shell visibility. | `Ctrl+B` |
|
||||
| Toggle background shell list. | `Ctrl+L` |
|
||||
| Kill the active background shell. | `Ctrl+K` |
|
||||
| Confirm selection in background shell list. | `Enter` |
|
||||
| Dismiss background shell list. | `Esc` |
|
||||
| Move focus from background shell to Gemini. | `Shift+Tab` |
|
||||
| Move focus from background shell list to Gemini. | `Tab` |
|
||||
| Show warning when trying to move focus away from background shell. | `Tab` |
|
||||
| Show warning when trying to move focus away from shell input. | `Tab` |
|
||||
| Move focus from Gemini to the active shell. | `Tab` |
|
||||
| Move focus from the shell back to Gemini. | `Shift+Tab` |
|
||||
| Clear the terminal screen and redraw the UI. | `Ctrl+L` |
|
||||
| Restart the application. | `R`<br />`Shift+R` |
|
||||
| Suspend the CLI and move it to the background. | `Ctrl+Z` |
|
||||
|
||||
<!-- KEYBINDINGS-AUTOGEN:END -->
|
||||
|
||||
@@ -156,7 +156,7 @@ available combinations.
|
||||
## Limitations
|
||||
|
||||
- On [Windows Terminal](https://en.wikipedia.org/wiki/Windows_Terminal):
|
||||
- `shift+enter` is not supported.
|
||||
- `shift+enter` is only supported in version 1.25 and higher.
|
||||
- `shift+tab`
|
||||
[is not supported](https://github.com/google-gemini/gemini-cli/issues/20314)
|
||||
on Node 20 and earlier versions of Node 22.
|
||||
|
||||
@@ -69,6 +69,19 @@ Learn more at
|
||||
If you use up your initial number of requests, you can continue to benefit from
|
||||
Gemini CLI by upgrading to one of the following subscriptions:
|
||||
|
||||
### Individuals
|
||||
|
||||
These tiers apply when you sign in with a personal account. To verify whether
|
||||
you're on a personal account, visit
|
||||
[Google One](https://one.google.com/about/plans?hl=en-US&g1_landing_page=0):
|
||||
|
||||
- If you are on a personal account, you will see your personal dashboard.
|
||||
- If you are not on a personal account, you will see: "You're currently signed
|
||||
in to your Google Workspace Account."
|
||||
|
||||
**Supported tiers:** _- Tiers not listed above, including Google AI Plus, are
|
||||
not supported._
|
||||
|
||||
- [Google AI Pro and AI Ultra](https://gemini.google/subscriptions/). This is
|
||||
recommended for individual developers. Quotas and pricing are based on a fixed
|
||||
price subscription.
|
||||
@@ -78,6 +91,20 @@ Gemini CLI by upgrading to one of the following subscriptions:
|
||||
Learn more at
|
||||
[Gemini Code Assist Quotas and Limits](https://developers.google.com/gemini-code-assist/resources/quotas)
|
||||
|
||||
### Through your organization
|
||||
|
||||
These tiers are applicable when you are signing in with a Google Workspace
|
||||
account.
|
||||
|
||||
- To verify your account type, visit
|
||||
[the Google One page](https://one.google.com/about/plans?hl=en-US&g1_landing_page=0).
|
||||
- You are on a workspace account if you see the message "You're currently signed
|
||||
in to your Google Workspace Account".
|
||||
|
||||
**Supported tiers:** _- Tiers not listed above, including Workspace AI
|
||||
Standard/Plus and AI Expanded, are not supported._
|
||||
|
||||
- [Workspace AI Ultra Access](https://workspace.google.com/products/ai-ultra/).
|
||||
- [Purchase a Gemini Code Assist Subscription through Google Cloud](https://cloud.google.com/gemini/docs/codeassist/overview).
|
||||
|
||||
Quotas and pricing are based on a fixed price subscription with assigned
|
||||
@@ -93,7 +120,7 @@ Gemini CLI by upgrading to one of the following subscriptions:
|
||||
- Model requests will be made across the Gemini model family as determined by
|
||||
Gemini CLI.
|
||||
|
||||
[Learn more about Gemini Code Assist Standard and Enterprise license limits](https://developers.google.com/gemini-code-assist/resources/quotas#quotas-for-agent-mode-gemini-cli).
|
||||
[Learn more about Gemini Code Assist license limits](https://developers.google.com/gemini-code-assist/resources/quotas#quotas-for-agent-mode-gemini-cli).
|
||||
|
||||
## Pay as you go
|
||||
|
||||
@@ -151,7 +178,7 @@ session's token usage, as well as information about the limits associated with
|
||||
your current quota.
|
||||
|
||||
For more information on the `/stats` command and its subcommands, see the
|
||||
[Command Reference](../../reference/commands.md#stats).
|
||||
[Command Reference](../reference/commands.md#stats).
|
||||
|
||||
A summary of model usage is also presented on exit at the end of a session.
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { expect } from 'vitest';
|
||||
import { evalTest } from './test-helper.js';
|
||||
|
||||
const MUTATION_AGENT_DEFINITION = `---
|
||||
name: mutation-agent
|
||||
description: An agent that modifies the workspace (writes, deletes, git operations, etc).
|
||||
max_turns: 1
|
||||
tools:
|
||||
- write_file
|
||||
---
|
||||
|
||||
You are the mutation agent. Do the mutation requested.
|
||||
`;
|
||||
|
||||
describe('concurrency safety eval test cases', () => {
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'mutation agents are run in parallel when explicitly requested',
|
||||
params: {
|
||||
settings: {
|
||||
experimental: {
|
||||
enableAgents: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
prompt:
|
||||
'Update A.txt to say "A" and update B.txt to say "B". Delegate these tasks to two separate mutation-agent subagents. You MUST run these subagents in parallel at the same time.',
|
||||
files: {
|
||||
'.gemini/agents/mutation-agent.md': MUTATION_AGENT_DEFINITION,
|
||||
},
|
||||
assert: async (rig) => {
|
||||
const logs = rig.readToolLogs();
|
||||
const mutationCalls = logs.filter(
|
||||
(log) => log.toolRequest?.name === 'mutation-agent',
|
||||
);
|
||||
|
||||
expect(
|
||||
mutationCalls.length,
|
||||
'Agent should have called the mutation-agent at least twice',
|
||||
).toBeGreaterThanOrEqual(2);
|
||||
|
||||
const firstPromptId = mutationCalls[0].toolRequest.prompt_id;
|
||||
const secondPromptId = mutationCalls[1].toolRequest.prompt_id;
|
||||
|
||||
expect(
|
||||
firstPromptId,
|
||||
'mutation agents should be called in parallel (same turn / prompt_ids) when explicitly requested',
|
||||
).toEqual(secondPromptId);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -112,6 +112,7 @@ export function evalTest(policy: EvalPolicy, evalCase: EvalCase) {
|
||||
// commands.
|
||||
execSync('git config core.editor "true"', execOptions);
|
||||
execSync('git config core.pager "cat"', execOptions);
|
||||
execSync('git config commit.gpgsign false', execOptions);
|
||||
execSync('git add .', execOptions);
|
||||
execSync('git commit --allow-empty -m "Initial commit"', execOptions);
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Part 1. "}],"role":"model"},"index":0}]},{"usageMetadata":{"promptTokenCount":100,"candidatesTokenCount":10,"totalTokenCount":110}},{"candidates":[{"content":{"parts":[{"text":"Part 2."}],"role":"model"},"index":0}],"finishReason":"STOP"}]}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { TestRig } from './test-helper.js';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
describe('API Resilience E2E', () => {
|
||||
let rig: TestRig;
|
||||
|
||||
beforeEach(() => {
|
||||
rig = new TestRig();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rig.cleanup();
|
||||
});
|
||||
|
||||
it('should not crash when receiving metadata-only chunks in a stream', async () => {
|
||||
await rig.setup('api-resilience-metadata-only', {
|
||||
fakeResponsesPath: join(
|
||||
dirname(fileURLToPath(import.meta.url)),
|
||||
'api-resilience.responses',
|
||||
),
|
||||
settings: {
|
||||
planSettings: { modelRouting: false },
|
||||
},
|
||||
});
|
||||
|
||||
// Run the CLI with a simple prompt.
|
||||
// The fake responses will provide a stream with a metadata-only chunk in the middle.
|
||||
// We use gemini-3-pro-preview to minimize internal service calls.
|
||||
const result = await rig.run({
|
||||
args: ['hi', '--model', 'gemini-3-pro-preview'],
|
||||
});
|
||||
|
||||
// Verify the output contains text from the normal chunks.
|
||||
// If the CLI crashed on the metadata chunk, rig.run would throw.
|
||||
expect(result).toContain('Part 1.');
|
||||
expect(result).toContain('Part 2.');
|
||||
|
||||
// Verify telemetry event for the prompt was still generated
|
||||
const hasUserPromptEvent = await rig.waitForTelemetryEvent('user_prompt');
|
||||
expect(hasUserPromptEvent).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -104,7 +104,7 @@ describe('extension reloading', () => {
|
||||
return (
|
||||
output.includes(
|
||||
'test-server (from test-extension) - Ready (1 tool)',
|
||||
) && output.includes('- hello')
|
||||
) && output.includes('- mcp_test-server_hello')
|
||||
);
|
||||
},
|
||||
30000, // 30s timeout
|
||||
@@ -148,7 +148,7 @@ describe('extension reloading', () => {
|
||||
return (
|
||||
output.includes(
|
||||
'test-server (from test-extension) - Ready (1 tool)',
|
||||
) && output.includes('- goodbye')
|
||||
) && output.includes('- mcp_test-server_goodbye')
|
||||
);
|
||||
},
|
||||
30000,
|
||||
|
||||
@@ -182,14 +182,22 @@ describe('Hooks Agent Flow', () => {
|
||||
);
|
||||
|
||||
const afterAgentScript = `
|
||||
console.log(JSON.stringify({
|
||||
decision: 'block',
|
||||
reason: 'Security policy triggered',
|
||||
hookSpecificOutput: {
|
||||
hookEventName: 'AfterAgent',
|
||||
clearContext: true
|
||||
}
|
||||
}));
|
||||
const fs = require('fs');
|
||||
const input = JSON.parse(fs.readFileSync(0, 'utf-8'));
|
||||
if (input.stop_hook_active) {
|
||||
// Retry turn: allow execution to proceed (breaks the loop)
|
||||
console.log(JSON.stringify({ decision: 'allow' }));
|
||||
} else {
|
||||
// First call: block and clear context to trigger the retry
|
||||
console.log(JSON.stringify({
|
||||
decision: 'block',
|
||||
reason: 'Security policy triggered',
|
||||
hookSpecificOutput: {
|
||||
hookEventName: 'AfterAgent',
|
||||
clearContext: true
|
||||
}
|
||||
}));
|
||||
}
|
||||
`;
|
||||
const afterAgentScriptPath = rig.createScript(
|
||||
'after_agent_clear.cjs',
|
||||
@@ -198,8 +206,10 @@ describe('Hooks Agent Flow', () => {
|
||||
|
||||
rig.setup('should process clearContext in AfterAgent hook output', {
|
||||
settings: {
|
||||
hooks: {
|
||||
hooksConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
hooks: {
|
||||
BeforeModel: [
|
||||
{
|
||||
hooks: [
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Hi there!"}],"role":"model"},"finishReason":"STOP","index":0}]}]}
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Clarification: I am a bot."}],"role":"model"},"finishReason":"STOP","index":0}]}]}
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Security policy triggered"}],"role":"model"},"finishReason":"STOP","index":0}]}]}
|
||||
|
||||
@@ -68,6 +68,7 @@ async function verifyToolExecution(
|
||||
promptCommand: PromptCommand,
|
||||
result: string,
|
||||
expectAllowed: boolean,
|
||||
expectedDenialString?: string,
|
||||
) {
|
||||
const log = await waitForToolCallLog(
|
||||
rig,
|
||||
@@ -78,10 +79,13 @@ async function verifyToolExecution(
|
||||
if (expectAllowed) {
|
||||
expect(log!.toolRequest.success).toBe(true);
|
||||
expect(result).not.toContain('Tool execution denied by policy');
|
||||
expect(result).not.toContain(`Tool "${promptCommand.tool}" not found`);
|
||||
expect(result).toContain(promptCommand.expectedSuccessResult);
|
||||
} else {
|
||||
expect(log!.toolRequest.success).toBe(false);
|
||||
expect(result).toContain('Tool execution denied by policy');
|
||||
expect(result).toContain(
|
||||
expectedDenialString || 'Tool execution denied by policy',
|
||||
);
|
||||
expect(result).toContain(promptCommand.expectedFailureResult);
|
||||
}
|
||||
}
|
||||
@@ -92,6 +96,7 @@ interface TestCase {
|
||||
promptCommand: PromptCommand;
|
||||
policyContent?: string;
|
||||
expectAllowed: boolean;
|
||||
expectedDenialString?: string;
|
||||
}
|
||||
|
||||
describe('Policy Engine Headless Mode', () => {
|
||||
@@ -125,7 +130,13 @@ describe('Policy Engine Headless Mode', () => {
|
||||
approvalMode: 'default',
|
||||
});
|
||||
|
||||
await verifyToolExecution(rig, tc.promptCommand, result, tc.expectAllowed);
|
||||
await verifyToolExecution(
|
||||
rig,
|
||||
tc.promptCommand,
|
||||
result,
|
||||
tc.expectAllowed,
|
||||
tc.expectedDenialString,
|
||||
);
|
||||
};
|
||||
|
||||
const testCases = [
|
||||
@@ -134,6 +145,7 @@ describe('Policy Engine Headless Mode', () => {
|
||||
responsesFile: 'policy-headless-shell-denied.responses',
|
||||
promptCommand: ECHO_PROMPT,
|
||||
expectAllowed: false,
|
||||
expectedDenialString: 'Tool "run_shell_command" not found',
|
||||
},
|
||||
{
|
||||
name: 'should allow ASK_USER tools in headless mode if explicitly allowed via policy file',
|
||||
@@ -178,6 +190,7 @@ describe('Policy Engine Headless Mode', () => {
|
||||
priority = 100
|
||||
`,
|
||||
expectAllowed: false,
|
||||
expectedDenialString: 'Tool execution denied by policy',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -348,8 +348,7 @@ export class Task {
|
||||
} else if (isSubagentProgress(outputChunk)) {
|
||||
outputAsText = JSON.stringify(outputChunk);
|
||||
} else if (Array.isArray(outputChunk)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const ansiOutput = outputChunk as AnsiOutput;
|
||||
const ansiOutput: AnsiOutput = outputChunk;
|
||||
outputAsText = ansiOutput
|
||||
.map((line: AnsiLine) =>
|
||||
line.map((token: AnsiToken) => token.text).join(''),
|
||||
|
||||
@@ -120,7 +120,6 @@ export async function loadConfig(
|
||||
await loadServerHierarchicalMemory(
|
||||
workspaceDir,
|
||||
[workspaceDir],
|
||||
false,
|
||||
fileService,
|
||||
extensionLoader,
|
||||
folderTrust,
|
||||
|
||||
@@ -208,7 +208,16 @@ describe('GeminiAgent', () => {
|
||||
});
|
||||
|
||||
expect(response.protocolVersion).toBe(acp.PROTOCOL_VERSION);
|
||||
expect(response.authMethods).toHaveLength(3);
|
||||
expect(response.authMethods).toHaveLength(4);
|
||||
const gatewayAuth = response.authMethods?.find(
|
||||
(m) => m.id === AuthType.GATEWAY,
|
||||
);
|
||||
expect(gatewayAuth?._meta).toEqual({
|
||||
gateway: {
|
||||
protocol: 'google',
|
||||
restartRequired: 'false',
|
||||
},
|
||||
});
|
||||
const geminiAuth = response.authMethods?.find(
|
||||
(m) => m.id === AuthType.USE_GEMINI,
|
||||
);
|
||||
@@ -228,6 +237,8 @@ describe('GeminiAgent', () => {
|
||||
expect(mockConfig.refreshAuth).toHaveBeenCalledWith(
|
||||
AuthType.LOGIN_WITH_GOOGLE,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
expect(mockSettings.setValue).toHaveBeenCalledWith(
|
||||
SettingScope.User,
|
||||
@@ -247,6 +258,8 @@ describe('GeminiAgent', () => {
|
||||
expect(mockConfig.refreshAuth).toHaveBeenCalledWith(
|
||||
AuthType.USE_GEMINI,
|
||||
'test-api-key',
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
expect(mockSettings.setValue).toHaveBeenCalledWith(
|
||||
SettingScope.User,
|
||||
@@ -255,6 +268,45 @@ describe('GeminiAgent', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should authenticate correctly with gateway method', async () => {
|
||||
await agent.authenticate({
|
||||
methodId: AuthType.GATEWAY,
|
||||
_meta: {
|
||||
gateway: {
|
||||
baseUrl: 'https://example.com',
|
||||
headers: { Authorization: 'Bearer token' },
|
||||
},
|
||||
},
|
||||
} as unknown as acp.AuthenticateRequest);
|
||||
|
||||
expect(mockConfig.refreshAuth).toHaveBeenCalledWith(
|
||||
AuthType.GATEWAY,
|
||||
undefined,
|
||||
'https://example.com',
|
||||
{ Authorization: 'Bearer token' },
|
||||
);
|
||||
expect(mockSettings.setValue).toHaveBeenCalledWith(
|
||||
SettingScope.User,
|
||||
'security.auth.selectedType',
|
||||
AuthType.GATEWAY,
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw acp.RequestError when gateway payload is malformed', async () => {
|
||||
await expect(
|
||||
agent.authenticate({
|
||||
methodId: AuthType.GATEWAY,
|
||||
_meta: {
|
||||
gateway: {
|
||||
// Invalid baseUrl
|
||||
baseUrl: 123,
|
||||
headers: { Authorization: 'Bearer token' },
|
||||
},
|
||||
},
|
||||
} as unknown as acp.AuthenticateRequest),
|
||||
).rejects.toThrow(/Malformed gateway payload/);
|
||||
});
|
||||
|
||||
it('should create a new session', async () => {
|
||||
vi.useFakeTimers();
|
||||
mockConfig.getContentGeneratorConfig = vi.fn().mockReturnValue({
|
||||
@@ -495,7 +547,7 @@ describe('GeminiAgent', () => {
|
||||
});
|
||||
|
||||
expect(session.prompt).toHaveBeenCalled();
|
||||
expect(result).toMatchObject({ stopReason: 'end_turn' });
|
||||
expect(result).toEqual({ stopReason: 'end_turn' });
|
||||
});
|
||||
|
||||
it('should delegate setMode to session', async () => {
|
||||
@@ -687,110 +739,50 @@ describe('Session', () => {
|
||||
content: { type: 'text', text: 'Hello' },
|
||||
},
|
||||
});
|
||||
expect(result).toMatchObject({ stopReason: 'end_turn' });
|
||||
});
|
||||
|
||||
it('should accumulate token counts into _meta.quota.token_count and model_usage', async () => {
|
||||
mockConfig.getModel.mockReturnValue('gemini-1.5-pro-test');
|
||||
const stream = createMockStream([
|
||||
{
|
||||
type: StreamEventType.CHUNK,
|
||||
value: {
|
||||
candidates: [{ content: { parts: [{ text: 'Answer 1' }] } }],
|
||||
usageMetadata: { promptTokenCount: 10, candidatesTokenCount: 20 },
|
||||
},
|
||||
},
|
||||
]);
|
||||
mockChat.sendMessageStream.mockResolvedValue(stream);
|
||||
|
||||
const result = await session.prompt({
|
||||
sessionId: 'session-1',
|
||||
prompt: [{ type: 'text', text: 'Hi' }],
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
stopReason: 'end_turn',
|
||||
_meta: {
|
||||
quota: {
|
||||
token_count: { input_tokens: 10, output_tokens: 20 },
|
||||
model_usage: [
|
||||
{
|
||||
model: 'gemini-1.5-pro-test',
|
||||
token_count: { input_tokens: 10, output_tokens: 20 },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(result).toEqual({ stopReason: 'end_turn' });
|
||||
});
|
||||
|
||||
it('should handle /memory command', async () => {
|
||||
vi.spyOn(
|
||||
(session as unknown as { commandHandler: CommandHandler }).commandHandler,
|
||||
'handleCommand',
|
||||
).mockResolvedValue(true);
|
||||
const handleCommandSpy = vi
|
||||
.spyOn(
|
||||
(session as unknown as { commandHandler: CommandHandler })
|
||||
.commandHandler,
|
||||
'handleCommand',
|
||||
)
|
||||
.mockResolvedValue(true);
|
||||
|
||||
const result = await session.prompt({
|
||||
sessionId: 'session-1',
|
||||
prompt: [{ type: 'text', text: '/memory view' }],
|
||||
});
|
||||
|
||||
expect(mockConnection.sessionUpdate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
update: expect.objectContaining({
|
||||
sessionUpdate: 'agent_message_chunk',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(result).toEqual({ stopReason: 'end_turn' });
|
||||
expect(mockChat.sendMessageStream).not.toHaveBeenCalled();
|
||||
});
|
||||
it('should handle /status command directly', async () => {
|
||||
mockConfig.getActiveModel.mockReturnValue('gemini-1.5-pro-test');
|
||||
const result = await session.prompt({
|
||||
sessionId: 'session-1',
|
||||
prompt: [{ type: 'text', text: '/status' }],
|
||||
});
|
||||
|
||||
expect(mockConnection.sessionUpdate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
update: expect.objectContaining({
|
||||
sessionUpdate: 'agent_message_chunk',
|
||||
content: expect.objectContaining({
|
||||
type: 'text',
|
||||
text: expect.stringContaining('gemini-1.5-pro-test'),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
expect(handleCommandSpy).toHaveBeenCalledWith(
|
||||
'/memory view',
|
||||
expect.any(Object),
|
||||
);
|
||||
expect(result).toEqual({ stopReason: 'end_turn' });
|
||||
// Chat should not be called
|
||||
expect(mockChat.sendMessageStream).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle /extensions command', async () => {
|
||||
vi.spyOn(
|
||||
(session as unknown as { commandHandler: CommandHandler }).commandHandler,
|
||||
'handleCommand',
|
||||
).mockResolvedValue(true);
|
||||
const handleCommandSpy = vi
|
||||
.spyOn(
|
||||
(session as unknown as { commandHandler: CommandHandler })
|
||||
.commandHandler,
|
||||
'handleCommand',
|
||||
)
|
||||
.mockResolvedValue(true);
|
||||
|
||||
const result = await session.prompt({
|
||||
sessionId: 'session-1',
|
||||
prompt: [{ type: 'text', text: '/extensions list' }],
|
||||
});
|
||||
|
||||
expect(mockConnection.sessionUpdate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
update: expect.objectContaining({
|
||||
sessionUpdate: 'agent_message_chunk',
|
||||
content: expect.objectContaining({
|
||||
type: 'text',
|
||||
text: expect.stringContaining('`test-mcp`'),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(result).toEqual({ stopReason: 'end_turn' });
|
||||
expect(handleCommandSpy).toHaveBeenCalledWith(
|
||||
'/extensions list',
|
||||
expect.any(Object),
|
||||
);
|
||||
expect(mockChat.sendMessageStream).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -903,7 +895,7 @@ describe('Session', () => {
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(result).toMatchObject({ stopReason: 'end_turn' });
|
||||
expect(result).toEqual({ stopReason: 'end_turn' });
|
||||
});
|
||||
|
||||
it('should handle tool call permission request', async () => {
|
||||
|
||||
@@ -98,6 +98,8 @@ export class GeminiAgent {
|
||||
private sessions: Map<string, Session> = new Map();
|
||||
private clientCapabilities: acp.ClientCapabilities | undefined;
|
||||
private apiKey: string | undefined;
|
||||
private baseUrl: string | undefined;
|
||||
private customHeaders: Record<string, string> | undefined;
|
||||
|
||||
constructor(
|
||||
private config: Config,
|
||||
@@ -131,6 +133,17 @@ export class GeminiAgent {
|
||||
name: 'Vertex AI',
|
||||
description: 'Use an API key with Vertex AI GenAI API',
|
||||
},
|
||||
{
|
||||
id: AuthType.GATEWAY,
|
||||
name: 'AI API Gateway',
|
||||
description: 'Use a custom AI API Gateway',
|
||||
_meta: {
|
||||
gateway: {
|
||||
protocol: 'google',
|
||||
restartRequired: 'false',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
await this.config.initialize();
|
||||
@@ -179,7 +192,38 @@ export class GeminiAgent {
|
||||
if (apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
await this.config.refreshAuth(method, apiKey ?? this.apiKey);
|
||||
|
||||
// Extract gateway details if present
|
||||
const gatewaySchema = z.object({
|
||||
baseUrl: z.string().optional(),
|
||||
headers: z.record(z.string()).optional(),
|
||||
});
|
||||
|
||||
let baseUrl: string | undefined;
|
||||
let headers: Record<string, string> | undefined;
|
||||
|
||||
if (meta?.['gateway']) {
|
||||
const result = gatewaySchema.safeParse(meta['gateway']);
|
||||
if (result.success) {
|
||||
baseUrl = result.data.baseUrl;
|
||||
headers = result.data.headers;
|
||||
} else {
|
||||
throw new acp.RequestError(
|
||||
-32602,
|
||||
`Malformed gateway payload: ${result.error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.baseUrl = baseUrl;
|
||||
this.customHeaders = headers;
|
||||
|
||||
await this.config.refreshAuth(
|
||||
method,
|
||||
apiKey ?? this.apiKey,
|
||||
baseUrl,
|
||||
headers,
|
||||
);
|
||||
} catch (e) {
|
||||
throw new acp.RequestError(-32000, getAcpErrorMessage(e));
|
||||
}
|
||||
@@ -209,7 +253,12 @@ export class GeminiAgent {
|
||||
let isAuthenticated = false;
|
||||
let authErrorMessage = '';
|
||||
try {
|
||||
await config.refreshAuth(authType, this.apiKey);
|
||||
await config.refreshAuth(
|
||||
authType,
|
||||
this.apiKey,
|
||||
this.baseUrl,
|
||||
this.customHeaders,
|
||||
);
|
||||
isAuthenticated = true;
|
||||
|
||||
// Extra validation for Gemini API key
|
||||
@@ -309,7 +358,10 @@ export class GeminiAgent {
|
||||
config.setFileSystemService(acpFileSystemService);
|
||||
}
|
||||
|
||||
const clientHistory = convertSessionToClientHistory(sessionData.messages);
|
||||
const clientHistory = convertSessionToClientHistory(
|
||||
sessionData.messages,
|
||||
sessionData.lastCompressionIndex,
|
||||
);
|
||||
|
||||
const geminiClient = config.getGeminiClient();
|
||||
await geminiClient.initialize();
|
||||
@@ -371,7 +423,12 @@ export class GeminiAgent {
|
||||
// This satisfies the security requirement to verify the user before executing
|
||||
// potentially unsafe server definitions.
|
||||
try {
|
||||
await config.refreshAuth(selectedAuthType, this.apiKey);
|
||||
await config.refreshAuth(
|
||||
selectedAuthType,
|
||||
this.apiKey,
|
||||
this.baseUrl,
|
||||
this.customHeaders,
|
||||
);
|
||||
} catch (e) {
|
||||
debugLogger.error(`Authentication failed: ${e}`);
|
||||
throw acp.RequestError.authRequired();
|
||||
@@ -646,10 +703,6 @@ export class Session {
|
||||
|
||||
let nextMessage: Content | null = { role: 'user', parts };
|
||||
|
||||
let totalInputTokens = 0;
|
||||
let totalOutputTokens = 0;
|
||||
const modelUsageMap = new Map<string, { input: number; output: number }>();
|
||||
|
||||
while (nextMessage !== null) {
|
||||
if (pendingSend.signal.aborted) {
|
||||
chat.addHistory(nextMessage);
|
||||
@@ -672,20 +725,11 @@ export class Session {
|
||||
);
|
||||
nextMessage = null;
|
||||
|
||||
let turnInputTokens = 0;
|
||||
let turnOutputTokens = 0;
|
||||
|
||||
for await (const resp of responseStream) {
|
||||
if (pendingSend.signal.aborted) {
|
||||
return { stopReason: CoreToolCallStatus.Cancelled };
|
||||
}
|
||||
|
||||
if (resp.type === StreamEventType.CHUNK && resp.value.usageMetadata) {
|
||||
turnInputTokens = resp.value.usageMetadata.promptTokenCount ?? 0;
|
||||
turnOutputTokens =
|
||||
resp.value.usageMetadata.candidatesTokenCount ?? 0;
|
||||
}
|
||||
|
||||
if (
|
||||
resp.type === StreamEventType.CHUNK &&
|
||||
resp.value.candidates &&
|
||||
@@ -717,19 +761,6 @@ export class Session {
|
||||
}
|
||||
}
|
||||
|
||||
totalInputTokens += turnInputTokens;
|
||||
totalOutputTokens += turnOutputTokens;
|
||||
|
||||
if (turnInputTokens > 0 || turnOutputTokens > 0) {
|
||||
const existingModelUsage = modelUsageMap.get(model) || {
|
||||
input: 0,
|
||||
output: 0,
|
||||
};
|
||||
existingModelUsage.input += turnInputTokens;
|
||||
existingModelUsage.output += turnOutputTokens;
|
||||
modelUsageMap.set(model, existingModelUsage);
|
||||
}
|
||||
|
||||
if (pendingSend.signal.aborted) {
|
||||
return { stopReason: CoreToolCallStatus.Cancelled };
|
||||
}
|
||||
@@ -766,28 +797,7 @@ export class Session {
|
||||
}
|
||||
}
|
||||
|
||||
const modelUsageArray = Array.from(modelUsageMap.entries()).map(
|
||||
([m, usage]) => ({
|
||||
model: m,
|
||||
token_count: {
|
||||
input_tokens: usage.input,
|
||||
output_tokens: usage.output,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
stopReason: 'end_turn',
|
||||
_meta: {
|
||||
quota: {
|
||||
token_count: {
|
||||
input_tokens: totalInputTokens,
|
||||
output_tokens: totalOutputTokens,
|
||||
},
|
||||
model_usage: modelUsageArray,
|
||||
},
|
||||
},
|
||||
};
|
||||
return { stopReason: 'end_turn' };
|
||||
}
|
||||
|
||||
private async handleCommand(
|
||||
|
||||
@@ -319,26 +319,43 @@ export class UninstallExtensionCommand implements Command {
|
||||
};
|
||||
}
|
||||
|
||||
const name = args.join(' ').trim();
|
||||
if (!name) {
|
||||
const all = args.includes('--all');
|
||||
const names = args.filter((a) => !a.startsWith('--')).map((a) => a.trim());
|
||||
|
||||
if (!all && names.length === 0) {
|
||||
return {
|
||||
name: this.name,
|
||||
data: `Usage: /extensions uninstall <extension-name>`,
|
||||
data: `Usage: /extensions uninstall <extension-names...>|--all`,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
await extensionLoader.uninstallExtension(name, false);
|
||||
let namesToUninstall: string[] = [];
|
||||
if (all) {
|
||||
namesToUninstall = extensionLoader.getExtensions().map((ext) => ext.name);
|
||||
} else {
|
||||
namesToUninstall = names;
|
||||
}
|
||||
|
||||
if (namesToUninstall.length === 0) {
|
||||
return {
|
||||
name: this.name,
|
||||
data: `Extension "${name}" uninstalled successfully.`,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
name: this.name,
|
||||
data: `Failed to uninstall extension "${name}": ${getErrorMessage(error)}`,
|
||||
data: all ? 'No extensions installed.' : 'No extension name provided.',
|
||||
};
|
||||
}
|
||||
|
||||
const output: string[] = [];
|
||||
for (const extensionName of namesToUninstall) {
|
||||
try {
|
||||
await extensionLoader.uninstallExtension(extensionName, false);
|
||||
output.push(`Extension "${extensionName}" uninstalled successfully.`);
|
||||
} catch (error) {
|
||||
output.push(
|
||||
`Failed to uninstall extension "${extensionName}": ${getErrorMessage(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { name: this.name, data: output.join('\n') };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import { getErrorMessage } from '../../utils/errors.js';
|
||||
// Hoisted mocks - these survive vi.clearAllMocks()
|
||||
const mockUninstallExtension = vi.hoisted(() => vi.fn());
|
||||
const mockLoadExtensions = vi.hoisted(() => vi.fn());
|
||||
const mockGetExtensions = vi.hoisted(() => vi.fn());
|
||||
|
||||
// Mock dependencies with hoisted functions
|
||||
vi.mock('../../config/extension-manager.js', async (importOriginal) => {
|
||||
@@ -38,6 +39,7 @@ vi.mock('../../config/extension-manager.js', async (importOriginal) => {
|
||||
ExtensionManager: vi.fn().mockImplementation(() => ({
|
||||
uninstallExtension: mockUninstallExtension,
|
||||
loadExtensions: mockLoadExtensions,
|
||||
getExtensions: mockGetExtensions,
|
||||
setRequestConsent: vi.fn(),
|
||||
setRequestSetting: vi.fn(),
|
||||
})),
|
||||
@@ -93,6 +95,7 @@ describe('extensions uninstall command', () => {
|
||||
afterEach(() => {
|
||||
mockLoadExtensions.mockClear();
|
||||
mockUninstallExtension.mockClear();
|
||||
mockGetExtensions.mockClear();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
@@ -145,6 +148,41 @@ describe('extensions uninstall command', () => {
|
||||
mockCwd.mockRestore();
|
||||
});
|
||||
|
||||
it('should uninstall all extensions when --all flag is used', async () => {
|
||||
mockLoadExtensions.mockResolvedValue(undefined);
|
||||
mockUninstallExtension.mockResolvedValue(undefined);
|
||||
mockGetExtensions.mockReturnValue([{ name: 'ext1' }, { name: 'ext2' }]);
|
||||
const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
|
||||
await handleUninstall({ all: true });
|
||||
|
||||
expect(mockUninstallExtension).toHaveBeenCalledTimes(2);
|
||||
expect(mockUninstallExtension).toHaveBeenCalledWith('ext1', false);
|
||||
expect(mockUninstallExtension).toHaveBeenCalledWith('ext2', false);
|
||||
expect(emitConsoleLog).toHaveBeenCalledWith(
|
||||
'log',
|
||||
'Extension "ext1" successfully uninstalled.',
|
||||
);
|
||||
expect(emitConsoleLog).toHaveBeenCalledWith(
|
||||
'log',
|
||||
'Extension "ext2" successfully uninstalled.',
|
||||
);
|
||||
mockCwd.mockRestore();
|
||||
});
|
||||
|
||||
it('should log a message if no extensions are installed and --all flag is used', async () => {
|
||||
mockLoadExtensions.mockResolvedValue(undefined);
|
||||
mockGetExtensions.mockReturnValue([]);
|
||||
const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
|
||||
await handleUninstall({ all: true });
|
||||
|
||||
expect(mockUninstallExtension).not.toHaveBeenCalled();
|
||||
expect(emitConsoleLog).toHaveBeenCalledWith(
|
||||
'log',
|
||||
'No extensions currently installed.',
|
||||
);
|
||||
mockCwd.mockRestore();
|
||||
});
|
||||
|
||||
it('should report errors for failed uninstalls but continue with others', async () => {
|
||||
mockLoadExtensions.mockResolvedValue(undefined);
|
||||
const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
|
||||
@@ -236,13 +274,14 @@ describe('extensions uninstall command', () => {
|
||||
const command = uninstallCommand;
|
||||
|
||||
it('should have correct command and describe', () => {
|
||||
expect(command.command).toBe('uninstall <names..>');
|
||||
expect(command.command).toBe('uninstall [names..]');
|
||||
expect(command.describe).toBe('Uninstalls one or more extensions.');
|
||||
});
|
||||
|
||||
describe('builder', () => {
|
||||
interface MockYargs {
|
||||
positional: Mock;
|
||||
option: Mock;
|
||||
check: Mock;
|
||||
}
|
||||
|
||||
@@ -250,11 +289,12 @@ describe('extensions uninstall command', () => {
|
||||
beforeEach(() => {
|
||||
yargsMock = {
|
||||
positional: vi.fn().mockReturnThis(),
|
||||
option: vi.fn().mockReturnThis(),
|
||||
check: vi.fn().mockReturnThis(),
|
||||
};
|
||||
});
|
||||
|
||||
it('should configure positional argument', () => {
|
||||
it('should configure arguments and options', () => {
|
||||
(command.builder as (yargs: Argv) => Argv)(
|
||||
yargsMock as unknown as Argv,
|
||||
);
|
||||
@@ -264,18 +304,31 @@ describe('extensions uninstall command', () => {
|
||||
type: 'string',
|
||||
array: true,
|
||||
});
|
||||
expect(yargsMock.option).toHaveBeenCalledWith('all', {
|
||||
type: 'boolean',
|
||||
describe: 'Uninstall all installed extensions.',
|
||||
default: false,
|
||||
});
|
||||
expect(yargsMock.check).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('check function should throw for missing names', () => {
|
||||
it('check function should throw for missing names and no --all flag', () => {
|
||||
(command.builder as (yargs: Argv) => Argv)(
|
||||
yargsMock as unknown as Argv,
|
||||
);
|
||||
const checkCallback = yargsMock.check.mock.calls[0][0];
|
||||
expect(() => checkCallback({ names: [] })).toThrow(
|
||||
'Please include at least one extension name to uninstall as a positional argument.',
|
||||
expect(() => checkCallback({ names: [], all: false })).toThrow(
|
||||
'Please include at least one extension name to uninstall as a positional argument, or use the --all flag.',
|
||||
);
|
||||
});
|
||||
|
||||
it('check function should pass if --all flag is used even without names', () => {
|
||||
(command.builder as (yargs: Argv) => Argv)(
|
||||
yargsMock as unknown as Argv,
|
||||
);
|
||||
const checkCallback = yargsMock.check.mock.calls[0][0];
|
||||
expect(() => checkCallback({ names: [], all: true })).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
it('handler should call handleUninstall', async () => {
|
||||
@@ -283,10 +336,17 @@ describe('extensions uninstall command', () => {
|
||||
mockUninstallExtension.mockResolvedValue(undefined);
|
||||
const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
|
||||
interface TestArgv {
|
||||
names: string[];
|
||||
[key: string]: unknown;
|
||||
names?: string[];
|
||||
all?: boolean;
|
||||
_: string[];
|
||||
$0: string;
|
||||
}
|
||||
const argv: TestArgv = { names: ['my-extension'], _: [], $0: '' };
|
||||
const argv: TestArgv = {
|
||||
names: ['my-extension'],
|
||||
all: false,
|
||||
_: [],
|
||||
$0: '',
|
||||
};
|
||||
await (command.handler as unknown as (args: TestArgv) => Promise<void>)(
|
||||
argv,
|
||||
);
|
||||
|
||||
@@ -14,7 +14,8 @@ import { promptForSetting } from '../../config/extensions/extensionSettings.js';
|
||||
import { exitCli } from '../utils.js';
|
||||
|
||||
interface UninstallArgs {
|
||||
names: string[]; // can be extension names or source URLs.
|
||||
names?: string[]; // can be extension names or source URLs.
|
||||
all?: boolean;
|
||||
}
|
||||
|
||||
export async function handleUninstall(args: UninstallArgs) {
|
||||
@@ -28,8 +29,24 @@ export async function handleUninstall(args: UninstallArgs) {
|
||||
});
|
||||
await extensionManager.loadExtensions();
|
||||
|
||||
let namesToUninstall: string[] = [];
|
||||
if (args.all) {
|
||||
namesToUninstall = extensionManager
|
||||
.getExtensions()
|
||||
.map((ext) => ext.name);
|
||||
} else if (args.names) {
|
||||
namesToUninstall = [...new Set(args.names)];
|
||||
}
|
||||
|
||||
if (namesToUninstall.length === 0) {
|
||||
if (args.all) {
|
||||
debugLogger.log('No extensions currently installed.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const errors: Array<{ name: string; error: string }> = [];
|
||||
for (const name of [...new Set(args.names)]) {
|
||||
for (const name of namesToUninstall) {
|
||||
try {
|
||||
await extensionManager.uninstallExtension(name, false);
|
||||
debugLogger.log(`Extension "${name}" successfully uninstalled.`);
|
||||
@@ -51,7 +68,7 @@ export async function handleUninstall(args: UninstallArgs) {
|
||||
}
|
||||
|
||||
export const uninstallCommand: CommandModule = {
|
||||
command: 'uninstall <names..>',
|
||||
command: 'uninstall [names..]',
|
||||
describe: 'Uninstalls one or more extensions.',
|
||||
builder: (yargs) =>
|
||||
yargs
|
||||
@@ -61,10 +78,15 @@ export const uninstallCommand: CommandModule = {
|
||||
type: 'string',
|
||||
array: true,
|
||||
})
|
||||
.option('all', {
|
||||
type: 'boolean',
|
||||
describe: 'Uninstall all installed extensions.',
|
||||
default: false,
|
||||
})
|
||||
.check((argv) => {
|
||||
if (!argv.names || argv.names.length === 0) {
|
||||
if (!argv.all && (!argv.names || argv.names.length === 0)) {
|
||||
throw new Error(
|
||||
'Please include at least one extension name to uninstall as a positional argument.',
|
||||
'Please include at least one extension name to uninstall as a positional argument, or use the --all flag.',
|
||||
);
|
||||
}
|
||||
return true;
|
||||
@@ -72,7 +94,9 @@ export const uninstallCommand: CommandModule = {
|
||||
handler: async (argv) => {
|
||||
await handleUninstall({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
names: argv['names'] as string[],
|
||||
names: argv['names'] as string[] | undefined,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
all: argv['all'] as boolean,
|
||||
});
|
||||
await exitCli();
|
||||
},
|
||||
|
||||
@@ -116,14 +116,16 @@ vi.mock('@google/gemini-cli-core', async () => {
|
||||
(
|
||||
cwd,
|
||||
dirs,
|
||||
debug,
|
||||
fileService,
|
||||
extensionLoader: ExtensionLoader,
|
||||
_folderTrust,
|
||||
_importFormat,
|
||||
_fileFilteringOptions,
|
||||
_maxDirs,
|
||||
) => {
|
||||
const extensionPaths = extensionLoader
|
||||
.getExtensions()
|
||||
.flatMap((e) => e.contextFiles);
|
||||
const extensionPaths =
|
||||
extensionLoader?.getExtensions?.()?.flatMap((e) => e.contextFiles) ||
|
||||
[];
|
||||
return Promise.resolve({
|
||||
memoryContent: extensionPaths.join(',') || '',
|
||||
fileCount: extensionPaths?.length || 0,
|
||||
@@ -669,6 +671,13 @@ describe('parseArguments', () => {
|
||||
const argv = await parseArguments(settings);
|
||||
expect(argv.isCommand).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly parse the --forever flag', async () => {
|
||||
process.argv = ['node', 'script.js', '--forever'];
|
||||
const settings = createTestMergedSettings({});
|
||||
const argv = await parseArguments(settings);
|
||||
expect(argv.forever).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadCliConfig', () => {
|
||||
@@ -847,7 +856,6 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
|
||||
expect(ServerConfig.loadServerHierarchicalMemory).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
[],
|
||||
false,
|
||||
expect.any(Object),
|
||||
expect.any(ExtensionManager),
|
||||
true,
|
||||
@@ -876,7 +884,6 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
|
||||
expect(ServerConfig.loadServerHierarchicalMemory).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
[includeDir],
|
||||
false,
|
||||
expect.any(Object),
|
||||
expect.any(ExtensionManager),
|
||||
true,
|
||||
@@ -904,7 +911,6 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
|
||||
expect(ServerConfig.loadServerHierarchicalMemory).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
[],
|
||||
false,
|
||||
expect.any(Object),
|
||||
expect.any(ExtensionManager),
|
||||
true,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import yargs from 'yargs/yargs';
|
||||
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import process from 'node:process';
|
||||
import { mcpCommand } from '../commands/mcp.js';
|
||||
@@ -38,6 +39,7 @@ import {
|
||||
type HookDefinition,
|
||||
type HookEventName,
|
||||
type OutputFormat,
|
||||
type SisyphusModeSettings,
|
||||
} from '@google/gemini-cli-core';
|
||||
import {
|
||||
type Settings,
|
||||
@@ -67,6 +69,7 @@ export interface CliArgs {
|
||||
query: string | undefined;
|
||||
model: string | undefined;
|
||||
sandbox: boolean | string | undefined;
|
||||
forever: boolean | undefined;
|
||||
debug: boolean | undefined;
|
||||
prompt: string | undefined;
|
||||
promptInteractive: string | undefined;
|
||||
@@ -143,7 +146,12 @@ export async function parseArguments(
|
||||
type: 'boolean',
|
||||
description: 'Run in sandbox?',
|
||||
})
|
||||
|
||||
.option('forever', {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Enable forever (long-running agent) mode. Uses GEMINI.md frontmatter for sisyphus engine config.',
|
||||
default: false,
|
||||
})
|
||||
.option('yolo', {
|
||||
alias: 'y',
|
||||
type: 'boolean',
|
||||
@@ -488,6 +496,68 @@ export async function loadCliConfig(
|
||||
|
||||
const experimentalJitContext = settings.experimental?.jitContext ?? false;
|
||||
|
||||
let sisyphusMode: SisyphusModeSettings | undefined;
|
||||
const isForeverMode = argv.forever ?? false;
|
||||
|
||||
if (isForeverMode) {
|
||||
try {
|
||||
const yaml = await import('js-yaml');
|
||||
const fsPromises = await import('node:fs/promises');
|
||||
const path = await import('node:path');
|
||||
const { FRONTMATTER_REGEX } = await import('@google/gemini-cli-core');
|
||||
const { GEMINI_DIR } = await import('@google/gemini-cli-core');
|
||||
const { DEFAULT_CONTEXT_FILENAME } = await import(
|
||||
'@google/gemini-cli-core'
|
||||
);
|
||||
|
||||
const geminiMdPath = path.default.join(
|
||||
cwd,
|
||||
GEMINI_DIR,
|
||||
DEFAULT_CONTEXT_FILENAME,
|
||||
);
|
||||
const mdContent = await fsPromises.default.readFile(
|
||||
geminiMdPath,
|
||||
'utf-8',
|
||||
);
|
||||
const match = mdContent.match(FRONTMATTER_REGEX);
|
||||
|
||||
if (match) {
|
||||
const parsed = yaml.default.load(match[1]);
|
||||
if (parsed && typeof parsed === 'object') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const frontmatter = parsed as Record<string, unknown>;
|
||||
if (frontmatter['sisyphus']) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const sisyphusSettings = frontmatter['sisyphus'] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
sisyphusMode = {
|
||||
enabled:
|
||||
typeof sisyphusSettings['enabled'] === 'boolean'
|
||||
? sisyphusSettings['enabled']
|
||||
: false,
|
||||
idleTimeout:
|
||||
typeof sisyphusSettings['idleTimeout'] === 'number'
|
||||
? sisyphusSettings['idleTimeout']
|
||||
: undefined,
|
||||
prompt:
|
||||
typeof sisyphusSettings['prompt'] === 'string'
|
||||
? sisyphusSettings['prompt']
|
||||
: undefined,
|
||||
a2aPort:
|
||||
typeof sisyphusSettings['a2aPort'] === 'number'
|
||||
? sisyphusSettings['a2aPort']
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (_e) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
|
||||
let memoryContent: string | HierarchicalMemory = '';
|
||||
let fileCount = 0;
|
||||
let filePaths: string[] = [];
|
||||
@@ -499,7 +569,6 @@ export async function loadCliConfig(
|
||||
settings.context?.loadMemoryFromIncludeDirectories || false
|
||||
? includeDirectories
|
||||
: [],
|
||||
debugMode,
|
||||
fileService,
|
||||
extensionManager,
|
||||
trustedFolder,
|
||||
@@ -512,8 +581,11 @@ export async function loadCliConfig(
|
||||
filePaths = result.filePaths;
|
||||
}
|
||||
|
||||
const question = argv.promptInteractive || argv.prompt || '';
|
||||
|
||||
const question =
|
||||
argv.promptInteractive ||
|
||||
argv.prompt ||
|
||||
process.env['GEMINI_CLI_INITIAL_PROMPT'] ||
|
||||
'';
|
||||
// Determine approval mode with backward compatibility
|
||||
let approvalMode: ApprovalMode;
|
||||
const rawApprovalMode =
|
||||
@@ -606,7 +678,8 @@ export async function loadCliConfig(
|
||||
!!argv.acp ||
|
||||
!!argv.experimentalAcp ||
|
||||
(!isHeadlessMode({ prompt: argv.prompt, query: argv.query }) &&
|
||||
!argv.isCommand);
|
||||
!argv.isCommand) ||
|
||||
!!argv.forever;
|
||||
|
||||
const allowedTools = argv.allowedTools || settings.tools?.allowed || [];
|
||||
|
||||
@@ -774,6 +847,8 @@ export async function loadCliConfig(
|
||||
? settings.general.plan
|
||||
: (extensionPlanSettings ?? settings.general?.plan),
|
||||
enableEventDrivenScheduler: true,
|
||||
isForeverMode,
|
||||
sisyphusMode,
|
||||
skillsSupport: settings.skills?.enabled ?? true,
|
||||
disabledSkills: settings.skills?.disabled,
|
||||
experimentalJitContext: settings.experimental?.jitContext,
|
||||
@@ -806,6 +881,7 @@ export async function loadCliConfig(
|
||||
fakeResponses: argv.fakeResponses,
|
||||
recordResponses: argv.recordResponses,
|
||||
retryFetchErrors: settings.general?.retryFetchErrors,
|
||||
billing: settings.billing,
|
||||
maxAttempts: settings.general?.maxAttempts,
|
||||
ptyInfo: ptyInfo?.name,
|
||||
disableLLMCorrection: settings.tools?.disableLLMCorrection,
|
||||
|
||||
@@ -58,46 +58,6 @@ describe('keyBindings config', () => {
|
||||
const config: KeyBindingConfig = defaultKeyBindings;
|
||||
expect(config[Command.HOME]).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have correct specific bindings', () => {
|
||||
// Verify navigation ignores shift
|
||||
const navUp = defaultKeyBindings[Command.NAVIGATION_UP];
|
||||
expect(navUp).toContainEqual({ key: 'up', shift: false });
|
||||
|
||||
const navDown = defaultKeyBindings[Command.NAVIGATION_DOWN];
|
||||
expect(navDown).toContainEqual({ key: 'down', shift: false });
|
||||
|
||||
// Verify dialog navigation
|
||||
const dialogNavUp = defaultKeyBindings[Command.DIALOG_NAVIGATION_UP];
|
||||
expect(dialogNavUp).toContainEqual({ key: 'up', shift: false });
|
||||
expect(dialogNavUp).toContainEqual({ key: 'k', shift: false });
|
||||
|
||||
const dialogNavDown = defaultKeyBindings[Command.DIALOG_NAVIGATION_DOWN];
|
||||
expect(dialogNavDown).toContainEqual({ key: 'down', shift: false });
|
||||
expect(dialogNavDown).toContainEqual({ key: 'j', shift: false });
|
||||
|
||||
// Verify physical home/end keys for cursor movement
|
||||
expect(defaultKeyBindings[Command.HOME]).toContainEqual({
|
||||
key: 'home',
|
||||
ctrl: false,
|
||||
shift: false,
|
||||
});
|
||||
expect(defaultKeyBindings[Command.END]).toContainEqual({
|
||||
key: 'end',
|
||||
ctrl: false,
|
||||
shift: false,
|
||||
});
|
||||
|
||||
// Verify physical home/end keys for scrolling
|
||||
expect(defaultKeyBindings[Command.SCROLL_HOME]).toContainEqual({
|
||||
key: 'home',
|
||||
ctrl: true,
|
||||
});
|
||||
expect(defaultKeyBindings[Command.SCROLL_END]).toContainEqual({
|
||||
key: 'end',
|
||||
ctrl: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('command metadata', () => {
|
||||
|
||||
@@ -134,27 +134,12 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
||||
[Command.EXIT]: [{ key: 'd', ctrl: true }],
|
||||
|
||||
// Cursor Movement
|
||||
[Command.HOME]: [
|
||||
{ key: 'a', ctrl: true },
|
||||
{ key: 'home', shift: false, ctrl: false },
|
||||
],
|
||||
[Command.END]: [
|
||||
{ key: 'e', ctrl: true },
|
||||
{ key: 'end', shift: false, ctrl: false },
|
||||
],
|
||||
[Command.MOVE_UP]: [
|
||||
{ key: 'up', shift: false, alt: false, ctrl: false, cmd: false },
|
||||
],
|
||||
[Command.MOVE_DOWN]: [
|
||||
{ key: 'down', shift: false, alt: false, ctrl: false, cmd: false },
|
||||
],
|
||||
[Command.MOVE_LEFT]: [
|
||||
{ key: 'left', shift: false, alt: false, ctrl: false, cmd: false },
|
||||
],
|
||||
[Command.MOVE_RIGHT]: [
|
||||
{ key: 'right', shift: false, alt: false, ctrl: false, cmd: false },
|
||||
{ key: 'f', ctrl: true },
|
||||
],
|
||||
[Command.HOME]: [{ key: 'a', ctrl: true }, { key: 'home' }],
|
||||
[Command.END]: [{ key: 'e', ctrl: true }, { key: 'end' }],
|
||||
[Command.MOVE_UP]: [{ key: 'up' }],
|
||||
[Command.MOVE_DOWN]: [{ key: 'down' }],
|
||||
[Command.MOVE_LEFT]: [{ key: 'left' }],
|
||||
[Command.MOVE_RIGHT]: [{ key: 'right' }, { key: 'f', ctrl: true }],
|
||||
[Command.MOVE_WORD_LEFT]: [
|
||||
{ key: 'left', ctrl: true },
|
||||
{ key: 'left', alt: true },
|
||||
@@ -183,8 +168,8 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
||||
[Command.DELETE_CHAR_LEFT]: [{ key: 'backspace' }, { key: 'h', ctrl: true }],
|
||||
[Command.DELETE_CHAR_RIGHT]: [{ key: 'delete' }, { key: 'd', ctrl: true }],
|
||||
[Command.UNDO]: [
|
||||
{ key: 'z', cmd: true, shift: false },
|
||||
{ key: 'z', alt: true, shift: false },
|
||||
{ key: 'z', cmd: true },
|
||||
{ key: 'z', alt: true },
|
||||
],
|
||||
[Command.REDO]: [
|
||||
{ key: 'z', ctrl: true, shift: true },
|
||||
@@ -207,56 +192,33 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
||||
[Command.PAGE_DOWN]: [{ key: 'pagedown' }],
|
||||
|
||||
// History & Search
|
||||
[Command.HISTORY_UP]: [{ key: 'p', shift: false, ctrl: true }],
|
||||
[Command.HISTORY_DOWN]: [{ key: 'n', shift: false, ctrl: true }],
|
||||
[Command.HISTORY_UP]: [{ key: 'p', ctrl: true }],
|
||||
[Command.HISTORY_DOWN]: [{ key: 'n', ctrl: true }],
|
||||
[Command.REVERSE_SEARCH]: [{ key: 'r', ctrl: true }],
|
||||
[Command.REWIND]: [{ key: 'double escape' }],
|
||||
[Command.SUBMIT_REVERSE_SEARCH]: [{ key: 'return', ctrl: false }],
|
||||
[Command.ACCEPT_SUGGESTION_REVERSE_SEARCH]: [{ key: 'tab', shift: false }],
|
||||
[Command.REWIND]: [{ key: 'double escape' }], // for documentation only
|
||||
[Command.SUBMIT_REVERSE_SEARCH]: [{ key: 'return' }],
|
||||
[Command.ACCEPT_SUGGESTION_REVERSE_SEARCH]: [{ key: 'tab' }],
|
||||
|
||||
// Navigation
|
||||
[Command.NAVIGATION_UP]: [{ key: 'up', shift: false }],
|
||||
[Command.NAVIGATION_DOWN]: [{ key: 'down', shift: false }],
|
||||
[Command.NAVIGATION_UP]: [{ key: 'up' }],
|
||||
[Command.NAVIGATION_DOWN]: [{ key: 'down' }],
|
||||
// Navigation shortcuts appropriate for dialogs where we do not need to accept
|
||||
// text input.
|
||||
[Command.DIALOG_NAVIGATION_UP]: [
|
||||
{ key: 'up', shift: false },
|
||||
{ key: 'k', shift: false },
|
||||
],
|
||||
[Command.DIALOG_NAVIGATION_DOWN]: [
|
||||
{ key: 'down', shift: false },
|
||||
{ key: 'j', shift: false },
|
||||
],
|
||||
[Command.DIALOG_NEXT]: [{ key: 'tab', shift: false }],
|
||||
[Command.DIALOG_NAVIGATION_UP]: [{ key: 'up' }, { key: 'k' }],
|
||||
[Command.DIALOG_NAVIGATION_DOWN]: [{ key: 'down' }, { key: 'j' }],
|
||||
[Command.DIALOG_NEXT]: [{ key: 'tab' }],
|
||||
[Command.DIALOG_PREV]: [{ key: 'tab', shift: true }],
|
||||
|
||||
// Suggestions & Completions
|
||||
[Command.ACCEPT_SUGGESTION]: [
|
||||
{ key: 'tab', shift: false },
|
||||
{ key: 'return', ctrl: false },
|
||||
],
|
||||
[Command.COMPLETION_UP]: [
|
||||
{ key: 'up', shift: false },
|
||||
{ key: 'p', shift: false, ctrl: true },
|
||||
],
|
||||
[Command.COMPLETION_DOWN]: [
|
||||
{ key: 'down', shift: false },
|
||||
{ key: 'n', shift: false, ctrl: true },
|
||||
],
|
||||
[Command.ACCEPT_SUGGESTION]: [{ key: 'tab' }, { key: 'return' }],
|
||||
[Command.COMPLETION_UP]: [{ key: 'up' }, { key: 'p', ctrl: true }],
|
||||
[Command.COMPLETION_DOWN]: [{ key: 'down' }, { key: 'n', ctrl: true }],
|
||||
[Command.EXPAND_SUGGESTION]: [{ key: 'right' }],
|
||||
[Command.COLLAPSE_SUGGESTION]: [{ key: 'left' }],
|
||||
|
||||
// Text Input
|
||||
// Must also exclude shift to allow shift+enter for newline
|
||||
[Command.SUBMIT]: [
|
||||
{
|
||||
key: 'return',
|
||||
shift: false,
|
||||
alt: false,
|
||||
ctrl: false,
|
||||
cmd: false,
|
||||
},
|
||||
],
|
||||
[Command.SUBMIT]: [{ key: 'return' }],
|
||||
[Command.NEWLINE]: [
|
||||
{ key: 'return', ctrl: true },
|
||||
{ key: 'return', cmd: true },
|
||||
@@ -283,19 +245,17 @@ export const defaultKeyBindings: KeyBindingConfig = {
|
||||
[Command.TOGGLE_BACKGROUND_SHELL_LIST]: [{ key: 'l', ctrl: true }],
|
||||
[Command.KILL_BACKGROUND_SHELL]: [{ key: 'k', ctrl: true }],
|
||||
[Command.UNFOCUS_BACKGROUND_SHELL]: [{ key: 'tab', shift: true }],
|
||||
[Command.UNFOCUS_BACKGROUND_SHELL_LIST]: [{ key: 'tab', shift: false }],
|
||||
[Command.SHOW_BACKGROUND_SHELL_UNFOCUS_WARNING]: [
|
||||
{ key: 'tab', shift: false },
|
||||
],
|
||||
[Command.SHOW_SHELL_INPUT_UNFOCUS_WARNING]: [{ key: 'tab', shift: false }],
|
||||
[Command.UNFOCUS_BACKGROUND_SHELL_LIST]: [{ key: 'tab' }],
|
||||
[Command.SHOW_BACKGROUND_SHELL_UNFOCUS_WARNING]: [{ key: 'tab' }],
|
||||
[Command.SHOW_SHELL_INPUT_UNFOCUS_WARNING]: [{ key: 'tab' }],
|
||||
[Command.BACKGROUND_SHELL_SELECT]: [{ key: 'return' }],
|
||||
[Command.BACKGROUND_SHELL_ESCAPE]: [{ key: 'escape' }],
|
||||
[Command.SHOW_MORE_LINES]: [{ key: 'o', ctrl: true }],
|
||||
[Command.EXPAND_PASTE]: [{ key: 'o', ctrl: true }],
|
||||
[Command.FOCUS_SHELL_INPUT]: [{ key: 'tab', shift: false }],
|
||||
[Command.FOCUS_SHELL_INPUT]: [{ key: 'tab' }],
|
||||
[Command.UNFOCUS_SHELL_INPUT]: [{ key: 'tab', shift: true }],
|
||||
[Command.CLEAR_SCREEN]: [{ key: 'l', ctrl: true }],
|
||||
[Command.RESTART_APP]: [{ key: 'r' }],
|
||||
[Command.RESTART_APP]: [{ key: 'r' }, { key: 'r', shift: true }],
|
||||
[Command.SUSPEND_APP]: [{ key: 'z', ctrl: true }],
|
||||
};
|
||||
|
||||
|
||||
@@ -93,13 +93,13 @@ describe('Policy Engine Integration Tests', () => {
|
||||
// Tools from allowed server should be allowed
|
||||
// Tools from allowed server should be allowed
|
||||
expect(
|
||||
(await engine.check({ name: 'allowed-server__tool1' }, undefined))
|
||||
(await engine.check({ name: 'mcp_allowed-server_tool1' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(
|
||||
await engine.check(
|
||||
{ name: 'allowed-server__another_tool' },
|
||||
{ name: 'mcp_allowed-server_another_tool' },
|
||||
undefined,
|
||||
)
|
||||
).decision,
|
||||
@@ -107,13 +107,13 @@ describe('Policy Engine Integration Tests', () => {
|
||||
|
||||
// Tools from trusted server should be allowed
|
||||
expect(
|
||||
(await engine.check({ name: 'trusted-server__tool1' }, undefined))
|
||||
(await engine.check({ name: 'mcp_trusted-server_tool1' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(
|
||||
await engine.check(
|
||||
{ name: 'trusted-server__special_tool' },
|
||||
{ name: 'mcp_trusted-server_special_tool' },
|
||||
undefined,
|
||||
)
|
||||
).decision,
|
||||
@@ -121,17 +121,17 @@ describe('Policy Engine Integration Tests', () => {
|
||||
|
||||
// Tools from blocked server should be denied
|
||||
expect(
|
||||
(await engine.check({ name: 'blocked-server__tool1' }, undefined))
|
||||
(await engine.check({ name: 'mcp_blocked-server_tool1' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
expect(
|
||||
(await engine.check({ name: 'blocked-server__any_tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_blocked-server_any_tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
|
||||
// Tools from unknown servers should use default
|
||||
expect(
|
||||
(await engine.check({ name: 'unknown-server__tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_unknown-server_tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ASK_USER);
|
||||
});
|
||||
@@ -151,12 +151,16 @@ describe('Policy Engine Integration Tests', () => {
|
||||
|
||||
// ANY tool with a server name should be allowed
|
||||
expect(
|
||||
(await engine.check({ name: 'mcp-server__tool' }, 'mcp-server'))
|
||||
(await engine.check({ name: 'mcp_mcp-server_tool' }, 'mcp-server'))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(await engine.check({ name: 'another-server__tool' }, 'another-server'))
|
||||
.decision,
|
||||
(
|
||||
await engine.check(
|
||||
{ name: 'mcp_another-server_tool' },
|
||||
'another-server',
|
||||
)
|
||||
).decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
|
||||
// Built-in tools should NOT be allowed by the MCP wildcard
|
||||
@@ -171,7 +175,7 @@ describe('Policy Engine Integration Tests', () => {
|
||||
allowed: ['my-server'],
|
||||
},
|
||||
tools: {
|
||||
exclude: ['my-server__dangerous-tool'],
|
||||
exclude: ['mcp_my-server_dangerous-tool'],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -184,20 +188,24 @@ describe('Policy Engine Integration Tests', () => {
|
||||
// MCP server allowed (priority 4.1) provides general allow for server
|
||||
// MCP server allowed (priority 4.1) provides general allow for server
|
||||
expect(
|
||||
(await engine.check({ name: 'my-server__safe-tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_my-server_safe-tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
// But specific tool exclude (priority 4.4) wins over server allow
|
||||
expect(
|
||||
(await engine.check({ name: 'my-server__dangerous-tool' }, undefined))
|
||||
.decision,
|
||||
(
|
||||
await engine.check(
|
||||
{ name: 'mcp_my-server_dangerous-tool' },
|
||||
undefined,
|
||||
)
|
||||
).decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
});
|
||||
|
||||
it('should handle complex mixed configurations', async () => {
|
||||
const settings: Settings = {
|
||||
tools: {
|
||||
allowed: ['custom-tool', 'my-server__special-tool'],
|
||||
allowed: ['custom-tool', 'mcp_my-server_special-tool'],
|
||||
exclude: ['glob', 'dangerous-tool'],
|
||||
},
|
||||
mcp: {
|
||||
@@ -242,21 +250,21 @@ describe('Policy Engine Integration Tests', () => {
|
||||
(await engine.check({ name: 'custom-tool' }, undefined)).decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(await engine.check({ name: 'my-server__special-tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_my-server_special-tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
|
||||
// MCP server tools
|
||||
expect(
|
||||
(await engine.check({ name: 'allowed-server__tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_allowed-server_tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(await engine.check({ name: 'trusted-server__tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_trusted-server_tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(await engine.check({ name: 'blocked-server__tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_blocked-server_tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
|
||||
@@ -483,7 +491,7 @@ describe('Policy Engine Integration Tests', () => {
|
||||
expect(blockedToolRule?.priority).toBe(4.4); // Command line exclude
|
||||
|
||||
const blockedServerRule = rules.find(
|
||||
(r) => r.toolName === 'blocked-server__*',
|
||||
(r) => r.toolName === 'mcp_blocked-server_*',
|
||||
);
|
||||
expect(blockedServerRule?.priority).toBe(4.9); // MCP server exclude
|
||||
|
||||
@@ -493,11 +501,13 @@ describe('Policy Engine Integration Tests', () => {
|
||||
expect(specificToolRule?.priority).toBe(4.3); // Command line allow
|
||||
|
||||
const trustedServerRule = rules.find(
|
||||
(r) => r.toolName === 'trusted-server__*',
|
||||
(r) => r.toolName === 'mcp_trusted-server_*',
|
||||
);
|
||||
expect(trustedServerRule?.priority).toBe(4.2); // MCP trusted server
|
||||
|
||||
const mcpServerRule = rules.find((r) => r.toolName === 'mcp-server__*');
|
||||
const mcpServerRule = rules.find(
|
||||
(r) => r.toolName === 'mcp_mcp-server_*',
|
||||
);
|
||||
expect(mcpServerRule?.priority).toBe(4.1); // MCP allowed server
|
||||
|
||||
const readOnlyToolRule = rules.find((r) => r.toolName === 'glob');
|
||||
@@ -509,18 +519,19 @@ describe('Policy Engine Integration Tests', () => {
|
||||
(await engine.check({ name: 'blocked-tool' }, undefined)).decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
expect(
|
||||
(await engine.check({ name: 'blocked-server__any' }, undefined))
|
||||
(await engine.check({ name: 'mcp_blocked-server_any' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
expect(
|
||||
(await engine.check({ name: 'specific-tool' }, undefined)).decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(await engine.check({ name: 'trusted-server__any' }, undefined))
|
||||
(await engine.check({ name: 'mcp_trusted-server_any' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect(
|
||||
(await engine.check({ name: 'mcp-server__any' }, undefined)).decision,
|
||||
(await engine.check({ name: 'mcp_mcp-server_any' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.ALLOW);
|
||||
expect((await engine.check({ name: 'glob' }, undefined)).decision).toBe(
|
||||
PolicyDecision.ALLOW,
|
||||
@@ -549,7 +560,7 @@ describe('Policy Engine Integration Tests', () => {
|
||||
|
||||
// Exclusion (195) should win over trust (90)
|
||||
expect(
|
||||
(await engine.check({ name: 'conflicted-server__tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_conflicted-server_tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
});
|
||||
@@ -560,7 +571,7 @@ describe('Policy Engine Integration Tests', () => {
|
||||
excluded: ['my-server'], // Priority 195 - DENY
|
||||
},
|
||||
tools: {
|
||||
allowed: ['my-server__special-tool'], // Priority 100 - ALLOW
|
||||
allowed: ['mcp_my-server_special-tool'], // Priority 100 - ALLOW
|
||||
},
|
||||
};
|
||||
|
||||
@@ -573,11 +584,11 @@ describe('Policy Engine Integration Tests', () => {
|
||||
// Server exclusion (195) wins over specific tool allow (100)
|
||||
// This might be counterintuitive but follows the priority system
|
||||
expect(
|
||||
(await engine.check({ name: 'my-server__special-tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_my-server_special-tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
expect(
|
||||
(await engine.check({ name: 'my-server__other-tool' }, undefined))
|
||||
(await engine.check({ name: 'mcp_my-server_other-tool' }, undefined))
|
||||
.decision,
|
||||
).toBe(PolicyDecision.DENY);
|
||||
});
|
||||
@@ -647,13 +658,13 @@ describe('Policy Engine Integration Tests', () => {
|
||||
const tool3Rule = rules.find((r) => r.toolName === 'tool3');
|
||||
expect(tool3Rule?.priority).toBe(4.4); // Excluded tools (user tier)
|
||||
|
||||
const server2Rule = rules.find((r) => r.toolName === 'server2__*');
|
||||
const server2Rule = rules.find((r) => r.toolName === 'mcp_server2_*');
|
||||
expect(server2Rule?.priority).toBe(4.9); // Excluded servers (user tier)
|
||||
|
||||
const tool1Rule = rules.find((r) => r.toolName === 'tool1');
|
||||
expect(tool1Rule?.priority).toBe(4.3); // Allowed tools (user tier)
|
||||
|
||||
const server1Rule = rules.find((r) => r.toolName === 'server1__*');
|
||||
const server1Rule = rules.find((r) => r.toolName === 'mcp_server1_*');
|
||||
expect(server1Rule?.priority).toBe(4.1); // Allowed servers (user tier)
|
||||
|
||||
const globRule = rules.find((r) => r.toolName === 'glob');
|
||||
|
||||
@@ -185,6 +185,9 @@ export interface SessionRetentionSettings {
|
||||
|
||||
/** Minimum retention period (safety limit, defaults to "1d") */
|
||||
minRetention?: string;
|
||||
|
||||
/** Whether the user has acknowledged the session retention warning */
|
||||
warningAcknowledged?: boolean;
|
||||
}
|
||||
|
||||
export interface SettingsError {
|
||||
|
||||
@@ -461,7 +461,7 @@ describe('SettingsSchema', () => {
|
||||
expect(gemmaModelRouter.category).toBe('Experimental');
|
||||
expect(gemmaModelRouter.default).toEqual({});
|
||||
expect(gemmaModelRouter.requiresRestart).toBe(true);
|
||||
expect(gemmaModelRouter.showInDialog).toBe(true);
|
||||
expect(gemmaModelRouter.showInDialog).toBe(false);
|
||||
expect(gemmaModelRouter.description).toBe(
|
||||
'Enable Gemma model router (experimental).',
|
||||
);
|
||||
@@ -472,9 +472,9 @@ describe('SettingsSchema', () => {
|
||||
expect(enabled.category).toBe('Experimental');
|
||||
expect(enabled.default).toBe(false);
|
||||
expect(enabled.requiresRestart).toBe(true);
|
||||
expect(enabled.showInDialog).toBe(true);
|
||||
expect(enabled.showInDialog).toBe(false);
|
||||
expect(enabled.description).toBe(
|
||||
'Enable the Gemma Model Router. Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim.',
|
||||
'Enable the Gemma Model Router (experimental). Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim.',
|
||||
);
|
||||
|
||||
const classifier = gemmaModelRouter.properties.classifier;
|
||||
|
||||
@@ -376,6 +376,16 @@ const SETTINGS_SCHEMA = {
|
||||
description: `Minimum retention period (safety limit, defaults to "${DEFAULT_MIN_RETENTION}")`,
|
||||
showInDialog: false,
|
||||
},
|
||||
warningAcknowledged: {
|
||||
type: 'boolean',
|
||||
label: 'Warning Acknowledged',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
default: false as boolean,
|
||||
description:
|
||||
'Whether the user has acknowledged the session retention warning',
|
||||
showInDialog: false,
|
||||
},
|
||||
},
|
||||
description: 'Settings for automatic session cleanup.',
|
||||
},
|
||||
@@ -1863,7 +1873,7 @@ const SETTINGS_SCHEMA = {
|
||||
requiresRestart: true,
|
||||
default: {},
|
||||
description: 'Enable Gemma model router (experimental).',
|
||||
showInDialog: true,
|
||||
showInDialog: false,
|
||||
properties: {
|
||||
enabled: {
|
||||
type: 'boolean',
|
||||
@@ -1872,8 +1882,8 @@ const SETTINGS_SCHEMA = {
|
||||
requiresRestart: true,
|
||||
default: false,
|
||||
description:
|
||||
'Enable the Gemma Model Router. Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim.',
|
||||
showInDialog: true,
|
||||
'Enable the Gemma Model Router (experimental). Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim.',
|
||||
showInDialog: false,
|
||||
},
|
||||
classifier: {
|
||||
type: 'object',
|
||||
|
||||
@@ -0,0 +1,453 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import http from 'node:http';
|
||||
import { writeFileSync, mkdirSync, unlinkSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import os from 'node:os';
|
||||
import crypto from 'node:crypto';
|
||||
import { appEvents, AppEvent } from './utils/events.js';
|
||||
|
||||
// --- A2A Task management ---
|
||||
|
||||
interface A2AResponseMessage {
|
||||
kind: 'message';
|
||||
role: 'agent';
|
||||
parts: Array<{ kind: 'text'; text: string }>;
|
||||
messageId: string;
|
||||
}
|
||||
|
||||
interface A2ATask {
|
||||
id: string;
|
||||
contextId: string;
|
||||
status: {
|
||||
state: 'submitted' | 'working' | 'completed' | 'failed';
|
||||
timestamp: string;
|
||||
message?: A2AResponseMessage;
|
||||
};
|
||||
}
|
||||
|
||||
const tasks = new Map<string, A2ATask>();
|
||||
|
||||
const TASK_CLEANUP_DELAY_MS = 10 * 60 * 1000; // 10 minutes
|
||||
const DEFAULT_BLOCKING_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
interface ResponseWaiter {
|
||||
taskId: string;
|
||||
resolve: (text: string) => void;
|
||||
}
|
||||
|
||||
const responseWaiters: ResponseWaiter[] = [];
|
||||
|
||||
// Queue for unsolicited responses (e.g. Sisyphus auto-resume output)
|
||||
const unsolicitedResponses: string[] = [];
|
||||
|
||||
/**
|
||||
* Called by AppContainer when streaming transitions from non-Idle to Idle.
|
||||
* If there's a pending A2A task, resolves it. Otherwise queues as unsolicited.
|
||||
*/
|
||||
export function notifyResponse(responseText: string): void {
|
||||
if (!responseText) return;
|
||||
|
||||
const waiter = responseWaiters.shift();
|
||||
if (!waiter) {
|
||||
// No A2A task waiting — queue as unsolicited (Sisyphus, etc.)
|
||||
unsolicitedResponses.push(responseText);
|
||||
return;
|
||||
}
|
||||
|
||||
const task = tasks.get(waiter.taskId);
|
||||
if (task) {
|
||||
task.status = {
|
||||
state: 'completed',
|
||||
timestamp: new Date().toISOString(),
|
||||
message: {
|
||||
kind: 'message',
|
||||
role: 'agent',
|
||||
parts: [{ kind: 'text', text: responseText }],
|
||||
messageId: crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
scheduleTaskCleanup(task.id);
|
||||
}
|
||||
|
||||
waiter.resolve(responseText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drain all unsolicited responses (from Sisyphus auto-resume, etc.).
|
||||
*/
|
||||
export function drainUnsolicitedResponses(): string[] {
|
||||
return unsolicitedResponses.splice(0, unsolicitedResponses.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are any in-flight tasks waiting for a response.
|
||||
*/
|
||||
export function hasPendingTasks(): boolean {
|
||||
return responseWaiters.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when streaming starts (Idle -> non-Idle) to mark the oldest
|
||||
* submitted task as "working".
|
||||
*/
|
||||
export function markTasksWorking(): void {
|
||||
const waiter = responseWaiters[0];
|
||||
if (!waiter) return;
|
||||
const task = tasks.get(waiter.taskId);
|
||||
if (task && task.status.state === 'submitted') {
|
||||
task.status = {
|
||||
state: 'working',
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleTaskCleanup(taskId: string): void {
|
||||
setTimeout(() => {
|
||||
tasks.delete(taskId);
|
||||
}, TASK_CLEANUP_DELAY_MS);
|
||||
}
|
||||
|
||||
function createTask(): A2ATask {
|
||||
const task: A2ATask = {
|
||||
id: crypto.randomUUID(),
|
||||
contextId: `session-${process.pid}`,
|
||||
status: {
|
||||
state: 'submitted',
|
||||
timestamp: new Date().toISOString(),
|
||||
},
|
||||
};
|
||||
tasks.set(task.id, task);
|
||||
return task;
|
||||
}
|
||||
|
||||
function formatTaskResult(task: A2ATask): object {
|
||||
return {
|
||||
kind: 'task',
|
||||
id: task.id,
|
||||
contextId: task.contextId,
|
||||
status: task.status,
|
||||
};
|
||||
}
|
||||
|
||||
// --- JSON-RPC helpers ---
|
||||
|
||||
interface JsonRpcRequest {
|
||||
jsonrpc?: string;
|
||||
id?: string | number | null;
|
||||
method?: string;
|
||||
params?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
function jsonRpcSuccess(id: string | number | null, result: object): object {
|
||||
return { jsonrpc: '2.0', id, result };
|
||||
}
|
||||
|
||||
function jsonRpcError(
|
||||
id: string | number | null,
|
||||
code: number,
|
||||
message: string,
|
||||
): object {
|
||||
return { jsonrpc: '2.0', id, error: { code, message } };
|
||||
}
|
||||
|
||||
// --- HTTP utilities ---
|
||||
|
||||
function getSessionsDir(): string {
|
||||
return join(os.homedir(), '.gemini', 'sessions');
|
||||
}
|
||||
|
||||
function getPortFilePath(): string {
|
||||
return join(getSessionsDir(), `interactive-${process.pid}.port`);
|
||||
}
|
||||
|
||||
function buildAgentCard(port: number): object {
|
||||
return {
|
||||
name: 'Gemini CLI Interactive Session',
|
||||
url: `http://localhost:${port}/`,
|
||||
protocolVersion: '0.3.0',
|
||||
provider: { organization: 'Google', url: 'https://google.com' },
|
||||
capabilities: { streaming: false, pushNotifications: false },
|
||||
defaultInputModes: ['text'],
|
||||
defaultOutputModes: ['text'],
|
||||
skills: [
|
||||
{
|
||||
id: 'interactive_session',
|
||||
name: 'Interactive Session',
|
||||
description: 'Send messages to the live interactive Gemini CLI session',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
interface A2AMessagePart {
|
||||
kind?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
function extractTextFromParts(
|
||||
parts: A2AMessagePart[] | undefined,
|
||||
): string | null {
|
||||
if (!Array.isArray(parts)) {
|
||||
return null;
|
||||
}
|
||||
const texts: string[] = [];
|
||||
for (const part of parts) {
|
||||
if (part.kind === 'text' && typeof part.text === 'string') {
|
||||
texts.push(part.text);
|
||||
}
|
||||
}
|
||||
return texts.length > 0 ? texts.join('\n') : null;
|
||||
}
|
||||
|
||||
function sendJson(
|
||||
res: http.ServerResponse,
|
||||
statusCode: number,
|
||||
data: object,
|
||||
): void {
|
||||
const body = JSON.stringify(data);
|
||||
res.writeHead(statusCode, {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': Buffer.byteLength(body),
|
||||
});
|
||||
res.end(body);
|
||||
}
|
||||
|
||||
function readBody(req: http.IncomingMessage): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
let size = 0;
|
||||
const maxSize = 1024 * 1024; // 1MB limit
|
||||
req.on('data', (chunk: Buffer) => {
|
||||
size += chunk.length;
|
||||
if (size > maxSize) {
|
||||
req.destroy();
|
||||
reject(new Error('Request body too large'));
|
||||
return;
|
||||
}
|
||||
chunks.push(chunk);
|
||||
});
|
||||
req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
|
||||
req.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
// --- JSON-RPC request handlers ---
|
||||
|
||||
function handleMessageSend(
|
||||
rpcId: string | number | null,
|
||||
params: Record<string, unknown>,
|
||||
res: http.ServerResponse,
|
||||
): void {
|
||||
const messageVal = params['message'];
|
||||
const message =
|
||||
messageVal && typeof messageVal === 'object'
|
||||
? (messageVal as { role?: string; parts?: A2AMessagePart[] })
|
||||
: undefined;
|
||||
const text = extractTextFromParts(message?.parts);
|
||||
if (!text) {
|
||||
sendJson(
|
||||
res,
|
||||
200,
|
||||
jsonRpcError(
|
||||
rpcId,
|
||||
-32602,
|
||||
'Missing or empty text. Expected: params.message.parts with kind "text".',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const task = createTask();
|
||||
|
||||
// Inject message into the session
|
||||
appEvents.emit(AppEvent.ExternalMessage, text);
|
||||
|
||||
// Block until response (standard A2A message/send semantics)
|
||||
const timer = setTimeout(() => {
|
||||
const idx = responseWaiters.findIndex((w) => w.taskId === task.id);
|
||||
if (idx !== -1) {
|
||||
responseWaiters.splice(idx, 1);
|
||||
}
|
||||
task.status = {
|
||||
state: 'failed',
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
scheduleTaskCleanup(task.id);
|
||||
sendJson(res, 200, jsonRpcError(rpcId, -32000, 'Request timed out'));
|
||||
}, DEFAULT_BLOCKING_TIMEOUT_MS);
|
||||
|
||||
responseWaiters.push({
|
||||
taskId: task.id,
|
||||
resolve: () => {
|
||||
clearTimeout(timer);
|
||||
// Task is already updated in notifyResponse
|
||||
const updatedTask = tasks.get(task.id);
|
||||
sendJson(
|
||||
res,
|
||||
200,
|
||||
jsonRpcSuccess(rpcId, formatTaskResult(updatedTask ?? task)),
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleResponsesPoll(
|
||||
rpcId: string | number | null,
|
||||
res: http.ServerResponse,
|
||||
): void {
|
||||
const responses = drainUnsolicitedResponses();
|
||||
sendJson(res, 200, jsonRpcSuccess(rpcId, { responses }));
|
||||
}
|
||||
|
||||
function handleTasksGet(
|
||||
rpcId: string | number | null,
|
||||
params: Record<string, unknown>,
|
||||
res: http.ServerResponse,
|
||||
): void {
|
||||
const taskId = params['id'];
|
||||
if (typeof taskId !== 'string') {
|
||||
sendJson(
|
||||
res,
|
||||
200,
|
||||
jsonRpcError(rpcId, -32602, 'Missing or invalid params.id'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const task = tasks.get(taskId);
|
||||
if (!task) {
|
||||
sendJson(res, 200, jsonRpcError(rpcId, -32001, 'Task not found'));
|
||||
return;
|
||||
}
|
||||
|
||||
sendJson(res, 200, jsonRpcSuccess(rpcId, formatTaskResult(task)));
|
||||
}
|
||||
|
||||
// --- Server ---
|
||||
|
||||
export interface ExternalListenerResult {
|
||||
port: number;
|
||||
cleanup: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an embedded HTTP server that accepts A2A-format JSON-RPC messages
|
||||
* and bridges them into the interactive session's message queue.
|
||||
*/
|
||||
export function startExternalListener(options?: {
|
||||
port?: number;
|
||||
}): Promise<ExternalListenerResult> {
|
||||
const port = options?.port ?? 0;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = http.createServer(
|
||||
(req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
const url = new URL(req.url ?? '/', `http://localhost`);
|
||||
|
||||
// GET /.well-known/agent-card.json
|
||||
if (
|
||||
req.method === 'GET' &&
|
||||
url.pathname === '/.well-known/agent-card.json'
|
||||
) {
|
||||
const address = server.address();
|
||||
const actualPort =
|
||||
typeof address === 'object' && address ? address.port : port;
|
||||
sendJson(res, 200, buildAgentCard(actualPort));
|
||||
return;
|
||||
}
|
||||
|
||||
// POST / — JSON-RPC 2.0 routing
|
||||
if (req.method === 'POST' && url.pathname === '/') {
|
||||
readBody(req)
|
||||
.then((rawBody) => {
|
||||
let parsed: JsonRpcRequest;
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
parsed = JSON.parse(rawBody) as JsonRpcRequest;
|
||||
} catch {
|
||||
sendJson(
|
||||
res,
|
||||
200,
|
||||
jsonRpcError(null, -32700, 'Parse error: invalid JSON'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const rpcId = parsed.id ?? null;
|
||||
const method = parsed.method;
|
||||
const params = parsed.params ?? {};
|
||||
|
||||
switch (method) {
|
||||
case 'message/send':
|
||||
handleMessageSend(rpcId, params, res);
|
||||
break;
|
||||
case 'tasks/get':
|
||||
handleTasksGet(rpcId, params, res);
|
||||
break;
|
||||
case 'responses/poll':
|
||||
handleResponsesPoll(rpcId, res);
|
||||
break;
|
||||
default:
|
||||
sendJson(
|
||||
res,
|
||||
200,
|
||||
jsonRpcError(
|
||||
rpcId,
|
||||
-32601,
|
||||
`Method not found: ${method ?? '(none)'}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
sendJson(
|
||||
res,
|
||||
200,
|
||||
jsonRpcError(null, -32603, 'Failed to read request body'),
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 404 for everything else
|
||||
sendJson(res, 404, { error: 'Not found' });
|
||||
},
|
||||
);
|
||||
|
||||
server.listen(port, '127.0.0.1', () => {
|
||||
const address = server.address();
|
||||
const actualPort =
|
||||
typeof address === 'object' && address ? address.port : port;
|
||||
|
||||
// Write port file
|
||||
try {
|
||||
const sessionsDir = getSessionsDir();
|
||||
mkdirSync(sessionsDir, { recursive: true });
|
||||
writeFileSync(getPortFilePath(), String(actualPort), 'utf-8');
|
||||
} catch {
|
||||
// Non-fatal: port file is a convenience, not a requirement
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
server.close();
|
||||
try {
|
||||
unlinkSync(getPortFilePath());
|
||||
} catch {
|
||||
// Ignore: file may already be deleted
|
||||
}
|
||||
};
|
||||
|
||||
resolve({ port: actualPort, cleanup });
|
||||
});
|
||||
|
||||
server.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -479,6 +479,7 @@ describe('gemini.tsx main function kitty protocol', () => {
|
||||
promptInteractive: undefined,
|
||||
query: undefined,
|
||||
yolo: undefined,
|
||||
forever: undefined,
|
||||
approvalMode: undefined,
|
||||
policy: undefined,
|
||||
allowedMcpServerNames: undefined,
|
||||
@@ -747,6 +748,60 @@ describe('gemini.tsx main function kitty protocol', () => {
|
||||
emitFeedbackSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should start normally with a warning when no sessions found for resume', async () => {
|
||||
const { SessionSelector, SessionError } = await import(
|
||||
'./utils/sessionUtils.js'
|
||||
);
|
||||
vi.mocked(SessionSelector).mockImplementation(
|
||||
() =>
|
||||
({
|
||||
resolveSession: vi
|
||||
.fn()
|
||||
.mockRejectedValue(SessionError.noSessionsFound()),
|
||||
}) as unknown as InstanceType<typeof SessionSelector>,
|
||||
);
|
||||
|
||||
const processExitSpy = vi
|
||||
.spyOn(process, 'exit')
|
||||
.mockImplementation((code) => {
|
||||
throw new MockProcessExitError(code);
|
||||
});
|
||||
const emitFeedbackSpy = vi.spyOn(coreEvents, 'emitFeedback');
|
||||
|
||||
vi.mocked(loadSettings).mockReturnValue(
|
||||
createMockSettings({
|
||||
merged: { advanced: {}, security: { auth: {} }, ui: { theme: 'test' } },
|
||||
workspace: { settings: {} },
|
||||
setValue: vi.fn(),
|
||||
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
|
||||
}),
|
||||
);
|
||||
|
||||
vi.mocked(parseArguments).mockResolvedValue({
|
||||
promptInteractive: false,
|
||||
resume: 'latest',
|
||||
} as unknown as CliArgs);
|
||||
vi.mocked(loadCliConfig).mockResolvedValue(
|
||||
createMockConfig({
|
||||
isInteractive: () => true,
|
||||
getQuestion: () => '',
|
||||
getSandbox: () => undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
await main();
|
||||
|
||||
// Should NOT have crashed
|
||||
expect(processExitSpy).not.toHaveBeenCalled();
|
||||
// Should NOT have emitted a feedback error
|
||||
expect(emitFeedbackSpy).not.toHaveBeenCalledWith(
|
||||
'error',
|
||||
expect.stringContaining('Error resuming session'),
|
||||
);
|
||||
processExitSpy.mockRestore();
|
||||
emitFeedbackSpy.mockRestore();
|
||||
});
|
||||
|
||||
it.skip('should log error when cleanupExpiredSessions fails', async () => {
|
||||
const { cleanupExpiredSessions } = await import(
|
||||
'./utils/sessionCleanup.js'
|
||||
@@ -959,13 +1014,18 @@ describe('gemini.tsx main function exit codes', () => {
|
||||
resume: 'invalid-session',
|
||||
} as unknown as CliArgs);
|
||||
|
||||
vi.mock('./utils/sessionUtils.js', () => ({
|
||||
SessionSelector: vi.fn().mockImplementation(() => ({
|
||||
resolveSession: vi
|
||||
.fn()
|
||||
.mockRejectedValue(new Error('Session not found')),
|
||||
})),
|
||||
}));
|
||||
vi.mock('./utils/sessionUtils.js', async (importOriginal) => {
|
||||
const original =
|
||||
await importOriginal<typeof import('./utils/sessionUtils.js')>();
|
||||
return {
|
||||
...original,
|
||||
SessionSelector: vi.fn().mockImplementation(() => ({
|
||||
resolveSession: vi
|
||||
.fn()
|
||||
.mockRejectedValue(new Error('Session not found')),
|
||||
})),
|
||||
};
|
||||
});
|
||||
|
||||
process.env['GEMINI_API_KEY'] = 'test-key';
|
||||
try {
|
||||
|
||||
@@ -84,7 +84,8 @@ import { validateNonInteractiveAuth } from './validateNonInterActiveAuth.js';
|
||||
import { checkForUpdates } from './ui/utils/updateCheck.js';
|
||||
import { handleAutoUpdate } from './utils/handleAutoUpdate.js';
|
||||
import { appEvents, AppEvent } from './utils/events.js';
|
||||
import { SessionSelector } from './utils/sessionUtils.js';
|
||||
import { startExternalListener } from './external-listener.js';
|
||||
import { SessionError, SessionSelector } from './utils/sessionUtils.js';
|
||||
import { SettingsContext } from './ui/contexts/SettingsContext.js';
|
||||
import { MouseProvider } from './ui/contexts/MouseContext.js';
|
||||
import { StreamingState } from './ui/types.js';
|
||||
@@ -323,6 +324,26 @@ export async function startInteractiveUI(
|
||||
registerCleanup(() => instance.unmount());
|
||||
|
||||
registerCleanup(setupTtyCheck());
|
||||
|
||||
// Auto-start A2A HTTP listener in Forever Mode
|
||||
const sisyphusMode = config.getSisyphusMode();
|
||||
if (config.getIsForeverMode()) {
|
||||
const a2aPort = sisyphusMode.a2aPort ?? 0;
|
||||
try {
|
||||
const listener = await startExternalListener({ port: a2aPort });
|
||||
registerCleanup(listener.cleanup);
|
||||
appEvents.emit(AppEvent.A2AListenerStarted, listener.port);
|
||||
coreEvents.emitFeedback(
|
||||
'info',
|
||||
`A2A endpoint listening on port ${listener.port}`,
|
||||
);
|
||||
} catch (err) {
|
||||
coreEvents.emitFeedback(
|
||||
'warning',
|
||||
`Failed to start A2A listener: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function main() {
|
||||
@@ -706,12 +727,24 @@ export async function main() {
|
||||
// Use the existing session ID to continue recording to the same session
|
||||
config.setSessionId(resumedSessionData.conversation.sessionId);
|
||||
} catch (error) {
|
||||
coreEvents.emitFeedback(
|
||||
'error',
|
||||
`Error resuming session: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
);
|
||||
await runExitCleanup();
|
||||
process.exit(ExitCodes.FATAL_INPUT_ERROR);
|
||||
if (
|
||||
error instanceof SessionError &&
|
||||
error.code === 'NO_SESSIONS_FOUND'
|
||||
) {
|
||||
// No sessions to resume — start a fresh session with a warning
|
||||
startupWarnings.push({
|
||||
id: 'resume-no-sessions',
|
||||
message: error.message,
|
||||
priority: WarningPriority.High,
|
||||
});
|
||||
} else {
|
||||
coreEvents.emitFeedback(
|
||||
'error',
|
||||
`Error resuming session: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
);
|
||||
await runExitCleanup();
|
||||
process.exit(ExitCodes.FATAL_INPUT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -222,6 +222,7 @@ export async function runNonInteractive({
|
||||
await geminiClient.resumeChat(
|
||||
convertSessionToClientHistory(
|
||||
resumedSessionData.conversation.messages,
|
||||
resumedSessionData.conversation.lastCompressionIndex,
|
||||
),
|
||||
resumedSessionData,
|
||||
);
|
||||
|
||||
@@ -17,21 +17,9 @@ const createMockCommand = (name: string, kind: CommandKind): SlashCommand => ({
|
||||
action: vi.fn(),
|
||||
});
|
||||
|
||||
const mockCommandA = createMockCommand('command-a', CommandKind.BUILT_IN);
|
||||
const mockCommandB = createMockCommand('command-b', CommandKind.BUILT_IN);
|
||||
const mockCommandC = createMockCommand('command-c', CommandKind.FILE);
|
||||
const mockCommandB_Override = createMockCommand('command-b', CommandKind.FILE);
|
||||
|
||||
class MockCommandLoader implements ICommandLoader {
|
||||
private commandsToLoad: SlashCommand[];
|
||||
|
||||
constructor(commandsToLoad: SlashCommand[]) {
|
||||
this.commandsToLoad = commandsToLoad;
|
||||
}
|
||||
|
||||
loadCommands = vi.fn(
|
||||
async (): Promise<SlashCommand[]> => Promise.resolve(this.commandsToLoad),
|
||||
);
|
||||
constructor(private readonly commands: SlashCommand[]) {}
|
||||
loadCommands = vi.fn(async () => Promise.resolve(this.commands));
|
||||
}
|
||||
|
||||
describe('CommandService', () => {
|
||||
@@ -43,424 +31,74 @@ describe('CommandService', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should load commands from a single loader', async () => {
|
||||
const mockLoader = new MockCommandLoader([mockCommandA, mockCommandB]);
|
||||
const service = await CommandService.create(
|
||||
[mockLoader],
|
||||
new AbortController().signal,
|
||||
);
|
||||
describe('basic loading', () => {
|
||||
it('should aggregate commands from multiple successful loaders', async () => {
|
||||
const cmdA = createMockCommand('a', CommandKind.BUILT_IN);
|
||||
const cmdB = createMockCommand('b', CommandKind.USER_FILE);
|
||||
const service = await CommandService.create(
|
||||
[new MockCommandLoader([cmdA]), new MockCommandLoader([cmdB])],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
expect(service.getCommands()).toHaveLength(2);
|
||||
expect(service.getCommands()).toEqual(
|
||||
expect.arrayContaining([cmdA, cmdB]),
|
||||
);
|
||||
});
|
||||
|
||||
expect(mockLoader.loadCommands).toHaveBeenCalledTimes(1);
|
||||
expect(commands).toHaveLength(2);
|
||||
expect(commands).toEqual(
|
||||
expect.arrayContaining([mockCommandA, mockCommandB]),
|
||||
);
|
||||
});
|
||||
it('should handle empty loaders and failed loaders gracefully', async () => {
|
||||
const cmdA = createMockCommand('a', CommandKind.BUILT_IN);
|
||||
const failingLoader = new MockCommandLoader([]);
|
||||
vi.spyOn(failingLoader, 'loadCommands').mockRejectedValue(
|
||||
new Error('fail'),
|
||||
);
|
||||
|
||||
it('should aggregate commands from multiple loaders', async () => {
|
||||
const loader1 = new MockCommandLoader([mockCommandA]);
|
||||
const loader2 = new MockCommandLoader([mockCommandC]);
|
||||
const service = await CommandService.create(
|
||||
[loader1, loader2],
|
||||
new AbortController().signal,
|
||||
);
|
||||
const service = await CommandService.create(
|
||||
[
|
||||
new MockCommandLoader([cmdA]),
|
||||
new MockCommandLoader([]),
|
||||
failingLoader,
|
||||
],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
expect(service.getCommands()).toHaveLength(1);
|
||||
expect(service.getCommands()[0].name).toBe('a');
|
||||
expect(debugLogger.debug).toHaveBeenCalledWith(
|
||||
'A command loader failed:',
|
||||
expect.any(Error),
|
||||
);
|
||||
});
|
||||
|
||||
expect(loader1.loadCommands).toHaveBeenCalledTimes(1);
|
||||
expect(loader2.loadCommands).toHaveBeenCalledTimes(1);
|
||||
expect(commands).toHaveLength(2);
|
||||
expect(commands).toEqual(
|
||||
expect.arrayContaining([mockCommandA, mockCommandC]),
|
||||
);
|
||||
});
|
||||
it('should return a readonly array of commands', async () => {
|
||||
const service = await CommandService.create(
|
||||
[new MockCommandLoader([createMockCommand('a', CommandKind.BUILT_IN)])],
|
||||
new AbortController().signal,
|
||||
);
|
||||
expect(() => (service.getCommands() as unknown[]).push({})).toThrow();
|
||||
});
|
||||
|
||||
it('should override commands from earlier loaders with those from later loaders', async () => {
|
||||
const loader1 = new MockCommandLoader([mockCommandA, mockCommandB]);
|
||||
const loader2 = new MockCommandLoader([
|
||||
mockCommandB_Override,
|
||||
mockCommandC,
|
||||
]);
|
||||
const service = await CommandService.create(
|
||||
[loader1, loader2],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
|
||||
expect(commands).toHaveLength(3); // Should be A, C, and the overridden B.
|
||||
|
||||
// The final list should contain the override from the *last* loader.
|
||||
const commandB = commands.find((cmd) => cmd.name === 'command-b');
|
||||
expect(commandB).toBeDefined();
|
||||
expect(commandB?.kind).toBe(CommandKind.FILE); // Verify it's the overridden version.
|
||||
expect(commandB).toEqual(mockCommandB_Override);
|
||||
|
||||
// Ensure the other commands are still present.
|
||||
expect(commands).toEqual(
|
||||
expect.arrayContaining([
|
||||
mockCommandA,
|
||||
mockCommandC,
|
||||
mockCommandB_Override,
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle loaders that return an empty array of commands gracefully', async () => {
|
||||
const loader1 = new MockCommandLoader([mockCommandA]);
|
||||
const emptyLoader = new MockCommandLoader([]);
|
||||
const loader3 = new MockCommandLoader([mockCommandB]);
|
||||
const service = await CommandService.create(
|
||||
[loader1, emptyLoader, loader3],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
|
||||
expect(emptyLoader.loadCommands).toHaveBeenCalledTimes(1);
|
||||
expect(commands).toHaveLength(2);
|
||||
expect(commands).toEqual(
|
||||
expect.arrayContaining([mockCommandA, mockCommandB]),
|
||||
);
|
||||
});
|
||||
|
||||
it('should load commands from successful loaders even if one fails', async () => {
|
||||
const successfulLoader = new MockCommandLoader([mockCommandA]);
|
||||
const failingLoader = new MockCommandLoader([]);
|
||||
const error = new Error('Loader failed');
|
||||
vi.spyOn(failingLoader, 'loadCommands').mockRejectedValue(error);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[successfulLoader, failingLoader],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
expect(commands).toHaveLength(1);
|
||||
expect(commands).toEqual([mockCommandA]);
|
||||
expect(debugLogger.debug).toHaveBeenCalledWith(
|
||||
'A command loader failed:',
|
||||
error,
|
||||
);
|
||||
});
|
||||
|
||||
it('getCommands should return a readonly array that cannot be mutated', async () => {
|
||||
const service = await CommandService.create(
|
||||
[new MockCommandLoader([mockCommandA])],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
|
||||
// Expect it to throw a TypeError at runtime because the array is frozen.
|
||||
expect(() => {
|
||||
// @ts-expect-error - Testing immutability is intentional here.
|
||||
commands.push(mockCommandB);
|
||||
}).toThrow();
|
||||
|
||||
// Verify the original array was not mutated.
|
||||
expect(service.getCommands()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should pass the abort signal to all loaders', async () => {
|
||||
const controller = new AbortController();
|
||||
const signal = controller.signal;
|
||||
|
||||
const loader1 = new MockCommandLoader([mockCommandA]);
|
||||
const loader2 = new MockCommandLoader([mockCommandB]);
|
||||
|
||||
await CommandService.create([loader1, loader2], signal);
|
||||
|
||||
expect(loader1.loadCommands).toHaveBeenCalledTimes(1);
|
||||
expect(loader1.loadCommands).toHaveBeenCalledWith(signal);
|
||||
expect(loader2.loadCommands).toHaveBeenCalledTimes(1);
|
||||
expect(loader2.loadCommands).toHaveBeenCalledWith(signal);
|
||||
});
|
||||
|
||||
it('should rename extension commands when they conflict', async () => {
|
||||
const builtinCommand = createMockCommand('deploy', CommandKind.BUILT_IN);
|
||||
const userCommand = createMockCommand('sync', CommandKind.FILE);
|
||||
const extensionCommand1 = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'firebase',
|
||||
description: '[firebase] Deploy to Firebase',
|
||||
};
|
||||
const extensionCommand2 = {
|
||||
...createMockCommand('sync', CommandKind.FILE),
|
||||
extensionName: 'git-helper',
|
||||
description: '[git-helper] Sync with remote',
|
||||
};
|
||||
|
||||
const mockLoader1 = new MockCommandLoader([builtinCommand]);
|
||||
const mockLoader2 = new MockCommandLoader([
|
||||
userCommand,
|
||||
extensionCommand1,
|
||||
extensionCommand2,
|
||||
]);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[mockLoader1, mockLoader2],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
expect(commands).toHaveLength(4);
|
||||
|
||||
// Built-in command keeps original name
|
||||
const deployBuiltin = commands.find(
|
||||
(cmd) => cmd.name === 'deploy' && !cmd.extensionName,
|
||||
);
|
||||
expect(deployBuiltin).toBeDefined();
|
||||
expect(deployBuiltin?.kind).toBe(CommandKind.BUILT_IN);
|
||||
|
||||
// Extension command conflicting with built-in gets renamed
|
||||
const deployExtension = commands.find(
|
||||
(cmd) => cmd.name === 'firebase.deploy',
|
||||
);
|
||||
expect(deployExtension).toBeDefined();
|
||||
expect(deployExtension?.extensionName).toBe('firebase');
|
||||
|
||||
// User command keeps original name
|
||||
const syncUser = commands.find(
|
||||
(cmd) => cmd.name === 'sync' && !cmd.extensionName,
|
||||
);
|
||||
expect(syncUser).toBeDefined();
|
||||
expect(syncUser?.kind).toBe(CommandKind.FILE);
|
||||
|
||||
// Extension command conflicting with user command gets renamed
|
||||
const syncExtension = commands.find(
|
||||
(cmd) => cmd.name === 'git-helper.sync',
|
||||
);
|
||||
expect(syncExtension).toBeDefined();
|
||||
expect(syncExtension?.extensionName).toBe('git-helper');
|
||||
});
|
||||
|
||||
it('should handle user/project command override correctly', async () => {
|
||||
const builtinCommand = createMockCommand('help', CommandKind.BUILT_IN);
|
||||
const userCommand = createMockCommand('help', CommandKind.FILE);
|
||||
const projectCommand = createMockCommand('deploy', CommandKind.FILE);
|
||||
const userDeployCommand = createMockCommand('deploy', CommandKind.FILE);
|
||||
|
||||
const mockLoader1 = new MockCommandLoader([builtinCommand]);
|
||||
const mockLoader2 = new MockCommandLoader([
|
||||
userCommand,
|
||||
userDeployCommand,
|
||||
projectCommand,
|
||||
]);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[mockLoader1, mockLoader2],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
expect(commands).toHaveLength(2);
|
||||
|
||||
// User command overrides built-in
|
||||
const helpCommand = commands.find((cmd) => cmd.name === 'help');
|
||||
expect(helpCommand).toBeDefined();
|
||||
expect(helpCommand?.kind).toBe(CommandKind.FILE);
|
||||
|
||||
// Project command overrides user command (last wins)
|
||||
const deployCommand = commands.find((cmd) => cmd.name === 'deploy');
|
||||
expect(deployCommand).toBeDefined();
|
||||
expect(deployCommand?.kind).toBe(CommandKind.FILE);
|
||||
});
|
||||
|
||||
it('should handle secondary conflicts when renaming extension commands', async () => {
|
||||
// User has both /deploy and /gcp.deploy commands
|
||||
const userCommand1 = createMockCommand('deploy', CommandKind.FILE);
|
||||
const userCommand2 = createMockCommand('gcp.deploy', CommandKind.FILE);
|
||||
|
||||
// Extension also has a deploy command that will conflict with user's /deploy
|
||||
const extensionCommand = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'gcp',
|
||||
description: '[gcp] Deploy to Google Cloud',
|
||||
};
|
||||
|
||||
const mockLoader = new MockCommandLoader([
|
||||
userCommand1,
|
||||
userCommand2,
|
||||
extensionCommand,
|
||||
]);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[mockLoader],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
expect(commands).toHaveLength(3);
|
||||
|
||||
// Original user command keeps its name
|
||||
const deployUser = commands.find(
|
||||
(cmd) => cmd.name === 'deploy' && !cmd.extensionName,
|
||||
);
|
||||
expect(deployUser).toBeDefined();
|
||||
|
||||
// User's dot notation command keeps its name
|
||||
const gcpDeployUser = commands.find(
|
||||
(cmd) => cmd.name === 'gcp.deploy' && !cmd.extensionName,
|
||||
);
|
||||
expect(gcpDeployUser).toBeDefined();
|
||||
|
||||
// Extension command gets renamed with suffix due to secondary conflict
|
||||
const deployExtension = commands.find(
|
||||
(cmd) => cmd.name === 'gcp.deploy1' && cmd.extensionName === 'gcp',
|
||||
);
|
||||
expect(deployExtension).toBeDefined();
|
||||
expect(deployExtension?.description).toBe('[gcp] Deploy to Google Cloud');
|
||||
});
|
||||
|
||||
it('should handle multiple secondary conflicts with incrementing suffixes', async () => {
|
||||
// User has /deploy, /gcp.deploy, and /gcp.deploy1
|
||||
const userCommand1 = createMockCommand('deploy', CommandKind.FILE);
|
||||
const userCommand2 = createMockCommand('gcp.deploy', CommandKind.FILE);
|
||||
const userCommand3 = createMockCommand('gcp.deploy1', CommandKind.FILE);
|
||||
|
||||
// Extension has a deploy command
|
||||
const extensionCommand = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'gcp',
|
||||
description: '[gcp] Deploy to Google Cloud',
|
||||
};
|
||||
|
||||
const mockLoader = new MockCommandLoader([
|
||||
userCommand1,
|
||||
userCommand2,
|
||||
userCommand3,
|
||||
extensionCommand,
|
||||
]);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[mockLoader],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const commands = service.getCommands();
|
||||
expect(commands).toHaveLength(4);
|
||||
|
||||
// Extension command gets renamed with suffix 2 due to multiple conflicts
|
||||
const deployExtension = commands.find(
|
||||
(cmd) => cmd.name === 'gcp.deploy2' && cmd.extensionName === 'gcp',
|
||||
);
|
||||
expect(deployExtension).toBeDefined();
|
||||
expect(deployExtension?.description).toBe('[gcp] Deploy to Google Cloud');
|
||||
});
|
||||
|
||||
it('should report conflicts via getConflicts', async () => {
|
||||
const builtinCommand = createMockCommand('deploy', CommandKind.BUILT_IN);
|
||||
const extensionCommand = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'firebase',
|
||||
};
|
||||
|
||||
const mockLoader = new MockCommandLoader([
|
||||
builtinCommand,
|
||||
extensionCommand,
|
||||
]);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[mockLoader],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const conflicts = service.getConflicts();
|
||||
expect(conflicts).toHaveLength(1);
|
||||
|
||||
expect(conflicts[0]).toMatchObject({
|
||||
name: 'deploy',
|
||||
winner: builtinCommand,
|
||||
losers: [
|
||||
{
|
||||
renamedTo: 'firebase.deploy',
|
||||
command: expect.objectContaining({
|
||||
name: 'deploy',
|
||||
extensionName: 'firebase',
|
||||
}),
|
||||
},
|
||||
],
|
||||
it('should pass the abort signal to all loaders', async () => {
|
||||
const controller = new AbortController();
|
||||
const loader = new MockCommandLoader([]);
|
||||
await CommandService.create([loader], controller.signal);
|
||||
expect(loader.loadCommands).toHaveBeenCalledWith(controller.signal);
|
||||
});
|
||||
});
|
||||
|
||||
it('should report extension vs extension conflicts correctly', async () => {
|
||||
// Both extensions try to register 'deploy'
|
||||
const extension1Command = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'firebase',
|
||||
};
|
||||
const extension2Command = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'aws',
|
||||
};
|
||||
describe('conflict delegation', () => {
|
||||
it('should delegate conflict resolution to SlashCommandResolver', async () => {
|
||||
const builtin = createMockCommand('help', CommandKind.BUILT_IN);
|
||||
const user = createMockCommand('help', CommandKind.USER_FILE);
|
||||
|
||||
const mockLoader = new MockCommandLoader([
|
||||
extension1Command,
|
||||
extension2Command,
|
||||
]);
|
||||
const service = await CommandService.create(
|
||||
[new MockCommandLoader([builtin, user])],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[mockLoader],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const conflicts = service.getConflicts();
|
||||
expect(conflicts).toHaveLength(1);
|
||||
|
||||
expect(conflicts[0]).toMatchObject({
|
||||
name: 'deploy',
|
||||
winner: expect.objectContaining({
|
||||
name: 'deploy',
|
||||
extensionName: 'firebase',
|
||||
}),
|
||||
losers: [
|
||||
{
|
||||
renamedTo: 'aws.deploy', // ext2 is 'aws' and it lost because it was second in the list
|
||||
command: expect.objectContaining({
|
||||
name: 'deploy',
|
||||
extensionName: 'aws',
|
||||
}),
|
||||
},
|
||||
],
|
||||
expect(service.getCommands().map((c) => c.name)).toContain('help');
|
||||
expect(service.getCommands().map((c) => c.name)).toContain('user.help');
|
||||
expect(service.getConflicts()).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should report multiple conflicts for the same command name', async () => {
|
||||
const builtinCommand = createMockCommand('deploy', CommandKind.BUILT_IN);
|
||||
const ext1 = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'ext1',
|
||||
};
|
||||
const ext2 = {
|
||||
...createMockCommand('deploy', CommandKind.FILE),
|
||||
extensionName: 'ext2',
|
||||
};
|
||||
|
||||
const mockLoader = new MockCommandLoader([builtinCommand, ext1, ext2]);
|
||||
|
||||
const service = await CommandService.create(
|
||||
[mockLoader],
|
||||
new AbortController().signal,
|
||||
);
|
||||
|
||||
const conflicts = service.getConflicts();
|
||||
expect(conflicts).toHaveLength(1);
|
||||
expect(conflicts[0].name).toBe('deploy');
|
||||
expect(conflicts[0].losers).toHaveLength(2);
|
||||
expect(conflicts[0].losers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
renamedTo: 'ext1.deploy',
|
||||
command: expect.objectContaining({ extensionName: 'ext1' }),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
renamedTo: 'ext2.deploy',
|
||||
command: expect.objectContaining({ extensionName: 'ext2' }),
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,16 +6,8 @@
|
||||
|
||||
import { debugLogger, coreEvents } from '@google/gemini-cli-core';
|
||||
import type { SlashCommand } from '../ui/commands/types.js';
|
||||
import type { ICommandLoader } from './types.js';
|
||||
|
||||
export interface CommandConflict {
|
||||
name: string;
|
||||
winner: SlashCommand;
|
||||
losers: Array<{
|
||||
command: SlashCommand;
|
||||
renamedTo: string;
|
||||
}>;
|
||||
}
|
||||
import type { ICommandLoader, CommandConflict } from './types.js';
|
||||
import { SlashCommandResolver } from './SlashCommandResolver.js';
|
||||
|
||||
/**
|
||||
* Orchestrates the discovery and loading of all slash commands for the CLI.
|
||||
@@ -24,9 +16,9 @@ export interface CommandConflict {
|
||||
* with an array of `ICommandLoader` instances, each responsible for fetching
|
||||
* commands from a specific source (e.g., built-in code, local files).
|
||||
*
|
||||
* The CommandService is responsible for invoking these loaders, aggregating their
|
||||
* results, and resolving any name conflicts. This architecture allows the command
|
||||
* system to be extended with new sources without modifying the service itself.
|
||||
* It uses a delegating resolver to reconcile name conflicts, ensuring that
|
||||
* all commands are uniquely addressable via source-specific prefixes while
|
||||
* allowing built-in commands to retain their primary names.
|
||||
*/
|
||||
export class CommandService {
|
||||
/**
|
||||
@@ -42,96 +34,71 @@ export class CommandService {
|
||||
/**
|
||||
* Asynchronously creates and initializes a new CommandService instance.
|
||||
*
|
||||
* This factory method orchestrates the entire command loading process. It
|
||||
* runs all provided loaders in parallel, aggregates their results, handles
|
||||
* name conflicts for extension commands by renaming them, and then returns a
|
||||
* fully constructed `CommandService` instance.
|
||||
* This factory method orchestrates the loading process and delegates
|
||||
* conflict resolution to the SlashCommandResolver.
|
||||
*
|
||||
* Conflict resolution:
|
||||
* - Extension commands that conflict with existing commands are renamed to
|
||||
* `extensionName.commandName`
|
||||
* - Non-extension commands (built-in, user, project) override earlier commands
|
||||
* with the same name based on loader order
|
||||
*
|
||||
* @param loaders An array of objects that conform to the `ICommandLoader`
|
||||
* interface. Built-in commands should come first, followed by FileCommandLoader.
|
||||
* @param signal An AbortSignal to cancel the loading process.
|
||||
* @returns A promise that resolves to a new, fully initialized `CommandService` instance.
|
||||
* @param loaders An array of loaders to fetch commands from.
|
||||
* @param signal An AbortSignal to allow cancellation.
|
||||
* @returns A promise that resolves to a fully initialized CommandService.
|
||||
*/
|
||||
static async create(
|
||||
loaders: ICommandLoader[],
|
||||
signal: AbortSignal,
|
||||
): Promise<CommandService> {
|
||||
const allCommands = await this.loadAllCommands(loaders, signal);
|
||||
const { finalCommands, conflicts } =
|
||||
SlashCommandResolver.resolve(allCommands);
|
||||
|
||||
if (conflicts.length > 0) {
|
||||
this.emitConflictEvents(conflicts);
|
||||
}
|
||||
|
||||
return new CommandService(
|
||||
Object.freeze(finalCommands),
|
||||
Object.freeze(conflicts),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes all loaders in parallel and flattens the results.
|
||||
*/
|
||||
private static async loadAllCommands(
|
||||
loaders: ICommandLoader[],
|
||||
signal: AbortSignal,
|
||||
): Promise<SlashCommand[]> {
|
||||
const results = await Promise.allSettled(
|
||||
loaders.map((loader) => loader.loadCommands(signal)),
|
||||
);
|
||||
|
||||
const allCommands: SlashCommand[] = [];
|
||||
const commands: SlashCommand[] = [];
|
||||
for (const result of results) {
|
||||
if (result.status === 'fulfilled') {
|
||||
allCommands.push(...result.value);
|
||||
commands.push(...result.value);
|
||||
} else {
|
||||
debugLogger.debug('A command loader failed:', result.reason);
|
||||
}
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
||||
const commandMap = new Map<string, SlashCommand>();
|
||||
const conflictsMap = new Map<string, CommandConflict>();
|
||||
|
||||
for (const cmd of allCommands) {
|
||||
let finalName = cmd.name;
|
||||
|
||||
// Extension commands get renamed if they conflict with existing commands
|
||||
if (cmd.extensionName && commandMap.has(cmd.name)) {
|
||||
const winner = commandMap.get(cmd.name)!;
|
||||
let renamedName = `${cmd.extensionName}.${cmd.name}`;
|
||||
let suffix = 1;
|
||||
|
||||
// Keep trying until we find a name that doesn't conflict
|
||||
while (commandMap.has(renamedName)) {
|
||||
renamedName = `${cmd.extensionName}.${cmd.name}${suffix}`;
|
||||
suffix++;
|
||||
}
|
||||
|
||||
finalName = renamedName;
|
||||
|
||||
if (!conflictsMap.has(cmd.name)) {
|
||||
conflictsMap.set(cmd.name, {
|
||||
name: cmd.name,
|
||||
winner,
|
||||
losers: [],
|
||||
});
|
||||
}
|
||||
|
||||
conflictsMap.get(cmd.name)!.losers.push({
|
||||
command: cmd,
|
||||
renamedTo: finalName,
|
||||
});
|
||||
}
|
||||
|
||||
commandMap.set(finalName, {
|
||||
...cmd,
|
||||
name: finalName,
|
||||
});
|
||||
}
|
||||
|
||||
const conflicts = Array.from(conflictsMap.values());
|
||||
if (conflicts.length > 0) {
|
||||
coreEvents.emitSlashCommandConflicts(
|
||||
conflicts.flatMap((c) =>
|
||||
c.losers.map((l) => ({
|
||||
name: c.name,
|
||||
renamedTo: l.renamedTo,
|
||||
loserExtensionName: l.command.extensionName,
|
||||
winnerExtensionName: c.winner.extensionName,
|
||||
})),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const finalCommands = Object.freeze(Array.from(commandMap.values()));
|
||||
const finalConflicts = Object.freeze(conflicts);
|
||||
return new CommandService(finalCommands, finalConflicts);
|
||||
/**
|
||||
* Formats and emits telemetry for command conflicts.
|
||||
*/
|
||||
private static emitConflictEvents(conflicts: CommandConflict[]): void {
|
||||
coreEvents.emitSlashCommandConflicts(
|
||||
conflicts.flatMap((c) =>
|
||||
c.losers.map((l) => ({
|
||||
name: c.name,
|
||||
renamedTo: l.renamedTo,
|
||||
loserExtensionName: l.command.extensionName,
|
||||
winnerExtensionName: l.reason.extensionName,
|
||||
loserMcpServerName: l.command.mcpServerName,
|
||||
winnerMcpServerName: l.reason.mcpServerName,
|
||||
loserKind: l.command.kind,
|
||||
winnerKind: l.reason.kind,
|
||||
})),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,6 +37,7 @@ import { sanitizeForDisplay } from '../ui/utils/textUtils.js';
|
||||
|
||||
interface CommandDirectory {
|
||||
path: string;
|
||||
kind: CommandKind;
|
||||
extensionName?: string;
|
||||
extensionId?: string;
|
||||
}
|
||||
@@ -111,6 +112,7 @@ export class FileCommandLoader implements ICommandLoader {
|
||||
this.parseAndAdaptFile(
|
||||
path.join(dirInfo.path, file),
|
||||
dirInfo.path,
|
||||
dirInfo.kind,
|
||||
dirInfo.extensionName,
|
||||
dirInfo.extensionId,
|
||||
),
|
||||
@@ -151,10 +153,16 @@ export class FileCommandLoader implements ICommandLoader {
|
||||
const storage = this.config?.storage ?? new Storage(this.projectRoot);
|
||||
|
||||
// 1. User commands
|
||||
dirs.push({ path: Storage.getUserCommandsDir() });
|
||||
dirs.push({
|
||||
path: Storage.getUserCommandsDir(),
|
||||
kind: CommandKind.USER_FILE,
|
||||
});
|
||||
|
||||
// 2. Project commands (override user commands)
|
||||
dirs.push({ path: storage.getProjectCommandsDir() });
|
||||
// 2. Project commands
|
||||
dirs.push({
|
||||
path: storage.getProjectCommandsDir(),
|
||||
kind: CommandKind.WORKSPACE_FILE,
|
||||
});
|
||||
|
||||
// 3. Extension commands (processed last to detect all conflicts)
|
||||
if (this.config) {
|
||||
@@ -165,6 +173,7 @@ export class FileCommandLoader implements ICommandLoader {
|
||||
|
||||
const extensionCommandDirs = activeExtensions.map((ext) => ({
|
||||
path: path.join(ext.path, 'commands'),
|
||||
kind: CommandKind.EXTENSION_FILE,
|
||||
extensionName: ext.name,
|
||||
extensionId: ext.id,
|
||||
}));
|
||||
@@ -179,12 +188,14 @@ export class FileCommandLoader implements ICommandLoader {
|
||||
* Parses a single .toml file and transforms it into a SlashCommand object.
|
||||
* @param filePath The absolute path to the .toml file.
|
||||
* @param baseDir The root command directory for name calculation.
|
||||
* @param kind The CommandKind.
|
||||
* @param extensionName Optional extension name to prefix commands with.
|
||||
* @returns A promise resolving to a SlashCommand, or null if the file is invalid.
|
||||
*/
|
||||
private async parseAndAdaptFile(
|
||||
filePath: string,
|
||||
baseDir: string,
|
||||
kind: CommandKind,
|
||||
extensionName?: string,
|
||||
extensionId?: string,
|
||||
): Promise<SlashCommand | null> {
|
||||
@@ -286,7 +297,7 @@ export class FileCommandLoader implements ICommandLoader {
|
||||
return {
|
||||
name: baseCommandName,
|
||||
description,
|
||||
kind: CommandKind.FILE,
|
||||
kind,
|
||||
extensionName,
|
||||
extensionId,
|
||||
action: async (
|
||||
|
||||
@@ -44,6 +44,7 @@ export class McpPromptLoader implements ICommandLoader {
|
||||
name: commandName,
|
||||
description: prompt.description || `Invoke prompt ${prompt.name}`,
|
||||
kind: CommandKind.MCP_PROMPT,
|
||||
mcpServerName: serverName,
|
||||
autoExecute: !prompt.arguments || prompt.arguments.length === 0,
|
||||
subCommands: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { SlashCommandConflictHandler } from './SlashCommandConflictHandler.js';
|
||||
import {
|
||||
coreEvents,
|
||||
CoreEvent,
|
||||
type SlashCommandConflictsPayload,
|
||||
type SlashCommandConflict,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { CommandKind } from '../ui/commands/types.js';
|
||||
|
||||
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import('@google/gemini-cli-core')>();
|
||||
return {
|
||||
...actual,
|
||||
coreEvents: {
|
||||
on: vi.fn(),
|
||||
off: vi.fn(),
|
||||
emitFeedback: vi.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('SlashCommandConflictHandler', () => {
|
||||
let handler: SlashCommandConflictHandler;
|
||||
|
||||
/**
|
||||
* Helper to find and invoke the registered conflict event listener.
|
||||
*/
|
||||
const simulateEvent = (conflicts: SlashCommandConflict[]) => {
|
||||
const callback = vi
|
||||
.mocked(coreEvents.on)
|
||||
.mock.calls.find(
|
||||
(call) => call[0] === CoreEvent.SlashCommandConflicts,
|
||||
)![1] as (payload: SlashCommandConflictsPayload) => void;
|
||||
callback({ conflicts });
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
handler = new SlashCommandConflictHandler();
|
||||
handler.start();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
handler.stop();
|
||||
vi.clearAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should listen for conflict events on start', () => {
|
||||
expect(coreEvents.on).toHaveBeenCalledWith(
|
||||
CoreEvent.SlashCommandConflicts,
|
||||
expect.any(Function),
|
||||
);
|
||||
});
|
||||
|
||||
it('should display a descriptive message for a single extension conflict', () => {
|
||||
simulateEvent([
|
||||
{
|
||||
name: 'deploy',
|
||||
renamedTo: 'firebase.deploy',
|
||||
loserExtensionName: 'firebase',
|
||||
loserKind: CommandKind.EXTENSION_FILE,
|
||||
winnerKind: CommandKind.BUILT_IN,
|
||||
},
|
||||
]);
|
||||
|
||||
vi.advanceTimersByTime(600);
|
||||
|
||||
expect(coreEvents.emitFeedback).toHaveBeenCalledWith(
|
||||
'info',
|
||||
"Extension 'firebase' command '/deploy' was renamed to '/firebase.deploy' because it conflicts with built-in command.",
|
||||
);
|
||||
});
|
||||
|
||||
it('should display a descriptive message for a single MCP conflict', () => {
|
||||
simulateEvent([
|
||||
{
|
||||
name: 'pickle',
|
||||
renamedTo: 'test-server.pickle',
|
||||
loserMcpServerName: 'test-server',
|
||||
loserKind: CommandKind.MCP_PROMPT,
|
||||
winnerExtensionName: 'pickle-rick',
|
||||
winnerKind: CommandKind.EXTENSION_FILE,
|
||||
},
|
||||
]);
|
||||
|
||||
vi.advanceTimersByTime(600);
|
||||
|
||||
expect(coreEvents.emitFeedback).toHaveBeenCalledWith(
|
||||
'info',
|
||||
"MCP server 'test-server' command '/pickle' was renamed to '/test-server.pickle' because it conflicts with extension 'pickle-rick' command.",
|
||||
);
|
||||
});
|
||||
|
||||
it('should group multiple conflicts for the same command name', () => {
|
||||
simulateEvent([
|
||||
{
|
||||
name: 'launch',
|
||||
renamedTo: 'user.launch',
|
||||
loserKind: CommandKind.USER_FILE,
|
||||
winnerKind: CommandKind.WORKSPACE_FILE,
|
||||
},
|
||||
{
|
||||
name: 'launch',
|
||||
renamedTo: 'workspace.launch',
|
||||
loserKind: CommandKind.WORKSPACE_FILE,
|
||||
winnerKind: CommandKind.USER_FILE,
|
||||
},
|
||||
]);
|
||||
|
||||
vi.advanceTimersByTime(600);
|
||||
|
||||
expect(coreEvents.emitFeedback).toHaveBeenCalledWith(
|
||||
'info',
|
||||
`Conflicts detected for command '/launch':
|
||||
- User command '/launch' was renamed to '/user.launch'
|
||||
- Workspace command '/launch' was renamed to '/workspace.launch'`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should debounce multiple events within the flush window', () => {
|
||||
simulateEvent([
|
||||
{
|
||||
name: 'a',
|
||||
renamedTo: 'user.a',
|
||||
loserKind: CommandKind.USER_FILE,
|
||||
winnerKind: CommandKind.BUILT_IN,
|
||||
},
|
||||
]);
|
||||
|
||||
vi.advanceTimersByTime(200);
|
||||
|
||||
simulateEvent([
|
||||
{
|
||||
name: 'b',
|
||||
renamedTo: 'user.b',
|
||||
loserKind: CommandKind.USER_FILE,
|
||||
winnerKind: CommandKind.BUILT_IN,
|
||||
},
|
||||
]);
|
||||
|
||||
vi.advanceTimersByTime(600);
|
||||
|
||||
// Should emit two feedbacks (one for each unique command name)
|
||||
expect(coreEvents.emitFeedback).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should deduplicate already notified conflicts', () => {
|
||||
const conflict = {
|
||||
name: 'deploy',
|
||||
renamedTo: 'firebase.deploy',
|
||||
loserExtensionName: 'firebase',
|
||||
loserKind: CommandKind.EXTENSION_FILE,
|
||||
winnerKind: CommandKind.BUILT_IN,
|
||||
};
|
||||
|
||||
simulateEvent([conflict]);
|
||||
vi.advanceTimersByTime(600);
|
||||
expect(coreEvents.emitFeedback).toHaveBeenCalledTimes(1);
|
||||
|
||||
vi.mocked(coreEvents.emitFeedback).mockClear();
|
||||
|
||||
simulateEvent([conflict]);
|
||||
vi.advanceTimersByTime(600);
|
||||
expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -8,10 +8,20 @@ import {
|
||||
coreEvents,
|
||||
CoreEvent,
|
||||
type SlashCommandConflictsPayload,
|
||||
type SlashCommandConflict,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { CommandKind } from '../ui/commands/types.js';
|
||||
|
||||
/**
|
||||
* Handles slash command conflict events and provides user feedback.
|
||||
*
|
||||
* This handler batches multiple conflict events into a single notification
|
||||
* block per command name to avoid UI clutter during startup or incremental loading.
|
||||
*/
|
||||
export class SlashCommandConflictHandler {
|
||||
private notifiedConflicts = new Set<string>();
|
||||
private pendingConflicts: SlashCommandConflict[] = [];
|
||||
private flushTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
constructor() {
|
||||
this.handleConflicts = this.handleConflicts.bind(this);
|
||||
@@ -23,11 +33,18 @@ export class SlashCommandConflictHandler {
|
||||
|
||||
stop() {
|
||||
coreEvents.off(CoreEvent.SlashCommandConflicts, this.handleConflicts);
|
||||
if (this.flushTimeout) {
|
||||
clearTimeout(this.flushTimeout);
|
||||
this.flushTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
private handleConflicts(payload: SlashCommandConflictsPayload) {
|
||||
const newConflicts = payload.conflicts.filter((c) => {
|
||||
const key = `${c.name}:${c.loserExtensionName}`;
|
||||
// Use a unique key to prevent duplicate notifications for the same conflict
|
||||
const sourceId =
|
||||
c.loserExtensionName || c.loserMcpServerName || c.loserKind;
|
||||
const key = `${c.name}:${sourceId}:${c.renamedTo}`;
|
||||
if (this.notifiedConflicts.has(key)) {
|
||||
return false;
|
||||
}
|
||||
@@ -36,19 +53,119 @@ export class SlashCommandConflictHandler {
|
||||
});
|
||||
|
||||
if (newConflicts.length > 0) {
|
||||
const conflictMessages = newConflicts
|
||||
.map((c) => {
|
||||
const winnerSource = c.winnerExtensionName
|
||||
? `extension '${c.winnerExtensionName}'`
|
||||
: 'an existing command';
|
||||
return `- Command '/${c.name}' from extension '${c.loserExtensionName}' was renamed to '/${c.renamedTo}' because it conflicts with ${winnerSource}.`;
|
||||
})
|
||||
.join('\n');
|
||||
this.pendingConflicts.push(...newConflicts);
|
||||
this.scheduleFlush();
|
||||
}
|
||||
}
|
||||
|
||||
coreEvents.emitFeedback(
|
||||
'info',
|
||||
`Command conflicts detected:\n${conflictMessages}`,
|
||||
);
|
||||
private scheduleFlush() {
|
||||
if (this.flushTimeout) {
|
||||
clearTimeout(this.flushTimeout);
|
||||
}
|
||||
// Use a trailing debounce to capture staggered reloads during startup
|
||||
this.flushTimeout = setTimeout(() => this.flush(), 500);
|
||||
}
|
||||
|
||||
private flush() {
|
||||
this.flushTimeout = null;
|
||||
const conflicts = [...this.pendingConflicts];
|
||||
this.pendingConflicts = [];
|
||||
|
||||
if (conflicts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Group conflicts by their original command name
|
||||
const grouped = new Map<string, SlashCommandConflict[]>();
|
||||
for (const c of conflicts) {
|
||||
const list = grouped.get(c.name) ?? [];
|
||||
list.push(c);
|
||||
grouped.set(c.name, list);
|
||||
}
|
||||
|
||||
for (const [name, commandConflicts] of grouped) {
|
||||
if (commandConflicts.length > 1) {
|
||||
this.emitGroupedFeedback(name, commandConflicts);
|
||||
} else {
|
||||
this.emitSingleFeedback(commandConflicts[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a grouped notification for multiple conflicts sharing the same name.
|
||||
*/
|
||||
private emitGroupedFeedback(
|
||||
name: string,
|
||||
conflicts: SlashCommandConflict[],
|
||||
): void {
|
||||
const messages = conflicts
|
||||
.map((c) => {
|
||||
const source = this.getSourceDescription(
|
||||
c.loserExtensionName,
|
||||
c.loserKind,
|
||||
c.loserMcpServerName,
|
||||
);
|
||||
return `- ${this.capitalize(source)} '/${c.name}' was renamed to '/${c.renamedTo}'`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
coreEvents.emitFeedback(
|
||||
'info',
|
||||
`Conflicts detected for command '/${name}':\n${messages}`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a descriptive notification for a single command conflict.
|
||||
*/
|
||||
private emitSingleFeedback(c: SlashCommandConflict): void {
|
||||
const loserSource = this.getSourceDescription(
|
||||
c.loserExtensionName,
|
||||
c.loserKind,
|
||||
c.loserMcpServerName,
|
||||
);
|
||||
const winnerSource = this.getSourceDescription(
|
||||
c.winnerExtensionName,
|
||||
c.winnerKind,
|
||||
c.winnerMcpServerName,
|
||||
);
|
||||
|
||||
coreEvents.emitFeedback(
|
||||
'info',
|
||||
`${this.capitalize(loserSource)} '/${c.name}' was renamed to '/${c.renamedTo}' because it conflicts with ${winnerSource}.`,
|
||||
);
|
||||
}
|
||||
|
||||
private capitalize(s: string): string {
|
||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a human-readable description of a command's source.
|
||||
*/
|
||||
private getSourceDescription(
|
||||
extensionName?: string,
|
||||
kind?: string,
|
||||
mcpServerName?: string,
|
||||
): string {
|
||||
switch (kind) {
|
||||
case CommandKind.EXTENSION_FILE:
|
||||
return extensionName
|
||||
? `extension '${extensionName}' command`
|
||||
: 'extension command';
|
||||
case CommandKind.MCP_PROMPT:
|
||||
return mcpServerName
|
||||
? `MCP server '${mcpServerName}' command`
|
||||
: 'MCP server command';
|
||||
case CommandKind.USER_FILE:
|
||||
return 'user command';
|
||||
case CommandKind.WORKSPACE_FILE:
|
||||
return 'workspace command';
|
||||
case CommandKind.BUILT_IN:
|
||||
return 'built-in command';
|
||||
default:
|
||||
return 'existing command';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { SlashCommandResolver } from './SlashCommandResolver.js';
|
||||
import { CommandKind, type SlashCommand } from '../ui/commands/types.js';
|
||||
|
||||
const createMockCommand = (name: string, kind: CommandKind): SlashCommand => ({
|
||||
name,
|
||||
description: `Description for ${name}`,
|
||||
kind,
|
||||
action: vi.fn(),
|
||||
});
|
||||
|
||||
describe('SlashCommandResolver', () => {
|
||||
describe('resolve', () => {
|
||||
it('should return all commands when there are no conflicts', () => {
|
||||
const cmdA = createMockCommand('a', CommandKind.BUILT_IN);
|
||||
const cmdB = createMockCommand('b', CommandKind.USER_FILE);
|
||||
|
||||
const { finalCommands, conflicts } = SlashCommandResolver.resolve([
|
||||
cmdA,
|
||||
cmdB,
|
||||
]);
|
||||
|
||||
expect(finalCommands).toHaveLength(2);
|
||||
expect(conflicts).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should rename extension commands when they conflict with built-in', () => {
|
||||
const builtin = createMockCommand('deploy', CommandKind.BUILT_IN);
|
||||
const extension = {
|
||||
...createMockCommand('deploy', CommandKind.EXTENSION_FILE),
|
||||
extensionName: 'firebase',
|
||||
};
|
||||
|
||||
const { finalCommands, conflicts } = SlashCommandResolver.resolve([
|
||||
builtin,
|
||||
extension,
|
||||
]);
|
||||
|
||||
expect(finalCommands.map((c) => c.name)).toContain('deploy');
|
||||
expect(finalCommands.map((c) => c.name)).toContain('firebase.deploy');
|
||||
expect(conflicts).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should prefix both user and workspace commands when they conflict', () => {
|
||||
const userCmd = createMockCommand('sync', CommandKind.USER_FILE);
|
||||
const workspaceCmd = createMockCommand(
|
||||
'sync',
|
||||
CommandKind.WORKSPACE_FILE,
|
||||
);
|
||||
|
||||
const { finalCommands, conflicts } = SlashCommandResolver.resolve([
|
||||
userCmd,
|
||||
workspaceCmd,
|
||||
]);
|
||||
|
||||
const names = finalCommands.map((c) => c.name);
|
||||
expect(names).not.toContain('sync');
|
||||
expect(names).toContain('user.sync');
|
||||
expect(names).toContain('workspace.sync');
|
||||
expect(conflicts).toHaveLength(1);
|
||||
expect(conflicts[0].losers).toHaveLength(2); // Both are considered losers
|
||||
});
|
||||
|
||||
it('should prefix file commands but keep built-in names during conflicts', () => {
|
||||
const builtin = createMockCommand('help', CommandKind.BUILT_IN);
|
||||
const user = createMockCommand('help', CommandKind.USER_FILE);
|
||||
|
||||
const { finalCommands } = SlashCommandResolver.resolve([builtin, user]);
|
||||
|
||||
const names = finalCommands.map((c) => c.name);
|
||||
expect(names).toContain('help');
|
||||
expect(names).toContain('user.help');
|
||||
});
|
||||
|
||||
it('should prefix both commands when MCP and user file conflict', () => {
|
||||
const mcp = {
|
||||
...createMockCommand('test', CommandKind.MCP_PROMPT),
|
||||
mcpServerName: 'test-server',
|
||||
};
|
||||
const user = createMockCommand('test', CommandKind.USER_FILE);
|
||||
|
||||
const { finalCommands } = SlashCommandResolver.resolve([mcp, user]);
|
||||
|
||||
const names = finalCommands.map((c) => c.name);
|
||||
expect(names).not.toContain('test');
|
||||
expect(names).toContain('test-server.test');
|
||||
expect(names).toContain('user.test');
|
||||
});
|
||||
|
||||
it('should prefix MCP commands with server name when they conflict with built-in', () => {
|
||||
const builtin = createMockCommand('help', CommandKind.BUILT_IN);
|
||||
const mcp = {
|
||||
...createMockCommand('help', CommandKind.MCP_PROMPT),
|
||||
mcpServerName: 'test-server',
|
||||
};
|
||||
|
||||
const { finalCommands } = SlashCommandResolver.resolve([builtin, mcp]);
|
||||
|
||||
const names = finalCommands.map((c) => c.name);
|
||||
expect(names).toContain('help');
|
||||
expect(names).toContain('test-server.help');
|
||||
});
|
||||
|
||||
it('should prefix both MCP commands when they conflict with each other', () => {
|
||||
const mcp1 = {
|
||||
...createMockCommand('test', CommandKind.MCP_PROMPT),
|
||||
mcpServerName: 'server1',
|
||||
};
|
||||
const mcp2 = {
|
||||
...createMockCommand('test', CommandKind.MCP_PROMPT),
|
||||
mcpServerName: 'server2',
|
||||
};
|
||||
|
||||
const { finalCommands } = SlashCommandResolver.resolve([mcp1, mcp2]);
|
||||
|
||||
const names = finalCommands.map((c) => c.name);
|
||||
expect(names).not.toContain('test');
|
||||
expect(names).toContain('server1.test');
|
||||
expect(names).toContain('server2.test');
|
||||
});
|
||||
|
||||
it('should favor the last built-in command silently during conflicts', () => {
|
||||
const builtin1 = {
|
||||
...createMockCommand('help', CommandKind.BUILT_IN),
|
||||
description: 'first',
|
||||
};
|
||||
const builtin2 = {
|
||||
...createMockCommand('help', CommandKind.BUILT_IN),
|
||||
description: 'second',
|
||||
};
|
||||
|
||||
const { finalCommands } = SlashCommandResolver.resolve([
|
||||
builtin1,
|
||||
builtin2,
|
||||
]);
|
||||
|
||||
expect(finalCommands).toHaveLength(1);
|
||||
expect(finalCommands[0].description).toBe('second');
|
||||
});
|
||||
|
||||
it('should fallback to numeric suffixes when both prefix and kind-based prefix are missing', () => {
|
||||
const cmd1 = createMockCommand('test', CommandKind.BUILT_IN);
|
||||
const cmd2 = {
|
||||
...createMockCommand('test', 'unknown' as CommandKind),
|
||||
};
|
||||
|
||||
const { finalCommands } = SlashCommandResolver.resolve([cmd1, cmd2]);
|
||||
|
||||
const names = finalCommands.map((c) => c.name);
|
||||
expect(names).toContain('test');
|
||||
expect(names).toContain('test1');
|
||||
});
|
||||
|
||||
it('should apply numeric suffixes when renames also conflict', () => {
|
||||
const user1 = createMockCommand('deploy', CommandKind.USER_FILE);
|
||||
const user2 = createMockCommand('gcp.deploy', CommandKind.USER_FILE);
|
||||
const extension = {
|
||||
...createMockCommand('deploy', CommandKind.EXTENSION_FILE),
|
||||
extensionName: 'gcp',
|
||||
};
|
||||
|
||||
const { finalCommands } = SlashCommandResolver.resolve([
|
||||
user1,
|
||||
user2,
|
||||
extension,
|
||||
]);
|
||||
|
||||
expect(finalCommands.find((c) => c.name === 'gcp.deploy1')).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { SlashCommand } from '../ui/commands/types.js';
|
||||
import { CommandKind } from '../ui/commands/types.js';
|
||||
import type { CommandConflict } from './types.js';
|
||||
|
||||
/**
|
||||
* Internal registry to track commands and conflicts during resolution.
|
||||
*/
|
||||
class CommandRegistry {
|
||||
readonly commandMap = new Map<string, SlashCommand>();
|
||||
readonly conflictsMap = new Map<string, CommandConflict>();
|
||||
readonly firstEncounters = new Map<string, SlashCommand>();
|
||||
|
||||
get finalCommands(): SlashCommand[] {
|
||||
return Array.from(this.commandMap.values());
|
||||
}
|
||||
|
||||
get conflicts(): CommandConflict[] {
|
||||
return Array.from(this.conflictsMap.values());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves name conflicts among slash commands.
|
||||
*
|
||||
* Rules:
|
||||
* 1. Built-in commands always keep the original name.
|
||||
* 2. All other types are prefixed with their source name (e.g. user.name).
|
||||
* 3. If multiple non-built-in commands conflict, all of them are renamed.
|
||||
*/
|
||||
export class SlashCommandResolver {
|
||||
/**
|
||||
* Orchestrates conflict resolution by applying renaming rules to ensures
|
||||
* every command has a unique name.
|
||||
*/
|
||||
static resolve(allCommands: SlashCommand[]): {
|
||||
finalCommands: SlashCommand[];
|
||||
conflicts: CommandConflict[];
|
||||
} {
|
||||
const registry = new CommandRegistry();
|
||||
|
||||
for (const cmd of allCommands) {
|
||||
const originalName = cmd.name;
|
||||
let finalName = originalName;
|
||||
|
||||
if (registry.firstEncounters.has(originalName)) {
|
||||
// We've already seen a command with this name, so resolve the conflict.
|
||||
finalName = this.handleConflict(cmd, registry);
|
||||
} else {
|
||||
// Track the first claimant to report them as the conflict reason later.
|
||||
registry.firstEncounters.set(originalName, cmd);
|
||||
}
|
||||
|
||||
// Store under final name, ensuring the command object reflects it.
|
||||
registry.commandMap.set(finalName, {
|
||||
...cmd,
|
||||
name: finalName,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
finalCommands: registry.finalCommands,
|
||||
conflicts: registry.conflicts,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a name collision by deciding which command keeps the name and which is renamed.
|
||||
*
|
||||
* @param incoming The command currently being processed that has a name collision.
|
||||
* @param registry The internal state of the resolution process.
|
||||
* @returns The final name to be assigned to the `incoming` command.
|
||||
*/
|
||||
private static handleConflict(
|
||||
incoming: SlashCommand,
|
||||
registry: CommandRegistry,
|
||||
): string {
|
||||
const collidingName = incoming.name;
|
||||
const originalClaimant = registry.firstEncounters.get(collidingName)!;
|
||||
|
||||
// Incoming built-in takes priority. Prefix any existing owner.
|
||||
if (incoming.kind === CommandKind.BUILT_IN) {
|
||||
this.prefixExistingCommand(collidingName, incoming, registry);
|
||||
return collidingName;
|
||||
}
|
||||
|
||||
// Incoming non-built-in is renamed to its source-prefixed version.
|
||||
const renamedName = this.getRenamedName(
|
||||
incoming.name,
|
||||
this.getPrefix(incoming),
|
||||
registry.commandMap,
|
||||
);
|
||||
this.trackConflict(
|
||||
registry.conflictsMap,
|
||||
collidingName,
|
||||
originalClaimant,
|
||||
incoming,
|
||||
renamedName,
|
||||
);
|
||||
|
||||
// Prefix current owner as well if it isn't a built-in.
|
||||
this.prefixExistingCommand(collidingName, incoming, registry);
|
||||
|
||||
return renamedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely renames the command currently occupying a name in the registry.
|
||||
*
|
||||
* @param name The name of the command to prefix.
|
||||
* @param reason The incoming command that is causing the prefixing.
|
||||
* @param registry The internal state of the resolution process.
|
||||
*/
|
||||
private static prefixExistingCommand(
|
||||
name: string,
|
||||
reason: SlashCommand,
|
||||
registry: CommandRegistry,
|
||||
): void {
|
||||
const currentOwner = registry.commandMap.get(name);
|
||||
|
||||
// Only non-built-in commands can be prefixed.
|
||||
if (!currentOwner || currentOwner.kind === CommandKind.BUILT_IN) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the new name for the owner using its source prefix.
|
||||
const renamedName = this.getRenamedName(
|
||||
currentOwner.name,
|
||||
this.getPrefix(currentOwner),
|
||||
registry.commandMap,
|
||||
);
|
||||
|
||||
// Update the registry: remove the old name and add the owner under the new name.
|
||||
registry.commandMap.delete(name);
|
||||
const renamedOwner = { ...currentOwner, name: renamedName };
|
||||
registry.commandMap.set(renamedName, renamedOwner);
|
||||
|
||||
// Record the conflict so the user can be notified of the prefixing.
|
||||
this.trackConflict(
|
||||
registry.conflictsMap,
|
||||
name,
|
||||
reason,
|
||||
currentOwner,
|
||||
renamedName,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique name using numeric suffixes if needed.
|
||||
*/
|
||||
private static getRenamedName(
|
||||
name: string,
|
||||
prefix: string | undefined,
|
||||
commandMap: Map<string, SlashCommand>,
|
||||
): string {
|
||||
const base = prefix ? `${prefix}.${name}` : name;
|
||||
let renamedName = base;
|
||||
let suffix = 1;
|
||||
|
||||
while (commandMap.has(renamedName)) {
|
||||
renamedName = `${base}${suffix}`;
|
||||
suffix++;
|
||||
}
|
||||
return renamedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a suitable prefix for a conflicting command.
|
||||
*/
|
||||
private static getPrefix(cmd: SlashCommand): string | undefined {
|
||||
switch (cmd.kind) {
|
||||
case CommandKind.EXTENSION_FILE:
|
||||
return cmd.extensionName;
|
||||
case CommandKind.MCP_PROMPT:
|
||||
return cmd.mcpServerName;
|
||||
case CommandKind.USER_FILE:
|
||||
return 'user';
|
||||
case CommandKind.WORKSPACE_FILE:
|
||||
return 'workspace';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a conflict event.
|
||||
*/
|
||||
private static trackConflict(
|
||||
conflictsMap: Map<string, CommandConflict>,
|
||||
originalName: string,
|
||||
reason: SlashCommand,
|
||||
displacedCommand: SlashCommand,
|
||||
renamedTo: string,
|
||||
) {
|
||||
if (!conflictsMap.has(originalName)) {
|
||||
conflictsMap.set(originalName, {
|
||||
name: originalName,
|
||||
losers: [],
|
||||
});
|
||||
}
|
||||
|
||||
conflictsMap.get(originalName)!.losers.push({
|
||||
command: displacedCommand,
|
||||
renamedTo,
|
||||
reason,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -22,3 +22,12 @@ export interface ICommandLoader {
|
||||
*/
|
||||
loadCommands(signal: AbortSignal): Promise<SlashCommand[]>;
|
||||
}
|
||||
|
||||
export interface CommandConflict {
|
||||
name: string;
|
||||
losers: Array<{
|
||||
command: SlashCommand;
|
||||
renamedTo: string;
|
||||
reason: SlashCommand;
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -160,6 +160,7 @@ vi.mock('./hooks/useIdeTrustListener.js');
|
||||
vi.mock('./hooks/useMessageQueue.js');
|
||||
vi.mock('./hooks/useApprovalModeIndicator.js');
|
||||
vi.mock('./hooks/useGitBranchName.js');
|
||||
vi.mock('./hooks/useExtensionUpdates.js');
|
||||
vi.mock('./contexts/VimModeContext.js');
|
||||
vi.mock('./contexts/SessionContext.js');
|
||||
vi.mock('./components/shared/text-buffer.js');
|
||||
@@ -218,6 +219,10 @@ import { useIdeTrustListener } from './hooks/useIdeTrustListener.js';
|
||||
import { useMessageQueue } from './hooks/useMessageQueue.js';
|
||||
import { useApprovalModeIndicator } from './hooks/useApprovalModeIndicator.js';
|
||||
import { useGitBranchName } from './hooks/useGitBranchName.js';
|
||||
import {
|
||||
useConfirmUpdateRequests,
|
||||
useExtensionUpdates,
|
||||
} from './hooks/useExtensionUpdates.js';
|
||||
import { useVimMode } from './contexts/VimModeContext.js';
|
||||
import { useSessionStats } from './contexts/SessionContext.js';
|
||||
import { useTextBuffer } from './components/shared/text-buffer.js';
|
||||
@@ -299,6 +304,8 @@ describe('AppContainer State Management', () => {
|
||||
const mockedUseMessageQueue = useMessageQueue as Mock;
|
||||
const mockedUseApprovalModeIndicator = useApprovalModeIndicator as Mock;
|
||||
const mockedUseGitBranchName = useGitBranchName as Mock;
|
||||
const mockedUseConfirmUpdateRequests = useConfirmUpdateRequests as Mock;
|
||||
const mockedUseExtensionUpdates = useExtensionUpdates as Mock;
|
||||
const mockedUseVimMode = useVimMode as Mock;
|
||||
const mockedUseSessionStats = useSessionStats as Mock;
|
||||
const mockedUseTextBuffer = useTextBuffer as Mock;
|
||||
@@ -328,6 +335,7 @@ describe('AppContainer State Management', () => {
|
||||
backgroundShells: new Map(),
|
||||
registerBackgroundShell: vi.fn(),
|
||||
dismissBackgroundShell: vi.fn(),
|
||||
sisyphusSecondsRemaining: null,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -451,6 +459,15 @@ describe('AppContainer State Management', () => {
|
||||
isFocused: true,
|
||||
hasReceivedFocusEvent: true,
|
||||
});
|
||||
mockedUseConfirmUpdateRequests.mockReturnValue({
|
||||
addConfirmUpdateExtensionRequest: vi.fn(),
|
||||
confirmUpdateExtensionRequests: [],
|
||||
});
|
||||
mockedUseExtensionUpdates.mockReturnValue({
|
||||
extensionsUpdateState: new Map(),
|
||||
extensionsUpdateStateInternal: new Map(),
|
||||
dispatchExtensionStateUpdate: vi.fn(),
|
||||
});
|
||||
|
||||
// Mock Config
|
||||
mockConfig = makeFakeConfig();
|
||||
@@ -2185,7 +2202,7 @@ describe('AppContainer State Management', () => {
|
||||
const mockedMeasureElement = measureElement as Mock;
|
||||
const mockedUseTerminalSize = useTerminalSize as Mock;
|
||||
|
||||
it('should prevent terminal height from being less than 1', async () => {
|
||||
it.skip('should prevent terminal height from being less than 1', async () => {
|
||||
const resizePtySpy = vi.spyOn(ShellExecutionService, 'resizePty');
|
||||
// Arrange: Simulate a small terminal and a large footer
|
||||
mockedUseTerminalSize.mockReturnValue({ columns: 80, rows: 5 });
|
||||
@@ -3126,7 +3143,7 @@ describe('AppContainer State Management', () => {
|
||||
});
|
||||
|
||||
describe('Shell Interaction', () => {
|
||||
it('should not crash if resizing the pty fails', async () => {
|
||||
it.skip('should not crash if resizing the pty fails', async () => {
|
||||
const resizePtySpy = vi
|
||||
.spyOn(ShellExecutionService, 'resizePty')
|
||||
.mockImplementation(() => {
|
||||
|
||||
@@ -126,6 +126,7 @@ import { useFolderTrust } from './hooks/useFolderTrust.js';
|
||||
import { useIdeTrustListener } from './hooks/useIdeTrustListener.js';
|
||||
import { type IdeIntegrationNudgeResult } from './IdeIntegrationNudge.js';
|
||||
import { appEvents, AppEvent, TransientMessageType } from '../utils/events.js';
|
||||
import { notifyResponse, markTasksWorking } from '../external-listener.js';
|
||||
import { type UpdateObject } from './utils/updateCheck.js';
|
||||
import { setUpdateHandler } from '../utils/handleAutoUpdate.js';
|
||||
import { registerCleanup, runExitCleanup } from '../utils/cleanup.js';
|
||||
@@ -231,6 +232,19 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
useMemoryMonitor(historyManager);
|
||||
const isAlternateBuffer = config.getUseAlternateBuffer();
|
||||
const [corgiMode, setCorgiMode] = useState(false);
|
||||
const [a2aListenerPort, setA2aListenerPort] = useState<number | null>(null);
|
||||
|
||||
// Listen for A2A listener startup to display port in status bar
|
||||
useEffect(() => {
|
||||
const handler = (port: number) => {
|
||||
setA2aListenerPort(port);
|
||||
};
|
||||
appEvents.on(AppEvent.A2AListenerStarted, handler);
|
||||
return () => {
|
||||
appEvents.off(AppEvent.A2AListenerStarted, handler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const [forceRerenderKey, setForceRerenderKey] = useState(0);
|
||||
const [debugMessage, setDebugMessage] = useState<string>('');
|
||||
const [quittingMessages, setQuittingMessages] = useState<
|
||||
@@ -1113,6 +1127,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
backgroundShells,
|
||||
dismissBackgroundShell,
|
||||
retryStatus,
|
||||
sisyphusSecondsRemaining,
|
||||
} = useGeminiStream(
|
||||
config.getGeminiClient(),
|
||||
historyManager.history,
|
||||
@@ -1204,6 +1219,53 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
isMcpReady,
|
||||
});
|
||||
|
||||
// Bridge external messages from A2A HTTP listener to message queue
|
||||
useEffect(() => {
|
||||
const handler = (text: string) => {
|
||||
addMessage(text);
|
||||
};
|
||||
appEvents.on(AppEvent.ExternalMessage, handler);
|
||||
return () => {
|
||||
appEvents.off(AppEvent.ExternalMessage, handler);
|
||||
};
|
||||
}, [addMessage]);
|
||||
|
||||
// Track streaming state transitions for A2A response capture
|
||||
const prevStreamingStateRef = useRef(streamingState);
|
||||
|
||||
useEffect(() => {
|
||||
const prev = prevStreamingStateRef.current;
|
||||
prevStreamingStateRef.current = streamingState;
|
||||
|
||||
// Mark tasks as "working" when streaming starts
|
||||
if (
|
||||
prev === StreamingState.Idle &&
|
||||
streamingState !== StreamingState.Idle
|
||||
) {
|
||||
markTasksWorking();
|
||||
}
|
||||
|
||||
// Capture response when streaming ends (for A2A tasks or unsolicited output)
|
||||
if (
|
||||
prev !== StreamingState.Idle &&
|
||||
streamingState === StreamingState.Idle
|
||||
) {
|
||||
// Collect all contiguous trailing gemini items to form the full response.
|
||||
// Items can be 'gemini' or 'gemini_content' (split large messages).
|
||||
const history = historyManager.history;
|
||||
const parts: string[] = [];
|
||||
for (let i = history.length - 1; i >= 0; i--) {
|
||||
const item = history[i];
|
||||
if (item.type !== 'gemini' && item.type !== 'gemini_content') break;
|
||||
if (typeof item.text === 'string' && item.text) {
|
||||
parts.unshift(item.text);
|
||||
}
|
||||
}
|
||||
notifyResponse(parts.join('\n'));
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [streamingState]);
|
||||
|
||||
cancelHandlerRef.current = useCallback(
|
||||
(shouldRestorePrompt: boolean = true) => {
|
||||
const pendingHistoryItems = [
|
||||
@@ -1421,32 +1483,6 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
const initialPromptSubmitted = useRef(false);
|
||||
const geminiClient = config.getGeminiClient();
|
||||
|
||||
useEffect(() => {
|
||||
if (activePtyId) {
|
||||
try {
|
||||
ShellExecutionService.resizePty(
|
||||
activePtyId,
|
||||
Math.floor(terminalWidth * SHELL_WIDTH_FRACTION),
|
||||
Math.max(
|
||||
Math.floor(availableTerminalHeight - SHELL_HEIGHT_PADDING),
|
||||
1,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
// This can happen in a race condition where the pty exits
|
||||
// right before we try to resize it.
|
||||
if (
|
||||
!(
|
||||
e instanceof Error &&
|
||||
e.message.includes('Cannot resize a pty that has already exited')
|
||||
)
|
||||
) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [terminalWidth, availableTerminalHeight, activePtyId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
initialPrompt &&
|
||||
@@ -1457,7 +1493,8 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
!isThemeDialogOpen &&
|
||||
!isEditorDialogOpen &&
|
||||
!showPrivacyNotice &&
|
||||
geminiClient?.isInitialized?.()
|
||||
geminiClient?.isInitialized?.() &&
|
||||
isMcpReady
|
||||
) {
|
||||
void handleFinalSubmit(initialPrompt);
|
||||
initialPromptSubmitted.current = true;
|
||||
@@ -1472,6 +1509,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
isEditorDialogOpen,
|
||||
showPrivacyNotice,
|
||||
geminiClient,
|
||||
isMcpReady,
|
||||
]);
|
||||
|
||||
const [idePromptAnswered, setIdePromptAnswered] = useState(false);
|
||||
@@ -1994,7 +2032,6 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
const nightly = props.version.includes('nightly');
|
||||
|
||||
const dialogsVisible =
|
||||
shouldShowIdePrompt ||
|
||||
shouldShowIdePrompt ||
|
||||
isFolderTrustDialogOpen ||
|
||||
isPolicyUpdateDialogOpen ||
|
||||
@@ -2299,10 +2336,11 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
...pendingGeminiHistoryItems,
|
||||
]),
|
||||
hintBuffer: '',
|
||||
sisyphusSecondsRemaining,
|
||||
a2aListenerPort,
|
||||
}),
|
||||
[
|
||||
isThemeDialogOpen,
|
||||
|
||||
themeError,
|
||||
isAuthenticating,
|
||||
isConfigInitialized,
|
||||
@@ -2420,6 +2458,8 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
adminSettingsChanged,
|
||||
newAgents,
|
||||
showIsExpandableHint,
|
||||
sisyphusSecondsRemaining,
|
||||
a2aListenerPort,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -29,9 +29,16 @@ vi.mock('../hooks/useKeypress.js', () => ({
|
||||
useKeypress: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../components/shared/text-buffer.js', () => ({
|
||||
useTextBuffer: vi.fn(),
|
||||
}));
|
||||
vi.mock('../components/shared/text-buffer.js', async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<
|
||||
typeof import('../components/shared/text-buffer.js')
|
||||
>();
|
||||
return {
|
||||
...actual,
|
||||
useTextBuffer: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('../contexts/UIStateContext.js', () => ({
|
||||
useUIState: vi.fn(() => ({
|
||||
|
||||
@@ -53,6 +53,7 @@ export const compressCommand: SlashCommand = {
|
||||
originalTokenCount: compressed.originalTokenCount,
|
||||
newTokenCount: compressed.newTokenCount,
|
||||
compressionStatus: compressed.compressionStatus,
|
||||
archivePath: compressed.archivePath,
|
||||
},
|
||||
} as HistoryItemCompression,
|
||||
Date.now(),
|
||||
|
||||
@@ -755,7 +755,7 @@ describe('extensionsCommand', () => {
|
||||
await uninstallAction!(mockContext, '');
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith({
|
||||
type: MessageType.ERROR,
|
||||
text: 'Usage: /extensions uninstall <extension-name>',
|
||||
text: 'Usage: /extensions uninstall <extension-names...>|--all',
|
||||
});
|
||||
expect(mockUninstallExtension).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -594,33 +594,53 @@ async function uninstallAction(context: CommandContext, args: string) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = args.trim();
|
||||
if (!name) {
|
||||
const uninstallArgs = args.split(' ').filter((value) => value.length > 0);
|
||||
const all = uninstallArgs.includes('--all');
|
||||
const names = uninstallArgs.filter((a) => !a.startsWith('--'));
|
||||
|
||||
if (!all && names.length === 0) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.ERROR,
|
||||
text: `Usage: /extensions uninstall <extension-name>`,
|
||||
text: `Usage: /extensions uninstall <extension-names...>|--all`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
context.ui.addItem({
|
||||
type: MessageType.INFO,
|
||||
text: `Uninstalling extension "${name}"...`,
|
||||
});
|
||||
let namesToUninstall: string[] = [];
|
||||
if (all) {
|
||||
namesToUninstall = extensionLoader.getExtensions().map((ext) => ext.name);
|
||||
} else {
|
||||
namesToUninstall = names;
|
||||
}
|
||||
|
||||
try {
|
||||
await extensionLoader.uninstallExtension(name, false);
|
||||
if (namesToUninstall.length === 0) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.INFO,
|
||||
text: `Extension "${name}" uninstalled successfully.`,
|
||||
text: all ? 'No extensions installed.' : 'No extension name provided.',
|
||||
});
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const extensionName of namesToUninstall) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.ERROR,
|
||||
text: `Failed to uninstall extension "${name}": ${getErrorMessage(
|
||||
error,
|
||||
)}`,
|
||||
type: MessageType.INFO,
|
||||
text: `Uninstalling extension "${extensionName}"...`,
|
||||
});
|
||||
|
||||
try {
|
||||
await extensionLoader.uninstallExtension(extensionName, false);
|
||||
context.ui.addItem({
|
||||
type: MessageType.INFO,
|
||||
text: `Extension "${extensionName}" uninstalled successfully.`,
|
||||
});
|
||||
} catch (error) {
|
||||
context.ui.addItem({
|
||||
type: MessageType.ERROR,
|
||||
text: `Failed to uninstall extension "${extensionName}": ${getErrorMessage(
|
||||
error,
|
||||
)}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,9 @@ export type SlashCommandActionReturn =
|
||||
|
||||
export enum CommandKind {
|
||||
BUILT_IN = 'built-in',
|
||||
FILE = 'file',
|
||||
USER_FILE = 'user-file',
|
||||
WORKSPACE_FILE = 'workspace-file',
|
||||
EXTENSION_FILE = 'extension-file',
|
||||
MCP_PROMPT = 'mcp-prompt',
|
||||
AGENT = 'agent',
|
||||
}
|
||||
@@ -203,6 +205,9 @@ export interface SlashCommand {
|
||||
extensionName?: string;
|
||||
extensionId?: string;
|
||||
|
||||
// Optional metadata for MCP commands
|
||||
mcpServerName?: string;
|
||||
|
||||
// The action to run. Optional for parent commands that only group sub-commands.
|
||||
action?: (
|
||||
context: CommandContext,
|
||||
|
||||
@@ -8,22 +8,14 @@ import type React from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
import { ApprovalMode } from '@google/gemini-cli-core';
|
||||
import { formatCommand } from '../utils/keybindingUtils.js';
|
||||
import { Command } from '../../config/keyBindings.js';
|
||||
|
||||
interface ApprovalModeIndicatorProps {
|
||||
approvalMode: ApprovalMode;
|
||||
allowPlanMode?: boolean;
|
||||
}
|
||||
|
||||
export const APPROVAL_MODE_TEXT = {
|
||||
AUTO_EDIT: 'auto-accept edits',
|
||||
PLAN: 'plan',
|
||||
YOLO: 'YOLO',
|
||||
HINT_SWITCH_TO_PLAN_MODE: 'shift+tab to plan',
|
||||
HINT_SWITCH_TO_MANUAL_MODE: 'shift+tab to manual',
|
||||
HINT_SWITCH_TO_AUTO_EDIT_MODE: 'shift+tab to accept edits',
|
||||
HINT_SWITCH_TO_YOLO_MODE: 'ctrl+y',
|
||||
};
|
||||
|
||||
export const ApprovalModeIndicator: React.FC<ApprovalModeIndicatorProps> = ({
|
||||
approvalMode,
|
||||
allowPlanMode,
|
||||
@@ -32,29 +24,32 @@ export const ApprovalModeIndicator: React.FC<ApprovalModeIndicatorProps> = ({
|
||||
let textContent = '';
|
||||
let subText = '';
|
||||
|
||||
const cycleHint = formatCommand(Command.CYCLE_APPROVAL_MODE);
|
||||
const yoloHint = formatCommand(Command.TOGGLE_YOLO);
|
||||
|
||||
switch (approvalMode) {
|
||||
case ApprovalMode.AUTO_EDIT:
|
||||
textColor = theme.status.warning;
|
||||
textContent = APPROVAL_MODE_TEXT.AUTO_EDIT;
|
||||
textContent = 'auto-accept edits';
|
||||
subText = allowPlanMode
|
||||
? APPROVAL_MODE_TEXT.HINT_SWITCH_TO_PLAN_MODE
|
||||
: APPROVAL_MODE_TEXT.HINT_SWITCH_TO_MANUAL_MODE;
|
||||
? `${cycleHint} to plan`
|
||||
: `${cycleHint} to manual`;
|
||||
break;
|
||||
case ApprovalMode.PLAN:
|
||||
textColor = theme.status.success;
|
||||
textContent = APPROVAL_MODE_TEXT.PLAN;
|
||||
subText = APPROVAL_MODE_TEXT.HINT_SWITCH_TO_MANUAL_MODE;
|
||||
textContent = 'plan';
|
||||
subText = `${cycleHint} to manual`;
|
||||
break;
|
||||
case ApprovalMode.YOLO:
|
||||
textColor = theme.status.error;
|
||||
textContent = APPROVAL_MODE_TEXT.YOLO;
|
||||
subText = APPROVAL_MODE_TEXT.HINT_SWITCH_TO_YOLO_MODE;
|
||||
textContent = 'YOLO';
|
||||
subText = yoloHint;
|
||||
break;
|
||||
case ApprovalMode.DEFAULT:
|
||||
default:
|
||||
textColor = theme.text.accent;
|
||||
textContent = '';
|
||||
subText = APPROVAL_MODE_TEXT.HINT_SWITCH_TO_AUTO_EDIT_MODE;
|
||||
subText = `${cycleHint} to accept edits`;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1347,4 +1347,47 @@ describe('AskUserDialog', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('expands paste placeholders in multi-select custom option via Done', async () => {
|
||||
const questions: Question[] = [
|
||||
{
|
||||
question: 'Which features?',
|
||||
header: 'Features',
|
||||
type: QuestionType.CHOICE,
|
||||
options: [{ label: 'TypeScript', description: '' }],
|
||||
multiSelect: true,
|
||||
},
|
||||
];
|
||||
|
||||
const onSubmit = vi.fn();
|
||||
const { stdin } = renderWithProviders(
|
||||
<AskUserDialog
|
||||
questions={questions}
|
||||
onSubmit={onSubmit}
|
||||
onCancel={vi.fn()}
|
||||
width={120}
|
||||
/>,
|
||||
{ width: 120 },
|
||||
);
|
||||
|
||||
// Select TypeScript
|
||||
writeKey(stdin, '\r');
|
||||
// Down to Other
|
||||
writeKey(stdin, '\x1b[B');
|
||||
|
||||
// Simulate bracketed paste of multi-line text into the custom option
|
||||
const pastedText = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6';
|
||||
const ESC = '\x1b';
|
||||
writeKey(stdin, `${ESC}[200~${pastedText}${ESC}[201~`);
|
||||
|
||||
// Down to Done and submit
|
||||
writeKey(stdin, '\x1b[B');
|
||||
writeKey(stdin, '\r');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onSubmit).toHaveBeenCalledWith({
|
||||
'0': `TypeScript, ${pastedText}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,7 +23,11 @@ import { useKeypress, type Key } from '../hooks/useKeypress.js';
|
||||
import { keyMatchers, Command } from '../keyMatchers.js';
|
||||
import { checkExhaustive } from '@google/gemini-cli-core';
|
||||
import { TextInput } from './shared/TextInput.js';
|
||||
import { useTextBuffer } from './shared/text-buffer.js';
|
||||
import { formatCommand } from '../utils/keybindingUtils.js';
|
||||
import {
|
||||
useTextBuffer,
|
||||
expandPastePlaceholders,
|
||||
} from './shared/text-buffer.js';
|
||||
import { getCachedStringWidth } from '../utils/textUtils.js';
|
||||
import { useTabbedNavigation } from '../hooks/useTabbedNavigation.js';
|
||||
import { DialogFooter } from './shared/DialogFooter.js';
|
||||
@@ -252,7 +256,7 @@ const ReviewView: React.FC<ReviewViewProps> = ({
|
||||
</Box>
|
||||
<DialogFooter
|
||||
primaryAction="Enter to submit"
|
||||
navigationActions="Tab/Shift+Tab to edit answers"
|
||||
navigationActions={`${formatCommand(Command.DIALOG_NEXT)}/${formatCommand(Command.DIALOG_PREV)} to edit answers`}
|
||||
extraParts={extraParts}
|
||||
/>
|
||||
</Box>
|
||||
@@ -302,10 +306,12 @@ const TextQuestionView: React.FC<TextQuestionViewProps> = ({
|
||||
const lastTextValueRef = useRef(textValue);
|
||||
useEffect(() => {
|
||||
if (textValue !== lastTextValueRef.current) {
|
||||
onSelectionChange?.(textValue);
|
||||
onSelectionChange?.(
|
||||
expandPastePlaceholders(textValue, buffer.pastedContent),
|
||||
);
|
||||
lastTextValueRef.current = textValue;
|
||||
}
|
||||
}, [textValue, onSelectionChange]);
|
||||
}, [textValue, onSelectionChange, buffer.pastedContent]);
|
||||
|
||||
// Handle Ctrl+C to clear all text
|
||||
const handleExtraKeys = useCallback(
|
||||
@@ -588,11 +594,15 @@ const ChoiceQuestionView: React.FC<ChoiceQuestionViewProps> = ({
|
||||
}
|
||||
});
|
||||
if (includeCustomOption && customOption.trim()) {
|
||||
answers.push(customOption.trim());
|
||||
const expanded = expandPastePlaceholders(
|
||||
customOption,
|
||||
customBuffer.pastedContent,
|
||||
);
|
||||
answers.push(expanded.trim());
|
||||
}
|
||||
return answers.join(', ');
|
||||
},
|
||||
[questionOptions],
|
||||
[questionOptions, customBuffer.pastedContent],
|
||||
);
|
||||
|
||||
// Synchronize selection changes with parent - only when it actually changes
|
||||
@@ -757,7 +767,12 @@ const ChoiceQuestionView: React.FC<ChoiceQuestionViewProps> = ({
|
||||
} else if (itemValue.type === 'other') {
|
||||
// In single select, selecting other submits it if it has text
|
||||
if (customOptionText.trim()) {
|
||||
onAnswer(customOptionText.trim());
|
||||
onAnswer(
|
||||
expandPastePlaceholders(
|
||||
customOptionText,
|
||||
customBuffer.pastedContent,
|
||||
).trim(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -767,6 +782,7 @@ const ChoiceQuestionView: React.FC<ChoiceQuestionViewProps> = ({
|
||||
selectedIndices,
|
||||
isCustomOptionSelected,
|
||||
customOptionText,
|
||||
customBuffer.pastedContent,
|
||||
onAnswer,
|
||||
buildAnswerString,
|
||||
],
|
||||
@@ -1146,7 +1162,7 @@ export const AskUserDialog: React.FC<AskUserDialogProps> = ({
|
||||
navigationActions={
|
||||
questions.length > 1
|
||||
? currentQuestion.type === 'text' || isEditingCustomOption
|
||||
? 'Tab/Shift+Tab to switch questions'
|
||||
? `${formatCommand(Command.DIALOG_NEXT)}/${formatCommand(Command.DIALOG_PREV)} to switch questions`
|
||||
: '←/→ to switch questions'
|
||||
: currentQuestion.type === 'text' || isEditingCustomOption
|
||||
? undefined
|
||||
|
||||
@@ -208,6 +208,8 @@ const createMockUIState = (overrides: Partial<UIState> = {}): UIState =>
|
||||
proQuotaRequest: null,
|
||||
validationRequest: null,
|
||||
},
|
||||
sisyphusSecondsRemaining: null,
|
||||
a2aListenerPort: null,
|
||||
...overrides,
|
||||
}) as UIState;
|
||||
|
||||
@@ -374,7 +376,7 @@ describe('Composer', () => {
|
||||
const uiState = createMockUIState({
|
||||
streamingState: StreamingState.Responding,
|
||||
thought: {
|
||||
subject: 'Detailed in-history thought',
|
||||
subject: 'Thinking about code',
|
||||
description: 'Full text is already in history',
|
||||
},
|
||||
});
|
||||
@@ -385,7 +387,7 @@ describe('Composer', () => {
|
||||
const { lastFrame } = await renderComposer(uiState, settings);
|
||||
|
||||
const output = lastFrame();
|
||||
expect(output).toContain('LoadingIndicator: Thinking ...');
|
||||
expect(output).toContain('LoadingIndicator: Thinking...');
|
||||
});
|
||||
|
||||
it('hides shortcuts hint while loading', async () => {
|
||||
|
||||
@@ -239,7 +239,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
||||
: uiState.currentLoadingPhrase
|
||||
}
|
||||
thoughtLabel={
|
||||
inlineThinkingMode === 'full' ? 'Thinking ...' : undefined
|
||||
inlineThinkingMode === 'full' ? 'Thinking...' : undefined
|
||||
}
|
||||
elapsedTime={uiState.elapsedTime}
|
||||
/>
|
||||
@@ -282,7 +282,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
||||
: uiState.currentLoadingPhrase
|
||||
}
|
||||
thoughtLabel={
|
||||
inlineThinkingMode === 'full' ? 'Thinking ...' : undefined
|
||||
inlineThinkingMode === 'full' ? 'Thinking...' : undefined
|
||||
}
|
||||
elapsedTime={uiState.elapsedTime}
|
||||
/>
|
||||
@@ -390,7 +390,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
||||
marginTop={
|
||||
(showApprovalIndicator ||
|
||||
uiState.shellModeActive) &&
|
||||
isNarrow
|
||||
!isNarrow
|
||||
? 1
|
||||
: 0
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('Help Component', () => {
|
||||
expect(output).toContain('Keyboard Shortcuts:');
|
||||
expect(output).toContain('Ctrl+C');
|
||||
expect(output).toContain('Ctrl+S');
|
||||
expect(output).toContain('Page Up/Down');
|
||||
expect(output).toContain('Page Up/Page Down');
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,8 @@ import { theme } from '../semantic-colors.js';
|
||||
import { type SlashCommand, CommandKind } from '../commands/types.js';
|
||||
import { KEYBOARD_SHORTCUTS_URL } from '../constants.js';
|
||||
import { sanitizeForDisplay } from '../utils/textUtils.js';
|
||||
import { formatCommand } from '../utils/keybindingUtils.js';
|
||||
import { Command } from '../../config/keyBindings.js';
|
||||
|
||||
interface Help {
|
||||
commands: readonly SlashCommand[];
|
||||
@@ -116,75 +118,75 @@ export const Help: React.FC<Help> = ({ commands }) => (
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Alt+Left/Right
|
||||
{formatCommand(Command.MOVE_WORD_LEFT)}/
|
||||
{formatCommand(Command.MOVE_WORD_RIGHT)}
|
||||
</Text>{' '}
|
||||
- Jump through words in the input
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Ctrl+C
|
||||
{formatCommand(Command.QUIT)}
|
||||
</Text>{' '}
|
||||
- Quit application
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
{process.platform === 'win32' ? 'Ctrl+Enter' : 'Ctrl+J'}
|
||||
{formatCommand(Command.NEWLINE)}
|
||||
</Text>{' '}
|
||||
{process.platform === 'linux'
|
||||
? '- New line (Alt+Enter works for certain linux distros)'
|
||||
: '- New line'}
|
||||
- New line
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Ctrl+L
|
||||
{formatCommand(Command.CLEAR_SCREEN)}
|
||||
</Text>{' '}
|
||||
- Clear the screen
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Ctrl+S
|
||||
{formatCommand(Command.TOGGLE_COPY_MODE)}
|
||||
</Text>{' '}
|
||||
- Enter selection mode to copy text
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Ctrl+X
|
||||
{formatCommand(Command.OPEN_EXTERNAL_EDITOR)}
|
||||
</Text>{' '}
|
||||
- Open input in external editor
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Ctrl+Y
|
||||
{formatCommand(Command.TOGGLE_YOLO)}
|
||||
</Text>{' '}
|
||||
- Toggle YOLO mode
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Enter
|
||||
{formatCommand(Command.SUBMIT)}
|
||||
</Text>{' '}
|
||||
- Send message
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Esc
|
||||
{formatCommand(Command.ESCAPE)}
|
||||
</Text>{' '}
|
||||
- Cancel operation / Clear input (double press)
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Page Up/Down
|
||||
{formatCommand(Command.PAGE_UP)}/{formatCommand(Command.PAGE_DOWN)}
|
||||
</Text>{' '}
|
||||
- Scroll page up/down
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Shift+Tab
|
||||
{formatCommand(Command.CYCLE_APPROVAL_MODE)}
|
||||
</Text>{' '}
|
||||
- Toggle auto-accepting edits
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold color={theme.text.accent}>
|
||||
Up/Down
|
||||
{formatCommand(Command.HISTORY_UP)}/
|
||||
{formatCommand(Command.HISTORY_DOWN)}
|
||||
</Text>{' '}
|
||||
- Cycle through your prompt history
|
||||
</Text>
|
||||
|
||||
@@ -290,6 +290,26 @@ describe('<HistoryItemDisplay />', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders "Thinking..." header when isFirstThinking is true', async () => {
|
||||
const item: HistoryItem = {
|
||||
...baseItem,
|
||||
type: 'thinking',
|
||||
thought: { subject: 'Thinking', description: 'test' },
|
||||
};
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<HistoryItemDisplay {...baseItem} item={item} isFirstThinking={true} />,
|
||||
{
|
||||
settings: createMockSettings({
|
||||
merged: { ui: { inlineThinkingMode: 'full' } },
|
||||
}),
|
||||
},
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toContain(' Thinking...');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
it('does not render thinking item when disabled', async () => {
|
||||
const item: HistoryItem = {
|
||||
...baseItem,
|
||||
|
||||
@@ -46,6 +46,8 @@ interface HistoryItemDisplayProps {
|
||||
commands?: readonly SlashCommand[];
|
||||
availableTerminalHeightGemini?: number;
|
||||
isExpandable?: boolean;
|
||||
isFirstThinking?: boolean;
|
||||
isFirstAfterThinking?: boolean;
|
||||
}
|
||||
|
||||
export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||
@@ -56,16 +58,30 @@ export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||
commands,
|
||||
availableTerminalHeightGemini,
|
||||
isExpandable,
|
||||
isFirstThinking = false,
|
||||
isFirstAfterThinking = false,
|
||||
}) => {
|
||||
const settings = useSettings();
|
||||
const inlineThinkingMode = getInlineThinkingMode(settings);
|
||||
const itemForDisplay = useMemo(() => escapeAnsiCtrlCodes(item), [item]);
|
||||
|
||||
const needsTopMarginAfterThinking =
|
||||
isFirstAfterThinking && inlineThinkingMode !== 'off';
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" key={itemForDisplay.id} width={terminalWidth}>
|
||||
<Box
|
||||
flexDirection="column"
|
||||
key={itemForDisplay.id}
|
||||
width={terminalWidth}
|
||||
marginTop={needsTopMarginAfterThinking ? 1 : 0}
|
||||
>
|
||||
{/* Render standard message types */}
|
||||
{itemForDisplay.type === 'thinking' && inlineThinkingMode !== 'off' && (
|
||||
<ThinkingMessage thought={itemForDisplay.thought} />
|
||||
<ThinkingMessage
|
||||
thought={itemForDisplay.thought}
|
||||
terminalWidth={terminalWidth}
|
||||
isFirstThinking={isFirstThinking}
|
||||
/>
|
||||
)}
|
||||
{itemForDisplay.type === 'hint' && (
|
||||
<HintMessage text={itemForDisplay.text} />
|
||||
|
||||
@@ -1349,7 +1349,7 @@ describe('InputPrompt', () => {
|
||||
it('should autocomplete custom commands from .toml files on Enter', async () => {
|
||||
const customCommand: SlashCommand = {
|
||||
name: 'find-capital',
|
||||
kind: CommandKind.FILE,
|
||||
kind: CommandKind.USER_FILE,
|
||||
description: 'Find capital of a country',
|
||||
action: vi.fn(),
|
||||
// No autoExecute flag - custom commands default to undefined
|
||||
@@ -2206,7 +2206,8 @@ describe('InputPrompt', () => {
|
||||
// Check that all lines, including the empty one, are rendered.
|
||||
// This implicitly tests that the Box wrapper provides height for the empty line.
|
||||
expect(frame).toContain('hello');
|
||||
expect(frame).toContain(`world${chalk.inverse(' ')}`);
|
||||
expect(frame).toContain('world');
|
||||
expect(frame).toContain(chalk.inverse(' '));
|
||||
|
||||
const outputLines = frame.trim().split('\n');
|
||||
// The number of lines should be 2 for the border plus 3 for the content.
|
||||
|
||||
@@ -15,7 +15,7 @@ import { HalfLinePaddedBox } from './shared/HalfLinePaddedBox.js';
|
||||
import {
|
||||
type TextBuffer,
|
||||
logicalPosToOffset,
|
||||
PASTED_TEXT_PLACEHOLDER_REGEX,
|
||||
expandPastePlaceholders,
|
||||
getTransformUnderCursor,
|
||||
LARGE_PASTE_LINE_THRESHOLD,
|
||||
LARGE_PASTE_CHAR_THRESHOLD,
|
||||
@@ -346,10 +346,9 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
|
||||
(submittedValue: string) => {
|
||||
let processedValue = submittedValue;
|
||||
if (buffer.pastedContent) {
|
||||
// Replace placeholders like [Pasted Text: 6 lines] with actual content
|
||||
processedValue = processedValue.replace(
|
||||
PASTED_TEXT_PLACEHOLDER_REGEX,
|
||||
(match) => buffer.pastedContent[match] || match,
|
||||
processedValue = expandPastePlaceholders(
|
||||
processedValue,
|
||||
buffer.pastedContent,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -258,13 +258,32 @@ describe('<LoadingIndicator />', () => {
|
||||
const output = lastFrame();
|
||||
expect(output).toBeDefined();
|
||||
if (output) {
|
||||
expect(output).toContain('💬');
|
||||
// Should NOT contain "Thinking... " prefix because the subject already starts with "Thinking"
|
||||
expect(output).not.toContain('Thinking... Thinking');
|
||||
expect(output).toContain('Thinking about something...');
|
||||
expect(output).not.toContain('and other stuff.');
|
||||
}
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should prepend "Thinking... " if the subject does not start with "Thinking"', async () => {
|
||||
const props = {
|
||||
thought: {
|
||||
subject: 'Planning the response...',
|
||||
description: 'details',
|
||||
},
|
||||
elapsedTime: 5,
|
||||
};
|
||||
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
|
||||
<LoadingIndicator {...props} />,
|
||||
StreamingState.Responding,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
expect(output).toContain('Thinking... Planning the response...');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should prioritize thought.subject over currentLoadingPhrase', async () => {
|
||||
const props = {
|
||||
thought: {
|
||||
@@ -280,13 +299,13 @@ describe('<LoadingIndicator />', () => {
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
expect(output).toContain('💬');
|
||||
expect(output).toContain('Thinking... ');
|
||||
expect(output).toContain('This should be displayed');
|
||||
expect(output).not.toContain('This should not be displayed');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should not display thought icon for non-thought loading phrases', async () => {
|
||||
it('should not display thought indicator for non-thought loading phrases', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = renderWithContext(
|
||||
<LoadingIndicator
|
||||
currentLoadingPhrase="some random tip..."
|
||||
@@ -295,7 +314,7 @@ describe('<LoadingIndicator />', () => {
|
||||
StreamingState.Responding,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).not.toContain('💬');
|
||||
expect(lastFrame()).not.toContain('Thinking... ');
|
||||
unmount();
|
||||
});
|
||||
|
||||
|
||||
@@ -58,7 +58,11 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({
|
||||
const hasThoughtIndicator =
|
||||
currentLoadingPhrase !== INTERACTIVE_SHELL_WAITING_PHRASE &&
|
||||
Boolean(thought?.subject?.trim());
|
||||
const thinkingIndicator = hasThoughtIndicator ? '💬 ' : '';
|
||||
// Avoid "Thinking... Thinking..." duplication if primaryText already starts with "Thinking"
|
||||
const thinkingIndicator =
|
||||
hasThoughtIndicator && !primaryText?.startsWith('Thinking')
|
||||
? 'Thinking... '
|
||||
: '';
|
||||
|
||||
const cancelAndTimerContent =
|
||||
showCancelAndTimer &&
|
||||
|
||||
@@ -22,17 +22,19 @@ import { CoreToolCallStatus } from '@google/gemini-cli-core';
|
||||
import { type IndividualToolCallDisplay } from '../types.js';
|
||||
|
||||
// Mock dependencies
|
||||
const mockUseSettings = vi.fn().mockReturnValue({
|
||||
merged: {
|
||||
ui: {
|
||||
inlineThinkingMode: 'off',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
vi.mock('../contexts/SettingsContext.js', async () => {
|
||||
const actual = await vi.importActual('../contexts/SettingsContext.js');
|
||||
return {
|
||||
...actual,
|
||||
useSettings: () => ({
|
||||
merged: {
|
||||
ui: {
|
||||
inlineThinkingMode: 'off',
|
||||
},
|
||||
},
|
||||
}),
|
||||
useSettings: () => mockUseSettings(),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -333,6 +335,13 @@ describe('MainContent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.mocked(useAlternateBuffer).mockReturnValue(false);
|
||||
mockUseSettings.mockReturnValue({
|
||||
merged: {
|
||||
ui: {
|
||||
inlineThinkingMode: 'off',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -570,6 +579,64 @@ describe('MainContent', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders multiple thinking messages sequentially correctly', async () => {
|
||||
mockUseSettings.mockReturnValue({
|
||||
merged: {
|
||||
ui: {
|
||||
inlineThinkingMode: 'expanded',
|
||||
},
|
||||
},
|
||||
});
|
||||
vi.mocked(useAlternateBuffer).mockReturnValue(true);
|
||||
|
||||
const uiState = {
|
||||
...defaultMockUiState,
|
||||
history: [
|
||||
{ id: 0, type: 'user' as const, text: 'Plan a solution' },
|
||||
{
|
||||
id: 1,
|
||||
type: 'thinking' as const,
|
||||
thought: {
|
||||
subject: 'Initial analysis',
|
||||
description:
|
||||
'This is a multiple line paragraph for the first thinking message of how the model analyzes the problem.',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
type: 'thinking' as const,
|
||||
thought: {
|
||||
subject: 'Planning execution',
|
||||
description:
|
||||
'This a second multiple line paragraph for the second thinking message explaining the plan in detail so that it wraps around the terminal display.',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
type: 'thinking' as const,
|
||||
thought: {
|
||||
subject: 'Refining approach',
|
||||
description:
|
||||
'And finally a third multiple line paragraph for the third thinking message to refine the solution.',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const renderResult = renderWithProviders(<MainContent />, {
|
||||
uiState: uiState as Partial<UIState>,
|
||||
});
|
||||
await renderResult.waitUntilReady();
|
||||
|
||||
const output = renderResult.lastFrame();
|
||||
expect(output).toContain('Initial analysis');
|
||||
expect(output).toContain('Planning execution');
|
||||
expect(output).toContain('Refining approach');
|
||||
expect(output).toMatchSnapshot();
|
||||
await expect(renderResult).toMatchSvgSnapshot();
|
||||
renderResult.unmount();
|
||||
});
|
||||
|
||||
describe('MainContent Tool Output Height Logic', () => {
|
||||
const testCases = [
|
||||
{
|
||||
|
||||
@@ -62,11 +62,31 @@ export const MainContent = () => {
|
||||
return -1;
|
||||
}, [uiState.history]);
|
||||
|
||||
const augmentedHistory = useMemo(
|
||||
() =>
|
||||
uiState.history.map((item, index) => {
|
||||
const isExpandable = index > lastUserPromptIndex;
|
||||
const prevType =
|
||||
index > 0 ? uiState.history[index - 1]?.type : undefined;
|
||||
const isFirstThinking =
|
||||
item.type === 'thinking' && prevType !== 'thinking';
|
||||
const isFirstAfterThinking =
|
||||
item.type !== 'thinking' && prevType === 'thinking';
|
||||
|
||||
return {
|
||||
item,
|
||||
isExpandable,
|
||||
isFirstThinking,
|
||||
isFirstAfterThinking,
|
||||
};
|
||||
}),
|
||||
[uiState.history, lastUserPromptIndex],
|
||||
);
|
||||
|
||||
const historyItems = useMemo(
|
||||
() =>
|
||||
uiState.history.map((h, index) => {
|
||||
const isExpandable = index > lastUserPromptIndex;
|
||||
return (
|
||||
augmentedHistory.map(
|
||||
({ item, isExpandable, isFirstThinking, isFirstAfterThinking }) => (
|
||||
<MemoizedHistoryItemDisplay
|
||||
terminalWidth={mainAreaWidth}
|
||||
availableTerminalHeight={
|
||||
@@ -75,21 +95,22 @@ export const MainContent = () => {
|
||||
: undefined
|
||||
}
|
||||
availableTerminalHeightGemini={MAX_GEMINI_MESSAGE_LINES}
|
||||
key={h.id}
|
||||
item={h}
|
||||
key={item.id}
|
||||
item={item}
|
||||
isPending={false}
|
||||
commands={uiState.slashCommands}
|
||||
isExpandable={isExpandable}
|
||||
isFirstThinking={isFirstThinking}
|
||||
isFirstAfterThinking={isFirstAfterThinking}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
[
|
||||
uiState.history,
|
||||
augmentedHistory,
|
||||
mainAreaWidth,
|
||||
staticAreaMaxItemHeight,
|
||||
uiState.slashCommands,
|
||||
uiState.constrainHeight,
|
||||
lastUserPromptIndex,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -106,18 +127,31 @@ export const MainContent = () => {
|
||||
const pendingItems = useMemo(
|
||||
() => (
|
||||
<Box flexDirection="column">
|
||||
{pendingHistoryItems.map((item, i) => (
|
||||
<HistoryItemDisplay
|
||||
key={i}
|
||||
availableTerminalHeight={
|
||||
uiState.constrainHeight ? staticAreaMaxItemHeight : undefined
|
||||
}
|
||||
terminalWidth={mainAreaWidth}
|
||||
item={{ ...item, id: 0 }}
|
||||
isPending={true}
|
||||
isExpandable={true}
|
||||
/>
|
||||
))}
|
||||
{pendingHistoryItems.map((item, i) => {
|
||||
const prevType =
|
||||
i === 0
|
||||
? uiState.history.at(-1)?.type
|
||||
: pendingHistoryItems[i - 1]?.type;
|
||||
const isFirstThinking =
|
||||
item.type === 'thinking' && prevType !== 'thinking';
|
||||
const isFirstAfterThinking =
|
||||
item.type !== 'thinking' && prevType === 'thinking';
|
||||
|
||||
return (
|
||||
<HistoryItemDisplay
|
||||
key={i}
|
||||
availableTerminalHeight={
|
||||
uiState.constrainHeight ? staticAreaMaxItemHeight : undefined
|
||||
}
|
||||
terminalWidth={mainAreaWidth}
|
||||
item={{ ...item, id: 0 }}
|
||||
isPending={true}
|
||||
isExpandable={true}
|
||||
isFirstThinking={isFirstThinking}
|
||||
isFirstAfterThinking={isFirstAfterThinking}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{showConfirmationQueue && confirmingTool && (
|
||||
<ToolConfirmationQueue confirmingTool={confirmingTool} />
|
||||
)}
|
||||
@@ -130,20 +164,25 @@ export const MainContent = () => {
|
||||
mainAreaWidth,
|
||||
showConfirmationQueue,
|
||||
confirmingTool,
|
||||
uiState.history,
|
||||
],
|
||||
);
|
||||
|
||||
const virtualizedData = useMemo(
|
||||
() => [
|
||||
{ type: 'header' as const },
|
||||
...uiState.history.map((item, index) => ({
|
||||
type: 'history' as const,
|
||||
item,
|
||||
isExpandable: index > lastUserPromptIndex,
|
||||
})),
|
||||
...augmentedHistory.map(
|
||||
({ item, isExpandable, isFirstThinking, isFirstAfterThinking }) => ({
|
||||
type: 'history' as const,
|
||||
item,
|
||||
isExpandable,
|
||||
isFirstThinking,
|
||||
isFirstAfterThinking,
|
||||
}),
|
||||
),
|
||||
{ type: 'pending' as const },
|
||||
],
|
||||
[uiState.history, lastUserPromptIndex],
|
||||
[augmentedHistory],
|
||||
);
|
||||
|
||||
const renderItem = useCallback(
|
||||
@@ -171,6 +210,8 @@ export const MainContent = () => {
|
||||
isPending={false}
|
||||
commands={uiState.slashCommands}
|
||||
isExpandable={item.isExpandable}
|
||||
isFirstThinking={item.isFirstThinking}
|
||||
isFirstAfterThinking={item.isFirstAfterThinking}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -6,15 +6,18 @@
|
||||
|
||||
import { render } from '../../test-utils/render.js';
|
||||
import { RawMarkdownIndicator } from './RawMarkdownIndicator.js';
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest';
|
||||
|
||||
describe('RawMarkdownIndicator', () => {
|
||||
const originalPlatform = process.platform;
|
||||
|
||||
beforeEach(() => vi.stubEnv('FORCE_GENERIC_KEYBINDING_HINTS', ''));
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it('renders correct key binding for darwin', async () => {
|
||||
@@ -26,7 +29,7 @@ describe('RawMarkdownIndicator', () => {
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('raw markdown mode');
|
||||
expect(lastFrame()).toContain('option+m to toggle');
|
||||
expect(lastFrame()).toContain('Option+M to toggle');
|
||||
unmount();
|
||||
});
|
||||
|
||||
@@ -39,7 +42,7 @@ describe('RawMarkdownIndicator', () => {
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('raw markdown mode');
|
||||
expect(lastFrame()).toContain('alt+m to toggle');
|
||||
expect(lastFrame()).toContain('Alt+M to toggle');
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
import type React from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
import { formatCommand } from '../utils/keybindingUtils.js';
|
||||
import { Command } from '../../config/keyBindings.js';
|
||||
|
||||
export const RawMarkdownIndicator: React.FC = () => {
|
||||
const modKey = process.platform === 'darwin' ? 'option+m' : 'alt+m';
|
||||
const modKey = formatCommand(Command.TOGGLE_MARKDOWN);
|
||||
return (
|
||||
<Box>
|
||||
<Text>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { Box, Text } from 'ink';
|
||||
import { Box, Text, useIsScreenReaderEnabled } from 'ink';
|
||||
import type React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
@@ -58,6 +58,7 @@ export const RewindConfirmation: React.FC<RewindConfirmationProps> = ({
|
||||
terminalWidth,
|
||||
timestamp,
|
||||
}) => {
|
||||
const isScreenReaderEnabled = useIsScreenReaderEnabled();
|
||||
useKeypress(
|
||||
(key) => {
|
||||
if (keyMatchers[Command.ESCAPE](key)) {
|
||||
@@ -83,6 +84,53 @@ export const RewindConfirmation: React.FC<RewindConfirmationProps> = ({
|
||||
option.value !== RewindOutcome.RevertOnly,
|
||||
);
|
||||
}, [stats]);
|
||||
if (isScreenReaderEnabled) {
|
||||
return (
|
||||
<Box flexDirection="column" width={terminalWidth}>
|
||||
<Text bold>Confirm Rewind</Text>
|
||||
|
||||
{stats && (
|
||||
<Box flexDirection="column">
|
||||
<Text>
|
||||
{stats.fileCount === 1
|
||||
? `File: ${stats.details?.at(0)?.fileName}`
|
||||
: `${stats.fileCount} files affected`}
|
||||
</Text>
|
||||
<Text>Lines added: {stats.addedLines}</Text>
|
||||
<Text>Lines removed: {stats.removedLines}</Text>
|
||||
{timestamp && <Text>({formatTimeAgo(timestamp)})</Text>}
|
||||
<Text>
|
||||
Note: Rewinding does not affect files edited manually or by the
|
||||
shell tool.
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{!stats && (
|
||||
<Box>
|
||||
<Text color={theme.text.secondary}>No code changes to revert.</Text>
|
||||
{timestamp && (
|
||||
<Text color={theme.text.secondary}>
|
||||
{' '}
|
||||
({formatTimeAgo(timestamp)})
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Text>Select an action:</Text>
|
||||
<Text color={theme.text.secondary}>
|
||||
Use arrow keys to navigate, Enter to confirm, Esc to cancel.
|
||||
</Text>
|
||||
|
||||
<RadioButtonSelect
|
||||
items={options}
|
||||
onSelect={handleSelect}
|
||||
isFocused={true}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
||||
import { act } from 'react';
|
||||
import { renderWithProviders } from '../../test-utils/render.js';
|
||||
import { RewindViewer } from './RewindViewer.js';
|
||||
@@ -14,6 +14,11 @@ import type {
|
||||
MessageRecord,
|
||||
} from '@google/gemini-cli-core';
|
||||
|
||||
vi.mock('ink', async () => {
|
||||
const actual = await vi.importActual<typeof import('ink')>('ink');
|
||||
return { ...actual, useIsScreenReaderEnabled: vi.fn(() => false) };
|
||||
});
|
||||
|
||||
vi.mock('./CliSpinner.js', () => ({
|
||||
CliSpinner: () => 'MockSpinner',
|
||||
}));
|
||||
@@ -71,6 +76,35 @@ describe('RewindViewer', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Screen Reader Accessibility', () => {
|
||||
beforeEach(async () => {
|
||||
const { useIsScreenReaderEnabled } = await import('ink');
|
||||
vi.mocked(useIsScreenReaderEnabled).mockReturnValue(true);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
const { useIsScreenReaderEnabled } = await import('ink');
|
||||
vi.mocked(useIsScreenReaderEnabled).mockReturnValue(false);
|
||||
});
|
||||
|
||||
it('renders the rewind viewer with conversation items', async () => {
|
||||
const conversation = createConversation([
|
||||
{ type: 'user', content: 'Hello', id: '1', timestamp: '1' },
|
||||
]);
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<RewindViewer
|
||||
conversation={conversation}
|
||||
onExit={vi.fn()}
|
||||
onRewind={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Rewind');
|
||||
expect(lastFrame()).toContain('Hello');
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rendering', () => {
|
||||
it.each([
|
||||
{ name: 'nothing interesting for empty conversation', messages: [] },
|
||||
@@ -400,3 +434,31 @@ describe('RewindViewer', () => {
|
||||
unmount2();
|
||||
});
|
||||
});
|
||||
it('renders accessible screen reader view when screen reader is enabled', async () => {
|
||||
const { useIsScreenReaderEnabled } = await import('ink');
|
||||
vi.mocked(useIsScreenReaderEnabled).mockReturnValue(true);
|
||||
|
||||
const messages: MessageRecord[] = [
|
||||
{ type: 'user', content: 'Hello world', id: '1', timestamp: '1' },
|
||||
{ type: 'user', content: 'Second message', id: '2', timestamp: '2' },
|
||||
];
|
||||
const conversation = createConversation(messages);
|
||||
const onExit = vi.fn();
|
||||
const onRewind = vi.fn();
|
||||
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<RewindViewer
|
||||
conversation={conversation}
|
||||
onExit={onExit}
|
||||
onRewind={onRewind}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
const frame = lastFrame();
|
||||
expect(frame).toContain('Rewind - Select a conversation point:');
|
||||
expect(frame).toContain('Stay at current position');
|
||||
|
||||
vi.mocked(useIsScreenReaderEnabled).mockReturnValue(false);
|
||||
unmount();
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import type React from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { Box, Text, useIsScreenReaderEnabled } from 'ink';
|
||||
import { useUIState } from '../contexts/UIStateContext.js';
|
||||
import {
|
||||
type ConversationRecord,
|
||||
@@ -50,6 +50,7 @@ export const RewindViewer: React.FC<RewindViewerProps> = ({
|
||||
}) => {
|
||||
const [isRewinding, setIsRewinding] = useState(false);
|
||||
const { terminalWidth, terminalHeight } = useUIState();
|
||||
const isScreenReaderEnabled = useIsScreenReaderEnabled();
|
||||
const {
|
||||
selectedMessageId,
|
||||
getStats,
|
||||
@@ -128,7 +129,6 @@ export const RewindViewer: React.FC<RewindViewerProps> = ({
|
||||
5,
|
||||
terminalHeight - DIALOG_PADDING - HEADER_HEIGHT - CONTROLS_HEIGHT - 2,
|
||||
);
|
||||
|
||||
const maxItemsToShow = Math.max(1, Math.floor(listHeight / 4));
|
||||
|
||||
if (selectedMessageId) {
|
||||
@@ -182,6 +182,41 @@ export const RewindViewer: React.FC<RewindViewerProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (isScreenReaderEnabled) {
|
||||
return (
|
||||
<Box flexDirection="column" width={terminalWidth}>
|
||||
<Text bold>Rewind - Select a conversation point:</Text>
|
||||
<BaseSelectionList
|
||||
items={items}
|
||||
initialIndex={items.length - 1}
|
||||
isFocused={true}
|
||||
showNumbers={true}
|
||||
wrapAround={false}
|
||||
onSelect={(item: MessageRecord) => {
|
||||
if (item?.id) {
|
||||
if (item.id === 'current-position') {
|
||||
onExit();
|
||||
} else {
|
||||
selectMessage(item.id);
|
||||
}
|
||||
}
|
||||
}}
|
||||
renderItem={(itemWrapper) => {
|
||||
const item = itemWrapper.value;
|
||||
const text =
|
||||
item.id === 'current-position'
|
||||
? 'Stay at current position'
|
||||
: getCleanedRewindText(item);
|
||||
return <Text>{text}</Text>;
|
||||
}}
|
||||
/>
|
||||
<Text color={theme.text.secondary}>
|
||||
Press Esc to exit, Enter to select, arrow keys to navigate.
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
borderStyle="round"
|
||||
|
||||
@@ -4,17 +4,20 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, afterEach, vi } from 'vitest';
|
||||
import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest';
|
||||
import { renderWithProviders } from '../../test-utils/render.js';
|
||||
import { ShortcutsHelp } from './ShortcutsHelp.js';
|
||||
|
||||
describe('ShortcutsHelp', () => {
|
||||
const originalPlatform = process.platform;
|
||||
|
||||
beforeEach(() => vi.stubEnv('FORCE_GENERIC_KEYBINDING_HINTS', ''));
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
vi.unstubAllEnvs();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
@@ -52,10 +55,10 @@ describe('ShortcutsHelp', () => {
|
||||
},
|
||||
);
|
||||
|
||||
it('always shows Tab Tab focus UI shortcut', async () => {
|
||||
it('always shows Tab focus UI shortcut', async () => {
|
||||
const rendered = renderWithProviders(<ShortcutsHelp />);
|
||||
await rendered.waitUntilReady();
|
||||
expect(rendered.lastFrame()).toContain('Tab Tab');
|
||||
expect(rendered.lastFrame()).toContain('Tab focus UI');
|
||||
rendered.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,29 +10,41 @@ import { theme } from '../semantic-colors.js';
|
||||
import { isNarrowWidth } from '../utils/isNarrowWidth.js';
|
||||
import { SectionHeader } from './shared/SectionHeader.js';
|
||||
import { useUIState } from '../contexts/UIStateContext.js';
|
||||
import { Command } from '../../config/keyBindings.js';
|
||||
import { formatCommand } from '../utils/keybindingUtils.js';
|
||||
|
||||
type ShortcutItem = {
|
||||
key: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const buildShortcutItems = (): ShortcutItem[] => {
|
||||
const isMac = process.platform === 'darwin';
|
||||
const altLabel = isMac ? 'Option' : 'Alt';
|
||||
|
||||
return [
|
||||
{ key: '!', description: 'shell mode' },
|
||||
{ key: '@', description: 'select file or folder' },
|
||||
{ key: 'Esc Esc', description: 'clear & rewind' },
|
||||
{ key: 'Tab Tab', description: 'focus UI' },
|
||||
{ key: 'Ctrl+Y', description: 'YOLO mode' },
|
||||
{ key: 'Shift+Tab', description: 'cycle mode' },
|
||||
{ key: 'Ctrl+V', description: 'paste images' },
|
||||
{ key: `${altLabel}+M`, description: 'raw markdown mode' },
|
||||
{ key: 'Ctrl+R', description: 'reverse-search history' },
|
||||
{ key: 'Ctrl+X', description: 'open external editor' },
|
||||
];
|
||||
};
|
||||
const buildShortcutItems = (): ShortcutItem[] => [
|
||||
{ key: '!', description: 'shell mode' },
|
||||
{ key: '@', description: 'select file or folder' },
|
||||
{ key: formatCommand(Command.REWIND), description: 'clear & rewind' },
|
||||
{ key: formatCommand(Command.FOCUS_SHELL_INPUT), description: 'focus UI' },
|
||||
{ key: formatCommand(Command.TOGGLE_YOLO), description: 'YOLO mode' },
|
||||
{
|
||||
key: formatCommand(Command.CYCLE_APPROVAL_MODE),
|
||||
description: 'cycle mode',
|
||||
},
|
||||
{
|
||||
key: formatCommand(Command.PASTE_CLIPBOARD),
|
||||
description: 'paste images',
|
||||
},
|
||||
{
|
||||
key: formatCommand(Command.TOGGLE_MARKDOWN),
|
||||
description: 'raw markdown mode',
|
||||
},
|
||||
{
|
||||
key: formatCommand(Command.REVERSE_SEARCH),
|
||||
description: 'reverse-search history',
|
||||
},
|
||||
{
|
||||
key: formatCommand(Command.OPEN_EXTERNAL_EDITOR),
|
||||
description: 'open external editor',
|
||||
},
|
||||
];
|
||||
|
||||
const Shortcut: React.FC<{ item: ShortcutItem }> = ({ item }) => (
|
||||
<Box flexDirection="row">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
||||
import { render } from '../../test-utils/render.js';
|
||||
import { Text } from 'ink';
|
||||
import { StatusDisplay } from './StatusDisplay.js';
|
||||
@@ -54,6 +54,8 @@ const createMockUIState = (overrides: UIStateOverrides = {}): UIState =>
|
||||
backgroundShellCount: 0,
|
||||
buffer: { text: '' },
|
||||
history: [{ id: 1, type: 'user', text: 'test' }],
|
||||
sisyphusSecondsRemaining: null,
|
||||
a2aListenerPort: null,
|
||||
...overrides,
|
||||
}) as UIState;
|
||||
|
||||
@@ -171,4 +173,42 @@ describe('StatusDisplay', () => {
|
||||
expect(lastFrame()).toContain('Shells: 3');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders Sisyphus countdown timer when active', async () => {
|
||||
const uiState = createMockUIState({
|
||||
sisyphusSecondsRemaining: 65, // 01:05
|
||||
});
|
||||
const { lastFrame, unmount } = await renderStatusDisplay(
|
||||
{ hideContextSummary: false },
|
||||
uiState,
|
||||
);
|
||||
expect(lastFrame()).toContain('✦ Resuming work in 01:05');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders A2A listener port when active', async () => {
|
||||
const uiState = createMockUIState({
|
||||
a2aListenerPort: 8080,
|
||||
});
|
||||
const { lastFrame, unmount } = await renderStatusDisplay(
|
||||
{ hideContextSummary: false },
|
||||
uiState,
|
||||
);
|
||||
expect(lastFrame()).toContain('⚡ A2A :8080');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders both A2A port and Sisyphus timer together', async () => {
|
||||
const uiState = createMockUIState({
|
||||
a2aListenerPort: 3000,
|
||||
sisyphusSecondsRemaining: 120, // 02:00
|
||||
});
|
||||
const { lastFrame, unmount } = await renderStatusDisplay(
|
||||
{ hideContextSummary: false },
|
||||
uiState,
|
||||
);
|
||||
expect(lastFrame()).toContain('⚡ A2A :3000');
|
||||
expect(lastFrame()).toContain('✦ Resuming work in 02:00');
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import { Text } from 'ink';
|
||||
import { Box, Text } from 'ink';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
import { useUIState } from '../contexts/UIStateContext.js';
|
||||
import { useSettings } from '../contexts/SettingsContext.js';
|
||||
@@ -24,18 +24,42 @@ export const StatusDisplay: React.FC<StatusDisplayProps> = ({
|
||||
const settings = useSettings();
|
||||
const config = useConfig();
|
||||
|
||||
const items: React.ReactNode[] = [];
|
||||
|
||||
if (process.env['GEMINI_SYSTEM_MD']) {
|
||||
return <Text color={theme.status.error}>|⌐■_■|</Text>;
|
||||
items.push(<Text color={theme.status.error}>|⌐■_■|</Text>);
|
||||
}
|
||||
|
||||
if (
|
||||
uiState.activeHooks.length > 0 &&
|
||||
settings.merged.hooksConfig.notifications
|
||||
) {
|
||||
return <HookStatusDisplay activeHooks={uiState.activeHooks} />;
|
||||
items.push(<HookStatusDisplay activeHooks={uiState.activeHooks} />);
|
||||
}
|
||||
|
||||
if (!settings.merged.ui.hideContextSummary && !hideContextSummary) {
|
||||
if (uiState.a2aListenerPort !== null) {
|
||||
items.push(
|
||||
<Text color={theme.text.accent}>⚡ A2A :{uiState.a2aListenerPort}</Text>,
|
||||
);
|
||||
}
|
||||
|
||||
if (uiState.sisyphusSecondsRemaining !== null) {
|
||||
const mins = Math.floor(uiState.sisyphusSecondsRemaining / 60);
|
||||
const secs = uiState.sisyphusSecondsRemaining % 60;
|
||||
const timerStr = `${mins.toString().padStart(2, '0')}:${secs
|
||||
.toString()
|
||||
.padStart(2, '0')}`;
|
||||
items.push(
|
||||
<Text color={theme.text.accent}>✦ Resuming work in {timerStr}</Text>,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
items.length === 0 &&
|
||||
uiState.sisyphusSecondsRemaining === null &&
|
||||
!settings.merged.ui.hideContextSummary &&
|
||||
!hideContextSummary
|
||||
) {
|
||||
return (
|
||||
<ContextSummaryDisplay
|
||||
ideContext={uiState.ideContextState}
|
||||
@@ -51,5 +75,17 @@ export const StatusDisplay: React.FC<StatusDisplayProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
if (items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box flexDirection="row">
|
||||
{items.map((item, index) => (
|
||||
<Box key={index} marginRight={index < items.length - 1 ? 1 : 0}>
|
||||
{item}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -211,7 +211,7 @@ describe('Hint Visibility', () => {
|
||||
<ThemeDialog {...baseProps} settings={settings} />,
|
||||
{
|
||||
settings,
|
||||
uiState: { terminalBackgroundColor: '#1E1E2E' },
|
||||
uiState: { terminalBackgroundColor: '#000000' },
|
||||
},
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`ApprovalModeIndicator > renders correctly for AUTO_EDIT mode 1`] = `
|
||||
"auto-accept edits shift+tab to manual
|
||||
"auto-accept edits Shift+Tab to manual
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ApprovalModeIndicator > renders correctly for AUTO_EDIT mode with plan enabled 1`] = `
|
||||
"auto-accept edits shift+tab to plan
|
||||
"auto-accept edits Shift+Tab to plan
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ApprovalModeIndicator > renders correctly for DEFAULT mode 1`] = `
|
||||
"shift+tab to accept edits
|
||||
"Shift+Tab to accept edits
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ApprovalModeIndicator > renders correctly for DEFAULT mode with plan enabled 1`] = `
|
||||
"shift+tab to accept edits
|
||||
"Shift+Tab to accept edits
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ApprovalModeIndicator > renders correctly for PLAN mode 1`] = `
|
||||
"plan shift+tab to manual
|
||||
"plan Shift+Tab to manual
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ApprovalModeIndicator > renders correctly for YOLO mode 1`] = `
|
||||
"YOLO ctrl+y
|
||||
"YOLO Ctrl+Y
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -11,17 +11,6 @@ Enter to submit · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Choice question placeholder > uses default placeholder when not provided 2`] = `
|
||||
"Select your preferred language:
|
||||
|
||||
1. TypeScript
|
||||
2. JavaScript
|
||||
● 3. Enter a custom value
|
||||
|
||||
Enter to submit · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 1`] = `
|
||||
"Select your preferred language:
|
||||
|
||||
@@ -33,17 +22,6 @@ Enter to submit · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 2`] = `
|
||||
"Select your preferred language:
|
||||
|
||||
1. TypeScript
|
||||
2. JavaScript
|
||||
● 3. Type another language...
|
||||
|
||||
Enter to submit · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 1`] = `
|
||||
"Choose an option
|
||||
|
||||
@@ -58,20 +36,6 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 2`] = `
|
||||
"Choose an option
|
||||
|
||||
▲
|
||||
● 1. Option 1
|
||||
Description 1
|
||||
2. Option 2
|
||||
Description 2
|
||||
▼
|
||||
|
||||
Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 1`] = `
|
||||
"Choose an option
|
||||
|
||||
@@ -111,45 +75,6 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 2`] = `
|
||||
"Choose an option
|
||||
|
||||
● 1. Option 1
|
||||
Description 1
|
||||
2. Option 2
|
||||
Description 2
|
||||
3. Option 3
|
||||
Description 3
|
||||
4. Option 4
|
||||
Description 4
|
||||
5. Option 5
|
||||
Description 5
|
||||
6. Option 6
|
||||
Description 6
|
||||
7. Option 7
|
||||
Description 7
|
||||
8. Option 8
|
||||
Description 8
|
||||
9. Option 9
|
||||
Description 9
|
||||
10. Option 10
|
||||
Description 10
|
||||
11. Option 11
|
||||
Description 11
|
||||
12. Option 12
|
||||
Description 12
|
||||
13. Option 13
|
||||
Description 13
|
||||
14. Option 14
|
||||
Description 14
|
||||
15. Option 15
|
||||
Description 15
|
||||
16. Enter a custom value
|
||||
|
||||
Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Text type questions > renders text input for type: "text" 1`] = `
|
||||
"What should we name this component?
|
||||
|
||||
|
||||
@@ -27,33 +27,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > bubbles up Ctrl+C when feedback is empty while editing 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Type your feedback...
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 1`] = `
|
||||
"Overview
|
||||
|
||||
@@ -81,33 +54,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Add tests
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > displays error state when file read fails 1`] = `
|
||||
" Error reading plan: File not found
|
||||
"
|
||||
@@ -194,33 +140,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > bubbles up Ctrl+C when feedback is empty while editing 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Type your feedback...
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 1`] = `
|
||||
"Overview
|
||||
|
||||
@@ -248,33 +167,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Add tests
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > displays error state when file read fails 1`] = `
|
||||
" Error reading plan: File not found
|
||||
"
|
||||
|
||||
@@ -388,8 +388,17 @@ exports[`<HistoryItemDisplay /> > renders InfoMessage for "info" type with multi
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`<HistoryItemDisplay /> > thinking items > renders thinking item when enabled 1`] = `
|
||||
" Thinking
|
||||
exports[`<HistoryItemDisplay /> > thinking items > renders "Thinking..." header when isFirstThinking is true 1`] = `
|
||||
" Thinking...
|
||||
│
|
||||
│ Thinking
|
||||
│ test
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`<HistoryItemDisplay /> > thinking items > renders thinking item when enabled 1`] = `
|
||||
" │
|
||||
│ Thinking
|
||||
│ test
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -78,27 +78,6 @@ exports[`InputPrompt > mouse interaction > should toggle paste expansion on doub
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 4`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> [Pasted Text: 10 lines]
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 5`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> [Pasted Text: 10 lines]
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 6`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> [Pasted Text: 10 lines]
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > snapshots > should not show inverted cursor when shell is focused 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> Type your message or @path/to/file
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="326" viewBox="0 0 920 326">
|
||||
<style>
|
||||
text { font-family: Consolas, "Courier New", monospace; font-size: 14px; dominant-baseline: text-before-edge; white-space: pre; }
|
||||
</style>
|
||||
<rect width="920" height="326" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">ScrollableList </text>
|
||||
<text x="0" y="19" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">AppHeader(full) </text>
|
||||
<rect x="0" y="34" width="900" height="17" fill="#141414" />
|
||||
<text x="0" y="36" fill="#000000" textLength="900" lengthAdjust="spacingAndGlyphs">▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀</text>
|
||||
<rect x="0" y="51" width="9" height="17" fill="#141414" />
|
||||
<rect x="9" y="51" width="18" height="17" fill="#141414" />
|
||||
<text x="9" y="53" fill="#d7afff" textLength="18" lengthAdjust="spacingAndGlyphs">> </text>
|
||||
<rect x="27" y="51" width="135" height="17" fill="#141414" />
|
||||
<text x="27" y="53" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">Plan a solution</text>
|
||||
<rect x="162" y="51" width="738" height="17" fill="#141414" />
|
||||
<rect x="0" y="68" width="900" height="17" fill="#141414" />
|
||||
<text x="0" y="70" fill="#000000" textLength="900" lengthAdjust="spacingAndGlyphs">▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄</text>
|
||||
<text x="0" y="87" fill="#ffffff" textLength="117" lengthAdjust="spacingAndGlyphs" font-style="italic"> Thinking... </text>
|
||||
<text x="9" y="104" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="121" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="121" fill="#ffffff" textLength="144" lengthAdjust="spacingAndGlyphs" font-weight="bold" font-style="italic">Initial analysis</text>
|
||||
<text x="9" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="846" lengthAdjust="spacingAndGlyphs" font-style="italic">This is a multiple line paragraph for the first thinking message of how the model analyzes the</text>
|
||||
<text x="9" y="155" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="155" fill="#afafaf" textLength="72" lengthAdjust="spacingAndGlyphs" font-style="italic">problem.</text>
|
||||
<text x="9" y="172" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="189" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="189" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs" font-weight="bold" font-style="italic">Planning execution</text>
|
||||
<text x="9" y="206" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="206" fill="#afafaf" textLength="828" lengthAdjust="spacingAndGlyphs" font-style="italic">This a second multiple line paragraph for the second thinking message explaining the plan in</text>
|
||||
<text x="9" y="223" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="223" fill="#afafaf" textLength="468" lengthAdjust="spacingAndGlyphs" font-style="italic">detail so that it wraps around the terminal display.</text>
|
||||
<text x="9" y="240" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="257" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold" font-style="italic">Refining approach</text>
|
||||
<text x="9" y="274" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="274" fill="#afafaf" textLength="792" lengthAdjust="spacingAndGlyphs" font-style="italic">And finally a third multiple line paragraph for the third thinking message to refine the</text>
|
||||
<text x="9" y="291" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="291" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs" font-style="italic">solution.</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -151,3 +151,46 @@ AppHeader(full)
|
||||
Gemini message 2
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`MainContent > renders multiple thinking messages sequentially correctly 1`] = `
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> Plan a solution
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
Thinking...
|
||||
│
|
||||
│ Initial analysis
|
||||
│ This is a multiple line paragraph for the first thinking message of how the model analyzes the
|
||||
│ problem.
|
||||
│
|
||||
│ Planning execution
|
||||
│ This a second multiple line paragraph for the second thinking message explaining the plan in
|
||||
│ detail so that it wraps around the terminal display.
|
||||
│
|
||||
│ Refining approach
|
||||
│ And finally a third multiple line paragraph for the third thinking message to refine the
|
||||
│ solution.
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`MainContent > renders multiple thinking messages sequentially correctly 2`] = `
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> Plan a solution
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
Thinking...
|
||||
│
|
||||
│ Initial analysis
|
||||
│ This is a multiple line paragraph for the first thinking message of how the model analyzes the
|
||||
│ problem.
|
||||
│
|
||||
│ Planning execution
|
||||
│ This a second multiple line paragraph for the second thinking message explaining the plan in
|
||||
│ detail so that it wraps around the terminal display.
|
||||
│
|
||||
│ Refining approach
|
||||
│ And finally a third multiple line paragraph for the third thinking message to refine the
|
||||
│ solution."
|
||||
`;
|
||||
|
||||
@@ -4,142 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Enable Auto Update </text>
|
||||
<text x="837" y="257" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging </text>
|
||||
<text x="828" y="512" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#005f00" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#005f00" />
|
||||
<text x="828" y="155" fill="#d7ffd7" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="837" y="257" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,142 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Enable Auto Update </text>
|
||||
<text x="837" y="257" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging </text>
|
||||
<text x="828" y="512" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#005f00" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#005f00" />
|
||||
<text x="828" y="155" fill="#d7ffd7" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="837" y="257" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,140 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="702" height="17" fill="#394545" />
|
||||
<rect x="819" y="153" width="54" height="17" fill="#394545" />
|
||||
<text x="819" y="155" fill="#a6e3a1" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Enable Auto Update true* </text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging false* </text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="702" height="17" fill="#005f00" />
|
||||
<rect x="819" y="153" width="54" height="17" fill="#005f00" />
|
||||
<text x="819" y="155" fill="#d7ffd7" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="828" y="257" fill="#ffffff" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="819" y="512" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,142 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Enable Auto Update </text>
|
||||
<text x="837" y="257" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging </text>
|
||||
<text x="828" y="512" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#005f00" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#005f00" />
|
||||
<text x="828" y="155" fill="#d7ffd7" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="837" y="257" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,142 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Enable Auto Update </text>
|
||||
<text x="837" y="257" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging </text>
|
||||
<text x="828" y="512" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#005f00" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#005f00" />
|
||||
<text x="828" y="155" fill="#d7ffd7" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="837" y="257" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,134 +4,136 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="36" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#3d3f51" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="36" y="87" fill="#6c7086" textLength="144" lengthAdjust="spacingAndGlyphs">Search to filter</text>
|
||||
<text x="873" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#3d3f51" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="155" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Vim Mode </text>
|
||||
<text x="828" y="155" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Enable Auto Update </text>
|
||||
<text x="837" y="257" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging </text>
|
||||
<text x="828" y="512" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#878787" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="36" y="87" fill="#afafaf" textLength="144" lengthAdjust="spacingAndGlyphs">Search to filter</text>
|
||||
<text x="873" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#878787" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="155" fill="#ffffff" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<text x="828" y="155" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="837" y="257" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="597" fill="#ffffff" textLength="90" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Apply To</text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="18" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="18" lengthAdjust="spacingAndGlyphs">1.</text>
|
||||
<rect x="63" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="72" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="72" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="189" y="612" width="684" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> 2. Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> 3. System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="18" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="18" lengthAdjust="spacingAndGlyphs">1.</text>
|
||||
<rect x="63" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="72" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="72" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="189" y="612" width="684" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="18" lengthAdjust="spacingAndGlyphs">2.</text>
|
||||
<text x="72" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="18" lengthAdjust="spacingAndGlyphs">3.</text>
|
||||
<text x="72" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,141 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="702" height="17" fill="#394545" />
|
||||
<rect x="819" y="153" width="54" height="17" fill="#394545" />
|
||||
<text x="819" y="155" fill="#a6e3a1" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Enable Auto Update false* </text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging </text>
|
||||
<text x="828" y="512" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="702" height="17" fill="#005f00" />
|
||||
<rect x="819" y="153" width="54" height="17" fill="#005f00" />
|
||||
<text x="819" y="155" fill="#d7ffd7" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="819" y="257" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,142 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Enable Auto Update </text>
|
||||
<text x="837" y="257" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging </text>
|
||||
<text x="828" y="512" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#005f00" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#005f00" />
|
||||
<text x="828" y="155" fill="#d7ffd7" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="837" y="257" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -4,140 +4,142 @@
|
||||
</style>
|
||||
<rect width="920" height="751" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="2" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="19" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="36" fill="#ffffff" textLength="99" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Settings </text>
|
||||
<text x="891" y="36" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="36" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="206" fill="#ffffff" textLength="801" lengthAdjust="spacingAndGlyphs"> Default Approval Mode </text>
|
||||
<text x="810" y="206" fill="#6c7086" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#6c7086" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="257" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Enable Auto Update false* </text>
|
||||
<text x="891" y="257" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#6c7086" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="308" fill="#ffffff" textLength="819" lengthAdjust="spacingAndGlyphs"> Enable Notifications </text>
|
||||
<text x="828" y="308" fill="#6c7086" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#6c7086" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="359" fill="#ffffff" textLength="783" lengthAdjust="spacingAndGlyphs"> Plan Directory </text>
|
||||
<text x="792" y="359" fill="#6c7086" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#6c7086" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="410" fill="#ffffff" textLength="828" lengthAdjust="spacingAndGlyphs"> Plan Model Routing </text>
|
||||
<text x="837" y="410" fill="#6c7086" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#6c7086" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="461" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Max Chat Model Attempts </text>
|
||||
<text x="855" y="461" fill="#6c7086" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#6c7086" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="512" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Debug Keystroke Logging true* </text>
|
||||
<text x="891" y="512" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#6c7086" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="87" fill="#afafaf" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#d7ffd7" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="138" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="155" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#005f00" />
|
||||
<text x="45" y="155" fill="#d7ffd7" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#005f00" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#005f00" />
|
||||
<text x="828" y="155" fill="#d7ffd7" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="155" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#005f00" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#005f00" />
|
||||
<text x="45" y="172" fill="#afafaf" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#005f00" />
|
||||
<text x="891" y="172" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="206" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs">Default Approval Mode</text>
|
||||
<text x="810" y="206" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">Default</text>
|
||||
<text x="891" y="206" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="223" fill="#afafaf" textLength="738" lengthAdjust="spacingAndGlyphs">The default approval mode for tool execution. 'default' prompts for approval, 'au…</text>
|
||||
<text x="891" y="223" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="240" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Enable Auto Update</text>
|
||||
<text x="819" y="257" fill="#ffffff" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="257" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="274" fill="#afafaf" textLength="225" lengthAdjust="spacingAndGlyphs">Enable automatic updates.</text>
|
||||
<text x="891" y="274" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="291" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="308" fill="#ffffff" textLength="180" lengthAdjust="spacingAndGlyphs">Enable Notifications</text>
|
||||
<text x="828" y="308" fill="#afafaf" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="308" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="325" fill="#afafaf" textLength="756" lengthAdjust="spacingAndGlyphs">Enable run-event notifications for action-required prompts and session completion. …</text>
|
||||
<text x="891" y="325" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="342" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="359" fill="#ffffff" textLength="126" lengthAdjust="spacingAndGlyphs">Plan Directory</text>
|
||||
<text x="792" y="359" fill="#afafaf" textLength="81" lengthAdjust="spacingAndGlyphs">undefined</text>
|
||||
<text x="891" y="359" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="376" fill="#afafaf" textLength="720" lengthAdjust="spacingAndGlyphs">The directory where planning artifacts are stored. If not specified, defaults t…</text>
|
||||
<text x="891" y="376" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="393" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="410" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Plan Model Routing</text>
|
||||
<text x="837" y="410" fill="#afafaf" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="891" y="410" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="427" fill="#afafaf" textLength="765" lengthAdjust="spacingAndGlyphs">Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pr…</text>
|
||||
<text x="891" y="427" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="444" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="461" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Max Chat Model Attempts</text>
|
||||
<text x="855" y="461" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">10</text>
|
||||
<text x="891" y="461" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="478" fill="#afafaf" textLength="729" lengthAdjust="spacingAndGlyphs">Maximum number of attempts for requests to the main chat model. Cannot exceed 10.</text>
|
||||
<text x="891" y="478" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="495" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="512" fill="#ffffff" textLength="207" lengthAdjust="spacingAndGlyphs">Debug Keystroke Logging</text>
|
||||
<text x="828" y="512" fill="#ffffff" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="512" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="529" fill="#afafaf" textLength="450" lengthAdjust="spacingAndGlyphs">Enable debug logging of keystrokes to the console.</text>
|
||||
<text x="891" y="529" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="546" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="563" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">▼</text>
|
||||
<text x="891" y="563" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="580" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
<text x="891" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="648" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> System Settings </text>
|
||||
<text x="891" y="648" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#6c7086" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="597" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#005f00" />
|
||||
<text x="27" y="614" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#005f00" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#005f00" />
|
||||
<text x="45" y="614" fill="#d7ffd7" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#005f00" />
|
||||
<text x="891" y="614" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="631" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Workspace Settings</text>
|
||||
<text x="891" y="631" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="45" y="648" fill="#ffffff" textLength="135" lengthAdjust="spacingAndGlyphs">System Settings</text>
|
||||
<text x="891" y="648" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="665" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="27" y="682" fill="#afafaf" textLength="657" lengthAdjust="spacingAndGlyphs">(Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close)</text>
|
||||
<text x="891" y="682" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="699" fill="#878787" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="716" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
@@ -5,8 +5,8 @@ exports[`ShortcutsHelp > renders correctly in 'narrow' mode on 'linux' 1`] = `
|
||||
Shortcuts See /help for more
|
||||
! shell mode
|
||||
@ select file or folder
|
||||
Esc Esc clear & rewind
|
||||
Tab Tab focus UI
|
||||
Double Esc clear & rewind
|
||||
Tab focus UI
|
||||
Ctrl+Y YOLO mode
|
||||
Shift+Tab cycle mode
|
||||
Ctrl+V paste images
|
||||
@@ -21,8 +21,8 @@ exports[`ShortcutsHelp > renders correctly in 'narrow' mode on 'mac' 1`] = `
|
||||
Shortcuts See /help for more
|
||||
! shell mode
|
||||
@ select file or folder
|
||||
Esc Esc clear & rewind
|
||||
Tab Tab focus UI
|
||||
Double Esc clear & rewind
|
||||
Tab focus UI
|
||||
Ctrl+Y YOLO mode
|
||||
Shift+Tab cycle mode
|
||||
Ctrl+V paste images
|
||||
@@ -37,8 +37,8 @@ exports[`ShortcutsHelp > renders correctly in 'wide' mode on 'linux' 1`] = `
|
||||
Shortcuts See /help for more
|
||||
! shell mode Shift+Tab cycle mode Ctrl+V paste images
|
||||
@ select file or folder Ctrl+Y YOLO mode Alt+M raw markdown mode
|
||||
Esc Esc clear & rewind Ctrl+R reverse-search history Ctrl+X open external editor
|
||||
Tab Tab focus UI
|
||||
Double Esc clear & rewind Ctrl+R reverse-search history Ctrl+X open external editor
|
||||
Tab focus UI
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -47,7 +47,7 @@ exports[`ShortcutsHelp > renders correctly in 'wide' mode on 'mac' 1`] = `
|
||||
Shortcuts See /help for more
|
||||
! shell mode Shift+Tab cycle mode Ctrl+V paste images
|
||||
@ select file or folder Ctrl+Y YOLO mode Option+M raw markdown mode
|
||||
Esc Esc clear & rewind Ctrl+R reverse-search history Ctrl+X open external editor
|
||||
Tab Tab focus UI
|
||||
Double Esc clear & rewind Ctrl+R reverse-search history Ctrl+X open external editor
|
||||
Tab focus UI
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#ffffff" textLength="18" lengthAdjust="spacingAndGlyphs" font-weight="bold">ID</text>
|
||||
<text x="45" y="2" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs" font-weight="bold">Name</text>
|
||||
<text x="0" y="19" fill="#3d3f51" textLength="900" lengthAdjust="spacingAndGlyphs">────────────────────────────────────────────────────────────────────────────────────────────────────</text>
|
||||
<text x="0" y="36" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">1 Alice </text>
|
||||
<text x="0" y="53" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">2 Bob </text>
|
||||
<text x="0" y="19" fill="#878787" textLength="900" lengthAdjust="spacingAndGlyphs">────────────────────────────────────────────────────────────────────────────────────────────────────</text>
|
||||
<text x="0" y="36" fill="#ffffff" textLength="9" lengthAdjust="spacingAndGlyphs">1</text>
|
||||
<text x="45" y="36" fill="#ffffff" textLength="45" lengthAdjust="spacingAndGlyphs">Alice</text>
|
||||
<text x="0" y="53" fill="#ffffff" textLength="9" lengthAdjust="spacingAndGlyphs">2</text>
|
||||
<text x="45" y="53" fill="#ffffff" textLength="27" lengthAdjust="spacingAndGlyphs">Bob</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |