@amalgm/chat 0.2.9-preview.35320975700 → 0.2.9-preview.35480111675

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 (42) hide show
  1. package/AGENTS.md +7 -6
  2. package/PURPOSE.md +21 -9
  3. package/dist/api/conversations.d.ts +5 -19
  4. package/dist/api/conversations.d.ts.map +1 -1
  5. package/dist/api/conversations.js +3 -23
  6. package/dist/api/conversations.js.map +1 -1
  7. package/dist/api/index.d.ts +1 -1
  8. package/dist/api/index.d.ts.map +1 -1
  9. package/dist/api/index.js.map +1 -1
  10. package/dist/conversations/types.d.ts +2 -0
  11. package/dist/conversations/types.d.ts.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/sessions/chat.d.ts +14 -0
  17. package/dist/sessions/chat.d.ts.map +1 -1
  18. package/dist/sessions/chat.js +223 -112
  19. package/dist/sessions/chat.js.map +1 -1
  20. package/dist/sessions/contracts.d.ts +13 -5
  21. package/dist/sessions/contracts.d.ts.map +1 -1
  22. package/dist/sessions/errors.d.ts +4 -4
  23. package/dist/sessions/errors.d.ts.map +1 -1
  24. package/dist/sessions/errors.js +7 -7
  25. package/dist/sessions/errors.js.map +1 -1
  26. package/dist/sessions/index.d.ts +2 -2
  27. package/dist/sessions/index.d.ts.map +1 -1
  28. package/dist/sessions/index.js +1 -1
  29. package/dist/sessions/index.js.map +1 -1
  30. package/dist/sessions/queue.d.ts +2 -0
  31. package/dist/sessions/queue.d.ts.map +1 -1
  32. package/dist/sessions/queue.js +6 -2
  33. package/dist/sessions/queue.js.map +1 -1
  34. package/docs/contracts/queued-input.md +10 -7
  35. package/host/auth.js +26 -3
  36. package/host/http.js +10 -25
  37. package/host/index.d.ts +6 -0
  38. package/host/index.js +1 -0
  39. package/host/sqlite/index.js +1 -1
  40. package/host/sqlite/rows.js +1 -0
  41. package/package.json +4 -4
  42. package/skills/chat/SKILL.md +1 -4
@@ -74,14 +74,17 @@ export interface ChatOptions<Binding, RuntimeSession> {
74
74
  readonly wait: (milliseconds: number) => Promise<void>;
75
75
  };
76
76
  }
77
- export interface StartSessionOptions {
78
- readonly sessionId?: string;
79
- readonly execution: ExecutionHandle;
77
+ /** Durable conversation attributes, fixed when the conversation is created. */
78
+ export interface ConversationAttributes {
80
79
  readonly title?: string;
81
80
  readonly origin?: string | null;
82
81
  readonly originId?: string | null;
83
82
  readonly metadata?: Readonly<Record<string, unknown>>;
84
83
  }
84
+ export interface StartSessionOptions extends ConversationAttributes {
85
+ readonly sessionId?: string;
86
+ readonly execution: ExecutionHandle;
87
+ }
85
88
  export interface ResumeSessionOptions {
86
89
  readonly sessionId: string;
87
90
  readonly execution: ExecutionHandle;
@@ -91,8 +94,8 @@ export interface ResumeStoredSessionResult<Binding, RuntimeSession> {
91
94
  readonly execution: ExecutionHandle;
92
95
  readonly latestTurn: ConversationTurn | null;
93
96
  }
94
- export interface SendOptions {
95
- readonly execution: ExecutionHandle;
97
+ /** One prompt and the stable identities of the turn it becomes. */
98
+ export interface TurnInput {
96
99
  readonly prompt: PromptInput;
97
100
  /** Stable caller id for the accepted turn; generated when omitted. */
98
101
  readonly clientTurnId?: string;
@@ -100,6 +103,11 @@ export interface SendOptions {
100
103
  readonly userMessageId?: string;
101
104
  readonly assistantMessageId?: string;
102
105
  }
106
+ export interface SendOptions extends TurnInput {
107
+ readonly execution: ExecutionHandle;
108
+ /** Create the conversation with these attributes when it does not exist yet. */
109
+ readonly conversation?: ConversationAttributes;
110
+ }
103
111
  export interface ReconnectOptions {
104
112
  readonly afterSequence?: number;
105
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/sessions/contracts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/sessions/contracts.ts"],"names":[],"mappings":"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"}
@@ -7,10 +7,6 @@ export declare class SessionBusyError extends Error {
7
7
  readonly code = "SESSION_BUSY";
8
8
  constructor(sessionId: string);
9
9
  }
10
- export declare class SessionAgentMismatchError extends Error {
11
- readonly code = "SESSION_AGENT_MISMATCH";
12
- constructor(sessionId: string);
13
- }
14
10
  export declare class TurnStreamError extends Error {
15
11
  readonly code: string;
16
12
  readonly turn: ConversationTurn;
@@ -24,4 +20,8 @@ export declare class StopUnsupportedError extends Error {
24
20
  readonly code = "STOP_UNSUPPORTED";
25
21
  constructor(sessionId: string);
26
22
  }
23
+ export declare class ChatClosedError extends Error {
24
+ readonly code = "CHAT_CLOSED";
25
+ constructor();
26
+ }
27
27
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/sessions/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,uBAAuB;gBAExB,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,kBAAkB;gBAEnB,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,4BAA4B;gBAE7B,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;gBAEpB,IAAI,EAAE,gBAAgB;CAOnC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,6BAA6B;gBAE9B,MAAM,EAAE,MAAM;CAI3B;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,sBAAsB;gBAEvB,SAAS,EAAE,MAAM;CAI9B"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/sessions/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,uBAAuB;gBAExB,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,kBAAkB;gBAEnB,SAAS,EAAE,MAAM;CAI9B;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;gBAEpB,IAAI,EAAE,gBAAgB;CAOnC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,6BAA6B;gBAE9B,MAAM,EAAE,MAAM;CAI3B;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,sBAAsB;gBAEvB,SAAS,EAAE,MAAM;CAI9B;AAGD,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,iBAAiB;;CAM/B"}
@@ -12,13 +12,6 @@ export class SessionBusyError extends Error {
12
12
  this.name = 'SessionBusyError';
13
13
  }
14
14
  }
15
- export class SessionAgentMismatchError extends Error {
16
- code = 'SESSION_AGENT_MISMATCH';
17
- constructor(sessionId) {
18
- super(`Session belongs to a different agent installation: ${sessionId}`);
19
- this.name = 'SessionAgentMismatchError';
20
- }
21
- }
22
15
  export class TurnStreamError extends Error {
23
16
  code;
24
17
  turn;
@@ -44,4 +37,11 @@ export class StopUnsupportedError extends Error {
44
37
  this.name = 'StopUnsupportedError';
45
38
  }
46
39
  }
40
+ export class ChatClosedError extends Error {
41
+ code = 'CHAT_CLOSED';
42
+ constructor() {
43
+ super('Chat is closed');
44
+ this.name = 'ChatClosedError';
45
+ }
46
+ }
47
47
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/sessions/errors.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,GAAG,mBAAmB,CAAC;IAEpC,YAAY,SAAiB;QAC3B,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,GAAG,cAAc,CAAC;IAE/B,YAAY,SAAiB;QAC3B,KAAK,CAAC,uCAAuC,SAAS,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,IAAI,GAAG,wBAAwB,CAAC;IAEzC,YAAY,SAAiB;QAC3B,KAAK,CAAC,sDAAsD,SAAS,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IACb,IAAI,CAAmB;IAEhC,YAAY,IAAsB;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1B,KAAK,CAAC,OAAO,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACvG,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,OAAO,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QACxG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IAC3C,IAAI,GAAG,yBAAyB,CAAC;IAE1C,YAAY,MAAc;QACxB,KAAK,CAAC,oDAAoD,MAAM,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;IAC5C,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,GAAG,kBAAkB,CAAC;IAEnC,YAAY,SAAiB;QAC3B,KAAK,CAAC,6CAA6C,SAAS,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/sessions/errors.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,GAAG,mBAAmB,CAAC;IAEpC,YAAY,SAAiB;QAC3B,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,GAAG,cAAc,CAAC;IAE/B,YAAY,SAAiB;QAC3B,KAAK,CAAC,uCAAuC,SAAS,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IACb,IAAI,CAAmB;IAEhC,YAAY,IAAsB;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1B,KAAK,CAAC,OAAO,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACvG,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,OAAO,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QACxG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IAC3C,IAAI,GAAG,yBAAyB,CAAC;IAE1C,YAAY,MAAc;QACxB,KAAK,CAAC,oDAAoD,MAAM,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;IAC5C,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,GAAG,kBAAkB,CAAC;IAEnC,YAAY,SAAiB;QAC3B,KAAK,CAAC,6CAA6C,SAAS,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAGD,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,GAAG,aAAa,CAAC;IAE9B;QACE,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF"}
@@ -1,5 +1,5 @@
1
- export type { ChatOptions, ChatRuntimePort, TurnControlResult, ReconnectOptions, ResumeSessionOptions, ResumeStoredSessionResult, RuntimePromptRequest, RuntimeTurnControlRequest, RuntimeResumeRequest, RuntimeStartRequest, SendOptions, StartSessionOptions, TurnReplay, } from './chat.js';
1
+ export type { ChatOptions, ChatRuntimePort, ConversationAttributes, TurnControlResult, ReconnectOptions, ResumeSessionOptions, ResumeStoredSessionResult, RuntimePromptRequest, RuntimeTurnControlRequest, RuntimeResumeRequest, RuntimeStartRequest, SendOptions, StartSessionOptions, TurnInput, TurnReplay, } from './chat.js';
2
2
  export { createExternalMessageRunner } from './external-message.js';
3
3
  export type { ExternalMessageAdmission, ExternalMessageExecution, ExternalMessageInput, ExternalMessageRunner, } from './external-message.js';
4
- export { Chat, ChatTurnStream, ChatSession, StopUnsupportedError, SessionAgentMismatchError, SessionBusyError, SessionNotFoundError, SubscriberBackpressureError, TurnStreamError, } from './chat.js';
4
+ export { Chat, ChatTurnStream, ChatSession, StopUnsupportedError, SessionBusyError, SessionNotFoundError, SubscriberBackpressureError, TurnStreamError, } from './chat.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sessions/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,UAAU,GACX,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,IAAI,EACJ,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,yBAAyB,EACzB,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sessions/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,SAAS,EACT,UAAU,GACX,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,IAAI,EACJ,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,WAAW,CAAC"}
@@ -1,3 +1,3 @@
1
1
  export { createExternalMessageRunner } from './external-message.js';
2
- export { Chat, ChatTurnStream, ChatSession, StopUnsupportedError, SessionAgentMismatchError, SessionBusyError, SessionNotFoundError, SubscriberBackpressureError, TurnStreamError, } from './chat.js';
2
+ export { Chat, ChatTurnStream, ChatSession, StopUnsupportedError, SessionBusyError, SessionNotFoundError, SubscriberBackpressureError, TurnStreamError, } from './chat.js';
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sessions/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAOpE,OAAO,EACL,IAAI,EACJ,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,yBAAyB,EACzB,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sessions/index.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAOpE,OAAO,EACL,IAAI,EACJ,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,WAAW,CAAC"}
@@ -2,5 +2,7 @@
2
2
  export declare class ConversationQueue {
3
3
  #private;
4
4
  run(id: string, next: () => Promise<boolean>, onFatal: (error: Error) => void): void;
5
+ /** Resolves once every drain in flight has returned; it starts nothing. */
6
+ settled(): Promise<void>;
5
7
  }
6
8
  //# sourceMappingURL=queue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/sessions/queue.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,qBAAa,iBAAiB;;IAG5B,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;CAerF"}
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/sessions/queue.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,qBAAa,iBAAiB;;IAG5B,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAgBpF,2EAA2E;IAC3E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAGzB"}
@@ -8,9 +8,9 @@ export class ConversationQueue {
8
8
  active.requested = true;
9
9
  return;
10
10
  }
11
- const state = { requested: true };
11
+ const state = { requested: true, done: Promise.resolve() };
12
12
  this.#drains.set(id, state);
13
- void (async () => {
13
+ state.done = (async () => {
14
14
  try {
15
15
  while (true) {
16
16
  state.requested = false;
@@ -25,5 +25,9 @@ export class ConversationQueue {
25
25
  }
26
26
  })().catch(error => onFatal(error instanceof Error ? error : new Error(String(error))));
27
27
  }
28
+ /** Resolves once every drain in flight has returned; it starts nothing. */
29
+ settled() {
30
+ return Promise.all([...this.#drains.values()].map(state => state.done)).then(() => undefined);
31
+ }
28
32
  }
29
33
  //# sourceMappingURL=queue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/sessions/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,oFAAoF;AACpF,MAAM,OAAO,iBAAiB;IACnB,OAAO,GAAG,IAAI,GAAG,EAAkC,CAAC;IAE7D,GAAG,CAAC,EAAU,EAAE,IAA4B,EAAE,OAA+B;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,MAAM,EAAE,CAAC;YAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;YAAC,OAAO;QAAC,CAAC;QAChD,MAAM,KAAK,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC5B,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,OAAO,IAAI,EAAE,CAAC;oBACZ,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;oBACxB,IAAI,MAAM,YAAY,CAAC,IAAI,CAAC;wBAAE,SAAS;oBACvC,IAAI,CAAC,KAAK,CAAC,SAAS;wBAAE,OAAO;gBAC/B,CAAC;YACH,CAAC;oBAAS,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;QACxC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1F,CAAC;CACF"}
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/sessions/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,oFAAoF;AACpF,MAAM,OAAO,iBAAiB;IACnB,OAAO,GAAG,IAAI,GAAG,EAAuD,CAAC;IAElF,GAAG,CAAC,EAAU,EAAE,IAA4B,EAAE,OAA+B;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,MAAM,EAAE,CAAC;YAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;YAAC,OAAO;QAAC,CAAC;QAChD,MAAM,KAAK,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE;YACvB,IAAI,CAAC;gBACH,OAAO,IAAI,EAAE,CAAC;oBACZ,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;oBACxB,IAAI,MAAM,YAAY,CAAC,IAAI,CAAC;wBAAE,SAAS;oBACvC,IAAI,CAAC,KAAK,CAAC,SAAS;wBAAE,OAAO;gBAC/B,CAAC;YACH,CAAC;oBAAS,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;QACxC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1F,CAAC;IAED,2EAA2E;IAC3E,OAAO;QACL,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAChG,CAAC;CACF"}
@@ -19,7 +19,7 @@ progress. All surfaces use one durable queue owned by Chat.
19
19
 
20
20
  ```text
21
21
  prepared prompt → queued → running → completed | failed | cancelled | interrupted
22
- └───────────→ cancelled (Delete) | failed (recovery); never invoked
22
+ └───────────→ cancelled (Delete or Stop) | failed (recovery); never invoked
23
23
  ```
24
24
 
25
25
  `startedAt` is null for all never-invoked turns, including deleted input and failed recovery. Deletion retains an
@@ -40,11 +40,11 @@ by adapter name. The existing durable queue priority encodes the steering decisi
40
40
  | Prepare | Resolve one immutable execution handle before Send. |
41
41
  | Start | Create or rejoin a durable conversation and prepare its provider session. |
42
42
  | Resume | Attach a saved conversation with exact execution/checkpoint facts. |
43
- | Send / enqueue | Commit one prompt, return acceptance, request the conversation drain. |
43
+ | Send | Commit one prompt, return acceptance, request the conversation drain; attaches or creates the conversation first when it is not live. |
44
44
  | Inspect queue | Read queued turns and the current running identity; no provider launch. |
45
45
  | Delete pending | Cancel only a still-queued identity; a stale Delete is a no-op. |
46
46
  | Steer / UI Interrupt | Prioritize one queued identity; request yield after the current provider step. |
47
- | Stop | Immediately request cancellation of the expected active identity. |
47
+ | Stop | Cancel the named queued turn or stop its running provider, decided under admission. |
48
48
  | Subscribe / reconnect | Replay after a durable sequence cursor, then follow the same turn. |
49
49
  | Disconnect | Detach a subscriber while provider and queue continue. |
50
50
  | Recover | Interrupt uncertain running work, restore queued exact bindings, drain. |
@@ -59,17 +59,20 @@ and controls use JSON on the same Chat HTTP surface, not synthetic ACP events.
59
59
 
60
60
  `session.send({ execution, prompt, clientTurnId })` always admits into the durable
61
61
  queue. Repeating the same id and exact input rejoins it; conflicting reuse raises
62
- `TURN_ID_CONFLICT`. The browser client offers `enqueue` for JSON acceptance and
63
- `send` for admission followed by SSE. Both use `POST /chat/conversations/:id/turns`.
62
+ `TURN_ID_CONFLICT`. Over HTTP, `client.send(id, { execution, prompt, clientTurnId,
63
+ conversation? })` is the only admission request: one `POST /chat/conversations/:id/turns`
64
+ answers `202 { turn }`, and `client.reconnect(id, turnId)` observes the output.
65
+ `conversation` carries the durable attributes used when the conversation does not
66
+ exist yet; a saved conversation is attached by the same request.
64
67
 
65
68
  - `client.queue(id)` → `{ queued, active }`.
66
69
  - `client.cancel(id, queuedTurnId)` → pending deletion result.
67
70
  - `client.steer(id, queuedTurnId, activeTurnId)` → cooperative request result.
68
- - `client.stop(id, activeTurnId)` → immediate Stop result.
71
+ - `client.stop(id, turnId)` → immediate Stop result.
69
72
  - `client.reconnect(id, turnId, { afterSequence, signal })` → durable updates.
70
73
 
71
74
  Control results use `{ accepted, turnId }`. Acceptance records the requested transition, not a cancelled execution outcome. Observe the turn's
72
- terminal record to learn when final work actually settled. A stale expected active
75
+ terminal record to learn when final work actually settled. An already-finished named
73
76
  id returns `accepted: false` for Stop and never stops another turn. Steering still promotes a queued message if the expected turn has ended; it cannot yield a different successor.
74
77
 
75
78
  ## Provider boundary
package/host/auth.js CHANGED
@@ -91,15 +91,18 @@ function findStableJsonIdentity(value, depth = 0) {
91
91
  return null;
92
92
  }
93
93
 
94
- function readJsonIdentity(file) {
94
+ function readJsonFile(file) {
95
95
  try {
96
- const raw = fs.readFileSync(file, 'utf8');
97
- return findStableJsonIdentity(JSON.parse(raw));
96
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
98
97
  } catch {
99
98
  return null;
100
99
  }
101
100
  }
102
101
 
102
+ function readJsonIdentity(file) {
103
+ return findStableJsonIdentity(readJsonFile(file));
104
+ }
105
+
103
106
  function providerAuthIdentity(harness) {
104
107
  if (harness === 'codex') {
105
108
  return readJsonIdentity(path.join(os.homedir(), '.codex', 'auth.json')) || 'codex:provider-default';
@@ -112,6 +115,26 @@ function providerAuthIdentity(harness) {
112
115
  return `${harness || 'provider'}:provider-default`;
113
116
  }
114
117
 
118
+ function hasLoginRecord(value, keys) {
119
+ return Boolean(value) && typeof value === 'object'
120
+ && keys.some(key => typeof value[key] === 'object' && value[key] !== null);
121
+ }
122
+
123
+ /**
124
+ * Whether this machine holds the provider login a `provider_auth` execution
125
+ * relies on: the same records `syncClaudeProviderAuth` copies into the agent's
126
+ * runtime home. Presence only, never contents, so this means "configured", not
127
+ * "verified". Harnesses whose login Chat does not read report no fact (`null`).
128
+ * An API key in the environment is BYOK material and never counts as a login.
129
+ */
130
+ export function providerLoginConfigured(harness, home = os.homedir()) {
131
+ if (harness !== 'claude_code') return null;
132
+ const claudeDir = path.join(home, '.claude');
133
+ return [path.join(home, '.claude.json'), path.join(claudeDir, '.claude.json')]
134
+ .some(file => hasLoginRecord(readJsonFile(file), ['oauthAccount', 'claudeAiOauth']))
135
+ || hasLoginRecord(readJsonFile(path.join(claudeDir, '.credentials.json')), ['claudeAiOauth']);
136
+ }
137
+
115
138
  function runtimeHome({ runtimeHomeRoot, harness, agentConfigId, method, authority }) {
116
139
  const harnessHome = path.join(runtimeHomeRoot, safePathSegment(harness));
117
140
  return path.join(
package/host/http.js CHANGED
@@ -9,6 +9,11 @@ function object(value) {
9
9
  return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
10
10
  }
11
11
 
12
+ function conversationAttributes(value) {
13
+ const attributes = object(value);
14
+ return { title: attributes.title, origin: attributes.origin, originId: attributes.originId, metadata: object(attributes.metadata) };
15
+ }
16
+
12
17
  async function readJson(request, limit) {
13
18
  const chunks = [];
14
19
  let size = 0;
@@ -31,12 +36,13 @@ async function readJson(request, limit) {
31
36
  function statusFor(error) {
32
37
  if (error?.code === 'SESSION_NOT_FOUND') return 404;
33
38
  if (['STOP_UNSUPPORTED', 'STEER_UNSUPPORTED'].includes(error?.code)) return 501;
34
- if (['SESSION_ALREADY_EXISTS', 'SESSION_BUSY', 'SESSION_AGENT_MISMATCH',
39
+ if (['SESSION_ALREADY_EXISTS', 'SESSION_BUSY',
35
40
  'EXECUTION_REVISION_MISMATCH', 'TURN_ID_CONFLICT', 'TURN_NOT_QUEUED',
36
41
  'CONVERSATION_BUSY', 'CONVERSATION_ARCHIVED'].includes(error?.code)) return 409;
37
42
  if (error instanceof SyntaxError || String(error?.code || '').startsWith('INVALID_')
38
43
  || error?.code === 'EXECUTION_NOT_PREPARED') return 400;
39
44
  if (error?.code === 'REQUEST_TOO_LARGE') return 413;
45
+ if (error?.code === 'CHAT_CLOSED') return 503;
40
46
  return 500;
41
47
  }
42
48
 
@@ -181,33 +187,13 @@ export function createChatHttpHandler(options) {
181
187
  sendJson(response, 200, { conversations: await chat.listConversations(listOptions(url)) });
182
188
  return true;
183
189
  }
184
- if (method === 'POST' && path.length === 1) {
185
- const body = await readJson(request, bodyLimit);
186
- const session = await chat.startSession({
187
- sessionId: body.conversationId,
188
- execution: body.execution,
189
- title: body.title,
190
- origin: body.origin,
191
- originId: body.originId,
192
- metadata: object(body.metadata),
193
- });
194
- sendJson(response, 201, { conversation: await session.inspect() });
195
- return true;
196
- }
197
190
  const conversationId = path[1];
198
191
  if (!conversationId) throw Object.assign(new Error('conversation id is required'), { code: 'INVALID_REQUEST' });
199
- if (method === 'POST' && path[2] === 'resume' && path.length === 3) {
200
- const body = await readJson(request, bodyLimit);
201
- const result = body.execution
202
- ? { session: await chat.resumeSession({ sessionId: conversationId, execution: body.execution }) }
203
- : await chat.resumeStoredSession(conversationId);
204
- sendJson(response, 200, { conversation: await result.session.inspect(), execution: result.execution });
205
- return true;
206
- }
207
192
  if (method === 'GET' && path[2] === 'turns' && path.length === 3) {
208
193
  sendJson(response, 200, { queued: await chat.queuedTurns(conversationId), active: await chat.activeTurn(conversationId) });
209
194
  return true;
210
195
  }
196
+ // The one hot path: admission answers immediately; output is observed through /events.
211
197
  if (method === 'POST' && path[2] === 'turns' && path.length === 3) {
212
198
  const body = await readJson(request, bodyLimit);
213
199
  const stream = await chat.send(conversationId, {
@@ -216,10 +202,9 @@ export function createChatHttpHandler(options) {
216
202
  clientTurnId: body.clientTurnId,
217
203
  userMessageId: body.userMessageId,
218
204
  assistantMessageId: body.assistantMessageId,
205
+ ...(body.conversation == null ? {} : { conversation: conversationAttributes(body.conversation) }),
219
206
  });
220
- if (String(request.headers.accept || '').includes('application/json')) {
221
- sendJson(response, 202, { turn: (await chat.replayTurn(conversationId, stream.turnId)).turn });
222
- } else await streamTurn(response, stream, stream.completion);
207
+ sendJson(response, 202, { turn: (await chat.replayTurn(conversationId, stream.turnId)).turn });
223
208
  return true;
224
209
  }
225
210
  if (path[2] === 'turns' && path[3] && path.length === 5 && method === 'POST') {
package/host/index.d.ts CHANGED
@@ -122,6 +122,12 @@ export class InvalidPreparedAuthError extends Error {
122
122
  readonly code: 'INVALID_PREPARED_AUTH';
123
123
  }
124
124
 
125
+ /**
126
+ * Whether `home` holds the provider login a subscription execution relies on
127
+ * (presence only); `null` for harnesses whose login Chat does not read.
128
+ */
129
+ export function providerLoginConfigured(harness: string, home?: string): boolean | null;
130
+
125
131
  export {
126
132
  SqliteConversationStore,
127
133
  SqliteConversationStoreError,
package/host/index.js CHANGED
@@ -60,6 +60,7 @@ export async function createChatHost(options) {
60
60
  export { NativeChatRuntime } from './native-runtime.js';
61
61
  export { createChatHttpHandler } from './http.js';
62
62
  export { NativeExecutionPreparer, InvalidPreparedAuthError } from './native-contract.js';
63
+ export { providerLoginConfigured } from './auth.js';
63
64
  export {
64
65
  SqliteConversationStore,
65
66
  SqliteConversationStoreError,
@@ -398,7 +398,7 @@ export class SqliteConversationStore {
398
398
  async listMessages(scope, conversationId) {
399
399
  const conversation = this.#requireConversation(scope, conversationId);
400
400
  return this.database.prepare(`
401
- SELECT m.*, t.error_json FROM messages m JOIN turns t ON t.id = m.turn_id
401
+ SELECT m.*, t.status AS turn_status, t.error_json FROM messages m JOIN turns t ON t.id = m.turn_id
402
402
  WHERE m.conversation_id = ? AND NOT (t.started_at IS NULL AND t.status = 'cancelled')
403
403
  ORDER BY CASE WHEN t.status = 'queued' THEN 1 ELSE 0 END, COALESCE(t.started_at, t.created_at), t.rowid, m.role DESC
404
404
  `).all(conversation.id).map(messageFromRow);
@@ -85,6 +85,7 @@ export function messageFromRow(row) {
85
85
  contentPlain: row.content_plain,
86
86
  modelId: row.model_id,
87
87
  error: row.role === 'assistant' && row.error_json ? Object.freeze(parseJson(row.error_json, {})) : null,
88
+ ...(row.role === 'assistant' ? { status: row.turn_status } : {}),
88
89
  createdAt: row.created_at,
89
90
  updatedAt: row.updated_at,
90
91
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amalgm/chat",
3
- "version": "0.2.9-preview.35320975700",
3
+ "version": "0.2.9-preview.35480111675",
4
4
  "description": "A provider-agnostic agent chat SDK with ACP content, prepared execution, normalized streams, and usage.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -119,11 +119,11 @@
119
119
  "allowScripts": {
120
120
  "better-sqlite3@12.11.1": true
121
121
  },
122
- "gitHead": "1df01806919ffa38e812988160bbc907c0dd9e59",
122
+ "gitHead": "399cea2ea226d47877e6686902a5321dea9645bd",
123
123
  "amalgmSource": {
124
124
  "repository": "amalgm-inc/amalgm-chat",
125
125
  "branch": "preview",
126
- "commit": "1df01806919ffa38e812988160bbc907c0dd9e59",
127
- "occurrence": "35320975700"
126
+ "commit": "399cea2ea226d47877e6686902a5321dea9645bd",
127
+ "occurrence": "35480111675"
128
128
  }
129
129
  }
@@ -246,10 +246,8 @@ Routes are mounted under `/chat` by default (configurable via
246
246
  | --- | --- |
247
247
  | `POST /chat/executions` | prepare an execution (`{ id, execution }` → handle) |
248
248
  | `GET /chat/conversations` | list conversations |
249
- | `POST /chat/conversations` | start a session |
250
249
  | `GET /chat/conversations/:id` | conversation record, messages, latest turn |
251
- | `POST /chat/conversations/:id/resume` | resume (with or without a new handle) |
252
- | `POST /chat/conversations/:id/turns` | admit a prompt; SSE, or JSON 202 with `Accept: application/json` |
250
+ | `POST /chat/conversations/:id/turns` | admit a prompt (`202 { turn }`); attaches a saved conversation, or creates it from `conversation` attributes |
253
251
  | `GET /chat/conversations/:id/turns` | queued turns and active identity |
254
252
  | `POST /chat/conversations/:id/turns/:turnId/cancel` | remove pending input |
255
253
  | `POST /chat/conversations/:id/turns/:turnId/steer` | prioritize pending input, yield after current step (`expectedTurnId`) |
@@ -277,7 +275,6 @@ Chat fails loudly with typed errors; every error object carries a stable
277
275
  | `UNSUPPORTED_EXECUTION_INPUT` | the agent cannot apply part of the contract |
278
276
  | `SESSION_NOT_FOUND` / `SESSION_ALREADY_EXISTS` | session id problems |
279
277
  | `SESSION_BUSY` | closing or archiving requires an idle conversation; Send queues |
280
- | `SESSION_AGENT_MISMATCH` | the new handle targets a different agent installation |
281
278
  | `SUBSCRIBER_BACKPRESSURE` | one slow subscriber overflowed its buffer and was disconnected (the turn keeps running) |
282
279
  | `STOP_UNSUPPORTED` | the adapter cannot stop this turn |
283
280