@jigging/agent-acp 0.1.0-alpha.6 → 0.1.0-alpha.7

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 CHANGED
@@ -47,6 +47,9 @@ retains credential, process, and dispatch authority.
47
47
  closes the writer with `error: 'LAGGED'`; no clean EOF hides incomplete output.
48
48
  Closed native warning notices go to console diagnostics, not answer text or
49
49
  public events; the host strips raw metadata and rejects authoritative errors.
50
+ - A native request rejection reports its known finite ACP method with
51
+ `EXECUTION_FAILED`, never the client's error text or data. That phase does not
52
+ establish the private cause, remote dispatch or permission to retry.
50
53
  - Optional conversational mode owns bounded direct commands/replies and per-turn
51
54
  results in `src/conversation.ts`. Native maxTurns, serial dispatch and interruption
52
55
  settlement remain host-enforced. One-shot calls retain their simple interface.
package/README.md CHANGED
@@ -38,6 +38,10 @@ filesystem context are not supplied.
38
38
 
39
39
  Native warnings are separate, sanitized console diagnostics rather than answer
40
40
  text or Agent events. Authoritative native errors remain invocation failures.
41
+ Rejected native requests report the failed ACP step, such as `session/new` or
42
+ `session/prompt`, with `EXECUTION_FAILED`. The client's private error text and
43
+ data are withheld. The step identifies where the rejection was received; it
44
+ does not establish its cause, remote effects, or permission to repeat the call.
41
45
 
42
46
  For conversational use, add `conversation: true` to input and connect direct
43
47
  `commands` and `replies` channels from the complete contract bundle. Initial
package/dist/flow.js CHANGED
@@ -3217,7 +3217,7 @@ class FinitePeer {
3217
3217
  if (frame.id !== id || Object.hasOwn(frame, "result") === Object.hasOwn(frame, "error"))
3218
3218
  failure("Native ACP response does not match its request");
3219
3219
  if (frame.error !== undefined)
3220
- throw new OperationError("EXECUTION_FAILED", "Native ACP request failed");
3220
+ throw new OperationError("EXECUTION_FAILED", `Native ACP request failed during ${method}; private client details were withheld.`);
3221
3221
  return object2(frame.result);
3222
3222
  }
3223
3223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jigging/agent-acp",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.7",
4
4
  "description": "An ordinary Agent Flow over a finite, host-authorized ACP resource",
5
5
  "license": "MPL-2.0",
6
6
  "repository": {
package/src/flow.ts CHANGED
@@ -32,6 +32,13 @@ const RESPONSES = './contracts/finite-acp/responses.json'
32
32
  const MAX_TEXT_BYTES = 8_388_608
33
33
 
34
34
  type Settlement = { result: RunResult } | { error: unknown }
35
+ type NativeRequestMethod =
36
+ | 'initialize'
37
+ | 'session/new'
38
+ | 'session/resume'
39
+ | 'session/set_config_option'
40
+ | 'session/set_mode'
41
+ | 'session/prompt'
35
42
 
36
43
  /** One replaceable method; process, credentials and reviewed policy stay outside. */
37
44
  export async function agentAcpFlow(run: RunContext): Promise<RunResult> {
@@ -261,7 +268,7 @@ class FinitePeer {
261
268
  private readonly updates: OptionalUpdates,
262
269
  ) {}
263
270
 
264
- async request(method: string, params: JsonObject): Promise<JsonObject> {
271
+ async request(method: NativeRequestMethod, params: JsonObject): Promise<JsonObject> {
265
272
  const id = ++this.operation
266
273
  await this.write({ jsonrpc: '2.0', id, method, params })
267
274
  for (;;) {
@@ -275,7 +282,10 @@ class FinitePeer {
275
282
  if (frame.id !== id || Object.hasOwn(frame, 'result') === Object.hasOwn(frame, 'error'))
276
283
  failure('Native ACP response does not match its request')
277
284
  if (frame.error !== undefined)
278
- throw new OperationError('EXECUTION_FAILED', 'Native ACP request failed')
285
+ throw new OperationError(
286
+ 'EXECUTION_FAILED',
287
+ `Native ACP request failed during ${method}; private client details were withheld.`,
288
+ )
279
289
  return object(frame.result)
280
290
  }
281
291
  }
package/test/flow.test.ts CHANGED
@@ -248,6 +248,54 @@ function fixture(options: Options = {}) {
248
248
  }
249
249
  }
250
250
 
251
+ describe('native request failure diagnostics', () => {
252
+ test.each([
253
+ 'initialize',
254
+ 'session/new',
255
+ 'session/resume',
256
+ 'session/set_config_option',
257
+ 'session/set_mode',
258
+ 'session/prompt',
259
+ ])(
260
+ 'identifies %s without exposing native error text or sending further requests',
261
+ async (method) => {
262
+ const restoring = method === 'session/resume'
263
+ const f = fixture({
264
+ ...(restoring
265
+ ? {
266
+ input: {
267
+ instructions: 'Continue.',
268
+ session: { restore: '013579ab-cdef-4567-89ab-0123456789ab' },
269
+ },
270
+ ready: { ...ready, restoreSessionId: 'owned-session' },
271
+ }
272
+ : {}),
273
+ async emit(frame, send) {
274
+ if (frame.method !== method) return false
275
+ await f.frameSend(send, {
276
+ jsonrpc: '2.0',
277
+ id: frame.id!,
278
+ error: {
279
+ code: -32603,
280
+ message: '/private/native-state secret-token rejected private-model',
281
+ data: { credential: 'secret-token', cause: 'untrusted native detail' },
282
+ },
283
+ })
284
+ return true
285
+ },
286
+ })
287
+ const failure = await agentAcpFlow(f.run).catch((error) => error)
288
+ expect(failure).toBeInstanceOf(OperationError)
289
+ expect(failure).toMatchObject({
290
+ code: 'EXECUTION_FAILED',
291
+ message: `Native ACP request failed during ${method}; private client details were withheld.`,
292
+ })
293
+ expect(f.frames.at(-1)?.method).toBe(method)
294
+ expect(f.stats()).toEqual({ calls: 1, cancelled: true, settled: true })
295
+ },
296
+ )
297
+ })
298
+
251
299
  describe('ordinary session retention and restoration', () => {
252
300
  test.each(['active', 'settled'])(
253
301
  'notice display during %s does not enter answers or selected public events',