agentp 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 +37 -11
- package/bin/agentp +18 -15
- package/bin/ocmux +79 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# agentp
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/agentp)
|
|
4
|
+
[](https://www.npmjs.com/package/agentp)
|
|
5
|
+
[](https://www.npmjs.com/package/agentp)
|
|
6
|
+
[](https://www.npmjs.com/package/agentp)
|
|
7
|
+
|
|
3
8
|
This package provides two CLI tools:
|
|
4
9
|
|
|
5
10
|
- **`agentp`** — pipes prompt text into a running OpenCode TUI session and streams the assistant final answer back to stdout
|
|
@@ -34,23 +39,24 @@ npm link
|
|
|
34
39
|
Notes:
|
|
35
40
|
|
|
36
41
|
- `agentp` connects to the OpenCode event endpoint over HTTP.
|
|
37
|
-
- In practice this means running `opencode
|
|
38
|
-
- `opencode
|
|
42
|
+
- In practice this means running `opencode serve` (or equivalent serve mode) so the port is open.
|
|
43
|
+
- `opencode attach` is optional but useful to monitor the full conversation in another terminal/tmux pane.
|
|
39
44
|
|
|
40
45
|
## Usage
|
|
41
46
|
|
|
42
47
|
```bash
|
|
43
|
-
agentp [options] [
|
|
48
|
+
agentp [options] [url]
|
|
44
49
|
```
|
|
45
50
|
|
|
46
51
|
Options:
|
|
47
52
|
|
|
48
|
-
- `--qa`: print
|
|
53
|
+
- `--qa`: print the original prompt and answer with labels (useful when used as a filter)
|
|
54
|
+
- `--version`: show version
|
|
49
55
|
- `--help`: show help message
|
|
50
56
|
|
|
51
57
|
Arguments:
|
|
52
58
|
|
|
53
|
-
- `
|
|
59
|
+
- `url`: OpenCode TUI server URL or port number (defaults to `4096`). Examples: `4096`, `http://localhost:4096`, `http://192.168.1.50:4096`
|
|
54
60
|
|
|
55
61
|
## Examples
|
|
56
62
|
|
|
@@ -73,10 +79,10 @@ Send a multi-line prompt from a file:
|
|
|
73
79
|
cat prompt.txt | agentp
|
|
74
80
|
```
|
|
75
81
|
|
|
76
|
-
Use
|
|
82
|
+
Use an explicit port:
|
|
77
83
|
|
|
78
84
|
```bash
|
|
79
|
-
cat prompt.txt | agentp
|
|
85
|
+
cat prompt.txt | agentp 4096
|
|
80
86
|
```
|
|
81
87
|
|
|
82
88
|
Capture answer to a file:
|
|
@@ -85,13 +91,19 @@ Capture answer to a file:
|
|
|
85
91
|
cat prompt.txt | agentp > answer.txt
|
|
86
92
|
```
|
|
87
93
|
|
|
94
|
+
Connect to a remote OpenCode server:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cat prompt.txt | agentp http://192.168.1.50:4096
|
|
98
|
+
```
|
|
99
|
+
|
|
88
100
|
From Vim/Neovim, send the current visual selection and replace it in place with the assistant answer:
|
|
89
101
|
|
|
90
102
|
```vim
|
|
91
103
|
:'<,'>!agentp
|
|
92
104
|
```
|
|
93
105
|
|
|
94
|
-
From Vim/Neovim, send the current visual selection and keep
|
|
106
|
+
From Vim/Neovim, send the current visual selection and keep the prompt with the answer:
|
|
95
107
|
|
|
96
108
|
```vim
|
|
97
109
|
:'<,'>!agentp --qa
|
|
@@ -109,9 +121,23 @@ Without arguments, searches upward from `<directory>` (default: `$PWD`) for `.oc
|
|
|
109
121
|
|
|
110
122
|
Subcommands:
|
|
111
123
|
|
|
112
|
-
- **`new [dir]`** — Create a new server in `dir` (default: `$PWD`). Errors if one already exists there. Warns if a parent directory already has a server.
|
|
124
|
+
- **`new [--git|--GIT] [dir]`** — Create a new server in `dir` (default: `$PWD`). Errors if one already exists there. Warns if a parent directory already has a server.
|
|
125
|
+
- `--git` resolves `dir` to the nearest parent with a `.git` entry (file or dir); errors if none is found.
|
|
126
|
+
- `--GIT` resolves `dir` to the nearest parent with a `.git` directory only; errors if none is found.
|
|
113
127
|
- **`kill [dir]`** — Kill the server found upward from `dir`. Removes its tmux window and state file.
|
|
114
|
-
- **`list
|
|
128
|
+
- **`list`** — List all running servers with their directories, URLs, and status.
|
|
129
|
+
|
|
130
|
+
Options:
|
|
131
|
+
|
|
132
|
+
- `-l`: long output for default/new commands (append `→ <dir>` after the URL)
|
|
133
|
+
- `--version`: show version
|
|
134
|
+
- `-h`: show help message
|
|
135
|
+
- `--`: treat the next argument as a directory even if it matches a subcommand name
|
|
136
|
+
|
|
137
|
+
Notes:
|
|
138
|
+
|
|
139
|
+
- If `<directory>` is not a valid path, `ocmux` tries to match it against the basenames of existing sessions (exact unique match).
|
|
140
|
+
- When using `--git`/`--GIT`, `ocmux` refuses to create a new server above an existing `.ocmux.json` found while searching for the git root.
|
|
115
141
|
|
|
116
142
|
### Requirements
|
|
117
143
|
|
|
@@ -133,7 +159,7 @@ Subcommands:
|
|
|
133
159
|
|
|
134
160
|
Operational hint:
|
|
135
161
|
|
|
136
|
-
- You can keep a separate `opencode
|
|
162
|
+
- You can keep a separate `opencode attach` view open to see the full run context while `agentp` is used from shell scripts or editor buffers.
|
|
137
163
|
|
|
138
164
|
## License
|
|
139
165
|
|
package/bin/agentp
CHANGED
|
@@ -47,8 +47,7 @@ async function submitPrompt(server) {
|
|
|
47
47
|
await makeRequest(buildJsonRequest(url, 'POST', '{}'), '{}');
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
async function sendPrompt(
|
|
51
|
-
const server = `http://localhost:${port}`;
|
|
50
|
+
async function sendPrompt(server) {
|
|
52
51
|
let promptText = '';
|
|
53
52
|
|
|
54
53
|
await clearPrompt(server);
|
|
@@ -71,9 +70,9 @@ const HUMAN_ROW = '👤:  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|
|
|
71
70
|
const AGENT_ROW = '🤖:  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄\n'
|
|
72
71
|
const FINAL_ROW = ' ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄\n';
|
|
73
72
|
|
|
74
|
-
function listenForFinalAnswer(
|
|
73
|
+
function listenForFinalAnswer(server, showFinalRow) {
|
|
75
74
|
return new Promise((resolve, reject) => {
|
|
76
|
-
const url =
|
|
75
|
+
const url = `${server}/event`;
|
|
77
76
|
const parsed = new URL(url);
|
|
78
77
|
|
|
79
78
|
const req = http.request({
|
|
@@ -155,7 +154,7 @@ function listenForFinalAnswer(port, showFinalRow) {
|
|
|
155
154
|
}
|
|
156
155
|
|
|
157
156
|
async function main() {
|
|
158
|
-
let
|
|
157
|
+
let serverBase = 'http://localhost:4096';
|
|
159
158
|
let qaMode = false;
|
|
160
159
|
|
|
161
160
|
const args = process.argv.slice(2);
|
|
@@ -164,33 +163,37 @@ async function main() {
|
|
|
164
163
|
console.log(version);
|
|
165
164
|
process.exit(0);
|
|
166
165
|
} else if (args[i] === '--help') {
|
|
167
|
-
console.error('Usage: agentp [options] [
|
|
166
|
+
console.error('Usage: agentp [options] [url]');
|
|
168
167
|
console.error('');
|
|
169
|
-
console.error('Pipe prompt text to an OpenCode TUI session
|
|
170
|
-
console.error('The assistant response is streamed to stdout.');
|
|
168
|
+
console.error('Pipe prompt text to an OpenCode TUI session and stream the assistant response to stdout.');
|
|
171
169
|
console.error('');
|
|
172
170
|
console.error('Options:');
|
|
173
171
|
console.error(' --version Show version');
|
|
174
|
-
console.error(' --qa Print
|
|
172
|
+
console.error(' --qa Print the original prompt and answer with labels (useful as a filter)');
|
|
175
173
|
console.error(' --help Show this help message');
|
|
176
174
|
console.error('');
|
|
177
175
|
console.error('Arguments:');
|
|
178
|
-
console.error('
|
|
176
|
+
console.error(' url OpenCode TUI server URL or port number (default: 4096)');
|
|
177
|
+
console.error(' Examples: 4096, http://localhost:4096, http://192.168.1.50:4096');
|
|
179
178
|
console.error('');
|
|
180
179
|
console.error('See also: ocmux -- manage OpenCode tmux sessions (ocmux --help)');
|
|
181
180
|
console.error('');
|
|
182
181
|
console.error('Examples:');
|
|
183
182
|
console.error(' printf "Summarize this file" | agentp');
|
|
184
|
-
console.error(' cat prompt.txt | agentp
|
|
183
|
+
console.error(' cat prompt.txt | agentp 4096');
|
|
184
|
+
console.error(' # Vim/Neovim filter, preserving prompt + answer:');
|
|
185
|
+
console.error(" :'<,'>!agentp --qa");
|
|
185
186
|
process.exit(0);
|
|
186
187
|
} else if (args[i] === '--qa') {
|
|
187
188
|
qaMode = true;
|
|
188
|
-
} else if (
|
|
189
|
-
|
|
189
|
+
} else if (args[i].includes('://')) {
|
|
190
|
+
serverBase = args[i].replace(/\/+$/, '');
|
|
191
|
+
} else if (/^\d+$/.test(args[i])) {
|
|
192
|
+
serverBase = 'http://localhost:' + args[i];
|
|
190
193
|
}
|
|
191
194
|
}
|
|
192
195
|
|
|
193
|
-
const promptText = await sendPrompt(
|
|
196
|
+
const promptText = await sendPrompt(serverBase);
|
|
194
197
|
|
|
195
198
|
if (qaMode) {
|
|
196
199
|
process.stdout.write(HUMAN_ROW);
|
|
@@ -198,7 +201,7 @@ async function main() {
|
|
|
198
201
|
process.stdout.write(AGENT_ROW);
|
|
199
202
|
}
|
|
200
203
|
|
|
201
|
-
await listenForFinalAnswer(
|
|
204
|
+
await listenForFinalAnswer(serverBase, qaMode);
|
|
202
205
|
}
|
|
203
206
|
|
|
204
207
|
main().catch((err) => {
|
package/bin/ocmux
CHANGED
|
@@ -66,6 +66,52 @@ function findParentStatefile(startDir) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
function findParentGitDir(startDir, requireDir) {
|
|
70
|
+
let dir = path.resolve(startDir);
|
|
71
|
+
let stateDir = null;
|
|
72
|
+
while (true) {
|
|
73
|
+
if (!stateDir && fs.existsSync(path.join(dir, '.ocmux.json'))) {
|
|
74
|
+
stateDir = dir;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const gitPath = path.join(dir, '.git');
|
|
78
|
+
if (fs.existsSync(gitPath)) {
|
|
79
|
+
if (!requireDir) {
|
|
80
|
+
return { dir, stateDir, gitPath };
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
if (fs.statSync(gitPath).isDirectory()) {
|
|
84
|
+
return { dir, stateDir, gitPath };
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
// ignore stat errors
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (dir === HOME || dir === path.dirname(dir)) return { dir: null, stateDir, gitPath: null };
|
|
92
|
+
dir = path.dirname(dir);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function resolveGitDir(startDir, requireDir, flagLabel) {
|
|
97
|
+
const result = findParentGitDir(startDir, requireDir);
|
|
98
|
+
if (!result.dir) {
|
|
99
|
+
const label = requireDir ? '.git directory' : '.git entry';
|
|
100
|
+
console.error(`Error: no ${label} found in ${startDir} or any of its parents.`);
|
|
101
|
+
console.error(`Run '${SCRIPT} new' without ${flagLabel} to create a server in the current directory.`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (result.stateDir && result.stateDir !== result.dir) {
|
|
106
|
+
console.error(`Error: found an existing ocmux server in ${result.stateDir}.`);
|
|
107
|
+
console.error(`Refusing to create a new server at ${result.dir} because it is above that session.`);
|
|
108
|
+
console.error(`Move outside ${result.stateDir} or pass an explicit directory.`);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return result.dir;
|
|
113
|
+
}
|
|
114
|
+
|
|
69
115
|
function windowByDir(dir) {
|
|
70
116
|
const r = tmux(['list-windows', '-t', SESSION, '-F', '#{window_index}\t#{window_name}']);
|
|
71
117
|
if (r.status !== 0) return null;
|
|
@@ -190,6 +236,9 @@ function printHelp() {
|
|
|
190
236
|
console.error(' new Create a new server in <directory> (default: $PWD).');
|
|
191
237
|
console.error(' Errors if one already exists there.');
|
|
192
238
|
console.error(' Warns if a parent directory already has a server.');
|
|
239
|
+
console.error(' --git Use the nearest parent with a .git entry (file or dir).');
|
|
240
|
+
console.error(' --GIT Use the nearest parent with a .git directory only.');
|
|
241
|
+
console.error(' Refuses to create above an existing .ocmux.json found while searching.');
|
|
193
242
|
console.error(' kill Kill the server found upward from <directory>.');
|
|
194
243
|
console.error(' Removes its tmux window and state file.');
|
|
195
244
|
console.error(' list List all running servers with their directories and URLs.');
|
|
@@ -198,7 +247,7 @@ function printHelp() {
|
|
|
198
247
|
console.error(' a subcommand name (e.g. "ocmux -- kill").');
|
|
199
248
|
console.error('');
|
|
200
249
|
console.error('Options:');
|
|
201
|
-
console.error(' -l Long output: append " → <dir>" after the URL.');
|
|
250
|
+
console.error(' -l Long output: append " → <dir>" after the URL (new/default).');
|
|
202
251
|
console.error(' --version Show version');
|
|
203
252
|
console.error(' -h Show this help');
|
|
204
253
|
console.error('');
|
|
@@ -439,12 +488,25 @@ function cmdKill(statefile) {
|
|
|
439
488
|
|
|
440
489
|
function main() {
|
|
441
490
|
let longMode = false;
|
|
491
|
+
let gitMode = null;
|
|
442
492
|
const positional = [];
|
|
443
493
|
let dirIsForced = false;
|
|
444
494
|
|
|
445
495
|
for (const arg of process.argv.slice(2)) {
|
|
446
496
|
if (arg === '-l') {
|
|
447
497
|
longMode = true;
|
|
498
|
+
} else if (arg === '--git') {
|
|
499
|
+
if (gitMode && gitMode !== 'nearest') {
|
|
500
|
+
console.error("Error: cannot combine '--git' with '--GIT'.");
|
|
501
|
+
process.exit(1);
|
|
502
|
+
}
|
|
503
|
+
gitMode = 'nearest';
|
|
504
|
+
} else if (arg === '--GIT') {
|
|
505
|
+
if (gitMode && gitMode !== 'root') {
|
|
506
|
+
console.error("Error: cannot combine '--git' with '--GIT'.");
|
|
507
|
+
process.exit(1);
|
|
508
|
+
}
|
|
509
|
+
gitMode = 'root';
|
|
448
510
|
} else if (arg === '--version') {
|
|
449
511
|
console.log(version);
|
|
450
512
|
process.exit(0);
|
|
@@ -495,12 +557,20 @@ function main() {
|
|
|
495
557
|
|
|
496
558
|
// Dispatch
|
|
497
559
|
if (subcommand === 'list') {
|
|
560
|
+
if (gitMode) {
|
|
561
|
+
console.error("Error: '--git' and '--GIT' are only valid with 'new'.");
|
|
562
|
+
process.exit(1);
|
|
563
|
+
}
|
|
498
564
|
if (targetDir !== process.cwd()) {
|
|
499
565
|
console.error("Error: 'list' does not accept a directory path.");
|
|
500
566
|
process.exit(1);
|
|
501
567
|
}
|
|
502
568
|
cmdList();
|
|
503
569
|
} else if (subcommand === 'kill') {
|
|
570
|
+
if (gitMode) {
|
|
571
|
+
console.error("Error: '--git' and '--GIT' are only valid with 'new'.");
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
504
574
|
const sf = findParentStatefile(targetDir);
|
|
505
575
|
if (!sf) {
|
|
506
576
|
console.error(`Error: no opencode server found in ${targetDir} or any of its parents.`);
|
|
@@ -509,8 +579,16 @@ function main() {
|
|
|
509
579
|
}
|
|
510
580
|
cmdKill(sf);
|
|
511
581
|
} else if (subcommand === 'new') {
|
|
582
|
+
if (gitMode) {
|
|
583
|
+
const flagLabel = gitMode === 'root' ? '--GIT' : '--git';
|
|
584
|
+
targetDir = resolveGitDir(targetDir, gitMode === 'root', flagLabel);
|
|
585
|
+
}
|
|
512
586
|
cmdNew(targetDir, longMode);
|
|
513
587
|
} else {
|
|
588
|
+
if (gitMode) {
|
|
589
|
+
console.error("Error: '--git' and '--GIT' are only valid with 'new'.");
|
|
590
|
+
process.exit(1);
|
|
591
|
+
}
|
|
514
592
|
// Default mode
|
|
515
593
|
const sf = findParentStatefile(targetDir);
|
|
516
594
|
if (!sf) {
|