@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.
Files changed (48) hide show
  1. package/README.en.md +138 -0
  2. package/README.md +55 -82
  3. package/lib/client/credentials/install.js +3 -3
  4. package/lib/client/i18n/copy.js +4 -1
  5. package/lib/client/i18n/host.js +1 -0
  6. package/lib/client/i18n/settings.js +30 -0
  7. package/lib/client/input-context.js +1 -1
  8. package/lib/client/python-tool/card.js +2 -2
  9. package/lib/client/python-tool/model.js +1 -1
  10. package/lib/client/right-tabs/install.js +10 -7
  11. package/lib/client/settings/card.js +90 -0
  12. package/lib/client/settings/install.js +14 -0
  13. package/lib/client.js +104 -70
  14. package/lib/datasource/changes-contract.js +6 -2
  15. package/lib/datasource/configure.js +1 -1
  16. package/lib/datasource/python-options.js +1 -7
  17. package/lib/datasource/python.js +12 -7
  18. package/lib/datasource/test.js +1 -1
  19. package/lib/disclosure/execution-guidance.js +5 -8
  20. package/lib/plugin-agents.js +2 -2
  21. package/lib/plugin.js +14 -4
  22. package/lib/presentation/assets/portable.js +1 -1
  23. package/lib/presentation/assets/static.js +47 -47
  24. package/lib/presentation/execution-policy.js +5 -0
  25. package/lib/presentation/projection/index.js +27 -10
  26. package/lib/presentation/tool.js +2 -1
  27. package/lib/settings.js +17 -0
  28. package/lib/types/client/i18n/copy.d.ts +15 -0
  29. package/lib/types/client/i18n/host.d.ts +1 -0
  30. package/lib/types/client/i18n/settings.d.ts +16 -0
  31. package/lib/types/client/settings/card.d.ts +9 -0
  32. package/lib/types/client/settings/install.d.ts +2 -0
  33. package/lib/types/client.d.ts +2 -2
  34. package/lib/types/datasource/python-options.d.ts +1 -2
  35. package/lib/types/datasource/python.d.ts +2 -2
  36. package/lib/types/disclosure/execution-guidance.d.ts +8 -0
  37. package/lib/types/plugin-agents.d.ts +2 -0
  38. package/lib/types/plugin.d.ts +23 -3
  39. package/lib/types/presentation/execution-policy.d.ts +5 -0
  40. package/lib/types/rpc.d.ts +2 -2
  41. package/lib/types/semantic-reference/rpc.d.ts +2 -2
  42. package/lib/types/settings.d.ts +14 -0
  43. package/package.json +85 -65
  44. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  45. package/skills/dsh-data-analysis-files/SKILL.md +22 -10
  46. package/skills/dsh-data-analysis-files/references/delivery.md +15 -0
  47. package/skills/dsh-data-analysis-presentation/SKILL.md +15 -19
  48. 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
+ }