cinna-cli 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cinna_cli-0.2.4/.claude/commands/cinna-cli.feature.doc.md +174 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/PKG-INFO +37 -4
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/README.md +36 -3
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/docs/README.md +195 -7
- cinna_cli-0.2.4/docs/features/account_workspace/account_workspace.md +207 -0
- cinna_cli-0.2.4/docs/features/account_workspace/account_workspace_acceptance.md +287 -0
- cinna_cli-0.2.4/docs/features/account_workspace/account_workspace_tech.md +255 -0
- cinna_cli-0.2.4/docs/features/agent_api/agent_api.md +185 -0
- cinna_cli-0.2.4/docs/features/agent_api/agent_api_acceptance.md +224 -0
- cinna_cli-0.2.4/docs/features/agent_api/agent_api_tech.md +162 -0
- cinna_cli-0.2.4/docs/features/agent_management/agent_management.md +149 -0
- cinna_cli-0.2.4/docs/features/agent_management/agent_management_acceptance.md +232 -0
- cinna_cli-0.2.4/docs/features/agent_management/agent_management_tech.md +160 -0
- cinna_cli-0.2.4/docs/features/agent_schedules/agent_schedules.md +155 -0
- cinna_cli-0.2.4/docs/features/agent_schedules/agent_schedules_acceptance.md +218 -0
- cinna_cli-0.2.4/docs/features/agent_schedules/agent_schedules_tech.md +136 -0
- cinna_cli-0.2.4/docs/features/bootstrap_onboarding/bootstrap_onboarding.md +192 -0
- cinna_cli-0.2.4/docs/features/bootstrap_onboarding/bootstrap_onboarding_acceptance.md +239 -0
- cinna_cli-0.2.4/docs/features/bootstrap_onboarding/bootstrap_onboarding_tech.md +188 -0
- cinna_cli-0.2.4/docs/features/doctor/doctor.md +162 -0
- cinna_cli-0.2.4/docs/features/doctor/doctor_acceptance.md +263 -0
- cinna_cli-0.2.4/docs/features/doctor/doctor_tech.md +154 -0
- cinna_cli-0.2.4/docs/features/git_versioning/git_versioning.md +170 -0
- cinna_cli-0.2.4/docs/features/git_versioning/git_versioning_acceptance.md +264 -0
- cinna_cli-0.2.4/docs/features/git_versioning/git_versioning_tech.md +137 -0
- cinna_cli-0.2.4/docs/features/live_sync/live_sync.md +153 -0
- cinna_cli-0.2.4/docs/features/live_sync/live_sync_acceptance.md +234 -0
- cinna_cli-0.2.4/docs/features/live_sync/live_sync_tech.md +199 -0
- cinna_cli-0.2.4/docs/features/mcp_integration/mcp_integration.md +166 -0
- cinna_cli-0.2.4/docs/features/mcp_integration/mcp_integration_acceptance.md +192 -0
- cinna_cli-0.2.4/docs/features/mcp_integration/mcp_integration_tech.md +145 -0
- cinna_cli-0.2.4/docs/features/remote_chat/remote_chat.md +152 -0
- cinna_cli-0.2.4/docs/features/remote_chat/remote_chat_acceptance.md +221 -0
- cinna_cli-0.2.4/docs/features/remote_chat/remote_chat_tech.md +159 -0
- cinna_cli-0.2.4/docs/features/remote_exec/remote_exec.md +124 -0
- cinna_cli-0.2.4/docs/features/remote_exec/remote_exec_acceptance.md +183 -0
- cinna_cli-0.2.4/docs/features/remote_exec/remote_exec_tech.md +106 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/pyproject.toml +1 -1
- cinna_cli-0.2.4/scripts/check_docs_references.py +242 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/account.py +171 -26
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/bootstrap.py +161 -17
- cinna_cli-0.2.4/src/cinna/chat.py +476 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/client.py +187 -22
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/config.py +122 -2
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/context.py +67 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/doctor.py +195 -23
- cinna_cli-0.2.4/src/cinna/git_versioning.py +584 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/main.py +653 -68
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/templates/ACCOUNT_CLAUDE.md.template +14 -1
- cinna_cli-0.2.4/src/cinna/templates/CHAT_TESTING.md +56 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/templates/CLAUDE.md.template +6 -1
- cinna_cli-0.2.4/src/cinna/templates/GIT_VERSIONING.md +110 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_account.py +78 -6
- cinna_cli-0.2.4/tests/test_chat.py +406 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_config.py +21 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_context.py +51 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_doctor.py +143 -8
- cinna_cli-0.2.4/tests/test_git_versioning.py +539 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_main.py +33 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/uv.lock +1 -1
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/.github/workflows/publish.yml +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/.gitignore +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/LICENSE.md +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/docs/interface.md +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/docs/mutagen_capabilities.md +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/__init__.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/auth.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/console.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/errors.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/logging.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/mcp_proxy.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/mutagen_runtime.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/sync.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/sync_session.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/sync_ssh_shim.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/sync_tui.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/src/cinna/templates/__init__.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/__init__.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/conftest.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_auth.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_bootstrap.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_client.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_mutagen_runtime.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_sync.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_sync_session.py +0 -0
- {cinna_cli-0.2.2 → cinna_cli-0.2.4}/tests/test_sync_ssh_shim.py +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create or update cinna-cli feature documentation (business / tech / acceptance).
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## User Input
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
$ARGUMENTS
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Feature name, description, or existing doc path to create/refactor.
|
|
12
|
+
|
|
13
|
+
## Task
|
|
14
|
+
|
|
15
|
+
Create or refactor feature documentation under `docs/features/` following the
|
|
16
|
+
layered structure below. cinna-cli is a **Python CLI** (source in `src/cinna/`,
|
|
17
|
+
tests in `tests/`) that drives local agent development against a remote platform
|
|
18
|
+
API — there is no frontend/backend split to document. Keep that in mind: file
|
|
19
|
+
references point into `src/cinna/…` and `tests/…`, not `backend/`/`frontend/`.
|
|
20
|
+
|
|
21
|
+
**If given an existing doc path** — refactor it into the correct structure (split
|
|
22
|
+
into business / tech / acceptance files as needed, move under
|
|
23
|
+
`docs/features/{feature}/`).
|
|
24
|
+
**If given a feature name** — create new documentation by exploring the codebase
|
|
25
|
+
first (`src/cinna/`, the `cinna <group>` command surface in `src/cinna/main.py`,
|
|
26
|
+
relevant tests).
|
|
27
|
+
|
|
28
|
+
## Documentation Architecture
|
|
29
|
+
|
|
30
|
+
### Layer 1 — Project index (`docs/README.md`)
|
|
31
|
+
|
|
32
|
+
The single concise entry point: project purpose, glossary, architecture, command
|
|
33
|
+
surface, and a **Feature Registry** linking each documented feature to its folder.
|
|
34
|
+
When you create/update a feature doc, add/update its row in the registry.
|
|
35
|
+
|
|
36
|
+
### Layer 2 — Feature folders (`docs/features/{feature}/`)
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
docs/
|
|
40
|
+
├── README.md # Layer 1 — project index + feature registry
|
|
41
|
+
└── features/
|
|
42
|
+
└── {feature}/ # one folder per feature (snake_case)
|
|
43
|
+
├── {feature}.md # Layer 3a — business logic / reasoning (required)
|
|
44
|
+
├── {feature}_tech.md # Layer 3b — implementation, file refs (optional)
|
|
45
|
+
└── {feature}_acceptance.md # Layer 3c — real-usage e2e scenarios (optional)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Feature-folder naming: snake_case, descriptive (`git_versioning`, `live_sync`,
|
|
49
|
+
`remote_exec`, `account_workspace`, `remote_chat`).
|
|
50
|
+
|
|
51
|
+
### Layer 3 — Feature documentation files
|
|
52
|
+
|
|
53
|
+
#### 3a. Business logic: `{feature}.md`
|
|
54
|
+
|
|
55
|
+
Explains **WHAT** the feature does and **WHY**, from a product/user perspective.
|
|
56
|
+
A reader should understand purpose, flows, and rules without reading code.
|
|
57
|
+
|
|
58
|
+
Required sections:
|
|
59
|
+
1. **Purpose** — 1–2 sentences: what it does for the user.
|
|
60
|
+
2. **Mental model / core concepts** — key terms and the model the user must hold
|
|
61
|
+
(for cinna-cli, almost always: how local files, the remote container, and any
|
|
62
|
+
external system relate; what is local vs remote vs on-demand).
|
|
63
|
+
3. **User flows** — numbered steps for the main ways users interact (commands run,
|
|
64
|
+
what happens, what they see).
|
|
65
|
+
4. **Business rules** — constraints, state/lifecycle rules, guardrails, failure
|
|
66
|
+
semantics (what is *fail-loud*, what is auto vs manual, direction guards…).
|
|
67
|
+
5. **Architecture overview** — a simple text diagram of the component flow, e.g.
|
|
68
|
+
`cinna git <verb> → git_versioning.py → real git → remote`.
|
|
69
|
+
6. **Integration points** — how it connects to other features (link their docs).
|
|
70
|
+
|
|
71
|
+
Style: concise bullets, no code blocks, focus on behavior and reasoning.
|
|
72
|
+
|
|
73
|
+
#### 3b. Technical details: `{feature}_tech.md`
|
|
74
|
+
|
|
75
|
+
Deep-dive for developers: **HOW** it's implemented, with file references.
|
|
76
|
+
|
|
77
|
+
Required sections:
|
|
78
|
+
1. **File locations** — every `src/cinna/…` module + the tests that cover it.
|
|
79
|
+
2. **Command surface** — `cinna <group> <verb>` → the function in
|
|
80
|
+
`src/cinna/main.py` that implements it, one line each.
|
|
81
|
+
3. **Key functions & flow** — module path + function names with a brief purpose
|
|
82
|
+
(e.g. `src/cinna/git_versioning.py:link()` — the link sequence).
|
|
83
|
+
4. **Config & registry** — fields written to `.cinna/config.json` and
|
|
84
|
+
`~/.cinna/agents.json` (the latter referenced as a path, it's runtime state).
|
|
85
|
+
5. **External contracts** — platform API endpoints consumed, and any external
|
|
86
|
+
tool invoked (git, mutagen) with the exact invariants relied on.
|
|
87
|
+
6. **Edge cases & guardrails** — the non-obvious behaviors a maintainer must
|
|
88
|
+
preserve, each tied to the code that enforces it.
|
|
89
|
+
|
|
90
|
+
Style: heavy use of `src/cinna/file.py:function()` references. <!-- nocheck --> **No
|
|
91
|
+
code blocks** — only file/function references.
|
|
92
|
+
|
|
93
|
+
#### 3c. Acceptance scenarios: `{feature}_acceptance.md` — **the e2e test catalog**
|
|
94
|
+
|
|
95
|
+
The catalog of **real-usage scenarios** a testing agent executes against a *live*
|
|
96
|
+
environment (a real backend + real container + real external systems) — **not**
|
|
97
|
+
unit tests. This is what catches the bugs unit tests miss: conflicting pushes,
|
|
98
|
+
multi-agent layout collisions, registry drift across commands, tarball/commit
|
|
99
|
+
divergence, stale state across command sequences.
|
|
100
|
+
|
|
101
|
+
Write it so an autonomous agent can pick it up and run each scenario end-to-end.
|
|
102
|
+
|
|
103
|
+
Required sections:
|
|
104
|
+
1. **Preconditions** — what the agent needs: a live platform URL, an account
|
|
105
|
+
workspace or setup token, at least one (ideally two) agents configured for the
|
|
106
|
+
feature, any external accounts/credentials, and the editable install
|
|
107
|
+
(`which cinna` → repo `src/cinna`).
|
|
108
|
+
2. **Scenario catalog** — a numbered list. Each scenario has:
|
|
109
|
+
- **Goal** — the real user intent being exercised.
|
|
110
|
+
- **Setup** — starting state.
|
|
111
|
+
- **Steps** — the exact `cinna …` (and supporting `git`/`cinna exec`) commands.
|
|
112
|
+
- **Expected** — observable outcome (output text, file/remote/registry/env
|
|
113
|
+
state). Be specific enough to assert.
|
|
114
|
+
- **Watch for** — the failure modes / regressions this scenario is designed to
|
|
115
|
+
surface (the "why this scenario exists").
|
|
116
|
+
3. **Cross-cutting invariants** — properties that must hold across *all* scenarios
|
|
117
|
+
(e.g. credentials never committed; a command that re-writes the registry must
|
|
118
|
+
not drop another command's state; fail-loud, never silent-clobber).
|
|
119
|
+
4. **Cleanup** — how to leave the live environment tidy afterward.
|
|
120
|
+
|
|
121
|
+
Style: imperative, runnable. Real commands in fenced blocks are encouraged here
|
|
122
|
+
(unlike the other layers). Prefer scenarios grounded in actual runs — when a real
|
|
123
|
+
test discovers a defect, **add the scenario that reproduces it** so it becomes a
|
|
124
|
+
permanent regression check.
|
|
125
|
+
|
|
126
|
+
### Minimal documentation
|
|
127
|
+
|
|
128
|
+
Not every feature needs all three files. Start with `{feature}.md`. Add `_tech.md`
|
|
129
|
+
when implementation detail would clutter the business doc or spans many modules.
|
|
130
|
+
Add `_acceptance.md` when the feature has **real-environment behavior worth
|
|
131
|
+
exercising e2e** (anything touching sync, git, the container, schedules, or
|
|
132
|
+
multi-agent/multi-command state — i.e. most non-trivial cinna-cli features).
|
|
133
|
+
|
|
134
|
+
## Style rules
|
|
135
|
+
|
|
136
|
+
**DO**
|
|
137
|
+
- Use file refs: `src/cinna/git_versioning.py:link()`, `tests/test_git_versioning.py`
|
|
138
|
+
- Use command refs: `cinna git push` — push the agent branch (ff-only)
|
|
139
|
+
- Use endpoint refs: `GET /api/v1/cli/git-coordinates`
|
|
140
|
+
- Link related docs: `See [Live Sync](../live_sync/live_sync.md)` <!-- nocheck -->
|
|
141
|
+
- Concise bullets; simple text architecture diagrams
|
|
142
|
+
- In `_acceptance.md`, write real runnable commands
|
|
143
|
+
|
|
144
|
+
**DON'T**
|
|
145
|
+
- Put code snippets in `{feature}.md` / `{feature}_tech.md`
|
|
146
|
+
- Duplicate content between the business and tech files
|
|
147
|
+
- Reference container/home paths (`/app/workspace/…`, `~/.cinna/…`) as if repo
|
|
148
|
+
files — they are illustrative; the checker skips them, but be intentional
|
|
149
|
+
|
|
150
|
+
## Process
|
|
151
|
+
|
|
152
|
+
1. **Scope** — new feature doc or refactor of an existing one?
|
|
153
|
+
2. **Folder** — map to `docs/features/{feature}/`.
|
|
154
|
+
3. **Explore** — read the relevant `src/cinna/` modules, the `cinna` command
|
|
155
|
+
surface, and the covering tests.
|
|
156
|
+
4. **Write** — always `{feature}.md`; add `_tech.md` / `_acceptance.md` per the
|
|
157
|
+
rules above.
|
|
158
|
+
5. **Update `docs/README.md`** — add/refresh the Feature Registry entry.
|
|
159
|
+
6. **Validate references** — run the checker on the files you touched:
|
|
160
|
+
```
|
|
161
|
+
python3 scripts/check_docs_references.py --files docs/features/{feature}/{feature}.md docs/features/{feature}/{feature}_tech.md docs/features/{feature}/{feature}_acceptance.md
|
|
162
|
+
```
|
|
163
|
+
Fix every broken reference before finishing. For *illustrative* paths that are
|
|
164
|
+
not real repo files (container/home/convention paths), append `<!-- nocheck -->`
|
|
165
|
+
to that line.
|
|
166
|
+
7. **Run the test suite** — `pytest -q` must stay green (the docs describe shipped
|
|
167
|
+
behavior; if a doc claims behavior the tests don't cover, add or point to the
|
|
168
|
+
test).
|
|
169
|
+
|
|
170
|
+
## Output
|
|
171
|
+
|
|
172
|
+
Write to `docs/features/{feature}/`. Report what was created/updated, any old
|
|
173
|
+
files replaced (don't delete automatically — report them), the reference-check
|
|
174
|
+
result, and the test-suite status.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cinna-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Local development CLI for Cinna Core agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/opencinna/cinna-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/opencinna/cinna-cli
|
|
@@ -255,6 +255,30 @@ cinna api PATCH agents/3fa85f64-5717-4562-b3fc-2c963f66afa6 --json '{"descriptio
|
|
|
255
255
|
cinna api POST tasks --data @task.json
|
|
256
256
|
```
|
|
257
257
|
|
|
258
|
+
### `cinna chat [--agent <ref>] [--resume <session_id>] [--file PATH ...] [MESSAGE...]`
|
|
259
|
+
|
|
260
|
+
Talk to an agent through a **real platform session** — the same conversation pipeline production uses (permission checks, agent-env calls, the model/SDK the platform selects), not a local mock. Built for a local coding agent to test the agent it is building: it can prepare a prompt, attach files, and read the reply back as structured data.
|
|
261
|
+
|
|
262
|
+
Run it from the account workspace (or any synced agent folder under it). The reply is observed by **polling** the backend rather than reading a live stream, so it is robust to streaming/transport quirks.
|
|
263
|
+
|
|
264
|
+
- `--agent <name|slug|id>` picks the agent; omit it inside a synced agent workspace to infer it. `--resume <session_id>` continues an existing conversation instead of opening a new one (default mode for a new session is `conversation`; `--mode building` opens a building session).
|
|
265
|
+
- The message is the positional argument; if omitted it is read from stdin, or you are prompted for it interactively in a TTY.
|
|
266
|
+
- `--file PATH` (repeatable) uploads a local file and attaches it to the message.
|
|
267
|
+
- Output is **NDJSON** by default — one JSON event per line (`session`, `upload`, `message`, `status`, `done`), trivially parseable by another agent. `--pretty` switches to a human-readable transcript.
|
|
268
|
+
- Each `message` carries the agent's reasoning/tool trace under **`events`** — an ordered list of the `thinking` blocks, `tool` calls (with their full `tool_input` payload) and tool results behind the reply, so you see *what the agent did*, not just its final `content`. Pass `--no-events` to drop the trace and keep only the final text.
|
|
269
|
+
- Files the agent attaches to its replies are downloaded under `./cinna-chat-files/<session_id>/` (override with `--download-dir`, or skip with `--no-download` to just report the file ids). Downloads are bounded by the api-proxy's 8 MiB response cap.
|
|
270
|
+
- `--interval` / `--timeout` tune the poll cadence and the maximum wait for a turn. Ctrl-C interrupts the agent's turn and exits.
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
cinna chat --agent crm-agent "Summarize today's leads"
|
|
274
|
+
cinna chat --agent crm-agent --file report.csv "Validate this export"
|
|
275
|
+
cinna chat --resume 3fa85f64-5717-4562-b3fc-2c963f66afa6 "Now break it down by region"
|
|
276
|
+
echo "ping" | cinna chat --agent crm-agent # message from stdin
|
|
277
|
+
cinna chat --agent crm-agent "hi" | jq -c 'select(.event=="message")'
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The session id is printed in the first `session` event — capture it to drive a multi-turn conversation with `--resume`.
|
|
281
|
+
|
|
258
282
|
### `cinna dev`
|
|
259
283
|
|
|
260
284
|
Start a foreground dev session — creates / resumes the Mutagen sync session for this workspace and attaches the terminal to a two-tab TUI (status + raw Mutagen details). Ctrl-C terminates the session; sync does not outlive the TUI. To observe sync from another terminal without affecting it, use `cinna sync status`.
|
|
@@ -320,16 +344,25 @@ It detects and fixes:
|
|
|
320
344
|
- **Halted sessions** — sessions stopped on `halted-on-root-deletion` (the local `workspace/` root was deleted) while the agent dir is otherwise intact. Terminated; `cinna dev` recreates a clean one.
|
|
321
345
|
- **Dead-remote sessions** — sessions stuck retrying a remote env that no longer exists (`connecting-beta` / beta polling error). Mutagen has **no** "give up after N failures" option — a session retries forever until paused or terminated — so `doctor` is the cleanup path for these. Terminated.
|
|
322
346
|
- **Orphaned sessions** — `cinna-*` sessions with no registry entry at all. Terminated.
|
|
347
|
+
- **Active sessions** — the healthy, still-watching sessions left over from past `cinna dev` runs. They are not broken, but they keep the shared Mutagen daemon busy and are recreated on demand, so doctor offers to clear them as a separate step.
|
|
323
348
|
- **Expired tokens** — for **account-managed** workspaces (those under an account root), the CLI token is re-minted automatically through the parent account token, no pasting required. **Standalone** workspaces (set up via `cinna setup`) can only be refreshed with a pasted setup token, so they are reported with a `cinna set-token` hint rather than changed.
|
|
324
349
|
- **Expired account token** — a sub-agent token can only be re-minted while the **account** token that mints it is still valid. When the account token has itself expired, doctor probes it once and surfaces a single _"renew the account token — run `cinna login`"_ finding (listing the blocked sub-agents) instead of a pile of re-mints that would all fail with 401. Run `cinna login`, then re-run `cinna doctor` to re-mint the dependents.
|
|
325
350
|
|
|
326
351
|
```bash
|
|
327
|
-
cinna doctor # diagnose, then
|
|
352
|
+
cinna doctor # diagnose, then walk the repair steps (each defaults to Yes)
|
|
328
353
|
cinna doctor --dry-run # report problems only; change nothing
|
|
329
|
-
cinna doctor --yes #
|
|
354
|
+
cinna doctor --yes # accept every step non-interactively
|
|
330
355
|
```
|
|
331
356
|
|
|
332
|
-
|
|
357
|
+
`doctor` first prints the live `cinna-*` session inventory — each session tagged with the **agent** and **folder** it serves — so you can see what's running before deciding anything. Findings it can't fix itself (standalone expired tokens) are listed under **No automatic fix — manual action needed** and never touched.
|
|
358
|
+
|
|
359
|
+
The repair then runs as three ordered, independently-confirmed steps, each defaulting to **Yes**:
|
|
360
|
+
|
|
361
|
+
1. **Delete stalled sessions** — deleted-workspace cleanup plus halted / dead / orphaned session termination.
|
|
362
|
+
2. **Terminate active sessions** — clear the healthy leftovers from the inventory above (recreated on the next `cinna dev`).
|
|
363
|
+
3. **Refresh tokens** — re-mint expired account-managed tokens.
|
|
364
|
+
|
|
365
|
+
`--yes` accepts all three; `--dry-run` shows the tables and changes nothing.
|
|
333
366
|
|
|
334
367
|
### `cinna disconnect`
|
|
335
368
|
|
|
@@ -218,6 +218,30 @@ cinna api PATCH agents/3fa85f64-5717-4562-b3fc-2c963f66afa6 --json '{"descriptio
|
|
|
218
218
|
cinna api POST tasks --data @task.json
|
|
219
219
|
```
|
|
220
220
|
|
|
221
|
+
### `cinna chat [--agent <ref>] [--resume <session_id>] [--file PATH ...] [MESSAGE...]`
|
|
222
|
+
|
|
223
|
+
Talk to an agent through a **real platform session** — the same conversation pipeline production uses (permission checks, agent-env calls, the model/SDK the platform selects), not a local mock. Built for a local coding agent to test the agent it is building: it can prepare a prompt, attach files, and read the reply back as structured data.
|
|
224
|
+
|
|
225
|
+
Run it from the account workspace (or any synced agent folder under it). The reply is observed by **polling** the backend rather than reading a live stream, so it is robust to streaming/transport quirks.
|
|
226
|
+
|
|
227
|
+
- `--agent <name|slug|id>` picks the agent; omit it inside a synced agent workspace to infer it. `--resume <session_id>` continues an existing conversation instead of opening a new one (default mode for a new session is `conversation`; `--mode building` opens a building session).
|
|
228
|
+
- The message is the positional argument; if omitted it is read from stdin, or you are prompted for it interactively in a TTY.
|
|
229
|
+
- `--file PATH` (repeatable) uploads a local file and attaches it to the message.
|
|
230
|
+
- Output is **NDJSON** by default — one JSON event per line (`session`, `upload`, `message`, `status`, `done`), trivially parseable by another agent. `--pretty` switches to a human-readable transcript.
|
|
231
|
+
- Each `message` carries the agent's reasoning/tool trace under **`events`** — an ordered list of the `thinking` blocks, `tool` calls (with their full `tool_input` payload) and tool results behind the reply, so you see *what the agent did*, not just its final `content`. Pass `--no-events` to drop the trace and keep only the final text.
|
|
232
|
+
- Files the agent attaches to its replies are downloaded under `./cinna-chat-files/<session_id>/` (override with `--download-dir`, or skip with `--no-download` to just report the file ids). Downloads are bounded by the api-proxy's 8 MiB response cap.
|
|
233
|
+
- `--interval` / `--timeout` tune the poll cadence and the maximum wait for a turn. Ctrl-C interrupts the agent's turn and exits.
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
cinna chat --agent crm-agent "Summarize today's leads"
|
|
237
|
+
cinna chat --agent crm-agent --file report.csv "Validate this export"
|
|
238
|
+
cinna chat --resume 3fa85f64-5717-4562-b3fc-2c963f66afa6 "Now break it down by region"
|
|
239
|
+
echo "ping" | cinna chat --agent crm-agent # message from stdin
|
|
240
|
+
cinna chat --agent crm-agent "hi" | jq -c 'select(.event=="message")'
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The session id is printed in the first `session` event — capture it to drive a multi-turn conversation with `--resume`.
|
|
244
|
+
|
|
221
245
|
### `cinna dev`
|
|
222
246
|
|
|
223
247
|
Start a foreground dev session — creates / resumes the Mutagen sync session for this workspace and attaches the terminal to a two-tab TUI (status + raw Mutagen details). Ctrl-C terminates the session; sync does not outlive the TUI. To observe sync from another terminal without affecting it, use `cinna sync status`.
|
|
@@ -283,16 +307,25 @@ It detects and fixes:
|
|
|
283
307
|
- **Halted sessions** — sessions stopped on `halted-on-root-deletion` (the local `workspace/` root was deleted) while the agent dir is otherwise intact. Terminated; `cinna dev` recreates a clean one.
|
|
284
308
|
- **Dead-remote sessions** — sessions stuck retrying a remote env that no longer exists (`connecting-beta` / beta polling error). Mutagen has **no** "give up after N failures" option — a session retries forever until paused or terminated — so `doctor` is the cleanup path for these. Terminated.
|
|
285
309
|
- **Orphaned sessions** — `cinna-*` sessions with no registry entry at all. Terminated.
|
|
310
|
+
- **Active sessions** — the healthy, still-watching sessions left over from past `cinna dev` runs. They are not broken, but they keep the shared Mutagen daemon busy and are recreated on demand, so doctor offers to clear them as a separate step.
|
|
286
311
|
- **Expired tokens** — for **account-managed** workspaces (those under an account root), the CLI token is re-minted automatically through the parent account token, no pasting required. **Standalone** workspaces (set up via `cinna setup`) can only be refreshed with a pasted setup token, so they are reported with a `cinna set-token` hint rather than changed.
|
|
287
312
|
- **Expired account token** — a sub-agent token can only be re-minted while the **account** token that mints it is still valid. When the account token has itself expired, doctor probes it once and surfaces a single _"renew the account token — run `cinna login`"_ finding (listing the blocked sub-agents) instead of a pile of re-mints that would all fail with 401. Run `cinna login`, then re-run `cinna doctor` to re-mint the dependents.
|
|
288
313
|
|
|
289
314
|
```bash
|
|
290
|
-
cinna doctor # diagnose, then
|
|
315
|
+
cinna doctor # diagnose, then walk the repair steps (each defaults to Yes)
|
|
291
316
|
cinna doctor --dry-run # report problems only; change nothing
|
|
292
|
-
cinna doctor --yes #
|
|
317
|
+
cinna doctor --yes # accept every step non-interactively
|
|
293
318
|
```
|
|
294
319
|
|
|
295
|
-
|
|
320
|
+
`doctor` first prints the live `cinna-*` session inventory — each session tagged with the **agent** and **folder** it serves — so you can see what's running before deciding anything. Findings it can't fix itself (standalone expired tokens) are listed under **No automatic fix — manual action needed** and never touched.
|
|
321
|
+
|
|
322
|
+
The repair then runs as three ordered, independently-confirmed steps, each defaulting to **Yes**:
|
|
323
|
+
|
|
324
|
+
1. **Delete stalled sessions** — deleted-workspace cleanup plus halted / dead / orphaned session termination.
|
|
325
|
+
2. **Terminate active sessions** — clear the healthy leftovers from the inventory above (recreated on the next `cinna dev`).
|
|
326
|
+
3. **Refresh tokens** — re-mint expired account-managed tokens.
|
|
327
|
+
|
|
328
|
+
`--yes` accepts all three; `--dry-run` shows the tables and changes nothing.
|
|
296
329
|
|
|
297
330
|
### `cinna disconnect`
|
|
298
331
|
|
|
@@ -198,7 +198,8 @@ main.py (CLI commands — Click)
|
|
|
198
198
|
│
|
|
199
199
|
├── bootstrap.py — setup orchestration
|
|
200
200
|
├── account.py — account workspace; `cinna login` (device auth), `cinna account`, `cinna agent`
|
|
201
|
-
├── doctor.py — `cinna doctor`: reconcile registry ↔ Mutagen,
|
|
201
|
+
├── doctor.py — `cinna doctor`: reconcile registry ↔ Mutagen, delete stalled / terminate active sessions, refresh tokens
|
|
202
|
+
├── chat.py — `cinna chat`: session-backed conversation testing (poll + NDJSON) over the api-proxy
|
|
202
203
|
├── config.py — .cinna/config.json: load/save/find
|
|
203
204
|
├── auth.py — JWT storage, Authorization headers
|
|
204
205
|
├── client.py — PlatformClient: HTTP + SSE stream_exec
|
|
@@ -216,12 +217,21 @@ main.py (CLI commands — Click)
|
|
|
216
217
|
|
|
217
218
|
### Local Directory Layout
|
|
218
219
|
|
|
219
|
-
After `cinna setup` (agent name normalized, e.g. "HR Manager Agent" → `hr-manager-agent
|
|
220
|
+
After `cinna setup` (agent name normalized, e.g. "HR Manager Agent" → `hr-manager-agent`),
|
|
221
|
+
every new checkout uses the **Model-A nested layout** (`config.compute_agent_layout`):
|
|
222
|
+
a clone-root dir holds the agent at `<subdir>/`, so the folder is already shaped like
|
|
223
|
+
the agent's git repo whether or not Git Versioning is enabled (see "Git Versioning"
|
|
224
|
+
below). `<subdir>` defaults to the agent slug. If the clone-root dir `<slug>/` is
|
|
225
|
+
already taken by a **different** agent (two names normalizing to the same slug), the
|
|
226
|
+
clone root falls back to `<slug>-<shorthash>/` (the agent id's short hash) so the two
|
|
227
|
+
don't collide; re-running setup for the *same* agent still reports "already set up".
|
|
220
228
|
|
|
221
229
|
```
|
|
222
|
-
hr-manager-agent/ (
|
|
230
|
+
hr-manager-agent/ (clone root — becomes the git working tree once linked)
|
|
231
|
+
└── hr-manager-agent/ (workspace root == the repo's <subdir>/ node)
|
|
223
232
|
.cinna/
|
|
224
|
-
config.json (agent config, CLI token, mutagen_version pin)
|
|
233
|
+
config.json (agent config, CLI token, mutagen_version pin, git{} layout)
|
|
234
|
+
cinna.agent.json (backend-owned manifest; present once git-versioned)
|
|
225
235
|
workspace/ (continuously synced with remote /app/workspace)
|
|
226
236
|
scripts/ (bundle-owned — shipped in published revisions)
|
|
227
237
|
docs/ (bundle-owned)
|
|
@@ -249,13 +259,146 @@ Per-user global state (one copy, shared across every agent workspace):
|
|
|
249
259
|
|
|
250
260
|
```
|
|
251
261
|
~/.cinna/
|
|
252
|
-
agents.json (agent_id → {platform_url, cli_token, workspace_path
|
|
262
|
+
agents.json (agent_id → {platform_url, cli_token, workspace_path,
|
|
263
|
+
git?:{clone_path, subdir, repo_url, ref, …}}; 0600)
|
|
253
264
|
mutagen-ssh/
|
|
254
265
|
ssh (bash wrapper — execs cinna-sync-ssh; 0755)
|
|
255
266
|
```
|
|
256
267
|
|
|
257
268
|
---
|
|
258
269
|
|
|
270
|
+
## Feature Registry
|
|
271
|
+
|
|
272
|
+
Each feature is documented under `docs/features/{feature}/` as a layered set:
|
|
273
|
+
`{feature}.md` (business logic / reasoning), `{feature}_tech.md` (implementation +
|
|
274
|
+
file refs), and `{feature}_acceptance.md` (live e2e scenarios). See
|
|
275
|
+
[cinna-cli.feature.doc](../.claude/commands/cinna-cli.feature.doc.md) for the
|
|
276
|
+
authoring convention.
|
|
277
|
+
|
|
278
|
+
| Feature | Command surface | Docs |
|
|
279
|
+
|---|---|---|
|
|
280
|
+
| **Bootstrap & onboarding** | `cinna setup` / `set-token` / `login` / `list` / `status` / `disconnect[-all]` / `completion` / `dev` / `redev` | [business](features/bootstrap_onboarding/bootstrap_onboarding.md) · [tech](features/bootstrap_onboarding/bootstrap_onboarding_tech.md) · [acceptance](features/bootstrap_onboarding/bootstrap_onboarding_acceptance.md) |
|
|
281
|
+
| **Account workspace** | `cinna account` (setup, agents, status, refresh-context, user-workspace, credentials) | [business](features/account_workspace/account_workspace.md) · [tech](features/account_workspace/account_workspace_tech.md) · [acceptance](features/account_workspace/account_workspace_acceptance.md) |
|
|
282
|
+
| **Agent management** | `cinna agent` (sync, unsync, create, restart-env, show, status) | [business](features/agent_management/agent_management.md) · [tech](features/agent_management/agent_management_tech.md) · [acceptance](features/agent_management/agent_management_acceptance.md) |
|
|
283
|
+
| **Agent schedules** | `cinna agent schedule` (list, generate, create, update, run, logs, delete) | [business](features/agent_schedules/agent_schedules.md) · [tech](features/agent_schedules/agent_schedules_tech.md) · [acceptance](features/agent_schedules/agent_schedules_acceptance.md) |
|
|
284
|
+
| **Live sync** | `cinna sync` (status, conflicts, push, pull, resolve) + Mutagen transport | [business](features/live_sync/live_sync.md) · [tech](features/live_sync/live_sync_tech.md) · [acceptance](features/live_sync/live_sync_acceptance.md) |
|
|
285
|
+
| **Remote exec** | `cinna exec` | [business](features/remote_exec/remote_exec.md) · [tech](features/remote_exec/remote_exec_tech.md) · [acceptance](features/remote_exec/remote_exec_acceptance.md) |
|
|
286
|
+
| **Remote chat** | `cinna chat` | [business](features/remote_chat/remote_chat.md) · [tech](features/remote_chat/remote_chat_tech.md) · [acceptance](features/remote_chat/remote_chat_acceptance.md) |
|
|
287
|
+
| **Agent API** | `cinna agent-api` (enable, refresh, spec, call) · `cinna api` · `cinna connect agent-api` | [business](features/agent_api/agent_api.md) · [tech](features/agent_api/agent_api_tech.md) · [acceptance](features/agent_api/agent_api_acceptance.md) |
|
|
288
|
+
| **MCP integration** | `cinna connect mcp` · `cinna mcp-proxy` (knowledge stdio server) | [business](features/mcp_integration/mcp_integration.md) · [tech](features/mcp_integration/mcp_integration_tech.md) · [acceptance](features/mcp_integration/mcp_integration_acceptance.md) |
|
|
289
|
+
| **Git versioning** | `cinna git` (link, status, commit, push, pull, log, checkout, unlink) | [business](features/git_versioning/git_versioning.md) · [tech](features/git_versioning/git_versioning_tech.md) · [acceptance](features/git_versioning/git_versioning_acceptance.md) |
|
|
290
|
+
|
|
291
|
+
The sections below (Git Versioning, Sync Transport, Remote Exec, Remote Chat,
|
|
292
|
+
Bootstrap Flow) remain as in-README quick references and backend contracts; the
|
|
293
|
+
feature folders above are the authoritative deep dives.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Git Versioning
|
|
298
|
+
|
|
299
|
+
> Full feature docs: [git_versioning](features/git_versioning/git_versioning.md)
|
|
300
|
+
> (business logic), [_tech](features/git_versioning/git_versioning_tech.md)
|
|
301
|
+
> (implementation), [_acceptance](features/git_versioning/git_versioning_acceptance.md)
|
|
302
|
+
> (live e2e scenarios). This section is the quick reference + backend contract.
|
|
303
|
+
|
|
304
|
+
A git-versioned agent has **two independent sync layers** on the same folder:
|
|
305
|
+
**Mutagen** keeps `workspace/` mirrored to the running container in near-real-time
|
|
306
|
+
(it ignores `.git`), and **git** durably versions the same files against the agent's
|
|
307
|
+
external remote. They meet only at the remote. All git ops are local and run with the
|
|
308
|
+
developer's **own** git/SSH credentials — the platform's deploy key never reaches the
|
|
309
|
+
CLI. (The agent-facing version of this guidance is shipped into each checkout as the
|
|
310
|
+
on-demand `GIT_VERSIONING.md`, referenced conditionally from `CLAUDE.md`.)
|
|
311
|
+
|
|
312
|
+
Because new checkouts already use the Model-A nested layout, enabling Git Versioning
|
|
313
|
+
later needs no re-download or file move — just a link:
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
cinna git status # is this agent git-versioned? linked? working-tree status
|
|
317
|
+
cinna git link # init the clone, sparse-checkout <subdir>, fetch + reset --mixed
|
|
318
|
+
cinna git commit -m "…" [--push] # stage the subdir + commit (honors .gitignore)
|
|
319
|
+
cinna git push # fast-forward only; rejected pushes tell you to pull --rebase
|
|
320
|
+
cinna git pull # rebase the remote in; Mutagen mirrors it into the running env
|
|
321
|
+
cinna git log # recent commits touching this agent's subdir
|
|
322
|
+
cinna git checkout <ref> [--reload] # restore a past version's workspace/ files into
|
|
323
|
+
# the tree (uncommitted) + flush to the running env via Mutagen
|
|
324
|
+
# — debug/rollback without committing
|
|
325
|
+
cinna git unlink # stop offering git helpers (keeps .git + history)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
`cinna setup` / `cinna agent sync` auto-run `git link` when the agent is already
|
|
329
|
+
git-versioned, so the developer gets a working tree from the first checkout.
|
|
330
|
+
`--agent <ref>` targets a synced child from the account root (like `cinna sync`).
|
|
331
|
+
|
|
332
|
+
Key behaviors: `link` uses `git reset --mixed` (never `--hard`) so the backend's
|
|
333
|
+
in-flight changes survive as ordinary uncommitted edits; pushes are fast-forward-only
|
|
334
|
+
and never auto-forced; a `sync_direction=pull` agent refuses local pushes; and a legacy
|
|
335
|
+
*flat* workspace that becomes git-versioned is **not** auto-converted (link prints a
|
|
336
|
+
disconnect + re-sync instruction).
|
|
337
|
+
|
|
338
|
+
### Backend contract (cinna-core)
|
|
339
|
+
|
|
340
|
+
The CLI consumes one discovery endpoint; the agent is derived from the per-agent
|
|
341
|
+
token, so the path has **no `{agent_id}`**:
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
GET /api/v1/cli/git-coordinates (Auth: per-agent CLI JWT)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Response (`CliGitCoordinates` — `client.get_git_coordinates`, modelled by
|
|
348
|
+
`git_versioning.GitCoordinates`). `vcs_enabled=false` ⇒ all other fields null; a 404
|
|
349
|
+
(older backend) is treated as `vcs_enabled=false`:
|
|
350
|
+
|
|
351
|
+
```jsonc
|
|
352
|
+
{
|
|
353
|
+
"vcs_enabled": true, // false ⇒ agent has no git source
|
|
354
|
+
"repo_url": "git@github.com:acme/agents.git",
|
|
355
|
+
"subdir": "hr-bot", // null ⇒ agent lives at the repo root
|
|
356
|
+
"ref": "main",
|
|
357
|
+
"sync_direction": "bidirectional", // "pull" | "push" | "bidirectional"
|
|
358
|
+
"last_synced_commit": "a1b2c3…", // SHA the backend last imported/pushed; may be null
|
|
359
|
+
"auth_hint": "ssh" // "ssh" | "https" — which local cred the DEV needs
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
The remote repo stores each agent as the `schema_version`-2 bundle snapshot — this is
|
|
364
|
+
the layout `link` reconciles against (`reset --mixed` brings the manifest + `.gitignore`
|
|
365
|
+
from the ref; `workspace/**` stays the live copy):
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
<repo-root>/<subdir>/
|
|
369
|
+
├── cinna.agent.json # backend-owned manifest (prompts, SDK config, schedules,
|
|
370
|
+
│ # plugin specs, required_credential_specs, content_hash…)
|
|
371
|
+
├── workspace/ # the editable agent files (scripts/, docs/, …)
|
|
372
|
+
└── .gitignore # auto-generated; excludes credentials/, app-data/, logs/,
|
|
373
|
+
# databases/, uploads/, plugins-derived, __pycache__, *.pyc…
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Contract rules the CLI honors:
|
|
377
|
+
|
|
378
|
+
- **Two-writer, fast-forward-only.** Backend (deploy key) and developer (own creds)
|
|
379
|
+
push the same ref; both ff-only, no auto-merge. A rejected dev push ⇒ surface
|
|
380
|
+
`git pull --rebase`, never force.
|
|
381
|
+
- **Backend-owned manifest.** `cinna.agent.json` is regenerated by the backend from
|
|
382
|
+
the DB on every backend push/connect — the CLI commits it as-is and never invents
|
|
383
|
+
values (it lacks the DB/env inputs). Editing prompt **files** under
|
|
384
|
+
`workspace/docs/` flows back into the DB via the platform's prompt-sync.
|
|
385
|
+
- **Never committable** (the committed `.gitignore` + a local `.git/info/exclude`
|
|
386
|
+
enforce it; the CLI never `git add -f`): `credentials/`, `app-data/`, logs,
|
|
387
|
+
databases, `uploads/`, plugins-derived files, `__pycache__/`, `*.pyc`, plus the
|
|
388
|
+
CLI's own `.cinna/` (holds the token) and generated guides.
|
|
389
|
+
- **Deploy key is host-side only** and never leaves the backend; `git-coordinates`
|
|
390
|
+
deliberately omits all key material — the dev authenticates with their own
|
|
391
|
+
git/SSH (`auth_hint` only advises which).
|
|
392
|
+
- **Backend adoption of dev pushes.** After a dev push the backend is behind; it
|
|
393
|
+
adopts the change when the user clicks **Pull** on the agent's Git Versioning card
|
|
394
|
+
or via the configured GitOps webhook — the CLI cannot trigger it.
|
|
395
|
+
|
|
396
|
+
The backend half lives in cinna-core — see its `docs/agents/agent_git_versioning/` <!-- nocheck: cross-repo (cinna-core) path -->
|
|
397
|
+
plus `backend/app/api/routes/cli.py` (`CliGitCoordinates` / `_git_auth_hint`),
|
|
398
|
+
`GitSourceService`, and `SSHKeyService`; that repo owns the authoritative spec.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
259
402
|
## Sync Transport
|
|
260
403
|
|
|
261
404
|
### Wire path
|
|
@@ -356,6 +499,31 @@ To run an actual remote shell snippet (pipes, redirects, `&&`), pass it explicit
|
|
|
356
499
|
|
|
357
500
|
---
|
|
358
501
|
|
|
502
|
+
## Remote Chat (`cinna chat`)
|
|
503
|
+
|
|
504
|
+
`cinna chat` lets a local coding agent **test the agent it is building** by driving a real platform conversation session — exercising the production path (permission checks, agent-env calls, the model/SDK the platform selects) rather than a local mock. It lives in `chat.py` and runs entirely through the **account workspace's api-proxy** (`AccountClient`), so it needs an account workspace (`.cinna/account.json`) — found by walking up from the cwd, exactly like the other account verbs, so it works from a synced `agents/<slug>/` folder too.
|
|
505
|
+
|
|
506
|
+
### Why polling, not streaming
|
|
507
|
+
|
|
508
|
+
The platform's send-message route (`POST /sessions/{id}/messages/stream`) returns a **JSON ack immediately** and runs the agent turn asynchronously; the live events go out over a Socket.IO room *and* are persisted onto each message's `message_metadata.streaming_events`. The api-proxy is a buffered JSON hatch (it rejects `text/event-stream`), so `cinna chat` never reads the stream. Instead it:
|
|
509
|
+
|
|
510
|
+
1. Creates the session (`POST /sessions/`, mode `conversation` by default) — or resumes the one passed to `--resume`.
|
|
511
|
+
2. Uploads each `--file` and collects the returned file ids.
|
|
512
|
+
3. Records the current message count as a cursor, then sends the message (`file_ids` carry the attachments).
|
|
513
|
+
4. **Polls** `GET /sessions/{id}/messages?offset=<cursor>` (messages are ordered ascending by `sequence_number`, so `offset` is the cursor) and `GET …/messages/streaming-status` (`{is_streaming}`) until the turn settles — `is_streaming` false with no message flagged `streaming_in_progress`. A start-grace window covers env wake / queueing before the turn begins; an overall `--timeout` bounds the wait.
|
|
514
|
+
|
|
515
|
+
Each finalized message is emitted as one NDJSON line (`session` / `upload` / `message` / `status` / `done`); the in-progress assistant message is held back (its content is still growing) and emitted once final. Every `message` also carries the agent's reasoning/tool trace under **`events`** — the normalized `streaming_events` (thinking blocks, `tool` calls with their full `tool_input` payloads, tool results), with the bookkeeping/`attachment` entries stripped (attachments are surfaced separately). The final coalesced text stays in `content`; the trace shows *how* the agent got there. `--no-events` drops the trace; `--pretty` swaps NDJSON for a Rich transcript. Ctrl-C calls `POST …/messages/interrupt` and exits 130.
|
|
516
|
+
|
|
517
|
+
### Attachments
|
|
518
|
+
|
|
519
|
+
Agents attach workspace files to replies via `<cinna_attach>` tags; the backend materializes them and both injects an `attachment` streaming event (`metadata.file_id` / `filename` / `mime_type` / `size`) and lists them under the message's `files[]` with `source == "agent_attachment"`. `chat.py` collects attachments from the streaming events (preferred) with the `files[]` list as a replay fallback, dedups by file id, and downloads each via the proxy (`GET /files/{id}/download`) into `./cinna-chat-files/<session_id>/`. Because the proxy buffers the response, downloads are bounded by its **8 MiB** response cap; larger files surface a clear `PlatformError` instead of a partial write.
|
|
520
|
+
|
|
521
|
+
### File upload — the one dedicated route
|
|
522
|
+
|
|
523
|
+
The api-proxy is JSON-only and cannot carry a multipart body, and neither the account token nor a per-agent token may call `/files/upload` directly. So uploading a local attachment uses a dedicated account-CLI route, **`POST /api/v1/cli/account/files/upload`** (multipart, account-token auth), added alongside the other `/cli/account/*` routes; it creates a `File` owned by the account user and returns `FileUploadPublic` whose `id` goes into the message's `file_ids`. This is the only part of `cinna chat` that does not ride the api-proxy.
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
359
527
|
## Bootstrap Flow
|
|
360
528
|
|
|
361
529
|
```
|
|
@@ -404,7 +572,7 @@ When a CLI token expires (or is revoked) the normal remedy is `cinna set-token <
|
|
|
404
572
|
|
|
405
573
|
**Account tokens** refresh without a paste. `cinna login` (run inside an account workspace) drives the platform's RFC 8628 device-authorization flow: `POST /account/login/start` returns a short code + verification URL, the user clicks **Authorize** in the browser (already signed in), and the CLI polls `POST /account/login/poll` until it receives the fresh token, which it writes back into `.cinna/account.json` in place. The poll endpoint always returns HTTP 200 with a `status` field (`authorization_pending` / `slow_down` / `authorized` / `access_denied` / `expired_token`) — a deliberate divergence from RFC 8628's 400+`error` shape. Run from a fresh folder, the same command bootstraps a new account workspace instead of resuming one.
|
|
406
574
|
|
|
407
|
-
**Bulk repair** is `cinna doctor`. It reconciles the `~/.cinna/agents.json` registry against the Mutagen daemon and heals the state that drifts as agents come and go — registry entries whose workspace was deleted, sessions halted on a deleted local root or stuck retrying a dead remote env, and orphaned sessions (Mutagen has no "stop after N failures" knob, so these retry forever until terminated). Expired **per-agent** tokens under an account workspace are re-minted automatically through the parent account token; when the **account** token has itself expired, doctor groups the blocked agents into a single "run `cinna login`" finding instead of attempting re-mints that would 401. Standalone agents are reported for a manual `cinna set-token`.
|
|
575
|
+
**Bulk repair** is `cinna doctor`. It reconciles the `~/.cinna/agents.json` registry against the Mutagen daemon and heals the state that drifts as agents come and go — registry entries whose workspace was deleted, sessions halted on a deleted local root or stuck retrying a dead remote env, and orphaned sessions (Mutagen has no "stop after N failures" knob, so these retry forever until terminated). It prints the live `cinna-*` session inventory up front — each tagged with the agent and folder it serves — then walks three ordered, separately-confirmed steps (each defaulting to Yes): **delete stalled sessions**, **terminate active sessions** (the healthy leftovers, recreated on the next `cinna dev`), and **refresh tokens**. Expired **per-agent** tokens under an account workspace are re-minted automatically through the parent account token; when the **account** token has itself expired, doctor groups the blocked agents into a single "run `cinna login`" finding instead of attempting re-mints that would 401. Standalone agents are reported for a manual `cinna set-token`.
|
|
408
576
|
|
|
409
577
|
### Authorization
|
|
410
578
|
|
|
@@ -434,13 +602,18 @@ When a CLI token expires (or is revoked) the normal remedy is `cinna set-token <
|
|
|
434
602
|
| GET | `/api/v1/cli/agents/{id}/building-context` | CLI JWT | Assembled building prompt |
|
|
435
603
|
| POST | `/api/v1/cli/agents/{id}/knowledge/search` | CLI JWT | Knowledge base search (via MCP proxy) |
|
|
436
604
|
| GET | `/api/v1/cli/agents/{id}/sync-runtime` | CLI JWT | Required Mutagen version + hash (also used by `cinna list` / `cinna status` as a cheap token-validity probe) |
|
|
605
|
+
| GET | `/api/v1/cli/git-coordinates` | CLI JWT | Agent's git-versioning coordinates — **no `{id}`**, derived from the token (see "Git Versioning"). 404 on older backends ⇒ treated as not-versioned |
|
|
437
606
|
| POST | `/api/v1/cli/agents/{id}/exec` | CLI JWT | Streaming SSE command execution |
|
|
438
607
|
| WSS | `/api/v1/cli/agents/{id}/sync-stream` | CLI JWT | Mutagen transport tunnel |
|
|
439
608
|
| POST | `/api/v1/cli/account/login/start` | None | Begin a `cinna login` device-authorization request |
|
|
440
609
|
| POST | `/api/v1/cli/account/login/poll` | None | Poll a `cinna login` request — always HTTP 200 + `status` |
|
|
441
610
|
| POST | `/api/v1/cli/account/agents/{id}/mint` | Account token | Mint a per-agent CLI token (`cinna agent sync`, `cinna doctor` re-mint) |
|
|
611
|
+
| POST | `/api/v1/cli/account/api-proxy` | Account token | Buffered JSON escape hatch — `cinna api`, and the transport for every `cinna chat` session/message call |
|
|
612
|
+
| POST | `/api/v1/cli/account/files/upload` | Account token | Multipart upload for `cinna chat --file` (the proxy can't carry multipart) |
|
|
613
|
+
|
|
614
|
+
`cinna chat` reaches the conversation API **through** the api-proxy (so these are inner routes, not CLI routes): `POST /sessions/`, `GET /sessions/{id}`, `GET /sessions/{id}/messages`, `POST /sessions/{id}/messages/stream`, `GET /sessions/{id}/messages/streaming-status`, `POST /sessions/{id}/messages/interrupt`, and `GET /files/{id}/download`.
|
|
442
615
|
|
|
443
|
-
The account-workspace surface adds the broader `/api/v1/cli/account/*` route group (login, agents, credentials, connect, schedules, status, api-proxy); only the routes the sync / login / doctor paths use are listed here.
|
|
616
|
+
The account-workspace surface adds the broader `/api/v1/cli/account/*` route group (login, agents, credentials, connect, schedules, status, api-proxy, files/upload); only the routes the sync / login / doctor / chat paths use are listed here.
|
|
444
617
|
|
|
445
618
|
Endpoints that were part of the old Docker-replica model (`build-context`, `workspace` POST, `workspace/manifest`, `credentials`) have been removed from the backend and from this CLI.
|
|
446
619
|
|
|
@@ -528,6 +701,21 @@ git push origin main && git push origin v0.1.5
|
|
|
528
701
|
|
|
529
702
|
---
|
|
530
703
|
|
|
704
|
+
## Feature Documentation
|
|
705
|
+
|
|
706
|
+
Per-feature docs live under `docs/features/{feature}/` in up to three layers:
|
|
707
|
+
`{feature}.md` (business logic / reasoning), `{feature}_tech.md` (implementation +
|
|
708
|
+
file refs), `{feature}_acceptance.md` (live e2e scenarios a testing agent runs
|
|
709
|
+
against a real environment). Author new ones with the `/cinna-cli.feature.doc`
|
|
710
|
+
command (`.claude/commands/cinna-cli.feature.doc.md`) and validate references with
|
|
711
|
+
`scripts/check_docs_references.py`.
|
|
712
|
+
|
|
713
|
+
| Feature | Docs | Summary |
|
|
714
|
+
|---------|------|---------|
|
|
715
|
+
| Git Versioning (`cinna git`) | [business](features/git_versioning/git_versioning.md) · [tech](features/git_versioning/git_versioning_tech.md) · [acceptance](features/git_versioning/git_versioning_acceptance.md) | Version an agent's workspace with git against its external remote (commit/push/pull/rollback) alongside live Mutagen sync. |
|
|
716
|
+
|
|
717
|
+
---
|
|
718
|
+
|
|
531
719
|
## Related Projects
|
|
532
720
|
|
|
533
721
|
- **cinna-core** — the platform backend. Hosts the API routes this CLI calls, the agent runtime, env core, building mode, and the web UI. Source plan for this CLI feature: `cinna-core/docs/drafts/cinna-cli-live-sync_plan.md`.
|