@jskit-ai/assistant-core 0.1.165 → 0.1.166

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 (63) hide show
  1. package/examples/conversation/App.vue +104 -0
  2. package/examples/conversation/README.md +42 -0
  3. package/examples/conversation/dist/assets/index-CSTXm6q3.css +1 -0
  4. package/examples/conversation/dist/assets/index-DGgOLzoo.js +30 -0
  5. package/examples/conversation/dist/index.html +4 -0
  6. package/examples/conversation/index.html +2 -0
  7. package/examples/conversation/main.js +9 -0
  8. package/examples/conversation/node_modules/.vite/deps/@mdi_js.js +7450 -0
  9. package/examples/conversation/node_modules/.vite/deps/@mdi_js.js.map +1 -0
  10. package/examples/conversation/node_modules/.vite/deps/VTooltip-jIxO6ULs.js +2311 -0
  11. package/examples/conversation/node_modules/.vite/deps/VTooltip-jIxO6ULs.js.map +1 -0
  12. package/examples/conversation/node_modules/.vite/deps/_metadata.json +70 -0
  13. package/examples/conversation/node_modules/.vite/deps/defineComponent-DK6LSjDW.js +710 -0
  14. package/examples/conversation/node_modules/.vite/deps/defineComponent-DK6LSjDW.js.map +1 -0
  15. package/examples/conversation/node_modules/.vite/deps/hotkey-parsing-DnoZxtbW.js +1214 -0
  16. package/examples/conversation/node_modules/.vite/deps/hotkey-parsing-DnoZxtbW.js.map +1 -0
  17. package/examples/conversation/node_modules/.vite/deps/icons-ze2hmg7j.js +98 -0
  18. package/examples/conversation/node_modules/.vite/deps/icons-ze2hmg7j.js.map +1 -0
  19. package/examples/conversation/node_modules/.vite/deps/package.json +3 -0
  20. package/examples/conversation/node_modules/.vite/deps/theme-D78LVcJg.js +1301 -0
  21. package/examples/conversation/node_modules/.vite/deps/theme-D78LVcJg.js.map +1 -0
  22. package/examples/conversation/node_modules/.vite/deps/vue.js +2 -0
  23. package/examples/conversation/node_modules/.vite/deps/vue.runtime.esm-bundler-YcakWsDn.js +8538 -0
  24. package/examples/conversation/node_modules/.vite/deps/vue.runtime.esm-bundler-YcakWsDn.js.map +1 -0
  25. package/examples/conversation/node_modules/.vite/deps/vuetify.js +413 -0
  26. package/examples/conversation/node_modules/.vite/deps/vuetify.js.map +1 -0
  27. package/examples/conversation/node_modules/.vite/deps/vuetify_components.js +25370 -0
  28. package/examples/conversation/node_modules/.vite/deps/vuetify_components.js.map +1 -0
  29. package/examples/conversation/node_modules/.vite/deps/vuetify_directives.js +132 -0
  30. package/examples/conversation/node_modules/.vite/deps/vuetify_directives.js.map +1 -0
  31. package/examples/conversation/node_modules/.vite/deps/vuetify_iconsets_mdi-svg.js +70 -0
  32. package/examples/conversation/node_modules/.vite/deps/vuetify_iconsets_mdi-svg.js.map +1 -0
  33. package/examples/conversation/package.json +22 -0
  34. package/examples/conversation/server.js +123 -0
  35. package/examples/conversation/vite.config.js +8 -0
  36. package/package.json +59 -7
  37. package/src/client/conversation/AssistantComposerActions.vue +43 -0
  38. package/src/client/conversation/AssistantConversationElement.vue +78 -0
  39. package/src/client/conversation/AssistantProgress.vue +88 -0
  40. package/src/client/conversation/AssistantPromptInput.vue +467 -0
  41. package/src/client/conversation/AssistantTranscript.vue +1361 -0
  42. package/src/client/conversation/LongTextInlineParts.vue +64 -0
  43. package/src/client/conversation/LongTextPreviewBlocks.vue +324 -0
  44. package/src/client/conversation/index.js +9 -0
  45. package/src/client/conversation/submitText.js +29 -0
  46. package/src/client/conversation/useScrollToBottom.js +151 -0
  47. package/src/server/conversation/codexClient.js +328 -0
  48. package/src/server/conversation/codexEvents.js +623 -0
  49. package/src/server/conversation/codexTurn.js +280 -0
  50. package/src/server/conversation/index.js +2 -0
  51. package/src/server/conversation/memoryStorage.js +76 -0
  52. package/src/server/conversation/normalize.js +7 -0
  53. package/src/server/conversation/openCodeClient.js +512 -0
  54. package/src/server/conversation/transcript.js +92 -0
  55. package/src/shared/conversation/answerChoiceSugar.js +191 -0
  56. package/src/shared/conversation/index.js +6 -0
  57. package/src/shared/conversation/longTextBlocks.js +403 -0
  58. package/src/shared/conversation/numberedQuestionSugar.js +295 -0
  59. package/src/shared/conversation/scrollFollowState.js +32 -0
  60. package/src/shared/conversation/thinkingText.js +13 -0
  61. package/src/shared/conversation/turns.js +30 -0
  62. package/src/testing/conversationStorageContract.js +35 -0
  63. package/test/conversation.test.js +57 -0
@@ -0,0 +1,104 @@
1
+ <template>
2
+ <v-app>
3
+ <main class="example">
4
+ <header><h1>Assistant</h1><span>{{ providerLabel }}</span></header>
5
+ <AssistantConversationElement
6
+ :adapter="adapter" :configuration="configuration"
7
+ :configuration-mode="configurationMode" :configuration-fields="fields"
8
+ >
9
+ <template #hints><p v-if="error" role="alert">{{ error }}</p></template>
10
+ </AssistantConversationElement>
11
+ </main>
12
+ </v-app>
13
+ </template>
14
+ <script setup>
15
+ import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
16
+ import { AssistantConversationElement } from "@jskit-ai/assistant-core/client/conversation";
17
+
18
+ const turns = ref([]), draft = ref(""), loading = ref(true), pending = ref(false), error = ref("");
19
+ const providerLabel = ref(""), configurationMode = ref("hidden"), configuration = ref({ tone: "concise" });
20
+ const fields = [{ name: "tone", label: "Answer style", items: ["concise", "detailed"] }];
21
+ let request = null;
22
+ let disposed = false;
23
+
24
+ async function reload() {
25
+ loading.value = true;
26
+ try {
27
+ const response = await fetch("/api/conversation");
28
+ if (!response.ok) throw new Error("Could not load the conversation.");
29
+ const data = await response.json();
30
+ if (disposed) return;
31
+ turns.value = data.turns;
32
+ providerLabel.value = data.providerLabel;
33
+ configurationMode.value = data.configurationMode;
34
+ configuration.value = data.configuration;
35
+ error.value = "";
36
+ } catch (failure) { if (!disposed) error.value = failure.message; }
37
+ finally { if (!disposed) loading.value = false; }
38
+ }
39
+
40
+ async function submit({ configuration: selectedConfiguration }) {
41
+ if (pending.value || !draft.value.trim()) return;
42
+ const text = draft.value;
43
+ pending.value = true;
44
+ error.value = "";
45
+ const controller = new AbortController();
46
+ request = controller;
47
+ try {
48
+ const response = await fetch("/api/messages", {
49
+ method: "POST", headers: { "Content-Type": "application/json" }, signal: controller.signal,
50
+ body: JSON.stringify({ messageId: crypto.randomUUID(), text, configuration: selectedConfiguration })
51
+ });
52
+ if (!response.ok) throw new Error((await response.json()).error || "Could not send.");
53
+ if (draft.value === text) draft.value = "";
54
+ const reader = response.body.getReader(), decoder = new TextDecoder();
55
+ let buffer = "";
56
+ try {
57
+ while (true) {
58
+ const { value, done } = await reader.read();
59
+ if (done) break;
60
+ buffer += decoder.decode(value, { stream: true });
61
+ let newline;
62
+ while ((newline = buffer.indexOf("\n")) >= 0) {
63
+ const event = JSON.parse(buffer.slice(0, newline));
64
+ buffer = buffer.slice(newline + 1);
65
+ if (disposed) continue;
66
+ if (event.type === "snapshot") turns.value = event.turns;
67
+ if (event.type === "error") error.value = event.message;
68
+ }
69
+ }
70
+ } finally { reader.releaseLock(); }
71
+ } catch (failure) { if (!disposed) error.value = failure.message; }
72
+ finally { if (!disposed) pending.value = false; request = null; }
73
+ }
74
+
75
+ async function stop() {
76
+ try {
77
+ const response = await fetch("/api/run", { method: "DELETE" });
78
+ if (!response.ok) throw new Error("Could not stop the assistant.");
79
+ } catch (failure) { error.value = failure.message; }
80
+ }
81
+
82
+ const adapter = reactive({
83
+ conversation: { turns, loading, visible: true, assistantLabel: "Assistant", scrollKey: "example" },
84
+ composer: {
85
+ draft, pending, disabled: pending, submitOnModifierEnter: true,
86
+ canSend: computed(() => !loading.value && !pending.value && Boolean(draft.value.trim())),
87
+ canStop: pending, placeholder: "Ask a question…"
88
+ },
89
+ actions: { reload, submit, stop,
90
+ setDraft: (value) => { draft.value = value; },
91
+ updateConfiguration: (value) => { configuration.value = value; }
92
+ }
93
+ });
94
+ onMounted(reload);
95
+ onBeforeUnmount(() => { disposed = true; request?.abort(); });
96
+ </script>
97
+ <style>
98
+ html, body, #app { margin: 0; height: 100%; }
99
+ .example { display: flex; flex-direction: column; height: 100dvh; max-width: 60rem; width: 100%; margin: auto; padding: 1rem; box-sizing: border-box; }
100
+ .example header { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; }
101
+ .example h1 { font-size: 1.4rem; }
102
+ .example header span { color: #666; font-size: .875rem; }
103
+ .example > .assistant-conversation { flex: 1; min-height: 0; }
104
+ </style>
@@ -0,0 +1,42 @@
1
+ # Standalone conversation example
2
+
3
+ Copy this directory into a new application, then run:
4
+
5
+ ```sh
6
+ npm install
7
+ npm run server
8
+ ```
9
+
10
+ In a second terminal:
11
+
12
+ ```sh
13
+ npm run dev
14
+ ```
15
+
16
+ Open http://127.0.0.1:5175. `npm run build` builds the client. The default demo
17
+ provider streams a labelled example response and needs no credentials.
18
+
19
+ Optional server environment:
20
+
21
+ | Variable | Meaning |
22
+ | --- | --- |
23
+ | `ASSISTANT_API_KEY` | Enables the existing JSKIT API-model client; server only. |
24
+ | `ASSISTANT_PROVIDER` | `openai`, `deepseek`, or `anthropic`; default `openai`. |
25
+ | `ASSISTANT_MODEL` | Model available to that provider/account. |
26
+ | `ASSISTANT_CONFIGURATION_MODE` | `hidden`, `readonly`, or `editable`; default `editable`. |
27
+ | `ASSISTANT_STORAGE_MODULE` | Path to an app module exporting async `createStorage()`. Otherwise history is held in memory and disappears on restart. |
28
+
29
+ This is a single-user local template with one conversation. A hosted app must
30
+ derive storage scope from authenticated actor/workspace/conversation ownership,
31
+ authorize every route and attachment, and retain provider-delivery evidence for
32
+ reconciliation after crashes. The example never executes the same message ID
33
+ twice. Retrying a request whose provider delivery is uncertain requires the app
34
+ to resolve that uncertainty first.
35
+
36
+ The server owns model choice, credentials and allowed configuration. Hidden or
37
+ read-only configuration always uses the server's fixed settings, regardless of
38
+ the submitted object. Replace the storage adapter to use your application's
39
+ database or files; the UI has no storage assumptions.
40
+
41
+ See the JSKIT guide **Embeddable assistant conversations** for the complete
42
+ client, storage and provider contracts and reusable storage-adapter checks.