@onefl666/dsh-great-plan 0.0.0-stage → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,127 @@
1
+ window.__ModuleLoader__.load({
2
+ id: '@onefl666/dsh-great-plan',
3
+ chunk: 'client.preset.js',
4
+ factory(require) {
5
+ const React = require('react');
6
+ const h = React.createElement;
7
+ const ui = require('@onefl666/dsh-great-plan/client.ui.js');
8
+
9
+ const BUILTIN_NAMES = {
10
+ standard: 'preset.standard',
11
+ ptc: 'preset.ptc',
12
+ minimal: 'preset.minimal',
13
+ cordis: 'preset.cordis',
14
+ };
15
+
16
+ const BUILTIN_DESCRIPTIONS = {
17
+ standard: 'preset.standardDescription',
18
+ ptc: 'preset.ptcDescription',
19
+ minimal: 'preset.minimalDescription',
20
+ cordis: 'preset.cordisDescription',
21
+ };
22
+
23
+ function createPresetStore(ctx) {
24
+ const store = ui.createStore({ status: 'idle', options: [], error: null });
25
+ let inflight;
26
+
27
+ async function load(force = false) {
28
+ if (inflight !== undefined) return inflight;
29
+ const state = store.getSnapshot();
30
+ if (!force && state.status === 'ready') return undefined;
31
+ store.set({ ...state, status: 'loading', error: null });
32
+ inflight = (async () => {
33
+ const presets = ctx.remote?.agentPresets;
34
+ if (presets?.list === undefined) {
35
+ store.set({ status: 'unavailable', options: [], error: null });
36
+ return;
37
+ }
38
+ const result = await presets.list();
39
+ if (!result.ok) {
40
+ if (result.error.code === 'gateway/invocation-unavailable') {
41
+ store.set({ status: 'unavailable', options: [], error: null });
42
+ return;
43
+ }
44
+ store.set({ status: 'error', options: [], error: result.error.message });
45
+ return;
46
+ }
47
+ const options = (result.value?.presets ?? [])
48
+ .filter((preset) => preset.broken === undefined)
49
+ .map((preset) => ({
50
+ id: preset.id,
51
+ name: preset.name,
52
+ description: preset.description,
53
+ isDefault: preset.isDefault === true,
54
+ }));
55
+ store.set({ status: options.length === 0 ? 'unavailable' : 'ready', options, error: null });
56
+ })().catch((error) => {
57
+ store.set({ status: 'error', options: [], error: ui.messageOf(error) });
58
+ }).finally(() => {
59
+ inflight = undefined;
60
+ });
61
+ return inflight;
62
+ }
63
+
64
+ return { store, load };
65
+ }
66
+
67
+ function usePresetState(store) {
68
+ return ui.useStore(store);
69
+ }
70
+
71
+ function presetDisplay(option, t) {
72
+ if (option?.name !== undefined && option.name !== '') return option.name;
73
+ const key = option === undefined ? undefined : BUILTIN_NAMES[option.id];
74
+ return key === undefined ? (option?.id ?? '') : t(key);
75
+ }
76
+
77
+ function presetDescription(option, t) {
78
+ if (option?.description !== undefined && option.description !== '') return option.description;
79
+ const key = option === undefined ? undefined : BUILTIN_DESCRIPTIONS[option.id];
80
+ return key === undefined ? undefined : t(key);
81
+ }
82
+
83
+ function defaultPresetId(state) {
84
+ return state.options.find((option) => option.isDefault === true)?.id;
85
+ }
86
+
87
+ function PresetOptions({ state, t, selectedId, onPick, onRetry }) {
88
+ const options = state.options ?? [];
89
+ const showLoading = state.status === 'loading' && options.length === 0;
90
+ if (showLoading) return h(ui.Note, null, h(ui.Loading, null, t('preset.loading')));
91
+ if (state.status === 'error' && options.length === 0) {
92
+ return h('div', null,
93
+ h(ui.ErrorText, null, t('preset.error', { message: state.error ?? '' })),
94
+ h(ui.Button, { variant: 'ghost', onClick: onRetry }, t('preset.retry')),
95
+ );
96
+ }
97
+ if (state.status === 'unavailable' || options.length === 0) return h(ui.Note, null, t('preset.unavailable'));
98
+ return h('div', { className: 'gp-list', role: 'radiogroup', 'aria-label': t('preset.title') },
99
+ state.status === 'error' ? h('div', null,
100
+ h(ui.ErrorText, null, t('preset.error', { message: state.error ?? '' })),
101
+ h(ui.Button, { variant: 'ghost', onClick: onRetry }, t('preset.retry')),
102
+ ) : null,
103
+ options.map((option) => {
104
+ const selected = option.id === selectedId;
105
+ return h(ui.ListRow, {
106
+ key: option.id,
107
+ title: presetDisplay(option, t),
108
+ description: presetDescription(option, t),
109
+ role: 'radio',
110
+ checked: selected,
111
+ selected,
112
+ onClick: () => onPick(option.id),
113
+ });
114
+ }),
115
+ );
116
+ }
117
+
118
+ return {
119
+ createPresetStore,
120
+ usePresetState,
121
+ presetDisplay,
122
+ presetDescription,
123
+ defaultPresetId,
124
+ PresetOptions,
125
+ };
126
+ },
127
+ });
@@ -0,0 +1,226 @@
1
+ window.__ModuleLoader__.load({
2
+ id: '@onefl666/dsh-great-plan',
3
+ chunk: 'client.settings.js',
4
+ factory(require) {
5
+ const React = require('react');
6
+ const h = React.createElement;
7
+ const ui = require('@onefl666/dsh-great-plan/client.ui.js');
8
+
9
+ /** Config fields shared with the Host prompt section and the fresh-session prompt. */
10
+ const FIELDS = {
11
+ brainstorming: 'injectBrainstormingPrompt',
12
+ budget: 'injectUnlimitedBudgetPrompt',
13
+ originalInstructions: 'includeOriginalUserInstructions',
14
+ minimalContext: 'includeMinimalRuntimeContext',
15
+ };
16
+
17
+ /** Settings rows, in display order. */
18
+ const ROWS = [
19
+ { field: FIELDS.brainstorming, title: 'settings.brainstorm.title', description: 'settings.brainstorm.description' },
20
+ { field: FIELDS.budget, title: 'settings.budget.title', description: 'settings.budget.description' },
21
+ { field: FIELDS.originalInstructions, title: 'settings.originalInstructions.title', description: 'settings.originalInstructions.description' },
22
+ { field: FIELDS.minimalContext, title: 'settings.minimalContext.title', description: 'settings.minimalContext.description' },
23
+ ];
24
+
25
+ /** Read one switch value from a configuration form snapshot. */
26
+ function readSwitchValue(snapshot, field) {
27
+ return snapshot?.value?.[field] !== false;
28
+ }
29
+
30
+ /** Read the brainstorming switch value from a configuration form snapshot. */
31
+ function readBrainstormingValue(snapshot) {
32
+ return readSwitchValue(snapshot, FIELDS.brainstorming);
33
+ }
34
+
35
+ /** Read the unlimited-budget switch value from a configuration form snapshot. */
36
+ function readBudgetValue(snapshot) {
37
+ return readSwitchValue(snapshot, FIELDS.budget);
38
+ }
39
+
40
+ /** Read the original-instruction switch value from a configuration form snapshot. */
41
+ function readOriginalInstructionsValue(snapshot) {
42
+ return readSwitchValue(snapshot, FIELDS.originalInstructions);
43
+ }
44
+
45
+ /** Read the minimal-runtime-context switch value from a configuration form snapshot. */
46
+ function readMinimalContextValue(snapshot) {
47
+ return readSwitchValue(snapshot, FIELDS.minimalContext);
48
+ }
49
+
50
+ /** Read the shared settings form snapshot, or undefined when the capability is unavailable. */
51
+ function readFormSnapshot(configForms) {
52
+ if (configForms === undefined || configForms === null || typeof configForms.get !== 'function') return undefined;
53
+ const form = configForms.get('great-plan');
54
+ if (form === undefined || form === null || typeof form.getSnapshot !== 'function') return undefined;
55
+ return form.getSnapshot();
56
+ }
57
+
58
+ /**
59
+ * Read one switch through the shared configuration mirror.
60
+ *
61
+ * A missing settings capability, an unreadable form, or an unready snapshot
62
+ * keeps the Host default (enabled) so execution never fails because of
63
+ * configuration.
64
+ */
65
+ function readSwitch(configForms, field) {
66
+ try {
67
+ return readSwitchValue(readFormSnapshot(configForms), field);
68
+ } catch {
69
+ return true;
70
+ }
71
+ }
72
+
73
+ /** Read the unlimited-budget switch; defaults to enabled. */
74
+ function readBudgetSwitch(configForms) {
75
+ return readSwitch(configForms, FIELDS.budget);
76
+ }
77
+
78
+ /** Read the original-instruction switch; defaults to enabled. */
79
+ function readOriginalInstructionsSwitch(configForms) {
80
+ return readSwitch(configForms, FIELDS.originalInstructions);
81
+ }
82
+
83
+ /** Read the minimal-runtime-context switch; defaults to enabled. */
84
+ function readMinimalContextSwitch(configForms) {
85
+ return readSwitch(configForms, FIELDS.minimalContext);
86
+ }
87
+
88
+ /**
89
+ * Read every fresh-session prompt switch from one snapshot.
90
+ *
91
+ * The Client composes one first message, so all three booleans must come
92
+ * from the same form snapshot. Any unavailable or unreadable configuration
93
+ * keeps the Host defaults (all enabled).
94
+ */
95
+ function readFreshPromptSwitches(configForms) {
96
+ try {
97
+ const snapshot = readFormSnapshot(configForms);
98
+ return {
99
+ unlimitedBudget: readBudgetValue(snapshot),
100
+ includeOriginalInstructions: readOriginalInstructionsValue(snapshot),
101
+ includeMinimalContext: readMinimalContextValue(snapshot),
102
+ };
103
+ } catch {
104
+ return { unlimitedBudget: true, includeOriginalInstructions: true, includeMinimalContext: true };
105
+ }
106
+ }
107
+
108
+ /** Stable id for one row's description element (referenced by `aria-describedby`). */
109
+ function descriptionId(field) {
110
+ return `gp-setting-desc-${field}`;
111
+ }
112
+
113
+ /**
114
+ * Settings page section entry point.
115
+ *
116
+ * The slot may render this component without a settings capability (or with
117
+ * a form that never became readable). This wrapper stays hook-free: it either
118
+ * renders the static unavailable copy or delegates to `GreatPlanForm`, which
119
+ * owns the store subscription and the busy/failure state.
120
+ */
121
+ function GreatPlanSection({ form, t }) {
122
+ if (form === undefined || form === null || typeof form.getSnapshot !== 'function') {
123
+ return h('div', { className: 'gp-settings' },
124
+ h('h2', { className: 'gp-settings-heading' }, t('settings.heading')),
125
+ h(ui.Note, null, t('settings.unavailable')),
126
+ );
127
+ }
128
+ return h(GreatPlanForm, { form, t });
129
+ }
130
+
131
+ /**
132
+ * Settings page body: independent switches for the plan prompt and the
133
+ * fresh-session execution prompt.
134
+ *
135
+ * The Host stays the fact source: accepted writes arrive through the shared
136
+ * configuration form, and a refused write keeps the previous value visible.
137
+ * Each switch that is off also offers a ghost button that writes the default
138
+ * (on) value back.
139
+ */
140
+ function GreatPlanForm({ form, t }) {
141
+ const snapshot = ui.useStore(form) ?? {};
142
+ const [busy, setBusy] = React.useState(false);
143
+ const [failed, setFailed] = React.useState(false);
144
+ const status = snapshot.status;
145
+ const ready = status === 'ready';
146
+ const loading = status === 'loading' || status === 'idle';
147
+ const unavailable = !ready && !loading;
148
+ const writable = snapshot.writable !== false;
149
+
150
+ const toggle = async (field, next) => {
151
+ if (busy) return;
152
+ setFailed(false);
153
+ setBusy(true);
154
+ try {
155
+ const accepted = await form.set(field, next);
156
+ if (!accepted) setFailed(true);
157
+ } catch {
158
+ setFailed(true);
159
+ } finally {
160
+ setBusy(false);
161
+ }
162
+ };
163
+
164
+ return h('div', { className: 'gp-settings' },
165
+ h('h2', { className: 'gp-settings-heading' }, t('settings.heading')),
166
+ loading ? h(ui.Loading, null, t('settings.loading')) : null,
167
+ unavailable ? h(ui.Note, null, t('settings.unavailable')) : null,
168
+ ready
169
+ ? ROWS.map((row) => {
170
+ const checked = readSwitchValue(snapshot, row.field);
171
+ const title = t(row.title);
172
+ const descId = descriptionId(row.field);
173
+ const disabled = busy || !writable;
174
+ return h('div', { key: row.field, className: 'gp-setting-row' },
175
+ h('div', { className: 'gp-setting-copy' },
176
+ h('div', { className: 'gp-setting-title' }, title),
177
+ h('div', { className: 'gp-setting-desc', id: descId }, t(row.description)),
178
+ ),
179
+ h('div', { className: 'gp-setting-controls' },
180
+ checked === false ? h(ui.Button, {
181
+ variant: 'ghost',
182
+ className: 'gp-setting-reset',
183
+ 'aria-label': t('settings.resetAria', { title }),
184
+ disabled,
185
+ onClick: () => {
186
+ toggle(row.field, true);
187
+ },
188
+ }, t('settings.reset')) : null,
189
+ h('button', {
190
+ type: 'button',
191
+ role: 'switch',
192
+ className: ui.cx('gp-switch', checked && 'gp-switch-on'),
193
+ 'aria-checked': checked,
194
+ 'aria-label': title,
195
+ 'aria-describedby': descId,
196
+ disabled,
197
+ onClick: () => {
198
+ toggle(row.field, !checked);
199
+ },
200
+ }, h('span', { className: 'gp-switch-thumb' })),
201
+ ),
202
+ );
203
+ })
204
+ : null,
205
+ ready && !writable ? h(ui.Note, null, t('settings.readOnly')) : null,
206
+ failed ? h(ui.ErrorText, null, t('settings.saveFailed')) : null,
207
+ );
208
+ }
209
+
210
+ return {
211
+ FIELDS,
212
+ ROWS,
213
+ readSwitchValue,
214
+ readBrainstormingValue,
215
+ readBudgetValue,
216
+ readOriginalInstructionsValue,
217
+ readMinimalContextValue,
218
+ readBudgetSwitch,
219
+ readOriginalInstructionsSwitch,
220
+ readMinimalContextSwitch,
221
+ readFreshPromptSwitches,
222
+ GreatPlanSection,
223
+ GreatPlanForm,
224
+ };
225
+ },
226
+ });