@plaited/acp-harness 0.2.6 → 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.
- package/LICENSE +1 -1
- package/README.md +120 -16
- package/bin/cli.ts +105 -636
- package/bin/tests/cli.spec.ts +218 -51
- package/package.json +20 -4
- package/src/acp-client.ts +5 -4
- package/src/acp-transport.ts +14 -7
- package/src/adapter-check.ts +542 -0
- package/src/adapter-scaffold.ts +934 -0
- package/src/balance.ts +232 -0
- package/src/calibrate.ts +300 -0
- package/src/capture.ts +457 -0
- package/src/constants.ts +94 -0
- package/src/grader-loader.ts +174 -0
- package/src/harness.ts +35 -0
- package/src/schemas-cli.ts +239 -0
- package/src/schemas.ts +567 -0
- package/src/summarize.ts +245 -0
- package/src/tests/adapter-check.spec.ts +70 -0
- package/src/tests/adapter-scaffold.spec.ts +112 -0
- package/src/tests/fixtures/grader-bad-module.ts +5 -0
- package/src/tests/fixtures/grader-exec-fail.py +9 -0
- package/src/tests/fixtures/grader-exec-invalid.py +6 -0
- package/src/tests/fixtures/grader-exec.py +29 -0
- package/src/tests/fixtures/grader-module.ts +14 -0
- package/src/tests/grader-loader.spec.ts +153 -0
- package/src/trials.ts +395 -0
- package/src/validate-refs.ts +188 -0
- package/.claude/rules/accuracy.md +0 -43
- package/.claude/rules/bun-apis.md +0 -80
- package/.claude/rules/code-review.md +0 -254
- package/.claude/rules/git-workflow.md +0 -37
- package/.claude/rules/github.md +0 -154
- package/.claude/rules/testing.md +0 -172
- package/.claude/skills/acp-harness/SKILL.md +0 -310
- package/.claude/skills/acp-harness/assets/Dockerfile.acp +0 -25
- package/.claude/skills/acp-harness/assets/docker-compose.acp.yml +0 -19
- package/.claude/skills/acp-harness/references/downstream.md +0 -288
- package/.claude/skills/acp-harness/references/output-formats.md +0 -221
- package/.claude-plugin/marketplace.json +0 -15
- package/.claude-plugin/plugin.json +0 -16
- package/.github/CODEOWNERS +0 -6
- package/.github/workflows/ci.yml +0 -63
- package/.github/workflows/publish.yml +0 -146
- package/.mcp.json +0 -20
- package/CLAUDE.md +0 -92
- package/Dockerfile.test +0 -23
- package/biome.json +0 -96
- package/bun.lock +0 -513
- package/docker-compose.test.yml +0 -21
- package/scripts/bun-test-wrapper.sh +0 -46
- package/src/acp.constants.ts +0 -56
- package/src/acp.schemas.ts +0 -161
- package/src/acp.types.ts +0 -28
- package/src/tests/fixtures/.claude/settings.local.json +0 -8
- package/src/tests/fixtures/.claude/skills/greeting/SKILL.md +0 -17
- 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
|
package/src/acp.constants.ts
DELETED
|
@@ -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'
|
package/src/acp.schemas.ts
DELETED
|
@@ -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,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
|
-
}
|