@windowkit/agent-chat 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +147 -2
- package/dist/core/driver.d.ts +183 -0
- package/dist/core/driver.d.ts.map +1 -0
- package/dist/core/driver.js +12 -0
- package/dist/core/driver.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/markdown.d.ts +7 -0
- package/dist/core/markdown.d.ts.map +1 -0
- package/dist/core/markdown.js +53 -0
- package/dist/core/markdown.js.map +1 -0
- package/dist/core/policy.d.ts +18 -0
- package/dist/core/policy.d.ts.map +1 -0
- package/dist/core/policy.js +67 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/reducer.d.ts +61 -0
- package/dist/core/reducer.d.ts.map +1 -0
- package/dist/core/reducer.js +391 -0
- package/dist/core/reducer.js.map +1 -0
- package/dist/core/session.d.ts +105 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +648 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/tools.d.ts +120 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +120 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/types.d.ts +295 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +21 -0
- package/dist/core/types.js.map +1 -0
- package/dist/drivers/claude/index.d.ts +20 -0
- package/dist/drivers/claude/index.d.ts.map +1 -0
- package/dist/drivers/claude/index.js +727 -0
- package/dist/drivers/claude/index.js.map +1 -0
- package/dist/drivers/claude/input.d.ts +7 -0
- package/dist/drivers/claude/input.d.ts.map +1 -0
- package/dist/drivers/claude/input.js +46 -0
- package/dist/drivers/claude/input.js.map +1 -0
- package/dist/drivers/claude/peers.d.ts +16 -0
- package/dist/drivers/claude/peers.d.ts.map +1 -0
- package/dist/drivers/claude/peers.js +137 -0
- package/dist/drivers/claude/peers.js.map +1 -0
- package/dist/drivers/claude/schema.d.ts +5 -0
- package/dist/drivers/claude/schema.d.ts.map +1 -0
- package/dist/drivers/claude/schema.js +77 -0
- package/dist/drivers/claude/schema.js.map +1 -0
- package/dist/drivers/claude/sdk.d.ts +86 -0
- package/dist/drivers/claude/sdk.d.ts.map +1 -0
- package/dist/drivers/claude/sdk.js +47 -0
- package/dist/drivers/claude/sdk.js.map +1 -0
- package/dist/drivers/claude/tools.d.ts +18 -0
- package/dist/drivers/claude/tools.d.ts.map +1 -0
- package/dist/drivers/claude/tools.js +119 -0
- package/dist/drivers/claude/tools.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/testing/fake.d.ts +63 -0
- package/dist/testing/fake.d.ts.map +1 -0
- package/dist/testing/fake.js +270 -0
- package/dist/testing/fake.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +4 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/view/AgentChat.d.ts +53 -0
- package/dist/view/AgentChat.d.ts.map +1 -0
- package/dist/view/AgentChat.js +87 -0
- package/dist/view/AgentChat.js.map +1 -0
- package/dist/view/CodeBlock.d.ts +9 -0
- package/dist/view/CodeBlock.d.ts.map +1 -0
- package/dist/view/CodeBlock.js +60 -0
- package/dist/view/CodeBlock.js.map +1 -0
- package/dist/view/Composer.d.ts +24 -0
- package/dist/view/Composer.d.ts.map +1 -0
- package/dist/view/Composer.js +144 -0
- package/dist/view/Composer.js.map +1 -0
- package/dist/view/Header.d.ts +3 -0
- package/dist/view/Header.d.ts.map +1 -0
- package/dist/view/Header.js +30 -0
- package/dist/view/Header.js.map +1 -0
- package/dist/view/MessageList.d.ts +9 -0
- package/dist/view/MessageList.d.ts.map +1 -0
- package/dist/view/MessageList.js +111 -0
- package/dist/view/MessageList.js.map +1 -0
- package/dist/view/QuestionCard.d.ts +6 -0
- package/dist/view/QuestionCard.d.ts.map +1 -0
- package/dist/view/QuestionCard.js +39 -0
- package/dist/view/QuestionCard.js.map +1 -0
- package/dist/view/TextBlock.d.ts +9 -0
- package/dist/view/TextBlock.d.ts.map +1 -0
- package/dist/view/TextBlock.js +22 -0
- package/dist/view/TextBlock.js.map +1 -0
- package/dist/view/ToolCard.d.ts +7 -0
- package/dist/view/ToolCard.d.ts.map +1 -0
- package/dist/view/ToolCard.js +155 -0
- package/dist/view/ToolCard.js.map +1 -0
- package/dist/view/Transcript.d.ts +5 -0
- package/dist/view/Transcript.d.ts.map +1 -0
- package/dist/view/Transcript.js +47 -0
- package/dist/view/Transcript.js.map +1 -0
- package/dist/view/context.d.ts +21 -0
- package/dist/view/context.d.ts.map +1 -0
- package/dist/view/context.js +37 -0
- package/dist/view/context.js.map +1 -0
- package/dist/view/fences.d.ts +13 -0
- package/dist/view/fences.d.ts.map +1 -0
- package/dist/view/fences.js +59 -0
- package/dist/view/fences.js.map +1 -0
- package/dist/view/files.d.ts +11 -0
- package/dist/view/files.d.ts.map +1 -0
- package/dist/view/files.js +109 -0
- package/dist/view/files.js.map +1 -0
- package/dist/view/look.d.ts +18 -0
- package/dist/view/look.d.ts.map +1 -0
- package/dist/view/look.js +37 -0
- package/dist/view/look.js.map +1 -0
- package/dist/view/types.d.ts +50 -0
- package/dist/view/types.d.ts.map +1 -0
- package/dist/view/types.js +14 -0
- package/dist/view/types.js.map +1 -0
- package/dist/view/use-agent.d.ts +11 -0
- package/dist/view/use-agent.d.ts.map +1 -0
- package/dist/view/use-agent.js +33 -0
- package/dist/view/use-agent.js.map +1 -0
- package/package.json +92 -4
- package/src/core/driver.ts +191 -0
- package/src/core/index.ts +54 -0
- package/src/core/markdown.ts +56 -0
- package/src/core/policy.ts +77 -0
- package/src/core/reducer.ts +490 -0
- package/src/core/session.ts +824 -0
- package/src/core/tools.ts +233 -0
- package/src/core/types.ts +321 -0
- package/src/drivers/claude/index.ts +825 -0
- package/src/drivers/claude/input.ts +47 -0
- package/src/drivers/claude/peers.ts +153 -0
- package/src/drivers/claude/schema.ts +99 -0
- package/src/drivers/claude/sdk.ts +138 -0
- package/src/drivers/claude/tools.ts +141 -0
- package/src/index.ts +51 -0
- package/src/testing/fake.ts +374 -0
- package/src/testing/index.ts +11 -0
- package/src/view/AgentChat.tsx +204 -0
- package/src/view/CodeBlock.tsx +108 -0
- package/src/view/Composer.tsx +230 -0
- package/src/view/Header.tsx +73 -0
- package/src/view/MessageList.tsx +290 -0
- package/src/view/QuestionCard.tsx +107 -0
- package/src/view/TextBlock.tsx +58 -0
- package/src/view/ToolCard.tsx +283 -0
- package/src/view/Transcript.tsx +81 -0
- package/src/view/context.ts +70 -0
- package/src/view/dom-globals.d.ts +10 -0
- package/src/view/fences.ts +73 -0
- package/src/view/files.ts +111 -0
- package/src/view/look.ts +53 -0
- package/src/view/types.ts +71 -0
- package/src/view/use-agent.ts +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrey Sidorov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,148 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @windowkit/agent-chat
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A chat with a local AI agent harness, embedded in a
|
|
4
|
+
[react-x11](https://github.com/sidorares/react-x11) app.
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
import { AgentChat } from '@windowkit/agent-chat';
|
|
8
|
+
|
|
9
|
+
<AgentChat agent="claude" />;
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
That is a working chat with Claude Code in the app's working directory: replies
|
|
13
|
+
stream in as markdown, tool calls show as cards with their output, anything
|
|
14
|
+
that changes something asks first, Enter sends and Escape stops. The message
|
|
15
|
+
box formats markdown as it is typed and sends exactly what was typed, with
|
|
16
|
+
`@` for a file, `/` for a command and Up for an earlier prompt. Everything
|
|
17
|
+
else is an opt-in on the same element: the app's context, its own functions
|
|
18
|
+
as tools, its own renderers for what the agent writes, and its own handlers
|
|
19
|
+
for anything the agent or the user does.
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @windowkit/agent-chat @react-x11/components react-x11 react
|
|
27
|
+
npm install @anthropic-ai/claude-agent-sdk # for agent="claude"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`react`, `react-x11` and `@react-x11/components` are peers: a second copy of
|
|
31
|
+
either renderer package breaks element registration. The Claude Agent SDK is
|
|
32
|
+
an optional peer, installed only by an app that drives Claude, and
|
|
33
|
+
authenticates the way the SDK does (`ANTHROPIC_API_KEY`, Bedrock, Vertex,
|
|
34
|
+
Foundry).
|
|
35
|
+
|
|
36
|
+
## Growing it
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// Context: where it works, what it is told, which built-ins it has.
|
|
40
|
+
<AgentChat
|
|
41
|
+
agent="claude"
|
|
42
|
+
cwd={project.root}
|
|
43
|
+
instructions="You are the build assistant for Acme."
|
|
44
|
+
coreTools={{ web: false }}
|
|
45
|
+
/>;
|
|
46
|
+
|
|
47
|
+
// The app's own tools, as functions. No MCP server to run.
|
|
48
|
+
const openTicket = defineTool({
|
|
49
|
+
description: 'Open a ticket in the tracker by id.',
|
|
50
|
+
parameters: z.object({ id: z.string() }),
|
|
51
|
+
run: ({ id }) => tracker.open(id),
|
|
52
|
+
render: ({ output }) => output && <TicketCard ticket={output} />,
|
|
53
|
+
});
|
|
54
|
+
<AgentChat agent="claude" tools={{ openTicket }} />;
|
|
55
|
+
|
|
56
|
+
// What the agent writes, drawn by the app — and the agent told it can.
|
|
57
|
+
<AgentChat
|
|
58
|
+
agent="claude"
|
|
59
|
+
fences={{
|
|
60
|
+
chart: {
|
|
61
|
+
render: (f) => <Chart spec={f.text} />,
|
|
62
|
+
describe: 'a Vega-Lite spec',
|
|
63
|
+
},
|
|
64
|
+
}}
|
|
65
|
+
/>;
|
|
66
|
+
|
|
67
|
+
// Interception: a Run button that calls the app, a gate on every tool call,
|
|
68
|
+
// and the agent's own shell replaced by the app's function.
|
|
69
|
+
<AgentChat
|
|
70
|
+
agent="claude"
|
|
71
|
+
codeActions={[
|
|
72
|
+
copyCode,
|
|
73
|
+
{
|
|
74
|
+
id: 'run',
|
|
75
|
+
label: 'Run',
|
|
76
|
+
when: (f) => f.lang === 'sh',
|
|
77
|
+
run: (f) => app.run(f.text),
|
|
78
|
+
},
|
|
79
|
+
]}
|
|
80
|
+
onToolCall={(call) => (call.kind === 'execute' ? 'ask' : undefined)}
|
|
81
|
+
coreTools={{ shell: sandboxShell }}
|
|
82
|
+
/>;
|
|
83
|
+
|
|
84
|
+
// The app drives the session: the same options, moved into a hook.
|
|
85
|
+
const agent = useAgent({ agent: 'claude', tools: { openTicket } });
|
|
86
|
+
<AgentChat session={agent} />;
|
|
87
|
+
|
|
88
|
+
// Another session's words: drawn as theirs, and told to the agent as such.
|
|
89
|
+
agent.send({
|
|
90
|
+
text: draft,
|
|
91
|
+
from: { kind: 'peer', id: 'writer', name: 'Writer' },
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
[docs/agent-chat.md](docs/agent-chat.md) has every prop, the gate, and the
|
|
96
|
+
session API.
|
|
97
|
+
|
|
98
|
+
## Harnesses
|
|
99
|
+
|
|
100
|
+
The UI never asks which agent it drives; it asks what the session can do, and
|
|
101
|
+
draws only the actions that work. A driver per harness family does the rest.
|
|
102
|
+
|
|
103
|
+
| Driver | Harness | State |
|
|
104
|
+
| -------- | -------------------------------------------------------------------------------------------------- | ------- |
|
|
105
|
+
| `claude` | Claude Code, through the Claude Agent SDK, in-process tools | Built |
|
|
106
|
+
| `acp` | Any ACP agent: Gemini CLI, Copilot, Cursor, opencode, goose, Grok Build, Codex through its adapter | Planned |
|
|
107
|
+
| `codex` | `codex app-server` | Planned |
|
|
108
|
+
|
|
109
|
+
[docs/drivers.md](docs/drivers.md) says what each does, and how to write one.
|
|
110
|
+
[docs/design.md](docs/design.md) is the survey and the reasons.
|
|
111
|
+
|
|
112
|
+
## Without a harness
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm run examples:demo
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`fakeDriver` from `@windowkit/agent-chat/testing` plays a script through the
|
|
119
|
+
real session: streamed text, approvals, the app's tools, questions. The demo
|
|
120
|
+
and every test run on it, with no SDK, no key and no network.
|
|
121
|
+
|
|
122
|
+
The same demo over real Claude Code — the same tool, fence renderer and Run
|
|
123
|
+
button, with Claude deciding what to do. The SDK is a devDependency of this
|
|
124
|
+
repository, so `npm install` has brought it:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
DEMO_AGENT=claude DEMO_CWD=~/scratch/demo npm run examples:demo
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`DEMO_CWD` is where Claude works, made if it is missing (default: the current
|
|
131
|
+
directory), and it asks before changing anything there. It authenticates as Claude Code does:
|
|
132
|
+
`ANTHROPIC_API_KEY`, or the configuration it already has. `CLAUDE_PATH` runs
|
|
133
|
+
your installed `claude` instead of the SDK's copy; SDK 0.3.N ships Claude Code
|
|
134
|
+
2.1.N, so keep the two in step.
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npm install
|
|
140
|
+
npm test # headless: react-x11 runs an X server in-process
|
|
141
|
+
npm run typecheck
|
|
142
|
+
npm run build && npm run check:package
|
|
143
|
+
npm run screenshots # docs/img, both colour schemes
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Licence
|
|
147
|
+
|
|
148
|
+
MIT
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { AnyToolDef, ToolResult } from './tools.js';
|
|
2
|
+
import type { Attachment, Capabilities, CoreToolKey, MessageSource, PeerSource, PermissionPolicy, PlanEntry, Question, SessionInfo, ToolCall, ToolKind, ToolOutput, ToolState, Usage } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* What a driver reports. Deltas, never snapshots: the reducer accumulates
|
|
5
|
+
* them, so a tool part cannot vanish because a driver forgot to repeat it.
|
|
6
|
+
* `parent` names the tool call a subagent's event belongs under.
|
|
7
|
+
*/
|
|
8
|
+
export type DriverEvent =
|
|
9
|
+
/** Assistant text: `delta` appends, `text` replaces (a finished block). */
|
|
10
|
+
{
|
|
11
|
+
type: 'text';
|
|
12
|
+
id: string;
|
|
13
|
+
delta?: string;
|
|
14
|
+
text?: string;
|
|
15
|
+
done?: boolean;
|
|
16
|
+
reasoning?: boolean;
|
|
17
|
+
parent?: string;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'tool-start';
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
kind?: ToolKind;
|
|
24
|
+
title?: string;
|
|
25
|
+
input?: unknown;
|
|
26
|
+
app?: boolean;
|
|
27
|
+
parent?: string;
|
|
28
|
+
}
|
|
29
|
+
/** A piece of the arguments' JSON. */
|
|
30
|
+
| {
|
|
31
|
+
type: 'tool-input';
|
|
32
|
+
id: string;
|
|
33
|
+
delta: string;
|
|
34
|
+
} | {
|
|
35
|
+
type: 'tool-update';
|
|
36
|
+
id: string;
|
|
37
|
+
input?: unknown;
|
|
38
|
+
title?: string;
|
|
39
|
+
kind?: ToolKind;
|
|
40
|
+
state?: ToolState;
|
|
41
|
+
/** Replaces the outputs. */
|
|
42
|
+
output?: readonly ToolOutput[];
|
|
43
|
+
/** Appended to them. */
|
|
44
|
+
append?: ToolOutput;
|
|
45
|
+
progress?: string;
|
|
46
|
+
} | {
|
|
47
|
+
type: 'tool-end';
|
|
48
|
+
id: string;
|
|
49
|
+
state: 'done' | 'error' | 'denied' | 'cancelled';
|
|
50
|
+
output?: readonly ToolOutput[];
|
|
51
|
+
error?: string;
|
|
52
|
+
} | {
|
|
53
|
+
type: 'plan';
|
|
54
|
+
entries: readonly PlanEntry[];
|
|
55
|
+
parent?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A message the harness took from someone other than the user — another
|
|
59
|
+
* session, a channel — and is acting on. A turn starts with it if none is
|
|
60
|
+
* running, as one does for `send`.
|
|
61
|
+
*/
|
|
62
|
+
| {
|
|
63
|
+
type: 'message';
|
|
64
|
+
id: string;
|
|
65
|
+
text: string;
|
|
66
|
+
from: MessageSource;
|
|
67
|
+
} | {
|
|
68
|
+
type: 'notice';
|
|
69
|
+
level: 'info' | 'warning' | 'error';
|
|
70
|
+
text: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'info';
|
|
73
|
+
info: Partial<SessionInfo>;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'usage';
|
|
76
|
+
usage: Usage;
|
|
77
|
+
} | {
|
|
78
|
+
type: 'turn-end';
|
|
79
|
+
reason: 'done' | 'stopped' | 'error' | 'limit';
|
|
80
|
+
error?: string;
|
|
81
|
+
};
|
|
82
|
+
/** The policy's answer, fast, with no user involved. */
|
|
83
|
+
export type GateDecision = {
|
|
84
|
+
behavior: 'allow';
|
|
85
|
+
input?: unknown;
|
|
86
|
+
} | {
|
|
87
|
+
behavior: 'deny';
|
|
88
|
+
message: string;
|
|
89
|
+
}
|
|
90
|
+
/** The user must decide: the driver routes the call to `approve`. */
|
|
91
|
+
| {
|
|
92
|
+
behavior: 'ask';
|
|
93
|
+
}
|
|
94
|
+
/** No opinion: the harness's own permission mode decides. */
|
|
95
|
+
| {
|
|
96
|
+
behavior: 'defer';
|
|
97
|
+
};
|
|
98
|
+
/** The user's answer, through the approval row. */
|
|
99
|
+
export type ApprovalResult = {
|
|
100
|
+
behavior: 'allow';
|
|
101
|
+
input?: unknown;
|
|
102
|
+
} | {
|
|
103
|
+
behavior: 'deny';
|
|
104
|
+
message: string;
|
|
105
|
+
interrupt?: boolean;
|
|
106
|
+
};
|
|
107
|
+
/** What a driver may ask of the session. */
|
|
108
|
+
export interface DriverHost {
|
|
109
|
+
readonly config: DriverConfig;
|
|
110
|
+
emit(event: DriverEvent): void;
|
|
111
|
+
/** Before a tool runs: the app's `onToolCall`, then the policy. Never
|
|
112
|
+
* waits on the user, so a harness hook with a timeout can call it. */
|
|
113
|
+
gate(call: ToolCall): Promise<GateDecision>;
|
|
114
|
+
/** The approval row: waits on the user, and while the session is paused.
|
|
115
|
+
* Has no timeout. */
|
|
116
|
+
approve(call: ToolCall, signal?: AbortSignal): Promise<ApprovalResult>;
|
|
117
|
+
/** A question for the user (`AskUserQuestion`). `null` if dismissed. */
|
|
118
|
+
ask(id: string, questions: readonly Question[], signal?: AbortSignal): Promise<Record<string, string> | null>;
|
|
119
|
+
/** Run one of the app's tools. Never throws: a failure is a result. */
|
|
120
|
+
runTool(name: string, input: unknown, ctx: {
|
|
121
|
+
callId?: string;
|
|
122
|
+
signal?: AbortSignal;
|
|
123
|
+
}): Promise<ToolResult>;
|
|
124
|
+
}
|
|
125
|
+
/** The session's options, resolved for a driver. */
|
|
126
|
+
export interface DriverConfig {
|
|
127
|
+
cwd: string;
|
|
128
|
+
folders: readonly string[];
|
|
129
|
+
/** Appended to the harness's own system prompt. Empty for none. */
|
|
130
|
+
instructions: string;
|
|
131
|
+
/** Replaces the harness's system prompt. */
|
|
132
|
+
systemPrompt?: string;
|
|
133
|
+
/** Categories and harness names switched off. */
|
|
134
|
+
removed: readonly string[];
|
|
135
|
+
/** Categories and harness names that always ask. */
|
|
136
|
+
asking: readonly string[];
|
|
137
|
+
/** Categories replaced by one of `tools`, by the tool's name. */
|
|
138
|
+
replaced: Readonly<Partial<Record<CoreToolKey, string>>>;
|
|
139
|
+
/** The app's tools, replacements included, by name. */
|
|
140
|
+
tools: ReadonlyMap<string, AnyToolDef>;
|
|
141
|
+
permissions: PermissionPolicy;
|
|
142
|
+
model?: string;
|
|
143
|
+
mode?: string;
|
|
144
|
+
/** A harness session id to resume. */
|
|
145
|
+
resume?: string;
|
|
146
|
+
settings: 'cli' | 'isolated';
|
|
147
|
+
driverOptions: Readonly<Record<string, unknown>>;
|
|
148
|
+
}
|
|
149
|
+
/** A message on its way to the harness. */
|
|
150
|
+
export interface OutgoingMessage {
|
|
151
|
+
/** The transcript's id for it. */
|
|
152
|
+
id: string;
|
|
153
|
+
text: string;
|
|
154
|
+
attachments: readonly Attachment[];
|
|
155
|
+
/** Sent while a turn runs; the driver delivers it as steering. */
|
|
156
|
+
steer: boolean;
|
|
157
|
+
/** Sent on another session's behalf. Absent: the user's own. */
|
|
158
|
+
from?: PeerSource;
|
|
159
|
+
}
|
|
160
|
+
export interface DriverSession {
|
|
161
|
+
readonly capabilities: Capabilities;
|
|
162
|
+
send(message: OutgoingMessage): void;
|
|
163
|
+
/** Stop the turn. The driver ends it with `turn-end` `'stopped'`. */
|
|
164
|
+
interrupt(): Promise<void>;
|
|
165
|
+
setModel?(id: string): Promise<void>;
|
|
166
|
+
setMode?(id: string): Promise<void>;
|
|
167
|
+
close(): Promise<void>;
|
|
168
|
+
}
|
|
169
|
+
export interface AgentDriver {
|
|
170
|
+
/** `'claude'`, `'fake'`: shown, and `SessionInfo.agent`. */
|
|
171
|
+
readonly name: string;
|
|
172
|
+
/**
|
|
173
|
+
* Start the harness. Throw `AgentUnavailableError` when it cannot run
|
|
174
|
+
* here — no SDK, no binary, no key — which is an ordinary state of a
|
|
175
|
+
* healthy machine, and the view shows the `fallback`.
|
|
176
|
+
*/
|
|
177
|
+
start(host: DriverHost): Promise<DriverSession>;
|
|
178
|
+
}
|
|
179
|
+
/** The harness cannot run here. Not a bug: the view shows its `fallback`. */
|
|
180
|
+
export declare class AgentUnavailableError extends Error {
|
|
181
|
+
readonly name = "AgentUnavailableError";
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/core/driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// The seam between the session and a harness.
|
|
2
|
+
//
|
|
3
|
+
// A driver turns one harness's protocol into `DriverEvent`s, and asks the
|
|
4
|
+
// session — through `DriverHost` — every question the protocol asks the
|
|
5
|
+
// client: may this tool run, what did the user answer, run the app's tool.
|
|
6
|
+
// It is public for the reason `ProcessHost` is in `@react-x11/components`:
|
|
7
|
+
// driving a harness nobody wrapped yet should not need a fork.
|
|
8
|
+
/** The harness cannot run here. Not a bug: the view shows its `fallback`. */
|
|
9
|
+
export class AgentUnavailableError extends Error {
|
|
10
|
+
name = 'AgentUnavailableError';
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/core/driver.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,2EAA2E;AAC3E,2EAA2E;AAC3E,+DAA+D;AAqL/D,6EAA6E;AAC7E,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC5B,IAAI,GAAG,uBAAuB,CAAC;CAClD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createAgentSession, describeRenderers, type AgentOptions, type AgentSession, type CoreToolSetting, type SessionSnapshot, } from './session.js';
|
|
2
|
+
export { AgentUnavailableError, type AgentDriver, type ApprovalResult, type DriverConfig, type DriverEvent, type DriverHost, type DriverSession, type GateDecision, type OutgoingMessage, } from './driver.js';
|
|
3
|
+
export { defineTool, errorResult, isStandardSchema, jsonSchemaOf, normalizeResult, validateInput, type AnyToolDef, type InferInput, type JsonObjectSchema, type StandardSchemaLike, type ToolContext, type ToolDef, type ToolParameters, type ToolRenderInfo, type ToolResult, } from './tools.js';
|
|
4
|
+
export { reduce, restore, findLivePart, findPart, type TranscriptAction, } from './reducer.js';
|
|
5
|
+
export { categoryOf, policyDecision } from './policy.js';
|
|
6
|
+
export { messageMarkdown, sourceLabel, transcriptMarkdown, } from './markdown.js';
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,MAAM,EACN,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,eAAe,EACf,WAAW,EACX,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// `@windowkit/agent-chat/core`: the session, the message model, the driver
|
|
2
|
+
// seam and the tool helpers. No React, and no renderer: a DOM or terminal
|
|
3
|
+
// front end can drive the same session.
|
|
4
|
+
export { createAgentSession, describeRenderers, } from './session.js';
|
|
5
|
+
export { AgentUnavailableError, } from './driver.js';
|
|
6
|
+
export { defineTool, errorResult, isStandardSchema, jsonSchemaOf, normalizeResult, validateInput, } from './tools.js';
|
|
7
|
+
export { reduce, restore, findLivePart, findPart, } from './reducer.js';
|
|
8
|
+
export { categoryOf, policyDecision } from './policy.js';
|
|
9
|
+
export { messageMarkdown, sourceLabel, transcriptMarkdown, } from './markdown.js';
|
|
10
|
+
export * from './types.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,0EAA0E;AAC1E,wCAAwC;AAExC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,GAKlB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,qBAAqB,GAStB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,aAAa,GAUd,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,MAAM,EACN,OAAO,EACP,YAAY,EACZ,QAAQ,GAET,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,eAAe,EACf,WAAW,EACX,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentMessage, MessageSource } from './types.js';
|
|
2
|
+
/** What a message's author is called: a peer's name, or its id; a
|
|
3
|
+
* channel's server. */
|
|
4
|
+
export declare function sourceLabel(from: MessageSource): string;
|
|
5
|
+
export declare function messageMarkdown(message: AgentMessage): string;
|
|
6
|
+
export declare function transcriptMarkdown(messages: readonly AgentMessage[]): string;
|
|
7
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/core/markdown.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAQ,MAAM,YAAY,CAAC;AAEpE;wBACwB;AACxB,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAEvD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAE7D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAW5E"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// A transcript as markdown: what Copy puts on the clipboard, and what an app
|
|
2
|
+
// saves. Text is written as the agent wrote it; a tool call is one line,
|
|
3
|
+
// since its output is the harness's and usually long.
|
|
4
|
+
/** What a message's author is called: a peer's name, or its id; a
|
|
5
|
+
* channel's server. */
|
|
6
|
+
export function sourceLabel(from) {
|
|
7
|
+
return from.kind === 'peer' ? from.name || from.id : from.server;
|
|
8
|
+
}
|
|
9
|
+
export function messageMarkdown(message) {
|
|
10
|
+
return message.parts.map(partMarkdown).filter(Boolean).join('\n\n');
|
|
11
|
+
}
|
|
12
|
+
export function transcriptMarkdown(messages) {
|
|
13
|
+
return messages
|
|
14
|
+
.map((m) => {
|
|
15
|
+
const body = messageMarkdown(m);
|
|
16
|
+
if (!body)
|
|
17
|
+
return '';
|
|
18
|
+
if (m.role !== 'user')
|
|
19
|
+
return body;
|
|
20
|
+
const who = m.from ? `From ${sourceLabel(m.from)}` : 'You';
|
|
21
|
+
return `**${who}:**\n\n${body}`;
|
|
22
|
+
})
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.join('\n\n---\n\n');
|
|
25
|
+
}
|
|
26
|
+
function partMarkdown(part) {
|
|
27
|
+
switch (part.type) {
|
|
28
|
+
case 'text':
|
|
29
|
+
return part.text;
|
|
30
|
+
case 'reasoning':
|
|
31
|
+
return '';
|
|
32
|
+
case 'tool':
|
|
33
|
+
return `> ${part.title}${part.state === 'done' ? '' : ` (${part.state})`}`;
|
|
34
|
+
case 'plan':
|
|
35
|
+
return part.entries
|
|
36
|
+
.map((e) => `- [${e.status === 'completed' ? 'x' : ' '}] ${e.text}`)
|
|
37
|
+
.join('\n');
|
|
38
|
+
case 'question':
|
|
39
|
+
return part.questions
|
|
40
|
+
.map((q) => {
|
|
41
|
+
const a = part.answers?.[q.question];
|
|
42
|
+
return a ? `> ${q.question}\n>\n> ${a}` : `> ${q.question}`;
|
|
43
|
+
})
|
|
44
|
+
.join('\n\n');
|
|
45
|
+
case 'file':
|
|
46
|
+
return `[${part.label}]`;
|
|
47
|
+
case 'notice':
|
|
48
|
+
return `_${part.text}_`;
|
|
49
|
+
case 'data':
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/core/markdown.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,yEAAyE;AACzE,sDAAsD;AAItD;wBACwB;AACxB,MAAM,UAAU,WAAW,CAAC,IAAmB;IAC7C,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAqB;IACnD,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAiC;IAClE,OAAO,QAAQ;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC3D,OAAO,KAAK,GAAG,UAAU,IAAI,EAAE,CAAC;IAClC,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,aAAa,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,YAAY,CAAC,IAAU;IAC9B,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,KAAK,WAAW;YACd,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,KAAK,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAC7E,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,OAAO;iBAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;iBACnE,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,IAAI,CAAC,SAAS;iBAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACT,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBACrC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC9D,CAAC,CAAC;iBACD,IAAI,CAAC,MAAM,CAAC,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;QAC3B,KAAK,QAAQ;YACX,OAAO,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC;QAC1B,KAAK,MAAM;YACT,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DriverConfig, GateDecision } from './driver.js';
|
|
2
|
+
import type { CoreToolKey, ToolCall, ToolKind } from './types.js';
|
|
3
|
+
/** The `coreTools` category a tool kind belongs to. */
|
|
4
|
+
export declare function categoryOf(kind: ToolKind): CoreToolKey | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* | policy | reads | edits | anything else |
|
|
7
|
+
* | ------------- | ----- | ----- | ------------- |
|
|
8
|
+
* | `'ask'` | run | ask | ask |
|
|
9
|
+
* | `'edits'` | run | run | ask |
|
|
10
|
+
* | `'read-only'` | run | deny | deny |
|
|
11
|
+
* | `'auto'` | the harness decides |
|
|
12
|
+
*
|
|
13
|
+
* Over all of it: an app tool runs unless its `ask` says otherwise, a
|
|
14
|
+
* category or name in `coreTools` set to `'ask'` always asks, and one set to
|
|
15
|
+
* `false` that a harness could not remove is denied.
|
|
16
|
+
*/
|
|
17
|
+
export declare function policyDecision(call: ToolCall, config: DriverConfig): GateDecision;
|
|
18
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/core/policy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAElE,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAgBlE;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,YAAY,GACnB,YAAY,CAiCd"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// The permission policy: what runs without asking, before the app's
|
|
2
|
+
// `onToolCall` has had a say. Pure, so the table below is the whole story.
|
|
3
|
+
/** The `coreTools` category a tool kind belongs to. */
|
|
4
|
+
export function categoryOf(kind) {
|
|
5
|
+
switch (kind) {
|
|
6
|
+
case 'execute':
|
|
7
|
+
return 'shell';
|
|
8
|
+
case 'read':
|
|
9
|
+
case 'search':
|
|
10
|
+
return 'read';
|
|
11
|
+
case 'edit':
|
|
12
|
+
case 'delete':
|
|
13
|
+
case 'move':
|
|
14
|
+
return 'edit';
|
|
15
|
+
case 'fetch':
|
|
16
|
+
return 'web';
|
|
17
|
+
default:
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const READS = new Set(['read', 'search', 'think']);
|
|
22
|
+
const EDITS = new Set(['edit', 'move']);
|
|
23
|
+
/**
|
|
24
|
+
* | policy | reads | edits | anything else |
|
|
25
|
+
* | ------------- | ----- | ----- | ------------- |
|
|
26
|
+
* | `'ask'` | run | ask | ask |
|
|
27
|
+
* | `'edits'` | run | run | ask |
|
|
28
|
+
* | `'read-only'` | run | deny | deny |
|
|
29
|
+
* | `'auto'` | the harness decides |
|
|
30
|
+
*
|
|
31
|
+
* Over all of it: an app tool runs unless its `ask` says otherwise, a
|
|
32
|
+
* category or name in `coreTools` set to `'ask'` always asks, and one set to
|
|
33
|
+
* `false` that a harness could not remove is denied.
|
|
34
|
+
*/
|
|
35
|
+
export function policyDecision(call, config) {
|
|
36
|
+
const category = categoryOf(call.kind);
|
|
37
|
+
const named = (list) => list.includes(call.label) ||
|
|
38
|
+
(!call.app && !!category && list.includes(category));
|
|
39
|
+
if (named(config.removed)) {
|
|
40
|
+
return { behavior: 'deny', message: `${call.label} is turned off here.` };
|
|
41
|
+
}
|
|
42
|
+
if (call.app) {
|
|
43
|
+
const tool = config.tools.get(call.label);
|
|
44
|
+
return tool?.ask ? { behavior: 'ask' } : { behavior: 'allow' };
|
|
45
|
+
}
|
|
46
|
+
if (named(config.asking))
|
|
47
|
+
return { behavior: 'ask' };
|
|
48
|
+
switch (config.permissions) {
|
|
49
|
+
case 'auto':
|
|
50
|
+
return { behavior: 'defer' };
|
|
51
|
+
case 'read-only':
|
|
52
|
+
return READS.has(call.kind)
|
|
53
|
+
? { behavior: 'allow' }
|
|
54
|
+
: {
|
|
55
|
+
behavior: 'deny',
|
|
56
|
+
message: 'This session is read-only: nothing may be changed.',
|
|
57
|
+
};
|
|
58
|
+
case 'edits':
|
|
59
|
+
return READS.has(call.kind) || EDITS.has(call.kind)
|
|
60
|
+
? { behavior: 'allow' }
|
|
61
|
+
: { behavior: 'ask' };
|
|
62
|
+
case 'ask':
|
|
63
|
+
default:
|
|
64
|
+
return READS.has(call.kind) ? { behavior: 'allow' } : { behavior: 'ask' };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/core/policy.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,2EAA2E;AAK3E,uDAAuD;AACvD,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,SAAS;YACZ,OAAO,OAAO,CAAC;QACjB,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC;QAChB,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,KAAK,CAAC;QACf;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,MAAM,KAAK,GAA0B,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1E,MAAM,KAAK,GAA0B,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE/D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAc,EACd,MAAoB;IAEpB,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,IAAuB,EAAE,EAAE,CACxC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;QACzB,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEvD,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,sBAAsB,EAAE,CAAC;IAC5E,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IACjE,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAErD,QAAQ,MAAM,CAAC,WAAW,EAAE,CAAC;QAC3B,KAAK,MAAM;YACT,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC/B,KAAK,WAAW;YACd,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBACzB,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE;gBACvB,CAAC,CAAC;oBACE,QAAQ,EAAE,MAAM;oBAChB,OAAO,EAAE,oDAAoD;iBAC9D,CAAC;QACR,KAAK,OAAO;YACV,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBACjD,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE;gBACvB,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC1B,KAAK,KAAK,CAAC;QACX;YACE,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC9E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { DriverEvent } from './driver.js';
|
|
2
|
+
import type { AgentMessage, ApprovalOption, Part, Question, ToolOutput } from './types.js';
|
|
3
|
+
export type TranscriptAction = DriverEvent
|
|
4
|
+
/** The user sent a message. */
|
|
5
|
+
| {
|
|
6
|
+
type: 'user';
|
|
7
|
+
message: AgentMessage;
|
|
8
|
+
}
|
|
9
|
+
/** A queued message is being sent now. */
|
|
10
|
+
| {
|
|
11
|
+
type: 'unqueue';
|
|
12
|
+
id: string;
|
|
13
|
+
}
|
|
14
|
+
/** A tool call waits for the user. */
|
|
15
|
+
| {
|
|
16
|
+
type: 'approval';
|
|
17
|
+
id: string;
|
|
18
|
+
options: readonly ApprovalOption[];
|
|
19
|
+
reason?: string;
|
|
20
|
+
}
|
|
21
|
+
/** The user, or the policy, answered it. */
|
|
22
|
+
| {
|
|
23
|
+
type: 'approved';
|
|
24
|
+
id: string;
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
} | {
|
|
27
|
+
type: 'question';
|
|
28
|
+
id: string;
|
|
29
|
+
questions: readonly Question[];
|
|
30
|
+
} | {
|
|
31
|
+
type: 'answered';
|
|
32
|
+
id: string;
|
|
33
|
+
answers: Readonly<Record<string, string>> | null;
|
|
34
|
+
}
|
|
35
|
+
/** The turn was stopped: what was open is cancelled. */
|
|
36
|
+
| {
|
|
37
|
+
type: 'stopped';
|
|
38
|
+
};
|
|
39
|
+
type Messages = readonly AgentMessage[];
|
|
40
|
+
export declare function reduce(messages: Messages, action: TranscriptAction, now?: number): Messages;
|
|
41
|
+
/**
|
|
42
|
+
* A transcript saved from an earlier session, made ready to show again:
|
|
43
|
+
* whatever was queued was never sent and is dropped, and whatever was still
|
|
44
|
+
* open ends as a stopped turn does — a stream stops streaming, a tool call
|
|
45
|
+
* is cancelled, a question is closed. Nothing in it is live any more.
|
|
46
|
+
*/
|
|
47
|
+
export declare function restore(messages: Messages): Messages;
|
|
48
|
+
/** The part with this id, in any message. */
|
|
49
|
+
export declare function findPart(messages: Messages, id: string): Part | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* The part with this id in a turn still under way: what an event may touch.
|
|
52
|
+
* A driver's ids are unique within a turn, not across a session — a script
|
|
53
|
+
* that names its calls runs the same names every turn — so a finished turn's
|
|
54
|
+
* parts are never the ones an event means. They keep the state they ended in.
|
|
55
|
+
*/
|
|
56
|
+
export declare function findLivePart(messages: Messages, id: string): Part | undefined;
|
|
57
|
+
/** A tool's progress line: a text output it replaces as it goes, and drops
|
|
58
|
+
* when the tool ends. */
|
|
59
|
+
export declare function isProgress(o: ToolOutput): boolean;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=reducer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/core/reducer.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,UAAU,EAGX,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,gBAAgB,GACxB,WAAW;AACb,+BAA+B;GAC7B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE;AACzC,0CAA0C;GACxC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AACjC,sCAAsC;GACpC;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AACH,4CAA4C;GAC1C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAA;CAAE,GAChE;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;CAClD;AACH,wDAAwD;GACtD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,KAAK,QAAQ,GAAG,SAAS,YAAY,EAAE,CAAC;AASxC,wBAAgB,MAAM,CACpB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,gBAAgB,EACxB,GAAG,GAAE,MAAmB,GACvB,QAAQ,CA+HV;AAuKD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAKpD;AA0CD,6CAA6C;AAC7C,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE7E;AAsED;0BAC0B;AAC1B,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAEjD"}
|