@scotthuang/agent-knock-knock 0.12.0 → 0.12.2
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.
- package/CHANGELOG.md +25 -0
- package/README.md +12 -9
- package/dist/src/cli-core.js +1614 -74
- package/dist/src/cli-core.js.map +1 -1
- package/dist/src/herdr-terminal-control-provider.js +8 -3
- package/dist/src/herdr-terminal-control-provider.js.map +1 -1
- package/dist/src/managed-session.d.ts +30 -2
- package/dist/src/managed-session.js +70 -6
- package/dist/src/managed-session.js.map +1 -1
- package/dist/src/openclaw-plugin.js +60 -11
- package/dist/src/openclaw-plugin.js.map +1 -1
- package/dist/src/session-store.d.ts +1 -0
- package/dist/src/session-store.js +32 -4
- package/dist/src/session-store.js.map +1 -1
- package/dist/src/terminal-agent-bridge.d.ts +13 -0
- package/dist/src/terminal-agent-bridge.js +57 -6
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-control-provider.js +60 -16
- package/dist/src/terminal-control-provider.js.map +1 -1
- package/dist/src/terminal-submission-acceptance.d.ts +31 -6
- package/dist/src/terminal-submission-acceptance.js +93 -16
- package/dist/src/terminal-submission-acceptance.js.map +1 -1
- package/package.json +1 -1
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +12 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.2 - 2026-08-11
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Let terminal-scoped sends absorb an exact, verified native-thread switch made by a human through Codex or Claude Code, including `/clear`, new-thread, and Resume flows across tmux and Herdr.
|
|
8
|
+
- Restore a uniquely matching historical Session with its own binding generation, or create a separate Session for a previously unseen native thread, without merging conversation history.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Keep explicit Session-scoped sends pinned to their original native context, while active Turns expose a snapshot-bound handoff decision that requires explicit confirmation before the current human context is adopted.
|
|
13
|
+
|
|
14
|
+
### Security
|
|
15
|
+
|
|
16
|
+
- Revalidate the native UUID, process birth, terminal endpoint, cwd, exclusive ownership, idle state, and exact composer immediately around terminal input, while preserving single-Enter and no-blind-retry guarantees.
|
|
17
|
+
- Persist human-observed handoffs through fenced lifecycle transitions and ledgers with crash recovery, stale-decision rejection, and strict isolation for prior Turns, monitors, callbacks, approvals, and dispatch receipts.
|
|
18
|
+
|
|
19
|
+
## 0.12.1 - 2026-08-11
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Allow a genuinely virgin Codex TUI to accept its first AKK send by pinning the exact process incarnation before input, then atomically refining the Session and Turn to the newly materialized native UUID, rollout, and request evidence after the single Enter.
|
|
24
|
+
- Recover both post-Enter virgin-binding crash windows without replaying terminal text or Enter, while preserving the existing ownership, binding-generation, process, pane, cwd, rollout, and request-hash fences.
|
|
25
|
+
- Preserve tmux `pane_current_path` when extended eight-field pane output is collapsed to whitespace or underscores, rejecting ambiguous or truncated records instead of appending the server socket and pane ID to the workspace.
|
|
26
|
+
- Preserve Codex composer ANSI styling through Herdr's visible screen buffer so an empty dim placeholder is not mistaken for authored draft text, while leaving ordinary monitor and status reads on Herdr's agent-aware detection buffer.
|
|
27
|
+
|
|
3
28
|
## 0.12.0 - 2026-08-10
|
|
4
29
|
|
|
5
30
|
### Added
|
package/README.md
CHANGED
|
@@ -83,11 +83,13 @@ terminal resource / process incarnation
|
|
|
83
83
|
└─ Turn 3 (turn_id)
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
Once an AKK session exists, an ordinary `send(session_id, request)` creates a new `turn_id`
|
|
86
|
+
Once an AKK session exists, an ordinary `send(session_id, request)` is **session-scoped**: it creates a new `turn_id` in that exact native coding-agent context and never silently follows a different thread now visible in the pane. A listed terminal may instead advertise a **terminal-scoped follow-current** send with its exact full `selector` and a fresh `expected_terminal_token`. Using that prefilled action says “continue in whatever verified context the human selected in this pane”; when the old Session is quiescent and the handoff is exact, AKK atomically detaches the old binding, restores or creates the Session for the live native thread, and only then creates the Turn. The token fences the terminal snapshot so a later pane, process, workspace, or native-thread change cannot be adopted by accident. Legacy selector-based first attach remains supported. Never infer a selector or token, copy one from another row, reuse one after another terminal action, or pass a selector as `session_id`. The `turn_id` is not a destination for later ordinary sends; it is the exact identity used for status, approval, cancellation, renewal, callback retry, close, and callback correlation. If a Turn is `waiting_for_openclaw`, `respond(turn_id, answer)` supplies the answer inside that same Turn instead of creating another one.
|
|
87
87
|
|
|
88
|
-
Human-friendly selectors such as `only`, `codex`, `claude`, a terminal ID, or `@short-ref` remain a discovery layer. A natural-language tool call may preserve one only when the user explicitly named it; otherwise use the exact selector returned by `AKK list`, or omit it and require a unique eligible pane.
|
|
88
|
+
Human-friendly selectors such as `only`, `codex`, `claude`, a terminal ID, or `@short-ref` remain a discovery layer. A natural-language tool call may preserve one only when the user explicitly named it; otherwise use the exact selector returned by `AKK list`, or omit it and require a unique eligible pane. Normally a managed row pre-fills its authoritative `session_id` for strict continuation. After a human changes the native thread outside AKK, an adoptable row instead pre-fills the exact terminal selector and `expected_terminal_token` for follow-current continuation. Merely observing that mismatch never mutates the Store. AKK advertises the fenced send only when it can prove a single source claim, exact live identity, idle empty composer, and no unresolved Turn, transition, dispatch, or approval. Active, ambiguous, stale, or unverifiable cases remain blocked and require the user to resolve or select the context explicitly. The same raw terminal row may advertise status, approval, cancellation, or orphan-close with its own prefilled `conversation_id` compatibility selector. Never infer, guess, or reuse compatibility selectors or tokens.
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
An exact human switch while the old Session still has one active Turn is a decision point, not an automatic redirect. In that case the terminal row may expose `handoff_decision` instead of a follow-current send. Its nested `choices.take_over_current.action` is the only authoritative supersede action: after explicit user confirmation, invoke its complete `agent_knock_knock_close` arguments unchanged (`turn_id`, `reason="superseded_by_human_context_switch"`, and `expected_handoff_token`). The snapshot-bound close records the old Turn's disposition and sends no terminal input. Then list again and use only the newly advertised follow-current send; never chain the old token into a send. Choosing `keep_source` changes no AKK state: restore the old native thread in the Codex or Claude TUI, then refresh the list. A completed/changed Turn or another human thread switch makes the decision token stale and requires a fresh decision.
|
|
91
|
+
|
|
92
|
+
Native clear/new/resume operations requested through AKK are explicit lifecycle actions, separate from ordinary Turn creation. A successful new/clear creates a new native thread and AKK Session; resume activates the exact historical native thread and its corresponding Session. Each successful lifecycle transition creates no Turn. A human may also run native `/clear`, `/new`, `/resume`, or the equivalent directly in the shared terminal. AKK does not forbid that takeover: the next exact, fresh terminal-scoped follow-current send can absorb the human-driven transition when it is safe, while a `session_id` send deliberately remains pinned to its old context. AKK serializes either transition, verifies the resulting native identity, and advances the terminal binding generation so work and callbacks from the previous context cannot cross the boundary. Exact AKK-driven lifecycle profiles are verified for Codex 0.146.0/0.146.1/0.147.0 and Claude Code 2.1.218/2.1.226.
|
|
91
93
|
|
|
92
94
|
AKK status and native status inspection are different operations. `agent_knock_knock_status` (and `/akk status`) reads AKK Turn state plus a bounded current terminal screen; it does not execute the coding agent's `/status`. When an idle terminal row advertises `native_inspect`, `agent_knock_knock_native_inspect` can execute only its prefilled, version-scoped inspection with the exact `terminal_id`, `inspection="status"`, and fresh `expected_binding_token`. Supported profiles are Codex 0.146.0/0.146.1/0.147.0 and Claude Code 2.1.218/2.1.226. Claude's adapter parses a newly opened Status panel, dismisses that exact panel once, and proves the same pane returned to an idle empty composer. The action creates no Session, Turn, receipt, monitor, or callback. `/usage`, `/cost`, `/stats`, `/usage-credits`, `/model`, `/compact`, arbitrary slash strings, and unsupported versions remain unavailable. In particular, bare Codex `/usage` opens an interactive menu whose later Enter can select an account-side usage-limit reset; do not automate it as a read-only inspection.
|
|
93
95
|
|
|
@@ -230,19 +232,19 @@ The core command surface is intentionally small:
|
|
|
230
232
|
|
|
231
233
|
`/akk list` performs a controlled reconciliation across managed turns, and `/akk status` limits reconciliation to the selected turn. This can close records whose idle retention has elapsed and restore eligible missing monitors, but it does not send terminal input or retry callback delivery. Independently, the running OpenClaw plugin supervises eligible `waiting_for_agent` monitors every five seconds; this liveness pass only restores missing monitors and likewise never retries callback transport. Standalone shell queries are read-only unless `--reconcile` is explicitly passed, and resolving a selector never changes turn state.
|
|
232
234
|
|
|
233
|
-
Selectors fail closed: `only` works only with one actionable target, `latest` requires a unique newest target, and `codex` or `claude` must identify exactly one eligible pane. These names and `@short-ref` are human-facing resolution inputs; a natural-language tool call may preserve one explicitly named by the user, but must not infer one. Managed JSON actions contain the authoritative full `session_id` or `turn_id`. For first attach, an unmanaged raw-terminal row's send action may instead contain its own prefilled `selector
|
|
235
|
+
Selectors fail closed: `only` works only with one actionable target, `latest` requires a unique newest target, and `codex` or `claude` must identify exactly one eligible pane. These names and `@short-ref` are human-facing resolution inputs; a natural-language tool call may preserve one explicitly named by the user, but must not infer one. Managed JSON actions normally contain the authoritative full `session_id` or `turn_id`. For first attach, an unmanaged raw-terminal row's send action may instead contain its own prefilled `selector`. For a safe human handoff, a terminal row may prefill its exact full `selector` together with `expected_terminal_token`; preserve both exactly to follow the pane's current context. Its advertised raw controls may contain that row's prefilled `conversation_id`. No compatibility selector or token may be guessed, copied from another row, or passed in an authoritative ID field. Before every terminal operation, AKK revalidates the expected agent PID and provider-owned terminal identity, then confirms that the process and pane working directories still match; every send also revalidates the idle prompt immediately before typing.
|
|
234
236
|
|
|
235
|
-
To change native context, first copy the full `terminal_id` from `/akk list`; lifecycle commands do not accept an ordinary-send `@short-ref` or loose agent selector. `/akk threads <exact-terminal-id>` lists exact, same-workspace candidates with a deterministic number, a collision-safe display-only `@short-id`, an opaque snapshot handle, and the complete UUID. `/akk resume-thread <exact-terminal-id>` without a selection shows that list. A complete UUID remains compatible. A number or short ID resolves only against the latest list displayed in the same OpenClaw session, while an opaque handle names its exact snapshot; all expire after five minutes and fail after terminal, process, workspace, binding, candidate-set, or relevant action changes. None is ever passed to Codex or Claude Code as native identity: AKK resolves the saved tuple back to its full UUID and fresh evidence tokens first. `previous` (or `刚才那个`) is advertised only when the current Session's latest committed lifecycle transition identifies exactly one currently verified resumable source; it never guesses from title, recency, or static lineage. `/akk new-thread` and its human alias `/akk clear-thread` start a clean context. AKK does not poll bindings in the background:
|
|
237
|
+
To ask AKK itself to change native context, first copy the full `terminal_id` from `/akk list`; lifecycle commands do not accept an ordinary-send `@short-ref` or loose agent selector. `/akk threads <exact-terminal-id>` lists exact, same-workspace candidates with a deterministic number, a collision-safe display-only `@short-id`, an opaque snapshot handle, and the complete UUID. `/akk resume-thread <exact-terminal-id>` without a selection shows that list. A complete UUID remains compatible. A number or short ID resolves only against the latest list displayed in the same OpenClaw session, while an opaque handle names its exact snapshot; all expire after five minutes and fail after terminal, process, workspace, binding, candidate-set, or relevant action changes. None is ever passed to Codex or Claude Code as native identity: AKK resolves the saved tuple back to its full UUID and fresh evidence tokens first. `previous` (or `刚才那个`) is advertised only when the current Session's latest committed lifecycle transition identifies exactly one currently verified resumable source; it never guesses from title, recency, or static lineage. `/akk new-thread` and its human alias `/akk clear-thread` start a clean context. AKK does not poll bindings or adopt observed switches in the background: a human-driven switch is adopted only as part of an explicit, fresh terminal-scoped send. If a recorded owner process exits, the next lifecycle listing can classify that sole historical binding as resumable, and the resume mutation compare-and-swap detaches it before touching the terminal. Stale, expired, unsupported, busy, ambiguous, active-elsewhere, or unverifiable transitions fail closed. Do not ask AKK to send `/clear`, `/new`, `/resume`, `/status`, Codex `/fork`, `/side`, or `/btw`, Claude `/branch`, or any other first-line native slash command as an ordinary task or answer; use an advertised AKK action, express the request in natural language, or enter an unsupported native command manually in the terminal UI.
|
|
236
238
|
|
|
237
239
|
To request a native Codex status card or Claude Status panel, first run `agent_knock_knock_list` and use only that terminal row's advertised `native_inspect` action. The structured tool schema is closed to `inspection="status"`; callers cannot provide `/status` or another slash command as text. AKK serializes the inspection with terminal mutations, revalidates the fresh token and exact terminal identity, and returns only after it proves one fresh bounded status result and an idle postcondition. For Claude, that includes safely dismissing the exact modal once. It never turns ordinary `send` or `respond` into a slash-command escape hatch.
|
|
238
240
|
|
|
239
|
-
The top-level
|
|
241
|
+
The top-level v8 `action_contracts` documents this closed inspection alongside the existing lifecycle and Turn actions. `available_actions` remains the authority for ordinary current actions. The deliberate exception is an active human-handoff conflict: `handoff_decision.choices.take_over_current.action` is an authoritative, snapshot-bound action only after explicit user confirmation; copy that complete action, then refresh the list before doing anything else.
|
|
240
242
|
|
|
241
|
-
For natural-language tool use, `agent_knock_knock_list` is terminal-first. Each live pane appears exactly once in `terminals[]`; `process_state` reports whether its coding-agent process is alive and `activity_state` reports the parsed screen state. `managed.session_id` identifies the continuing AKK session, `managed.current_turn` is its optional active Turn, and `managed.recent_turn` is retained history; retained Turns do not occupy the terminal. Pass `all=true` to include older entries in `managed.history`. By default, `unavailable_managed_turns[]` contains attention-needed records whose pane cannot be presented as a live terminal; `all=true` also includes retained unavailable history.
|
|
243
|
+
For natural-language tool use, `agent_knock_knock_list` is terminal-first. Each live pane appears exactly once in `terminals[]`; `process_state` reports whether its coding-agent process is alive and `activity_state` reports the parsed screen state. `managed.session_id` identifies the continuing AKK session, `managed.current_turn` is its optional active Turn, and `managed.recent_turn` is retained history; retained Turns do not occupy the terminal. A human-driven native-thread mismatch remains honestly classified as `management_state="conflict"`; its `handoff_state` is `external_handoff_adoptable` only when the row advertises the fenced follow-current `send`, otherwise it is `external_handoff_blocked`. Listing never performs the adoption. Pass `all=true` to include older entries in `managed.history`. By default, `unavailable_managed_turns[]` contains attention-needed records whose pane cannot be presented as a live terminal; `all=true` also includes retained unavailable history.
|
|
242
244
|
|
|
243
|
-
Use only an `available_actions` entry returned in that snapshot, begin with its prefilled authoritative arguments, and supply every `missing_required` field. A managed Session's `send` uses its prefilled `session_id` and creates a new Turn.
|
|
245
|
+
Use only an `available_actions` entry returned in that snapshot, begin with its prefilled authoritative arguments, and supply every `missing_required` field. The sole additional action source is a terminal row's nested `handoff_decision.choices.take_over_current.action`, which requires explicit user confirmation and must be copied whole. A managed Session's strict `send` uses its prefilled `session_id` and creates a new Turn only in that Session's native context. A terminal-scoped follow-current `send` instead carries the selected row's exact full `selector` and `expected_terminal_token`; preserve both and add only `request`. This is the safe path for continuing after a human changed threads directly in the pane. Legacy first attach may still use a discovery selector explicitly named by the user or the unmanaged raw-terminal row's prefilled `selector`; do not infer or reuse one. `respond` is available only while a Turn is `waiting_for_openclaw`; it uses `turn_id` and keeps the answer inside that Turn. Managed status, approval, cancellation, renewal, callback retry, and close also use the exact `turn_id`. Native inspection instead uses the exact terminal row's `terminal_id`, closed `inspection`, and snapshot-bound `expected_binding_token`; do not substitute AKK status or ordinary send. A raw terminal may be controlled only through the exact status, approval, cancellation, or orphan-close action that its own row advertises with a prefilled `conversation_id`; never construct or guess one. `timeoutSeconds` is unsupported, and monitoring limits should be omitted unless the user explicitly asks to change them. AKK revalidates availability before every side effect.
|
|
244
246
|
|
|
245
|
-
The top-level action contracts include `native_inspect`, `list_resumable_threads`, `new_thread`, `resume_thread`, and the conflict-only `reconcile_binding` recovery action. A supported idle Codex or Claude Code terminal may advertise `native_inspect` with its exact terminal ID, the closed `status` inspection kind, and a fresh binding token. The terminal row also advertises `list_resumable_threads` and, when currently safe, `new_thread`. Thread listing is read-only with respect to Session/Turn state, takes only the full `terminal_id`, and returns a fresh `expected_binding_token` plus candidate rows; each `resumable=true` row retains its complete UUID and exact prefilled `resume_thread` action. If `previous` is present, use only its exact prefilled action for a natural-language “刚才那个” request. Numbers, short IDs, and handles are human display/navigation aids, never tool arguments or authoritative native identity. The `new_thread` and `resume_thread` mutations require the fresh token, and resume additionally requires the candidate's complete `native_thread_id` and opaque `candidate_token`.
|
|
247
|
+
The top-level v8 action contracts include `send`, `native_inspect`, `list_resumable_threads`, `new_thread`, `resume_thread`, and the conflict-only `reconcile_binding` recovery action. `send` has two deliberately different managed scopes: `session_id` is strict context, while the exact terminal `selector` plus `expected_terminal_token` is follow-current context. A supported idle Codex or Claude Code terminal may advertise `native_inspect` with its exact terminal ID, the closed `status` inspection kind, and a fresh binding token. The terminal row also advertises `list_resumable_threads` and, when currently safe, `new_thread`. Thread listing is read-only with respect to Session/Turn state, takes only the full `terminal_id`, and returns a fresh `expected_binding_token` plus candidate rows; each `resumable=true` row retains its complete UUID and exact prefilled `resume_thread` action. If `previous` is present, use only its exact prefilled action for a natural-language “刚才那个” request. Numbers, short IDs, and handles are human display/navigation aids, never tool arguments or authoritative native identity. The `new_thread` and `resume_thread` mutations require the fresh token, and resume additionally requires the candidate's complete `native_thread_id` and opaque `candidate_token`. `reconcile_binding` remains a low-level compatibility/recovery action for a safely detachable conflict when no ordinary follow-current send is appropriate; it never adopts the replacement thread, sends terminal input, or creates a Turn. Never construct, guess, truncate, combine across snapshots, or reuse those values after another terminal action. Native inspection and lifecycle results contain no `turn_id` because no work was sent.
|
|
246
248
|
|
|
247
249
|
Workspace is not a routing boundary. AKK can list, inspect, and control verified panes across projects; when more than one target matches, use a selector to choose one explicitly.
|
|
248
250
|
|
|
@@ -316,6 +318,7 @@ With the global npm CLI installed, start with `agent-knock-knock doctor`. It run
|
|
|
316
318
|
| Source changes do not appear | Build, reinstall from the checkout, and restart the Gateway. |
|
|
317
319
|
| Terminal Turn is `stalled` | Inspect `status` and the terminal; use `/akk renew only <minutes>` only when exactly one live stalled Turn needs more monitoring time. |
|
|
318
320
|
| Turn is `callback_failed` | Run `/akk retry-callback only` when it is the only actionable failed callback, or use its `@short-ref`. |
|
|
321
|
+
| A human thread switch reports `active_turn_requires_decision` | Do not redirect automatically. Ask the user to choose. For takeover, run only the complete nested `take_over_current.action` after explicit confirmation, then list again and use the fresh follow-current send. To keep the old work, restore its native thread in the TUI and refresh the list. |
|
|
319
322
|
| `AKK list` reports an orphaned terminal dispatch or lifecycle transition | Inspect the named pane first, then run the exact `/akk close ...` recovery command returned by `list`. It contains exactly one fresh `--expected-message-id ...` or `--expected-transition-id ...` fence; do not construct, substitute, or reuse it. AKK leaves the coding agent and terminal pane running. |
|
|
320
323
|
| Claude permission is not offered through AKK | Resolve unsupported dialogs in the terminal. The AKK path requires the exact supported one-time Bash prompt for the current managed turn. |
|
|
321
324
|
| Claude request was not auto-approved | Check `autoApprove.enabled`, the agent, the rule's canonical `workspaces`, and the exact command vector. The request must also have matching current screen and local transcript evidence. |
|