fix(web): reconcile rebased subagent contracts
This commit is contained in:
@@ -72,6 +72,7 @@ describe('core Web profile', () => {
|
|||||||
"tools": [
|
"tools": [
|
||||||
"bash",
|
"bash",
|
||||||
"str_replace_editor",
|
"str_replace_editor",
|
||||||
|
"list_agents",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const EXPECTED_TOOLS = [
|
|||||||
'edit',
|
'edit',
|
||||||
'exit_plan_mode',
|
'exit_plan_mode',
|
||||||
'get_goal',
|
'get_goal',
|
||||||
|
'list_agents',
|
||||||
'ralph',
|
'ralph',
|
||||||
'read',
|
'read',
|
||||||
'send_message',
|
'send_message',
|
||||||
|
|||||||
@@ -1,43 +1,47 @@
|
|||||||
- banner:
|
- banner:
|
||||||
- navigation "Session hierarchy":
|
- heading "event-sourcing researcher" [level=1]
|
||||||
- button "Ask a research subagent to"
|
|
||||||
- text: /
|
|
||||||
- button "event-sourcing researcher" [disabled]
|
|
||||||
- text: · 2 turns
|
|
||||||
- button "1 个子代理":
|
- button "1 个子代理":
|
||||||
- text: 1 个子代理
|
- text: 1 个子代理
|
||||||
- img
|
- img
|
||||||
- tablist:
|
- tablist:
|
||||||
- tab "Chat" [selected]
|
- tab "Chat" [selected]
|
||||||
- tab "Trajectory"
|
- tab "Trajectory"
|
||||||
- tab "Waterfall"
|
- text: Explain event sourcing in one sentence. {{clock}}
|
||||||
- text: Explain event sourcing in one sentence.
|
- button "Copy":
|
||||||
- button "复制":
|
|
||||||
- img
|
- img
|
||||||
- button "在新对话中分支":
|
- button "Branch into a new conversation":
|
||||||
- img
|
- img
|
||||||
- button "编辑":
|
- button "Context injection":
|
||||||
- img
|
- img
|
||||||
|
- img
|
||||||
|
- text: Context injection
|
||||||
- button "Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.":
|
- button "Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.":
|
||||||
|
- img
|
||||||
- img
|
- img
|
||||||
- text: Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.
|
- text: Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.
|
||||||
- paragraph: Event sourcing is a pattern where all changes to an application's state are stored as an immutable, append-only sequence of events, rather than persisting only the current state, enabling full auditability, temporal queries, and event-driven architectures.
|
- paragraph: Event sourcing is a pattern where all changes to an application's state are stored as an immutable, append-only sequence of events, rather than persisting only the current state, enabling full auditability, temporal queries, and event-driven architectures.
|
||||||
- text: Now give the same explanation to a human reader.
|
- button "Copy":
|
||||||
- button "复制":
|
|
||||||
- img
|
- img
|
||||||
- button "在新对话中分支":
|
- button "Branch into a new conversation":
|
||||||
- img
|
- img
|
||||||
- button "编辑":
|
- text: {{clock}} Now give the same explanation to a human reader. {{clock}}
|
||||||
|
- button "Copy":
|
||||||
|
- img
|
||||||
|
- button "Branch into a new conversation":
|
||||||
- img
|
- img
|
||||||
- button "Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.":
|
- button "Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.":
|
||||||
|
- img
|
||||||
- img
|
- img
|
||||||
- text: Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.
|
- text: Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.
|
||||||
- paragraph: Event sourcing is a pattern where all changes to an application's state are stored as an immutable, append-only sequence of events, rather than persisting only the current state, enabling full auditability, temporal queries, and event-driven architectures.
|
- paragraph: Event sourcing is a pattern where all changes to an application's state are stored as an immutable, append-only sequence of events, rather than persisting only the current state, enabling full auditability, temporal queries, and event-driven architectures.
|
||||||
- text: cache hit 99% · 15,738 tokens · 2 turns · 2 steps
|
- button "Copy":
|
||||||
|
- img
|
||||||
|
- button "Branch into a new conversation":
|
||||||
|
- img
|
||||||
|
- text: {{clock}}
|
||||||
- textbox "Message the agent"
|
- textbox "Message the agent"
|
||||||
- button "Add attachment":
|
- button "Commands":
|
||||||
- img
|
- img
|
||||||
- combobox "Access mode":
|
- 'button "Access mode, current: Full access"': Full access
|
||||||
- option "Read-only" [selected]
|
|
||||||
- option "Read-write"
|
|
||||||
- button "Send message" [disabled]
|
- button "Send message" [disabled]
|
||||||
|
- text: 2 turns · 2 steps Context 6% of 128K Cache hit 99% Input 15.6K tok · Output 158 tok
|
||||||
|
|||||||
@@ -458,10 +458,6 @@ flowchart TD
|
|||||||
pkg_client_ui_skill --> pkg_client_ui_slash
|
pkg_client_ui_skill --> pkg_client_ui_slash
|
||||||
pkg_client_ui_skill --> pkg_client_ui_slots
|
pkg_client_ui_skill --> pkg_client_ui_slots
|
||||||
pkg_client_ui_skill --> pkg_invariants
|
pkg_client_ui_skill --> pkg_invariants
|
||||||
pkg_client_ui_subagent --> pkg_client_runtime
|
|
||||||
pkg_client_ui_subagent --> pkg_client_ui_slash
|
|
||||||
pkg_client_ui_subagent --> pkg_client_ui_slots
|
|
||||||
pkg_client_ui_subagent --> pkg_invariants
|
|
||||||
pkg_code_runtime_worker --> pkg_code_runtime
|
pkg_code_runtime_worker --> pkg_code_runtime
|
||||||
pkg_code_runtime_worker --> pkg_invariants
|
pkg_code_runtime_worker --> pkg_invariants
|
||||||
pkg_code_runtime_worker --> pkg_session
|
pkg_code_runtime_worker --> pkg_session
|
||||||
@@ -835,6 +831,12 @@ flowchart TD
|
|||||||
pkg_client_ui_goal --> pkg_client_ui_slots
|
pkg_client_ui_goal --> pkg_client_ui_slots
|
||||||
pkg_client_ui_goal --> pkg_goal
|
pkg_client_ui_goal --> pkg_goal
|
||||||
pkg_client_ui_goal --> pkg_invariants
|
pkg_client_ui_goal --> pkg_invariants
|
||||||
|
pkg_client_ui_subagent --> pkg_client_runtime
|
||||||
|
pkg_client_ui_subagent --> pkg_client_ui_conversation
|
||||||
|
pkg_client_ui_subagent --> pkg_client_ui_primitives
|
||||||
|
pkg_client_ui_subagent --> pkg_client_ui_slash
|
||||||
|
pkg_client_ui_subagent --> pkg_client_ui_slots
|
||||||
|
pkg_client_ui_subagent --> pkg_invariants
|
||||||
pkg_session_reference --> pkg_agent
|
pkg_session_reference --> pkg_agent
|
||||||
pkg_session_reference --> pkg_compact
|
pkg_session_reference --> pkg_compact
|
||||||
pkg_session_reference --> pkg_invariants
|
pkg_session_reference --> pkg_invariants
|
||||||
@@ -1138,7 +1140,6 @@ flowchart TD
|
|||||||
| [`app-boot`](../packages/ui/app-boot) | `ui` | [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`system-prompt`](../packages/core/system-prompt) |
|
| [`app-boot`](../packages/ui/app-boot) | `ui` | [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths), [`system-prompt`](../packages/core/system-prompt) |
|
||||||
| [`client-ui-layout`](../packages/client/ui-layout) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-theme`](../packages/client/ui-theme), [`invariants`](../packages/support/invariants) |
|
| [`client-ui-layout`](../packages/client/ui-layout) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-theme`](../packages/client/ui-theme), [`invariants`](../packages/support/invariants) |
|
||||||
| [`client-ui-skill`](../packages/client/ui-skill) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
| [`client-ui-skill`](../packages/client/ui-skill) | `client` | [`client-connection`](../packages/client/connection), [`client-runtime`](../packages/client/runtime), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||||
| [`client-ui-subagent`](../packages/client/ui-subagent) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
|
||||||
| [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | `code-runtime` | [`code-runtime`](../packages/code-runtime/code-runtime), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
|
| [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | `code-runtime` | [`code-runtime`](../packages/code-runtime/code-runtime), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
|
||||||
| [`host-directory-picker-browse`](../packages/host/directory-picker-browse) | `host` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
|
| [`host-directory-picker-browse`](../packages/host/directory-picker-browse) | `host` | [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
|
||||||
| [`host-directory-picker-native`](../packages/host/directory-picker-native) | `host` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
|
| [`host-directory-picker-native`](../packages/host/directory-picker-native) | `host` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-ui-workspace`](../packages/client/ui-workspace), [`invariants`](../packages/support/invariants) |
|
||||||
@@ -1211,6 +1212,7 @@ flowchart TD
|
|||||||
| [`tool-ask-user`](../packages/ui/tool-ask-user) | `ui` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
|
| [`tool-ask-user`](../packages/ui/tool-ask-user) | `ui` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools), [`user-interaction`](../packages/ui/user-interaction) |
|
||||||
| [`client-ui-command`](../packages/client/ui-command) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
| [`client-ui-command`](../packages/client/ui-command) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||||
| [`client-ui-goal`](../packages/client/ui-goal) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants) |
|
| [`client-ui-goal`](../packages/client/ui-goal) | `client` | [`client-connection`](../packages/client/connection), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants) |
|
||||||
|
| [`client-ui-subagent`](../packages/client/ui-subagent) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-conversation`](../packages/client/ui-conversation), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slash`](../packages/client/ui-slash), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
|
||||||
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
|
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
|
||||||
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
|
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
|
||||||
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ const runningCall = (callId: string, name = 'bash'): RunningToolCall => ({
|
|||||||
/** Empty sessions-list hook for the global standard-kit seat. */
|
/** Empty sessions-list hook for the global standard-kit seat. */
|
||||||
function emptySessions() {
|
function emptySessions() {
|
||||||
const store = createSnapshotStore<SessionListState>(
|
const store = createSnapshotStore<SessionListState>(
|
||||||
{ ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, currentAddress: undefined, })
|
{ ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, currentAddress: undefined })
|
||||||
return bindSnapshotSelector(store)
|
return bindSnapshotSelector(store)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ describe('render branch tails', () => {
|
|||||||
const chat = createChatStore().create()
|
const chat = createChatStore().create()
|
||||||
chat.actions.select({ turnSeq: 1, callId: 'ghost' } satisfies SelectionTarget)
|
chat.actions.select({ turnSeq: 1, callId: 'ghost' } satisfies SelectionTarget)
|
||||||
const emptyList = createSnapshotStore<SessionListState>(
|
const emptyList = createSnapshotStore<SessionListState>(
|
||||||
{ ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, currentAddress: undefined, })
|
{ ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, currentAddress: undefined })
|
||||||
const emptyWorkspaces = createSnapshotStore<WorkspaceListState>({
|
const emptyWorkspaces = createSnapshotStore<WorkspaceListState>({
|
||||||
items: [], archivedSessionIds: [], state: 'idle', phase: 'ready', error: null,
|
items: [], archivedSessionIds: [], state: 'idle', phase: 'ready', error: null,
|
||||||
baselinesReady: true, recentWorkspaceId: undefined,
|
baselinesReady: true, recentWorkspaceId: undefined,
|
||||||
@@ -113,7 +113,7 @@ describe('render branch tails', () => {
|
|||||||
const chat = createChatStore().create()
|
const chat = createChatStore().create()
|
||||||
chat.actions.select({ turnSeq: 8, callId: 'p1:code:1', toolName: 'read' } satisfies SelectionTarget)
|
chat.actions.select({ turnSeq: 8, callId: 'p1:code:1', toolName: 'read' } satisfies SelectionTarget)
|
||||||
const emptyList = createSnapshotStore<SessionListState>(
|
const emptyList = createSnapshotStore<SessionListState>(
|
||||||
{ ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, currentAddress: undefined, })
|
{ ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, currentAddress: undefined })
|
||||||
const emptyWorkspaces = createSnapshotStore<WorkspaceListState>({
|
const emptyWorkspaces = createSnapshotStore<WorkspaceListState>({
|
||||||
items: [], archivedSessionIds: [], state: 'idle', phase: 'ready', error: null,
|
items: [], archivedSessionIds: [], state: 'idle', phase: 'ready', error: null,
|
||||||
baselinesReady: true, recentWorkspaceId: undefined,
|
baselinesReady: true, recentWorkspaceId: undefined,
|
||||||
|
|||||||
@@ -46,6 +46,8 @@
|
|||||||
border: 1px solid var(--dsw-alias-border-l2);
|
border: 1px solid var(--dsw-alias-border-l2);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: var(--dsw-specific-menu);
|
background: var(--dsw-specific-menu);
|
||||||
|
--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
|
||||||
|
--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);
|
||||||
box-shadow: var(--dsw-shadow-lv3);
|
box-shadow: var(--dsw-shadow-lv3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,19 @@ function sessionBlank(session: Session): boolean {
|
|||||||
return !session.events.some(event => event.type === 'turn/start')
|
return !session.events.some(event => event.type === 'turn/start')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Shared Session-header projection for list baselines and creation frames. */
|
||||||
|
function sessionListFields(header: SessionHeader): {
|
||||||
|
parentSessionId?: SessionId
|
||||||
|
origin?: 'subagent'
|
||||||
|
cwd?: string
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
...header.parentSession === undefined ? {} : { parentSessionId: header.parentSession },
|
||||||
|
...header.origin === undefined ? {} : { origin: header.origin },
|
||||||
|
...header.cwd === undefined ? {} : { cwd: header.cwd },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** SessionSummary projection for attached (in-memory) sessions. */
|
/** SessionSummary projection for attached (in-memory) sessions. */
|
||||||
function summarize(session: Session, running: boolean): SessionSummary {
|
function summarize(session: Session, running: boolean): SessionSummary {
|
||||||
return {
|
return {
|
||||||
@@ -282,9 +295,7 @@ function summarize(session: Session, running: boolean): SessionSummary {
|
|||||||
updatedAt: lastActivityTime(session.events) ?? session.header.createdAt,
|
updatedAt: lastActivityTime(session.events) ?? session.header.createdAt,
|
||||||
running,
|
running,
|
||||||
blank: sessionBlank(session),
|
blank: sessionBlank(session),
|
||||||
...session.header.parentSession === undefined ? {} : { parentSessionId: session.header.parentSession },
|
...sessionListFields(session.header),
|
||||||
...session.header.origin === undefined ? {} : { origin: session.header.origin },
|
|
||||||
...session.header.cwd === undefined ? {} : { cwd: session.header.cwd },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2378,10 +2389,8 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
|||||||
// Derived at frame time like summarize(); a just-created session
|
// Derived at frame time like summarize(); a just-created session
|
||||||
// has run no turn yet, so this is constantly true in practice.
|
// has run no turn yet, so this is constantly true in practice.
|
||||||
blank: sessionBlank(session),
|
blank: sessionBlank(session),
|
||||||
...session.header.parentSession === undefined ? {} : { parentSessionId: session.header.parentSession },
|
// Including cwd lets the client group the new session without refreshing the list.
|
||||||
...session.header.origin === undefined ? {} : { origin: session.header.origin },
|
...sessionListFields(session.header),
|
||||||
// cwd rides the frame so the client list needs no refresh to group the new session.
|
|
||||||
...session.header.cwd === undefined ? {} : { cwd: session.header.cwd },
|
|
||||||
}))
|
}))
|
||||||
}),
|
}),
|
||||||
ctx.on('session/disposed', (session: Session) => {
|
ctx.on('session/disposed', (session: Session) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user