@jini-ai/chat 0.3.11 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +126 -0
- package/README.md +152 -6
- package/dist/core/ag-ui/entry.d.ts +53 -0
- package/dist/core/ag-ui/entry.js +135 -0
- package/dist/core/agentic/chat-capabilities.d.ts +1 -1
- package/dist/core/agentic/index.d.ts +1 -1
- package/dist/core/agentic/index.js +1 -1
- package/dist/core/assistant-content.d.ts +6 -2
- package/dist/core/assistant-content.js +2 -2
- package/dist/core/compact-events.d.ts +3 -1
- package/dist/core/compact-events.js +1 -1
- package/dist/core/events.d.ts +1 -1
- package/dist/core/events.js +1 -1
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/core/messages.d.ts +4 -2
- package/dist/core/messages.js +2 -2
- package/dist/core/partial-json.d.ts +6 -2
- package/dist/core/partial-json.js +3 -3
- package/dist/core/persistence/index.d.ts +1 -1
- package/dist/core/persistence/index.js +1 -1
- package/dist/core/persistence/ports.d.ts +2 -123
- package/dist/core/persistence/title.d.ts +3 -1
- package/dist/core/persistence/title.js +1 -1
- package/dist/core/question-form/format.d.ts +16 -7
- package/dist/core/question-form/format.js +3 -3
- package/dist/core/question-form/normalize.d.ts +7 -2
- package/dist/core/question-form/normalize.js +5 -5
- package/dist/core/question-form/scan.d.ts +18 -6
- package/dist/core/question-form/scan.js +14 -14
- package/dist/core/run-activity.d.ts +16 -4
- package/dist/core/run-activity.js +11 -11
- package/dist/core/run-events/entry.d.ts +121 -0
- package/dist/core/run-events/entry.js +290 -0
- package/dist/core/todos.d.ts +20 -8
- package/dist/core/todos.js +11 -11
- package/dist/core/tool-events.d.ts +3 -1
- package/dist/core/tool-events.js +1 -1
- package/dist/core/tool-output.d.ts +3 -1
- package/dist/core/tool-output.js +1 -1
- package/dist/core/tools.d.ts +14 -3
- package/dist/core/tools.js +3 -3
- package/dist/core/transcript.d.ts +13 -5
- package/dist/core/transcript.js +5 -5
- package/dist/core/util/manifest.d.ts +9 -3
- package/dist/core/util/manifest.js +3 -3
- package/dist/core/util/markdown-context.d.ts +11 -3
- package/dist/core/util/markdown-context.js +3 -3
- package/dist/core/util/markup-attributes.d.ts +3 -1
- package/dist/core/util/markup-attributes.js +1 -1
- package/dist/core/util/parser.d.ts +9 -5
- package/dist/core/util/parser.js +13 -13
- package/dist/core/util/recover.d.ts +6 -2
- package/dist/core/util/recover.js +6 -6
- package/dist/core/util/strip.d.ts +19 -5
- package/dist/core/util/strip.js +17 -17
- package/dist/core/util/validate.d.ts +3 -1
- package/dist/core/util/validate.js +1 -1
- package/dist/embed-widget/browser/page-actions.d.ts +121 -0
- package/dist/embed-widget/browser/page-actions.js +113 -0
- package/dist/embed-widget/browser/session-store.d.ts +44 -0
- package/dist/embed-widget/browser/session-store.js +103 -0
- package/dist/embed-widget/react/embed.d.ts +45 -0
- package/dist/embed-widget/react/embed.js +87 -0
- package/dist/embed-widget/react/header.d.ts +21 -0
- package/dist/embed-widget/react/header.js +18 -0
- package/dist/embed-widget/transports/fetch-sse.d.ts +75 -0
- package/dist/embed-widget/transports/fetch-sse.js +175 -0
- package/dist/react/agent-bridge/frontend-session-bridge.d.ts +15 -3
- package/dist/react/agent-bridge/frontend-session-bridge.js +13 -6
- package/dist/react/artifact-types.d.ts +3 -3
- package/dist/react/artifact-types.js +3 -3
- package/dist/react/components/A2uiSurfaceCard.js +34 -13
- package/dist/react/components/AttachmentPreviewModal.hooks.d.ts +7 -2
- package/dist/react/components/AttachmentPreviewModal.hooks.js +5 -5
- package/dist/react/components/AttachmentPreviewModal.js +2 -2
- package/dist/react/components/AttachmentTray.d.ts +3 -1
- package/dist/react/components/AttachmentTray.js +2 -2
- package/dist/react/components/ChatFab.js +1 -1
- package/dist/react/components/Composer.js +9 -9
- package/dist/react/components/ConversationList.js +1 -1
- package/dist/react/components/McpUiSurfaceCard.d.ts +4 -2
- package/dist/react/components/McpUiSurfaceCard.js +5 -5
- package/dist/react/components/MessageList.js +1 -1
- package/dist/react/components/MessageRow.js +9 -9
- package/dist/react/components/QuestionForm.js +5 -5
- package/dist/react/components/ToolCard.js +9 -9
- package/dist/react/components/composer-discovery.d.ts +29 -8
- package/dist/react/components/composer-discovery.js +10 -10
- package/dist/react/ext-event-renderer-registry.d.ts +15 -5
- package/dist/react/ext-event-renderer-registry.js +4 -4
- package/dist/react/features/chat-pane/components/AgentRuntimePicker.d.ts +3 -1
- package/dist/react/features/chat-pane/components/AgentRuntimePicker.js +3 -3
- package/dist/react/features/chat-pane/components/ChatPane.js +43 -43
- package/dist/react/features/chat-pane/create-daemon-attachment-uploader.d.ts +4 -1
- package/dist/react/features/chat-pane/create-daemon-attachment-uploader.js +5 -35
- package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.d.ts +5 -2
- package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.js +1 -1
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.d.ts +38 -10
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.js +15 -15
- package/dist/react/features/chat-pane/hooks/useChatPane.hooks.js +31 -31
- package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.d.ts +3 -1
- package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.js +3 -3
- package/dist/react/features/chat-pane/hooks/useChatPaneComposerPlaceholder.hooks.d.ts +4 -1
- package/dist/react/features/chat-pane/hooks/useChatPaneComposerPlaceholder.hooks.js +1 -1
- package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.js +30 -30
- package/dist/react/features/chat-pane/hooks/useChatPaneWorkingDirectory.hooks.js +57 -57
- package/dist/react/features/chat-pane/rules.d.ts +13 -4
- package/dist/react/features/chat-pane/rules.js +5 -5
- package/dist/react/features/chat-pane/types.d.ts +1 -1
- package/dist/react/hooks/attachment-preview-cache.d.ts +7 -2
- package/dist/react/hooks/attachment-preview-cache.js +2 -2
- package/dist/react/hooks/composer-draft-cache.d.ts +17 -5
- package/dist/react/hooks/composer-draft-cache.js +6 -6
- package/dist/react/hooks/useArtifactStream.d.ts +5 -1
- package/dist/react/hooks/useArtifactStream.js +3 -3
- package/dist/react/hooks/useChatFabDrag.d.ts +9 -4
- package/dist/react/hooks/useChatFabDrag.js +4 -4
- package/dist/react/hooks/useComposer.js +8 -8
- package/dist/react/hooks/useConversation.js +56 -4
- package/dist/react/hooks/useExtEventGroups.d.ts +5 -1
- package/dist/react/hooks/useExtEventGroups.js +1 -1
- package/dist/react/hooks/useLatestOperation.d.ts +8 -3
- package/dist/react/hooks/useLatestOperation.js +4 -4
- package/dist/react/hooks/usePinnedTodos.d.ts +3 -1
- package/dist/react/hooks/usePinnedTodos.js +3 -3
- package/dist/react/hooks/useQuestionForms.d.ts +7 -2
- package/dist/react/hooks/useQuestionForms.js +7 -7
- package/dist/react/hooks/useRunActivity.d.ts +6 -1
- package/dist/react/hooks/useRunActivity.js +3 -3
- package/dist/react/hooks/useRunStream.d.ts +3 -1
- package/dist/react/hooks/useRunStream.js +1 -1
- package/dist/react/hooks/useToolTimeline.d.ts +3 -1
- package/dist/react/hooks/useToolTimeline.js +3 -3
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +6 -6
- package/dist/react/message-blocks.d.ts +10 -4
- package/dist/react/message-blocks.js +2 -2
- package/dist/react/styles/reference.css +3 -3
- package/dist/react/tool-renderer-registry.d.ts +8 -3
- package/dist/react/tool-renderer-registry.js +3 -3
- package/dist/react/util/defined-props.d.ts +3 -1
- package/dist/react/util/defined-props.js +1 -1
- package/dist/server/run-finalizer/entry.d.ts +47 -0
- package/dist/server/run-finalizer/entry.js +156 -0
- package/dist/server/run-finalizer/ports.d.ts +52 -0
- package/dist/store/contracts/index.d.ts +5 -0
- package/dist/store/contracts/index.js +5 -0
- package/dist/store/errors.d.ts +12 -0
- package/dist/store/errors.js +18 -0
- package/dist/store/index.d.ts +4 -0
- package/dist/store/index.js +2 -0
- package/dist/store/legacy/index.d.ts +3 -0
- package/dist/store/legacy/index.js +2 -0
- package/dist/store/legacy/sqlite/conversations.d.ts +129 -0
- package/dist/store/legacy/sqlite/conversations.js +274 -0
- package/dist/store/legacy/sqlite/index.d.ts +6 -0
- package/dist/store/legacy/sqlite/index.js +5 -0
- package/dist/store/legacy/sqlite/messages.d.ts +156 -0
- package/dist/store/legacy/sqlite/messages.js +246 -0
- package/dist/store/legacy/sqlite/schema.d.ts +3 -0
- package/dist/store/legacy/sqlite/schema.js +40 -0
- package/dist/store/pglite/index.d.ts +21 -0
- package/dist/store/pglite/index.js +17 -0
- package/dist/store/ports.d.ts +121 -0
- package/dist/store/ports.js +2 -0
- package/dist/store/postgres/index.d.ts +21 -0
- package/dist/store/postgres/index.js +17 -0
- package/dist/store/sql/boundary.d.ts +28 -0
- package/dist/store/sql/boundary.js +32 -0
- package/dist/store/sql/cursor.d.ts +24 -0
- package/dist/store/sql/cursor.js +49 -0
- package/dist/store/sql/maintenance.d.ts +9 -0
- package/dist/store/sql/maintenance.js +16 -0
- package/dist/store/sql/store.d.ts +22 -0
- package/dist/store/sql/store.js +340 -0
- package/dist/store/sql/tables.d.ts +34 -0
- package/dist/store/sql/tables.js +2 -0
- package/dist/store/sqlite/index.d.ts +36 -0
- package/dist/store/sqlite/index.js +29 -0
- package/dist/store/sqlite/schema.d.ts +49 -0
- package/dist/store/sqlite/schema.js +80 -0
- package/package.json +211 -14
- package/dist/react/features/model-picker/components/CredentialStatusBadge.d.ts +0 -7
- package/dist/react/features/model-picker/components/CredentialStatusBadge.js +0 -20
- package/dist/react/features/model-picker/components/ModelPicker.d.ts +0 -9
- package/dist/react/features/model-picker/components/ModelPicker.js +0 -34
- package/dist/react/features/model-picker/constants.d.ts +0 -6
- package/dist/react/features/model-picker/constants.js +0 -9
- package/dist/react/features/model-picker/dependencies.d.ts +0 -11
- package/dist/react/features/model-picker/dependencies.js +0 -10
- package/dist/react/features/model-picker/hooks/useModelPicker.hooks.d.ts +0 -27
- package/dist/react/features/model-picker/hooks/useModelPicker.hooks.js +0 -62
- package/dist/react/features/model-picker/index.d.ts +0 -32
- package/dist/react/features/model-picker/index.js +0 -29
- package/dist/react/features/model-picker/ports.d.ts +0 -11
- package/dist/react/features/model-picker/rules.d.ts +0 -26
- package/dist/react/features/model-picker/rules.js +0 -84
- package/dist/react/features/model-picker/types.d.ts +0 -38
- package/dist/react/features/model-picker/types.js +0 -2
- package/dist/react/poc-mcp-ui-official/PocMcpUiCard.d.ts +0 -9
- package/dist/react/poc-mcp-ui-official/PocMcpUiCard.js +0 -29
- package/dist/react/poc-mcp-ui-official/create-poc-resource.d.ts +0 -30
- package/dist/react/poc-mcp-ui-official/create-poc-resource.js +0 -44
- /package/dist/{react/features/model-picker → server/run-finalizer}/ports.js +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module store/sqlite/schema
|
|
3
|
+
*
|
|
4
|
+
* Canonical unchanged DDL for ai_chats and ai_chat_messages. Hosts own their database,
|
|
5
|
+
* migration ledger and connection configuration. A host with migrations retains its frozen
|
|
6
|
+
* migration statements; a fresh fixture or host without a migrator may call the explicit helper.
|
|
7
|
+
* Store construction never invokes it, chooses a file, or sets connection-wide pragmas.
|
|
8
|
+
*/
|
|
9
|
+
import type { SqliteClient } from '@jini-ai/db/sqlite';
|
|
10
|
+
/**
|
|
11
|
+
* The canonical chat-history schema.
|
|
12
|
+
*
|
|
13
|
+
* Notes on the parts that are easy to get wrong:
|
|
14
|
+
*
|
|
15
|
+
* - **`scope_id`** is the host's partition key (workspace/tenant/project). It is `NOT NULL` from
|
|
16
|
+
* the first migration on purpose: adding it later is trivial, but *backfilling* it is not —
|
|
17
|
+
* pre-existing rows carry no evidence of which partition they belonged to, so a late addition
|
|
18
|
+
* forces a choice between deleting history and guessing.
|
|
19
|
+
* - **`owner_kind` + the CHECK pair** make "a guest row with a `user_id`" unrepresentable rather
|
|
20
|
+
* than merely discouraged.
|
|
21
|
+
* - **`owner_id`** holds a user id for `user`, and a *hash* of the session key for `guest`. The
|
|
22
|
+
* raw token never reaches this table.
|
|
23
|
+
* - **`title_source`** exists so an agent-generated title cannot clobber a manual rename. That
|
|
24
|
+
* rule is enforced in the store, but it needs a column to be enforceable at all.
|
|
25
|
+
* - **`position`** orders messages, not `created_at`: two inserts inside the same millisecond
|
|
26
|
+
* are ordinary under concurrent writers, and a tie there corrupts replay order permanently.
|
|
27
|
+
* `UNIQUE (conversation_id, position)` turns a position-assignment bug into a loud constraint
|
|
28
|
+
* violation instead of a silently scrambled transcript.
|
|
29
|
+
* - **`expires_at NULL`** means "never expires". The retention sweep filters on
|
|
30
|
+
* `expires_at IS NOT NULL`, so authenticated history is out of its reach by construction, not
|
|
31
|
+
* by a predicate that could drift.
|
|
32
|
+
*/
|
|
33
|
+
export declare const CHAT_HISTORY_DDL = "\nCREATE TABLE IF NOT EXISTS ai_chats (\n id TEXT PRIMARY KEY,\n scope_id TEXT NOT NULL,\n owner_kind TEXT NOT NULL CHECK (owner_kind IN ('user','guest')),\n owner_id TEXT NOT NULL,\n title TEXT,\n title_source TEXT NOT NULL DEFAULT 'fallback'\n CHECK (title_source IN ('fallback','generated','manual')),\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n expires_at INTEGER\n);\n\nCREATE INDEX IF NOT EXISTS idx_ai_chats_owner\n ON ai_chats(scope_id, owner_kind, owner_id, updated_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_ai_chats_expiry\n ON ai_chats(expires_at) WHERE expires_at IS NOT NULL;\n\nCREATE TABLE IF NOT EXISTS ai_chat_messages (\n id TEXT PRIMARY KEY,\n conversation_id TEXT NOT NULL REFERENCES ai_chats(id) ON DELETE CASCADE,\n role TEXT NOT NULL CHECK (role IN ('user','assistant')),\n content TEXT NOT NULL,\n agent_id TEXT,\n agent_name TEXT,\n events_json TEXT,\n attachments_json TEXT,\n run_id TEXT,\n run_status TEXT,\n position INTEGER NOT NULL,\n created_at INTEGER NOT NULL,\n started_at INTEGER,\n ended_at INTEGER,\n UNIQUE (conversation_id, position)\n);\n\nCREATE INDEX IF NOT EXISTS idx_ai_chat_messages_order\n ON ai_chat_messages(conversation_id, position);\n";
|
|
34
|
+
/**
|
|
35
|
+
* Creates the chat-history tables in the given database if they are absent.
|
|
36
|
+
*
|
|
37
|
+
* Idempotent, matching `ensureToolCatalogTables`'s convention. For a host whose database is
|
|
38
|
+
* managed by its own migration system, prefer copying {@link CHAT_HISTORY_DDL} into a numbered
|
|
39
|
+
* migration instead — see this module's header for why two migrators over one file is a hazard.
|
|
40
|
+
*
|
|
41
|
+
* The caller is responsible for `PRAGMA foreign_keys = ON`; without it the `ON DELETE CASCADE`
|
|
42
|
+
* above is silently inert and deleting a conversation orphans its messages. This function does
|
|
43
|
+
* not set it, because pragmas are connection-wide and a library has no business reconfiguring a
|
|
44
|
+
* handle it was merely lent.
|
|
45
|
+
*/
|
|
46
|
+
export declare function ensureChatHistoryTables({ db }: {
|
|
47
|
+
db: Pick<SqliteClient, 'exec'>;
|
|
48
|
+
}): void;
|
|
49
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The canonical chat-history schema.
|
|
3
|
+
*
|
|
4
|
+
* Notes on the parts that are easy to get wrong:
|
|
5
|
+
*
|
|
6
|
+
* - **`scope_id`** is the host's partition key (workspace/tenant/project). It is `NOT NULL` from
|
|
7
|
+
* the first migration on purpose: adding it later is trivial, but *backfilling* it is not —
|
|
8
|
+
* pre-existing rows carry no evidence of which partition they belonged to, so a late addition
|
|
9
|
+
* forces a choice between deleting history and guessing.
|
|
10
|
+
* - **`owner_kind` + the CHECK pair** make "a guest row with a `user_id`" unrepresentable rather
|
|
11
|
+
* than merely discouraged.
|
|
12
|
+
* - **`owner_id`** holds a user id for `user`, and a *hash* of the session key for `guest`. The
|
|
13
|
+
* raw token never reaches this table.
|
|
14
|
+
* - **`title_source`** exists so an agent-generated title cannot clobber a manual rename. That
|
|
15
|
+
* rule is enforced in the store, but it needs a column to be enforceable at all.
|
|
16
|
+
* - **`position`** orders messages, not `created_at`: two inserts inside the same millisecond
|
|
17
|
+
* are ordinary under concurrent writers, and a tie there corrupts replay order permanently.
|
|
18
|
+
* `UNIQUE (conversation_id, position)` turns a position-assignment bug into a loud constraint
|
|
19
|
+
* violation instead of a silently scrambled transcript.
|
|
20
|
+
* - **`expires_at NULL`** means "never expires". The retention sweep filters on
|
|
21
|
+
* `expires_at IS NOT NULL`, so authenticated history is out of its reach by construction, not
|
|
22
|
+
* by a predicate that could drift.
|
|
23
|
+
*/
|
|
24
|
+
export const CHAT_HISTORY_DDL = `
|
|
25
|
+
CREATE TABLE IF NOT EXISTS ai_chats (
|
|
26
|
+
id TEXT PRIMARY KEY,
|
|
27
|
+
scope_id TEXT NOT NULL,
|
|
28
|
+
owner_kind TEXT NOT NULL CHECK (owner_kind IN ('user','guest')),
|
|
29
|
+
owner_id TEXT NOT NULL,
|
|
30
|
+
title TEXT,
|
|
31
|
+
title_source TEXT NOT NULL DEFAULT 'fallback'
|
|
32
|
+
CHECK (title_source IN ('fallback','generated','manual')),
|
|
33
|
+
created_at INTEGER NOT NULL,
|
|
34
|
+
updated_at INTEGER NOT NULL,
|
|
35
|
+
expires_at INTEGER
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_ai_chats_owner
|
|
39
|
+
ON ai_chats(scope_id, owner_kind, owner_id, updated_at DESC);
|
|
40
|
+
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_ai_chats_expiry
|
|
42
|
+
ON ai_chats(expires_at) WHERE expires_at IS NOT NULL;
|
|
43
|
+
|
|
44
|
+
CREATE TABLE IF NOT EXISTS ai_chat_messages (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
conversation_id TEXT NOT NULL REFERENCES ai_chats(id) ON DELETE CASCADE,
|
|
47
|
+
role TEXT NOT NULL CHECK (role IN ('user','assistant')),
|
|
48
|
+
content TEXT NOT NULL,
|
|
49
|
+
agent_id TEXT,
|
|
50
|
+
agent_name TEXT,
|
|
51
|
+
events_json TEXT,
|
|
52
|
+
attachments_json TEXT,
|
|
53
|
+
run_id TEXT,
|
|
54
|
+
run_status TEXT,
|
|
55
|
+
position INTEGER NOT NULL,
|
|
56
|
+
created_at INTEGER NOT NULL,
|
|
57
|
+
started_at INTEGER,
|
|
58
|
+
ended_at INTEGER,
|
|
59
|
+
UNIQUE (conversation_id, position)
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_ai_chat_messages_order
|
|
63
|
+
ON ai_chat_messages(conversation_id, position);
|
|
64
|
+
`;
|
|
65
|
+
/**
|
|
66
|
+
* Creates the chat-history tables in the given database if they are absent.
|
|
67
|
+
*
|
|
68
|
+
* Idempotent, matching `ensureToolCatalogTables`'s convention. For a host whose database is
|
|
69
|
+
* managed by its own migration system, prefer copying {@link CHAT_HISTORY_DDL} into a numbered
|
|
70
|
+
* migration instead — see this module's header for why two migrators over one file is a hazard.
|
|
71
|
+
*
|
|
72
|
+
* The caller is responsible for `PRAGMA foreign_keys = ON`; without it the `ON DELETE CASCADE`
|
|
73
|
+
* above is silently inert and deleting a conversation orphans its messages. This function does
|
|
74
|
+
* not set it, because pragmas are connection-wide and a library has no business reconfiguring a
|
|
75
|
+
* handle it was merely lent.
|
|
76
|
+
*/
|
|
77
|
+
export function ensureChatHistoryTables({ db }) {
|
|
78
|
+
db.exec(CHAT_HISTORY_DDL);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=schema.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Jini's chat/artifact frontend, consolidated into one package with two subpaths: framework-free chat vocabulary and pure parsers in `/core`, headless hooks + presentational components + slots in `/react`. Import only the layer you need.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -17,11 +17,29 @@
|
|
|
17
17
|
"./core": "universal",
|
|
18
18
|
"./react": "browser",
|
|
19
19
|
"./react/chat-pane": "browser",
|
|
20
|
-
"./react/styles/reference.css": "browser"
|
|
21
|
-
|
|
20
|
+
"./react/styles/reference.css": "browser",
|
|
21
|
+
"./store": "universal",
|
|
22
|
+
"./store/sqlite": "node",
|
|
23
|
+
"./store/pglite": "node",
|
|
24
|
+
"./store/postgres": "node",
|
|
25
|
+
"./store/legacy": "universal",
|
|
26
|
+
"./store/legacy/sqlite": "node",
|
|
27
|
+
"./core/run-events": "universal",
|
|
28
|
+
"./core/ag-ui": "universal",
|
|
29
|
+
"./server/run-finalizer": "universal",
|
|
30
|
+
"./react/embed": "browser",
|
|
31
|
+
"./transports/fetch-sse": "universal",
|
|
32
|
+
"./browser/session-store": "browser",
|
|
33
|
+
"./browser/page-actions": "browser"
|
|
34
|
+
},
|
|
35
|
+
"neutralEntries": [
|
|
36
|
+
"src/store/contracts"
|
|
37
|
+
]
|
|
22
38
|
},
|
|
23
39
|
"type": "module",
|
|
24
|
-
"sideEffects":
|
|
40
|
+
"sideEffects": [
|
|
41
|
+
"./dist/**/*.css"
|
|
42
|
+
],
|
|
25
43
|
"main": "./dist/core/index.js",
|
|
26
44
|
"types": "./dist/core/index.d.ts",
|
|
27
45
|
"exports": {
|
|
@@ -45,15 +63,81 @@
|
|
|
45
63
|
"import": "./dist/react/chat-pane.js",
|
|
46
64
|
"default": "./dist/react/chat-pane.js"
|
|
47
65
|
},
|
|
48
|
-
"./react/styles/reference.css": "./dist/react/styles/reference.css"
|
|
66
|
+
"./react/styles/reference.css": "./dist/react/styles/reference.css",
|
|
67
|
+
"./store": {
|
|
68
|
+
"types": "./dist/store/index.d.ts",
|
|
69
|
+
"import": "./dist/store/index.js"
|
|
70
|
+
},
|
|
71
|
+
"./store/sqlite": {
|
|
72
|
+
"types": "./dist/store/sqlite/index.d.ts",
|
|
73
|
+
"import": "./dist/store/sqlite/index.js"
|
|
74
|
+
},
|
|
75
|
+
"./store/pglite": {
|
|
76
|
+
"types": "./dist/store/pglite/index.d.ts",
|
|
77
|
+
"import": "./dist/store/pglite/index.js"
|
|
78
|
+
},
|
|
79
|
+
"./store/postgres": {
|
|
80
|
+
"types": "./dist/store/postgres/index.d.ts",
|
|
81
|
+
"import": "./dist/store/postgres/index.js"
|
|
82
|
+
},
|
|
83
|
+
"./store/legacy": {
|
|
84
|
+
"types": "./dist/store/legacy/index.d.ts",
|
|
85
|
+
"import": "./dist/store/legacy/index.js",
|
|
86
|
+
"default": "./dist/store/legacy/index.js"
|
|
87
|
+
},
|
|
88
|
+
"./store/legacy/sqlite": {
|
|
89
|
+
"types": "./dist/store/legacy/sqlite/index.d.ts",
|
|
90
|
+
"import": "./dist/store/legacy/sqlite/index.js",
|
|
91
|
+
"default": "./dist/store/legacy/sqlite/index.js"
|
|
92
|
+
},
|
|
93
|
+
"./core/run-events": {
|
|
94
|
+
"types": "./dist/core/run-events/entry.d.ts",
|
|
95
|
+
"import": "./dist/core/run-events/entry.js",
|
|
96
|
+
"default": "./dist/core/run-events/entry.js"
|
|
97
|
+
},
|
|
98
|
+
"./core/ag-ui": {
|
|
99
|
+
"types": "./dist/core/ag-ui/entry.d.ts",
|
|
100
|
+
"import": "./dist/core/ag-ui/entry.js",
|
|
101
|
+
"default": "./dist/core/ag-ui/entry.js"
|
|
102
|
+
},
|
|
103
|
+
"./server/run-finalizer": {
|
|
104
|
+
"types": "./dist/server/run-finalizer/entry.d.ts",
|
|
105
|
+
"import": "./dist/server/run-finalizer/entry.js",
|
|
106
|
+
"default": "./dist/server/run-finalizer/entry.js"
|
|
107
|
+
},
|
|
108
|
+
"./react/embed": {
|
|
109
|
+
"types": "./dist/embed-widget/react/embed.d.ts",
|
|
110
|
+
"import": "./dist/embed-widget/react/embed.js",
|
|
111
|
+
"default": "./dist/embed-widget/react/embed.js"
|
|
112
|
+
},
|
|
113
|
+
"./transports/fetch-sse": {
|
|
114
|
+
"types": "./dist/embed-widget/transports/fetch-sse.d.ts",
|
|
115
|
+
"import": "./dist/embed-widget/transports/fetch-sse.js",
|
|
116
|
+
"default": "./dist/embed-widget/transports/fetch-sse.js"
|
|
117
|
+
},
|
|
118
|
+
"./browser/session-store": {
|
|
119
|
+
"types": "./dist/embed-widget/browser/session-store.d.ts",
|
|
120
|
+
"import": "./dist/embed-widget/browser/session-store.js",
|
|
121
|
+
"default": "./dist/embed-widget/browser/session-store.js"
|
|
122
|
+
},
|
|
123
|
+
"./browser/page-actions": {
|
|
124
|
+
"types": "./dist/embed-widget/browser/page-actions.d.ts",
|
|
125
|
+
"import": "./dist/embed-widget/browser/page-actions.js",
|
|
126
|
+
"default": "./dist/embed-widget/browser/page-actions.js"
|
|
127
|
+
}
|
|
49
128
|
},
|
|
50
129
|
"files": [
|
|
51
130
|
"dist",
|
|
131
|
+
"README.md",
|
|
132
|
+
"CHANGELOG.md",
|
|
133
|
+
"LICENSE",
|
|
52
134
|
"!dist/**/*.test.js",
|
|
53
135
|
"!dist/**/*.test.d.ts",
|
|
54
136
|
"!dist/**/*.test.js.map",
|
|
55
137
|
"!dist/**/*.test.d.ts.map",
|
|
56
138
|
"!dist/**/__tests__/**",
|
|
139
|
+
"!dist/react/poc-mcp-ui-official/**",
|
|
140
|
+
"!dist/react/features/model-picker/**",
|
|
57
141
|
"!dist/**/*.map"
|
|
58
142
|
],
|
|
59
143
|
"publishConfig": {
|
|
@@ -61,16 +145,27 @@
|
|
|
61
145
|
"registry": "https://registry.npmjs.org"
|
|
62
146
|
},
|
|
63
147
|
"dependencies": {
|
|
64
|
-
"@
|
|
65
|
-
"@
|
|
66
|
-
"@jini-ai/
|
|
67
|
-
"@jini-ai/
|
|
68
|
-
"@jini-ai/protocol": "0.3.1",
|
|
69
|
-
"@jini-ai/ui": "0.3.14"
|
|
148
|
+
"@jini-ai/protocol": "0.4.0",
|
|
149
|
+
"@jini-ai/agentic": "0.4.0",
|
|
150
|
+
"@jini-ai/ui": "0.4.0",
|
|
151
|
+
"@jini-ai/core": "0.4.0"
|
|
70
152
|
},
|
|
71
153
|
"peerDependencies": {
|
|
72
154
|
"react": "^18.3.0 || ^19.0.0",
|
|
73
|
-
"react-dom": "^18.3.0 || ^19.0.0"
|
|
155
|
+
"react-dom": "^18.3.0 || ^19.0.0",
|
|
156
|
+
"@jini-ai/db": "^0.2.0",
|
|
157
|
+
"kysely": "^0.29.6",
|
|
158
|
+
"better-sqlite3": "^13.0.0",
|
|
159
|
+
"@electric-sql/pglite": "0.5.8",
|
|
160
|
+
"pg": "^8.23.0",
|
|
161
|
+
"@ag-ui/core": "0.0.58",
|
|
162
|
+
"@mcp-ui/client": "7.1.1",
|
|
163
|
+
"@radix-ui/react-checkbox": "^1.3.11",
|
|
164
|
+
"@radix-ui/react-label": "^2.1.15",
|
|
165
|
+
"@radix-ui/react-radio-group": "^1.4.7",
|
|
166
|
+
"@radix-ui/react-select": "^2.3.7",
|
|
167
|
+
"@radix-ui/react-slot": "^1.3.3",
|
|
168
|
+
"recharts": "^3.10.1"
|
|
74
169
|
},
|
|
75
170
|
"peerDependenciesMeta": {
|
|
76
171
|
"react": {
|
|
@@ -78,23 +173,125 @@
|
|
|
78
173
|
},
|
|
79
174
|
"react-dom": {
|
|
80
175
|
"optional": true
|
|
176
|
+
},
|
|
177
|
+
"@jini-ai/db": {
|
|
178
|
+
"optional": true
|
|
179
|
+
},
|
|
180
|
+
"kysely": {
|
|
181
|
+
"optional": true
|
|
182
|
+
},
|
|
183
|
+
"better-sqlite3": {
|
|
184
|
+
"optional": true
|
|
185
|
+
},
|
|
186
|
+
"@electric-sql/pglite": {
|
|
187
|
+
"optional": true
|
|
188
|
+
},
|
|
189
|
+
"pg": {
|
|
190
|
+
"optional": true
|
|
191
|
+
},
|
|
192
|
+
"@ag-ui/core": {
|
|
193
|
+
"optional": true
|
|
194
|
+
},
|
|
195
|
+
"@mcp-ui/client": {
|
|
196
|
+
"optional": true
|
|
197
|
+
},
|
|
198
|
+
"@radix-ui/react-checkbox": {
|
|
199
|
+
"optional": true
|
|
200
|
+
},
|
|
201
|
+
"@radix-ui/react-label": {
|
|
202
|
+
"optional": true
|
|
203
|
+
},
|
|
204
|
+
"@radix-ui/react-radio-group": {
|
|
205
|
+
"optional": true
|
|
206
|
+
},
|
|
207
|
+
"@radix-ui/react-select": {
|
|
208
|
+
"optional": true
|
|
209
|
+
},
|
|
210
|
+
"@radix-ui/react-slot": {
|
|
211
|
+
"optional": true
|
|
212
|
+
},
|
|
213
|
+
"recharts": {
|
|
214
|
+
"optional": true
|
|
81
215
|
}
|
|
82
216
|
},
|
|
83
217
|
"devDependencies": {
|
|
218
|
+
"@mcp-ui/client": "7.1.1",
|
|
219
|
+
"@radix-ui/react-checkbox": "^1.3.11",
|
|
220
|
+
"@radix-ui/react-label": "^2.1.15",
|
|
221
|
+
"@radix-ui/react-radio-group": "^1.4.7",
|
|
222
|
+
"@radix-ui/react-select": "^2.3.7",
|
|
223
|
+
"@radix-ui/react-slot": "^1.3.3",
|
|
84
224
|
"@testing-library/jest-dom": "^6.6.3",
|
|
85
225
|
"@testing-library/react": "^16.3.0",
|
|
86
226
|
"@testing-library/user-event": "^14.5.0",
|
|
227
|
+
"@types/better-sqlite3": "7.6.13",
|
|
228
|
+
"@types/jsdom": "^21.1.7",
|
|
87
229
|
"@types/react": "^19.2.0",
|
|
88
230
|
"@types/react-dom": "^19.2.0",
|
|
89
231
|
"@vitest/coverage-v8": "^2.1.9",
|
|
90
232
|
"jsdom": "^25.0.1",
|
|
91
233
|
"react": "^19.2.0",
|
|
92
|
-
"react-dom": "^19.2.0"
|
|
234
|
+
"react-dom": "^19.2.0",
|
|
235
|
+
"recharts": "^3.10.1",
|
|
236
|
+
"kysely": "0.29.6",
|
|
237
|
+
"better-sqlite3": "13.0.3",
|
|
238
|
+
"@electric-sql/pglite": "0.5.8",
|
|
239
|
+
"pg": "8.23.0",
|
|
240
|
+
"@ag-ui/core": "0.0.58",
|
|
241
|
+
"@jini-ai/db": "0.2.0",
|
|
242
|
+
"@jini-ai/agent-runtime": "0.4.0"
|
|
243
|
+
},
|
|
244
|
+
"typesVersions": {
|
|
245
|
+
"*": {
|
|
246
|
+
"core": [
|
|
247
|
+
"./dist/core/index.d.ts"
|
|
248
|
+
],
|
|
249
|
+
"react": [
|
|
250
|
+
"./dist/react/index.d.ts"
|
|
251
|
+
],
|
|
252
|
+
"store": [
|
|
253
|
+
"./dist/store/index.d.ts"
|
|
254
|
+
],
|
|
255
|
+
"store/sqlite": [
|
|
256
|
+
"./dist/store/sqlite/index.d.ts"
|
|
257
|
+
],
|
|
258
|
+
"store/pglite": [
|
|
259
|
+
"./dist/store/pglite/index.d.ts"
|
|
260
|
+
],
|
|
261
|
+
"store/postgres": [
|
|
262
|
+
"./dist/store/postgres/index.d.ts"
|
|
263
|
+
],
|
|
264
|
+
"react/chat-pane": [
|
|
265
|
+
"./dist/react/chat-pane.d.ts"
|
|
266
|
+
],
|
|
267
|
+
"core/run-events": [
|
|
268
|
+
"./dist/core/run-events/entry.d.ts"
|
|
269
|
+
],
|
|
270
|
+
"core/ag-ui": [
|
|
271
|
+
"./dist/core/ag-ui/entry.d.ts"
|
|
272
|
+
],
|
|
273
|
+
"server/run-finalizer": [
|
|
274
|
+
"./dist/server/run-finalizer/entry.d.ts"
|
|
275
|
+
],
|
|
276
|
+
"react/embed": [
|
|
277
|
+
"./dist/embed-widget/react/embed.d.ts"
|
|
278
|
+
],
|
|
279
|
+
"transports/fetch-sse": [
|
|
280
|
+
"./dist/embed-widget/transports/fetch-sse.d.ts"
|
|
281
|
+
],
|
|
282
|
+
"browser/session-store": [
|
|
283
|
+
"./dist/embed-widget/browser/session-store.d.ts"
|
|
284
|
+
],
|
|
285
|
+
"browser/page-actions": [
|
|
286
|
+
"./dist/embed-widget/browser/page-actions.d.ts"
|
|
287
|
+
]
|
|
288
|
+
}
|
|
93
289
|
},
|
|
94
290
|
"scripts": {
|
|
95
291
|
"build": "tsc -p tsconfig.json && mkdir -p dist/react/styles && cp src/react/styles/reference.css dist/react/styles/",
|
|
96
292
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
97
293
|
"test": "vitest run",
|
|
98
|
-
"test:coverage": "vitest run --coverage"
|
|
294
|
+
"test:coverage": "vitest run --coverage",
|
|
295
|
+
"test:postgres": "vitest run --config vitest.postgres.config.ts src/store/__tests__/postgres.postgres.test.ts"
|
|
99
296
|
}
|
|
100
297
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { CredentialStatus } from '../types.js';
|
|
2
|
-
export interface CredentialStatusBadgeProps {
|
|
3
|
-
status: CredentialStatus;
|
|
4
|
-
className?: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function CredentialStatusBadge({ status, className }: CredentialStatusBadgeProps): import("react").JSX.Element;
|
|
7
|
-
//# sourceMappingURL=CredentialStatusBadge.d.ts.map
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* @module CredentialStatusBadge
|
|
4
|
-
*
|
|
5
|
-
* A provider's credential status as a small pill — ported from
|
|
6
|
-
* `NewProjectPanel.tsx`'s inline `newproj-provider-badge` span
|
|
7
|
-
* ("Configured"/"Integrated"/"Unsupported"), de-branded and relabeled to
|
|
8
|
-
* this feature's generic `CredentialStatus` union.
|
|
9
|
-
*/
|
|
10
|
-
import { useT } from '../../../hooks/context.js';
|
|
11
|
-
const STATUS_LABEL = {
|
|
12
|
-
configured: 'Configured',
|
|
13
|
-
available: 'Available',
|
|
14
|
-
unconfigured: 'Not configured',
|
|
15
|
-
};
|
|
16
|
-
export function CredentialStatusBadge({ status, className }) {
|
|
17
|
-
const t = useT();
|
|
18
|
-
return (_jsx("span", { className: `model-picker-status-badge model-picker-status-badge--${status}${className ? ` ${className}` : ''}`, "data-status": status, children: t(STATUS_LABEL[status]) }));
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=CredentialStatusBadge.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { UseModelPickerOptions } from '../hooks/useModelPicker.hooks.js';
|
|
2
|
-
export interface ModelPickerProps extends UseModelPickerOptions {
|
|
3
|
-
label: string;
|
|
4
|
-
searchPlaceholder?: string;
|
|
5
|
-
className?: string;
|
|
6
|
-
'data-testid'?: string;
|
|
7
|
-
}
|
|
8
|
-
export declare function ModelPicker({ label, searchPlaceholder, className, 'data-testid': testId, ...pickerOptions }: ModelPickerProps): import("react").JSX.Element;
|
|
9
|
-
//# sourceMappingURL=ModelPicker.d.ts.map
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* @module ModelPicker
|
|
4
|
-
*
|
|
5
|
-
* A generic, provider-grouped, credential-status-badged, searchable model
|
|
6
|
-
* picker: trigger button + inline popover. Consolidates two independently
|
|
7
|
-
* re-implemented OD shapes that R6 confirmed share this exact pattern —
|
|
8
|
-
* `NewProjectPanel.tsx`'s `MediaModelCards` (provider grouping + status
|
|
9
|
-
* badges + search) and `modelOptions.tsx`'s `SearchableModelSelect`
|
|
10
|
-
* (searchable trigger/popover with outside-click/Escape dismissal, folded
|
|
11
|
-
* into `useModelPicker`). Unlike `SearchableModelSelect`, the popover
|
|
12
|
-
* renders inline rather than via a `document.body` portal — this package
|
|
13
|
-
* has no fixed-positioning collision-avoidance primitive of its own, and an
|
|
14
|
-
* inline popover keeps the component trivially testable; a host embedding
|
|
15
|
-
* this inside a clipping/overflow container can override positioning with
|
|
16
|
-
* its own CSS. See `source-map.md`.
|
|
17
|
-
*/
|
|
18
|
-
import { useT } from '../../../hooks/context.js';
|
|
19
|
-
import { Icon } from '../../../components/Icon.js';
|
|
20
|
-
import { modelSubtitle } from '../rules.js';
|
|
21
|
-
import { useModelPicker } from '../hooks/useModelPicker.hooks.js';
|
|
22
|
-
import { CredentialStatusBadge } from './CredentialStatusBadge.js';
|
|
23
|
-
export function ModelPicker({ label, searchPlaceholder, className, 'data-testid': testId, ...pickerOptions }) {
|
|
24
|
-
const t = useT();
|
|
25
|
-
const { open, query, filteredGroups, selection, shouldShowSearch, containerRef, setQuery, toggle, select } = useModelPicker(pickerOptions);
|
|
26
|
-
const triggerTitle = selection?.model.label ?? t('No model selected');
|
|
27
|
-
const triggerSubtitle = selection ? modelSubtitle(selection) : t('Choose a model');
|
|
28
|
-
const totalMatches = filteredGroups.reduce((count, group) => count + group.models.length, 0);
|
|
29
|
-
return (_jsxs("div", { className: `model-picker${className ? ` ${className}` : ''}`, ref: containerRef, "data-testid": testId, children: [_jsx("span", { className: "model-picker-label", children: t(label) }), _jsxs("button", { type: "button", className: `model-picker-trigger${open ? ' is-open' : ''}${selection ? '' : ' is-empty'}`, onClick: toggle, "aria-haspopup": "listbox", "aria-expanded": open, "data-testid": testId ? `${testId}-trigger` : undefined, children: [_jsxs("span", { className: "model-picker-trigger-meta", children: [_jsx("span", { className: "model-picker-trigger-title", children: triggerTitle }), _jsx("span", { className: "model-picker-trigger-subtitle", children: triggerSubtitle })] }), _jsx(Icon, { name: "chevron-down", size: 14, className: "model-picker-trigger-chevron" })] }), open ? (_jsxs("div", { className: "model-picker-popover", role: "listbox", "data-testid": testId ? `${testId}-popover` : undefined, children: [shouldShowSearch ? (_jsx("div", { className: "model-picker-search-row", children: _jsx("input", { type: "search", className: "model-picker-search", value: query, placeholder: t(searchPlaceholder ?? 'Search models'), "aria-label": t(searchPlaceholder ?? 'Search models'), "data-testid": testId ? `${testId}-search` : undefined, onChange: (event) => setQuery(event.target.value) }) })) : null, _jsx("div", { className: "model-picker-list", children: totalMatches === 0 ? (_jsx("div", { className: "model-picker-empty", children: t('No matching models') })) : (filteredGroups.map((group) => (_jsxs("div", { className: "model-picker-group", children: [_jsxs("div", { className: "model-picker-group-head", children: [_jsx("span", { children: t(group.provider.label) }), _jsx(CredentialStatusBadge, { status: group.status })] }), group.models.map((model) => {
|
|
30
|
-
const active = selection?.model.id === model.id;
|
|
31
|
-
return (_jsxs("button", { type: "button", role: "option", "aria-selected": active, className: `model-picker-option${active ? ' is-active' : ''}`, "data-testid": testId ? `${testId}-option-${model.id}` : undefined, onClick: () => select(model.id), children: [_jsxs("span", { className: "model-picker-option-title", children: [model.label, model.default ? _jsx("span", { className: "model-picker-option-badge", children: t('Recommended') }) : null] }), model.hint ? _jsx("span", { className: "model-picker-option-hint", children: model.hint }) : null] }, model.id));
|
|
32
|
-
})] }, group.provider.id)))) })] })) : null] }));
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=ModelPicker.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { CredentialStatus } from './types.js';
|
|
2
|
-
/** Below this many total options, the picker skips the search input (matches OD's `SearchableModelSelect`). */
|
|
3
|
-
export declare const DEFAULT_MIN_SEARCHABLE_OPTIONS = 8;
|
|
4
|
-
/** Lower sorts first: configured providers surface above merely-available, above unconfigured. */
|
|
5
|
-
export declare const CREDENTIAL_STATUS_SORT_PRIORITY: Record<CredentialStatus, number>;
|
|
6
|
-
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** Below this many total options, the picker skips the search input (matches OD's `SearchableModelSelect`). */
|
|
2
|
-
export const DEFAULT_MIN_SEARCHABLE_OPTIONS = 8;
|
|
3
|
-
/** Lower sorts first: configured providers surface above merely-available, above unconfigured. */
|
|
4
|
-
export const CREDENTIAL_STATUS_SORT_PRIORITY = {
|
|
5
|
-
configured: 0,
|
|
6
|
-
available: 1,
|
|
7
|
-
unconfigured: 2,
|
|
8
|
-
};
|
|
9
|
-
//# sourceMappingURL=constants.js.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ModelPickerPort } from './ports.js';
|
|
2
|
-
/**
|
|
3
|
-
* Default port: no live provider-model fetch — the picker works from
|
|
4
|
-
* whatever `models`/`providers` a host passes in directly. A host that wants
|
|
5
|
-
* a live catalogue supplies its own `ModelPickerPort` (a real fetch
|
|
6
|
-
* implementation) to `useModelPicker`/`<ModelPicker>` instead; this package
|
|
7
|
-
* ships only the no-op default, never a concrete transport call, matching
|
|
8
|
-
* the `features/connectors/` canary's `dependencies.ts` precedent.
|
|
9
|
-
*/
|
|
10
|
-
export declare const defaultModelPickerPort: ModelPickerPort;
|
|
11
|
-
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default port: no live provider-model fetch — the picker works from
|
|
3
|
-
* whatever `models`/`providers` a host passes in directly. A host that wants
|
|
4
|
-
* a live catalogue supplies its own `ModelPickerPort` (a real fetch
|
|
5
|
-
* implementation) to `useModelPicker`/`<ModelPicker>` instead; this package
|
|
6
|
-
* ships only the no-op default, never a concrete transport call, matching
|
|
7
|
-
* the `features/connectors/` canary's `dependencies.ts` precedent.
|
|
8
|
-
*/
|
|
9
|
-
export const defaultModelPickerPort = {};
|
|
10
|
-
//# sourceMappingURL=dependencies.js.map
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { RefObject } from 'react';
|
|
2
|
-
import type { CredentialStatus, ModelOption, ModelPickerGroup, ModelPickerSelection, ModelProvider } from '../types.js';
|
|
3
|
-
export interface UseModelPickerOptions {
|
|
4
|
-
models: readonly ModelOption[];
|
|
5
|
-
providers: readonly ModelProvider[];
|
|
6
|
-
statusByProviderId: Readonly<Record<string, CredentialStatus>>;
|
|
7
|
-
value: string;
|
|
8
|
-
onChange: (modelId: string) => void;
|
|
9
|
-
/** When true, auto-selects the first available model whenever `value` doesn't match any model. Defaults to false. */
|
|
10
|
-
autoSelectFirst?: boolean;
|
|
11
|
-
minSearchableOptions?: number;
|
|
12
|
-
}
|
|
13
|
-
export interface ModelPickerController {
|
|
14
|
-
open: boolean;
|
|
15
|
-
query: string;
|
|
16
|
-
groups: ModelPickerGroup[];
|
|
17
|
-
filteredGroups: ModelPickerGroup[];
|
|
18
|
-
selection: ModelPickerSelection | null;
|
|
19
|
-
shouldShowSearch: boolean;
|
|
20
|
-
containerRef: RefObject<HTMLDivElement | null>;
|
|
21
|
-
setQuery: (query: string) => void;
|
|
22
|
-
toggle: () => void;
|
|
23
|
-
close: () => void;
|
|
24
|
-
select: (modelId: string) => void;
|
|
25
|
-
}
|
|
26
|
-
export declare function useModelPicker({ models, providers, statusByProviderId, value, onChange, autoSelectFirst, minSearchableOptions, }: UseModelPickerOptions): ModelPickerController;
|
|
27
|
-
//# sourceMappingURL=useModelPicker.hooks.d.ts.map
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module useModelPicker
|
|
3
|
-
*
|
|
4
|
-
* Headless controller for the model-picker feature: open/query state,
|
|
5
|
-
* derived provider groups + current selection, and the outside-click/
|
|
6
|
-
* Escape dismissal that `InlineModelSwitcher.tsx`'s popover and
|
|
7
|
-
* `modelOptions.tsx`'s `SearchableModelSelect` both hand-roll. All grouping/
|
|
8
|
-
* filtering/selection logic is delegated to the pure `rules.ts` — this hook
|
|
9
|
-
* only owns React state and the DOM-subscription effect.
|
|
10
|
-
*/
|
|
11
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
12
|
-
import { DEFAULT_MIN_SEARCHABLE_OPTIONS } from '../constants.js';
|
|
13
|
-
import { filterModelGroups, findSelectedModel, firstAvailableModelId, groupModelsByProvider } from '../rules.js';
|
|
14
|
-
export function useModelPicker({ models, providers, statusByProviderId, value, onChange, autoSelectFirst = false, minSearchableOptions = DEFAULT_MIN_SEARCHABLE_OPTIONS, }) {
|
|
15
|
-
const [open, setOpen] = useState(false);
|
|
16
|
-
const [query, setQuery] = useState('');
|
|
17
|
-
const containerRef = useRef(null);
|
|
18
|
-
const groups = useMemo(() => groupModelsByProvider(models, providers, statusByProviderId), [models, providers, statusByProviderId]);
|
|
19
|
-
const filteredGroups = useMemo(() => filterModelGroups(groups, query), [groups, query]);
|
|
20
|
-
const selection = useMemo(() => findSelectedModel(groups, value), [groups, value]);
|
|
21
|
-
const totalOptionCount = useMemo(() => groups.reduce((count, group) => count + group.models.length, 0), [groups]);
|
|
22
|
-
const shouldShowSearch = totalOptionCount >= minSearchableOptions;
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (!autoSelectFirst || selection)
|
|
25
|
-
return;
|
|
26
|
-
const fallbackId = firstAvailableModelId(groups);
|
|
27
|
-
if (fallbackId)
|
|
28
|
-
onChange(fallbackId);
|
|
29
|
-
}, [autoSelectFirst, groups, onChange, selection]);
|
|
30
|
-
const close = useCallback(() => {
|
|
31
|
-
setOpen(false);
|
|
32
|
-
setQuery('');
|
|
33
|
-
}, []);
|
|
34
|
-
const toggle = useCallback(() => {
|
|
35
|
-
setOpen((prev) => !prev);
|
|
36
|
-
}, []);
|
|
37
|
-
const select = useCallback((modelId) => {
|
|
38
|
-
onChange(modelId);
|
|
39
|
-
close();
|
|
40
|
-
}, [close, onChange]);
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
if (!open)
|
|
43
|
-
return;
|
|
44
|
-
const onPointerDown = (event) => {
|
|
45
|
-
if (containerRef.current?.contains(event.target))
|
|
46
|
-
return;
|
|
47
|
-
close();
|
|
48
|
-
};
|
|
49
|
-
const onKeyDown = (event) => {
|
|
50
|
-
if (event.key === 'Escape')
|
|
51
|
-
close();
|
|
52
|
-
};
|
|
53
|
-
document.addEventListener('mousedown', onPointerDown);
|
|
54
|
-
document.addEventListener('keydown', onKeyDown);
|
|
55
|
-
return () => {
|
|
56
|
-
document.removeEventListener('mousedown', onPointerDown);
|
|
57
|
-
document.removeEventListener('keydown', onKeyDown);
|
|
58
|
-
};
|
|
59
|
-
}, [open, close]);
|
|
60
|
-
return { open, query, groups, filteredGroups, selection, shouldShowSearch, containerRef, setQuery, toggle, close, select };
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=useModelPicker.hooks.js.map
|