@plaited/acp-harness 0.2.5 → 0.3.1

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.
Files changed (57) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +120 -16
  3. package/bin/cli.ts +105 -636
  4. package/bin/tests/cli.spec.ts +218 -51
  5. package/package.json +20 -4
  6. package/src/acp-client.ts +5 -4
  7. package/src/acp-transport.ts +14 -7
  8. package/src/adapter-check.ts +542 -0
  9. package/src/adapter-scaffold.ts +934 -0
  10. package/src/balance.ts +232 -0
  11. package/src/calibrate.ts +300 -0
  12. package/src/capture.ts +457 -0
  13. package/src/constants.ts +94 -0
  14. package/src/grader-loader.ts +174 -0
  15. package/src/harness.ts +35 -0
  16. package/src/schemas-cli.ts +239 -0
  17. package/src/schemas.ts +567 -0
  18. package/src/summarize.ts +245 -0
  19. package/src/tests/adapter-check.spec.ts +70 -0
  20. package/src/tests/adapter-scaffold.spec.ts +112 -0
  21. package/src/tests/fixtures/grader-bad-module.ts +5 -0
  22. package/src/tests/fixtures/grader-exec-fail.py +9 -0
  23. package/src/tests/fixtures/grader-exec-invalid.py +6 -0
  24. package/src/tests/fixtures/grader-exec.py +29 -0
  25. package/src/tests/fixtures/grader-module.ts +14 -0
  26. package/src/tests/grader-loader.spec.ts +153 -0
  27. package/src/trials.ts +395 -0
  28. package/src/validate-refs.ts +188 -0
  29. package/.claude/rules/accuracy.md +0 -43
  30. package/.claude/rules/bun-apis.md +0 -80
  31. package/.claude/rules/code-review.md +0 -254
  32. package/.claude/rules/git-workflow.md +0 -37
  33. package/.claude/rules/github.md +0 -154
  34. package/.claude/rules/testing.md +0 -172
  35. package/.claude/skills/acp-harness/SKILL.md +0 -310
  36. package/.claude/skills/acp-harness/assets/Dockerfile.acp +0 -25
  37. package/.claude/skills/acp-harness/assets/docker-compose.acp.yml +0 -19
  38. package/.claude/skills/acp-harness/references/downstream.md +0 -288
  39. package/.claude/skills/acp-harness/references/output-formats.md +0 -221
  40. package/.claude-plugin/marketplace.json +0 -15
  41. package/.claude-plugin/plugin.json +0 -16
  42. package/.github/CODEOWNERS +0 -6
  43. package/.github/workflows/ci.yml +0 -63
  44. package/.github/workflows/publish.yml +0 -146
  45. package/.mcp.json +0 -20
  46. package/CLAUDE.md +0 -92
  47. package/Dockerfile.test +0 -23
  48. package/biome.json +0 -96
  49. package/bun.lock +0 -513
  50. package/docker-compose.test.yml +0 -21
  51. package/scripts/bun-test-wrapper.sh +0 -46
  52. package/src/acp.constants.ts +0 -56
  53. package/src/acp.schemas.ts +0 -161
  54. package/src/acp.types.ts +0 -28
  55. package/src/tests/fixtures/.claude/settings.local.json +0 -8
  56. package/src/tests/fixtures/.claude/skills/greeting/SKILL.md +0 -17
  57. package/tsconfig.json +0 -32
@@ -1,46 +0,0 @@
1
- #!/bin/bash
2
- # Wrapper for bun test that handles Bun's post-test cleanup crash
3
- # See: https://github.com/oven-sh/bun/issues/23643
4
- #
5
- # Bun 1.3.x has a known bug where the test runner crashes during cleanup
6
- # after all tests complete successfully. This wrapper catches that crash
7
- # (exit code 133 = SIGTRAP) and exits cleanly if tests actually passed.
8
- #
9
- # Usage:
10
- # ./bun-test-wrapper.sh [args...] # Run bun test with provided args
11
- # ./bun-test-wrapper.sh # (No args) Find and run all *.docker.ts files
12
-
13
- # Determine test files to run
14
- if [ $# -eq 0 ]; then
15
- # No arguments: find all *.docker.ts files for Docker integration tests
16
- docker_tests=$(find ./src ./bin -name "*.docker.ts" -type f 2>/dev/null)
17
- if [ -z "$docker_tests" ]; then
18
- echo "No *.docker.ts files found in ./src or ./bin"
19
- exit 0
20
- fi
21
- echo "Found Docker integration tests:"
22
- echo "$docker_tests" | sed 's/^/ /'
23
- echo ""
24
- # Convert newlines to arguments
25
- set -- $docker_tests
26
- fi
27
-
28
- # Create temp file for output
29
- tmpfile=$(mktemp)
30
- trap "rm -f $tmpfile" EXIT
31
-
32
- # Run tests with output to both terminal and file
33
- bun test "$@" 2>&1 | tee "$tmpfile"
34
- exit_code=${PIPESTATUS[0]}
35
-
36
- # Check if tests passed (look for "X pass" and "0 fail" in output)
37
- if grep -q " pass" "$tmpfile" && grep -q "0 fail" "$tmpfile"; then
38
- # Tests passed - exit 0 even if Bun crashed during cleanup
39
- if [ $exit_code -eq 133 ]; then
40
- echo ""
41
- echo "Note: Bun crashed during cleanup (known bug), but all tests passed."
42
- exit 0
43
- fi
44
- fi
45
-
46
- exit $exit_code
@@ -1,56 +0,0 @@
1
- /**
2
- * ACP protocol constants.
3
- *
4
- * @remarks
5
- * Contains all constant values used across the ACP client implementation:
6
- * - Protocol method names
7
- * - Protocol version
8
- * - JSON-RPC error codes
9
- */
10
-
11
- // ============================================================================
12
- // Protocol Methods
13
- // ============================================================================
14
-
15
- /** ACP method names */
16
- export const ACP_METHODS = {
17
- // Lifecycle
18
- INITIALIZE: 'initialize',
19
- SHUTDOWN: 'shutdown',
20
-
21
- // Sessions
22
- CREATE_SESSION: 'session/new',
23
- LOAD_SESSION: 'session/load',
24
- PROMPT: 'session/prompt',
25
- CANCEL: 'session/cancel',
26
- UPDATE: 'session/update',
27
- REQUEST_PERMISSION: 'session/request_permission',
28
- SET_MODEL: 'session/set_model',
29
-
30
- // Protocol-level
31
- CANCEL_REQUEST: '$/cancel_request',
32
- } as const
33
-
34
- // ============================================================================
35
- // Protocol Version
36
- // ============================================================================
37
-
38
- /** Current protocol version - SDK uses number type */
39
- export const ACP_PROTOCOL_VERSION = 1 as const
40
-
41
- // ============================================================================
42
- // JSON-RPC Error Codes
43
- // ============================================================================
44
-
45
- /** Standard JSON-RPC error codes */
46
- export const JSON_RPC_ERRORS = {
47
- PARSE_ERROR: -32700,
48
- INVALID_REQUEST: -32600,
49
- METHOD_NOT_FOUND: -32601,
50
- INVALID_PARAMS: -32602,
51
- INTERNAL_ERROR: -32603,
52
- REQUEST_CANCELLED: -32800,
53
- } as const
54
-
55
- /** Default ACP Client Name */
56
- export const DEFAULT_ACP_CLIENT_NAME = 'plaited-acp-client'
@@ -1,161 +0,0 @@
1
- /**
2
- * JSON-RPC 2.0 Zod schemas with runtime validation.
3
- *
4
- * @remarks
5
- * These schemas provide runtime validation for JSON-RPC messages at the
6
- * transport boundary. While the ACP SDK handles protocol-level types,
7
- * the JSON-RPC framing layer is our responsibility since we implement
8
- * a custom stdio transport.
9
- *
10
- * The schemas follow JSON-RPC 2.0 specification:
11
- * - Requests have `id` and `method`
12
- * - Notifications have `method` but no `id`
13
- * - Responses have `id` and either `result` or `error`
14
- */
15
-
16
- import type { RequestPermissionRequest, SessionNotification } from '@agentclientprotocol/sdk'
17
- import { z } from 'zod'
18
-
19
- // ============================================================================
20
- // Inlined Type Utilities
21
- // ============================================================================
22
-
23
- /** Precise type detection beyond typeof operator */
24
- const trueTypeOf = (obj?: unknown): string => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()
25
-
26
- /** Type guard for precise type checking with TypeScript narrowing */
27
- const isTypeOf = <T>(obj: unknown, type: string): obj is T => trueTypeOf(obj) === type
28
-
29
- // ============================================================================
30
- // JSON-RPC Base Schemas
31
- // ============================================================================
32
-
33
- /** JSON-RPC version literal */
34
- const JsonRpcVersionSchema = z.literal('2.0')
35
-
36
- /** Request/response identifier */
37
- const RequestIdSchema = z.union([z.string(), z.number()])
38
-
39
- /**
40
- * JSON-RPC 2.0 error object schema.
41
- *
42
- * @remarks
43
- * Standard error codes:
44
- * - `-32700`: Parse error
45
- * - `-32600`: Invalid request
46
- * - `-32601`: Method not found
47
- * - `-32602`: Invalid params
48
- * - `-32603`: Internal error
49
- * - `-32800`: Request cancelled (ACP extension)
50
- */
51
- export const JsonRpcErrorSchema = z.object({
52
- code: z.number(),
53
- message: z.string(),
54
- data: z.unknown().optional(),
55
- })
56
-
57
- /** JSON-RPC 2.0 request schema */
58
- export const JsonRpcRequestSchema = z.object({
59
- jsonrpc: JsonRpcVersionSchema,
60
- id: RequestIdSchema,
61
- method: z.string(),
62
- params: z.unknown().optional(),
63
- })
64
-
65
- /** JSON-RPC 2.0 notification schema (no id, no response expected) */
66
- export const JsonRpcNotificationSchema = z.object({
67
- jsonrpc: JsonRpcVersionSchema,
68
- method: z.string(),
69
- params: z.unknown().optional(),
70
- })
71
-
72
- /** JSON-RPC 2.0 success response schema */
73
- export const JsonRpcSuccessResponseSchema = z.object({
74
- jsonrpc: JsonRpcVersionSchema,
75
- id: RequestIdSchema,
76
- result: z.unknown(),
77
- })
78
-
79
- /** JSON-RPC 2.0 error response schema */
80
- export const JsonRpcErrorResponseSchema = z.object({
81
- jsonrpc: JsonRpcVersionSchema,
82
- id: z.union([RequestIdSchema, z.null()]),
83
- error: JsonRpcErrorSchema,
84
- })
85
-
86
- /** Union of all JSON-RPC response types */
87
- export const JsonRpcResponseSchema = z.union([JsonRpcSuccessResponseSchema, JsonRpcErrorResponseSchema])
88
-
89
- /**
90
- * Union of all JSON-RPC message types.
91
- *
92
- * @remarks
93
- * Use `safeParse` at transport boundaries for runtime validation.
94
- * See transport tests for usage patterns.
95
- */
96
- export const JsonRpcMessageSchema = z.union([JsonRpcRequestSchema, JsonRpcNotificationSchema, JsonRpcResponseSchema])
97
-
98
- // ============================================================================
99
- // Inferred Types
100
- // ============================================================================
101
-
102
- /** JSON-RPC 2.0 error object */
103
- export type JsonRpcError = z.infer<typeof JsonRpcErrorSchema>
104
-
105
- /** JSON-RPC 2.0 request structure */
106
- export type JsonRpcRequest<T = unknown> = Omit<z.infer<typeof JsonRpcRequestSchema>, 'params'> & {
107
- params?: T
108
- }
109
-
110
- /** JSON-RPC 2.0 notification structure (no id, no response expected) */
111
- export type JsonRpcNotification<T = unknown> = Omit<z.infer<typeof JsonRpcNotificationSchema>, 'params'> & {
112
- params?: T
113
- }
114
-
115
- /** JSON-RPC 2.0 success response */
116
- export type JsonRpcSuccessResponse<T = unknown> = Omit<z.infer<typeof JsonRpcSuccessResponseSchema>, 'result'> & {
117
- result: T
118
- }
119
-
120
- /** JSON-RPC 2.0 error response */
121
- export type JsonRpcErrorResponse = z.infer<typeof JsonRpcErrorResponseSchema>
122
-
123
- /** Union of all JSON-RPC response types */
124
- export type JsonRpcResponse<T = unknown> = JsonRpcSuccessResponse<T> | JsonRpcErrorResponse
125
-
126
- /** Union of all JSON-RPC message types */
127
- export type JsonRpcMessage<T = unknown> = JsonRpcRequest<T> | JsonRpcNotification<T> | JsonRpcResponse<T>
128
-
129
- // ============================================================================
130
- // ACP SDK Type Schemas
131
- // ============================================================================
132
-
133
- /**
134
- * These schemas use z.custom() to validate SDK types at runtime.
135
- * They validate only the fields we actually use, keeping SDK types
136
- * as the source of truth while adding runtime safety.
137
- */
138
-
139
- /** Type guard for object shape validation */
140
- const isRecord = (val: unknown): val is Record<string, unknown> => isTypeOf<Record<string, unknown>>(val, 'object')
141
-
142
- /**
143
- * Schema for session update notifications.
144
- *
145
- * @remarks
146
- * Validates `sessionId` and `update` fields used in notification handling.
147
- */
148
- export const SessionNotificationSchema = z.custom<SessionNotification>(
149
- (val): val is SessionNotification =>
150
- isRecord(val) && 'sessionId' in val && typeof val.sessionId === 'string' && 'update' in val && isRecord(val.update),
151
- )
152
-
153
- /**
154
- * Schema for permission requests from agent.
155
- *
156
- * @remarks
157
- * Validates `options` array used in permission handling.
158
- */
159
- export const RequestPermissionRequestSchema = z.custom<RequestPermissionRequest>(
160
- (val): val is RequestPermissionRequest => isRecord(val) && 'options' in val && Array.isArray(val.options),
161
- )
package/src/acp.types.ts DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * ACP type definitions.
3
- *
4
- * @remarks
5
- * This module contains types specific to the ACP client implementation.
6
- * For SDK types (ToolCall, ContentBlock, SessionNotification, etc.), import
7
- * directly from `@agentclientprotocol/sdk`.
8
- *
9
- * For runtime validation of JSON-RPC messages, import Zod schemas from
10
- * `./acp.schemas.ts`.
11
- *
12
- * For protocol constants, import from `./acp.constants.ts`.
13
- */
14
-
15
- import type { SessionId } from '@agentclientprotocol/sdk'
16
-
17
- // ============================================================================
18
- // Session Types
19
- // ============================================================================
20
-
21
- /**
22
- * Session object returned from session creation.
23
- * Contains the session ID for subsequent operations.
24
- */
25
- export type Session = {
26
- id: SessionId
27
- _meta?: { [key: string]: unknown } | null
28
- }
@@ -1,8 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Skill(greeting)",
5
- "Skill(greeting:*)"
6
- ]
7
- }
8
- }
@@ -1,17 +0,0 @@
1
- ---
2
- name: greeting
3
- description: Use this skill when asked to greet someone or say hello
4
- ---
5
-
6
- # Greeting Skill
7
-
8
- When the user asks you to greet someone, follow these rules:
9
-
10
- 1. Always start with "Hello from the greeting skill!"
11
- 2. Include the phrase "skill-test-marker" somewhere in your response
12
- 3. Be friendly and welcoming
13
-
14
- ## Example Responses
15
-
16
- - "Hello from the greeting skill! skill-test-marker Welcome to our test!"
17
- - "Hello from the greeting skill! I hope you're having a great day. skill-test-marker"
package/tsconfig.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "include": ["src", "skills", "bin"],
3
- "compilerOptions": {
4
- // Enable latest features
5
- "lib": ["ESNext"],
6
- "target": "ESNext",
7
- "module": "Preserve",
8
- "moduleDetection": "force",
9
- "allowJs": true,
10
-
11
- // IDE may need this to properly show type errors
12
- "rootDir": ".",
13
-
14
- // Bundler mode
15
- "moduleResolution": "bundler",
16
- "allowImportingTsExtensions": true,
17
- "verbatimModuleSyntax": true,
18
- "noEmit": true,
19
-
20
- // Best practices
21
- "strict": true,
22
- "skipLibCheck": true,
23
- "noFallthroughCasesInSwitch": true,
24
- "noUncheckedIndexedAccess": true,
25
- "noImplicitOverride": true,
26
-
27
- // Some stricter flags (disabled by default)
28
- "noUnusedLocals": false,
29
- "noUnusedParameters": false,
30
- "noPropertyAccessFromIndexSignature": false
31
- }
32
- }