@classic-homes/agent-chat 0.1.0 → 0.1.1

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.
@@ -6,6 +6,7 @@
6
6
  DocumentContext,
7
7
  FileRef,
8
8
  } from '@classic-homes/agent-contracts';
9
+ import type { BackendMode } from '@classic-homes/agent-contracts';
9
10
  import { ChatSession } from '../session.svelte.js';
10
11
  import ArtifactPanel from './ArtifactPanel.svelte';
11
12
  import Composer from './Composer.svelte';
@@ -17,6 +18,8 @@
17
18
  /** Sandbox origin for artifacts and MCP-UI (agent-api `/frame`). */
18
19
  sandboxOrigin: string;
19
20
  conversationId?: string | null;
21
+ /** Backend mode from `/api/me`; shows the mock banner before any turn runs. */
22
+ mode?: BackendMode;
20
23
  agent?: AgentKey;
21
24
  clientKind?: ClientKind;
22
25
  variant?: 'page' | 'panel';
@@ -36,6 +39,7 @@
36
39
  client,
37
40
  sandboxOrigin,
38
41
  conversationId = null,
42
+ mode,
39
43
  agent = 'classic-agent',
40
44
  clientKind,
41
45
  variant = 'page',
@@ -54,16 +58,26 @@
54
58
  const session = new ChatSession({
55
59
  client,
56
60
  conversationId,
61
+ mode,
57
62
  agent,
58
63
  clientKind,
59
64
  getContext,
60
65
  onConversationStarted: (id) => onconversationstarted?.(id),
61
66
  onToolResult: (name, status) => ontoolresult?.(name, status),
62
67
  });
68
+ // The constructor already knows `conversationId`; what decides a fetch is whether the
69
+ // transcript for it has been loaded (or started) in this session.
63
70
  $effect(() => {
64
- if (conversationId && conversationId !== session.conversationId)
71
+ if (
72
+ conversationId &&
73
+ conversationId !== session.loadedConversationId &&
74
+ session.status !== 'loading'
75
+ )
65
76
  void session.load(conversationId);
66
77
  });
78
+ $effect(() => {
79
+ if (mode && !session.mode) session.mode = mode;
80
+ });
67
81
 
68
82
  let composer: Composer | undefined = $state();
69
83
  let draft = $state('');
@@ -1,10 +1,13 @@
1
1
  import type { AgentApiClient } from '@classic-homes/agent-client';
2
2
  import type { AgentKey, ClientKind, DocumentContext } from '@classic-homes/agent-contracts';
3
+ import type { BackendMode } from '@classic-homes/agent-contracts';
3
4
  interface Props {
4
5
  client: AgentApiClient;
5
6
  /** Sandbox origin for artifacts and MCP-UI (agent-api `/frame`). */
6
7
  sandboxOrigin: string;
7
8
  conversationId?: string | null;
9
+ /** Backend mode from `/api/me`; shows the mock banner before any turn runs. */
10
+ mode?: BackendMode;
8
11
  agent?: AgentKey;
9
12
  clientKind?: ClientKind;
10
13
  variant?: 'page' | 'panel';
@@ -1 +1 @@
1
- {"version":3,"file":"AgentChat.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/AgentChat.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EACR,QAAQ,EACR,UAAU,EACV,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AAQxC,UAAU,KAAK;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;IACtD,qBAAqB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,iGAAiG;IACjG,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmGH,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"AgentChat.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/AgentChat.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EACR,QAAQ,EACR,UAAU,EACV,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAQhE,UAAU,KAAK;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;IACtD,qBAAqB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,iGAAiG;IACjG,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+GH,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -1,9 +1,11 @@
1
1
  import type { AgentApiClient } from '@classic-homes/agent-client';
2
- import type { AgentKey, ChatEvent, ClientKind, DocumentContext, FileRef } from '@classic-homes/agent-contracts';
2
+ import type { AgentKey, BackendMode, ChatEvent, ClientKind, DocumentContext, FileRef } from '@classic-homes/agent-contracts';
3
3
  import { type AssistantMessage, type ChatMessage } from './reducer.js';
4
4
  export interface ChatSessionOptions {
5
5
  client: AgentApiClient;
6
6
  conversationId?: string | null;
7
+ /** Backend mode known before the first turn (from `/api/me`), so the mock banner shows at once. */
8
+ mode?: BackendMode;
7
9
  agent?: AgentKey;
8
10
  clientKind?: ClientKind;
9
11
  /** Context attached to each turn when the host's toggle is on. */
@@ -21,6 +23,8 @@ export declare class ChatSession {
21
23
  messages: ChatMessage[];
22
24
  status: SessionStatus;
23
25
  conversationId: string | null;
26
+ /** The conversation whose transcript `messages` holds (loaded or started here); null before. */
27
+ loadedConversationId: string | null;
24
28
  mode: "mock" | "live" | undefined;
25
29
  loadError: string | undefined;
26
30
  pendingFiles: {
@@ -1 +1 @@
1
- {"version":3,"file":"session.svelte.d.ts","sourceRoot":"","sources":["../src/lib/session.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,KAAK,EACV,QAAQ,EAER,SAAS,EAET,UAAU,EACV,eAAe,EACf,OAAO,EACR,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;IACtD,qBAAqB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;AAE7D;;;GAGG;AACH,qBAAa,WAAW;IACtB,QAAQ,gBAA6B;IACrC,MAAM,gBAAiC;IACvC,cAAc,gBAA+B;IAC7C,IAAI,8BAA8C;IAClD,SAAS,qBAAyC;IAClD,YAAY;;;;;;QAAyB;IAErC,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,OAAO,EAAE,kBAAkB;IAKvC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,OAAO,IAAI,gBAAgB,GAAG,SAAS,CAG1C;IAED,yFAAyF;IACnF,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B5E,+FAA+F;IACzF,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9C,MAAM,IAAI,IAAI;YAOA,GAAG;IAkDjB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,MAAM;CAKf;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAE1E"}
1
+ {"version":3,"file":"session.svelte.d.ts","sourceRoot":"","sources":["../src/lib/session.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,KAAK,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EAET,UAAU,EACV,eAAe,EACf,OAAO,EACR,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,mGAAmG;IACnG,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;IACtD,qBAAqB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;AAE7D;;;GAGG;AACH,qBAAa,WAAW;IACtB,QAAQ,gBAA6B;IACrC,MAAM,gBAAiC;IACvC,cAAc,gBAA+B;IAC7C,gGAAgG;IAChG,oBAAoB,gBAA+B;IACnD,IAAI,8BAA8C;IAClD,SAAS,qBAAyC;IAClD,YAAY;;;;;;QAAyB;IAErC,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,OAAO,EAAE,kBAAkB;IAMvC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,OAAO,IAAI,gBAAgB,GAAG,SAAS,CAG1C;IAED,yFAAyF;IACnF,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B3C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B5E,+FAA+F;IACzF,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9C,MAAM,IAAI,IAAI;YAOA,GAAG;IAmDjB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,MAAM;CAKf;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAE1E"}
@@ -8,6 +8,8 @@ export class ChatSession {
8
8
  messages = $state([]);
9
9
  status = $state('idle');
10
10
  conversationId = $state(null);
11
+ /** The conversation whose transcript `messages` holds (loaded or started here); null before. */
12
+ loadedConversationId = $state(null);
11
13
  mode = $state(undefined);
12
14
  loadError = $state(undefined);
13
15
  pendingFiles = $state([]);
@@ -16,6 +18,7 @@ export class ChatSession {
16
18
  constructor(options) {
17
19
  this.options = options;
18
20
  this.conversationId = options.conversationId ?? null;
21
+ this.mode = options.mode;
19
22
  }
20
23
  get streaming() {
21
24
  return this.status === 'streaming';
@@ -31,6 +34,7 @@ export class ChatSession {
31
34
  try {
32
35
  const detail = await this.options.client.getConversation(conversationId);
33
36
  this.conversationId = conversationId;
37
+ this.loadedConversationId = conversationId;
34
38
  this.messages = detail.messages.map((m) => m.role === 'user'
35
39
  ? {
36
40
  id: m.id,
@@ -106,6 +110,7 @@ export class ChatSession {
106
110
  this.mode = event.mode;
107
111
  if (this.conversationId !== event.conversationId) {
108
112
  this.conversationId = event.conversationId;
113
+ this.loadedConversationId = event.conversationId;
109
114
  this.options.onConversationStarted?.(event.conversationId);
110
115
  }
111
116
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classic-homes/agent-chat",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Svelte 5 chat UI for Classic Agent: session state, message list, composer, tool timeline, artifacts and MCP-UI sandbox frames. Consumed by the Classic App.",
@@ -17,8 +17,8 @@
17
17
  "dist"
18
18
  ],
19
19
  "dependencies": {
20
- "@classic-homes/agent-client": "0.1.0",
21
- "@classic-homes/agent-contracts": "0.1.0",
20
+ "@classic-homes/agent-client": "0.1.1",
21
+ "@classic-homes/agent-contracts": "0.1.1",
22
22
  "dompurify": "3.4.17"
23
23
  },
24
24
  "peerDependencies": {