cuonztech-agent-harness 0.5.2 → 0.7.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.
@@ -0,0 +1,127 @@
1
+ // TESTSYSTEM — Mietbuchungs-Attrappe für den Agent-Harness-Kaltstart-Test.
2
+ // Keine echten Daten, keine Abhängigkeiten. Speichert Buchungen in bookings.json
3
+ // neben dieser Datei (oder in der Datei aus TESTSYSTEM_DATA), damit jeder
4
+ // Schreibvorgang nachprüfbar bleibt.
5
+ // Start: node server.mjs (MCP über stdio, JSON-RPC, Zeile für Zeile)
6
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
7
+ import { createInterface } from "node:readline";
8
+ import { fileURLToPath } from "node:url";
9
+ import { dirname, join } from "node:path";
10
+
11
+ const DATA = process.env.TESTSYSTEM_DATA ?? join(dirname(fileURLToPath(import.meta.url)), "bookings.json");
12
+ const PROTOCOL = "2024-11-05";
13
+
14
+ function load() {
15
+ return existsSync(DATA) ? JSON.parse(readFileSync(DATA, "utf8")) : [];
16
+ }
17
+ function save(list) {
18
+ writeFileSync(DATA, JSON.stringify(list, null, 2) + "\n");
19
+ }
20
+
21
+ const TOOLS = [
22
+ {
23
+ name: "create_booking",
24
+ description: "Legt eine neue Mietbuchung an (schreibt in das Testsystem).",
25
+ inputSchema: {
26
+ type: "object",
27
+ properties: {
28
+ customer: { type: "string", description: "Name des Kunden" },
29
+ date: { type: "string", description: "Datum, z. B. 2026-11-03" },
30
+ amount_chf: { type: "number", description: "Betrag in CHF" },
31
+ idempotency_key: { type: "string", description: "Optional: gleicher Key = gleiche Buchung, kein Doppel" },
32
+ },
33
+ required: ["customer", "date", "amount_chf"],
34
+ },
35
+ annotations: { readOnlyHint: false },
36
+ },
37
+ {
38
+ name: "list_bookings",
39
+ description: "Listet alle Buchungen eines Kunden (nur lesend).",
40
+ inputSchema: {
41
+ type: "object",
42
+ properties: { customer: { type: "string" } },
43
+ required: ["customer"],
44
+ },
45
+ annotations: { readOnlyHint: true },
46
+ },
47
+ {
48
+ name: "get_booking",
49
+ description: "Liefert eine Buchung anhand ihrer ID (nur lesend).",
50
+ inputSchema: {
51
+ type: "object",
52
+ properties: { booking_id: { type: "string" } },
53
+ required: ["booking_id"],
54
+ },
55
+ annotations: { readOnlyHint: true },
56
+ },
57
+ ];
58
+
59
+ function callTool(name, args) {
60
+ const list = load();
61
+ if (name === "create_booking") {
62
+ if (args.idempotency_key) {
63
+ const known = list.find((b) => b.idempotency_key === args.idempotency_key);
64
+ if (known) return { booking: known, duplicate_prevented: true };
65
+ }
66
+ const booking = {
67
+ idempotency_key: args.idempotency_key ?? null,
68
+ booking_id: `B-${String(list.length + 1).padStart(4, "0")}`,
69
+ customer: args.customer,
70
+ date: args.date,
71
+ amount_chf: args.amount_chf,
72
+ created_at: new Date().toISOString(),
73
+ };
74
+ list.push(booking);
75
+ save(list);
76
+ return { booking };
77
+ }
78
+ if (name === "list_bookings") {
79
+ return { bookings: list.filter((b) => b.customer === args.customer) };
80
+ }
81
+ if (name === "get_booking") {
82
+ const booking = list.find((b) => b.booking_id === args.booking_id);
83
+ return booking ? { booking } : { error: `booking ${args.booking_id} not found` };
84
+ }
85
+ throw new Error(`unknown tool ${name}`);
86
+ }
87
+
88
+ function reply(id, result) {
89
+ process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, result }) + "\n");
90
+ }
91
+ function replyError(id, code, message) {
92
+ process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } }) + "\n");
93
+ }
94
+
95
+ createInterface({ input: process.stdin }).on("line", (line) => {
96
+ if (!line.trim()) return;
97
+ let msg;
98
+ try {
99
+ msg = JSON.parse(line);
100
+ } catch {
101
+ return replyError(null, -32700, "parse error");
102
+ }
103
+ if (msg.id === undefined) return; // Notifications brauchen keine Antwort.
104
+ switch (msg.method) {
105
+ case "initialize":
106
+ return reply(msg.id, {
107
+ protocolVersion: PROTOCOL,
108
+ capabilities: { tools: {} },
109
+ serverInfo: { name: "testsystem-mietbuchung", version: "0.1.0" },
110
+ });
111
+ case "tools/list":
112
+ return reply(msg.id, { tools: TOOLS });
113
+ case "tools/call": {
114
+ try {
115
+ const data = callTool(msg.params.name, msg.params.arguments ?? {});
116
+ return reply(msg.id, { content: [{ type: "text", text: JSON.stringify(data) }] });
117
+ } catch (err) {
118
+ return reply(msg.id, {
119
+ content: [{ type: "text", text: String(err.message) }],
120
+ isError: true,
121
+ });
122
+ }
123
+ }
124
+ default:
125
+ return replyError(msg.id, -32601, `method not found: ${msg.method}`);
126
+ }
127
+ });
@@ -0,0 +1,23 @@
1
+ @echo off
2
+ rem Doppelklick-Start der Oberflaeche (Windows). Prueft Node und oeffnet den Browser.
3
+ setlocal
4
+ where node >nul 2>nul
5
+ if errorlevel 1 (
6
+ echo Node.js ist nicht installiert.
7
+ echo Bitte Version 20 oder neuer von https://nodejs.org installieren und diese Datei danach erneut starten.
8
+ pause
9
+ exit /b 1
10
+ )
11
+ node -e "process.exit(Number(process.versions.node.split('.')[0])>=20?0:1)"
12
+ if errorlevel 1 (
13
+ echo Die installierte Node.js-Version ist zu alt. Noetig ist Version 20 oder neuer.
14
+ echo Bitte von https://nodejs.org aktualisieren und diese Datei danach erneut starten.
15
+ pause
16
+ exit /b 1
17
+ )
18
+ if exist "%~dp0..\dist\index.js" (
19
+ node "%~dp0..\dist\index.js" ui %*
20
+ ) else (
21
+ npx -y cuonztech-agent-harness ui %*
22
+ )
23
+ if errorlevel 1 pause
@@ -0,0 +1,18 @@
1
+ #!/bin/sh
2
+ # Start der Oberflaeche (macOS und Linux). Prueft Node und oeffnet den Browser.
3
+ if ! command -v node >/dev/null 2>&1; then
4
+ echo "Node.js ist nicht installiert."
5
+ echo "Bitte Version 20 oder neuer von https://nodejs.org installieren und das Skript danach erneut starten."
6
+ exit 1
7
+ fi
8
+ if ! node -e "process.exit(Number(process.versions.node.split('.')[0])>=20?0:1)"; then
9
+ echo "Die installierte Node.js-Version ist zu alt. Noetig ist Version 20 oder neuer."
10
+ echo "Hinweis: 'apt install nodejs' liefert unter Ubuntu 24.04 nur Node 18. Bitte von https://nodejs.org installieren."
11
+ exit 1
12
+ fi
13
+ here="$(cd "$(dirname "$0")" && pwd)"
14
+ if [ -f "$here/../dist/index.js" ]; then
15
+ exec node "$here/../dist/index.js" ui "$@"
16
+ else
17
+ exec npx -y cuonztech-agent-harness ui "$@"
18
+ fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cuonztech-agent-harness",
3
- "version": "0.5.2",
3
+ "version": "0.7.0",
4
4
  "mcpName": "io.github.cuonztech/agent-harness",
5
5
  "description": "Chaos-Proxy für MCP-Server: injiziert F1-F5-Fehlerszenarien (Ghost-Write nach Timeout, 429, defektes JSON, Duplicate Dispatch, 500) vor einem echten Upstream-MCP-Server und prüft, ob ein Agent Schreibvorgänge doppelt ausführt. Mit Resilience Score und System-Prompt-Patches für beobachtetes Fehlverhalten.",
6
6
  "type": "module",
@@ -45,6 +45,8 @@
45
45
  },
46
46
  "files": [
47
47
  "dist/**/*.js",
48
+ "launchers",
49
+ "examples/testsystem/server.mjs",
48
50
  "README.md",
49
51
  "LICENSE",
50
52
  "server.json"
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/cuonztech/agent-harness",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.5.2",
9
+ "version": "0.7.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "cuonztech-agent-harness",
14
- "version": "0.5.2",
14
+ "version": "0.7.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  }