@chengxianglibra/dsh-data-analysis 0.2.0 → 0.2.2
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/README.en.md +138 -0
- package/README.md +55 -82
- package/lib/client/credentials/install.js +3 -3
- package/lib/client/i18n/copy.js +4 -1
- package/lib/client/i18n/host.js +1 -0
- package/lib/client/i18n/settings.js +30 -0
- package/lib/client/input-context.js +1 -1
- package/lib/client/python-tool/card.js +2 -2
- package/lib/client/python-tool/model.js +1 -1
- package/lib/client/right-tabs/install.js +10 -7
- package/lib/client/settings/card.js +90 -0
- package/lib/client/settings/install.js +14 -0
- package/lib/client.js +104 -70
- package/lib/datasource/changes-contract.js +6 -2
- package/lib/datasource/configure.js +1 -1
- package/lib/datasource/python-options.js +1 -7
- package/lib/datasource/python.js +12 -7
- package/lib/datasource/test.js +1 -1
- package/lib/disclosure/execution-guidance.js +5 -8
- package/lib/plugin-agents.js +2 -2
- package/lib/plugin.js +14 -4
- package/lib/presentation/assets/portable.js +1 -1
- package/lib/presentation/assets/static.js +47 -47
- package/lib/presentation/execution-policy.js +5 -0
- package/lib/presentation/projection/index.js +27 -10
- package/lib/presentation/tool.js +2 -1
- package/lib/settings.js +17 -0
- package/lib/types/client/i18n/copy.d.ts +15 -0
- package/lib/types/client/i18n/host.d.ts +1 -0
- package/lib/types/client/i18n/settings.d.ts +16 -0
- package/lib/types/client/settings/card.d.ts +9 -0
- package/lib/types/client/settings/install.d.ts +2 -0
- package/lib/types/client.d.ts +2 -2
- package/lib/types/datasource/python-options.d.ts +1 -2
- package/lib/types/datasource/python.d.ts +2 -2
- package/lib/types/disclosure/execution-guidance.d.ts +8 -0
- package/lib/types/plugin-agents.d.ts +2 -0
- package/lib/types/plugin.d.ts +23 -3
- package/lib/types/presentation/execution-policy.d.ts +5 -0
- package/lib/types/rpc.d.ts +2 -2
- package/lib/types/semantic-reference/rpc.d.ts +2 -2
- package/lib/types/settings.d.ts +14 -0
- package/package.json +85 -65
- package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
- package/skills/dsh-data-analysis-files/SKILL.md +22 -10
- package/skills/dsh-data-analysis-files/references/delivery.md +15 -0
- package/skills/dsh-data-analysis-presentation/SKILL.md +15 -19
- package/skills/dsh-data-analysis-presentation/references/schema.md +4 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useState, useSyncExternalStore } from 'react';
|
|
3
|
+
import { useCopy } from "../i18n/context.js";
|
|
4
|
+
/** Seconds in the form, exact integer milliseconds at the Host boundary. */
|
|
5
|
+
export function timeoutMilliseconds(text) {
|
|
6
|
+
if (!/^\d+(?:\.\d{1,3})?$/.test(text.trim()))
|
|
7
|
+
return undefined;
|
|
8
|
+
const value = Math.round(Number(text) * 1000);
|
|
9
|
+
return Number.isSafeInteger(value) && value > 0 && value <= 2_147_483_647 ? value : undefined;
|
|
10
|
+
}
|
|
11
|
+
export function PythonSettingsCard({ scope }) {
|
|
12
|
+
const t = useCopy();
|
|
13
|
+
const subscribe = useCallback((listener) => scope.subscribe(listener), [scope]);
|
|
14
|
+
const getSnapshot = useCallback(() => scope.getSnapshot(), [scope]);
|
|
15
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
16
|
+
const [draft, setDraft] = useState();
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
const [saving, setSaving] = useState(false);
|
|
19
|
+
const [failed, setFailed] = useState(false);
|
|
20
|
+
if (snapshot.status !== 'ready' || !snapshot.value)
|
|
21
|
+
return null;
|
|
22
|
+
const text = draft?.text ?? String(snapshot.value.pythonTimeoutMs / 1000);
|
|
23
|
+
const timeoutMs = timeoutMilliseconds(text);
|
|
24
|
+
const disabled = !snapshot.writable || saving;
|
|
25
|
+
const edit = (text) => {
|
|
26
|
+
if (snapshot.revision === undefined)
|
|
27
|
+
return;
|
|
28
|
+
setDraft({ text, revision: draft?.revision ?? snapshot.revision });
|
|
29
|
+
setFailed(false);
|
|
30
|
+
};
|
|
31
|
+
const save = async () => {
|
|
32
|
+
if (!draft || disabled || timeoutMs === undefined)
|
|
33
|
+
return;
|
|
34
|
+
setSaving(true);
|
|
35
|
+
setFailed(false);
|
|
36
|
+
try {
|
|
37
|
+
await scope.mutate([{ op: 'set', path: ['pythonTimeoutMs'], value: timeoutMs }], draft.revision);
|
|
38
|
+
// A refused Host write can settle normally after the scope recovers its snapshot.
|
|
39
|
+
const latest = scope.getSnapshot();
|
|
40
|
+
const user = latest.user;
|
|
41
|
+
const overridden = user != null && Object.hasOwn(user, 'pythonTimeoutMs');
|
|
42
|
+
const landed = latest.status === 'ready' &&
|
|
43
|
+
latest.value !== undefined &&
|
|
44
|
+
overridden &&
|
|
45
|
+
user?.pythonTimeoutMs === timeoutMs &&
|
|
46
|
+
latest.value.pythonTimeoutMs === timeoutMs;
|
|
47
|
+
if (landed) {
|
|
48
|
+
setDraft(undefined);
|
|
49
|
+
setOpen(false);
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
setFailed(true);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
setFailed(true);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
setSaving(false);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return (_jsxs("li", { className: `marivo-settings-card${open ? ' marivo-settings-open' : ''}`, children: [_jsx("style", { children: styles }), _jsxs("button", { type: "button", className: "marivo-settings-header", "aria-expanded": open, "aria-controls": "marivo-settings-body", "aria-label": `${t(open ? 'marivo.settings.collapse' : 'marivo.settings.expand')}: ${t('marivo.settings.title')}`, onClick: () => setOpen(!open), children: [_jsxs("span", { className: "marivo-settings-heading", children: [_jsx("span", { className: "marivo-settings-name", children: t('marivo.settings.title') }), _jsx("span", { className: "marivo-settings-description", children: t('marivo.settings.description') })] }), draft && (_jsx("span", { className: "marivo-settings-pending", role: "status", children: t('marivo.settings.unsaved') })), _jsx("svg", { className: "marivo-settings-chevron", width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "m3 5 4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), open && (_jsxs("div", { id: "marivo-settings-body", className: "marivo-settings-body", children: [_jsxs("div", { className: "marivo-settings-field", children: [_jsx("label", { htmlFor: "marivo-python-timeout", children: t('marivo.settings.timeout') }), _jsx("input", { id: "marivo-python-timeout", type: "number", min: "0.001", max: "2147483.647", step: "0.001", value: text, disabled: disabled, "aria-describedby": "marivo-python-timeout-hint", "aria-invalid": timeoutMs === undefined, onChange: (event) => edit(event.target.value) }), _jsx("p", { id: "marivo-python-timeout-hint", children: t('marivo.settings.hint') }), timeoutMs === undefined && _jsx("p", { role: "alert", children: t('marivo.settings.invalid') }), !snapshot.writable && _jsx("p", { role: "status", children: t('marivo.settings.read-only') }), failed && _jsx("p", { role: "alert", children: t('marivo.settings.failed') })] }), _jsxs("div", { className: "marivo-settings-actions", children: [_jsx("button", { type: "button", disabled: saving || !draft, onClick: () => {
|
|
62
|
+
setDraft(undefined);
|
|
63
|
+
setFailed(false);
|
|
64
|
+
}, children: t('marivo.settings.discard') }), _jsx("button", { type: "button", className: "marivo-settings-save", disabled: disabled || !draft || timeoutMs === undefined, onClick: () => void save(), children: t(saving ? 'marivo.settings.saving' : 'marivo.settings.save') })] })] }))] }));
|
|
65
|
+
}
|
|
66
|
+
// Match Harness PluginCard/fields chrome; those components are not public runtime exports.
|
|
67
|
+
const styles = `
|
|
68
|
+
.marivo-settings-card{list-style:none;border:.5px solid var(--dsw-alias-border-l4,#ddd);border-radius:16px;background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-primary,#202124);transition:border-color .16s,background .16s}
|
|
69
|
+
.marivo-settings-card:hover,.marivo-settings-open{border-color:var(--dsw-alias-label-dimmed,#ccc)}
|
|
70
|
+
.marivo-settings-open{background:var(--dsw-alias-bg-layer-2,#fff)}
|
|
71
|
+
.marivo-settings-header{box-sizing:border-box;width:100%;appearance:none;border:0;background:none;font:inherit;color:inherit;text-align:left;cursor:pointer;display:flex;align-items:center;gap:12px;padding:14px 16px;border-radius:12px}
|
|
72
|
+
.marivo-settings-heading{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
|
|
73
|
+
.marivo-settings-name{font-size:15px;font-weight:600;line-height:1.4}
|
|
74
|
+
.marivo-settings-description{font-size:13px;line-height:1.5;color:var(--dsw-alias-label-tertiary,#888)}
|
|
75
|
+
.marivo-settings-chevron{flex:none;color:var(--dsw-alias-label-tertiary,#888);transition:transform .16s}
|
|
76
|
+
.marivo-settings-open .marivo-settings-chevron{transform:rotate(180deg)}
|
|
77
|
+
.marivo-settings-pending{flex:none;font-size:12px;border-radius:4px;padding:0 4px;background:var(--dsw-alias-bg-layer-1,#f5f5f5);color:var(--dsw-alias-label-tertiary,#888)}
|
|
78
|
+
.marivo-settings-body{border-top:.5px solid var(--dsw-alias-border-l2,#eee);margin:0 16px;padding-bottom:8px}
|
|
79
|
+
.marivo-settings-field{display:flex;flex-direction:column;gap:6px;padding:12px 0}
|
|
80
|
+
.marivo-settings-body p{margin:0;font-size:12px;color:var(--dsw-alias-label-tertiary,#888);line-height:1.5}
|
|
81
|
+
.marivo-settings-body p[role=alert]{color:var(--dsw-alias-label-error,#c33)}
|
|
82
|
+
.marivo-settings-body label{font-size:13px;line-height:1.5;font-weight:500}
|
|
83
|
+
.marivo-settings-field input{box-sizing:border-box;width:100%;min-width:0;height:34px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l4,#ddd);border-radius:8px;background:var(--dsw-alias-bg-layer-3,#fff);font:inherit;font-size:13px;line-height:1.5;color:inherit}
|
|
84
|
+
.marivo-settings-field input[aria-invalid=true]{border-color:var(--dsw-alias-label-error,#c33)}
|
|
85
|
+
.marivo-settings-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 0 4px;border-top:.5px solid var(--dsw-alias-border-l2,#eee)}
|
|
86
|
+
.marivo-settings-actions button{appearance:none;border:1px solid var(--dsw-alias-border-l2,#ddd);border-radius:8px;padding:5px 14px;font:inherit;font-size:13px;line-height:1.5;cursor:pointer;background:none;color:var(--dsw-alias-label-secondary,#666)}
|
|
87
|
+
.marivo-settings-actions .marivo-settings-save{border-color:transparent;background:var(--dsw-alias-label-primary,#202124);color:var(--dsw-alias-bg-layer-3,#fff)}
|
|
88
|
+
.marivo-settings-card :disabled{opacity:.4;cursor:default}
|
|
89
|
+
.marivo-settings-card :focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#4682e9);outline-offset:1px}
|
|
90
|
+
`;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { localized } from "../i18n/host.js";
|
|
3
|
+
import { PythonSettingsCard } from "./card.js";
|
|
4
|
+
export function installSettings(ctx) {
|
|
5
|
+
const scope = ctx.configForms.get('dsh-data-analysis');
|
|
6
|
+
const Card = localized(ctx, PythonSettingsCard);
|
|
7
|
+
ctx.effect(() => ctx.configForms.whileServed(['dsh-data-analysis'], () => ctx.slots.inject('plugins.bundle.config', () => ctx.slots.register({
|
|
8
|
+
name: 'plugins.bundle.config',
|
|
9
|
+
key: '@chengxianglibra/dsh-data-analysis',
|
|
10
|
+
locale: 'marivo.settings',
|
|
11
|
+
}, function SettingsCard() {
|
|
12
|
+
return _jsx(Card, { scope: scope });
|
|
13
|
+
}))));
|
|
14
|
+
}
|