claude-smart 0.2.31 → 0.2.32
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.md +2 -2
- package/bin/claude-smart.js +172 -18
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/dashboard/app/api/config/route.ts +11 -2
- package/plugin/dashboard/app/api/health/route.ts +45 -6
- package/plugin/dashboard/app/api/reflexio/[...path]/route.ts +15 -7
- package/plugin/dashboard/app/api/rules/applied/route.ts +27 -0
- package/plugin/dashboard/app/configure/env/page.tsx +36 -31
- package/plugin/dashboard/app/configure/layout.tsx +1 -1
- package/plugin/dashboard/app/configure/server/page.tsx +8 -14
- package/plugin/dashboard/app/dashboard/page.tsx +311 -115
- package/plugin/dashboard/app/globals.css +80 -66
- package/plugin/dashboard/app/layout.tsx +13 -10
- package/plugin/dashboard/app/preferences/[id]/page.tsx +21 -32
- package/plugin/dashboard/app/preferences/page.tsx +154 -54
- package/plugin/dashboard/app/preferences/project/[id]/page.tsx +1 -0
- package/plugin/dashboard/app/rules/[id]/page.tsx +51 -0
- package/plugin/dashboard/app/sessions/[sessionId]/page.tsx +4 -4
- package/plugin/dashboard/app/sessions/page.tsx +14 -10
- package/plugin/dashboard/app/skills/page.tsx +175 -56
- package/plugin/dashboard/app/skills/project/[id]/page.tsx +22 -38
- package/plugin/dashboard/app/skills/shared/[id]/page.tsx +20 -37
- package/plugin/dashboard/components/common/delete-learning-danger-zone.tsx +166 -0
- package/plugin/dashboard/components/common/empty-state.tsx +4 -2
- package/plugin/dashboard/components/common/learnings-badge.tsx +1 -1
- package/plugin/dashboard/components/common/page-header.tsx +5 -3
- package/plugin/dashboard/components/common/page-tabs.tsx +4 -4
- package/plugin/dashboard/components/common/stat-card.tsx +9 -5
- package/plugin/dashboard/components/layout/sidebar.tsx +24 -9
- package/plugin/dashboard/components/layout/top-bar.tsx +37 -25
- package/plugin/dashboard/components/ui/input.tsx +1 -0
- package/plugin/dashboard/hooks/use-settings.tsx +30 -61
- package/plugin/dashboard/hooks/use-stall-state.ts +5 -9
- package/plugin/dashboard/lib/config-file.ts +2 -0
- package/plugin/dashboard/lib/reflexio-client.ts +23 -48
- package/plugin/dashboard/lib/session-reader.ts +222 -6
- package/plugin/dashboard/lib/types.ts +20 -1
- package/plugin/dashboard/package-lock.json +70 -95
- package/plugin/dashboard/package.json +5 -2
- package/plugin/pyproject.toml +1 -1
- package/plugin/scripts/_lib.sh +61 -0
- package/plugin/scripts/backend-service.sh +13 -2
- package/plugin/scripts/cli.sh +1 -0
- package/plugin/scripts/codex-hook.js +100 -3
- package/plugin/scripts/dashboard-service.sh +95 -19
- package/plugin/scripts/hook_entry.sh +13 -7
- package/plugin/scripts/smart-install.sh +18 -13
- package/plugin/src/claude_smart/cli.py +86 -20
- package/plugin/src/claude_smart/context_format.py +244 -6
- package/plugin/src/claude_smart/context_inject.py +8 -1
- package/plugin/src/claude_smart/cs_cite.py +186 -34
- package/plugin/src/claude_smart/env_config.py +102 -0
- package/plugin/src/claude_smart/events/stop.py +32 -6
- package/plugin/src/claude_smart/internal_call.py +30 -0
- package/plugin/src/claude_smart/publish.py +5 -0
- package/plugin/src/claude_smart/reflexio_adapter.py +102 -26
- package/plugin/uv.lock +1 -1
|
@@ -8,14 +8,14 @@ import { Input } from "@/components/ui/input";
|
|
|
8
8
|
import { Label } from "@/components/ui/label";
|
|
9
9
|
import { Switch } from "@/components/ui/switch";
|
|
10
10
|
import { Separator } from "@/components/ui/separator";
|
|
11
|
-
import {
|
|
11
|
+
import { SETTINGS_CHANGED_EVENT } from "@/hooks/use-settings";
|
|
12
12
|
import type { ClaudeCodeHookConfig, ClaudeSmartConfig } from "@/lib/types";
|
|
13
13
|
|
|
14
14
|
export default function ConfigureEnvPage() {
|
|
15
|
-
const { reflexioUrl, setReflexioUrl } = useSettings();
|
|
16
15
|
const [config, setConfig] = useState<ClaudeSmartConfig | null>(null);
|
|
17
16
|
const [hookConfig, setHookConfig] = useState<ClaudeCodeHookConfig | null>(null);
|
|
18
17
|
const [hookDirty, setHookDirty] = useState(false);
|
|
18
|
+
const [apiKeyDirty, setApiKeyDirty] = useState(false);
|
|
19
19
|
const [error, setError] = useState<string | null>(null);
|
|
20
20
|
const [saved, setSaved] = useState(false);
|
|
21
21
|
const [saving, setSaving] = useState(false);
|
|
@@ -31,6 +31,7 @@ export default function ConfigureEnvPage() {
|
|
|
31
31
|
setConfig(envConfig);
|
|
32
32
|
setHookConfig(claudeConfig);
|
|
33
33
|
setHookDirty(false);
|
|
34
|
+
setApiKeyDirty(false);
|
|
34
35
|
})
|
|
35
36
|
.catch((e) => setError(e instanceof Error ? e.message : String(e)));
|
|
36
37
|
}, []);
|
|
@@ -63,11 +64,14 @@ export default function ConfigureEnvPage() {
|
|
|
63
64
|
setSaving(true);
|
|
64
65
|
setError(null);
|
|
65
66
|
try {
|
|
67
|
+
const envUpdate: Partial<ClaudeSmartConfig> = { ...config };
|
|
68
|
+
if (!apiKeyDirty) delete envUpdate.REFLEXIO_API_KEY;
|
|
69
|
+
delete envUpdate.REFLEXIO_API_KEY_SET;
|
|
66
70
|
const [envRes, hookRes] = await Promise.all([
|
|
67
71
|
fetch("/api/config", {
|
|
68
72
|
method: "PUT",
|
|
69
73
|
headers: { "content-type": "application/json" },
|
|
70
|
-
body: JSON.stringify(
|
|
74
|
+
body: JSON.stringify(envUpdate),
|
|
71
75
|
}),
|
|
72
76
|
fetch("/api/claude-settings", {
|
|
73
77
|
method: "PUT",
|
|
@@ -89,7 +93,9 @@ export default function ConfigureEnvPage() {
|
|
|
89
93
|
const updatedHook: ClaudeCodeHookConfig = await hookRes.json();
|
|
90
94
|
setConfig(updated);
|
|
91
95
|
setHookConfig(updatedHook);
|
|
96
|
+
window.dispatchEvent(new Event(SETTINGS_CHANGED_EVENT));
|
|
92
97
|
setHookDirty(false);
|
|
98
|
+
setApiKeyDirty(false);
|
|
93
99
|
setSaved(true);
|
|
94
100
|
} catch (e) {
|
|
95
101
|
setError(e instanceof Error ? e.message : String(e));
|
|
@@ -111,7 +117,7 @@ export default function ConfigureEnvPage() {
|
|
|
111
117
|
}
|
|
112
118
|
/>
|
|
113
119
|
|
|
114
|
-
<div className="p-6 max-w-
|
|
120
|
+
<div className="p-6 max-w-3xl mx-auto space-y-5">
|
|
115
121
|
{error && (
|
|
116
122
|
<div className="rounded-lg border border-destructive/30 bg-destructive/5 text-destructive px-4 py-3 text-sm">
|
|
117
123
|
{error}
|
|
@@ -124,27 +130,7 @@ export default function ConfigureEnvPage() {
|
|
|
124
130
|
</div>
|
|
125
131
|
)}
|
|
126
132
|
|
|
127
|
-
<section className="space-y-4">
|
|
128
|
-
<div>
|
|
129
|
-
<h2 className="text-sm font-semibold">Dashboard</h2>
|
|
130
|
-
<p className="text-xs text-muted-foreground">
|
|
131
|
-
Stored in browser localStorage — only affects this UI.
|
|
132
|
-
</p>
|
|
133
|
-
</div>
|
|
134
|
-
<div className="space-y-2">
|
|
135
|
-
<Label>Reflexio endpoint (dashboard)</Label>
|
|
136
|
-
<Input
|
|
137
|
-
value={reflexioUrl}
|
|
138
|
-
onChange={(e) => setReflexioUrl(e.target.value)}
|
|
139
|
-
className="font-mono text-xs"
|
|
140
|
-
placeholder="http://localhost:8071"
|
|
141
|
-
/>
|
|
142
|
-
</div>
|
|
143
|
-
</section>
|
|
144
|
-
|
|
145
|
-
<Separator />
|
|
146
|
-
|
|
147
|
-
<section className="space-y-4">
|
|
133
|
+
<section className="space-y-4 rounded-lg border border-border bg-card/92 p-5 shadow-sm">
|
|
148
134
|
<div>
|
|
149
135
|
<h2 className="text-sm font-semibold">claude-smart environment</h2>
|
|
150
136
|
<p className="text-xs text-muted-foreground">
|
|
@@ -162,11 +148,30 @@ export default function ConfigureEnvPage() {
|
|
|
162
148
|
<Input
|
|
163
149
|
value={config.REFLEXIO_URL}
|
|
164
150
|
onChange={(e) => update("REFLEXIO_URL", e.target.value)}
|
|
165
|
-
className="font-mono text-xs"
|
|
151
|
+
className="font-mono text-xs bg-background/80"
|
|
166
152
|
placeholder="http://localhost:8071/"
|
|
167
153
|
/>
|
|
168
154
|
</div>
|
|
169
155
|
|
|
156
|
+
<div className="space-y-2">
|
|
157
|
+
<Label>REFLEXIO_API_KEY</Label>
|
|
158
|
+
<Input
|
|
159
|
+
type="password"
|
|
160
|
+
value={String(config.REFLEXIO_API_KEY ?? "")}
|
|
161
|
+
onChange={(e) => {
|
|
162
|
+
setApiKeyDirty(true);
|
|
163
|
+
update("REFLEXIO_API_KEY", e.target.value);
|
|
164
|
+
}}
|
|
165
|
+
className="font-mono text-xs bg-background/80"
|
|
166
|
+
placeholder={
|
|
167
|
+
config.REFLEXIO_API_KEY_SET
|
|
168
|
+
? "(configured - leave blank to keep existing key)"
|
|
169
|
+
: "(empty - local mode)"
|
|
170
|
+
}
|
|
171
|
+
autoComplete="off"
|
|
172
|
+
/>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
170
175
|
<div className="flex items-start justify-between gap-4">
|
|
171
176
|
<div className="min-w-0">
|
|
172
177
|
<Label htmlFor="use-local-cli">CLAUDE_SMART_USE_LOCAL_CLI</Label>
|
|
@@ -206,7 +211,7 @@ export default function ConfigureEnvPage() {
|
|
|
206
211
|
<Input
|
|
207
212
|
value={String(config.CLAUDE_SMART_CLI_PATH ?? "")}
|
|
208
213
|
onChange={(e) => update("CLAUDE_SMART_CLI_PATH", e.target.value)}
|
|
209
|
-
className="font-mono text-xs"
|
|
214
|
+
className="font-mono text-xs bg-background/80"
|
|
210
215
|
placeholder="(empty — auto-detect via $PATH)"
|
|
211
216
|
/>
|
|
212
217
|
</div>
|
|
@@ -218,7 +223,7 @@ export default function ConfigureEnvPage() {
|
|
|
218
223
|
onChange={(e) =>
|
|
219
224
|
update("CLAUDE_SMART_CLI_TIMEOUT", e.target.value)
|
|
220
225
|
}
|
|
221
|
-
className="font-mono text-xs"
|
|
226
|
+
className="font-mono text-xs bg-background/80"
|
|
222
227
|
placeholder="120"
|
|
223
228
|
/>
|
|
224
229
|
</div>
|
|
@@ -230,7 +235,7 @@ export default function ConfigureEnvPage() {
|
|
|
230
235
|
onChange={(e) =>
|
|
231
236
|
update("CLAUDE_SMART_STATE_DIR", e.target.value)
|
|
232
237
|
}
|
|
233
|
-
className="font-mono text-xs"
|
|
238
|
+
className="font-mono text-xs bg-background/80"
|
|
234
239
|
placeholder="(empty — default ~/.claude-smart/sessions)"
|
|
235
240
|
/>
|
|
236
241
|
</div>
|
|
@@ -240,7 +245,7 @@ export default function ConfigureEnvPage() {
|
|
|
240
245
|
|
|
241
246
|
<Separator />
|
|
242
247
|
|
|
243
|
-
<section className="space-y-4">
|
|
248
|
+
<section className="space-y-4 rounded-lg border border-border bg-card/92 p-5 shadow-sm">
|
|
244
249
|
<div>
|
|
245
250
|
<h2 className="text-sm font-semibold">Claude Code hook environment</h2>
|
|
246
251
|
<p className="text-xs text-muted-foreground">
|
|
@@ -270,7 +275,7 @@ export default function ConfigureEnvPage() {
|
|
|
270
275
|
onCheckedChange={updateOptimizer}
|
|
271
276
|
/>
|
|
272
277
|
</div>
|
|
273
|
-
<div className="rounded-md border border-border bg-
|
|
278
|
+
<div className="rounded-md border border-border bg-background/60 p-3 text-xs text-muted-foreground space-y-2">
|
|
274
279
|
<div className="flex items-center justify-between gap-4">
|
|
275
280
|
<span>Effective value</span>
|
|
276
281
|
<span className="font-medium text-foreground">
|
|
@@ -30,7 +30,7 @@ export default function ConfigureLayout({
|
|
|
30
30
|
|
|
31
31
|
return (
|
|
32
32
|
<div className="flex-1 flex flex-col overflow-hidden">
|
|
33
|
-
<div className="border-b border-border bg-
|
|
33
|
+
<div className="border-b border-border bg-background/72 px-6 py-4 backdrop-blur">
|
|
34
34
|
<PageTabs
|
|
35
35
|
items={tabs}
|
|
36
36
|
activeId={
|
|
@@ -6,7 +6,6 @@ import { PageHeader } from "@/components/common/page-header";
|
|
|
6
6
|
import { Button } from "@/components/ui/button";
|
|
7
7
|
import { Input } from "@/components/ui/input";
|
|
8
8
|
import { Label } from "@/components/ui/label";
|
|
9
|
-
import { useSettings } from "@/hooks/use-settings";
|
|
10
9
|
import type { ReflexioConfig } from "@/lib/types";
|
|
11
10
|
|
|
12
11
|
type ExtractorField =
|
|
@@ -14,7 +13,6 @@ type ExtractorField =
|
|
|
14
13
|
| "user_playbook_extractor_configs";
|
|
15
14
|
|
|
16
15
|
export default function ConfigureServerPage() {
|
|
17
|
-
const { reflexioUrl } = useSettings();
|
|
18
16
|
const [srvConfig, setSrvConfig] = useState<ReflexioConfig | null>(null);
|
|
19
17
|
const [srvError, setSrvError] = useState<string | null>(null);
|
|
20
18
|
const [srvSaved, setSrvSaved] = useState(false);
|
|
@@ -22,11 +20,8 @@ export default function ConfigureServerPage() {
|
|
|
22
20
|
const [srvLoading, setSrvLoading] = useState(true);
|
|
23
21
|
|
|
24
22
|
const fetchSrvConfig = useCallback(async (): Promise<ReflexioConfig> => {
|
|
25
|
-
const headers: HeadersInit = {};
|
|
26
|
-
if (reflexioUrl) headers["x-reflexio-url"] = reflexioUrl;
|
|
27
23
|
const res = await fetch("/api/reflexio/api/get_config", {
|
|
28
24
|
cache: "no-store",
|
|
29
|
-
headers,
|
|
30
25
|
});
|
|
31
26
|
if (!res.ok) {
|
|
32
27
|
const body = await res.json().catch(() => null);
|
|
@@ -36,7 +31,7 @@ export default function ConfigureServerPage() {
|
|
|
36
31
|
throw new Error(detail);
|
|
37
32
|
}
|
|
38
33
|
return (await res.json()) as ReflexioConfig;
|
|
39
|
-
}, [
|
|
34
|
+
}, []);
|
|
40
35
|
|
|
41
36
|
useEffect(() => {
|
|
42
37
|
let alive = true;
|
|
@@ -84,7 +79,6 @@ export default function ConfigureServerPage() {
|
|
|
84
79
|
setSrvError(null);
|
|
85
80
|
try {
|
|
86
81
|
const headers: HeadersInit = { "content-type": "application/json" };
|
|
87
|
-
if (reflexioUrl) headers["x-reflexio-url"] = reflexioUrl;
|
|
88
82
|
const res = await fetch("/api/reflexio/api/set_config", {
|
|
89
83
|
method: "POST",
|
|
90
84
|
headers,
|
|
@@ -120,7 +114,7 @@ export default function ConfigureServerPage() {
|
|
|
120
114
|
}
|
|
121
115
|
/>
|
|
122
116
|
|
|
123
|
-
<div className="p-6 max-w-
|
|
117
|
+
<div className="p-6 max-w-3xl mx-auto space-y-5">
|
|
124
118
|
{srvError && (
|
|
125
119
|
<div className="rounded-lg border border-destructive/30 bg-destructive/5 text-destructive px-4 py-3 text-sm">
|
|
126
120
|
{srvError}
|
|
@@ -136,7 +130,7 @@ export default function ConfigureServerPage() {
|
|
|
136
130
|
{srvLoading ? (
|
|
137
131
|
<div className="text-sm text-muted-foreground">Loading…</div>
|
|
138
132
|
) : srvConfig ? (
|
|
139
|
-
<section className="space-y-5">
|
|
133
|
+
<section className="space-y-5 rounded-lg border border-border bg-card/92 p-5 shadow-sm">
|
|
140
134
|
<div className="space-y-2">
|
|
141
135
|
<Label>Additional agent description</Label>
|
|
142
136
|
<p className="text-xs text-muted-foreground">
|
|
@@ -148,7 +142,7 @@ export default function ConfigureServerPage() {
|
|
|
148
142
|
onChange={(e) =>
|
|
149
143
|
updateSrv("agent_context_prompt", e.target.value || null)
|
|
150
144
|
}
|
|
151
|
-
className="w-full font-mono text-xs min-h-[80px] rounded-md border border-input bg-
|
|
145
|
+
className="w-full font-mono text-xs min-h-[80px] rounded-md border border-input bg-background/80 px-3 py-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
152
146
|
placeholder="(empty)"
|
|
153
147
|
/>
|
|
154
148
|
</div>
|
|
@@ -170,7 +164,7 @@ export default function ConfigureServerPage() {
|
|
|
170
164
|
Number.isFinite(n) && n > 0 ? n : undefined,
|
|
171
165
|
);
|
|
172
166
|
}}
|
|
173
|
-
className="font-mono text-xs"
|
|
167
|
+
className="font-mono text-xs bg-background/80"
|
|
174
168
|
placeholder="10"
|
|
175
169
|
/>
|
|
176
170
|
</div>
|
|
@@ -192,7 +186,7 @@ export default function ConfigureServerPage() {
|
|
|
192
186
|
Number.isFinite(n) && n > 0 ? n : undefined,
|
|
193
187
|
);
|
|
194
188
|
}}
|
|
195
|
-
className="font-mono text-xs"
|
|
189
|
+
className="font-mono text-xs bg-background/80"
|
|
196
190
|
placeholder="5"
|
|
197
191
|
/>
|
|
198
192
|
</div>
|
|
@@ -215,7 +209,7 @@ export default function ConfigureServerPage() {
|
|
|
215
209
|
e.target.value,
|
|
216
210
|
)
|
|
217
211
|
}
|
|
218
|
-
className="w-full font-mono text-xs min-h-[120px] rounded-md border border-input bg-
|
|
212
|
+
className="w-full font-mono text-xs min-h-[120px] rounded-md border border-input bg-background/80 px-3 py-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
219
213
|
/>
|
|
220
214
|
) : (
|
|
221
215
|
<div className="text-xs text-muted-foreground italic">
|
|
@@ -242,7 +236,7 @@ export default function ConfigureServerPage() {
|
|
|
242
236
|
e.target.value,
|
|
243
237
|
)
|
|
244
238
|
}
|
|
245
|
-
className="w-full font-mono text-xs min-h-[120px] rounded-md border border-input bg-
|
|
239
|
+
className="w-full font-mono text-xs min-h-[120px] rounded-md border border-input bg-background/80 px-3 py-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
246
240
|
/>
|
|
247
241
|
) : (
|
|
248
242
|
<div className="text-xs text-muted-foreground italic">
|