@jigging/agent-method 0.1.0-alpha.3 → 0.1.0-alpha.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jigging/agent-method",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
4
4
  "description": "A reusable bounded Agent method with an ordinary FLOW entrypoint",
5
5
  "license": "MPL-2.0",
6
6
  "repository": {
@@ -51,4 +51,4 @@
51
51
  "@types/node": "24.13.3",
52
52
  "typescript": "7.0.2"
53
53
  }
54
- }
54
+ }
@@ -1,5 +1,5 @@
1
1
  import { handle, type JsonValue } from '@jigging/flow'
2
- import { withAgentConversation, AgentConversationError } from '../src/conversation.js'
2
+ import { AgentConversationError, withAgentConversation } from '../src/conversation.js'
3
3
 
4
4
  await handle(async (run) => {
5
5
  const displayed: string[] = []
@@ -32,9 +32,12 @@ await handle(async (run) => {
32
32
  const first = await conversation.initial
33
33
  if (run.input === 'callback-error') throw new Error('application rejected draft')
34
34
  const second = conversation.prompt({ instructions: 'Apply this correction' })
35
- if (run.input === 'interrupt' || run.input === 'completion-race')
36
- await conversation.interrupt()
37
- return { first, second: await second }
35
+ const control = ['interrupt', 'completion-race', 'not-running-race'].includes(
36
+ run.input as string,
37
+ )
38
+ ? await conversation.interrupt()
39
+ : undefined
40
+ return { first, second: await second, ...(control === undefined ? {} : { control }) }
38
41
  },
39
42
  )
40
43
  return {
@@ -136,14 +136,27 @@ async function exercise(mode: string) {
136
136
  } else if (request.method === 'channel/send') {
137
137
  ok(request, null)
138
138
  const command = p.value
139
- item({ type: 'accepted', command: command.type, turn: command.turn })
140
- if (command.type === 'prompt') {
141
- if (mode === 'late-error') {
142
- nativeSettled = true
143
- fail(call, 'EXECUTION_FAILED')
144
- } else if (!['interrupt', 'completion-race'].includes(mode)) terminal(command.turn)
145
- } else if (command.type === 'interrupt')
146
- terminal(command.turn, mode === 'interrupt' ? 'cancelled' : 'result')
139
+ if (command.type === 'interrupt' && mode === 'not-running-race') {
140
+ // The turn finishes as the interruption reaches the Agent. The
141
+ // terminal result must remain distinct from the control rejection.
142
+ terminal(command.turn)
143
+ item({
144
+ type: 'rejected',
145
+ command: 'interrupt',
146
+ turn: command.turn,
147
+ code: 'NOT_RUNNING',
148
+ })
149
+ } else {
150
+ item({ type: 'accepted', command: command.type, turn: command.turn })
151
+ if (command.type === 'prompt') {
152
+ if (mode === 'late-error') {
153
+ nativeSettled = true
154
+ fail(call, 'EXECUTION_FAILED')
155
+ } else if (!['interrupt', 'completion-race', 'not-running-race'].includes(mode))
156
+ terminal(command.turn)
157
+ } else if (command.type === 'interrupt')
158
+ terminal(command.turn, mode === 'interrupt' ? 'cancelled' : 'result')
159
+ }
147
160
  } else if (request.method === 'channel/close') {
148
161
  expect(p.endpoint).toBe('commands:s')
149
162
  closed = true
@@ -230,11 +243,21 @@ async function exercise(mode: string) {
230
243
  }
231
244
  }
232
245
 
233
- for (const mode of ['normal', 'interrupt', 'completion-race']) {
246
+ for (const mode of ['normal', 'interrupt', 'completion-race', 'not-running-race']) {
234
247
  test(`public conversation helper: ${mode}`, async () => {
235
- const { output } = await exercise(mode)
248
+ const { output, operations } = await exercise(mode)
236
249
  expect(output.turns).toHaveLength(2)
237
250
  expect(output.value.second.type).toBe(mode === 'interrupt' ? 'cancelled' : 'result')
251
+ if (mode === 'interrupt' || mode === 'completion-race')
252
+ expect(output.value.control).toBe('accepted')
253
+ if (mode === 'not-running-race') {
254
+ expect(output.value.control).toBe('not-running')
255
+ expect(
256
+ operations
257
+ .filter((operation) => operation.method === 'channel/send')
258
+ .map((operation) => operation.params.value.type),
259
+ ).toEqual(['prompt', 'interrupt', 'close'])
260
+ }
238
261
  expect(output.settlement).toEqual({ outcome: 'done', output: { turns: 2 } })
239
262
  })
240
263
  }