@jigging/agent-acp 0.1.0-alpha.5 → 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
@@ -33,6 +33,8 @@ retains credential, process, and dispatch authority.
33
33
  - Jig consumers may select this declared dependency with `npm:@jigging/agent-acp`
34
34
  in a local Binding; the Binding still grants the exact native client.
35
35
  Contract-keyed project selection does not create that grant or choose a vendor.
36
+ The README teaches package-selected caller creation and offline contract import
37
+ from ordinary root/member installs; consumers do not name physical installer paths.
36
38
  - Reuse `@jigging/agent-method` for prompt preparation and result validation.
37
39
  Complete ACP dialogue and resource settlement are separate requirements.
38
40
  - Locally detected invalid ACP cancels the resource while preserving that
@@ -45,6 +47,9 @@ retains credential, process, and dispatch authority.
45
47
  closes the writer with `error: 'LAGGED'`; no clean EOF hides incomplete output.
46
48
  Closed native warning notices go to console diagnostics, not answer text or
47
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.
48
53
  - Optional conversational mode owns bounded direct commands/replies and per-turn
49
54
  results in `src/conversation.ts`. Native maxTurns, serial dispatch and interruption
50
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
@@ -127,6 +131,30 @@ The example's client is a choice, not a Jig default; `codex`, `claude` and `pi`
127
131
  use the same grant interface. The operator configures the native installation, model and
128
132
  authentication described in [Choose an Agent](https://jig.md/guide/agents).
129
133
 
134
+ To call this Agent from a new Flow, install the declared project dependency
135
+ with `bun install`, then select its complete contract when creating the caller:
136
+
137
+ ```sh
138
+ jig new worker --use agent=npm:@jigging/agent-acp
139
+ ```
140
+
141
+ For an existing caller, create its `contracts/` parent and import the bundle:
142
+
143
+ ```sh
144
+ mkdir -p flows/worker/contracts
145
+ jig import-contract npm:@jigging/agent-acp flows/worker/contracts/agent
146
+ ```
147
+
148
+ Declare `uses.agent.contract: './contracts/agent/FLOW.contract.json'` in that
149
+ caller's metadata. Selection uses the nearest ordinary project or member-local
150
+ installation, copies all referenced channel descriptors offline, and runs no
151
+ package code. The copied contract belongs to the caller: an installation update
152
+ does not replace it or grant new authority. An existing destination is refused;
153
+ choose a new directory to inspect a changed contract before updating the caller.
154
+ See the [conversation walkthrough](https://jig.md/guide/conversations) for a
155
+ complete two-turn caller and the separate native turn grant. These authoring
156
+ commands require the matching Jig source candidate until its alpha is published.
157
+
130
158
  ```sh
131
159
  jig review
132
160
  jig run binding:agent --input '{"instructions":"Explain one useful check."}' --receive events
package/dist/flow.js CHANGED
@@ -1,9 +1,11 @@
1
1
  // ../agent-method/dist/errors.js
2
2
  class AgentMethodError extends Error {
3
3
  code;
4
- constructor(code, message) {
4
+ details;
5
+ constructor(code, message, details) {
5
6
  super(message);
6
7
  this.code = code;
8
+ this.details = details;
7
9
  this.name = "AgentMethodError";
8
10
  }
9
11
  }
@@ -3215,7 +3217,7 @@ class FinitePeer {
3215
3217
  if (frame.id !== id || Object.hasOwn(frame, "result") === Object.hasOwn(frame, "error"))
3216
3218
  failure("Native ACP response does not match its request");
3217
3219
  if (frame.error !== undefined)
3218
- 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.`);
3219
3221
  return object2(frame.result);
3220
3222
  }
3221
3223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jigging/agent-acp",
3
- "version": "0.1.0-alpha.5",
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": {
@@ -37,7 +37,7 @@
37
37
  ],
38
38
  "devDependencies": {
39
39
  "@jigging/flow": "0.1.0-alpha.13",
40
- "@jigging/agent-method": "0.1.0-alpha.5",
40
+ "@jigging/agent-method": "0.1.0-alpha.6",
41
41
  "@types/node": "24.13.3",
42
42
  "typescript": "7.0.2"
43
43
  }
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',