Repository navigation
Closed
Description
Overview
Restructure ai-chat into an abstract base with two core subtypes, ai-chat-native (NodeSpace's agent loop; local inference or BYO-Key) and ai-chat-pty (an external agent in a terminal). The AI-chat types are defined once in nodespace-types (ADR-088 §1–§2, ADR-086 §1). ai-chat-acp is named but not created until ACP is implemented.
Problem Statement
- One concrete
ai-chattype covers different shapes, withprovider∈native | openai-compat | pty. Every mode-specific field is optional, so nothing can be required, and a native chat can carry a transcript. - Two definitions.
AiChatNodeand its sub-types exist inpackages/nodespace-types/src/ai_chat.rsand again inpackages/core/src/models/ai_chat_node.rs. - Capture keys (
packages/daemon/src/services/capture_service.rs):- They use a
capture:prefix, a misapplied ADR-063 extension prefix; these are core's own fields. - Four keys are undeclared (
capture:agent_type,capture:started_at,capture:ended_at,capture:exit_code). started_atandended_atduplicatecreated_atandlast_active.- The keys are written through
update_node_unchecked, which skips validation.
- They use a
session_statususesarchivedfor "ended". Capture writes it, and the PTY viewer reads it (ai-chat-pty-session.svelte).modeldoes two jobs. It holds the model id for native chats and the harness name for PTY chats (ai-chat-default-model.ts).
Proposed Solution
ai-chatbecomes abstract, with base fieldscontent(title),agent(nodespace,claude,codex, …),model(optional),summary(optional prose) andlast_active. Base rules, inherited by every subtype: not embedded; no inbound references;local_onlyhandling;children: any; it ownsnodespace://link decoration.ai-chat-nativeownsprovider(native | openai-compat),turn_status,context_tokens, and (for now) the existingmessages[]. Message nodes are a separate issue.ai-chat-ptyownssession_status(active | ended),session_id(local_only),transcript(local_only) andexit_code. Capture writes these bare names andsummary, through the validated update.started_at,ended_atandagent_typego (agentis on the base).- One definition of each AI-chat type in
nodespace-types; delete core's copies. - Frontend: a plugin and viewer per subtype (the existing native and PTY viewers); the AI Chats list queries the base type and so gets both subtypes.
- No migration: reset the database.
Architecture Impact
Implements decisions/088-ai-chat-subtypes-and-message-nodes.md §1–§2 (nodespace-docs), which supersedes ADR-034 in part and ADR-061 §6's capture: names. It uses ADR-086 §6 (abstract types) and §5 (composed rules). Update architecture/ai-chat-node.md in the same PR.
Acceptance Criteria
-
ai-chatis abstract: creating one directly is refused;ai-chat-nativeandai-chat-ptyare core subtypes with their own typed structs (tests) - A query for
ai-chatreturns both subtypes, and the AI Chats sidebar lists both (tests) - Capture writes bare
session_id,transcript,summary,exit_codeandsession_status: endedthrough the validated update; nocapture:key,started_atorended_atis written (test) -
session_statusisactive | ended; the PTY viewer readsended -
agentholds the harness ornodespace;modelholds only a model id - No AI-chat type is defined in
packages/core/src/models/ai_chat_node.rs - Follows
development/node-type-sequence.md; thenode-types.mdAI-chat sheets updated in the same PR -
bun run test:changedpasses;bun run quality:fixclean
Technical Specifications
Reference Files
packages/core/src/models/core_schemas.rs(ai-chat schema),packages/core/src/models/ai_chat_node.rspackages/nodespace-types/src/ai_chat.rspackages/core/src/behaviors/mod.rs(AiChatNodeBehavior)packages/daemon/src/services/capture_service.rs,packages/daemon/src/services/agent_session_service.rspackages/desktop-app/src/lib/components/viewers/ai-chat-node-viewer.svelte,ai-chat-pty-session.svelte,ai-chat-model-selector.sveltepackages/desktop-app/src/lib/services/ai-chat-default-model.ts,packages/desktop-app/src/lib/stores/ai-chats.svelte.ts,packages/desktop-app/src/lib/types/ai-chat-node.ts
Dependencies
- Add the core node type registry, shared envelope, closed schemas and extends-aware rules #3439 (abstract types, registry, composed rules)
Related Issues
- Drop project.status archived and the AI chat viewer's archived read-only gate #3445 (removes the archived read-only gate)
Non-Goals
- Message nodes (separate issue)
- PTY resume, and a real derived summary (open items in ADR-088)
- ACP support
Activity
malibio commentedon Oct 1, 2026
Baseline — Frontend: 301 test files passed, 5558 tests passed
Address review: exclude the chat family from eval snapshots, end a se…
Address re-review: write a session's end only to a terminal chat, and…
Address re-review: pin promoted-field shapes for every typed type, an…
Split ai-chat into an abstract base with ai-chat-native and ai-chat-p…
Split ai-chat into an abstract base with ai-chat-native and ai-chat-p…
Split ai-chat into an abstract base with ai-chat-native and ai-chat-p…