@workbench-kit/adapters 0.0.1-prototype.0 → 0.0.2-prototype.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.
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@workbench-kit/adapters",
3
- "version": "0.0.1-prototype.0",
3
+ "version": "0.0.2-prototype.0.1.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./src/index.ts",
8
8
  "./library": "./src/library.ts",
9
9
  "./runtime": "./src/runtime.ts",
10
- "./workspace": "./src/workspace.ts"
10
+ "./workspace": "./src/workspace.ts",
11
+ "./workbench-demo": "./src/workbench-demo.ts",
12
+ "./workbench-demo-config": "./src/workbench-demo-config.ts",
13
+ "./persistence": "./src/persistence.ts"
11
14
  },
12
15
  "files": [
13
16
  "src",
@@ -17,9 +20,9 @@
17
20
  "!src/**/*.stories.tsx"
18
21
  ],
19
22
  "dependencies": {
20
- "@workbench-kit/contracts": "0.0.1-prototype.0",
21
- "@workbench-kit/runtime": "0.0.1-prototype.0",
22
- "@workbench-kit/workspace": "0.0.1-prototype.0"
23
+ "@workbench-kit/contracts": "0.0.2-prototype.0.1.1",
24
+ "@workbench-kit/runtime": "0.0.2-prototype.0.1.1",
25
+ "@workbench-kit/workspace": "0.0.2-prototype.0.1.1"
23
26
  },
24
27
  "description": "Workbench Kit adapters for workspace repositories and runtime transports.",
25
28
  "publishConfig": {
@@ -29,7 +32,7 @@
29
32
  },
30
33
  "repository": {
31
34
  "type": "git",
32
- "url": "git+https://github.com/NewChoBo/newchobo-ui-package.git",
35
+ "url": "git+https://github.com/NewChoBo/workbench-kit.git",
33
36
  "directory": "packages/adapters"
34
37
  },
35
38
  "scripts": {
package/src/index.ts CHANGED
@@ -1,3 +1,8 @@
1
- export * from './runtime';
2
- export * from './library';
3
- export * from './workspace';
1
+ export * from './runtime';
2
+ export * from './library';
3
+ export * from './workspace';
4
+ export * from './workbench-demo';
5
+ export * from './widget-studio-assets';
6
+ export * from './widget-studio-asset-package';
7
+ export * from './workbench-demo-config';
8
+ export * from './persistence';
package/src/library.ts CHANGED
@@ -1,145 +1,145 @@
1
- import type { LibraryManifest, LibraryProvider } from '@workbench-kit/contracts';
2
- import {
3
- normalizeLibraryItemProviderSource,
4
- parseLibraryManifest,
5
- parseLibraryManifestText,
6
- } from '@workbench-kit/contracts';
7
-
8
- type ManifestTextLoader = () => Promise<string> | string;
9
-
10
- export interface LibraryManifestProviderOptions {
11
- displayName: string;
12
- id: string;
13
- loadManifestText: ManifestTextLoader;
14
- }
15
-
16
- export interface StaticLibraryManifestProviderOptions {
17
- displayName: string;
18
- id: string;
19
- manifestText: string;
20
- }
21
-
22
- export interface ObjectLibraryManifestProviderOptions {
23
- displayName: string;
24
- id: string;
25
- manifest: unknown;
26
- }
27
-
28
- export interface HttpLibraryManifestProviderOptions {
29
- displayName: string;
30
- id: string;
31
- manifestUrl: string;
32
- readText?: (url: string) => Promise<string>;
33
- }
34
-
35
- export function createLibraryManifestProvider({
36
- displayName,
37
- id,
38
- loadManifestText,
39
- }: LibraryManifestProviderOptions): LibraryProvider {
40
- return {
41
- displayName,
42
- id,
43
- async listItems() {
44
- const manifest = parseLibraryManifestSourceText(id, await loadManifestText());
45
- return manifest.items.map((item) =>
46
- normalizeLibraryItemProviderSource(item, {
47
- providerId: id,
48
- }),
49
- );
50
- },
51
- };
52
- }
53
-
54
- export function createStaticLibraryManifestProvider({
55
- displayName,
56
- id,
57
- manifestText,
58
- }: StaticLibraryManifestProviderOptions): LibraryProvider {
59
- return createLibraryManifestProvider({
60
- displayName,
61
- id,
62
- loadManifestText: () => manifestText,
63
- });
64
- }
65
-
66
- export function createLibraryManifestObjectProvider({
67
- displayName,
68
- id,
69
- manifest,
70
- }: ObjectLibraryManifestProviderOptions): LibraryProvider {
71
- return {
72
- displayName,
73
- id,
74
- async listItems() {
75
- const parsedManifest = parseLibraryManifestSourceData(id, manifest);
76
- return parsedManifest.items.map((item) =>
77
- normalizeLibraryItemProviderSource(item, {
78
- providerId: id,
79
- }),
80
- );
81
- },
82
- };
83
- }
84
-
85
- export function createLibraryManifestUrlProvider({
86
- displayName,
87
- id,
88
- manifestUrl,
89
- readText,
90
- }: HttpLibraryManifestProviderOptions): LibraryProvider {
91
- return createLibraryManifestProvider({
92
- displayName,
93
- id,
94
- loadManifestText: async () => {
95
- const loader = readText ?? defaultReadText;
96
- return loader(manifestUrl);
97
- },
98
- });
99
- }
100
-
101
- function parseLibraryManifestSourceText(
102
- providerId: string,
103
- rawManifestText: string,
104
- ): LibraryManifest {
105
- const manifest = parseLibraryManifestText(rawManifestText, `library-manifest:${providerId}`);
106
-
107
- return normalizeManifestSourceId(manifest, providerId);
108
- }
109
-
110
- function parseLibraryManifestSourceData(
111
- providerId: string,
112
- rawManifestData: unknown,
113
- ): LibraryManifest {
114
- const manifest = parseLibraryManifest(rawManifestData, `library-manifest:${providerId}`);
115
-
116
- return normalizeManifestSourceId(manifest, providerId);
117
- }
118
-
119
- function normalizeManifestSourceId(manifest: LibraryManifest, providerId: string): LibraryManifest {
120
- if (manifest.source.sourceId) {
121
- return manifest;
122
- }
123
-
124
- return {
125
- ...manifest,
126
- source: {
127
- ...manifest.source,
128
- sourceId: providerId,
129
- },
130
- };
131
- }
132
-
133
- async function defaultReadText(url: string): Promise<string> {
134
- if (typeof globalThis.fetch !== 'function') {
135
- throw new Error('fetch is not available in this environment');
136
- }
137
-
138
- const response = await globalThis.fetch(url);
139
- if (!response.ok) {
140
- const statusText = response.statusText ? ` ${response.statusText}` : '';
141
- throw new Error(`Failed to load library manifest from ${url}: ${response.status}${statusText}`);
142
- }
143
-
144
- return response.text();
145
- }
1
+ import type { LibraryManifest, LibraryProvider } from '@workbench-kit/contracts';
2
+ import {
3
+ normalizeLibraryItemProviderSource,
4
+ parseLibraryManifest,
5
+ parseLibraryManifestText,
6
+ } from '@workbench-kit/contracts';
7
+
8
+ type ManifestTextLoader = () => Promise<string> | string;
9
+
10
+ export interface LibraryManifestProviderOptions {
11
+ displayName: string;
12
+ id: string;
13
+ loadManifestText: ManifestTextLoader;
14
+ }
15
+
16
+ export interface StaticLibraryManifestProviderOptions {
17
+ displayName: string;
18
+ id: string;
19
+ manifestText: string;
20
+ }
21
+
22
+ export interface ObjectLibraryManifestProviderOptions {
23
+ displayName: string;
24
+ id: string;
25
+ manifest: unknown;
26
+ }
27
+
28
+ export interface HttpLibraryManifestProviderOptions {
29
+ displayName: string;
30
+ id: string;
31
+ manifestUrl: string;
32
+ readText?: (url: string) => Promise<string>;
33
+ }
34
+
35
+ export function createLibraryManifestProvider({
36
+ displayName,
37
+ id,
38
+ loadManifestText,
39
+ }: LibraryManifestProviderOptions): LibraryProvider {
40
+ return {
41
+ displayName,
42
+ id,
43
+ async listItems() {
44
+ const manifest = parseLibraryManifestSourceText(id, await loadManifestText());
45
+ return manifest.items.map((item) =>
46
+ normalizeLibraryItemProviderSource(item, {
47
+ providerId: id,
48
+ }),
49
+ );
50
+ },
51
+ };
52
+ }
53
+
54
+ export function createStaticLibraryManifestProvider({
55
+ displayName,
56
+ id,
57
+ manifestText,
58
+ }: StaticLibraryManifestProviderOptions): LibraryProvider {
59
+ return createLibraryManifestProvider({
60
+ displayName,
61
+ id,
62
+ loadManifestText: () => manifestText,
63
+ });
64
+ }
65
+
66
+ export function createLibraryManifestObjectProvider({
67
+ displayName,
68
+ id,
69
+ manifest,
70
+ }: ObjectLibraryManifestProviderOptions): LibraryProvider {
71
+ return {
72
+ displayName,
73
+ id,
74
+ async listItems() {
75
+ const parsedManifest = parseLibraryManifestSourceData(id, manifest);
76
+ return parsedManifest.items.map((item) =>
77
+ normalizeLibraryItemProviderSource(item, {
78
+ providerId: id,
79
+ }),
80
+ );
81
+ },
82
+ };
83
+ }
84
+
85
+ export function createLibraryManifestUrlProvider({
86
+ displayName,
87
+ id,
88
+ manifestUrl,
89
+ readText,
90
+ }: HttpLibraryManifestProviderOptions): LibraryProvider {
91
+ return createLibraryManifestProvider({
92
+ displayName,
93
+ id,
94
+ loadManifestText: async () => {
95
+ const loader = readText ?? defaultReadText;
96
+ return loader(manifestUrl);
97
+ },
98
+ });
99
+ }
100
+
101
+ function parseLibraryManifestSourceText(
102
+ providerId: string,
103
+ rawManifestText: string,
104
+ ): LibraryManifest {
105
+ const manifest = parseLibraryManifestText(rawManifestText, `library-manifest:${providerId}`);
106
+
107
+ return normalizeManifestSourceId(manifest, providerId);
108
+ }
109
+
110
+ function parseLibraryManifestSourceData(
111
+ providerId: string,
112
+ rawManifestData: unknown,
113
+ ): LibraryManifest {
114
+ const manifest = parseLibraryManifest(rawManifestData, `library-manifest:${providerId}`);
115
+
116
+ return normalizeManifestSourceId(manifest, providerId);
117
+ }
118
+
119
+ function normalizeManifestSourceId(manifest: LibraryManifest, providerId: string): LibraryManifest {
120
+ if (manifest.source.sourceId) {
121
+ return manifest;
122
+ }
123
+
124
+ return {
125
+ ...manifest,
126
+ source: {
127
+ ...manifest.source,
128
+ sourceId: providerId,
129
+ },
130
+ };
131
+ }
132
+
133
+ async function defaultReadText(url: string): Promise<string> {
134
+ if (typeof globalThis.fetch !== 'function') {
135
+ throw new Error('fetch is not available in this environment');
136
+ }
137
+
138
+ const response = await globalThis.fetch(url);
139
+ if (!response.ok) {
140
+ const statusText = response.statusText ? ` ${response.statusText}` : '';
141
+ throw new Error(`Failed to load library manifest from ${url}: ${response.status}${statusText}`);
142
+ }
143
+
144
+ return response.text();
145
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Optional persistence boundary for host apps that store workbench UI state
3
+ * outside the in-memory adapters used by Storybook fixtures.
4
+ */
5
+ export interface WorkbenchPersistenceAdapter {
6
+ loadState<T>(key: string): Promise<T | null>;
7
+ removeState(key: string): Promise<void>;
8
+ saveState<T>(key: string, value: T): Promise<void>;
9
+ }
10
+
11
+ export class InMemoryWorkbenchPersistenceAdapter implements WorkbenchPersistenceAdapter {
12
+ private readonly store = new Map<string, unknown>();
13
+
14
+ async loadState<T>(key: string): Promise<T | null> {
15
+ if (!this.store.has(key)) return null;
16
+ return structuredClone(this.store.get(key)) as T;
17
+ }
18
+
19
+ async removeState(key: string): Promise<void> {
20
+ this.store.delete(key);
21
+ }
22
+
23
+ async saveState<T>(key: string, value: T): Promise<void> {
24
+ this.store.set(key, structuredClone(value));
25
+ }
26
+ }
package/src/runtime.ts CHANGED
@@ -1,97 +1,97 @@
1
- import type { ChatStreamEvent, ChatTransport } from '@workbench-kit/contracts';
2
- import type { WorkbenchRuntimeEvent, MockWorkbenchRuntime } from '@workbench-kit/runtime';
3
-
4
- export interface RuntimeChatTransportOptions {
5
- runtime: MockWorkbenchRuntime;
6
- }
7
-
8
- export function createChatTransportFromRuntime({
9
- runtime,
10
- }: RuntimeChatTransportOptions): ChatTransport {
11
- return {
12
- cancel: () => runtime.cancel(),
13
- sendMessage: async (message, options) => {
14
- void options;
15
- const next = runtime.sendMessage(message);
16
- if (!next) return undefined;
17
-
18
- return {
19
- content: next.content,
20
- createdAt: next.createdAt,
21
- id: next.id,
22
- label: next.label,
23
- source: next.source,
24
- };
25
- },
26
- subscribe: (listener: (event: ChatStreamEvent) => void) =>
27
- runtime.subscribe((event: WorkbenchRuntimeEvent) => {
28
- if (event.type === 'message') {
29
- listener({
30
- message: {
31
- content: event.message.content,
32
- createdAt: event.message.createdAt,
33
- id: event.message.id,
34
- label: event.message.label,
35
- source: event.message.source,
36
- },
37
- type: 'message',
38
- });
39
- return;
40
- }
41
-
42
- if (event.type === 'message-delta') {
43
- listener({
44
- delta: event.delta,
45
- message: {
46
- content: event.message.content,
47
- createdAt: event.message.createdAt,
48
- id: event.message.id,
49
- label: event.message.label,
50
- source: event.message.source,
51
- },
52
- type: 'message-delta',
53
- });
54
- return;
55
- }
56
-
57
- if (event.type === 'status') {
58
- listener({
59
- previousStatus: event.previousStatus,
60
- status: event.status,
61
- type: 'status',
62
- });
63
- return;
64
- }
65
-
66
- if (event.patch.type === 'delete-file') {
67
- listener({
68
- patch: { path: event.patch.path, type: 'delete-file' },
69
- type: 'workspace-patch',
70
- });
71
- return;
72
- }
73
-
74
- listener({
75
- patch: {
76
- content: event.patch.content,
77
- mimeType: event.patch.mimeType,
78
- path: event.patch.path,
79
- source: event.patch.source,
80
- type: 'write-file',
81
- updatedAt: event.patch.updatedAt,
82
- },
83
- type: 'workspace-patch',
84
- });
85
- }),
86
- };
87
- }
88
-
89
- export function emitRuntimeWorkspacePatch({
90
- runtime,
91
- patch,
92
- }: {
93
- runtime: Pick<MockWorkbenchRuntime, 'emitWorkspacePatch'>;
94
- patch: Parameters<MockWorkbenchRuntime['emitWorkspacePatch']>[0];
95
- }) {
96
- runtime.emitWorkspacePatch(patch);
97
- }
1
+ import type { ChatStreamEvent, ChatTransport } from '@workbench-kit/contracts';
2
+ import type { WorkbenchRuntimeEvent, MockWorkbenchRuntime } from '@workbench-kit/runtime';
3
+
4
+ export interface RuntimeChatTransportOptions {
5
+ runtime: MockWorkbenchRuntime;
6
+ }
7
+
8
+ export function createChatTransportFromRuntime({
9
+ runtime,
10
+ }: RuntimeChatTransportOptions): ChatTransport {
11
+ return {
12
+ cancel: () => runtime.cancel(),
13
+ sendMessage: async (message, options) => {
14
+ void options;
15
+ const next = runtime.sendMessage(message);
16
+ if (!next) return undefined;
17
+
18
+ return {
19
+ content: next.content,
20
+ createdAt: next.createdAt,
21
+ id: next.id,
22
+ label: next.label,
23
+ source: next.source,
24
+ };
25
+ },
26
+ subscribe: (listener: (event: ChatStreamEvent) => void) =>
27
+ runtime.subscribe((event: WorkbenchRuntimeEvent) => {
28
+ if (event.type === 'message') {
29
+ listener({
30
+ message: {
31
+ content: event.message.content,
32
+ createdAt: event.message.createdAt,
33
+ id: event.message.id,
34
+ label: event.message.label,
35
+ source: event.message.source,
36
+ },
37
+ type: 'message',
38
+ });
39
+ return;
40
+ }
41
+
42
+ if (event.type === 'message-delta') {
43
+ listener({
44
+ delta: event.delta,
45
+ message: {
46
+ content: event.message.content,
47
+ createdAt: event.message.createdAt,
48
+ id: event.message.id,
49
+ label: event.message.label,
50
+ source: event.message.source,
51
+ },
52
+ type: 'message-delta',
53
+ });
54
+ return;
55
+ }
56
+
57
+ if (event.type === 'status') {
58
+ listener({
59
+ previousStatus: event.previousStatus,
60
+ status: event.status,
61
+ type: 'status',
62
+ });
63
+ return;
64
+ }
65
+
66
+ if (event.patch.type === 'delete-file') {
67
+ listener({
68
+ patch: { path: event.patch.path, type: 'delete-file' },
69
+ type: 'workspace-patch',
70
+ });
71
+ return;
72
+ }
73
+
74
+ listener({
75
+ patch: {
76
+ content: event.patch.content,
77
+ mimeType: event.patch.mimeType,
78
+ path: event.patch.path,
79
+ source: event.patch.source,
80
+ type: 'write-file',
81
+ updatedAt: event.patch.updatedAt,
82
+ },
83
+ type: 'workspace-patch',
84
+ });
85
+ }),
86
+ };
87
+ }
88
+
89
+ export function emitRuntimeWorkspacePatch({
90
+ runtime,
91
+ patch,
92
+ }: {
93
+ runtime: Pick<MockWorkbenchRuntime, 'emitWorkspacePatch'>;
94
+ patch: Parameters<MockWorkbenchRuntime['emitWorkspacePatch']>[0];
95
+ }) {
96
+ runtime.emitWorkspacePatch(patch);
97
+ }
@@ -0,0 +1,65 @@
1
+ import type { WorkspaceFile } from '@workbench-kit/workspace';
2
+
3
+ export const WIDGET_STUDIO_ASSETS_DIR = 'src/widgets/assets';
4
+ export const WIDGET_STUDIO_CUSTOM_ASSETS_DIR = 'src/widgets/assets/custom';
5
+
6
+ const MANIFEST_MIME = 'application/vnd.workbench-kit.widget-asset-manifest+json';
7
+ const CONTENT_MIME = 'application/vnd.workbench-kit.widget-asset-content+json';
8
+ const SCHEMA_MIME = 'application/vnd.workbench-kit.widget-asset-schema+json';
9
+
10
+ export interface WidgetStudioAssetPackageDefinition {
11
+ readonly slug: string;
12
+ readonly baseDir?: string | undefined;
13
+ readonly updatedAt: string;
14
+ readonly manifest: Record<string, unknown>;
15
+ readonly content: Record<string, unknown>;
16
+ readonly schema?: Record<string, unknown> | undefined;
17
+ }
18
+
19
+ function json(value: unknown): string {
20
+ return `${JSON.stringify(value, null, 2)}\n`;
21
+ }
22
+
23
+ export function createWidgetStudioAssetPackageFiles(
24
+ definition: WidgetStudioAssetPackageDefinition,
25
+ ): WorkspaceFile[] {
26
+ const baseDir = definition.baseDir ?? WIDGET_STUDIO_ASSETS_DIR;
27
+ const root = `${baseDir}/${definition.slug}`;
28
+ const files: WorkspaceFile[] = [
29
+ {
30
+ path: `${root}/manifest.json`,
31
+ mimeType: MANIFEST_MIME,
32
+ updatedAt: definition.updatedAt,
33
+ source: 'user',
34
+ content: json({
35
+ $schema: 'https://workbench-kit.dev/schemas/widget-asset-manifest.v1.jdw.schema.json',
36
+ ...definition.manifest,
37
+ }),
38
+ },
39
+ {
40
+ path: `${root}/content.json`,
41
+ mimeType: CONTENT_MIME,
42
+ updatedAt: definition.updatedAt,
43
+ source: 'user',
44
+ content: json(definition.content),
45
+ },
46
+ ];
47
+
48
+ if (definition.schema) {
49
+ files.push({
50
+ path: `${root}/schema.json`,
51
+ mimeType: SCHEMA_MIME,
52
+ updatedAt: definition.updatedAt,
53
+ source: 'user',
54
+ content: json(definition.schema),
55
+ });
56
+ }
57
+
58
+ return files;
59
+ }
60
+
61
+ export function flattenWidgetStudioAssetPackages(
62
+ packages: readonly WidgetStudioAssetPackageDefinition[],
63
+ ): WorkspaceFile[] {
64
+ return packages.flatMap((definition) => createWidgetStudioAssetPackageFiles(definition));
65
+ }