@zvada/agent-server 0.3.2 → 0.3.3
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/AGENTS.md +34 -0
- package/CHANGELOG.md +11 -0
- package/README.md +14 -3
- package/docs/consuming.md +13 -0
- package/docs/deploy.md +21 -2
- package/docs/harnesses.md +43 -0
- package/package.json +2 -8
- package/src/client/transports.ts +6 -1
- package/src/core/agents/acp/acp-agent.ts +57 -24
- package/src/core/agents/acp/adapter.ts +4 -0
- package/src/core/agents/claude-code/claude-agent.ts +24 -4
- package/src/core/agents/claude-code/generator-session.ts +1 -1
- package/src/core/agents/claude-code/session-manager.ts +15 -4
- package/src/core/agents/codex-app-server/adapter.ts +8 -5
- package/src/core/agents/codex-app-server/client.ts +3 -1
- package/src/core/agents/codex-app-server/codex-app-server-agent.ts +256 -74
- package/src/core/agents/codex-sdk/adapter.ts +8 -8
- package/src/core/agents/codex-sdk/codex-sdk-agent.ts +71 -29
- package/src/core/agents/session-store.ts +35 -8
- package/src/core/index.ts +3 -0
- package/src/core/presets.ts +7 -2
- package/src/core/provision/provisioner.ts +140 -55
- package/src/core/runtime/event-processor.ts +6 -1
- package/src/protocol/reduce.ts +5 -1
- package/src/protocol/verify.ts +36 -0
- package/src/protocol/wire.ts +11 -5
- package/src/server/acp/translate.ts +32 -22
- package/src/server/agent-server.ts +23 -5
- package/src/server/bin.ts +40 -5
- package/src/server/feedback.ts +76 -0
package/src/server/bin.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// agent-server install # prefetch the pinned agent CLIs
|
|
12
12
|
//
|
|
13
13
|
// All logs go to stderr; stdout is reserved for the wire in stdio mode.
|
|
14
|
+
import pkg from "../../package.json" with { type: "json" };
|
|
14
15
|
import {
|
|
15
16
|
KNOWN_ACP_AGENTS,
|
|
16
17
|
type ProvisionMode,
|
|
@@ -19,13 +20,14 @@ import {
|
|
|
19
20
|
} from "../core/index.ts";
|
|
20
21
|
import { isAgentHarness } from "../protocol/index.ts";
|
|
21
22
|
import { AgentServer } from "./agent-server.ts";
|
|
23
|
+
import { runFeedback } from "./feedback.ts";
|
|
22
24
|
import { runInstall } from "./install.ts";
|
|
23
25
|
import { dial, listen, stdioTransport } from "./transports.ts";
|
|
24
26
|
|
|
25
|
-
const VERSION =
|
|
27
|
+
const VERSION: string = pkg.version;
|
|
26
28
|
|
|
27
29
|
interface Args {
|
|
28
|
-
command: "serve" | "install";
|
|
30
|
+
command: "serve" | "install" | "feedback";
|
|
29
31
|
mode: "stdio" | "listen" | "dial" | "acp";
|
|
30
32
|
listen?: { hostname?: string; port: number };
|
|
31
33
|
dialUrl?: string;
|
|
@@ -33,21 +35,27 @@ interface Args {
|
|
|
33
35
|
acpAgent?: string;
|
|
34
36
|
bufferSize?: number;
|
|
35
37
|
provisionMode?: ProvisionMode;
|
|
38
|
+
feedback?: { message?: string; category?: string; subject?: string; resume?: string };
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
function usage(exitCode: number): never {
|
|
39
42
|
console.error(
|
|
40
43
|
[
|
|
41
|
-
"usage: agent-server [install] [--listen [host:]port | --dial <ws-url>] [options]",
|
|
44
|
+
"usage: agent-server [install|feedback] [--listen [host:]port | --dial <ws-url>] [options]",
|
|
42
45
|
"",
|
|
43
46
|
" (default) serve NDJSON JSON-RPC on stdio",
|
|
44
47
|
" --acp speak ACP v1 on stdio instead (be the agent)",
|
|
45
48
|
" install download the pinned agent CLIs into the managed cache",
|
|
46
49
|
" (always downloads — run at image build time to erase",
|
|
47
50
|
" sandbox cold starts; --provision applies to serving only)",
|
|
51
|
+
' feedback "<report>" report friction to the agent-server maintainers',
|
|
52
|
+
" (--category api|cli|docs|other, --subject <exact item>,",
|
|
53
|
+
" --resume <threadId>; no auth; structured eval reports",
|
|
54
|
+
" ride `npx hivenet --to agent-server --task ...`)",
|
|
48
55
|
" --listen [host:]port accept WebSocket clients",
|
|
49
56
|
" --dial <ws-url> dial out to a consumer (auto-reconnect)",
|
|
50
57
|
" --harness <a,b> restrict harnesses (default: all installed)",
|
|
58
|
+
" --acp-agent <spec> ACP agent: known name (pi|gemini) or launch command",
|
|
51
59
|
" --provision <mode> CLI provisioning: auto | pinned | system (default auto)",
|
|
52
60
|
" --buffer <n> replay buffer size per session (default 4096)",
|
|
53
61
|
" --version, --help",
|
|
@@ -69,7 +77,17 @@ function parseArgs(argv: string[]): Args {
|
|
|
69
77
|
return v;
|
|
70
78
|
};
|
|
71
79
|
if (arg === "install" && i === 0) args.command = "install";
|
|
72
|
-
else if (arg === "
|
|
80
|
+
else if (arg === "feedback" && i === 0) {
|
|
81
|
+
args.command = "feedback";
|
|
82
|
+
args.feedback = {};
|
|
83
|
+
} else if (args.command === "feedback" && args.feedback) {
|
|
84
|
+
if (arg === "--category") args.feedback.category = next();
|
|
85
|
+
else if (arg === "--subject") args.feedback.subject = next();
|
|
86
|
+
else if (arg === "--resume") args.feedback.resume = next();
|
|
87
|
+
else if (!arg.startsWith("--") && args.feedback.message === undefined)
|
|
88
|
+
args.feedback.message = arg;
|
|
89
|
+
else usage(1);
|
|
90
|
+
} else if (arg === "--stdio") args.mode = "stdio";
|
|
73
91
|
else if (arg === "--acp") args.mode = "acp";
|
|
74
92
|
else if (arg === "--listen") {
|
|
75
93
|
args.mode = "listen";
|
|
@@ -80,7 +98,11 @@ function parseArgs(argv: string[]): Args {
|
|
|
80
98
|
args.mode = "dial";
|
|
81
99
|
args.dialUrl = next();
|
|
82
100
|
} else if (arg === "--harness") args.harnesses = next().split(",").filter(Boolean);
|
|
83
|
-
else if (arg === "--
|
|
101
|
+
else if (arg === "--acp-agent" || arg.startsWith("--acp-agent=")) {
|
|
102
|
+
const spec = arg === "--acp-agent" ? next() : arg.slice(12);
|
|
103
|
+
if (!spec.trim() || spec.startsWith("-")) usage(1);
|
|
104
|
+
args.acpAgent = spec;
|
|
105
|
+
} else if (arg === "--provision") {
|
|
84
106
|
const mode = next();
|
|
85
107
|
if (mode !== "auto" && mode !== "pinned" && mode !== "system") usage(1);
|
|
86
108
|
args.provisionMode = mode;
|
|
@@ -98,6 +120,19 @@ function parseArgs(argv: string[]): Args {
|
|
|
98
120
|
|
|
99
121
|
const args = parseArgs(process.argv.slice(2));
|
|
100
122
|
|
|
123
|
+
if (args.command === "feedback") {
|
|
124
|
+
const message = args.feedback?.message;
|
|
125
|
+
if (!message) usage(1);
|
|
126
|
+
try {
|
|
127
|
+
const result = await runFeedback({ ...args.feedback, message, clientVersion: VERSION });
|
|
128
|
+
for (const line of result.lines) console.error(line);
|
|
129
|
+
process.exit(0);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error(`feedback failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
101
136
|
const harnesses = args.harnesses?.map((h) => {
|
|
102
137
|
if (isAgentHarness(h)) return h;
|
|
103
138
|
if (KNOWN_ACP_AGENTS[h]) {
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// `agent-server feedback` — report friction to the maintainers over hivenet.
|
|
2
|
+
//
|
|
3
|
+
// Deliberately zero-dep (raw fetch, no `hivenet` package): the compiled
|
|
4
|
+
// single-binary deploys have no npm/npx, so this subcommand is the only
|
|
5
|
+
// feedback path there. Wire shape per hivenet's v1 feedback API.
|
|
6
|
+
|
|
7
|
+
const ENDPOINT = "https://hivenet.app/v1/feedback";
|
|
8
|
+
const PROJECT = "agent-server";
|
|
9
|
+
const TIMEOUT_MS = 10_000;
|
|
10
|
+
|
|
11
|
+
export interface FeedbackOptions {
|
|
12
|
+
message: string;
|
|
13
|
+
/** Suggested: api | cli | docs | other. Defaults to cli. */
|
|
14
|
+
category?: string;
|
|
15
|
+
/** The exact item: export, error code, harness, or command. */
|
|
16
|
+
subject?: string;
|
|
17
|
+
/** Continue an existing thread instead of opening a new one. */
|
|
18
|
+
resume?: string;
|
|
19
|
+
clientVersion?: string;
|
|
20
|
+
/** Injectable transport boundary for tests. */
|
|
21
|
+
fetchImpl?: (url: string, init: RequestInit) => Promise<Response>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface FeedbackResult {
|
|
25
|
+
threadId: string;
|
|
26
|
+
/** Human-readable lines to print (thread id, guidance, ask). */
|
|
27
|
+
lines: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** POST one feedback report; returns the lines the CLI should print. */
|
|
31
|
+
export async function runFeedback(options: FeedbackOptions): Promise<FeedbackResult> {
|
|
32
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
33
|
+
const threadId = options.resume ?? crypto.randomUUID().replaceAll("-", "");
|
|
34
|
+
const response = await doFetch(ENDPOINT, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: { "content-type": "application/json" },
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
v: 1,
|
|
39
|
+
to: PROJECT,
|
|
40
|
+
feedback: options.message,
|
|
41
|
+
category: options.category ?? "cli",
|
|
42
|
+
...(options.subject ? { subject: options.subject } : {}),
|
|
43
|
+
thread: { id: threadId },
|
|
44
|
+
client: { name: "agent-server-cli", version: options.clientVersion ?? "0" },
|
|
45
|
+
consent: { telemetry: false },
|
|
46
|
+
}),
|
|
47
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
48
|
+
});
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new Error(`feedback rejected: ${response.status} ${await safeText(response)}`);
|
|
51
|
+
}
|
|
52
|
+
const body = (await response.json()) as {
|
|
53
|
+
thread?: string;
|
|
54
|
+
guidance?: string;
|
|
55
|
+
ask?: { prompt?: string; command?: string };
|
|
56
|
+
};
|
|
57
|
+
const thread = body.thread ?? threadId;
|
|
58
|
+
const lines = [
|
|
59
|
+
`delivered to ${PROJECT} (thread ${thread})`,
|
|
60
|
+
`continue this thread: agent-server feedback --resume ${thread} "<follow-up>"`,
|
|
61
|
+
];
|
|
62
|
+
if (body.guidance) lines.push(`guidance from the maintainers: ${body.guidance}`);
|
|
63
|
+
if (body.ask?.prompt) {
|
|
64
|
+
lines.push(`the maintainers ask: ${body.ask.prompt}`);
|
|
65
|
+
if (body.ask.command) lines.push(` answer (only if grounded): ${body.ask.command}`);
|
|
66
|
+
}
|
|
67
|
+
return { threadId: thread, lines };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function safeText(response: Response): Promise<string> {
|
|
71
|
+
try {
|
|
72
|
+
return (await response.text()).slice(0, 200);
|
|
73
|
+
} catch {
|
|
74
|
+
return "";
|
|
75
|
+
}
|
|
76
|
+
}
|