@agentshouse/mdruntime 0.1.0-ce531b51ff088 → 0.1.0-cec6690d5712e

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 (168) hide show
  1. package/AGENTS.md +121 -29
  2. package/README.md +21 -11
  3. package/dist/adapter.d.ts +65 -28
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js +1 -9
  6. package/dist/attached-model.d.ts +11 -0
  7. package/dist/attached-model.d.ts.map +1 -0
  8. package/dist/attached-model.js +47 -0
  9. package/dist/attempt.d.ts +16 -0
  10. package/dist/attempt.d.ts.map +1 -0
  11. package/dist/attempt.js +57 -0
  12. package/dist/bootstrap.d.ts +20 -6
  13. package/dist/bootstrap.d.ts.map +1 -1
  14. package/dist/bootstrap.js +89 -35
  15. package/dist/change-set.d.ts.map +1 -1
  16. package/dist/change-set.js +13 -7
  17. package/dist/change.d.ts +4 -0
  18. package/dist/change.d.ts.map +1 -1
  19. package/dist/chat/acts.d.ts +34 -0
  20. package/dist/chat/acts.d.ts.map +1 -0
  21. package/dist/chat/acts.js +36 -0
  22. package/dist/chat/context.d.ts +3 -0
  23. package/dist/chat/context.d.ts.map +1 -0
  24. package/dist/chat/context.js +10 -0
  25. package/dist/chat/input.d.ts +9 -0
  26. package/dist/chat/input.d.ts.map +1 -0
  27. package/dist/chat/input.js +99 -0
  28. package/dist/chat/kit.d.ts +60 -0
  29. package/dist/chat/kit.d.ts.map +1 -0
  30. package/dist/chat/kit.js +123 -0
  31. package/dist/chat/lasting.d.ts +6 -0
  32. package/dist/chat/lasting.d.ts.map +1 -0
  33. package/dist/chat/lasting.js +19 -0
  34. package/dist/chat/list.d.ts +20 -0
  35. package/dist/chat/list.d.ts.map +1 -0
  36. package/dist/chat/list.js +59 -0
  37. package/dist/chat/markdown.d.ts +19 -0
  38. package/dist/chat/markdown.d.ts.map +1 -0
  39. package/dist/chat/markdown.js +187 -0
  40. package/dist/chat/message.d.ts +6 -0
  41. package/dist/chat/message.d.ts.map +1 -0
  42. package/dist/chat/message.js +192 -0
  43. package/dist/chat/messages.d.ts +21 -0
  44. package/dist/chat/messages.d.ts.map +1 -0
  45. package/dist/chat/messages.js +151 -0
  46. package/dist/chat/name.d.ts +6 -0
  47. package/dist/chat/name.d.ts.map +1 -0
  48. package/dist/chat/name.js +37 -0
  49. package/dist/chat/opened.d.ts +11 -0
  50. package/dist/chat/opened.d.ts.map +1 -0
  51. package/dist/chat/opened.js +17 -0
  52. package/dist/chat/overlay.d.ts +31 -0
  53. package/dist/chat/overlay.d.ts.map +1 -0
  54. package/dist/chat/overlay.js +97 -0
  55. package/dist/chat/parts.d.ts +57 -0
  56. package/dist/chat/parts.d.ts.map +1 -0
  57. package/dist/chat/parts.js +119 -0
  58. package/dist/chat/process.d.ts +20 -0
  59. package/dist/chat/process.d.ts.map +1 -0
  60. package/dist/chat/process.js +32 -0
  61. package/dist/chat/provider.d.ts +63 -0
  62. package/dist/chat/provider.d.ts.map +1 -0
  63. package/dist/chat/provider.js +645 -0
  64. package/dist/chat/question.d.ts +9 -0
  65. package/dist/chat/question.d.ts.map +1 -0
  66. package/dist/chat/question.js +80 -0
  67. package/dist/chat/questions.d.ts +31 -0
  68. package/dist/chat/questions.d.ts.map +1 -0
  69. package/dist/chat/questions.js +111 -0
  70. package/dist/chat/read.d.ts +5 -0
  71. package/dist/chat/read.d.ts.map +1 -0
  72. package/dist/chat/read.js +13 -0
  73. package/dist/chat/ready.d.ts +33 -0
  74. package/dist/chat/ready.d.ts.map +1 -0
  75. package/dist/chat/ready.js +91 -0
  76. package/dist/chat/style.d.ts +4 -0
  77. package/dist/chat/style.d.ts.map +1 -0
  78. package/dist/chat/style.js +302 -0
  79. package/dist/chat.d.ts +14 -0
  80. package/dist/chat.d.ts.map +1 -0
  81. package/dist/chat.js +8 -0
  82. package/dist/client.d.ts +12 -7
  83. package/dist/client.d.ts.map +1 -1
  84. package/dist/client.js +64 -25
  85. package/dist/collection.d.ts +6 -11
  86. package/dist/collection.d.ts.map +1 -1
  87. package/dist/collection.js +56 -19
  88. package/dist/connection.d.ts +21 -16
  89. package/dist/connection.d.ts.map +1 -1
  90. package/dist/connection.js +713 -587
  91. package/dist/conversation.d.ts +28 -8
  92. package/dist/conversation.d.ts.map +1 -1
  93. package/dist/conversation.js +222 -81
  94. package/dist/expectation.d.ts +21 -0
  95. package/dist/expectation.d.ts.map +1 -0
  96. package/dist/expectation.js +70 -0
  97. package/dist/failure.d.ts +13 -0
  98. package/dist/failure.d.ts.map +1 -0
  99. package/dist/failure.js +19 -0
  100. package/dist/host.d.ts +8 -1
  101. package/dist/host.d.ts.map +1 -1
  102. package/dist/host.js +39 -39
  103. package/dist/identity.d.ts +2 -0
  104. package/dist/identity.d.ts.map +1 -1
  105. package/dist/identity.js +10 -1
  106. package/dist/index.d.ts +7 -4
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +2 -0
  109. package/dist/memory.d.ts +12 -5
  110. package/dist/memory.d.ts.map +1 -1
  111. package/dist/memory.js +108 -36
  112. package/dist/model.d.ts +13 -12
  113. package/dist/model.d.ts.map +1 -1
  114. package/dist/model.js +6 -3
  115. package/dist/observation.d.ts +2 -0
  116. package/dist/observation.d.ts.map +1 -1
  117. package/dist/observation.js +24 -14
  118. package/dist/open.d.ts +2 -0
  119. package/dist/open.d.ts.map +1 -0
  120. package/dist/open.js +1 -0
  121. package/dist/outcome.d.ts +22 -3
  122. package/dist/outcome.d.ts.map +1 -1
  123. package/dist/outcome.js +35 -1
  124. package/dist/overlay.d.ts +1 -1
  125. package/dist/overlay.d.ts.map +1 -1
  126. package/dist/overlay.js +19 -15
  127. package/dist/paths.d.ts +0 -1
  128. package/dist/paths.d.ts.map +1 -1
  129. package/dist/paths.js +0 -16
  130. package/dist/query.d.ts +10 -3
  131. package/dist/query.d.ts.map +1 -1
  132. package/dist/query.js +78 -36
  133. package/dist/reach.d.ts +40 -0
  134. package/dist/reach.d.ts.map +1 -0
  135. package/dist/reach.js +272 -0
  136. package/dist/react.d.ts +41 -0
  137. package/dist/react.d.ts.map +1 -0
  138. package/dist/react.js +64 -0
  139. package/dist/read-side.d.ts +4 -0
  140. package/dist/read-side.d.ts.map +1 -1
  141. package/dist/read-side.js +116 -54
  142. package/dist/refresh.d.ts +12 -1
  143. package/dist/refresh.d.ts.map +1 -1
  144. package/dist/refresh.js +35 -22
  145. package/dist/replica.d.ts +6 -6
  146. package/dist/replica.d.ts.map +1 -1
  147. package/dist/replica.js +53 -39
  148. package/dist/room-draft.d.ts +11 -8
  149. package/dist/room-draft.d.ts.map +1 -1
  150. package/dist/room-draft.js +19 -26
  151. package/dist/rows.d.ts +4 -1
  152. package/dist/rows.d.ts.map +1 -1
  153. package/dist/rows.js +82 -39
  154. package/dist/save.d.ts +4 -3
  155. package/dist/save.d.ts.map +1 -1
  156. package/dist/save.js +127 -68
  157. package/dist/search.d.ts +3 -2
  158. package/dist/search.d.ts.map +1 -1
  159. package/dist/status.d.ts +2 -2
  160. package/dist/status.d.ts.map +1 -1
  161. package/dist/status.js +0 -8
  162. package/dist/store.d.ts +26 -2
  163. package/dist/store.d.ts.map +1 -1
  164. package/dist/store.js +206 -90
  165. package/dist/wire.d.ts +56 -19
  166. package/dist/wire.d.ts.map +1 -1
  167. package/dist/wire.js +63 -61
  168. package/package.json +23 -3
@@ -0,0 +1,47 @@
1
+ import { verify } from '@agentshouse/mdmodel';
2
+ import { MD_MODEL } from './collection.js';
3
+ import { sameModel } from './model.js';
4
+ const EMPTY_SCHEMA = { verdict: 'accept', model: { types: {} } };
5
+ export function attachedModel(answer, previous) {
6
+ if (answer.kind === 'model-unavailable') {
7
+ return { state: { status: 'unavailable', reason: answer.reason }, refused: null };
8
+ }
9
+ if (previous.status !== 'unavailable' &&
10
+ sameModel(previous.snapshot, answer.snapshot) &&
11
+ previous.snapshot.schema !== answer.snapshot.schema) {
12
+ return {
13
+ state: {
14
+ status: 'unavailable',
15
+ reason: 'invalid',
16
+ schema: answer.snapshot.schema,
17
+ revision: answer.snapshot.revision,
18
+ },
19
+ refused: null,
20
+ };
21
+ }
22
+ const verified = answer.snapshot.schema === null ? EMPTY_SCHEMA : verify(answer.snapshot.schema);
23
+ if (verified.verdict === 'refuse') {
24
+ return {
25
+ state: {
26
+ status: 'unavailable',
27
+ reason: 'invalid',
28
+ schema: answer.snapshot.schema,
29
+ revision: answer.snapshot.revision,
30
+ },
31
+ refused: {
32
+ identity: answer.snapshot.identity,
33
+ rule: verified.rule,
34
+ ...(verified.location === undefined ? {} : { location: verified.location }),
35
+ },
36
+ };
37
+ }
38
+ return {
39
+ state: {
40
+ status: 'current',
41
+ snapshot: structuredClone(answer.snapshot),
42
+ verifiedWith: MD_MODEL,
43
+ types: verified.model.types,
44
+ },
45
+ refused: null,
46
+ };
47
+ }
@@ -0,0 +1,16 @@
1
+ export type Answered = 'accepted' | 'refused' | 'unanswered' | 'offline';
2
+ export type Identities = {
3
+ of(intent: string): string;
4
+ settle(answered: Answered): void;
5
+ };
6
+ export declare function identities(mint?: () => string): Identities;
7
+ export declare function intentOf(name: string, about: unknown): string;
8
+ export type Attempt = {
9
+ identity(intent: string): string;
10
+ settle(answered: Answered, drop: (act: number) => void): void;
11
+ };
12
+ export type Attempts = {
13
+ begin(act: number): Attempt;
14
+ };
15
+ export declare function attempts(mint?: () => string): Attempts;
16
+ //# sourceMappingURL=attempt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attempt.d.ts","sourceRoot":"","sources":["../src/attempt.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;AAEzE,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAM,MAAoC,GAAG,UAAU,CAmBvF;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAE7D;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B,CAAC;AAEF,wBAAgB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,MAAM,GAAG,QAAQ,CAyBtD"}
@@ -0,0 +1,57 @@
1
+ import { changeBatchIdentity } from './identity.js';
2
+ export function identities(mint = () => changeBatchIdentity()) {
3
+ const kept = new Map();
4
+ let used = new Map();
5
+ return {
6
+ of(intent) {
7
+ const one = used.get(intent) ?? kept.get(intent) ?? mint();
8
+ used.set(intent, one);
9
+ return one;
10
+ },
11
+ settle(answered) {
12
+ if (answered !== 'offline') {
13
+ for (const [intent, one] of used) {
14
+ if (answered === 'unanswered')
15
+ kept.set(intent, one);
16
+ else
17
+ kept.delete(intent);
18
+ }
19
+ }
20
+ used = new Map();
21
+ },
22
+ };
23
+ }
24
+ export function intentOf(name, about) {
25
+ return `${name}\u0000${JSON.stringify(about)}`;
26
+ }
27
+ export function attempts(mint) {
28
+ const numbers = identities(mint);
29
+ const waiting = new Map();
30
+ return {
31
+ begin(act) {
32
+ const intents = [];
33
+ return {
34
+ identity(intent) {
35
+ intents.push(intent);
36
+ return numbers.of(intent);
37
+ },
38
+ settle(answered, drop) {
39
+ numbers.settle(answered);
40
+ if (answered === 'refused' || answered === 'offline')
41
+ drop(act);
42
+ if (answered === 'offline')
43
+ return;
44
+ for (const intent of intents) {
45
+ const earlier = waiting.get(intent);
46
+ if (earlier !== undefined && earlier !== act)
47
+ drop(earlier);
48
+ if (answered === 'unanswered')
49
+ waiting.set(intent, act);
50
+ else
51
+ waiting.delete(intent);
52
+ }
53
+ },
54
+ };
55
+ },
56
+ };
57
+ }
@@ -1,10 +1,24 @@
1
1
  import type { ModelState } from './model.js';
2
- import type { Adapter, AdapterFailure, Authorization, DiscoveredRoom } from './adapter.js';
3
- import { type Staged } from './replica.js';
4
- import { type Unconfirmed } from './transfer.js';
5
- export type BootstrapOutcome = Staged | Unconfirmed | AdapterFailure;
6
- export declare function bootstrapRoom(adapter: Adapter, authorization: Authorization, room: DiscoveredRoom, models: {
2
+ import type { Adapter, AdapterFailure, Authorization, DiscoveredRoom, RetryableRefusal, RoomModels } from './adapter.js';
3
+ import { type ConfirmedLayer } from './replica.js';
4
+ import type { StagedLayer, TransferRecord } from './store.js';
5
+ import { type Refused, type Unconfirmed } from './transfer.js';
6
+ export type Bootstrapped = {
7
+ kind: 'staged';
8
+ confirmed: ConfirmedLayer;
9
+ stored: StagedLayer;
10
+ };
11
+ export type BootstrapOutcome = Bootstrapped | Refused | Unconfirmed | RetryableRefusal | AdapterFailure;
12
+ export type HeldModels = {
7
13
  collection: ModelState;
8
14
  selection: ModelState;
9
- }, continuing: () => boolean): Promise<BootstrapOutcome>;
15
+ };
16
+ export type Remodel = (models: RoomModels | undefined, held: HeldModels) => HeldModels;
17
+ export type Staging = {
18
+ held(locator: string): TransferRecord | null;
19
+ staged(record: TransferRecord): Promise<StagedLayer>;
20
+ stage(record: TransferRecord, page: StagedLayer): Promise<boolean>;
21
+ abandon(locator: string): Promise<void>;
22
+ };
23
+ export declare function bootstrapRoom(adapter: Adapter, authorization: Authorization, room: DiscoveredRoom, held: HeldModels, remodel: Remodel, continuing: () => boolean, staging: Staging): Promise<BootstrapOutcome>;
10
24
  //# sourceMappingURL=bootstrap.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,aAAa,EACb,cAAc,EAGf,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC;AAErE,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,UAAU,CAAA;CAAE,EACzD,UAAU,EAAE,MAAM,OAAO,GACxB,OAAO,CAAC,gBAAgB,CAAC,CA+C3B"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,aAAa,EAEb,cAAc,EAEd,gBAAgB,EAChB,UAAU,EACX,MAAM,cAAc,CAAC;AAItB,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAiB,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAe,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAE9F,MAAM,MAAM,gBAAgB,GACxB,YAAY,GACZ,OAAO,GACP,WAAW,GACX,gBAAgB,GAChB,cAAc,CAAC;AAEnB,MAAM,MAAM,UAAU,GAAG;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,UAAU,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,EAAE,IAAI,EAAE,UAAU,KAAK,UAAU,CAAC;AAEvF,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IAC7C,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrD,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC,CAAC;AAgCF,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,OAAO,EACzB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,gBAAgB,CAAC,CA4E3B"}
package/dist/bootstrap.js CHANGED
@@ -1,56 +1,110 @@
1
1
  import { declaredAttachments } from './attachment.js';
2
+ import { transferIdentity } from './identity.js';
3
+ import { advancement } from './refresh.js';
2
4
  import { readStaged } from './replica.js';
3
5
  import { unconfirmed } from './transfer.js';
4
- export async function bootstrapRoom(adapter, authorization, room, models, continuing) {
5
- const first = await adapter.bootstrap(authorization, {
6
- locator: room.locator,
7
- selection: room.replica.selection,
8
- });
9
- if (first.kind !== 'bootstrap')
10
- return first;
11
- const roomVersion = first.roomVersion;
12
- const documents = { ...first.documents };
13
- const revisions = { ...first.revisions };
14
- const changes = { ...first.changes };
15
- const binaryTargets = new Set(first.binaryTargets);
16
- const attachments = [first.attachments ?? []];
17
- let pageToken = first.pageToken;
18
- while (pageToken !== undefined) {
6
+ const RESUMABLE = new Set([
7
+ 'transport-uncertainty',
8
+ 'retryable-refusal',
9
+ 'unconfirmed',
10
+ ]);
11
+ function pageLayer(page) {
12
+ return {
13
+ documents: page.documents,
14
+ revisions: page.revisions,
15
+ changes: page.changes,
16
+ written: Object.fromEntries(Object.keys(page.documents).map((path) => [path, page.roomVersion])),
17
+ binaryTargets: page.binaryTargets,
18
+ };
19
+ }
20
+ async function heldTransfer(staging, room) {
21
+ const record = staging.held(room.locator);
22
+ if (record === null)
23
+ return null;
24
+ if (record.selection === room.replica.selection) {
25
+ return { record, layer: await staging.staged(record) };
26
+ }
27
+ await staging.abandon(room.locator);
28
+ return null;
29
+ }
30
+ export async function bootstrapRoom(adapter, authorization, room, held, remodel, continuing, staging) {
31
+ const locator = room.locator;
32
+ const selection = room.replica.selection;
33
+ const kept = await heldTransfer(staging, room);
34
+ const documents = { ...kept?.layer.documents };
35
+ const revisions = { ...kept?.layer.revisions };
36
+ const changes = { ...kept?.layer.changes };
37
+ const written = { ...kept?.layer.written };
38
+ const binaryTargets = new Set(kept?.layer.binaryTargets);
39
+ let transfer = kept?.record ?? null;
40
+ while (transfer === null || transfer.pageToken !== null) {
19
41
  if (!continuing())
20
42
  return unconfirmed;
21
43
  const page = await adapter.bootstrap(authorization, {
22
- locator: room.locator,
23
- selection: room.replica.selection,
24
- pageToken,
44
+ locator,
45
+ selection,
46
+ ...(transfer?.pageToken == null ? {} : { pageToken: transfer.pageToken }),
25
47
  });
26
- if (page.kind !== 'bootstrap')
48
+ if (page.kind !== 'bootstrap') {
49
+ if (!RESUMABLE.has(page.kind))
50
+ await staging.abandon(locator);
27
51
  return page;
28
- if (page.roomVersion !== roomVersion)
52
+ }
53
+ transfer = {
54
+ locator,
55
+ transfer: transfer?.transfer ?? transferIdentity(),
56
+ selection,
57
+ from: transfer?.from ?? page.roomVersion,
58
+ last: page.roomVersion,
59
+ pageToken: page.pageToken ?? null,
60
+ models: remodel(page.models, transfer?.models ?? held),
61
+ attachments: [...(transfer?.attachments ?? []), page.attachments ?? []],
62
+ };
63
+ const staged = pageLayer(page);
64
+ if (!(await staging.stage(transfer, staged)))
29
65
  return unconfirmed;
30
- Object.assign(documents, page.documents);
31
- Object.assign(revisions, page.revisions);
32
- Object.assign(changes, page.changes);
33
- for (const target of page.binaryTargets)
66
+ Object.assign(documents, staged.documents);
67
+ Object.assign(revisions, staged.revisions);
68
+ Object.assign(changes, staged.changes);
69
+ Object.assign(written, staged.written);
70
+ for (const target of staged.binaryTargets)
34
71
  binaryTargets.add(target);
35
- attachments.push(page.attachments ?? []);
36
- pageToken = page.pageToken;
37
72
  }
38
- return readStaged({
39
- locator: room.locator,
73
+ const record = {
74
+ locator,
40
75
  name: room.name,
76
+ handle: room.handle,
41
77
  operations: room.operations,
42
78
  replica: room.replica,
43
- attachedModel: room.attachedModel,
44
- model: models.collection,
79
+ model: transfer.models.collection,
45
80
  typedSelection: room.typedSelection ?? null,
46
- selectionModel: models.selection,
81
+ selectionModel: transfer.models.selection,
47
82
  providerOwnedPaths: room.providerOwnedPaths,
48
- roomVersion,
83
+ roomVersion: transfer.from,
84
+ transfer: transfer.transfer,
49
85
  documents,
50
86
  binaryTargets: [...binaryTargets].sort(),
51
87
  revisions,
52
88
  changes,
53
- written: Object.fromEntries(Object.keys(documents).map((path) => [path, roomVersion])),
54
- attachments: declaredAttachments(attachments),
55
- });
89
+ written,
90
+ attachments: declaredAttachments(transfer.attachments),
91
+ };
92
+ const reconciled = transfer.last === transfer.from
93
+ ? { kind: 'still-current' }
94
+ : await advancement(adapter, authorization, record, remodel, continuing);
95
+ if (reconciled.kind === 'advanced' || reconciled.kind === 'still-current') {
96
+ const read = readStaged(reconciled.kind === 'advanced' ? reconciled.record : record);
97
+ if (read.kind === 'refused') {
98
+ await staging.abandon(locator);
99
+ return read;
100
+ }
101
+ return { kind: 'staged', confirmed: read.confirmed, stored: record };
102
+ }
103
+ if (reconciled.kind === 'beyond-horizon') {
104
+ await staging.abandon(locator);
105
+ return unconfirmed;
106
+ }
107
+ if (!RESUMABLE.has(reconciled.kind))
108
+ await staging.abandon(locator);
109
+ return reconciled;
56
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../src/change-set.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAU,KAAK,GAAG,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE,SAAS,GAAG,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,MAAM,EAAE,SAAS;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAAC;AAqBF,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,GAAG,IAAI,EACtB,KAAK,EAAE,OAAO,GAAG,IAAI,EACrB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CAClB,GACL,SAAS,CAiDX;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,SAAS,CAUX;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,CAUrE"}
1
+ {"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../src/change-set.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAwB,KAAK,GAAG,EAAE,MAAM,WAAW,CAAC;AAE3D,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,EAAE,CAAC;IACvB,KAAK,EAAE,SAAS,GAAG,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,MAAM,EAAE,SAAS;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAAC;AAqBF,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,GAAG,IAAI,EACtB,KAAK,EAAE,OAAO,GAAG,IAAI,EACrB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CAClB,GACL,SAAS,CAqDX;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,SAAS,CAUX;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,CAUrE"}
@@ -1,15 +1,17 @@
1
+ import { passingDocument } from './collection.js';
1
2
  import { sameChange } from './overlay.js';
2
3
  import { beneath } from './paths.js';
3
4
  import { compositionOf, sameMembership } from './replica.js';
4
- import { rowsOf } from './rows.js';
5
+ import { markdownPath, rowsOf } from './rows.js';
5
6
  function rowsAt(locator, replica, path) {
6
7
  if (replica === null)
7
8
  return [];
8
- const document = replica.visible.collection.documents[path];
9
- if (document === undefined && !replica.visible.binaryTargets.includes(path)) {
9
+ const visible = replica.visible;
10
+ const document = markdownPath(path) ? passingDocument(visible.collection, path) : null;
11
+ const held = visible.documents[path] !== undefined && document !== undefined;
12
+ if (!held && !visible.binaryTargets.includes(path))
10
13
  return [];
11
- }
12
- return rowsOf(locator, path, document ?? null, compositionOf(replica.confirmed.record), replica.visible.changes[path] ?? null);
14
+ return rowsOf(locator, path, document ?? null, compositionOf(replica.confirmed.record), visible.changes[path] ?? null);
13
15
  }
14
16
  function modelShape(model) {
15
17
  return model.status === 'unavailable' ? 'unavailable' : JSON.stringify(model.types);
@@ -45,8 +47,12 @@ export function changeSet(locator, before, after, changed = {}) {
45
47
  documents.push({
46
48
  locator,
47
49
  path,
48
- before: rowsAt(locator, before, path),
49
- after: rowsAt(locator, after, path),
50
+ get before() {
51
+ return rowsAt(locator, before, path);
52
+ },
53
+ get after() {
54
+ return rowsAt(locator, after, path);
55
+ },
50
56
  });
51
57
  }
52
58
  return {
package/dist/change.d.ts CHANGED
@@ -51,6 +51,10 @@ export type Precondition = {
51
51
  readonly kind: 'revision';
52
52
  readonly path: string;
53
53
  readonly revision: string;
54
+ } | {
55
+ readonly kind: 'content';
56
+ readonly path: string;
57
+ readonly content: string;
54
58
  } | {
55
59
  readonly kind: 'present';
56
60
  readonly path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"change.d.ts","sourceRoot":"","sources":["../src/change.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GACd;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5E;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC7E;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,YAAY,GACpB;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC/E;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,CAAC,EAAE,OAAO,YAAY,EAAE,iBAAiB,CAAC;IACpD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;CAChC,CAAC;AAUF,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAEzD"}
1
+ {"version":3,"file":"change.d.ts","sourceRoot":"","sources":["../src/change.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { type Answered } from '../attempt.js';
2
+ import { type CallResult } from '../outcome.js';
3
+ import type { Expected } from './overlay.js';
4
+ export type ChatResult = CallResult | {
5
+ readonly kind: 'offline';
6
+ };
7
+ export type ChatOutcome = {
8
+ readonly state: 'sending';
9
+ } | {
10
+ readonly state: 'offline';
11
+ } | {
12
+ readonly state: 'failed';
13
+ readonly result: CallResult;
14
+ };
15
+ export declare function accepted(result: ChatResult): result is Extract<CallResult, {
16
+ readonly kind: 'action';
17
+ }>;
18
+ export declare function unanswered(result: ChatResult): boolean;
19
+ export declare function outcomeOf(result: ChatResult): ChatOutcome | null;
20
+ export declare function answeredOf(result: ChatResult): Answered;
21
+ export type Sender = {
22
+ carried(name: string, about: unknown, sending: (operation: string) => Promise<CallResult>): Promise<ChatResult>;
23
+ expect(expected: Expected): void;
24
+ draw(expected: Expected): void;
25
+ };
26
+ type Senders = {
27
+ readonly online: boolean;
28
+ identity(intent: string): string;
29
+ expect(expected: Expected): void;
30
+ draw(expected: Expected): void;
31
+ };
32
+ export declare function sender({ online, identity, expect, draw }: Senders): Sender;
33
+ export {};
34
+ //# sourceMappingURL=acts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acts.d.ts","sourceRoot":"","sources":["../../src/chat/acts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC;AAE9D,wBAAgB,QAAQ,CACtB,MAAM,EAAE,UAAU,GACjB,MAAM,IAAI,OAAO,CAAC,UAAU,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAE5D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAEtD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,CAGhE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAIvD;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GAClD,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,OAAO,GAAG,MAAM,CAa1E"}
@@ -0,0 +1,36 @@
1
+ import { intentOf } from '../attempt.js';
2
+ import { UNCERTAIN } from '../outcome.js';
3
+ export function accepted(result) {
4
+ return result.kind === 'action';
5
+ }
6
+ export function unanswered(result) {
7
+ return result.kind === 'transport-uncertainty';
8
+ }
9
+ export function outcomeOf(result) {
10
+ if (accepted(result))
11
+ return null;
12
+ return result.kind === 'offline' ? { state: 'offline' } : { state: 'failed', result };
13
+ }
14
+ export function answeredOf(result) {
15
+ if (accepted(result))
16
+ return 'accepted';
17
+ if (result.kind === 'offline')
18
+ return 'offline';
19
+ return unanswered(result) ? 'unanswered' : 'refused';
20
+ }
21
+ export function sender({ online, identity, expect, draw }) {
22
+ return {
23
+ async carried(name, about, sending) {
24
+ if (!online)
25
+ return { kind: 'offline' };
26
+ try {
27
+ return await sending(identity(intentOf(name, about)));
28
+ }
29
+ catch {
30
+ return UNCERTAIN;
31
+ }
32
+ },
33
+ expect,
34
+ draw,
35
+ };
36
+ }
@@ -0,0 +1,3 @@
1
+ import type { TurnContext } from '../adapter.js';
2
+ export declare function contextText(context: TurnContext): string;
3
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/chat/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAQjD,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAExD"}
@@ -0,0 +1,10 @@
1
+ function figure(tokens) {
2
+ if (tokens >= 1_000_000)
3
+ return `${(tokens / 1_000_000).toFixed(1).replace(/\.0$/, '')}M`;
4
+ if (tokens >= 1_000)
5
+ return `${Math.round(tokens / 1_000)}k`;
6
+ return String(tokens);
7
+ }
8
+ export function contextText(context) {
9
+ return `${figure(context.used)}/${figure(context.window)}`;
10
+ }
@@ -0,0 +1,9 @@
1
+ import { type ReactElement, type ReactNode } from 'react';
2
+ import { type ChatNoteProps } from './kit.js';
3
+ export type ChatInputProps = {
4
+ readonly messageLength?: number;
5
+ readonly note?: (note: ChatNoteProps) => ReactNode;
6
+ readonly autoFocus?: boolean;
7
+ };
8
+ export declare function ChatInput({ messageLength, note, autoFocus, }: ChatInputProps): ReactElement;
9
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/chat/input.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAqBlG,OAAO,EAAsD,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAMlG,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,SAAS,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAiGF,wBAAgB,SAAS,CAAC,EACxB,aAAa,EACb,IAAY,EACZ,SAAiB,GAClB,EAAE,cAAc,GAAG,YAAY,CA+K/B"}
@@ -0,0 +1,99 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useContext, useEffect, useMemo, useRef } from 'react';
3
+ import { ComposerPrimitive, useAui, useAuiState, } from '@assistant-ui/react';
4
+ import { DropdownMenu } from 'radix-ui';
5
+ import ArrowUp from 'lucide-react/dist/esm/icons/arrow-up.mjs';
6
+ import Check from 'lucide-react/dist/esm/icons/check.mjs';
7
+ import ChevronDown from 'lucide-react/dist/esm/icons/chevron-down.mjs';
8
+ import CornerDownRight from 'lucide-react/dist/esm/icons/corner-down-right.mjs';
9
+ import ListEnd from 'lucide-react/dist/esm/icons/list-end.mjs';
10
+ import Paperclip from 'lucide-react/dist/esm/icons/paperclip.mjs';
11
+ import Pencil from 'lucide-react/dist/esm/icons/pencil.mjs';
12
+ import Plus from 'lucide-react/dist/esm/icons/plus.mjs';
13
+ import Square from 'lucide-react/dist/esm/icons/square.mjs';
14
+ import X from 'lucide-react/dist/esm/icons/x.mjs';
15
+ import { contextText } from './context.js';
16
+ import { Button, ChatNote, IconButton, Name, Portal, Scoped } from './kit.js';
17
+ import { COMMAND } from './process.js';
18
+ import { useChat, useChatScope } from './provider.js';
19
+ import { forgetAnswers } from './question.js';
20
+ import { useOpened } from './opened.js';
21
+ const commanded = {
22
+ serialize: (item) => `${COMMAND}${item.id}`,
23
+ parse: (said) => [{ kind: 'text', text: said }],
24
+ };
25
+ const atStart = (said, char, cursor) => {
26
+ const typed = said.slice(0, cursor);
27
+ return typed.startsWith(char) && !/\s/.test(typed)
28
+ ? { query: typed.slice(char.length), offset: 0, endOffset: cursor }
29
+ : null;
30
+ };
31
+ function commandItem(command) {
32
+ return {
33
+ id: command.name,
34
+ type: 'command',
35
+ label: `${COMMAND}${command.name}`,
36
+ description: command.description,
37
+ };
38
+ }
39
+ function commandsFound(commands, query) {
40
+ const asked = query.toLowerCase();
41
+ const named = commands.filter((one) => one.name.toLowerCase().startsWith(asked));
42
+ const within = commands.filter((one) => !named.includes(one) && one.name.toLowerCase().includes(asked));
43
+ return [...named, ...within].map(commandItem);
44
+ }
45
+ function Attached({ id, name }) {
46
+ const aui = useAui();
47
+ return (_jsxs("span", { className: "ahc-chip ahc-chip--removable", children: [_jsx(Paperclip, { "aria-hidden": "true" }), _jsx(Name, { text: name }), _jsx(IconButton, { label: `Remove ${name}`, compact: true, onClick: () => void aui.composer().attachment({ id }).remove(), children: _jsx(X, { "aria-hidden": "true" }) })] }));
48
+ }
49
+ function Picker({ option, choose, }) {
50
+ const container = useContext(Portal);
51
+ return (_jsxs(DropdownMenu.Root, { modal: false, children: [_jsxs(DropdownMenu.Trigger, { className: "ahc-btn ahc-picker", "aria-label": option.name, title: option.name, children: [_jsx(Name, { text: option.values.find((one) => one.value === option.value)?.name ?? option.value }), _jsx(ChevronDown, { "aria-hidden": "true" })] }), _jsx(DropdownMenu.Portal, { container: container, children: _jsxs(DropdownMenu.Content, { className: "ahc-menu", side: "top", align: "start", children: [_jsx(DropdownMenu.Label, { className: "ahc-menu__heading", children: option.name }), _jsx(DropdownMenu.RadioGroup, { value: option.value, onValueChange: (value) => {
52
+ if (value !== option.value)
53
+ void choose(option.id, value);
54
+ }, children: option.values.map((one) => (_jsxs(DropdownMenu.RadioItem, { value: one.value, className: "ahc-row", children: [_jsx("span", { className: "ahc-row__label", children: one.name }), _jsx(DropdownMenu.ItemIndicator, { asChild: true, children: _jsx(Check, { "aria-hidden": "true" }) })] }, one.value))) })] }) })] }));
55
+ }
56
+ function noted(note) {
57
+ return _jsx(ChatNote, { ...note });
58
+ }
59
+ export function ChatInput({ messageLength, note = noted, autoFocus = false, }) {
60
+ const chat = useChat();
61
+ const { client } = useChatScope();
62
+ const aui = useAui();
63
+ const opened = useOpened();
64
+ const { lone, commands, context, queued, running } = opened;
65
+ const conversation = chat.conversation ?? '';
66
+ const input = useRef(null);
67
+ const picker = useRef(null);
68
+ const thread = chat.conversation ?? `new:${chat.agent ?? ''}`;
69
+ useEffect(() => {
70
+ if (autoFocus)
71
+ input.current?.focus();
72
+ }, [autoFocus, thread]);
73
+ const typed = useAuiState((s) => s.composer.text);
74
+ const attached = useAuiState((s) => s.composer.attachments.length > 0);
75
+ const fault = messageLength !== undefined && typed.length > messageLength
76
+ ? `Keep it to ${messageLength} characters.`
77
+ : null;
78
+ const listed = useMemo(() => ({
79
+ categories: () => [],
80
+ categoryItems: () => [],
81
+ search: (query) => commandsFound(commands, query),
82
+ }), [commands]);
83
+ const interrupt = () => void chat.stop().then((stopped) => {
84
+ if (stopped)
85
+ void forgetAnswers(client, conversation);
86
+ });
87
+ const edit = (id) => {
88
+ chat.edit(id);
89
+ input.current?.focus();
90
+ };
91
+ const drafted = typed.trim() !== '' || attached;
92
+ const readOnly = opened.deleted;
93
+ return (_jsx(Scoped, { children: _jsxs("div", { className: "ahc-input-area", children: [readOnly || queued.length === 0 ? null : (_jsxs("div", { role: "group", "aria-label": "Queued messages", className: "ahc-queue", children: [_jsxs("div", { className: "ahc-queue__head", children: [_jsx(ListEnd, { "aria-hidden": "true" }), _jsx("span", { className: "ahc-queue__said", children: `${queued.length} ${queued.length === 1 ? 'message waits' : 'messages wait'} for ${opened.name} to finish` }), running ? (_jsx(Button, { variant: "outline", compact: true, onClick: interrupt, children: "Send now" })) : null] }), queued.map((item) => (_jsxs("div", { className: "ahc-queue-row", children: [_jsx(CornerDownRight, { "aria-hidden": "true", className: "ahc-muted" }), _jsx("span", { className: "ahc-queue-row__text", children: item.text }), _jsx(IconButton, { label: "Edit queued message", compact: true, onClick: () => edit(item.id), children: _jsx(Pencil, { "aria-hidden": "true" }) }), _jsx(IconButton, { label: "Remove queued message", compact: true, onClick: () => chat.unqueue(item.id), children: _jsx(X, { "aria-hidden": "true" }) })] }, item.id)))] })), readOnly ? null : (_jsx(ComposerPrimitive.Root, { className: "ahc-composer", children: _jsxs(ComposerPrimitive.Unstable_TriggerPopoverRoot, { children: [commands.length === 0 ? null : (_jsxs(ComposerPrimitive.Unstable_TriggerPopover, { char: COMMAND, matcher: atStart, adapter: listed, "aria-label": "Commands", className: "ahc-menu ahc-commands", children: [_jsx(ComposerPrimitive.Unstable_TriggerPopover.Directive, { formatter: commanded }), _jsx(ComposerPrimitive.Unstable_TriggerPopoverItems, { children: (items) => items.map((item, index) => (_jsx(ComposerPrimitive.Unstable_TriggerPopoverItem, { item: item, index: index, className: "ahc-row ahc-row--two", children: _jsxs("span", { className: "ahc-row__label", children: [_jsx("span", { className: "ahc-row__title ahc-mono", children: item.label }), _jsx("span", { className: "ahc-row__sub", children: item.description })] }) }, item.id))) })] })), attached ? (_jsx("div", { className: "ahc-chips", children: _jsx(ComposerPrimitive.Attachments, { children: ({ attachment }) => _jsx(Attached, { id: attachment.id, name: attachment.name }) }) })) : null, _jsx(ComposerPrimitive.Input, { asChild: true, "aria-label": "Message", placeholder: lone === null ? `Message ${opened.name}` : lone.field.prompt, submitMode: fault === null ? 'enter' : 'none', children: _jsx("textarea", { ref: input, className: "ahc-composer__input", rows: 1 }) }), _jsxs("div", { className: "ahc-composer__bar", children: [_jsx(IconButton, { label: "Add files", onClick: () => picker.current?.click(), children: _jsx(Plus, { size: 20, "aria-hidden": "true" }) }), _jsx("input", { ref: picker, type: "file", multiple: true, hidden: true, onChange: (event) => {
94
+ const chosen = [...(event.target.files ?? [])];
95
+ event.target.value = '';
96
+ for (const file of chosen)
97
+ void aui.composer().addAttachment(file);
98
+ } }), opened.options.map((option) => (_jsx(Picker, { option: option, choose: chat.choose }, option.id))), _jsx("span", { className: "ahc-spacer" }), context === null ? null : (_jsx("span", { title: "Context in use", className: "ahc-meta", children: contextText(context) })), running ? (_jsx("button", { type: "button", className: `ahc-btn ahc-btn--icon ${drafted ? 'ahc-btn--outline' : 'ahc-btn--ink'}`, "aria-label": "Stop", title: "Stop", onClick: interrupt, children: _jsx(Square, { "aria-hidden": "true" }) })) : null, running && !drafted ? null : (_jsx(ComposerPrimitive.Send, { className: "ahc-btn ahc-btn--icon ahc-btn--ink", "aria-label": running ? 'Queue message' : 'Send', disabled: fault !== null, children: _jsx(ArrowUp, { size: 20, "aria-hidden": "true" }) }))] })] }) })), fault === null ? null : (_jsx("p", { className: "ahc-note", role: "status", "data-state": "refused", children: fault })), note({ outcome: chat.acting.outcome }), note({ outcome: chat.sending.outcome, again: chat.sending.again ?? undefined })] }) }));
99
+ }