pith-ui 0.1.1 → 0.2.0-app.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.
Files changed (140) hide show
  1. package/AI.md +33 -8
  2. package/API.md +424 -268
  3. package/APP-API.md +2019 -0
  4. package/APP.md +137 -0
  5. package/README.md +37 -4
  6. package/dist/app/files.d.ts +68 -0
  7. package/dist/app/files.d.ts.map +1 -0
  8. package/dist/app/files.js +177 -0
  9. package/dist/app/files.js.map +1 -0
  10. package/dist/app/index.d.ts +57 -0
  11. package/dist/app/index.d.ts.map +1 -0
  12. package/dist/app/index.js +300 -0
  13. package/dist/app/index.js.map +1 -0
  14. package/dist/app/internal.d.ts +31 -0
  15. package/dist/app/internal.d.ts.map +1 -0
  16. package/dist/app/internal.js +2 -0
  17. package/dist/app/internal.js.map +1 -0
  18. package/dist/app/resources.d.ts +89 -0
  19. package/dist/app/resources.d.ts.map +1 -0
  20. package/dist/app/resources.js +190 -0
  21. package/dist/app/resources.js.map +1 -0
  22. package/dist/app/session.d.ts +14 -0
  23. package/dist/app/session.d.ts.map +1 -0
  24. package/dist/app/session.js +12 -0
  25. package/dist/app/session.js.map +1 -0
  26. package/dist/app/settings.d.ts +109 -0
  27. package/dist/app/settings.d.ts.map +1 -0
  28. package/dist/app/settings.js +279 -0
  29. package/dist/app/settings.js.map +1 -0
  30. package/dist/app/workspace.d.ts +228 -0
  31. package/dist/app/workspace.d.ts.map +1 -0
  32. package/dist/app/workspace.js +402 -0
  33. package/dist/app/workspace.js.map +1 -0
  34. package/dist/composer.d.ts.map +1 -1
  35. package/dist/composer.js +37 -27
  36. package/dist/composer.js.map +1 -1
  37. package/dist/content/conversation-reader.d.ts.map +1 -1
  38. package/dist/content/conversation-reader.js +8 -1
  39. package/dist/content/conversation-reader.js.map +1 -1
  40. package/dist/content/conversation-view.d.ts.map +1 -1
  41. package/dist/content/conversation-view.js +34 -8
  42. package/dist/content/conversation-view.js.map +1 -1
  43. package/dist/content/image-viewer.d.ts.map +1 -1
  44. package/dist/content/image-viewer.js +11 -3
  45. package/dist/content/image-viewer.js.map +1 -1
  46. package/dist/content/paged-preview.d.ts +1 -1
  47. package/dist/content/paged-preview.d.ts.map +1 -1
  48. package/dist/content/paged-preview.js +4 -2
  49. package/dist/content/paged-preview.js.map +1 -1
  50. package/dist/content/views.d.ts +3 -0
  51. package/dist/content/views.d.ts.map +1 -1
  52. package/dist/content/views.js +110 -41
  53. package/dist/content/views.js.map +1 -1
  54. package/dist/content/welcome.d.ts.map +1 -1
  55. package/dist/content/welcome.js +5 -2
  56. package/dist/content/welcome.js.map +1 -1
  57. package/dist/dom.js +1 -1
  58. package/dist/dom.js.map +1 -1
  59. package/dist/files/panels.d.ts +2 -0
  60. package/dist/files/panels.d.ts.map +1 -1
  61. package/dist/files/panels.js +202 -128
  62. package/dist/files/panels.js.map +1 -1
  63. package/dist/files/systems.d.ts.map +1 -1
  64. package/dist/files/systems.js +37 -64
  65. package/dist/files/systems.js.map +1 -1
  66. package/dist/forms/actions.d.ts +24 -2
  67. package/dist/forms/actions.d.ts.map +1 -1
  68. package/dist/forms/actions.js +54 -25
  69. package/dist/forms/actions.js.map +1 -1
  70. package/dist/forms/custom-connection.d.ts.map +1 -1
  71. package/dist/forms/custom-connection.js +3 -2
  72. package/dist/forms/custom-connection.js.map +1 -1
  73. package/dist/forms/history.d.ts +1 -1
  74. package/dist/forms/history.d.ts.map +1 -1
  75. package/dist/forms/history.js +78 -15
  76. package/dist/forms/history.js.map +1 -1
  77. package/dist/forms/identity.d.ts.map +1 -1
  78. package/dist/forms/identity.js +9 -25
  79. package/dist/forms/identity.js.map +1 -1
  80. package/dist/forms/model-editor.js +3 -3
  81. package/dist/forms/model-editor.js.map +1 -1
  82. package/dist/forms/panels.d.ts +9 -2
  83. package/dist/forms/panels.d.ts.map +1 -1
  84. package/dist/forms/panels.js +79 -88
  85. package/dist/forms/panels.js.map +1 -1
  86. package/dist/forms/provider-login.d.ts.map +1 -1
  87. package/dist/forms/provider-login.js +20 -36
  88. package/dist/forms/provider-login.js.map +1 -1
  89. package/dist/forms/resource-editor.js +5 -4
  90. package/dist/forms/resource-editor.js.map +1 -1
  91. package/dist/foundations.d.ts +1 -1
  92. package/dist/foundations.d.ts.map +1 -1
  93. package/dist/foundations.js +22 -38
  94. package/dist/foundations.js.map +1 -1
  95. package/dist/navigation/context-menu.d.ts +7 -1
  96. package/dist/navigation/context-menu.d.ts.map +1 -1
  97. package/dist/navigation/context-menu.js +60 -57
  98. package/dist/navigation/context-menu.js.map +1 -1
  99. package/dist/navigation/navigation.d.ts +13 -0
  100. package/dist/navigation/navigation.d.ts.map +1 -1
  101. package/dist/navigation/navigation.js +96 -130
  102. package/dist/navigation/navigation.js.map +1 -1
  103. package/dist/operation.d.ts +12 -0
  104. package/dist/operation.d.ts.map +1 -0
  105. package/dist/operation.js +49 -0
  106. package/dist/operation.js.map +1 -0
  107. package/dist/primitives.d.ts +8 -1
  108. package/dist/primitives.d.ts.map +1 -1
  109. package/dist/primitives.js +114 -143
  110. package/dist/primitives.js.map +1 -1
  111. package/dist/reconcile.d.ts +11 -0
  112. package/dist/reconcile.d.ts.map +1 -0
  113. package/dist/reconcile.js +36 -0
  114. package/dist/reconcile.js.map +1 -0
  115. package/dist/select.d.ts +14 -0
  116. package/dist/select.d.ts.map +1 -0
  117. package/dist/select.js +304 -0
  118. package/dist/select.js.map +1 -0
  119. package/dist/styles.css +439 -370
  120. package/dist/surface.d.ts +31 -0
  121. package/dist/surface.d.ts.map +1 -1
  122. package/dist/surface.js +193 -3
  123. package/dist/surface.js.map +1 -1
  124. package/dist/tasks/approval.d.ts.map +1 -1
  125. package/dist/tasks/approval.js +83 -45
  126. package/dist/tasks/approval.js.map +1 -1
  127. package/dist/tasks/permission-element.d.ts +3 -0
  128. package/dist/tasks/permission-element.d.ts.map +1 -0
  129. package/dist/tasks/permission-element.js +10 -0
  130. package/dist/tasks/permission-element.js.map +1 -0
  131. package/dist/tasks/permission.d.ts.map +1 -1
  132. package/dist/tasks/permission.js +37 -18
  133. package/dist/tasks/permission.js.map +1 -1
  134. package/dist/tasks/runtime.d.ts.map +1 -1
  135. package/dist/tasks/runtime.js +32 -15
  136. package/dist/tasks/runtime.js.map +1 -1
  137. package/dist/workspace.d.ts.map +1 -1
  138. package/dist/workspace.js +93 -40
  139. package/dist/workspace.js.map +1 -1
  140. package/package.json +42 -8
@@ -1,39 +1,68 @@
1
- import { escape } from '../dom.js';
1
+ import { escape, setText } from '../dom.js';
2
2
  import { adoptAction } from '../foundations.js';
3
+ import { reconcileKeyed } from '../reconcile.js';
3
4
  export function providerActionsMarkup(provider) { return `<div class="pui-feature-toolbar">${provider.oauth ? `<button type="button" class="pui-secondary-button" data-sdk="${provider.signedIn ? 'logout' : 'login'}" data-id="${escape(provider.id)}">${provider.signedIn ? 'Sign out' : 'Sign in with provider'}</button>` : ''}${provider.custom ? `<button type="button" class="pui-secondary-button" data-sdk="custom" data-id="${escape(provider.id)}">Edit models and prices</button><button type="button" class="pui-secondary-button pui-destructive-button" data-sdk="remove-connection" data-id="${escape(provider.id)}">Remove connection</button>` : ''}</div>`; }
5
+ const resourceCommand = (kind, name) => kind === 'skill' ? `/skill:${name} ` : `/${name} `;
4
6
  export function resourceActionsMarkup(kind, resource, workspaceId) {
5
- const command = kind === 'skill' ? `/skill:${resource.name} ` : `/${resource.name} `;
6
- return `<div class="pui-file-actions">${kind !== 'instructions' ? `<button class="pui-secondary-button" data-sdk="use-resource" data-command="${escape(command)}">Use</button>` : ''}<button class="pui-secondary-button" data-sdk="resource" data-resource-workspace="${escape(workspaceId)}" data-kind="${kind}" data-path="${escape(resource.path)}">View / edit</button></div>`;
7
+ return `<div class="pui-file-actions">${kind !== 'instructions' ? `<button type="button" class="pui-secondary-button" data-sdk="use-resource" data-command="${escape(resourceCommand(kind, resource.name))}">Use</button>` : ''}<button type="button" class="pui-secondary-button" data-sdk="resource" data-resource-workspace="${escape(workspaceId)}" data-kind="${escape(kind)}" data-path="${escape(resource.path)}">View / edit</button></div>`;
7
8
  }
8
- function actions(initial, markup, options) {
9
+ function actions(initial, className, describe, options, onAction) {
9
10
  const element = document.createElement('div');
10
11
  element.className = 'pui-feature-actions';
11
- let destroyed = false, signature = '';
12
- let handles = [];
12
+ const toolbar = document.createElement('div');
13
+ toolbar.className = className;
14
+ element.append(toolbar);
15
+ const rows = new Map();
16
+ let destroyed = false;
17
+ const release = (row) => { if (row.stop)
18
+ row.element.removeEventListener('click', row.stop); row.handle.destroy(); };
13
19
  const update = (state) => {
14
20
  if (destroyed)
15
21
  return;
16
- const next = markup(state);
17
- if (next === signature)
18
- return;
19
- signature = next;
20
- handles.forEach(handle => handle.destroy());
21
- handles = [];
22
- element.innerHTML = next;
23
- if (options.onAction)
24
- for (const button of element.querySelectorAll('[data-sdk]')) {
25
- // Stop before the owned callback runs: it may synchronously replace or
26
- // destroy this block, removing listeners further up the bubbling path.
27
- const stopDelegation = (event) => event.stopPropagation();
28
- button.addEventListener('click', stopDelegation);
29
- const handle = adoptAction(button, { onAction: () => options.onAction(button.dataset.sdk, button.dataset), onError: options.onError });
30
- handles.push({ ...handle, destroy() { button.removeEventListener('click', stopDelegation); handle.destroy(); } });
31
- }
22
+ reconcileKeyed(toolbar, rows, describe(state), { key: view => view.key, element: row => row.element, create(view) {
23
+ const button = document.createElement('button');
24
+ button.type = 'button';
25
+ const stop = onAction || options.onAction ? (event) => event.stopPropagation() : undefined;
26
+ // Stop before the callback: it can synchronously destroy this owner.
27
+ if (stop)
28
+ button.addEventListener('click', stop);
29
+ const row = { element: button, view, handle: adoptAction(button, { onAction: stop ? () => onAction ? onAction(row.view.action, row.view.target) : options.onAction(row.view.action, button.dataset) : undefined, onError: options.onError }), stop };
30
+ return row;
31
+ }, update(row, view) { row.view = view; row.element.className = `pui-secondary-button${view.destructive ? ' pui-destructive-button' : ''}`; setText(row.element, view.label); for (const [name, value] of Object.entries(view.dataset))
32
+ row.element.dataset[name] = value; if (view.disabled !== undefined)
33
+ row.handle.update({ disabled: view.disabled }); }, destroy: release });
32
34
  };
33
35
  update(initial);
34
36
  return { element, update, destroy() { if (destroyed)
35
- return; destroyed = true; handles.forEach(handle => handle.destroy()); handles = []; element.remove(); } };
37
+ return; destroyed = true; for (const row of rows.values())
38
+ release(row); rows.clear(); element.remove(); } };
39
+ }
40
+ export function createProviderActions(state, options = {}) {
41
+ return actions(state, 'pui-feature-toolbar', value => {
42
+ const target = Object.freeze({ id: value.id });
43
+ const result = [];
44
+ const add = (action, label, destructive = false) => result.push({ key: JSON.stringify([value.id, action]), action, label, target, dataset: { sdk: action, id: value.id }, destructive, disabled: !!value.disabled });
45
+ if (value.oauth)
46
+ add(value.signedIn ? 'logout' : 'login', value.signedIn ? 'Sign out' : 'Sign in with provider');
47
+ if (value.custom) {
48
+ add('custom', 'Edit models and prices');
49
+ add('remove-connection', 'Remove connection', true);
50
+ }
51
+ return result;
52
+ }, options, options.onProviderAction);
53
+ }
54
+ export function createResourceActions(state, options = {}) {
55
+ return actions(state, 'pui-file-actions', value => {
56
+ const resource = Object.freeze({ ...value.resource });
57
+ const identity = JSON.stringify([value.workspaceId, value.kind, resource.name, resource.path]);
58
+ const target = Object.freeze({ workspaceId: value.workspaceId, kind: value.kind, resource });
59
+ const result = [];
60
+ if (value.kind !== 'instructions') {
61
+ const command = resourceCommand(value.kind, resource.name);
62
+ result.push({ key: identity + 'use-resource', action: 'use-resource', label: 'Use', target: Object.freeze({ ...target, command }), dataset: { sdk: 'use-resource', command } });
63
+ }
64
+ result.push({ key: identity + 'resource', action: 'resource', label: 'View / edit', target, dataset: { sdk: 'resource', resourceWorkspace: value.workspaceId, kind: value.kind, path: resource.path } });
65
+ return result;
66
+ }, options, options.onResourceAction);
36
67
  }
37
- export function createProviderActions(state, options = {}) { return actions(state, providerActionsMarkup, options); }
38
- export function createResourceActions(state, options = {}) { return actions(state, (state) => resourceActionsMarkup(state.kind, state.resource, state.workspaceId), options); }
39
68
  //# sourceMappingURL=actions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/forms/actions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { UIBlock, UIAction } from '../core.js';\nimport { escape } from '../dom.js';\nimport {adoptAction, type ActionController} from '../foundations.js';\nexport interface ProviderActionsState {id: string; oauth: boolean; signedIn: boolean; custom: boolean}\nexport interface ResourceActionsState {kind: string; resource: {name: string; path: string}; workspaceId: string}\nexport function providerActionsMarkup(provider: ProviderActionsState): string {return `<div class=\"pui-feature-toolbar\">${provider.oauth ? `<button type=\"button\" class=\"pui-secondary-button\" data-sdk=\"${provider.signedIn ? 'logout' : 'login'}\" data-id=\"${escape(provider.id)}\">${provider.signedIn ? 'Sign out' : 'Sign in with provider'}</button>` : ''}${provider.custom ? `<button type=\"button\" class=\"pui-secondary-button\" data-sdk=\"custom\" data-id=\"${escape(provider.id)}\">Edit models and prices</button><button type=\"button\" class=\"pui-secondary-button pui-destructive-button\" data-sdk=\"remove-connection\" data-id=\"${escape(provider.id)}\">Remove connection</button>` : ''}</div>`;}\nexport function resourceActionsMarkup(kind: string, resource: {name: string; path: string}, workspaceId: string): string {\n const command = kind === 'skill' ? `/skill:${resource.name} ` : `/${resource.name} `;\n return `<div class=\"pui-file-actions\">${kind !== 'instructions' ? `<button class=\"pui-secondary-button\" data-sdk=\"use-resource\" data-command=\"${escape(command)}\">Use</button>` : ''}<button class=\"pui-secondary-button\" data-sdk=\"resource\" data-resource-workspace=\"${escape(workspaceId)}\" data-kind=\"${kind}\" data-path=\"${escape(resource.path)}\">View / edit</button></div>`;\n}\nexport interface FeatureActionOptions {onAction?: (action: string, target: DOMStringMap) => ReturnType<UIAction>; onError?: (message: string) => void}\nfunction actions<State>(initial: State, markup: (state: State) => string, options: FeatureActionOptions): UIBlock<State> {\n const element = document.createElement('div'); element.className = 'pui-feature-actions'; let destroyed = false, signature = ''; let handles: ActionController[] = [];\n const update = (state: Readonly<State>) => {\n if (destroyed) return; const next = markup(state); if (next === signature) return; signature = next;\n handles.forEach(handle => handle.destroy()); handles = []; element.innerHTML = next;\n if (options.onAction) for (const button of element.querySelectorAll<HTMLButtonElement>('[data-sdk]')) {\n // Stop before the owned callback runs: it may synchronously replace or\n // destroy this block, removing listeners further up the bubbling path.\n const stopDelegation = (event: Event) => event.stopPropagation();\n button.addEventListener('click',stopDelegation);\n const handle = adoptAction(button, {onAction: () => options.onAction!(button.dataset.sdk!, button.dataset), onError: options.onError});\n handles.push({...handle,destroy() {button.removeEventListener('click',stopDelegation);handle.destroy();}});\n }\n }; update(initial);\n return {element, update, destroy() {if (destroyed) return; destroyed = true; handles.forEach(handle => handle.destroy()); handles = []; element.remove();}};\n}\nexport function createProviderActions(state: ProviderActionsState, options: FeatureActionOptions = {}): UIBlock<ProviderActionsState> {return actions(state, providerActionsMarkup, options);}\nexport function createResourceActions(state: ResourceActionsState, options: FeatureActionOptions = {}): UIBlock<ResourceActionsState> {return actions(state, (state) => resourceActionsMarkup(state.kind, state.resource, state.workspaceId), options);}\n"]}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/forms/actions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { UIBlock, UIAction } from '../core.js';\nimport { escape, setText } from '../dom.js';\nimport {adoptAction, type ActionController} from '../foundations.js';\nimport {reconcileKeyed} from '../reconcile.js';\nexport interface ProviderActionsState {id: string; oauth: boolean; signedIn: boolean; custom: boolean; disabled?: boolean}\nexport type ResourceKind = 'instructions' | 'skill' | 'template';\nexport interface ResourceActionsState {kind: string; resource: {name: string; path: string}; workspaceId: string}\nexport type ProviderAction = 'login' | 'logout' | 'custom' | 'remove-connection';\nexport type ResourceAction = 'use-resource' | 'resource';\nexport interface ProviderActionTarget {readonly id: string}\nexport interface ResourceActionTarget {readonly workspaceId: string; readonly kind: string; readonly resource: {readonly name: string; readonly path: string}; readonly command?: string}\nexport function providerActionsMarkup(provider: ProviderActionsState): string {return `<div class=\"pui-feature-toolbar\">${provider.oauth ? `<button type=\"button\" class=\"pui-secondary-button\" data-sdk=\"${provider.signedIn ? 'logout' : 'login'}\" data-id=\"${escape(provider.id)}\">${provider.signedIn ? 'Sign out' : 'Sign in with provider'}</button>` : ''}${provider.custom ? `<button type=\"button\" class=\"pui-secondary-button\" data-sdk=\"custom\" data-id=\"${escape(provider.id)}\">Edit models and prices</button><button type=\"button\" class=\"pui-secondary-button pui-destructive-button\" data-sdk=\"remove-connection\" data-id=\"${escape(provider.id)}\">Remove connection</button>` : ''}</div>`;}\nconst resourceCommand = (kind: string, name: string) => kind === 'skill' ? `/skill:${name} ` : `/${name} `;\nexport function resourceActionsMarkup(kind: string, resource: {name: string; path: string}, workspaceId: string): string {\n return `<div class=\"pui-file-actions\">${kind !== 'instructions' ? `<button type=\"button\" class=\"pui-secondary-button\" data-sdk=\"use-resource\" data-command=\"${escape(resourceCommand(kind,resource.name))}\">Use</button>` : ''}<button type=\"button\" class=\"pui-secondary-button\" data-sdk=\"resource\" data-resource-workspace=\"${escape(workspaceId)}\" data-kind=\"${escape(kind)}\" data-path=\"${escape(resource.path)}\">View / edit</button></div>`;\n}\nexport interface FeatureActionOptions {onAction?: (action: string, target: DOMStringMap) => ReturnType<UIAction>; onError?: (message: string) => void}\nexport interface ProviderActionOptions extends FeatureActionOptions {onProviderAction?: (action: ProviderAction, target: ProviderActionTarget) => ReturnType<UIAction>}\nexport interface ResourceActionOptions extends FeatureActionOptions {onResourceAction?: (action: ResourceAction, target: ResourceActionTarget) => ReturnType<UIAction>}\ntype ActionView<Action, Target> = {key: string; action: Action; label: string; target: Target; dataset: Record<string,string>; destructive?: boolean; disabled?: boolean};\nfunction actions<State, Action extends string, Target>(initial: State, className: string, describe: (state: Readonly<State>) => readonly ActionView<Action,Target>[], options: FeatureActionOptions, onAction?: (action: Action,target: Target) => ReturnType<UIAction>): UIBlock<State> {\n const element = document.createElement('div'); element.className = 'pui-feature-actions'; const toolbar = document.createElement('div'); toolbar.className = className; element.append(toolbar);\n type Row = {element: HTMLButtonElement; view: ActionView<Action,Target>; handle: ActionController; stop?: (event: Event) => void};\n const rows = new Map<string,Row>(); let destroyed = false;\n const release = (row: Row) => {if (row.stop) row.element.removeEventListener('click',row.stop); row.handle.destroy();};\n const update = (state: Readonly<State>) => {\n if (destroyed) return;\n reconcileKeyed(toolbar,rows,describe(state),{key:view=>view.key,element:row=>row.element,create(view) {\n const button = document.createElement('button'); button.type = 'button';\n const stop = onAction || options.onAction ? (event: Event) => event.stopPropagation() : undefined;\n // Stop before the callback: it can synchronously destroy this owner.\n if (stop) button.addEventListener('click',stop);\n const row: Row = {element:button,view,handle:adoptAction(button,{onAction:stop ? () => onAction ? onAction(row.view.action,row.view.target) : options.onAction!(row.view.action,button.dataset) : undefined,onError:options.onError}),stop}; return row;\n },update(row,view) {row.view = view; row.element.className = `pui-secondary-button${view.destructive ? ' pui-destructive-button' : ''}`; setText(row.element,view.label); for (const [name,value] of Object.entries(view.dataset)) row.element.dataset[name] = value; if (view.disabled !== undefined) row.handle.update({disabled:view.disabled});},destroy:release});\n }; update(initial);\n return {element, update, destroy() {if (destroyed) return; destroyed = true; for (const row of rows.values()) release(row); rows.clear(); element.remove();}};\n}\nexport function createProviderActions(state: ProviderActionsState, options: ProviderActionOptions = {}): UIBlock<ProviderActionsState> {\n return actions(state,'pui-feature-toolbar',value => {\n const target = Object.freeze({id:value.id}); const result: ActionView<ProviderAction,ProviderActionTarget>[] = [];\n const add = (action: ProviderAction,label: string,destructive = false) => result.push({key:JSON.stringify([value.id,action]),action,label,target,dataset:{sdk:action,id:value.id},destructive,disabled:!!value.disabled});\n if (value.oauth) add(value.signedIn ? 'logout' : 'login',value.signedIn ? 'Sign out' : 'Sign in with provider');\n if (value.custom) {add('custom','Edit models and prices'); add('remove-connection','Remove connection',true);} return result;\n },options,options.onProviderAction);\n}\nexport function createResourceActions(state: ResourceActionsState, options: ResourceActionOptions = {}): UIBlock<ResourceActionsState> {\n return actions(state,'pui-file-actions',value => {\n const resource = Object.freeze({...value.resource}); const identity = JSON.stringify([value.workspaceId,value.kind,resource.name,resource.path]);\n const target = Object.freeze({workspaceId:value.workspaceId,kind:value.kind,resource}); const result: ActionView<ResourceAction,ResourceActionTarget>[] = [];\n if (value.kind !== 'instructions') {const command = resourceCommand(value.kind,resource.name); result.push({key:identity+'use-resource',action:'use-resource',label:'Use',target:Object.freeze({...target,command}),dataset:{sdk:'use-resource',command}});}\n result.push({key:identity+'resource',action:'resource',label:'View / edit',target,dataset:{sdk:'resource',resourceWorkspace:value.workspaceId,kind:value.kind,path:resource.path}}); return result;\n },options,options.onResourceAction);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"custom-connection.d.ts","sourceRoot":"","sources":["../../src/forms/custom-connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,OAAO,EAAC,MAAM,YAAY,CAAC;AAGrD,MAAM,WAAW,gBAAgB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC;AACxO,MAAM,WAAW,qBAAqB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAC;AAC9K,MAAM,WAAW,gBAAgB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC;AAChP,MAAM,WAAW,qBAAqB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAAC;AAG/H,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAC;AAClG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG;IAAC,IAAI,IAAI,gBAAgB,CAAC;IAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;CAAC,CAe3K;AACD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,GAAE;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;CAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,GAAG;IAAC,IAAI,IAAI,qBAAqB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAC,CAcjS"}
1
+ {"version":3,"file":"custom-connection.d.ts","sourceRoot":"","sources":["../../src/forms/custom-connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,OAAO,EAAC,MAAM,YAAY,CAAC;AAGrD,MAAM,WAAW,gBAAgB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC;AACxO,MAAM,WAAW,qBAAqB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAC;AAC9K,MAAM,WAAW,gBAAgB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC;AAChP,MAAM,WAAW,qBAAqB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAAC;AAG/H,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAC;AAClG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG;IAAC,IAAI,IAAI,gBAAgB,CAAC;IAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;CAAC,CAe3K;AACD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,GAAE;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;CAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,GAAG;IAAC,IAAI,IAAI,qBAAqB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAC,CAejS"}
@@ -40,7 +40,7 @@ export function createCustomModelRow(model, index = 0) {
40
40
  export function createCustomConnectionEditor(state, options = {}) {
41
41
  const element = document.createElement('div');
42
42
  element.className = 'pui-custom-connection-editor';
43
- element.innerHTML = `<p class="pui-modal-description">Give this endpoint its own name. It can coexist with official providers and other compatible endpoints.</p><form id="custom-form"><label class="pui-field-label">Connection name<input id="custom-name" required value="${escape(state.name)}" /></label><label class="pui-field-label">API base URL<input id="custom-url" type="url" required value="${escape(state.baseUrl)}" placeholder="https://example.com/v1" /></label><label class="pui-field-label">API protocol<select id="custom-api" class="pui-feature-select">${protocols.map((p) => `<option ${state.api === p ? 'selected' : ''}>${p}</option>`).join('')}</select></label><label class="pui-field-label">API key<input id="custom-key" type="password" autocomplete="new-password" placeholder="${state.editing ? 'Leave blank to keep the key at the same endpoint' : 'API key (optional for local endpoints)'}" /></label><div id="custom-models"></div><button type="button" class="pui-secondary-button" id="add-custom-model">Add model</button><p class="pui-field-hint">Limits and capabilities are provided by you. Prices are USD per million tokens. Fill all four rates (0 for free/unused), or leave all four blank for unknown prices.</p><p class="pui-form-error" data-custom-error role="alert"></p><div class="pui-modal-footer"><button type="button" class="pui-secondary-button" data-close="sdk-dialog">Cancel</button><button class="pui-primary-button" type="submit">Save connection</button></div></form>`;
43
+ element.innerHTML = `<p class="pui-modal-description">Give this endpoint its own name. It can coexist with official providers and other compatible endpoints.</p><form id="custom-form"><label class="pui-field-label">Connection name<input id="custom-name" required value="${escape(state.name)}" /></label><label class="pui-field-label">API base URL<input id="custom-url" type="url" required value="${escape(state.baseUrl)}" placeholder="https://example.com/v1" /></label><label class="pui-field-label">API protocol<select id="custom-api" class="pui-feature-select">${protocols.map((p) => `<option ${state.api === p ? 'selected' : ''}>${p}</option>`).join('')}</select></label><label class="pui-field-label">API key<input id="custom-key" type="password" autocomplete="new-password" placeholder="${state.editing ? 'Leave blank to keep the key at the same endpoint' : 'API key (optional for local endpoints)'}" /></label><div id="custom-models"></div><button type="button" class="pui-secondary-button" id="add-custom-model">Add model</button><p class="pui-field-hint">Limits and capabilities are provided by you. Prices are USD per million tokens. Fill all four rates (0 for free/unused), or leave all four blank for unknown prices.</p><p class="pui-form-error" data-custom-error role="alert"></p><div class="pui-modal-footer"><button type="button" class="pui-secondary-button" data-pui-close data-close="sdk-dialog">Cancel</button><button class="pui-primary-button" type="submit">Save connection</button></div></form>`;
44
44
  const prefix = options.idPrefix ?? uniqueId('pui-custom') + '-';
45
45
  scopeIds(element, prefix);
46
46
  const $ = (id) => localField(element, prefix + id);
@@ -49,6 +49,7 @@ export function createCustomConnectionEditor(state, options = {}) {
49
49
  let nextIndex = 0, destroyed = false, pending = false;
50
50
  const abort = new AbortController();
51
51
  let current = state;
52
+ parts.control($('custom-api'));
52
53
  const add = (model) => { const index = nextIndex++; const row = createCustomModelRow(model, index); rows.set(index, row); $('custom-models').append(row.element); if (current.disabled || pending)
53
54
  for (const button of row.element.querySelectorAll('button'))
54
55
  button.disabled = true; };
@@ -60,7 +61,7 @@ export function createCustomConnectionEditor(state, options = {}) {
60
61
  const read = () => ({ name: parts.control($('custom-name')).getValue(), baseUrl: parts.control($('custom-url')).getValue(), api: parts.control($('custom-api')).getValue(), apiKey: parts.control($('custom-key')).getValue(), models: [...rows.values()].map(row => row.read()) });
61
62
  const update = (next) => { if (destroyed)
62
63
  return; current = next; if (next.error !== undefined)
63
- parts.feedback(element.querySelector('[data-custom-error]')).update({ message: next.error, tone: 'error' }); parts.update(); for (const button of form.querySelectorAll('button'))
64
+ parts.feedback(element.querySelector('[data-custom-error]')).update({ message: next.error, tone: 'error' }); parts.update(); for (const button of form.querySelectorAll('button:not([role="combobox"]):not([role="option"])'))
64
65
  parts.action(button).update({ disabled: next.disabled, pending: button.hasAttribute('data-close') ? false : pending }); };
65
66
  const submission = bindFormSubmission(form, { read, unavailable: () => !!current.disabled, onSubmit: options.onSubmit, onPending(value) { pending = value; update(current); }, onError(error) { update({ ...current, error }); } });
66
67
  update(state);
@@ -1 +1 @@
1
- {"version":3,"file":"custom-connection.js","sourceRoot":"","sources":["../../src/forms/custom-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import {scopeIds,localField,bindFormSubmission} from './identity.js';\nimport type {ActionResult,UIBlock} from '../core.js';\nimport { escape, uniqueId } from '../dom.js';\nimport {adoptProductParts} from '../foundations.js';\nexport interface CustomModelValue {id: string; name?: string; contextWindow?: number; maxTokens?: number; reasoning?: boolean; input?: readonly string[]; cost?: {input: number; output: number; cacheRead: number; cacheWrite: number}}\nexport interface CustomConnectionState {name: string; baseUrl: string; api: string; editing: boolean; models: readonly CustomModelValue[]; error?: string; disabled?: boolean}\nexport interface CustomModelDraft {sourceIndex: number; id: string; name: string; contextWindow: number; maxTokens: number; reasoning: boolean; images: boolean; prices: {input: string; output: string; cacheRead: string; cacheWrite: string}}\nexport interface CustomConnectionDraft {name: string; baseUrl: string; api: string; apiKey: string; models: CustomModelDraft[]}\nconst protocols = ['openai-completions', 'openai-responses', 'anthropic-messages', 'google-generative-ai', 'mistral-conversations'];\nfunction modelRowMarkup(model: CustomModelValue, index: number): string {return `<fieldset class=\"pui-custom-model\" data-model-index=\"${index}\"><legend>Model ${index + 1}</legend><label>Model ID<input name=\"id\" required value=\"${escape(model.id)}\" /></label><label>Display name<input name=\"name\" value=\"${escape(model.name || '')}\" /></label><div class=\"pui-sdk-grid\"><label>Context tokens<input name=\"contextWindow\" type=\"number\" min=\"1\" required value=\"${escape(model.contextWindow)}\" /></label><label>Max output tokens<input name=\"maxTokens\" type=\"number\" min=\"1\" required value=\"${escape(model.maxTokens)}\" /></label></div><div class=\"pui-sdk-grid\"><label class=\"pui-checkbox-field\"><input name=\"reasoning\" type=\"checkbox\" ${model.reasoning ? 'checked' : ''} />Thinking effort</label><label class=\"pui-checkbox-field\"><input name=\"images\" type=\"checkbox\" ${model.input?.includes('image') ? 'checked' : ''} />Images</label></div><details class=\"pui-provider-advanced\"><summary>Price estimate (optional)</summary><div class=\"pui-sdk-grid\">${(['input', 'output', 'cacheRead', 'cacheWrite'] as const).map((rate) => `<label>${({ input: \"Input\", output: \"Output\", cacheRead: \"Cache read\", cacheWrite: \"Cache write\" } as Record<string, string>)[rate]}<input name=\"price-${rate}\" type=\"number\" min=\"0\" step=\"any\" value=\"${escape(model.cost?.[rate] ?? '')}\" /></label>`).join('')}</div></details><button type=\"button\" class=\"pui-secondary-button pui-destructive-button\" data-remove-model>Remove model</button></fieldset>`;}\nexport interface CustomModelRowState extends CustomModelValue {disabled?: boolean; error?: string}\nexport function createCustomModelRow(model: CustomModelRowState, index = 0): UIBlock<CustomModelRowState> & {read(): CustomModelDraft; reset(model: CustomModelValue): void} {\n const element = document.createElement('div'); element.className = 'pui-custom-model-row'; element.innerHTML = modelRowMarkup(model,index);\n const field = element.querySelector<HTMLFieldSetElement>('fieldset')!; const error = document.createElement('p'); error.className = 'pui-form-error'; error.setAttribute('role','alert'); element.append(error); const parts = adoptProductParts(element); let destroyed = false;\n const input = (name: string) => field.querySelector<HTMLInputElement>(`[name=\"${name}\"]`)!;\n const reset = (value: CustomModelValue) => {\n if (destroyed) return;\n parts.control(input('id')).reset(value.id); parts.control(input('name')).reset(value.name || '');\n parts.control(input('contextWindow')).reset(value.contextWindow === undefined ? '' : String(value.contextWindow)); parts.control(input('maxTokens')).reset(value.maxTokens === undefined ? '' : String(value.maxTokens));\n parts.control(input('reasoning')).reset(!!value.reasoning); parts.control(input('images')).reset(!!value.input?.includes('image'));\n for (const rate of ['input','output','cacheRead','cacheWrite'] as const) parts.control(input('price-'+rate)).reset(value.cost?.[rate] === undefined ? '' : String(value.cost[rate]));\n };\n const value = (name:string) => parts.control(input(name)).getValue();\n const read = (): CustomModelDraft => ({sourceIndex:index,id:value('id').trim(),name:value('name').trim(),contextWindow:Number(value('contextWindow')),maxTokens:Number(value('maxTokens')),reasoning:parts.control(input('reasoning')).getChecked(),images:parts.control(input('images')).getChecked(),prices:{input:value('price-input'),output:value('price-output'),cacheRead:value('price-cacheRead'),cacheWrite:value('price-cacheWrite')}});\n const update = (state: Readonly<CustomModelRowState>) => {if (destroyed) return; if (state.disabled !== undefined) field.disabled = state.disabled; if (state.error !== undefined) parts.feedback(error).update({message:state.error,tone:'error'});};\n update(model); return {element,read,reset,update,destroy() {if (destroyed) return; destroyed = true; parts.destroy(); element.remove();}};\n}\nexport function createCustomConnectionEditor(state: CustomConnectionState, options: {idPrefix?: string; onSubmit?: (draft: CustomConnectionDraft) => ActionResult | Promise<ActionResult>} = {}): UIBlock<CustomConnectionState> & {read(): CustomConnectionDraft; readonly form: HTMLFormElement} {\n const element = document.createElement('div'); element.className = 'pui-custom-connection-editor'; element.innerHTML = `<p class=\"pui-modal-description\">Give this endpoint its own name. It can coexist with official providers and other compatible endpoints.</p><form id=\"custom-form\"><label class=\"pui-field-label\">Connection name<input id=\"custom-name\" required value=\"${escape(state.name)}\" /></label><label class=\"pui-field-label\">API base URL<input id=\"custom-url\" type=\"url\" required value=\"${escape(state.baseUrl)}\" placeholder=\"https://example.com/v1\" /></label><label class=\"pui-field-label\">API protocol<select id=\"custom-api\" class=\"pui-feature-select\">${protocols.map((p) => `<option ${state.api === p ? 'selected' : ''}>${p}</option>`).join('')}</select></label><label class=\"pui-field-label\">API key<input id=\"custom-key\" type=\"password\" autocomplete=\"new-password\" placeholder=\"${state.editing ? 'Leave blank to keep the key at the same endpoint' : 'API key (optional for local endpoints)'}\" /></label><div id=\"custom-models\"></div><button type=\"button\" class=\"pui-secondary-button\" id=\"add-custom-model\">Add model</button><p class=\"pui-field-hint\">Limits and capabilities are provided by you. Prices are USD per million tokens. Fill all four rates (0 for free/unused), or leave all four blank for unknown prices.</p><p class=\"pui-form-error\" data-custom-error role=\"alert\"></p><div class=\"pui-modal-footer\"><button type=\"button\" class=\"pui-secondary-button\" data-close=\"sdk-dialog\">Cancel</button><button class=\"pui-primary-button\" type=\"submit\">Save connection</button></div></form>`;\n const prefix = options.idPrefix ?? uniqueId('pui-custom') + '-'; scopeIds(element, prefix);\n const $ = <T extends HTMLElement = HTMLElement>(id: string) => localField<T>(element, prefix + id);\n const form = $<HTMLFormElement>('custom-form'); const parts = adoptProductParts(element), rows = new Map<number, ReturnType<typeof createCustomModelRow>>(); let nextIndex = 0, destroyed = false, pending = false; const abort = new AbortController(); let current = state;\n const add = (model: CustomModelValue) => {const index = nextIndex++; const row = createCustomModelRow(model,index); rows.set(index,row); $('custom-models').append(row.element); if (current.disabled || pending) for (const button of row.element.querySelectorAll<HTMLButtonElement>('button')) button.disabled = true;};\n state.models.forEach(add);\n $('add-custom-model').addEventListener('click', () => {if (!current.disabled && !pending) add({id:'',contextWindow:128000,maxTokens:8192});}, {signal:abort.signal});\n $('custom-models').addEventListener('click', event => {const target = (event.target as HTMLElement).closest<HTMLButtonElement>('[data-remove-model]'); if (!target || target.disabled || current.disabled || pending) return; const index = Number(target.closest<HTMLElement>('[data-model-index]')?.dataset.modelIndex); rows.get(index)?.destroy(); rows.delete(index);}, {signal:abort.signal});\n const read = (): CustomConnectionDraft => ({name:parts.control($<HTMLInputElement>('custom-name')).getValue(),baseUrl:parts.control($<HTMLInputElement>('custom-url')).getValue(),api:parts.control($<HTMLSelectElement>('custom-api')).getValue(),apiKey:parts.control($<HTMLInputElement>('custom-key')).getValue(),models:[...rows.values()].map(row => row.read())});\n const update = (next: Readonly<CustomConnectionState>) => {if (destroyed) return; current = next; if (next.error !== undefined) parts.feedback(element.querySelector<HTMLElement>('[data-custom-error]')!).update({message:next.error,tone:'error'}); parts.update(); for (const button of form.querySelectorAll<HTMLButtonElement>('button')) parts.action(button).update({disabled:next.disabled,pending:button.hasAttribute('data-close') ? false : pending});};\n const submission = bindFormSubmission(form,{read,unavailable:()=>!!current.disabled,onSubmit:options.onSubmit,onPending(value) {pending = value; update(current);},onError(error) {update({...current,error});}});\n update(state);\n return {element,form,read,update,destroy() {if (destroyed) return; destroyed = true; submission.destroy(); abort.abort(); for (const row of rows.values()) row.destroy(); rows.clear(); for (const input of element.querySelectorAll<HTMLInputElement>('input[type=\"password\"]')) parts.control(input).reset(''); parts.destroy(); element.remove();}};\n}\n"]}
1
+ {"version":3,"file":"custom-connection.js","sourceRoot":"","sources":["../../src/forms/custom-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import {scopeIds,localField,bindFormSubmission} from './identity.js';\nimport type {ActionResult,UIBlock} from '../core.js';\nimport { escape, uniqueId } from '../dom.js';\nimport {adoptProductParts} from '../foundations.js';\nexport interface CustomModelValue {id: string; name?: string; contextWindow?: number; maxTokens?: number; reasoning?: boolean; input?: readonly string[]; cost?: {input: number; output: number; cacheRead: number; cacheWrite: number}}\nexport interface CustomConnectionState {name: string; baseUrl: string; api: string; editing: boolean; models: readonly CustomModelValue[]; error?: string; disabled?: boolean}\nexport interface CustomModelDraft {sourceIndex: number; id: string; name: string; contextWindow: number; maxTokens: number; reasoning: boolean; images: boolean; prices: {input: string; output: string; cacheRead: string; cacheWrite: string}}\nexport interface CustomConnectionDraft {name: string; baseUrl: string; api: string; apiKey: string; models: CustomModelDraft[]}\nconst protocols = ['openai-completions', 'openai-responses', 'anthropic-messages', 'google-generative-ai', 'mistral-conversations'];\nfunction modelRowMarkup(model: CustomModelValue, index: number): string {return `<fieldset class=\"pui-custom-model\" data-model-index=\"${index}\"><legend>Model ${index + 1}</legend><label>Model ID<input name=\"id\" required value=\"${escape(model.id)}\" /></label><label>Display name<input name=\"name\" value=\"${escape(model.name || '')}\" /></label><div class=\"pui-sdk-grid\"><label>Context tokens<input name=\"contextWindow\" type=\"number\" min=\"1\" required value=\"${escape(model.contextWindow)}\" /></label><label>Max output tokens<input name=\"maxTokens\" type=\"number\" min=\"1\" required value=\"${escape(model.maxTokens)}\" /></label></div><div class=\"pui-sdk-grid\"><label class=\"pui-checkbox-field\"><input name=\"reasoning\" type=\"checkbox\" ${model.reasoning ? 'checked' : ''} />Thinking effort</label><label class=\"pui-checkbox-field\"><input name=\"images\" type=\"checkbox\" ${model.input?.includes('image') ? 'checked' : ''} />Images</label></div><details class=\"pui-provider-advanced\"><summary>Price estimate (optional)</summary><div class=\"pui-sdk-grid\">${(['input', 'output', 'cacheRead', 'cacheWrite'] as const).map((rate) => `<label>${({ input: \"Input\", output: \"Output\", cacheRead: \"Cache read\", cacheWrite: \"Cache write\" } as Record<string, string>)[rate]}<input name=\"price-${rate}\" type=\"number\" min=\"0\" step=\"any\" value=\"${escape(model.cost?.[rate] ?? '')}\" /></label>`).join('')}</div></details><button type=\"button\" class=\"pui-secondary-button pui-destructive-button\" data-remove-model>Remove model</button></fieldset>`;}\nexport interface CustomModelRowState extends CustomModelValue {disabled?: boolean; error?: string}\nexport function createCustomModelRow(model: CustomModelRowState, index = 0): UIBlock<CustomModelRowState> & {read(): CustomModelDraft; reset(model: CustomModelValue): void} {\n const element = document.createElement('div'); element.className = 'pui-custom-model-row'; element.innerHTML = modelRowMarkup(model,index);\n const field = element.querySelector<HTMLFieldSetElement>('fieldset')!; const error = document.createElement('p'); error.className = 'pui-form-error'; error.setAttribute('role','alert'); element.append(error); const parts = adoptProductParts(element); let destroyed = false;\n const input = (name: string) => field.querySelector<HTMLInputElement>(`[name=\"${name}\"]`)!;\n const reset = (value: CustomModelValue) => {\n if (destroyed) return;\n parts.control(input('id')).reset(value.id); parts.control(input('name')).reset(value.name || '');\n parts.control(input('contextWindow')).reset(value.contextWindow === undefined ? '' : String(value.contextWindow)); parts.control(input('maxTokens')).reset(value.maxTokens === undefined ? '' : String(value.maxTokens));\n parts.control(input('reasoning')).reset(!!value.reasoning); parts.control(input('images')).reset(!!value.input?.includes('image'));\n for (const rate of ['input','output','cacheRead','cacheWrite'] as const) parts.control(input('price-'+rate)).reset(value.cost?.[rate] === undefined ? '' : String(value.cost[rate]));\n };\n const value = (name:string) => parts.control(input(name)).getValue();\n const read = (): CustomModelDraft => ({sourceIndex:index,id:value('id').trim(),name:value('name').trim(),contextWindow:Number(value('contextWindow')),maxTokens:Number(value('maxTokens')),reasoning:parts.control(input('reasoning')).getChecked(),images:parts.control(input('images')).getChecked(),prices:{input:value('price-input'),output:value('price-output'),cacheRead:value('price-cacheRead'),cacheWrite:value('price-cacheWrite')}});\n const update = (state: Readonly<CustomModelRowState>) => {if (destroyed) return; if (state.disabled !== undefined) field.disabled = state.disabled; if (state.error !== undefined) parts.feedback(error).update({message:state.error,tone:'error'});};\n update(model); return {element,read,reset,update,destroy() {if (destroyed) return; destroyed = true; parts.destroy(); element.remove();}};\n}\nexport function createCustomConnectionEditor(state: CustomConnectionState, options: {idPrefix?: string; onSubmit?: (draft: CustomConnectionDraft) => ActionResult | Promise<ActionResult>} = {}): UIBlock<CustomConnectionState> & {read(): CustomConnectionDraft; readonly form: HTMLFormElement} {\n const element = document.createElement('div'); element.className = 'pui-custom-connection-editor'; element.innerHTML = `<p class=\"pui-modal-description\">Give this endpoint its own name. It can coexist with official providers and other compatible endpoints.</p><form id=\"custom-form\"><label class=\"pui-field-label\">Connection name<input id=\"custom-name\" required value=\"${escape(state.name)}\" /></label><label class=\"pui-field-label\">API base URL<input id=\"custom-url\" type=\"url\" required value=\"${escape(state.baseUrl)}\" placeholder=\"https://example.com/v1\" /></label><label class=\"pui-field-label\">API protocol<select id=\"custom-api\" class=\"pui-feature-select\">${protocols.map((p) => `<option ${state.api === p ? 'selected' : ''}>${p}</option>`).join('')}</select></label><label class=\"pui-field-label\">API key<input id=\"custom-key\" type=\"password\" autocomplete=\"new-password\" placeholder=\"${state.editing ? 'Leave blank to keep the key at the same endpoint' : 'API key (optional for local endpoints)'}\" /></label><div id=\"custom-models\"></div><button type=\"button\" class=\"pui-secondary-button\" id=\"add-custom-model\">Add model</button><p class=\"pui-field-hint\">Limits and capabilities are provided by you. Prices are USD per million tokens. Fill all four rates (0 for free/unused), or leave all four blank for unknown prices.</p><p class=\"pui-form-error\" data-custom-error role=\"alert\"></p><div class=\"pui-modal-footer\"><button type=\"button\" class=\"pui-secondary-button\" data-pui-close data-close=\"sdk-dialog\">Cancel</button><button class=\"pui-primary-button\" type=\"submit\">Save connection</button></div></form>`;\n const prefix = options.idPrefix ?? uniqueId('pui-custom') + '-'; scopeIds(element, prefix);\n const $ = <T extends HTMLElement = HTMLElement>(id: string) => localField<T>(element, prefix + id);\n const form = $<HTMLFormElement>('custom-form'); const parts = adoptProductParts(element), rows = new Map<number, ReturnType<typeof createCustomModelRow>>(); let nextIndex = 0, destroyed = false, pending = false; const abort = new AbortController(); let current = state;\n parts.control($<HTMLSelectElement>('custom-api'));\n const add = (model: CustomModelValue) => {const index = nextIndex++; const row = createCustomModelRow(model,index); rows.set(index,row); $('custom-models').append(row.element); if (current.disabled || pending) for (const button of row.element.querySelectorAll<HTMLButtonElement>('button')) button.disabled = true;};\n state.models.forEach(add);\n $('add-custom-model').addEventListener('click', () => {if (!current.disabled && !pending) add({id:'',contextWindow:128000,maxTokens:8192});}, {signal:abort.signal});\n $('custom-models').addEventListener('click', event => {const target = (event.target as HTMLElement).closest<HTMLButtonElement>('[data-remove-model]'); if (!target || target.disabled || current.disabled || pending) return; const index = Number(target.closest<HTMLElement>('[data-model-index]')?.dataset.modelIndex); rows.get(index)?.destroy(); rows.delete(index);}, {signal:abort.signal});\n const read = (): CustomConnectionDraft => ({name:parts.control($<HTMLInputElement>('custom-name')).getValue(),baseUrl:parts.control($<HTMLInputElement>('custom-url')).getValue(),api:parts.control($<HTMLSelectElement>('custom-api')).getValue(),apiKey:parts.control($<HTMLInputElement>('custom-key')).getValue(),models:[...rows.values()].map(row => row.read())});\n const update = (next: Readonly<CustomConnectionState>) => {if (destroyed) return; current = next; if (next.error !== undefined) parts.feedback(element.querySelector<HTMLElement>('[data-custom-error]')!).update({message:next.error,tone:'error'}); parts.update(); for (const button of form.querySelectorAll<HTMLButtonElement>('button:not([role=\"combobox\"]):not([role=\"option\"])')) parts.action(button).update({disabled:next.disabled,pending:button.hasAttribute('data-close') ? false : pending});};\n const submission = bindFormSubmission(form,{read,unavailable:()=>!!current.disabled,onSubmit:options.onSubmit,onPending(value) {pending = value; update(current);},onError(error) {update({...current,error});}});\n update(state);\n return {element,form,read,update,destroy() {if (destroyed) return; destroyed = true; submission.destroy(); abort.abort(); for (const row of rows.values()) row.destroy(); rows.clear(); for (const input of element.querySelectorAll<HTMLInputElement>('input[type=\"password\"]')) parts.control(input).reset(''); parts.destroy(); element.remove();}};\n}\n"]}
@@ -10,7 +10,7 @@ export interface BranchHistoryState {
10
10
  error?: string;
11
11
  loading?: boolean;
12
12
  }
13
- export declare function createBranchHistory(state: BranchHistoryState, options?: {
13
+ export declare function createBranchHistory(initial: BranchHistoryState, options?: {
14
14
  onContinue?: (id: string) => void | Promise<void>;
15
15
  }): UIBlock<BranchHistoryState>;
16
16
  //# sourceMappingURL=history.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/forms/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,iBAAiB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC;AAC5F,MAAM,WAAW,kBAAkB;IAAE,KAAK,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAC;AACnH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,EAAE,OAAO,GAAE;IAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAK7J"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/forms/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI1C,MAAM,WAAW,iBAAiB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC;AAC5F,MAAM,WAAW,kBAAkB;IAAE,KAAK,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAC;AAEnH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,GAAE;IAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAsD/J"}
@@ -1,21 +1,84 @@
1
- import { escape } from '../dom.js';
2
- export function createBranchHistory(state, options = {}) {
1
+ import { setText } from '../dom.js';
2
+ import { adoptAction, adoptFeedback } from '../foundations.js';
3
+ export function createBranchHistory(initial, options = {}) {
3
4
  const element = document.createElement('div');
4
5
  element.className = 'pui-branch-history';
5
- const abort = new AbortController();
6
+ const description = document.createElement('p');
7
+ description.className = 'pui-modal-description';
8
+ description.textContent = 'Continue from any saved message. Other branches remain available here; files and external actions are not undone.';
9
+ const list = document.createElement('div');
10
+ list.className = 'pui-branch-list';
11
+ const empty = document.createElement('p');
12
+ empty.textContent = 'No history yet.';
13
+ const status = document.createElement('div');
14
+ const error = document.createElement('p');
15
+ error.className = 'pui-form-error';
16
+ const feedback = adoptFeedback(status, { presentation: 'inline' });
17
+ const actionFeedback = adoptFeedback(error, { presentation: 'inline' });
18
+ const rows = new Map();
6
19
  let destroyed = false;
7
- const update = (state) => { if (destroyed)
8
- return; if (state.loading) {
9
- element.textContent = 'Loading history…';
10
- return;
11
- } if (state.error) {
12
- element.textContent = state.error;
13
- return;
14
- } element.innerHTML = `<p class="pui-modal-description">Continue from any saved message. Other branches remain available here; files and external actions are not undone.</p><div class="pui-branch-list">${(state.nodes || []).map((node) => `<article class="pui-branch-node ${node.active ? 'pui-current-branch' : ''}"><div class="pui-connection-card-heading"><strong>${escape(node.role)}${node.active ? ' · current branch' : ''}</strong><button class="pui-secondary-button" data-branch="${escape(node.id)}">Continue here</button></div><p>${escape(node.text.slice(0, 360) || '(Image or empty reply)')}</p></article>`).join('') || '<p>No history yet.</p>'}</div>`; };
15
- element.addEventListener('click', (event) => { const target = event.target.closest('[data-branch]'); if (target && options.onContinue)
16
- void options.onContinue(target.dataset.branch); }, { signal: abort.signal });
17
- update(state);
20
+ const clear = () => { for (const row of rows.values())
21
+ row.action.destroy(); rows.clear(); list.replaceChildren(); };
22
+ const update = (state) => {
23
+ if (destroyed)
24
+ return;
25
+ if (state.loading || state.error) {
26
+ clear();
27
+ const message = state.loading ? 'Loading history…' : state.error;
28
+ feedback.update({ message, tone: state.loading ? 'info' : 'error' });
29
+ actionFeedback.update({ message: '', tone: 'error' });
30
+ element.replaceChildren(status);
31
+ return;
32
+ }
33
+ feedback.update({ message: '', tone: 'info' });
34
+ if (description.parentNode !== element)
35
+ element.replaceChildren(description, list, error);
36
+ const nodes = state.nodes ?? [];
37
+ const keep = new Set(nodes.map(node => node.id));
38
+ for (const [id, row] of rows)
39
+ if (!keep.has(id)) {
40
+ row.action.destroy();
41
+ row.element.remove();
42
+ rows.delete(id);
43
+ }
44
+ let cursor = list.firstElementChild;
45
+ for (const node of nodes) {
46
+ let row = rows.get(node.id);
47
+ if (!row) {
48
+ const article = document.createElement('article');
49
+ article.className = 'pui-branch-node';
50
+ const heading = document.createElement('div');
51
+ heading.className = 'pui-connection-card-heading';
52
+ const role = document.createElement('strong'), button = document.createElement('button'), text = document.createElement('p');
53
+ button.type = 'button';
54
+ button.className = 'pui-secondary-button';
55
+ button.textContent = 'Continue here';
56
+ button.dataset.branch = node.id;
57
+ heading.append(role, button);
58
+ article.append(heading, text);
59
+ const action = adoptAction(button, {
60
+ onAction: options.onContinue ? () => { actionFeedback.update({ message: '', tone: 'error' }); return options.onContinue(node.id); } : undefined,
61
+ onError: message => actionFeedback.update({ message, tone: 'error' }),
62
+ });
63
+ row = { element: article, role, text, action };
64
+ rows.set(node.id, row);
65
+ }
66
+ row.element.classList.toggle('pui-current-branch', node.active);
67
+ setText(row.role, `${node.role}${node.active ? ' · current branch' : ''}`);
68
+ setText(row.text, node.text.slice(0, 360) || '(Image or empty reply)');
69
+ if (row.element !== cursor)
70
+ list.insertBefore(row.element, cursor);
71
+ cursor = row.element.nextElementSibling;
72
+ }
73
+ if (!nodes.length) {
74
+ if (empty.parentNode !== list)
75
+ list.append(empty);
76
+ }
77
+ else
78
+ empty.remove();
79
+ };
80
+ update(initial);
18
81
  return { element, update, destroy() { if (destroyed)
19
- return; destroyed = true; abort.abort(); element.remove(); } };
82
+ return; destroyed = true; clear(); feedback.destroy(); actionFeedback.destroy(); element.remove(); } };
20
83
  }
21
84
  //# sourceMappingURL=history.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/forms/history.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGnC,MAAM,UAAU,mBAAmB,CAAC,KAAyB,EAAE,UAA+D,EAAE;IAC/H,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAAC,OAAO,CAAC,SAAS,GAAG,oBAAoB,CAAC;IAAC,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IAAC,IAAI,SAAS,GAAG,KAAK,CAAC;IACpJ,MAAM,MAAM,GAAG,CAAC,KAAmC,EAAE,EAAE,GAAE,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAAA,OAAO,CAAC,WAAW,GAAG,kBAAkB,CAAC;QAAC,OAAO;IAAA,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAAA,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC;QAAC,OAAO;IAAA,CAAC,CAAC,OAAO,CAAC,SAAS,GAAG,sLAAsL,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mCAAmC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,sDAAsD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,8DAA8D,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,oCAAoC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,wBAAwB,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,wBAAwB,QAAQ,CAAC,CAAA,CAAC,CAAC;IACx2B,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,GAAE,MAAM,MAAM,GAAI,KAAK,CAAC,MAAsB,CAAC,OAAO,CAAoB,eAAe,CAAC,CAAC,CAAC,IAAI,MAAM,IAAI,OAAO,CAAC,UAAU;QAAE,KAAK,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,MAAO,CAAC,CAAC,CAAA,CAAC,EAAE,EAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;IACrP,MAAM,CAAC,KAAK,CAAC,CAAC;IAAC,OAAO,EAAC,OAAO,EAAE,MAAM,EAAE,OAAO,KAAI,IAAI,SAAS;YAAE,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA,CAAC,EAAC,CAAC;AAChI,CAAC","sourcesContent":["import type { UIBlock } from '../core.js';\nimport { escape } from '../dom.js';\nexport interface BranchHistoryNode {id: string; role: string; text: string; active: boolean}\nexport interface BranchHistoryState {nodes: readonly BranchHistoryNode[] | null; error?: string; loading?: boolean}\nexport function createBranchHistory(state: BranchHistoryState, options: {onContinue?: (id: string) => void | Promise<void>} = {}): UIBlock<BranchHistoryState> {\n const element = document.createElement('div'); element.className = 'pui-branch-history'; const abort = new AbortController(); let destroyed = false;\n const update = (state: Readonly<BranchHistoryState>) => {if (destroyed) return; if (state.loading) {element.textContent = 'Loading history…'; return;} if (state.error) {element.textContent = state.error; return;} element.innerHTML = `<p class=\"pui-modal-description\">Continue from any saved message. Other branches remain available here; files and external actions are not undone.</p><div class=\"pui-branch-list\">${(state.nodes || []).map((node) => `<article class=\"pui-branch-node ${node.active ? 'pui-current-branch' : ''}\"><div class=\"pui-connection-card-heading\"><strong>${escape(node.role)}${node.active ? ' · current branch' : ''}</strong><button class=\"pui-secondary-button\" data-branch=\"${escape(node.id)}\">Continue here</button></div><p>${escape(node.text.slice(0, 360) || '(Image or empty reply)')}</p></article>`).join('') || '<p>No history yet.</p>'}</div>`;};\n element.addEventListener('click', (event) => {const target = (event.target as HTMLElement).closest<HTMLButtonElement>('[data-branch]'); if (target && options.onContinue) void options.onContinue(target.dataset.branch!);}, {signal: abort.signal});\n update(state); return {element, update, destroy() {if (destroyed) return; destroyed = true; abort.abort(); element.remove();}};\n}\n"]}
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/forms/history.ts"],"names":[],"mappings":"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","sourcesContent":["import type { UIBlock } from '../core.js';\nimport { setText } from '../dom.js';\nimport { adoptAction, adoptFeedback, type ActionController } from '../foundations.js';\n\nexport interface BranchHistoryNode {id: string; role: string; text: string; active: boolean}\nexport interface BranchHistoryState {nodes: readonly BranchHistoryNode[] | null; error?: string; loading?: boolean}\n\nexport function createBranchHistory(initial: BranchHistoryState, options: {onContinue?: (id: string) => void | Promise<void>} = {}): UIBlock<BranchHistoryState> {\n const element = document.createElement('div'); element.className = 'pui-branch-history';\n const description = document.createElement('p'); description.className = 'pui-modal-description';\n description.textContent = 'Continue from any saved message. Other branches remain available here; files and external actions are not undone.';\n const list = document.createElement('div'); list.className = 'pui-branch-list';\n const empty = document.createElement('p'); empty.textContent = 'No history yet.';\n const status = document.createElement('div');\n const error = document.createElement('p'); error.className = 'pui-form-error';\n const feedback = adoptFeedback(status, { presentation: 'inline' });\n const actionFeedback = adoptFeedback(error, { presentation: 'inline' });\n type Row = { element: HTMLElement; role: HTMLElement; text: HTMLElement; action: ActionController };\n const rows = new Map<string, Row>();\n let destroyed = false;\n const clear = (): void => { for (const row of rows.values()) row.action.destroy(); rows.clear(); list.replaceChildren(); };\n const update = (state: Readonly<BranchHistoryState>): void => {\n if (destroyed) return;\n if (state.loading || state.error) {\n clear();\n const message = state.loading ? 'Loading history…' : state.error!;\n feedback.update({ message, tone: state.loading ? 'info' : 'error' });\n actionFeedback.update({ message: '', tone: 'error' });\n element.replaceChildren(status);\n return;\n }\n feedback.update({ message: '', tone: 'info' });\n if (description.parentNode !== element) element.replaceChildren(description, list, error);\n const nodes = state.nodes ?? [];\n const keep = new Set(nodes.map(node => node.id));\n for (const [id, row] of rows) if (!keep.has(id)) { row.action.destroy(); row.element.remove(); rows.delete(id); }\n let cursor = list.firstElementChild;\n for (const node of nodes) {\n let row = rows.get(node.id);\n if (!row) {\n const article = document.createElement('article'); article.className = 'pui-branch-node';\n const heading = document.createElement('div'); heading.className = 'pui-connection-card-heading';\n const role = document.createElement('strong'), button = document.createElement('button'), text = document.createElement('p');\n button.type = 'button'; button.className = 'pui-secondary-button'; button.textContent = 'Continue here'; button.dataset.branch = node.id;\n heading.append(role, button); article.append(heading, text);\n const action = adoptAction(button, {\n onAction: options.onContinue ? () => { actionFeedback.update({ message: '', tone: 'error' }); return options.onContinue!(node.id); } : undefined,\n onError: message => actionFeedback.update({ message, tone: 'error' }),\n });\n row = { element: article, role, text, action }; rows.set(node.id, row);\n }\n row.element.classList.toggle('pui-current-branch', node.active);\n setText(row.role, `${node.role}${node.active ? ' · current branch' : ''}`);\n setText(row.text, node.text.slice(0, 360) || '(Image or empty reply)');\n if (row.element !== cursor) list.insertBefore(row.element, cursor);\n cursor = row.element.nextElementSibling;\n }\n if (!nodes.length) { if (empty.parentNode !== list) list.append(empty); } else empty.remove();\n };\n update(initial);\n return { element, update, destroy() { if (destroyed) return; destroyed = true; clear(); feedback.destroy(); actionFeedback.destroy(); element.remove(); } };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/forms/identity.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQhE;AACD,wBAAgB,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAIhG;AACD,OAAO,EAAY,KAAK,YAAY,EAAC,MAAM,YAAY,CAAC;AAGxD,wFAAwF;AACxF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAC,eAAe,EAAC,OAAO,EAAC;IACrE,IAAI,EAAC,MAAI,KAAK,CAAC;IACf,WAAW,EAAC,MAAI,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAC,KAAK,KAAG,YAAY,GAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,SAAS,EAAC,CAAC,OAAO,EAAC,OAAO,KAAG,IAAI,CAAC;IAClC,OAAO,EAAC,CAAC,KAAK,EAAC,MAAM,KAAG,IAAI,CAAC;CAC9B,GAAE;IAAC,UAAU,IAAG,IAAI,CAAC;IAAA,OAAO,IAAG,IAAI,CAAA;CAAC,CAUpC"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/forms/identity.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQhE;AACD,wBAAgB,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAIhG;AACD,OAAO,EAAC,KAAK,YAAY,EAAC,MAAM,YAAY,CAAC;AAI7C,wFAAwF;AACxF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAC,eAAe,EAAC,OAAO,EAAC;IACrE,IAAI,EAAC,MAAI,KAAK,CAAC;IACf,WAAW,EAAC,MAAI,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAC,KAAK,KAAG,YAAY,GAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,SAAS,EAAC,CAAC,OAAO,EAAC,OAAO,KAAG,IAAI,CAAC;IAClC,OAAO,EAAC,CAAC,KAAK,EAAC,MAAM,KAAG,IAAI,CAAC;CAC9B,GAAE;IAAC,UAAU,IAAG,IAAI,CAAC;IAAA,OAAO,IAAG,IAAI,CAAA;CAAC,CAQpC"}
@@ -18,36 +18,20 @@ export function localField(root, id) {
18
18
  throw new Error(`Unknown component field: ${id}`);
19
19
  return found;
20
20
  }
21
- import { Generation } from '../core.js';
21
+ import {} from '../core.js';
22
+ import { createOperation } from '../operation.js';
22
23
  /** Shared form lifetime; business writes and target identity remain with the caller. */
23
24
  export function bindFormSubmission(form, options) {
24
- const generation = new Generation(), abort = new AbortController();
25
- let pending = false;
25
+ const abort = new AbortController();
26
+ const operation = createOperation({ unavailable: options.unavailable, onPending: options.onPending, onError: options.onError });
26
27
  if (options.onSubmit)
27
- form.addEventListener('submit', async (event) => {
28
+ form.addEventListener('submit', event => {
28
29
  event.preventDefault();
29
- if (pending || options.unavailable() || !form.reportValidity())
30
+ if (operation.pending || options.unavailable() || !form.reportValidity())
30
31
  return;
31
- const sequence = generation.next();
32
- pending = true;
33
- options.onError('');
34
- options.onPending(true);
35
- try {
36
- const result = await options.onSubmit(options.read());
37
- if (generation.current(sequence) && !result.ok)
38
- options.onError(result.error);
39
- }
40
- catch (error) {
41
- if (generation.current(sequence))
42
- options.onError(error instanceof Error ? error.message : String(error));
43
- }
44
- finally {
45
- if (generation.current(sequence)) {
46
- pending = false;
47
- options.onPending(false);
48
- }
49
- }
32
+ operation.run(() => { options.onError(''); return options.onSubmit(options.read()); }, result => { if (!result.ok)
33
+ options.onError(result.error); });
50
34
  }, { signal: abort.signal });
51
- return { invalidate() { generation.invalidate(); pending = false; options.onPending(false); }, destroy() { generation.destroy(); abort.abort(); } };
35
+ return { invalidate() { operation.invalidate(); }, destroy() { operation.destroy(); abort.abort(); } };
52
36
  }
53
37
  //# sourceMappingURL=identity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/forms/identity.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,MAAM,UAAU,QAAQ,CAAC,IAAiB,EAAE,MAAc;IACxD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,CAAc,mEAAmE,CAAC;QAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACpK,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;IACvG,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAc,GAAG,CAAC,CAAC;QAAE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YAC1G,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YAC3C,IAAI,KAAK;gBAAE,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7F,CAAC;AACH,CAAC;AACD,MAAM,UAAU,UAAU,CAAsC,IAAiB,EAAE,EAAU;IAC3F,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAc,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3G,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;IAC9D,OAAO,KAAU,CAAC;AACpB,CAAC;AACD,OAAO,EAAC,UAAU,EAAmB,MAAM,YAAY,CAAC;AAGxD,wFAAwF;AACxF,MAAM,UAAU,kBAAkB,CAAQ,IAAoB,EAAC,OAM9D;IACC,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,EAAC,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IAAC,IAAI,OAAO,GAAG,KAAK,CAAC;IACvF,IAAI,OAAO,CAAC,QAAQ;QAAE,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAC,KAAK,EAAC,KAAK,EAAA,EAAE;YAChE,KAAK,CAAC,cAAc,EAAE,CAAC;YAAC,IAAI,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;gBAAE,OAAO;YAC/F,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;YAAC,OAAO,GAAG,IAAI,CAAC;YAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACjG,IAAI,CAAC;gBAAA,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;gBAAC,IAAI,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAAA,CAAC;YAC5I,OAAO,KAAK,EAAE,CAAC;gBAAA,IAAI,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;oBAAE,OAAO,CAAC,OAAO,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAAA,CAAC;oBAClH,CAAC;gBAAA,IAAI,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAAA,OAAO,GAAG,KAAK,CAAC;oBAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAAA,CAAC;YAAA,CAAC;QAC1F,CAAC,EAAC,EAAC,MAAM,EAAC,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;IACzB,OAAO,EAAC,UAAU,KAAI,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA,CAAC,EAAC,OAAO,KAAI,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA,CAAC,EAAC,CAAC;AAC/I,CAAC","sourcesContent":["/** Scope DOM IDs and their references without relying on document-level lookup. */\nexport function scopeIds(root: HTMLElement, prefix: string): void {\n for (const control of root.querySelectorAll<HTMLElement>('input:not([type=\"checkbox\"]):not([type=\"file\"]), textarea, select')) control.classList.add('pui-control');\n if (!prefix) return;\n const attributes = ['id', 'for', 'aria-labelledby', 'aria-describedby', 'aria-controls', 'data-close'];\n for (const node of [root, ...root.querySelectorAll<HTMLElement>('*')]) for (const attribute of attributes) {\n const value = node.getAttribute(attribute);\n if (value) node.setAttribute(attribute, value.split(' ').map(id => prefix + id).join(' '));\n }\n}\nexport function localField<T extends HTMLElement = HTMLElement>(root: HTMLElement, id: string): T {\n const found = [...root.querySelectorAll<HTMLElement>('[id]')].find(node => node.getAttribute('id') === id);\n if (!found) throw new Error(`Unknown component field: ${id}`);\n return found as T;\n}\nimport {Generation,type ActionResult} from '../core.js';\n\n\n/** Shared form lifetime; business writes and target identity remain with the caller. */\nexport function bindFormSubmission<Value>(form:HTMLFormElement,options:{\n read:()=>Value;\n unavailable:()=>boolean;\n onSubmit?: (value:Value)=>ActionResult|Promise<ActionResult>;\n onPending:(pending:boolean)=>void;\n onError:(error:string)=>void;\n}):{invalidate():void;destroy():void} {\n const generation = new Generation(),abort = new AbortController(); let pending = false;\n if (options.onSubmit) form.addEventListener('submit',async event=>{\n event.preventDefault(); if (pending || options.unavailable() || !form.reportValidity()) return;\n const sequence = generation.next(); pending = true; options.onError(''); options.onPending(true);\n try {const result = await options.onSubmit!(options.read()); if (generation.current(sequence) && !result.ok) options.onError(result.error);}\n catch (error) {if (generation.current(sequence)) options.onError(error instanceof Error ? error.message : String(error));}\n finally {if (generation.current(sequence)) {pending = false; options.onPending(false);}}\n },{signal:abort.signal});\n return {invalidate() {generation.invalidate(); pending = false; options.onPending(false);},destroy() {generation.destroy(); abort.abort();}};\n}\n"]}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/forms/identity.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,MAAM,UAAU,QAAQ,CAAC,IAAiB,EAAE,MAAc;IACxD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,CAAc,mEAAmE,CAAC;QAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACpK,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;IACvG,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAc,GAAG,CAAC,CAAC;QAAE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YAC1G,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YAC3C,IAAI,KAAK;gBAAE,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7F,CAAC;AACH,CAAC;AACD,MAAM,UAAU,UAAU,CAAsC,IAAiB,EAAE,EAAU;IAC3F,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAc,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3G,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;IAC9D,OAAO,KAAU,CAAC;AACpB,CAAC;AACD,OAAO,EAAmB,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAC,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAGhD,wFAAwF;AACxF,MAAM,UAAU,kBAAkB,CAAQ,IAAoB,EAAC,OAM9D;IACC,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,eAAe,CAAC,EAAC,WAAW,EAAC,OAAO,CAAC,WAAW,EAAC,SAAS,EAAC,OAAO,CAAC,SAAS,EAAC,OAAO,EAAC,OAAO,CAAC,OAAO,EAAC,CAAC,CAAC;IACzH,IAAI,OAAO,CAAC,QAAQ;QAAE,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAC,KAAK,CAAA,EAAE;YAC1D,KAAK,CAAC,cAAc,EAAE,CAAC;YAAC,IAAI,SAAS,CAAC,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;gBAAE,OAAO;YACzG,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,GAAE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,QAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA,CAAC,EAAE,MAAM,CAAC,EAAE,GAAE,IAAI,CAAC,MAAM,CAAC,EAAE;gBAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA,CAAC,CAAC,CAAC;QACpJ,CAAC,EAAC,EAAC,MAAM,EAAC,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC;IACzB,OAAO,EAAC,UAAU,KAAI,SAAS,CAAC,UAAU,EAAE,CAAC,CAAA,CAAC,EAAC,OAAO,KAAI,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA,CAAC,EAAC,CAAC;AAClG,CAAC","sourcesContent":["/** Scope DOM IDs and their references without relying on document-level lookup. */\nexport function scopeIds(root: HTMLElement, prefix: string): void {\n for (const control of root.querySelectorAll<HTMLElement>('input:not([type=\"checkbox\"]):not([type=\"file\"]), textarea, select')) control.classList.add('pui-control');\n if (!prefix) return;\n const attributes = ['id', 'for', 'aria-labelledby', 'aria-describedby', 'aria-controls', 'data-close'];\n for (const node of [root, ...root.querySelectorAll<HTMLElement>('*')]) for (const attribute of attributes) {\n const value = node.getAttribute(attribute);\n if (value) node.setAttribute(attribute, value.split(' ').map(id => prefix + id).join(' '));\n }\n}\nexport function localField<T extends HTMLElement = HTMLElement>(root: HTMLElement, id: string): T {\n const found = [...root.querySelectorAll<HTMLElement>('[id]')].find(node => node.getAttribute('id') === id);\n if (!found) throw new Error(`Unknown component field: ${id}`);\n return found as T;\n}\nimport {type ActionResult} from '../core.js';\nimport {createOperation} from '../operation.js';\n\n\n/** Shared form lifetime; business writes and target identity remain with the caller. */\nexport function bindFormSubmission<Value>(form:HTMLFormElement,options:{\n read:()=>Value;\n unavailable:()=>boolean;\n onSubmit?: (value:Value)=>ActionResult|Promise<ActionResult>;\n onPending:(pending:boolean)=>void;\n onError:(error:string)=>void;\n}):{invalidate():void;destroy():void} {\n const abort = new AbortController();\n const operation = createOperation({unavailable:options.unavailable,onPending:options.onPending,onError:options.onError});\n if (options.onSubmit) form.addEventListener('submit',event=>{\n event.preventDefault(); if (operation.pending || options.unavailable() || !form.reportValidity()) return;\n operation.run(() => {options.onError(''); return options.onSubmit!(options.read());}, result => {if (!result.ok) options.onError(result.error);});\n },{signal:abort.signal});\n return {invalidate() {operation.invalidate();},destroy() {operation.destroy(); abort.abort();}};\n}\n"]}
@@ -26,7 +26,7 @@ export function createModelEditor(initial, options = {}) {
26
26
  const entry = (state.models || []).find(entry => entry.provider === provider.value && entry.id === selected);
27
27
  const levels = entry?.thinkingLevels?.length ? entry.thinkingLevels : ['off'];
28
28
  optionsInto(effort, levels.map(level => ({ value: level, label: thinkingLabel(level) })));
29
- effort.value = levels.includes(preferred) ? preferred : levels.includes('high') ? 'high' : levels.includes('medium') ? 'medium' : levels[0];
29
+ parts.control(effort).reset(levels.includes(preferred) ? preferred : levels.includes('high') ? 'high' : levels.includes('medium') ? 'medium' : levels[0]);
30
30
  effort.hidden = levels.length < 2;
31
31
  field('thinking-label').hidden = effort.hidden;
32
32
  field('capabilities').textContent = entry ? `${entry.supportsImages ? 'Text + images' : 'Text only'} · ${new Intl.NumberFormat('en').format(entry.contextWindow)} context tokens · ${new Intl.NumberFormat('en').format(entry.maxTokens)} max output tokens` : 'No matching models.';
@@ -36,7 +36,7 @@ export function createModelEditor(initial, options = {}) {
36
36
  const query = search.value.trim().toLowerCase();
37
37
  const entries = (state.models || []).filter(entry => entry.provider === provider.value && (entry.id === selected || `${entry.name} ${entry.id}`.toLowerCase().includes(query)));
38
38
  optionsInto(model, entries.map(entry => ({ value: entry.id, label: `${entry.name} — ${entry.id}` })));
39
- model.value = entries.some(entry => entry.id === selected) ? selected : entries[0]?.id || '';
39
+ parts.control(model).reset(entries.some(entry => entry.id === selected) ? selected : entries[0]?.id || '');
40
40
  capabilities(preferred);
41
41
  };
42
42
  const chooseProvider = (selection) => {
@@ -63,7 +63,7 @@ export function createModelEditor(initial, options = {}) {
63
63
  if (!initialized || !draft.provider)
64
64
  reset(next.selection);
65
65
  else {
66
- provider.value = state.providers?.some(entry => entry.id === draft.provider) ? draft.provider : state.providers?.[0]?.id || '';
66
+ parts.control(provider).reset(state.providers?.some(entry => entry.id === draft.provider) ? draft.provider : state.providers?.[0]?.id || '');
67
67
  selected = draft.model;
68
68
  renderModels(draft.thinkingLevel);
69
69
  }