@onefl666/dsh-great-plan 0.0.0-stage → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +102 -2
- package/README.zh-CN.md +103 -0
- package/cordis.patch.yml +3 -0
- package/icon.svg +19 -0
- package/lib/client.actions.js +963 -0
- package/lib/client.js +366 -0
- package/lib/client.model.js +232 -0
- package/lib/client.panel.js +749 -0
- package/lib/client.preset.js +115 -0
- package/lib/client.settings.js +168 -0
- package/lib/client.ui.js +528 -0
- package/lib/host/apply.js +25 -0
- package/lib/host/config.js +19 -0
- package/lib/host/plan-compaction.js +135 -0
- package/lib/host/plan-evidence.js +195 -0
- package/lib/host/plan-range.js +35 -0
- package/lib/index.js +2 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +69 -4
|
@@ -0,0 +1,115 @@
|
|
|
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 BUILTINS = {
|
|
10
|
+
standard: { name: 'preset.standard', description: 'preset.standardDescription' },
|
|
11
|
+
ptc: { name: 'preset.ptc', description: 'preset.ptcDescription' },
|
|
12
|
+
minimal: { name: 'preset.minimal', description: 'preset.minimalDescription' },
|
|
13
|
+
cordis: { name: 'preset.cordis', description: 'preset.cordisDescription' },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function createPresetStore(ctx) {
|
|
17
|
+
const store = ui.createStore({ status: 'idle', options: [], error: null });
|
|
18
|
+
let inflight;
|
|
19
|
+
|
|
20
|
+
async function load(force = false) {
|
|
21
|
+
if (inflight !== undefined) return inflight;
|
|
22
|
+
const state = store.getSnapshot();
|
|
23
|
+
if (!force && state.status === 'ready') return undefined;
|
|
24
|
+
store.set({ ...state, status: 'loading', error: null });
|
|
25
|
+
inflight = (async () => {
|
|
26
|
+
const presets = ctx.remote?.agentPresets;
|
|
27
|
+
if (presets?.list === undefined) {
|
|
28
|
+
store.set({ status: 'unavailable', options: [], error: null });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const result = await presets.list();
|
|
32
|
+
if (!result.ok) {
|
|
33
|
+
if (result.error.code === 'gateway/invocation-unavailable') {
|
|
34
|
+
store.set({ status: 'unavailable', options: [], error: null });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
store.set({ status: 'error', options: [], error: result.error.message });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const options = (result.value?.presets ?? [])
|
|
41
|
+
.filter((preset) => preset.broken === undefined)
|
|
42
|
+
.map((preset) => ({
|
|
43
|
+
id: preset.id,
|
|
44
|
+
name: preset.name,
|
|
45
|
+
description: preset.description,
|
|
46
|
+
isDefault: preset.isDefault === true,
|
|
47
|
+
}));
|
|
48
|
+
store.set({ status: options.length === 0 ? 'unavailable' : 'ready', options, error: null });
|
|
49
|
+
})().catch((error) => {
|
|
50
|
+
store.set({ status: 'error', options: [], error: ui.messageOf(error) });
|
|
51
|
+
}).finally(() => {
|
|
52
|
+
inflight = undefined;
|
|
53
|
+
});
|
|
54
|
+
return inflight;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return { store, load };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function presetDisplay(option, t) {
|
|
61
|
+
if (option?.name !== undefined && option.name !== '') return option.name;
|
|
62
|
+
const key = option === undefined ? undefined : BUILTINS[option.id]?.name;
|
|
63
|
+
return key === undefined ? (option?.id ?? '') : t(key);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function presetDescription(option, t) {
|
|
67
|
+
if (option?.description !== undefined && option.description !== '') return option.description;
|
|
68
|
+
const key = option === undefined ? undefined : BUILTINS[option.id]?.description;
|
|
69
|
+
return key === undefined ? undefined : t(key);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function defaultPresetId(state) {
|
|
73
|
+
return state.options.find((option) => option.isDefault === true)?.id;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function PresetOptions({ state, t, selectedId, onPick, onRetry }) {
|
|
77
|
+
const options = state.options ?? [];
|
|
78
|
+
const showLoading = state.status === 'loading' && options.length === 0;
|
|
79
|
+
if (showLoading) return h(ui.Note, null, h(ui.Loading, null, t('preset.loading')));
|
|
80
|
+
if (state.status === 'error' && options.length === 0) {
|
|
81
|
+
return h('div', null,
|
|
82
|
+
h(ui.ErrorText, null, t('preset.error', { message: state.error ?? '' })),
|
|
83
|
+
h(ui.Button, { variant: 'ghost', onClick: onRetry }, t('preset.retry')),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (state.status === 'unavailable' || options.length === 0) return h(ui.Note, null, t('preset.unavailable'));
|
|
87
|
+
return h('div', { className: 'gp-list', role: 'radiogroup', 'aria-label': t('preset.title') },
|
|
88
|
+
state.status === 'error' ? h('div', null,
|
|
89
|
+
h(ui.ErrorText, null, t('preset.error', { message: state.error ?? '' })),
|
|
90
|
+
h(ui.Button, { variant: 'ghost', onClick: onRetry }, t('preset.retry')),
|
|
91
|
+
) : null,
|
|
92
|
+
options.map((option) => {
|
|
93
|
+
const selected = option.id === selectedId;
|
|
94
|
+
return h(ui.ListRow, {
|
|
95
|
+
key: option.id,
|
|
96
|
+
title: presetDisplay(option, t),
|
|
97
|
+
description: presetDescription(option, t),
|
|
98
|
+
role: 'radio',
|
|
99
|
+
checked: selected,
|
|
100
|
+
selected,
|
|
101
|
+
onClick: () => onPick(option.id),
|
|
102
|
+
});
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
createPresetStore,
|
|
109
|
+
presetDisplay,
|
|
110
|
+
presetDescription,
|
|
111
|
+
defaultPresetId,
|
|
112
|
+
PresetOptions,
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
});
|
|
@@ -0,0 +1,168 @@
|
|
|
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
|
+
const ROWS = [
|
|
18
|
+
{ field: FIELDS.brainstorming, title: 'settings.brainstorm.title', description: 'settings.brainstorm.description' },
|
|
19
|
+
{ field: FIELDS.budget, title: 'settings.budget.title', description: 'settings.budget.description' },
|
|
20
|
+
{ field: FIELDS.originalInstructions, title: 'settings.originalInstructions.title', description: 'settings.originalInstructions.description' },
|
|
21
|
+
{ field: FIELDS.minimalContext, title: 'settings.minimalContext.title', description: 'settings.minimalContext.description' },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
/** Read one switch value from a configuration form snapshot. */
|
|
25
|
+
function readSwitchValue(snapshot, field) {
|
|
26
|
+
return snapshot?.value?.[field] !== false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Read the shared settings form snapshot, or undefined when the capability is unavailable. */
|
|
30
|
+
function readFormSnapshot(configForms) {
|
|
31
|
+
if (configForms === undefined || configForms === null || typeof configForms.get !== 'function') return undefined;
|
|
32
|
+
const form = configForms.get('great-plan');
|
|
33
|
+
if (form === undefined || form === null || typeof form.getSnapshot !== 'function') return undefined;
|
|
34
|
+
return form.getSnapshot();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Read every fresh-session prompt switch from one snapshot.
|
|
39
|
+
*
|
|
40
|
+
* The Client composes one first message, so all three booleans must come
|
|
41
|
+
* from the same form snapshot. Any unavailable or unreadable configuration
|
|
42
|
+
* keeps the Host defaults (all enabled).
|
|
43
|
+
*/
|
|
44
|
+
function readFreshPromptSwitches(configForms) {
|
|
45
|
+
try {
|
|
46
|
+
const snapshot = readFormSnapshot(configForms);
|
|
47
|
+
return {
|
|
48
|
+
unlimitedBudget: readSwitchValue(snapshot, FIELDS.budget),
|
|
49
|
+
includeOriginalInstructions: readSwitchValue(snapshot, FIELDS.originalInstructions),
|
|
50
|
+
includeMinimalContext: readSwitchValue(snapshot, FIELDS.minimalContext),
|
|
51
|
+
};
|
|
52
|
+
} catch {
|
|
53
|
+
return { unlimitedBudget: true, includeOriginalInstructions: true, includeMinimalContext: true };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Stable id for one row's description element (referenced by `aria-describedby`). */
|
|
58
|
+
function descriptionId(field) {
|
|
59
|
+
return `gp-setting-desc-${field}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Settings page section entry point.
|
|
64
|
+
*
|
|
65
|
+
* The slot may render this component without a settings capability (or with
|
|
66
|
+
* a form that never became readable). This wrapper stays hook-free: it either
|
|
67
|
+
* renders the static unavailable copy or delegates to `GreatPlanForm`, which
|
|
68
|
+
* owns the store subscription and the busy/failure state.
|
|
69
|
+
*/
|
|
70
|
+
function GreatPlanSection({ form, t }) {
|
|
71
|
+
if (form === undefined || form === null || typeof form.getSnapshot !== 'function') {
|
|
72
|
+
return h('div', { className: 'gp-settings' },
|
|
73
|
+
h('h2', { className: 'gp-settings-heading' }, t('settings.heading')),
|
|
74
|
+
h(ui.Note, null, t('settings.unavailable')),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return h(GreatPlanForm, { form, t });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Settings page body: independent switches for the plan prompt and the
|
|
82
|
+
* fresh-session execution prompt.
|
|
83
|
+
*
|
|
84
|
+
* The Host stays the fact source: accepted writes arrive through the shared
|
|
85
|
+
* configuration form, and a refused write keeps the previous value visible.
|
|
86
|
+
* Each switch that is off also offers a ghost button that writes the default
|
|
87
|
+
* (on) value back.
|
|
88
|
+
*/
|
|
89
|
+
function GreatPlanForm({ form, t }) {
|
|
90
|
+
const snapshot = ui.useStore(form) ?? {};
|
|
91
|
+
const [busy, setBusy] = React.useState(false);
|
|
92
|
+
const [failed, setFailed] = React.useState(false);
|
|
93
|
+
const status = snapshot.status;
|
|
94
|
+
const ready = status === 'ready';
|
|
95
|
+
const loading = status === 'loading' || status === 'idle';
|
|
96
|
+
const unavailable = !ready && !loading;
|
|
97
|
+
const writable = snapshot.writable !== false;
|
|
98
|
+
|
|
99
|
+
const toggle = async (field, next) => {
|
|
100
|
+
if (busy) return;
|
|
101
|
+
setFailed(false);
|
|
102
|
+
setBusy(true);
|
|
103
|
+
try {
|
|
104
|
+
const accepted = await form.set(field, next);
|
|
105
|
+
if (!accepted) setFailed(true);
|
|
106
|
+
} catch {
|
|
107
|
+
setFailed(true);
|
|
108
|
+
} finally {
|
|
109
|
+
setBusy(false);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return h('div', { className: 'gp-settings' },
|
|
114
|
+
h('h2', { className: 'gp-settings-heading' }, t('settings.heading')),
|
|
115
|
+
loading ? h(ui.Loading, null, t('settings.loading')) : null,
|
|
116
|
+
unavailable ? h(ui.Note, null, t('settings.unavailable')) : null,
|
|
117
|
+
ready
|
|
118
|
+
? ROWS.map((row) => {
|
|
119
|
+
const checked = readSwitchValue(snapshot, row.field);
|
|
120
|
+
const title = t(row.title);
|
|
121
|
+
const descId = descriptionId(row.field);
|
|
122
|
+
const disabled = busy || !writable;
|
|
123
|
+
return h('div', { key: row.field, className: 'gp-setting-row' },
|
|
124
|
+
h('div', { className: 'gp-setting-copy' },
|
|
125
|
+
h('div', { className: 'gp-setting-title' }, title),
|
|
126
|
+
h('div', { className: 'gp-setting-desc', id: descId }, t(row.description)),
|
|
127
|
+
),
|
|
128
|
+
h('div', { className: 'gp-setting-controls' },
|
|
129
|
+
checked === false ? h(ui.Button, {
|
|
130
|
+
variant: 'ghost',
|
|
131
|
+
className: 'gp-setting-reset',
|
|
132
|
+
'aria-label': t('settings.resetAria', { title }),
|
|
133
|
+
disabled,
|
|
134
|
+
onClick: () => {
|
|
135
|
+
toggle(row.field, true);
|
|
136
|
+
},
|
|
137
|
+
}, t('settings.reset')) : null,
|
|
138
|
+
h('button', {
|
|
139
|
+
type: 'button',
|
|
140
|
+
role: 'switch',
|
|
141
|
+
className: ui.cx('gp-switch', checked && 'gp-switch-on'),
|
|
142
|
+
'aria-checked': checked,
|
|
143
|
+
'aria-label': title,
|
|
144
|
+
'aria-describedby': descId,
|
|
145
|
+
disabled,
|
|
146
|
+
onClick: () => {
|
|
147
|
+
toggle(row.field, !checked);
|
|
148
|
+
},
|
|
149
|
+
}, h('span', { className: 'gp-switch-thumb' })),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
})
|
|
153
|
+
: null,
|
|
154
|
+
ready && !writable ? h(ui.Note, null, t('settings.readOnly')) : null,
|
|
155
|
+
failed ? h(ui.ErrorText, null, t('settings.saveFailed')) : null,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
FIELDS,
|
|
161
|
+
ROWS,
|
|
162
|
+
readSwitchValue,
|
|
163
|
+
readFreshPromptSwitches,
|
|
164
|
+
GreatPlanSection,
|
|
165
|
+
GreatPlanForm,
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
});
|