paseo-terminal-integration 0.2.0 → 0.4.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 +48 -37
- package/client/code-block-actions.tsx +367 -0
- package/client/legacy.tsx +60 -0
- package/client/reveal-run.ts +24 -0
- package/client/run-card.tsx +20 -34
- package/client/sdk-compat.ts +34 -0
- package/client/settings-screen.tsx +7 -20
- package/index.client.tsx +26 -90
- package/index.server.ts +19 -17
- package/package.json +29 -28
- package/server/attachments.ts +3 -1
- package/server/runner.ts +183 -17
- package/shared/code-blocks.ts +13 -1
- package/shared/contracts.ts +26 -30
- 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/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,11 @@ 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(
|
|
192
|
+
`${run.mode === "background" ? "Running in background" : "Running"} · ${elapsed(run)}`,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
209
195
|
if (run.status === "done") {
|
|
210
196
|
parts.push(`${run.exitCode === 0 ? "✓" : "✗"} exit ${run.exitCode}`);
|
|
211
197
|
tone = run.exitCode === 0 ? styles.success : styles.danger;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// COMPAT(inlineCodeBlockActions): copies of the inline code-action SDK types until a published
|
|
2
|
+
// @getpaseo/plugin exports them; remove after 2027-04-01.
|
|
3
|
+
import type { ComponentType } from "react";
|
|
4
|
+
import type { PluginCleanup } from "@getpaseo/plugin";
|
|
5
|
+
import type { PluginClientContext, PluginSurfaceProps } from "@getpaseo/plugin/client";
|
|
6
|
+
|
|
7
|
+
type HostNavigation = NonNullable<PluginSurfaceProps["navigation"]>;
|
|
8
|
+
|
|
9
|
+
export interface PluginCodeBlockActionsProps extends Omit<PluginSurfaceProps, "navigation"> {
|
|
10
|
+
readonly navigation?: HostNavigation & {
|
|
11
|
+
readonly openTerminal?: (input: {
|
|
12
|
+
readonly workspaceId: string;
|
|
13
|
+
readonly terminalId: string;
|
|
14
|
+
readonly serverId?: string;
|
|
15
|
+
}) => void;
|
|
16
|
+
};
|
|
17
|
+
agentId: string;
|
|
18
|
+
messageId: string;
|
|
19
|
+
blockIndex: number;
|
|
20
|
+
code: string;
|
|
21
|
+
language: string;
|
|
22
|
+
phase: "streaming" | "complete";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PluginCodeBlockActionsContribution {
|
|
26
|
+
id: string;
|
|
27
|
+
languages: readonly string[];
|
|
28
|
+
Component: ComponentType<PluginCodeBlockActionsProps>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Older clients lack addCodeBlockActions; check for it before calling. */
|
|
32
|
+
export type InlineActionsClient = PluginClientContext & {
|
|
33
|
+
addCodeBlockActions?: (contribution: PluginCodeBlockActionsContribution) => PluginCleanup;
|
|
34
|
+
};
|
|
@@ -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);
|
|
@@ -25,27 +20,19 @@ export function SettingsScreen({ theme }: PluginSurfaceProps) {
|
|
|
25
20
|
const { values, revision } = settings;
|
|
26
21
|
|
|
27
22
|
return (
|
|
28
|
-
<SettingsSection title="
|
|
23
|
+
<SettingsSection title="Code block actions">
|
|
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
|
|
27
|
+
hint={`Initial state of the "Send output to agent" checkbox on each code block.`}
|
|
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. Choose Main panel or On the side in Settings → Layout → Open location → Terminals. Manually moved tabs keep their location.`}
|
|
49
36
|
/>
|
|
50
37
|
</SettingsCard>
|
|
51
38
|
</SettingsSection>
|
package/index.client.tsx
CHANGED
|
@@ -1,99 +1,35 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { contributeLegacy } from "./client/legacy";
|
|
3
|
+
import type { PluginCleanup } from "@getpaseo/plugin";
|
|
4
|
+
import type { InlineActionsClient } from "./client/sdk-compat";
|
|
5
|
+
import { CodeBlockActions } from "./client/code-block-actions";
|
|
4
6
|
import { SettingsScreen } from "./client/settings-screen";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
});
|
|
26
|
-
|
|
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
|
-
|
|
7
|
+
import { RUNNABLE_LANGUAGES } from "./shared/code-blocks";
|
|
8
|
+
import { terminalOutputSource } from "./shared/contracts";
|
|
9
|
+
|
|
10
|
+
export default function contribute(client: InlineActionsClient): PluginCleanup {
|
|
11
|
+
if (typeof client.addCodeBlockActions === "function") {
|
|
12
|
+
client.addCodeBlockActions({
|
|
13
|
+
id: "run",
|
|
14
|
+
languages: RUNNABLE_LANGUAGES,
|
|
15
|
+
Component: CodeBlockActions,
|
|
16
|
+
});
|
|
17
|
+
// COMPAT(legacyRunCards): added in the inline-actions fork, remove after 2027-04-01.
|
|
18
|
+
client.addTimelineRenderer({
|
|
19
|
+
kind: "terminal-run-card",
|
|
20
|
+
version: 1,
|
|
21
|
+
schema: z.unknown(),
|
|
22
|
+
Component: () => null,
|
|
23
|
+
});
|
|
24
|
+
} else {
|
|
25
|
+
contributeLegacy(client);
|
|
26
|
+
}
|
|
36
27
|
client.addSettingsScreen({
|
|
37
28
|
id: "preferences",
|
|
38
29
|
title: "Terminal integration",
|
|
39
30
|
icon: "SquareTerminal",
|
|
40
31
|
Component: SettingsScreen,
|
|
41
32
|
});
|
|
42
|
-
|
|
43
33
|
client.addAttachmentSource(terminalOutputSource);
|
|
44
|
-
|
|
45
|
-
client.addSlashCommand({
|
|
46
|
-
name: "run",
|
|
47
|
-
description: "Run a shell command in the workspace terminal and send its output to the agent",
|
|
48
|
-
argumentHint: "<command>",
|
|
49
|
-
context: "agent",
|
|
50
|
-
async onSubmit({ args, agent, rpc, openPanel }) {
|
|
51
|
-
if (!args) throw new Error("Usage: /run <command>");
|
|
52
|
-
const { panelLocation } = await rpc(runAdhoc, { agentId: agent.id, command: args });
|
|
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
|
-
}
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
async function addRunButtons(agentId: string, rpc: PluginClientContext["rpc"]) {
|
|
62
|
-
const { count } = await rpc(scanBlocks, { agentId });
|
|
63
|
-
if (count === 0) throw new Error("The latest reply has no runnable code blocks");
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
client.addSlashCommand({
|
|
67
|
-
name: "blocks",
|
|
68
|
-
description: "Add terminal run buttons for code blocks in the agent's latest reply",
|
|
69
|
-
argumentHint: "",
|
|
70
|
-
context: "agent",
|
|
71
|
-
onSubmit: ({ agent, rpc }) => addRunButtons(agent.id, rpc),
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
client.addCommandCenterItem({
|
|
75
|
-
id: "scan-latest-reply",
|
|
76
|
-
title: "Terminal: add run buttons to the latest reply",
|
|
77
|
-
icon: "SquareTerminal",
|
|
78
|
-
keywords: ["run", "code block", "terminal", "execute"],
|
|
79
|
-
context: "agent",
|
|
80
|
-
onSelect: ({ agent, rpc }) => addRunButtons(agent.id, rpc),
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
client.addCommandCenterItem({
|
|
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);
|
|
34
|
+
return () => {};
|
|
99
35
|
}
|
package/index.server.ts
CHANGED
|
@@ -2,14 +2,10 @@ 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 {
|
|
7
|
+
enableLegacyCards,
|
|
8
8
|
cancelRun,
|
|
9
|
-
closeTerminalView,
|
|
10
|
-
openTerminalView,
|
|
11
|
-
readTerminalView,
|
|
12
|
-
resizeTerminalView,
|
|
13
9
|
runAdhoc,
|
|
14
10
|
runKey,
|
|
15
11
|
runStatus,
|
|
@@ -20,13 +16,20 @@ import {
|
|
|
20
16
|
} from "./shared/contracts";
|
|
21
17
|
|
|
22
18
|
export default function contribute(server: PluginServerContext) {
|
|
23
|
-
|
|
19
|
+
server.registerSettings(preferences);
|
|
24
20
|
let runner: TerminalRunner | null = null;
|
|
25
|
-
const streams = new TerminalStreams();
|
|
26
21
|
const runnerFor = (paseo: ConstructorParameters<typeof TerminalRunner>[0]) =>
|
|
27
22
|
(runner ??= new TerminalRunner(paseo));
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
// COMPAT(legacyRunCards): only old clients opt into scanning; remove after 2027-04-01.
|
|
25
|
+
let legacyCardsRequested = false;
|
|
26
|
+
server.handle(enableLegacyCards, async () => {
|
|
27
|
+
legacyCardsRequested = true;
|
|
28
|
+
return { enabled: true };
|
|
29
|
+
});
|
|
30
|
+
server.on("agent.turn_ended", (event, { paseo }) => {
|
|
31
|
+
if (legacyCardsRequested) return appendCardForTurn(paseo, event);
|
|
32
|
+
});
|
|
30
33
|
|
|
31
34
|
server.handle(startRun, (input, { paseo }) => runnerFor(paseo).start(input));
|
|
32
35
|
server.handle(runStatus, ({ keys }, { paseo }) => ({ runs: runnerFor(paseo).status(keys) }));
|
|
@@ -37,9 +40,14 @@ export default function contribute(server: PluginServerContext) {
|
|
|
37
40
|
const block = { lang: "bash", code: command };
|
|
38
41
|
const cardId = await appendRunCard(paseo, agentId, [block]);
|
|
39
42
|
if (!cardId) throw new Error("Command is too long");
|
|
40
|
-
await runnerFor(paseo).start({
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
await runnerFor(paseo).start({
|
|
44
|
+
agentId,
|
|
45
|
+
key: runKey(cardId, 0),
|
|
46
|
+
...block,
|
|
47
|
+
send: true,
|
|
48
|
+
mode: "terminal",
|
|
49
|
+
});
|
|
50
|
+
return { cardId };
|
|
43
51
|
});
|
|
44
52
|
|
|
45
53
|
server.handle(scanBlocks, async ({ agentId }, { paseo }) => ({
|
|
@@ -48,14 +56,8 @@ export default function contribute(server: PluginServerContext) {
|
|
|
48
56
|
|
|
49
57
|
server.handle(searchTerminalOutput, searchTerminals);
|
|
50
58
|
|
|
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
59
|
return async () => {
|
|
57
60
|
runner?.stop();
|
|
58
|
-
await streams.stop();
|
|
59
61
|
await cleanupScripts();
|
|
60
62
|
};
|
|
61
63
|
}
|
package/package.json
CHANGED
|
@@ -1,48 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paseo-terminal-integration",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Run agent code blocks in a Paseo terminal and send the output back to the agent; attach terminal output to prompts",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agents",
|
|
7
|
+
"paseo",
|
|
8
|
+
"paseo-plugin",
|
|
9
|
+
"terminal"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/keefeere/paseo-terminal-integration#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/keefeere/paseo-terminal-integration/issues"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": "Chechulin Serhii",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/keefeere/paseo-terminal-integration.git"
|
|
20
|
+
},
|
|
4
21
|
"files": [
|
|
5
22
|
"paseo-plugin.json",
|
|
6
23
|
"index.client.tsx",
|
|
7
24
|
"index.server.ts",
|
|
8
25
|
"client/",
|
|
9
26
|
"server/",
|
|
10
|
-
"shared/"
|
|
27
|
+
"shared/",
|
|
28
|
+
"!**/*.test.ts"
|
|
11
29
|
],
|
|
12
30
|
"scripts": {
|
|
13
|
-
"typecheck": "tsc --noEmit"
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"lint": "oxlint",
|
|
34
|
+
"format": "oxfmt ."
|
|
14
35
|
},
|
|
15
36
|
"devDependencies": {
|
|
16
|
-
"@getpaseo/plugin": "0.10.
|
|
37
|
+
"@getpaseo/plugin": "0.10.2",
|
|
17
38
|
"@tanstack/react-query": "^5.90.11",
|
|
18
39
|
"@types/node": "^26.6.2",
|
|
19
40
|
"@types/react": "~19.2.0",
|
|
41
|
+
"oxfmt": "0.46.0",
|
|
42
|
+
"oxlint": "1.61.0",
|
|
20
43
|
"react": "19.1.0",
|
|
21
44
|
"react-native": "0.81.5",
|
|
22
45
|
"typescript": "^5.9.3",
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
"description": "Run agent code blocks in a Paseo terminal and send the output back to the agent; attach terminal output to prompts",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"author": "Chechulin Serhii",
|
|
28
|
-
"repository": {
|
|
29
|
-
"type": "git",
|
|
30
|
-
"url": "git+https://github.com/keefeere/paseo-terminal-integration.git"
|
|
31
|
-
},
|
|
32
|
-
"homepage": "https://github.com/keefeere/paseo-terminal-integration#readme",
|
|
33
|
-
"bugs": {
|
|
34
|
-
"url": "https://github.com/keefeere/paseo-terminal-integration/issues"
|
|
35
|
-
},
|
|
36
|
-
"keywords": [
|
|
37
|
-
"paseo",
|
|
38
|
-
"paseo-plugin",
|
|
39
|
-
"terminal",
|
|
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"
|
|
46
|
+
"vitest": "^4.1.7",
|
|
47
|
+
"zod": "4.4.3"
|
|
47
48
|
}
|
|
48
49
|
}
|
package/server/attachments.ts
CHANGED
|
@@ -32,7 +32,9 @@ export async function searchTerminals(
|
|
|
32
32
|
|
|
33
33
|
const items = await Promise.all(
|
|
34
34
|
matches.map(async (entry) => {
|
|
35
|
-
const capture = await paseo.terminals
|
|
35
|
+
const capture = await paseo.terminals
|
|
36
|
+
.ref(entry)
|
|
37
|
+
.capture({ start: -lineCount, stripAnsi: true });
|
|
36
38
|
const lines = trimBlankEdges(withoutRunMarkers(capture.lines));
|
|
37
39
|
const name = entry.name || "Terminal";
|
|
38
40
|
const workspace = workspaceNames.get(entry.workspaceId);
|