@agentshouse/kit 0.2.1-c0b2838a220ac → 0.2.1-c0eea939ba749

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 (92) hide show
  1. package/README.md +16 -15
  2. package/dist/acp.js +34 -14
  3. package/dist/agents.js +85 -17
  4. package/dist/api.js +1 -1
  5. package/dist/app-git.js +10 -26
  6. package/dist/bootstrap.json +4 -4
  7. package/dist/bridge.js +3 -6
  8. package/dist/chatgpt.js +9 -2
  9. package/dist/clis.js +11 -1
  10. package/dist/conversations.js +133 -73
  11. package/dist/copies.js +86 -45
  12. package/dist/end.js +3 -2
  13. package/dist/events.js +4 -0
  14. package/dist/files.js +1 -1
  15. package/dist/git.js +2 -3
  16. package/dist/home.js +31 -13
  17. package/dist/house-cli.js +291 -0
  18. package/dist/house-main.js +7 -262
  19. package/dist/inputs.js +37 -0
  20. package/dist/instructions.js +4 -28
  21. package/dist/kit-cli.js +68 -0
  22. package/dist/kit-main.js +8 -67
  23. package/dist/login.js +39 -10
  24. package/dist/logout.js +0 -2
  25. package/dist/placement.js +2 -20
  26. package/dist/resident.js +60 -15
  27. package/dist/service.js +22 -0
  28. package/dist/sign-in.js +5 -23
  29. package/dist/skills.js +71 -12
  30. package/dist/stream.js +62 -16
  31. package/dist/transcription.js +3 -3
  32. package/dist/update.js +20 -23
  33. package/dist/wire.js +1 -1
  34. package/dist/work.js +3 -5
  35. package/how-we-work.md +13 -3
  36. package/package.json +2 -1
  37. package/skills/ask-matt/SKILL.md +17 -11
  38. package/skills/ask-matt/agents/openai.yaml +1 -0
  39. package/skills/code-review/SKILL.md +5 -5
  40. package/skills/codebase-design/DESIGN-IT-TWICE.md +1 -1
  41. package/skills/codebase-design/SKILL.md +0 -2
  42. package/skills/diagnosing-bugs/SKILL.md +2 -4
  43. package/skills/domain-modeling/{CONTEXT-FORMAT.md → GLOSSARY-FORMAT.md} +10 -10
  44. package/skills/domain-modeling/SKILL.md +12 -14
  45. package/skills/grill-me/SKILL.md +1 -2
  46. package/skills/grill-me/agents/openai.yaml +1 -0
  47. package/skills/grill-with-docs/SKILL.md +1 -2
  48. package/skills/grill-with-docs/agents/openai.yaml +1 -0
  49. package/skills/grilling/SKILL.md +2 -2
  50. package/skills/handoff/SKILL.md +2 -3
  51. package/skills/handoff/agents/openai.yaml +1 -0
  52. package/skills/implement/SKILL.md +5 -4
  53. package/skills/implement/agents/openai.yaml +1 -0
  54. package/skills/implement-spec/SKILL.md +40 -0
  55. package/skills/implement-spec/agents/openai.yaml +5 -0
  56. package/skills/improve-codebase-architecture/SKILL.md +6 -7
  57. package/skills/improve-codebase-architecture/agents/openai.yaml +1 -0
  58. package/skills/pr/CREDITS.md +3 -0
  59. package/skills/pr/LICENSE +21 -0
  60. package/skills/pr/SKILL.md +170 -0
  61. package/skills/pr/agents/openai.yaml +3 -0
  62. package/skills/prototype/SKILL.md +0 -2
  63. package/skills/research/SKILL.md +0 -2
  64. package/skills/retro/LICENSE +21 -0
  65. package/skills/retro/SKILL.md +44 -0
  66. package/skills/retro/agents/openai.yaml +5 -0
  67. package/skills/tdd/SKILL.md +2 -4
  68. package/skills/teach/SKILL.md +3 -4
  69. package/skills/teach/agents/openai.yaml +1 -0
  70. package/skills/to-questionnaire/SKILL.md +1 -2
  71. package/skills/to-questionnaire/agents/openai.yaml +1 -0
  72. package/skills/to-spec/SKILL.md +1 -2
  73. package/skills/to-spec/agents/openai.yaml +1 -0
  74. package/skills/to-tickets/SKILL.md +3 -4
  75. package/skills/to-tickets/agents/openai.yaml +1 -0
  76. package/skills/triage/AGENT-BRIEF.md +207 -0
  77. package/skills/triage/LICENSE +21 -0
  78. package/skills/triage/OUT-OF-SCOPE.md +105 -0
  79. package/skills/triage/SKILL.md +112 -0
  80. package/skills/triage/agents/openai.yaml +5 -0
  81. package/skills/wait-what/SKILL.md +2 -3
  82. package/skills/wait-what/agents/openai.yaml +1 -0
  83. package/skills/wayfinder/SKILL.md +5 -6
  84. package/skills/wayfinder/agents/openai.yaml +1 -0
  85. package/skills/wizard/LICENSE +21 -0
  86. package/skills/wizard/SKILL.md +44 -0
  87. package/skills/wizard/agents/openai.yaml +3 -0
  88. package/skills/wizard/template.sh +223 -0
  89. package/skills/writing-for-agents/SKILL.md +0 -2
  90. package/skills/resolving-merge-conflicts/SKILL.md +0 -16
  91. package/skills/resolving-merge-conflicts/agents/openai.yaml +0 -3
  92. /package/skills/{resolving-merge-conflicts → implement-spec}/LICENSE +0 -0
@@ -1,39 +1,88 @@
1
- import { client, } from '@agentclientprotocol/sdk';
1
+ import { client, RequestError, } from '@agentclientprotocol/sdk';
2
2
  import { createHash, randomUUID } from 'node:crypto';
3
3
  import { mkdir } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
5
  import { unlessAborted } from './abort.js';
6
6
  import { startAdapter } from './acp.js';
7
+ import { finalRefusal } from './api.js';
7
8
  import { openBridge } from './bridge.js';
8
9
  import { CLIS } from './clis.js';
9
- import { readerFor } from './events.js';
10
+ import { answeredFailure, readerFor } from './events.js';
10
11
  import { placeFiles, uploadBytes } from './files.js';
11
12
  import { agentBase } from './home.js';
12
13
  import { instructions } from './instructions.js';
13
14
  import { Parts } from './parts.js';
15
+ import { refusalOf } from './refusals.js';
14
16
  import { killMarked, Scope } from './scope.js';
15
17
  import { holdSecretInput } from './secret-input.js';
16
18
  import { createHowWeWork } from './skills.js';
17
19
  import { transcribe } from './transcription.js';
18
20
  import { workFor } from './work.js';
21
+ const SIGNED_OUT = RequestError.authRequired().code;
19
22
  const KILLED = 'the conversation was killed';
23
+ const REFUSED = 'the CLI refused the prompt';
24
+ const NO_CONNECTION = "the Agent's computer could not open this conversation; try again";
25
+ const GONE = 'House no longer holds this conversation; start a new one';
26
+ const RETIRED = "this conversation's Agent is retired, so it cannot start";
27
+ const ENDED = {
28
+ conversation_not_found: GONE,
29
+ conversation_historical: RETIRED,
30
+ };
31
+ const NO_START = "the Agent's CLI did not start";
32
+ const NO_SESSION = "the Agent's CLI did not open a session";
33
+ const NO_RESUME = "the Agent's CLI could not resume this conversation";
34
+ const NO_SETTINGS = "the Agent's CLI refused the Agent's model, mode or effort";
35
+ class NotStarted extends Error {
36
+ }
37
+ async function step(reason, work) {
38
+ try {
39
+ return await work;
40
+ }
41
+ catch (error) {
42
+ throw new NotStarted(typeof reason === 'string' ? reason : reason(error), { cause: error });
43
+ }
44
+ }
45
+ function unbridged(error) {
46
+ return (finalRefusal(error) ? ENDED[refusalOf(error.text)?.code ?? ''] : undefined) ?? NO_CONNECTION;
47
+ }
48
+ const EXIT_PLAN_MODE = {
49
+ parse(value) {
50
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
51
+ throw new Error('_x.ai/exit_plan_mode needs an object');
52
+ }
53
+ return value;
54
+ },
55
+ };
20
56
  export const CONVERSATION_INPUTS = new Set(['open', 'message', 'interrupt', 'kill', 'option', 'answer']);
21
57
  function causeOf(error) {
22
58
  return error instanceof Error ? error.message : String(error);
23
59
  }
60
+ function answeredWith(error) {
61
+ const signedOut = typeof error === 'object' && error !== null && error.code === SIGNED_OUT;
62
+ return { failure: signedOut ? 'signed_out' : 'error', cause: causeOf(error) };
63
+ }
64
+ function exitedWith(running, cause) {
65
+ return running.killed ? { failure: 'killed', cause: KILLED } : { failure: 'exited', cause };
66
+ }
24
67
  function answerMessage(request, response) {
25
68
  return `The User answered a question you asked earlier.\nQuestion: ${JSON.stringify(request)}\nAnswer: ${JSON.stringify(response)}`;
26
69
  }
27
70
  function logged(error) {
28
71
  process.stderr.write(`kit: ${causeOf(error)}\n`);
29
72
  }
73
+ function refusal(conversation, error) {
74
+ if (conversation.kills > 0)
75
+ return KILLED;
76
+ const cause = error instanceof NotStarted ? `${error.message}: ${causeOf(error.cause)}` : causeOf(error);
77
+ logged(new Error(`conversation ${conversation.id} did not start: ${cause}`));
78
+ return causeOf(error);
79
+ }
30
80
  function marker(bridge) {
31
81
  return `HOUSE_BRIDGE=${bridge.env.HOUSE_BRIDGE}`;
32
82
  }
33
83
  class Turn {
34
84
  id = randomUUID();
35
85
  parts;
36
- admitted = false;
37
86
  questions = 0;
38
87
  secrets = 0;
39
88
  prompted = false;
@@ -57,6 +106,7 @@ class Conversation {
57
106
  subagents = new Map();
58
107
  held = [];
59
108
  opening = null;
109
+ prompted = null;
60
110
  kills = 0;
61
111
  killed = new AbortController();
62
112
  interrupts = 0;
@@ -79,9 +129,7 @@ function asksSecret(request) {
79
129
  export class Conversations {
80
130
  kit;
81
131
  conversations = new Map();
82
- acks = new Map();
83
132
  questions = new Map();
84
- carrying = 0;
85
133
  reporting = 0;
86
134
  watched = false;
87
135
  constructor(kit) {
@@ -90,37 +138,26 @@ export class Conversations {
90
138
  setInterval(() => this.look(), 2_000);
91
139
  }
92
140
  input(input) {
93
- this.carrying++;
94
- const carried = this.acks.get(input.input_id) ??
95
- (() => {
96
- const conversation = this.conversation(input.conversation_id);
97
- if (input.kind === 'kill') {
98
- conversation.kills++;
99
- conversation.killed.abort(new Error(KILLED));
100
- for (const waiting of conversation.waiting.splice(0))
101
- waiting.settle({ refused: KILLED });
102
- this.halt(conversation);
103
- }
104
- if (input.kind === 'interrupt') {
105
- conversation.interrupts++;
106
- conversation.interrupted.abort();
107
- }
108
- const handled = conversation.queue.then(() => this.carry(conversation, input));
109
- conversation.queue = handled.catch(() => undefined);
110
- const work = handled.then(({ ack }) => ack);
111
- this.acks.set(input.input_id, work);
112
- return work;
113
- })();
114
- carried
115
- .then((body) => this.kit.house.deliver(`/kit/inputs/${input.input_id}/ack`, body))
116
- .catch(logged)
117
- .finally(() => {
118
- this.carrying--;
119
- this.kit.changed();
141
+ void this.kit.inputs.carry(input.input_id, () => {
142
+ const conversation = this.conversation(input.conversation_id);
143
+ if (input.kind === 'kill') {
144
+ conversation.kills++;
145
+ conversation.killed.abort(new Error(KILLED));
146
+ for (const waiting of conversation.waiting.splice(0))
147
+ waiting.settle({ refused: KILLED });
148
+ this.halt(conversation);
149
+ }
150
+ if (input.kind === 'interrupt') {
151
+ conversation.interrupts++;
152
+ conversation.interrupted.abort();
153
+ }
154
+ const handled = conversation.queue.then(() => this.carry(conversation, input));
155
+ conversation.queue = handled.catch(() => undefined);
156
+ return handled.then(async ({ ack }) => ({ ack: await ack }));
120
157
  });
121
158
  }
122
159
  idle() {
123
- if (this.carrying > 0 || this.reporting > 0)
160
+ if (this.reporting > 0)
124
161
  return false;
125
162
  for (const conversation of this.conversations.values()) {
126
163
  const turn = conversation.turn;
@@ -200,10 +237,10 @@ export class Conversations {
200
237
  if (conversation.running !== null)
201
238
  return {};
202
239
  try {
203
- return { provider_session_id: await this.start(conversation, await this.route(conversation, input.agent_id), null) };
240
+ return { provider_session_id: await this.start(conversation, await this.route(conversation, input.agent_id), null, true) };
204
241
  }
205
242
  catch (error) {
206
- return { refused: causeOf(error) };
243
+ return { refused: refusal(conversation, error) };
207
244
  }
208
245
  }
209
246
  async message(conversation, input) {
@@ -220,7 +257,7 @@ export class Conversations {
220
257
  throw new Error(KILLED);
221
258
  }
222
259
  catch (error) {
223
- return { ack: Promise.resolve({ refused: conversation.kills > 0 ? KILLED : causeOf(error) }) };
260
+ return { ack: Promise.resolve({ refused: refusal(conversation, error) }) };
224
261
  }
225
262
  return {
226
263
  ack: new Promise((settle) => {
@@ -243,13 +280,17 @@ export class Conversations {
243
280
  async send(conversation, waiting) {
244
281
  const { input } = waiting;
245
282
  let ack = {};
283
+ let started = false;
246
284
  const prompt = [];
247
285
  try {
248
286
  if (conversation.running === null) {
249
- const resumed = input.provider_session_id ?? conversation.session;
250
- const opened = await this.start(conversation, waiting.route, resumed);
251
- if (resumed === null)
252
- ack = { provider_session_id: opened };
287
+ const stored = conversation.session ?? input.provider_session_id;
288
+ const empty = input.first === true && conversation.prompted !== stored;
289
+ started = (await this.start(conversation, waiting.route, stored, empty)) !== stored;
290
+ }
291
+ const session = conversation.running.sessionId;
292
+ if (started || (input.first === true && session !== input.provider_session_id)) {
293
+ ack = { provider_session_id: session };
253
294
  }
254
295
  if (input.first === true) {
255
296
  prompt.push({
@@ -261,11 +302,11 @@ export class Conversations {
261
302
  throw new Error(KILLED);
262
303
  }
263
304
  catch (error) {
264
- if ('provider_session_id' in ack) {
305
+ if (started) {
265
306
  conversation.session = null;
266
307
  await this.kill(conversation);
267
308
  }
268
- waiting.settle({ refused: conversation.kills > 0 ? KILLED : causeOf(error) });
309
+ waiting.settle({ refused: refusal(conversation, error) });
269
310
  return;
270
311
  }
271
312
  this.prompt(conversation, [...prompt, ...waiting.content]);
@@ -343,14 +384,15 @@ export class Conversations {
343
384
  }
344
385
  return route;
345
386
  }
346
- async start(conversation, route, sessionId) {
387
+ async start(conversation, route, sessionId, empty) {
347
388
  const reader = readerFor(route.kind);
348
389
  reader.session = sessionId;
349
390
  const app = client({ name: '@agentshouse/kit' })
350
391
  .onRequest('session/request_permission', ({ params, signal }) => this.ask(conversation, 'session/request_permission', params, false, signal))
351
- .onRequest('elicitation/create', ({ params, signal }) => this.ask(conversation, 'elicitation/create', params, asksSecret(params), signal));
392
+ .onRequest('elicitation/create', ({ params, signal }) => this.ask(conversation, 'elicitation/create', params, asksSecret(params), signal))
393
+ .onRequest('_x.ai/exit_plan_mode', EXIT_PLAN_MODE, ({ params, signal }) => this.ask(conversation, '_x.ai/exit_plan_mode', params, false, signal));
352
394
  const cli = await unlessAborted(this.kit.agents.cli(route.kind), conversation.killed.signal);
353
- const bridge = await openBridge(this.kit.house, this.kit.copies, conversation.id, conversation.killed.signal);
395
+ const bridge = await step(unbridged, openBridge(this.kit.house, this.kit.copies, conversation.id, conversation.killed.signal));
354
396
  if (conversation.kills > 0) {
355
397
  bridge.close();
356
398
  throw new Error(KILLED);
@@ -358,27 +400,28 @@ export class Conversations {
358
400
  conversation.opening = bridge;
359
401
  const work = workFor(route.kind, route.working_directory, () => this.kit.changed());
360
402
  const scope = new Scope(marker(bridge), randomUUID(), cli);
403
+ let adapter = null;
361
404
  try {
362
405
  await unlessAborted(createHowWeWork(bridge), conversation.killed.signal);
363
406
  await CLIS[route.kind].allowHouse(bridge.env.PATH);
364
- const adapter = await startAdapter(route.kind, cli, route.working_directory, app, (message) => {
407
+ const streamed = await step(NO_CONNECTION, work.open(cli));
408
+ adapter = await step(NO_START, startAdapter(route.kind, cli, route.working_directory, app, (message) => {
365
409
  work.read(message);
366
410
  this.read(conversation, reader, message);
367
- }, { ...bridge.env, ...(await work.open(cli)) }, undefined, scope);
411
+ }, { ...bridge.env, ...streamed }, undefined, scope));
368
412
  void adapter.exited.then(() => bridge.close());
369
413
  const agent = adapter.connection.agent;
370
414
  const cwd = route.working_directory;
371
415
  const _meta = CLIS[route.kind].sessionMeta(bridge.env.HOUSE_BRIDGE, conversation.id);
372
- const opened = sessionId === null
373
- ? await agent.request('session/new', { cwd, mcpServers: [], _meta })
374
- : { ...(await agent.request('session/resume', { sessionId, cwd, mcpServers: [], _meta })), sessionId };
416
+ const resumed = sessionId === null ? null : await this.resume(conversation, route.kind, adapter, { sessionId, cwd, mcpServers: [], _meta }, empty);
417
+ const opened = resumed ?? (await step(NO_SESSION, agent.request('session/new', { cwd, mcpServers: [], _meta })));
375
418
  reader.session = opened.sessionId;
376
- if (sessionId === null && CLIS[route.kind].renames) {
419
+ if (opened.sessionId !== sessionId && CLIS[route.kind].renames) {
377
420
  const prompt = [{ type: 'text', text: `/rename ${conversation.id}` }];
378
- await agent.request('session/prompt', { sessionId: opened.sessionId, prompt });
421
+ await step(NO_SESSION, agent.request('session/prompt', { sessionId: opened.sessionId, prompt }));
379
422
  }
380
423
  const running = { adapter, bridge, sessionId: opened.sessionId, killed: false, reader, work, scope };
381
- const options = await this.launchSettings(running, route, opened.configOptions ?? []);
424
+ const options = await step(NO_SETTINGS, this.launchSettings(running, route, opened.configOptions ?? []));
382
425
  void work.settled().then(() => scope.record());
383
426
  conversation.running = running;
384
427
  conversation.session = running.sessionId;
@@ -386,11 +429,11 @@ export class Conversations {
386
429
  if (conversation.commands !== null)
387
430
  this.commands(conversation, conversation.commands);
388
431
  this.options(conversation, options);
389
- void adapter.exited.then((cause) => this.exited(conversation, adapter, cause));
432
+ void adapter.lost.then((cause) => this.exited(conversation, running, cause));
390
433
  return running.sessionId;
391
434
  }
392
435
  catch (error) {
393
- scope.kill();
436
+ adapter?.retire();
394
437
  work.close();
395
438
  conversation.leftovers.add(scope);
396
439
  bridge.close();
@@ -400,6 +443,18 @@ export class Conversations {
400
443
  conversation.opening = null;
401
444
  }
402
445
  }
446
+ async resume(conversation, kind, adapter, request, empty) {
447
+ try {
448
+ return { ...(await adapter.connection.agent.request('session/resume', request)), sessionId: request.sessionId };
449
+ }
450
+ catch (error) {
451
+ if (!empty || conversation.kills > 0 || !CLIS[kind].unknownSession(error)) {
452
+ throw new NotStarted(NO_RESUME, { cause: error });
453
+ }
454
+ logged(new Error(`conversation ${conversation.id} opens a new session: ${NO_RESUME}: ${causeOf(error)}`));
455
+ return null;
456
+ }
457
+ }
403
458
  async launchSettings(running, route, offered) {
404
459
  let options = offered;
405
460
  const settings = [
@@ -421,13 +476,10 @@ export class Conversations {
421
476
  }
422
477
  return options;
423
478
  }
424
- exited(conversation, adapter, cause) {
425
- const running = conversation.running;
426
- if (running?.adapter !== adapter)
427
- return;
479
+ exited(conversation, running, cause) {
428
480
  this.detach(conversation, running);
429
481
  if (conversation.turn !== null) {
430
- this.end(conversation, conversation.turn, { failed: running.killed ? KILLED : cause });
482
+ this.end(conversation, conversation.turn, exitedWith(running, cause));
431
483
  }
432
484
  this.next(conversation);
433
485
  this.kit.changed();
@@ -466,7 +518,7 @@ export class Conversations {
466
518
  return delivered;
467
519
  }
468
520
  write(conversation, turn, operation) {
469
- if (!turn.admitted || turn.ended || !this.watched)
521
+ if (turn.ended || !this.watched)
470
522
  return;
471
523
  this.kit.send({ type: 'turn', conversation_id: conversation.id, turn_id: turn.id, ...operation });
472
524
  }
@@ -477,12 +529,7 @@ export class Conversations {
477
529
  begin(conversation) {
478
530
  const turn = new Turn((operation) => this.write(conversation, turn, operation));
479
531
  conversation.open++;
480
- void this.deliver(conversation, turn, 'started', {})
481
- .then(() => {
482
- turn.admitted = true;
483
- this.replay(conversation, turn);
484
- })
485
- .catch(logged);
532
+ void this.deliver(conversation, turn, 'started', {}).catch(logged);
486
533
  conversation.turn = turn;
487
534
  if (conversation.context !== null)
488
535
  turn.parts.measure(conversation.context);
@@ -491,13 +538,17 @@ export class Conversations {
491
538
  this.kit.changed();
492
539
  return turn;
493
540
  }
494
- end(conversation, turn, failed) {
541
+ end(conversation, turn, failed, notice = null) {
495
542
  if (turn.ended)
496
543
  return;
544
+ if (failed !== null)
545
+ logged(new Error(`conversation ${conversation.id} turn ${turn.id} failed: ${failed.cause}`));
497
546
  if (conversation.turn === turn) {
498
547
  for (const event of conversation.running?.reader.closeTurn() ?? [])
499
548
  this.apply(conversation, turn, event);
500
549
  }
550
+ if (notice !== null)
551
+ turn.parts.start({ type: 'marker', marker: 'retry', text: notice });
501
552
  turn.ended = true;
502
553
  conversation.open--;
503
554
  if (conversation.turn === turn)
@@ -505,7 +556,7 @@ export class Conversations {
505
556
  const body = Promise.allSettled(turn.uploads).then(() => ({
506
557
  parts: turn.parts.saved(),
507
558
  context: turn.parts.context,
508
- ...failed,
559
+ ...(failed === null ? {} : { failed: failed.failure }),
509
560
  }));
510
561
  void this.deliver(conversation, turn, 'ended', body).catch(logged);
511
562
  this.next(conversation);
@@ -515,16 +566,25 @@ export class Conversations {
515
566
  const running = conversation.running;
516
567
  const turn = this.begin(conversation);
517
568
  turn.prompted = true;
518
- running.adapter.connection.agent.request('session/prompt', { sessionId: running.sessionId, prompt }).then(() => this.end(conversation, turn, null), async (error) => {
569
+ conversation.prompted = running.sessionId;
570
+ running.adapter.connection.agent.request('session/prompt', { sessionId: running.sessionId, prompt }).then((answer) => {
571
+ const notice = answeredFailure(answer);
572
+ if (notice !== null) {
573
+ this.end(conversation, turn, { failure: notice.limit ? 'limit' : 'error', cause: notice.title }, notice.title);
574
+ }
575
+ else {
576
+ this.end(conversation, turn, answer.stopReason === 'refusal' ? { failure: 'refused', cause: REFUSED } : null);
577
+ }
578
+ }, async (error) => {
519
579
  if (running.adapter.connection.signal.aborted) {
520
- this.end(conversation, turn, { failed: running.killed ? KILLED : await running.adapter.exited });
580
+ this.end(conversation, turn, exitedWith(running, await running.adapter.exited));
521
581
  }
522
582
  else {
523
583
  if (conversation.open === 1 && conversation.running === running) {
524
- running.scope.kill();
584
+ running.adapter.retire();
525
585
  this.detach(conversation, running);
526
586
  }
527
- this.end(conversation, turn, { failed: causeOf(error) });
587
+ this.end(conversation, turn, answeredWith(error));
528
588
  }
529
589
  });
530
590
  }