pocket-coding 0.3.0__tar.gz → 0.4.0__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.
Files changed (99) hide show
  1. pocket_coding-0.4.0/LICENSE +4 -0
  2. pocket_coding-0.4.0/PKG-INFO +449 -0
  3. pocket_coding-0.4.0/README.md +424 -0
  4. pocket_coding-0.4.0/pocket_coding.egg-info/PKG-INFO +449 -0
  5. pocket_coding-0.4.0/pocket_coding.egg-info/SOURCES.txt +68 -0
  6. pocket_coding-0.4.0/pocket_coding.egg-info/dependency_links.txt +1 -0
  7. pocket_coding-0.4.0/pocket_coding.egg-info/entry_points.txt +2 -0
  8. pocket_coding-0.4.0/pocket_coding.egg-info/requires.txt +7 -0
  9. pocket_coding-0.4.0/pocket_coding.egg-info/top_level.txt +1 -0
  10. pocket_coding-0.4.0/poco/__init__.py +1 -0
  11. pocket_coding-0.4.0/poco/agent/__init__.py +1 -0
  12. pocket_coding-0.4.0/poco/agent/catalog.py +258 -0
  13. pocket_coding-0.4.0/poco/agent/runner.py +1414 -0
  14. pocket_coding-0.4.0/poco/cli.py +284 -0
  15. pocket_coding-0.4.0/poco/config.py +114 -0
  16. pocket_coding-0.4.0/poco/demo.py +9 -0
  17. pocket_coding-0.4.0/poco/interaction/__init__.py +1 -0
  18. pocket_coding-0.4.0/poco/interaction/card_dispatcher.py +101 -0
  19. pocket_coding-0.4.0/poco/interaction/card_handlers.py +1226 -0
  20. pocket_coding-0.4.0/poco/interaction/card_models.py +103 -0
  21. pocket_coding-0.4.0/poco/interaction/service.py +227 -0
  22. pocket_coding-0.4.0/poco/main.py +431 -0
  23. pocket_coding-0.4.0/poco/platform/__init__.py +1 -0
  24. pocket_coding-0.4.0/poco/platform/feishu/__init__.py +1 -0
  25. pocket_coding-0.4.0/poco/platform/feishu/card_gateway.py +207 -0
  26. pocket_coding-0.4.0/poco/platform/feishu/cards.py +1597 -0
  27. pocket_coding-0.4.0/poco/platform/feishu/client.py +282 -0
  28. pocket_coding-0.4.0/poco/platform/feishu/debug.py +90 -0
  29. pocket_coding-0.4.0/poco/platform/feishu/gateway.py +441 -0
  30. pocket_coding-0.4.0/poco/platform/feishu/longconn.py +300 -0
  31. pocket_coding-0.4.0/poco/platform/feishu/project_bootstrap.py +169 -0
  32. pocket_coding-0.4.0/poco/platform/feishu/verification.py +82 -0
  33. pocket_coding-0.4.0/poco/project/__init__.py +2 -0
  34. pocket_coding-0.4.0/poco/project/bootstrap.py +64 -0
  35. pocket_coding-0.4.0/poco/project/controller.py +172 -0
  36. pocket_coding-0.4.0/poco/project/models.py +103 -0
  37. pocket_coding-0.4.0/poco/session/controller.py +68 -0
  38. pocket_coding-0.4.0/poco/session/models.py +71 -0
  39. pocket_coding-0.4.0/poco/storage/__init__.py +1 -0
  40. pocket_coding-0.4.0/poco/storage/memory.py +108 -0
  41. pocket_coding-0.4.0/poco/storage/protocols.py +61 -0
  42. pocket_coding-0.4.0/poco/storage/sqlite.py +482 -0
  43. pocket_coding-0.4.0/poco/task/__init__.py +1 -0
  44. pocket_coding-0.4.0/poco/task/controller.py +405 -0
  45. pocket_coding-0.4.0/poco/task/dispatcher.py +123 -0
  46. pocket_coding-0.4.0/poco/task/models.py +174 -0
  47. pocket_coding-0.4.0/poco/task/notifier.py +296 -0
  48. pocket_coding-0.4.0/poco/task/rendering.py +61 -0
  49. pocket_coding-0.4.0/poco/workspace/controller.py +78 -0
  50. pocket_coding-0.4.0/poco/workspace/models.py +29 -0
  51. pocket_coding-0.4.0/pyproject.toml +52 -0
  52. pocket_coding-0.4.0/setup.cfg +4 -0
  53. pocket_coding-0.4.0/tests/test_agent_catalog.py +64 -0
  54. pocket_coding-0.4.0/tests/test_agent_runner.py +729 -0
  55. pocket_coding-0.4.0/tests/test_card_dispatcher.py +162 -0
  56. pocket_coding-0.4.0/tests/test_card_gateway.py +1372 -0
  57. pocket_coding-0.4.0/tests/test_cli.py +122 -0
  58. pocket_coding-0.4.0/tests/test_config.py +58 -0
  59. pocket_coding-0.4.0/tests/test_debug_api.py +74 -0
  60. pocket_coding-0.4.0/tests/test_demo_api.py +93 -0
  61. pocket_coding-0.4.0/tests/test_demo_cards.py +120 -0
  62. pocket_coding-0.4.0/tests/test_feishu_client.py +890 -0
  63. pocket_coding-0.4.0/tests/test_feishu_gateway.py +591 -0
  64. pocket_coding-0.4.0/tests/test_feishu_longconn.py +194 -0
  65. pocket_coding-0.4.0/tests/test_health.py +48 -0
  66. pocket_coding-0.4.0/tests/test_session_controller.py +52 -0
  67. pocket_coding-0.4.0/tests/test_state_persistence.py +131 -0
  68. pocket_coding-0.4.0/tests/test_task_controller.py +208 -0
  69. pocket_coding-0.4.0/tests/test_task_dispatcher.py +160 -0
  70. pocket_coding-0.4.0/tests/test_task_notifier.py +396 -0
  71. pocket_coding-0.3.0/.gitignore +0 -16
  72. pocket_coding-0.3.0/PKG-INFO +0 -129
  73. pocket_coding-0.3.0/README.md +0 -108
  74. pocket_coding-0.3.0/README.zh-CN.md +0 -110
  75. pocket_coding-0.3.0/poco/__init__.py +0 -4
  76. pocket_coding-0.3.0/poco/app.py +0 -124
  77. pocket_coding-0.3.0/poco/config/__init__.py +0 -59
  78. pocket_coding-0.3.0/poco/config/store.py +0 -507
  79. pocket_coding-0.3.0/poco/providers/__init__.py +0 -48
  80. pocket_coding-0.3.0/poco/providers/base.py +0 -54
  81. pocket_coding-0.3.0/poco/providers/claude.py +0 -400
  82. pocket_coding-0.3.0/poco/providers/codex.py +0 -367
  83. pocket_coding-0.3.0/poco/providers/cursor.py +0 -424
  84. pocket_coding-0.3.0/poco/providers/models.py +0 -73
  85. pocket_coding-0.3.0/poco/relay/__init__.py +0 -39
  86. pocket_coding-0.3.0/poco/relay/app.py +0 -1353
  87. pocket_coding-0.3.0/poco/relay/cards.py +0 -1452
  88. pocket_coding-0.3.0/poco/relay/messenger.py +0 -450
  89. pocket_coding-0.3.0/poco/relay/models.py +0 -110
  90. pocket_coding-0.3.0/poco/relay/runtime.py +0 -433
  91. pocket_coding-0.3.0/poco/relay/stores.py +0 -310
  92. pocket_coding-0.3.0/poco/relay/utils.py +0 -116
  93. pocket_coding-0.3.0/poco/runtime.py +0 -219
  94. pocket_coding-0.3.0/poco/tui/__init__.py +0 -5
  95. pocket_coding-0.3.0/poco/tui/app.py +0 -1119
  96. pocket_coding-0.3.0/poco/tui/resources.py +0 -192
  97. pocket_coding-0.3.0/poco/tui/sections.py +0 -219
  98. pocket_coding-0.3.0/poco/tui/state.py +0 -121
  99. pocket_coding-0.3.0/pyproject.toml +0 -46
@@ -0,0 +1,4 @@
1
+ All rights reserved.
2
+
3
+ This repository is not licensed for public redistribution, modification,
4
+ or commercial use unless explicitly permitted by the copyright holder.
@@ -0,0 +1,449 @@
1
+ Metadata-Version: 2.4
2
+ Name: pocket-coding
3
+ Version: 0.4.0
4
+ Summary: PoCo: pocket coding for server-side AI agents through mobile messaging entrypoints.
5
+ Author: Yihanc
6
+ Keywords: ai-agent,automation,developer-tools,feishu,mobile
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Framework :: FastAPI
14
+ Classifier: Topic :: Software Development :: Build Tools
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: fastapi<1.0,>=0.115
19
+ Requires-Dist: lark-oapi<2.0,>=1.5
20
+ Requires-Dist: uvicorn<1.0,>=0.32
21
+ Provides-Extra: dev
22
+ Requires-Dist: build<2.0,>=1.2; extra == "dev"
23
+ Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
24
+ Dynamic: license-file
25
+
26
+ # PoCo
27
+
28
+ PoCo is a Python-first MVP scaffold for controlling server-side AI agent workflows from mobile messaging entrypoints.
29
+
30
+ ## Quick Start
31
+
32
+ Install from source:
33
+
34
+ ```bash
35
+ python3 -m pip install -e .
36
+ poco config
37
+ poco start
38
+ ```
39
+
40
+ Then verify:
41
+
42
+ ```bash
43
+ poco status
44
+ ```
45
+
46
+ When published, the install command should be:
47
+
48
+ ```bash
49
+ python3 -m pip install pocket-coding
50
+ ```
51
+
52
+ ## Current Scope
53
+
54
+ - `FastAPI` webhook service
55
+ - Feishu-first event gateway
56
+ - Optional Feishu long-connection intake for local development
57
+ - Feishu callback verification token support
58
+ - Feishu tenant access token retrieval and text / interactive card send support
59
+ - Card-first interaction scaffolding with platform-neutral dispatcher
60
+ - Codex-first agent execution path
61
+ - Asynchronous background task dispatch
62
+ - Feishu task-state push on confirmation wait and terminal states
63
+ - Platform-independent task controller
64
+ - In-memory task state store
65
+ - Stub fallback runner for flow validation
66
+
67
+ ## Local Run
68
+
69
+ ### Install CLI
70
+
71
+ Install PoCo once in editable mode so the `poco` command is available:
72
+
73
+ ```bash
74
+ python3 -m pip install -e .
75
+ ```
76
+
77
+ ### Lowest-Friction Start
78
+
79
+ If you only want to verify that PoCo itself can run on this machine, you can start with no Feishu credentials at all:
80
+
81
+ ```bash
82
+ poco start
83
+ curl http://127.0.0.1:8000/health
84
+ ```
85
+
86
+ In that mode:
87
+
88
+ - PoCo runs in local/demo mode
89
+ - the agent backend can still be checked
90
+ - you can still use the local demo HTTP interface
91
+ - Feishu callback handling is not ready yet
92
+
93
+ The `/health` response will tell you exactly what is missing.
94
+
95
+ ### Local Demo Interface
96
+
97
+ You can exercise the full command flow without Feishu:
98
+
99
+ ```bash
100
+ curl -X POST http://127.0.0.1:8000/demo/command \
101
+ -H 'Content-Type: application/json' \
102
+ -d '{"text":"/run Reply with exactly: DEMO_OK"}'
103
+ ```
104
+
105
+ Check task status:
106
+
107
+ ```bash
108
+ curl http://127.0.0.1:8000/tasks/<task_id>
109
+ ```
110
+
111
+ Approval flow example:
112
+
113
+ ```bash
114
+ curl -X POST http://127.0.0.1:8000/demo/command \
115
+ -H 'Content-Type: application/json' \
116
+ -d '{"text":"/run confirm: Reply with exactly: APPROVED"}'
117
+
118
+ curl -X POST http://127.0.0.1:8000/demo/tasks/<task_id>/approve
119
+ ```
120
+
121
+ PoCo currently plans to support:
122
+
123
+ - Codex
124
+ - Claude Code
125
+ - Cursor Agent
126
+
127
+ Current implementation priority is Codex, and the default backend is `codex`.
128
+
129
+ Normal user-facing setup should not require agent-specific shell configuration.
130
+ In the intended product flow:
131
+
132
+ - users only need to configure the Feishu bot and start the PoCo service
133
+ - project backend is chosen in the DM project-creation card
134
+ - backend-specific settings are changed later through Feishu cards
135
+
136
+ The environment variables below are only server-side defaults and debugging overrides.
137
+ They are not part of the intended end-user setup flow.
138
+
139
+ Minimum server-side agent configuration:
140
+
141
+ ```bash
142
+ export POCO_AGENT_BACKEND="codex"
143
+ export POCO_CODEX_COMMAND="codex"
144
+ export POCO_CODEX_WORKDIR="/absolute/path/to/your/repo"
145
+ ```
146
+
147
+ Optional server-side defaults for Codex:
148
+
149
+ ```bash
150
+ export POCO_CODEX_MODEL="gpt-5.4"
151
+ export POCO_CODEX_SANDBOX="workspace-write"
152
+ export POCO_CODEX_APPROVAL_POLICY="never"
153
+ export POCO_CODEX_TIMEOUT_SECONDS="900"
154
+ ```
155
+
156
+ PoCo now runs the `codex` backend through `codex app-server` over stdio, so task cards can consume true `agentMessage/delta` events instead of waiting for a final `exec --json` message block.
157
+
158
+ Optional server-side defaults for Claude Code:
159
+
160
+ ```bash
161
+ export POCO_CLAUDE_COMMAND="claude"
162
+ export POCO_CLAUDE_WORKDIR="/absolute/path/to/your/repo"
163
+ export POCO_CLAUDE_MODEL="sonnet"
164
+ export POCO_CLAUDE_PERMISSION_MODE="default"
165
+ export POCO_CLAUDE_TIMEOUT_SECONDS="900"
166
+ ```
167
+
168
+ Optional server-side defaults for Cursor Agent:
169
+
170
+ ```bash
171
+ export POCO_CURSOR_COMMAND="cursor-agent"
172
+ export POCO_CURSOR_WORKDIR="/absolute/path/to/your/repo"
173
+ export POCO_CURSOR_MODEL="gpt-5"
174
+ export POCO_CURSOR_MODE="default"
175
+ export POCO_CURSOR_SANDBOX="default"
176
+ export POCO_CURSOR_TIMEOUT_SECONDS="900"
177
+ ```
178
+
179
+ Use `POCO_AGENT_BACKEND=stub` only for local flow validation without a real agent backend.
180
+
181
+ PoCo now supports `codex`, `claude_code`, and `cursor_agent`. `coco` is still recognized as planned but not implemented yet.
182
+
183
+ ### Normal User Flow
184
+
185
+ The intended startup path is now:
186
+
187
+ ```bash
188
+ poco config
189
+ poco start
190
+ ```
191
+
192
+ `poco config` prompts for:
193
+
194
+ - Feishu App ID
195
+ - Feishu App Secret
196
+
197
+ PoCo stores them in a local user config file under `~/.poco/poco.config.json`, so normal users do not need to export shell variables.
198
+
199
+ PoCo now defaults to Feishu `longconn`, so the normal local/mobile-first path does not require setting an inbound delivery mode explicitly. Only set `POCO_FEISHU_DELIVERY_MODE` if you intentionally want to force `webhook`.
200
+
201
+ Useful lifecycle commands:
202
+
203
+ ```bash
204
+ poco status
205
+ poco shutdown
206
+ poco restart
207
+ ```
208
+
209
+ ### Packaging
210
+
211
+ Build release artifacts locally:
212
+
213
+ ```bash
214
+ python3 -m pip install build
215
+ python3 -m build
216
+ ```
217
+
218
+ This produces:
219
+
220
+ - `dist/*.whl`
221
+ - `dist/*.tar.gz`
222
+
223
+ Advanced server-side overrides only:
224
+
225
+ ```bash
226
+ export POCO_FEISHU_API_BASE_URL="https://open.feishu.cn"
227
+ export POCO_FEISHU_VERIFICATION_TOKEN="xxx"
228
+ export POCO_FEISHU_ENCRYPT_KEY="xxx"
229
+ export POCO_STATE_BACKEND="sqlite"
230
+ export POCO_STATE_DB_PATH="/absolute/path/to/poco.db"
231
+ ```
232
+
233
+ Notes:
234
+
235
+ - `POCO_FEISHU_VERIFICATION_TOKEN` is optional in the current MVP. Leaving it unset reduces setup friction, but also lowers webhook security.
236
+ - If `POCO_FEISHU_ENCRYPT_KEY` is configured, the service expects Feishu signature headers and validates them.
237
+ - Encrypted callback payload bodies are not supported yet, so keep event encryption disabled for the current MVP.
238
+ - `longconn` is now the default inbound mode and removes the need for public inbound webhook access during local development.
239
+ - The current long-connection implementation now handles both `im.message.receive_v1` and card callback traffic for local/mobile-first operation.
240
+ - Callback token/signature settings apply to webhook delivery. Feishu long-connection inbound events are authenticated by the long-connection session itself.
241
+ - `POCO_STATE_BACKEND=sqlite` is now the default runtime path. PoCo persists projects, workspace state and tasks so restart does not lose existing group/workspace tracking.
242
+ - `POCO_STATE_DB_PATH` defaults to `~/.poco/poco.db`.
243
+
244
+ Manual fallback start:
245
+
246
+ ```bash
247
+ uvicorn poco.main:app --reload
248
+ ```
249
+
250
+ Health check:
251
+
252
+ ```bash
253
+ curl http://127.0.0.1:8000/health
254
+ ```
255
+
256
+ The health response now includes:
257
+
258
+ - current runtime mode: `local` or `feishu`
259
+ - chosen Feishu delivery mode: `webhook` or `longconn`
260
+ - chosen agent backend and whether it looks ready
261
+ - whether the Feishu long-connection listener is actually ready
262
+ - which state backend is in use
263
+ - whether Feishu callback token verification is enabled
264
+ - whether Feishu signature validation is enabled
265
+ - what is still missing
266
+ - warnings about relaxed safety settings
267
+
268
+ ### Card Demo Interface
269
+
270
+ You can now exercise the first DM card chain locally:
271
+
272
+ ```bash
273
+ curl http://127.0.0.1:8000/demo/cards/dm/projects
274
+ ```
275
+
276
+ Create a project through the demo card-action endpoint:
277
+
278
+ ```bash
279
+ curl -X POST http://127.0.0.1:8000/demo/card-actions \
280
+ -H 'Content-Type: application/json' \
281
+ -d '{
282
+ "event": {
283
+ "operator": {"open_id": "ou_demo_user"},
284
+ "context": {"open_message_id": "om_demo_card"},
285
+ "action": {
286
+ "value": {
287
+ "intent_key": "project.create",
288
+ "surface": "dm",
289
+ "request_id": "req_demo_project_create_1"
290
+ },
291
+ "form_value": {
292
+ "name": "PoCo",
293
+ "backend": "codex"
294
+ }
295
+ }
296
+ }
297
+ }'
298
+ ```
299
+
300
+ This currently proves the first card chain:
301
+
302
+ - DM card action payload -> `ActionIntent`
303
+ - dispatcher -> project handler
304
+ - `IntentDispatchResult` -> render instruction
305
+ - renderer -> card response payload
306
+
307
+ Real Feishu DM bootstrap is now also wired:
308
+
309
+ - when PoCo receives a DM message event from Feishu
310
+ - it replies with a real Feishu card JSON 2.0 project-list card
311
+ - the project-list card now contains real callback buttons such as `Create Project + Group`
312
+ - `Create Project + Group` now creates the project and, in real Feishu mode, bootstraps a dedicated group chat in the same action
313
+ - after the group is created, PoCo also posts the first workspace overview card into that group
314
+ - opening a project in DM now lands on a `Project Config` card instead of a bare detail card
315
+ - current group chats still keep the text-command fallback path
316
+
317
+ That means the current interaction split is:
318
+
319
+ - `DM`: control-plane card bootstrap and first project-management actions
320
+ - `Group`: first workspace overview card plus text-command task fallback
321
+
322
+ Notes about project bootstrap:
323
+
324
+ - in real Feishu mode, `project.create` now calls the Feishu group-create API and binds the returned `chat_id` to the new project
325
+ - after binding the group, PoCo best-effort posts the first workspace overview card into the new group
326
+ - if group bootstrap fails, PoCo rolls the project creation back instead of leaving a half-created project behind
327
+ - in local/demo mode without Feishu credentials, `project.create` still works, but no group is created
328
+
329
+ ### Feishu Debug Snapshot
330
+
331
+ When Feishu messages do not get any reply, inspect:
332
+
333
+ ```bash
334
+ curl http://127.0.0.1:8000/debug/feishu
335
+ ```
336
+
337
+ It shows:
338
+
339
+ - recent inbound Feishu callbacks
340
+ - the reply target PoCo selected for each callback
341
+ - recent outbound send attempts, including DM card sends
342
+ - recent Feishu send errors
343
+ - current long-connection listener status
344
+
345
+ This is the fastest way to tell whether the problem is:
346
+
347
+ - Feishu never called PoCo
348
+ - PoCo picked the wrong reply target
349
+ - PoCo tried to send but Feishu rejected the request
350
+
351
+ Real Feishu callbacks should target:
352
+
353
+ ```text
354
+ POST /platform/feishu/events
355
+ ```
356
+
357
+ Card action callbacks should currently target:
358
+
359
+ ```text
360
+ POST /platform/feishu/card-actions
361
+ ```
362
+
363
+ Current interaction model:
364
+
365
+ - DM messages currently bootstrap a compact home card instead of returning text help
366
+ - DM home cards now expose only `New` and `Manage`
367
+ - DM `New` now uses a pure-card form to collect `project name`, then creates the project and group before returning to the DM home card
368
+ - DM `Manage` now focuses on destructive admin actions; projects can be deleted there without opening a project detail card first, and deletion now cascades through local project state in sqlite/in-memory stores
369
+ - newly created project groups now receive an initial workspace overview card
370
+ - group workspace and task cards now keep `Working Dir` selection inside Feishu cards, with both folder browsing and manual path entry
371
+ - group workspace cards are now intentionally compact: workspace metadata is collapsed into the title, and the body keeps only `Stop`, `Working Dir`, and `Agent`
372
+ - `Agent` now opens a dedicated agent-selection card; applying agent settings returns to the main workspace card
373
+ - working dir selection now stays inside Feishu cards; no browser page is required
374
+ - `Use Default` now updates the in-memory workspace context and becomes the first real write path for group-side workdir state
375
+ - `Enter Path` now updates the same in-memory workspace context and becomes the second real write path, using manual source
376
+ - DM `Manage Dir Presets` can now add project-level presets, and group `Choose Preset` can apply them into the current in-memory workspace context
377
+ - Group text `/run` now resolves the bound project and current workspace workdir, then stamps that into task execution context
378
+ - Bound group workspaces now also treat ordinary plain-text messages as task prompts by default
379
+ - Bound group workspaces now run tasks in a single-project queue: if one task is still active, the next message is queued instead of starting a parallel Codex run
380
+ - codex-backed groups now persist the upstream Codex thread id and resume it through `codex app-server`, so follow-up messages continue the same Codex conversation instead of starting from a blank context
381
+ - Group text-created tasks now reply with a single initial `task_status` card, and later live/terminal updates stay on that same card
382
+ - Codex execution now prefers the task's `effective_workdir` over the global fallback directory
383
+ - group card `task.submit` now reuses the same task-execution path and inherits the current workspace workdir
384
+ - `task.submit` now replaces the current composer card with a `task_status` card and binds that message to the task flow
385
+ - The webhook request returns quickly after acknowledging the command
386
+ - Task execution happens in a background dispatcher
387
+ - When a task waits for confirmation, completes, fails, or is cancelled, PoCo now pushes a `task_status` card to the stored Feishu reply target
388
+ - Waiting task cards now include `Approve` / `Reject` actions that resume or cancel the task through card callbacks
389
+ - Once a task status card has been sent, later task-state notifications now try to update that same card in place before falling back to a new message
390
+ - workspace cards now keep a bound message id and will also be refreshed with latest-task changes when task state changes
391
+ - task status cards now prefer the agent's raw result over summary text, and long results are paginated instead of being replaced by a summary
392
+ - task status cards now collapse task id, status, agent and effective workdir into the title; the body is reserved for model output or confirmation text instead of duplicated metadata
393
+ - task status titles now lead with bracketed status, for example `[Running] Task: ... (codex, no working dir)`, to keep the scan path tighter on mobile
394
+ - task and workspace cards now prefer direct action buttons over navigation-only buttons; task cards expose `Stop`, `Working Dir`, and `Agent` instead of `Back`/`Refresh` style controls
395
+ - workspace cards no longer try to show latest-result body; the title carries status / agent / workdir / current task, and the body stays action-only
396
+ - running task cards now show throttled live output updates from the agent, instead of staying at a coarse `running` state
397
+
398
+ By default, PoCo runs with `longconn` inbound delivery:
399
+
400
+ - inbound message events arrive over Feishu long connection instead of the webhook route
401
+ - DM events can now trigger proactive project-list card sends
402
+ - group events still reuse the same `InteractionService -> TaskController -> Dispatcher -> Notifier` chain
403
+ - outbound replies still use the Feishu HTTP API
404
+ - card callbacks are now also handled through the Feishu long-connection listener
405
+
406
+ To verify the DM card bootstrap on a real Feishu bot:
407
+
408
+ 1. Start `uvicorn poco.main:app --reload`
409
+ 2. Confirm `/health` shows `feishu_listener_ready=true`
410
+ 3. Send any DM message like `hi` to the bot
411
+ 4. The bot should reply with a `PoCo Projects` card
412
+ 5. Click `Create Project + Group` and the card should return to the DM home card
413
+
414
+ Example webhook payload:
415
+
416
+ ```json
417
+ {
418
+ "token": "verification_token_from_feishu",
419
+ "event": {
420
+ "sender": {
421
+ "sender_id": {
422
+ "open_id": "ou_demo_user"
423
+ }
424
+ },
425
+ "message": {
426
+ "chat_id": "oc_demo_chat",
427
+ "content": "{\"text\":\"/run confirm: review the deployment plan\"}"
428
+ }
429
+ }
430
+ }
431
+ ```
432
+
433
+ ## Supported Commands
434
+
435
+ - In a bound project group, you can now send plain text directly and PoCo will treat it as the task prompt.
436
+ - Group text-created tasks now reply with a single initial `task_status` card, and later live/terminal updates stay on that same card.
437
+ - Running-state card update failures no longer fallback to new-card fanout.
438
+ - PoCo now keeps a minimal persisted `active session` per project, and workspace cards show that session instead of a placeholder.
439
+ - PoCo now treats each project group as one stable session, instead of exposing multi-session lifecycle controls in the group UI.
440
+ - In sqlite-backed runtime, task card message ids are now persisted immediately so follow-up updates do not fan out into fresh cards.
441
+ - `/run <prompt>`
442
+ - `/status <task_id>`
443
+ - `/approve <task_id>`
444
+ - `/reject <task_id>`
445
+ - `/help`
446
+
447
+ If the prompt starts with `confirm:`, the stub runner pauses the task at a confirmation checkpoint so the approval flow can be exercised without a real agent backend.
448
+
449
+ The same `confirm:` prefix also works for the Codex backend: PoCo will pause before invoking `codex`, then continue only after `/approve <task_id>`.