paseo-terminal-integration 0.2.0 → 0.3.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/README.md +30 -27
- package/client/run-card.tsx +18 -34
- package/client/settings-screen.tsx +6 -19
- package/index.client.tsx +6 -39
- package/index.server.ts +9 -16
- package/package.json +2 -8
- package/server/runner.ts +174 -16
- package/shared/contracts.ts +7 -29
- package/shared/settings.ts +1 -8
- package/shared/text.ts +1 -1
- package/client/panel-opener.ts +0 -29
- package/client/terminal-panel.tsx +0 -273
- package/client/xterm-modules.d.ts +0 -13
- package/client/xterm-view.tsx +0 -222
- package/server/streams.ts +0 -228
package/README.md
CHANGED
|
@@ -6,27 +6,26 @@ Two-way bridge between agent chats and Paseo terminals.
|
|
|
6
6
|
(`bash`, `sh`, `shell`, `console`, `zsh`, `fish`, `python`, `js`/`node`) get a **Run in terminal**
|
|
7
7
|
card under the reply:
|
|
8
8
|
|
|
9
|
-
- **Run
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
- **Run** runs the block in the workspace terminal "Agent commands", a regular Paseo terminal tab.
|
|
10
|
+
- **Run in background** runs it as a hidden process in the agent's working directory: no terminal
|
|
11
|
+
tab, and the card keeps the last 5,000 lines instead of what fits on a terminal screen. Nothing
|
|
12
|
+
can be typed into it: stdin is empty, so password and confirmation prompts fail instead of
|
|
13
|
+
waiting. Background runs do not wait for the terminal.
|
|
14
|
+
- With **Send output to agent** checked (the default), the command, exit code, and output go to
|
|
15
|
+
the agent as a new message when the block finishes. If the agent is busy, delivery waits until
|
|
16
|
+
its turn ends instead of interrupting it. Unchecked, **Send output** sends it later.
|
|
14
17
|
- **Stop** sends Ctrl-C; **Send output so far** reports a still-running command.
|
|
15
18
|
|
|
16
|
-
**Terminal
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Paseo gives every workspace terminal its own tab, so "Agent commands" also appears in the tab bar
|
|
27
|
-
(in the background). Closing that tab ends the terminal; the next run starts a new one. Runs in
|
|
28
|
-
one workspace are queued so a command never types into another one's stdin. Each block runs as a
|
|
29
|
-
script in the agent's working directory, so `cd` and `export` do not persist between runs.
|
|
19
|
+
**Terminal beside the chat.** "Agent commands" opens as a background tab. Drag the tab onto the
|
|
20
|
+
right or bottom edge of the chat to split the workspace; it stays there while the terminal is open,
|
|
21
|
+
so you can watch runs and type answers to `sudo` passwords or `y/n` questions next to the
|
|
22
|
+
conversation. From the keyboard, split the pane and move the tab into it with the shortcuts in
|
|
23
|
+
**Settings → Shortcuts → Tabs & panes**. Closing the tab ends the terminal; the next run starts a
|
|
24
|
+
new one in a new tab.
|
|
25
|
+
|
|
26
|
+
Terminal runs in one workspace are queued so a command never types into another one's stdin.
|
|
27
|
+
Each block runs as a script in the agent's working directory, so `cd` and `export` do not persist
|
|
28
|
+
between runs. **Settings → Plugins → Terminal integration** sets the checkbox's default.
|
|
30
29
|
|
|
31
30
|
**Terminal → agent.** In the composer's attachment menu, **Terminal output** attaches the latest
|
|
32
31
|
lines of any terminal on the daemon. Type part of a name or path to filter, and a number to choose
|
|
@@ -39,10 +38,10 @@ Requires Paseo 0.10.1 or later and a macOS or Linux daemon host with `bash` (plu
|
|
|
39
38
|
|
|
40
39
|
```bash
|
|
41
40
|
paseo plugin install npm:paseo-terminal-integration
|
|
41
|
+
# or from GitHub
|
|
42
|
+
paseo plugin install github:keefeere/paseo-terminal-integration
|
|
42
43
|
```
|
|
43
44
|
|
|
44
|
-
Install from npm: GitHub installs skip npm dependencies, which the terminal panel needs.
|
|
45
|
-
|
|
46
45
|
Plugins are trusted, unsandboxed code: this one types commands into terminals on the daemon host.
|
|
47
46
|
Nothing runs until you press a button or submit `/run`.
|
|
48
47
|
|
|
@@ -53,17 +52,13 @@ Nothing runs until you press a button or submit `/run`.
|
|
|
53
52
|
| `/run <command>` | Run a shell command and send its output to the agent |
|
|
54
53
|
| `/blocks` | Add a run card for the latest reply (e.g. older chats) |
|
|
55
54
|
| ⌘K / Ctrl+K → "Terminal: add run buttons to …" | Same as `/blocks` |
|
|
56
|
-
| ⌘K / Ctrl+K → "Terminal: show … in the side panel" | Open the terminal panel in the Explorer |
|
|
57
55
|
|
|
58
56
|
## Limitations
|
|
59
57
|
|
|
60
|
-
-
|
|
58
|
+
- Terminal output is read from the screen, so very long lines arrive wrapped and only the last
|
|
61
59
|
3,000 rows are visible. The agent receives at most 300 lines or 24,000 characters.
|
|
62
60
|
- Run state lives in the plugin process; reloading the plugin forgets it (the cards stay).
|
|
63
|
-
-
|
|
64
|
-
`$PASEO_HOME/paseo.pid` and the local credential, as the `paseo` CLI does. A daemon listening on
|
|
65
|
-
a Unix socket gets the plain-text panel instead.
|
|
66
|
-
- Opening or resizing the panel resizes the PTY to fit it, as focusing a terminal tab does.
|
|
61
|
+
- Plugins cannot split panes or move tabs, so placing the terminal beside the chat is up to you.
|
|
67
62
|
- A command that has not started within 20 seconds fails, for example when something else is
|
|
68
63
|
running in "Agent commands".
|
|
69
64
|
|
|
@@ -77,6 +72,14 @@ paseo plugin reload terminal-integration
|
|
|
77
72
|
paseo plugin logs terminal-integration
|
|
78
73
|
```
|
|
79
74
|
|
|
75
|
+
To release, bump the version and push the tag; GitHub Actions publishes it to npm through trusted
|
|
76
|
+
publishing, and Paseo Cafe picks up the new version from there:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm version patch # or minor; commits and tags vX.Y.Z
|
|
80
|
+
git push --follow-tags
|
|
81
|
+
```
|
|
82
|
+
|
|
80
83
|
## License
|
|
81
84
|
|
|
82
85
|
MIT
|
package/client/run-card.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useRpc, useSettings, type PluginTimelineItemProps } from "@getpaseo/plugin/client";
|
|
2
2
|
import { copyText, Icon, useToast } from "@getpaseo/plugin/client/react-native";
|
|
3
3
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
4
|
import { useMemo, useState } from "react";
|
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
startRun,
|
|
12
12
|
TERMINAL_NAME,
|
|
13
13
|
type RunCardData,
|
|
14
|
+
type RunMode,
|
|
14
15
|
type RunSnapshot,
|
|
15
16
|
} from "../shared/contracts";
|
|
16
17
|
import { preferences } from "../shared/settings";
|
|
17
|
-
import { openTerminalPanel } from "./panel-opener";
|
|
18
18
|
|
|
19
19
|
type Theme = PluginTimelineItemProps["theme"];
|
|
20
20
|
type Styles = ReturnType<typeof createStyles>;
|
|
@@ -44,24 +44,15 @@ export function RunCard({ item, agentId, theme, layout }: PluginTimelineItemProp
|
|
|
44
44
|
const cancel = useRpc(cancelRun);
|
|
45
45
|
const send = useRpc(sendRunOutput);
|
|
46
46
|
|
|
47
|
-
const workspaceId = useAgent(agentId, (agent) => agent.workspaceId);
|
|
48
47
|
const settings = useSettings(preferences);
|
|
49
|
-
const saved = settings.status === "ready" ? settings.values : null;
|
|
50
|
-
const panelLocation = saved?.panelLocation ?? "explorer";
|
|
51
48
|
const [sendChoice, setSendChoice] = useState<boolean | null>(null);
|
|
52
|
-
const sendToAgent =
|
|
53
|
-
|
|
54
|
-
layout.compact || panelLocation === "workspace" ? "Run in terminal tab" : "Run in side terminal";
|
|
49
|
+
const sendToAgent =
|
|
50
|
+
sendChoice ?? (settings.status === "ready" ? settings.values.sendToAgent : true);
|
|
55
51
|
|
|
56
|
-
function
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
function runBlock(key: string, block: RunCardData["blocks"][number], visible: boolean) {
|
|
61
|
-
return act(key, async () => {
|
|
62
|
-
await start({ agentId, key, lang: block.lang, code: block.code, send: sendToAgent });
|
|
63
|
-
if (visible) showTerminal();
|
|
64
|
-
});
|
|
52
|
+
function runBlock(key: string, block: RunCardData["blocks"][number], mode: RunMode) {
|
|
53
|
+
return act(key, () =>
|
|
54
|
+
start({ agentId, key, lang: block.lang, code: block.code, send: sendToAgent, mode }),
|
|
55
|
+
);
|
|
65
56
|
}
|
|
66
57
|
|
|
67
58
|
const queryKey = useMemo(() => ["terminal-run-status", cardId], [cardId]);
|
|
@@ -99,19 +90,10 @@ export function RunCard({ item, agentId, theme, layout }: PluginTimelineItemProp
|
|
|
99
90
|
<Checkbox
|
|
100
91
|
styles={styles}
|
|
101
92
|
theme={theme}
|
|
102
|
-
label="Send to agent"
|
|
93
|
+
label="Send output to agent"
|
|
103
94
|
checked={sendToAgent}
|
|
104
95
|
onChange={setSendChoice}
|
|
105
96
|
/>
|
|
106
|
-
{workspaceId ? (
|
|
107
|
-
<ActionButton
|
|
108
|
-
styles={styles}
|
|
109
|
-
theme={theme}
|
|
110
|
-
icon="PanelRight"
|
|
111
|
-
label="Terminal"
|
|
112
|
-
onPress={showTerminal}
|
|
113
|
-
/>
|
|
114
|
-
) : null}
|
|
115
97
|
</View>
|
|
116
98
|
{blocks.map((block, index) => {
|
|
117
99
|
const key = keys[index];
|
|
@@ -154,19 +136,19 @@ export function RunCard({ item, agentId, theme, layout }: PluginTimelineItemProp
|
|
|
154
136
|
<ActionButton
|
|
155
137
|
styles={styles}
|
|
156
138
|
theme={theme}
|
|
157
|
-
icon="
|
|
158
|
-
label=
|
|
139
|
+
icon="Play"
|
|
140
|
+
label="Run"
|
|
159
141
|
tone="primary"
|
|
160
142
|
disabled={busy || active}
|
|
161
|
-
onPress={() => runBlock(key, block,
|
|
143
|
+
onPress={() => runBlock(key, block, "terminal")}
|
|
162
144
|
/>
|
|
163
145
|
<ActionButton
|
|
164
146
|
styles={styles}
|
|
165
147
|
theme={theme}
|
|
166
|
-
icon="
|
|
167
|
-
label="Run
|
|
148
|
+
icon="EyeOff"
|
|
149
|
+
label="Run in background"
|
|
168
150
|
disabled={busy || active}
|
|
169
|
-
onPress={() => runBlock(key, block,
|
|
151
|
+
onPress={() => runBlock(key, block, "background")}
|
|
170
152
|
/>
|
|
171
153
|
{run && !run.sent && !active ? (
|
|
172
154
|
<ActionButton
|
|
@@ -205,7 +187,9 @@ function RunStatus({ run, styles }: { run: RunSnapshot; styles: Styles }) {
|
|
|
205
187
|
const parts: string[] = [];
|
|
206
188
|
let tone: TextStyle = styles.muted;
|
|
207
189
|
if (run.status === "queued") parts.push("Queued, waiting for the terminal");
|
|
208
|
-
if (run.status === "running")
|
|
190
|
+
if (run.status === "running") {
|
|
191
|
+
parts.push(`${run.mode === "background" ? "Running in background" : "Running"} · ${elapsed(run)}`);
|
|
192
|
+
}
|
|
209
193
|
if (run.status === "done") {
|
|
210
194
|
parts.push(`${run.exitCode === 0 ? "✓" : "✗"} exit ${run.exitCode}`);
|
|
211
195
|
tone = run.exitCode === 0 ? styles.success : styles.danger;
|
|
@@ -3,16 +3,11 @@ import {
|
|
|
3
3
|
SettingsCard,
|
|
4
4
|
SettingsRow,
|
|
5
5
|
SettingsSection,
|
|
6
|
-
SettingsSelect,
|
|
7
6
|
SettingsSwitch,
|
|
8
7
|
} from "@getpaseo/plugin/client/ui";
|
|
9
8
|
import { Text } from "react-native";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
const panelLocationChoices: { label: string; value: PanelLocation }[] = [
|
|
13
|
-
{ label: "Side panel (Explorer)", value: "explorer" },
|
|
14
|
-
{ label: "Workspace tab", value: "workspace" },
|
|
15
|
-
];
|
|
9
|
+
import { TERMINAL_NAME } from "../shared/contracts";
|
|
10
|
+
import { preferences } from "../shared/settings";
|
|
16
11
|
|
|
17
12
|
export function SettingsScreen({ theme }: PluginSurfaceProps) {
|
|
18
13
|
const settings = useSettings(preferences);
|
|
@@ -27,25 +22,17 @@ export function SettingsScreen({ theme }: PluginSurfaceProps) {
|
|
|
27
22
|
return (
|
|
28
23
|
<SettingsSection title="Run cards">
|
|
29
24
|
<SettingsCard>
|
|
30
|
-
<SettingsSelect
|
|
31
|
-
label="Show the terminal in"
|
|
32
|
-
hint={`Used by "Run in side terminal", the Terminal button, and /run. Phones always use a tab and never switch to it automatically.`}
|
|
33
|
-
value={values.panelLocation}
|
|
34
|
-
options={panelLocationChoices}
|
|
35
|
-
disabled={settings.saving}
|
|
36
|
-
error={settings.saveError}
|
|
37
|
-
onValueChange={(panelLocation) => void settings.save({ ...values, panelLocation }, revision)}
|
|
38
|
-
/>
|
|
39
25
|
<SettingsSwitch
|
|
40
26
|
label="Send output to the agent by default"
|
|
41
|
-
hint={`Initial state of the "Send to agent" checkbox on each run card.`}
|
|
27
|
+
hint={`Initial state of the "Send output to agent" checkbox on each run card.`}
|
|
42
28
|
value={values.sendToAgent}
|
|
43
29
|
disabled={settings.saving}
|
|
30
|
+
error={settings.saveError}
|
|
44
31
|
onValueChange={(sendToAgent) => void settings.save({ ...values, sendToAgent }, revision)}
|
|
45
32
|
/>
|
|
46
33
|
<SettingsRow
|
|
47
|
-
label="
|
|
48
|
-
hint={`
|
|
34
|
+
label="Where the terminal appears"
|
|
35
|
+
hint={`Commands run in the "${TERMINAL_NAME}" terminal tab. To keep it beside the chat, drag the tab onto the right or bottom edge of the chat; it stays there while the terminal is open.`}
|
|
49
36
|
/>
|
|
50
37
|
</SettingsCard>
|
|
51
38
|
</SettingsSection>
|
package/index.client.tsx
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
|
+
import type { PluginCleanup } from "@getpaseo/plugin";
|
|
1
2
|
import type { PluginClientContext } from "@getpaseo/plugin/client";
|
|
2
|
-
import { setPanelOpener } from "./client/panel-opener";
|
|
3
3
|
import { RunCard } from "./client/run-card";
|
|
4
4
|
import { SettingsScreen } from "./client/settings-screen";
|
|
5
|
-
import { TerminalPanel } from "./client/terminal-panel";
|
|
6
5
|
import {
|
|
7
6
|
RUN_CARD_KIND,
|
|
8
7
|
RUN_CARD_VERSION,
|
|
9
8
|
runAdhoc,
|
|
10
9
|
runCardSchema,
|
|
11
10
|
scanBlocks,
|
|
12
|
-
TERMINAL_NAME,
|
|
13
11
|
terminalOutputSource,
|
|
14
12
|
} from "./shared/contracts";
|
|
15
|
-
import { TERMINAL_PANEL_ID } from "./shared/settings";
|
|
16
|
-
|
|
17
|
-
export default function contribute(client: PluginClientContext) {
|
|
18
|
-
setPanelOpener((id, options) => client.openPanel(id, options));
|
|
19
13
|
|
|
14
|
+
// A function declaration: the host reads the default export before the module body has run.
|
|
15
|
+
export default function contribute(client: PluginClientContext): PluginCleanup {
|
|
20
16
|
client.addTimelineRenderer({
|
|
21
17
|
kind: RUN_CARD_KIND,
|
|
22
18
|
version: RUN_CARD_VERSION,
|
|
@@ -24,15 +20,6 @@ export default function contribute(client: PluginClientContext) {
|
|
|
24
20
|
Component: RunCard,
|
|
25
21
|
});
|
|
26
22
|
|
|
27
|
-
client.addWorkspacePanel({
|
|
28
|
-
id: TERMINAL_PANEL_ID,
|
|
29
|
-
title: TERMINAL_NAME,
|
|
30
|
-
icon: "SquareTerminal",
|
|
31
|
-
context: "workspace",
|
|
32
|
-
locations: ["explorer", "workspace"],
|
|
33
|
-
Component: TerminalPanel,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
23
|
client.addSettingsScreen({
|
|
37
24
|
id: "preferences",
|
|
38
25
|
title: "Terminal integration",
|
|
@@ -47,14 +34,9 @@ export default function contribute(client: PluginClientContext) {
|
|
|
47
34
|
description: "Run a shell command in the workspace terminal and send its output to the agent",
|
|
48
35
|
argumentHint: "<command>",
|
|
49
36
|
context: "agent",
|
|
50
|
-
async onSubmit({ args, agent, rpc
|
|
37
|
+
async onSubmit({ args, agent, rpc }) {
|
|
51
38
|
if (!args) throw new Error("Usage: /run <command>");
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
openPanel(TERMINAL_PANEL_ID, { location: panelLocation });
|
|
55
|
-
} catch {
|
|
56
|
-
// Compact layouts have no Explorer; the card's Terminal button still opens a tab.
|
|
57
|
-
}
|
|
39
|
+
await rpc(runAdhoc, { agentId: agent.id, command: args });
|
|
58
40
|
},
|
|
59
41
|
});
|
|
60
42
|
|
|
@@ -80,20 +62,5 @@ export default function contribute(client: PluginClientContext) {
|
|
|
80
62
|
onSelect: ({ agent, rpc }) => addRunButtons(agent.id, rpc),
|
|
81
63
|
});
|
|
82
64
|
|
|
83
|
-
|
|
84
|
-
id: "open-terminal-panel",
|
|
85
|
-
title: `Terminal: show "${TERMINAL_NAME}" in the side panel`,
|
|
86
|
-
icon: "PanelRight",
|
|
87
|
-
keywords: ["terminal", "explorer", "sidebar", "agent commands"],
|
|
88
|
-
context: "workspace",
|
|
89
|
-
onSelect({ openPanel }) {
|
|
90
|
-
try {
|
|
91
|
-
openPanel(TERMINAL_PANEL_ID, { location: "explorer" });
|
|
92
|
-
} catch {
|
|
93
|
-
openPanel(TERMINAL_PANEL_ID, { location: "workspace" });
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
return () => setPanelOpener(null);
|
|
65
|
+
return () => {};
|
|
99
66
|
}
|
package/index.server.ts
CHANGED
|
@@ -2,14 +2,9 @@ import type { PluginServerContext } from "@getpaseo/plugin/server";
|
|
|
2
2
|
import { searchTerminals } from "./server/attachments";
|
|
3
3
|
import { appendCardForTurn, appendRunCard, scanLatestReply } from "./server/cards";
|
|
4
4
|
import { cleanupScripts, TerminalRunner } from "./server/runner";
|
|
5
|
-
import { TerminalStreams } from "./server/streams";
|
|
6
5
|
import { preferences } from "./shared/settings";
|
|
7
6
|
import {
|
|
8
7
|
cancelRun,
|
|
9
|
-
closeTerminalView,
|
|
10
|
-
openTerminalView,
|
|
11
|
-
readTerminalView,
|
|
12
|
-
resizeTerminalView,
|
|
13
8
|
runAdhoc,
|
|
14
9
|
runKey,
|
|
15
10
|
runStatus,
|
|
@@ -20,9 +15,8 @@ import {
|
|
|
20
15
|
} from "./shared/contracts";
|
|
21
16
|
|
|
22
17
|
export default function contribute(server: PluginServerContext) {
|
|
23
|
-
|
|
18
|
+
server.registerSettings(preferences);
|
|
24
19
|
let runner: TerminalRunner | null = null;
|
|
25
|
-
const streams = new TerminalStreams();
|
|
26
20
|
const runnerFor = (paseo: ConstructorParameters<typeof TerminalRunner>[0]) =>
|
|
27
21
|
(runner ??= new TerminalRunner(paseo));
|
|
28
22
|
|
|
@@ -37,9 +31,14 @@ export default function contribute(server: PluginServerContext) {
|
|
|
37
31
|
const block = { lang: "bash", code: command };
|
|
38
32
|
const cardId = await appendRunCard(paseo, agentId, [block]);
|
|
39
33
|
if (!cardId) throw new Error("Command is too long");
|
|
40
|
-
await runnerFor(paseo).start({
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
await runnerFor(paseo).start({
|
|
35
|
+
agentId,
|
|
36
|
+
key: runKey(cardId, 0),
|
|
37
|
+
...block,
|
|
38
|
+
send: true,
|
|
39
|
+
mode: "terminal",
|
|
40
|
+
});
|
|
41
|
+
return { cardId };
|
|
43
42
|
});
|
|
44
43
|
|
|
45
44
|
server.handle(scanBlocks, async ({ agentId }, { paseo }) => ({
|
|
@@ -48,14 +47,8 @@ export default function contribute(server: PluginServerContext) {
|
|
|
48
47
|
|
|
49
48
|
server.handle(searchTerminalOutput, searchTerminals);
|
|
50
49
|
|
|
51
|
-
server.handle(openTerminalView, (input) => streams.open(input));
|
|
52
|
-
server.handle(readTerminalView, (input) => streams.read(input));
|
|
53
|
-
server.handle(resizeTerminalView, (input) => streams.resize(input));
|
|
54
|
-
server.handle(closeTerminalView, (input) => streams.close(input));
|
|
55
|
-
|
|
56
50
|
return async () => {
|
|
57
51
|
runner?.stop();
|
|
58
|
-
await streams.stop();
|
|
59
52
|
await cleanupScripts();
|
|
60
53
|
};
|
|
61
54
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paseo-terminal-integration",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"files": [
|
|
5
5
|
"paseo-plugin.json",
|
|
6
6
|
"index.client.tsx",
|
|
@@ -38,11 +38,5 @@
|
|
|
38
38
|
"paseo-plugin",
|
|
39
39
|
"terminal",
|
|
40
40
|
"agents"
|
|
41
|
-
]
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"@getpaseo/client": "0.10.1",
|
|
44
|
-
"@xterm/addon-fit": "^0.11.0",
|
|
45
|
-
"@xterm/addon-web-links": "^0.12.0",
|
|
46
|
-
"@xterm/xterm": "^6.0.0"
|
|
47
|
-
}
|
|
41
|
+
]
|
|
48
42
|
}
|