clawport-ui 0.8.1 → 0.8.3
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/app/agents/[id]/page.tsx +16 -0
- package/app/api/chat/[id]/route.ts +1 -1
- package/app/api/kanban/chat/[id]/route.ts +1 -1
- package/app/api/memory/reindex/route.ts +36 -0
- package/app/api/memory/route.ts +36 -1
- package/app/memory/page.tsx +1419 -49
- package/components/AgentNode.tsx +18 -0
- package/components/chat/ConversationView.tsx +1 -1
- package/lib/agents-registry.ts +43 -3
- package/lib/agents.json +20 -0
- package/lib/agents.test.ts +54 -1
- package/lib/conversations.test.ts +1 -0
- package/lib/memory-health-prompt.test.ts +247 -0
- package/lib/memory-health-prompt.ts +320 -0
- package/lib/memory-health.test.ts +440 -0
- package/lib/memory-health.ts +368 -0
- package/lib/memory-hints.test.ts +207 -0
- package/lib/memory-hints.ts +139 -0
- package/lib/memory-write.test.ts +300 -0
- package/lib/memory-write.ts +162 -0
- package/lib/slash-commands.test.ts +1 -0
- package/lib/teams.test.ts +1 -0
- package/lib/types.ts +37 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/clawport-ui)
|
|
10
10
|
[](LICENSE)
|
|
11
|
-
[](#testing)
|
|
12
12
|
|
|
13
13
|
[Website](https://clawport.dev) | [Setup Guide](SETUP.md) | [API Docs](docs/API.md) | [npm](https://www.npmjs.com/package/clawport-ui)
|
|
14
14
|
|
|
@@ -171,7 +171,7 @@ clawport help # Show usage
|
|
|
171
171
|
## Testing
|
|
172
172
|
|
|
173
173
|
```bash
|
|
174
|
-
npm test #
|
|
174
|
+
npm test # 771 tests across 31 suites (Vitest)
|
|
175
175
|
npx tsc --noEmit # Type-check (zero errors)
|
|
176
176
|
npx next build # Production build
|
|
177
177
|
```
|
package/app/agents/[id]/page.tsx
CHANGED
|
@@ -490,6 +490,22 @@ export default function AgentDetailPage({
|
|
|
490
490
|
>
|
|
491
491
|
{agent.title}
|
|
492
492
|
</p>
|
|
493
|
+
{agent.model && (
|
|
494
|
+
<span
|
|
495
|
+
style={{
|
|
496
|
+
display: "inline-block",
|
|
497
|
+
marginTop: "var(--space-1)",
|
|
498
|
+
fontSize: "var(--text-caption2)",
|
|
499
|
+
fontFamily: "var(--font-mono)",
|
|
500
|
+
color: "var(--text-tertiary)",
|
|
501
|
+
background: "var(--fill-secondary)",
|
|
502
|
+
padding: "1px 8px",
|
|
503
|
+
borderRadius: 6,
|
|
504
|
+
}}
|
|
505
|
+
>
|
|
506
|
+
{agent.model.split("/").pop()}
|
|
507
|
+
</span>
|
|
508
|
+
)}
|
|
493
509
|
{/* Color swatch */}
|
|
494
510
|
<div
|
|
495
511
|
style={{
|
|
@@ -93,7 +93,7 @@ export async function POST(
|
|
|
93
93
|
|
|
94
94
|
try {
|
|
95
95
|
const stream = await openai.chat.completions.create({
|
|
96
|
-
model: 'claude-sonnet-4-6',
|
|
96
|
+
model: agent.model || 'claude-sonnet-4-6',
|
|
97
97
|
stream: true,
|
|
98
98
|
messages: [
|
|
99
99
|
{ role: 'system' as const, content: systemPrompt },
|
|
@@ -90,7 +90,7 @@ Help the user with this ticket. Stay in character as ${agent.name}, ${agent.titl
|
|
|
90
90
|
|
|
91
91
|
try {
|
|
92
92
|
const stream = await openai.chat.completions.create({
|
|
93
|
-
model: 'claude-sonnet-4-6',
|
|
93
|
+
model: agent.model || 'claude-sonnet-4-6',
|
|
94
94
|
stream: true,
|
|
95
95
|
messages: [
|
|
96
96
|
{ role: 'system' as const, content: systemPrompt },
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { execSync } from 'child_process'
|
|
3
|
+
import { requireEnv } from '@/lib/env'
|
|
4
|
+
|
|
5
|
+
export async function POST() {
|
|
6
|
+
let bin: string
|
|
7
|
+
try {
|
|
8
|
+
bin = requireEnv('OPENCLAW_BIN')
|
|
9
|
+
} catch {
|
|
10
|
+
return NextResponse.json(
|
|
11
|
+
{ status: 'unavailable', message: 'OPENCLAW_BIN not configured', timestamp: null },
|
|
12
|
+
{ status: 503 }
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const output = execSync(`${bin} memory reindex`, {
|
|
18
|
+
timeout: 30000,
|
|
19
|
+
encoding: 'utf-8',
|
|
20
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
21
|
+
}).trim()
|
|
22
|
+
|
|
23
|
+
return NextResponse.json({
|
|
24
|
+
status: 'success',
|
|
25
|
+
message: output || 'Reindex completed',
|
|
26
|
+
timestamp: new Date().toISOString(),
|
|
27
|
+
})
|
|
28
|
+
} catch (err) {
|
|
29
|
+
const message = err instanceof Error ? err.message : 'Reindex failed'
|
|
30
|
+
return NextResponse.json({
|
|
31
|
+
status: 'failed',
|
|
32
|
+
message,
|
|
33
|
+
timestamp: new Date().toISOString(),
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
}
|
package/app/api/memory/route.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { getMemoryFiles, getMemoryConfig, getMemoryStatus, computeMemoryStats } from '@/lib/memory'
|
|
2
|
+
import { computeMemoryHealth } from '@/lib/memory-health'
|
|
3
|
+
import { writeMemoryFile, PathValidationError } from '@/lib/memory-write'
|
|
2
4
|
import { apiErrorResponse } from '@/lib/api-error'
|
|
3
5
|
import { NextResponse } from 'next/server'
|
|
4
6
|
|
|
@@ -8,8 +10,41 @@ export async function GET() {
|
|
|
8
10
|
const config = getMemoryConfig()
|
|
9
11
|
const status = getMemoryStatus()
|
|
10
12
|
const stats = computeMemoryStats(files)
|
|
11
|
-
|
|
13
|
+
const health = computeMemoryHealth(files, config, status, stats)
|
|
14
|
+
return NextResponse.json({ files, config, status, stats, health })
|
|
12
15
|
} catch (err) {
|
|
13
16
|
return apiErrorResponse(err, 'Failed to load memory files')
|
|
14
17
|
}
|
|
15
18
|
}
|
|
19
|
+
|
|
20
|
+
export async function PUT(req: Request) {
|
|
21
|
+
try {
|
|
22
|
+
const body = await req.json()
|
|
23
|
+
const { relativePath, content, expectedLastModified } = body
|
|
24
|
+
|
|
25
|
+
if (typeof content !== 'string') {
|
|
26
|
+
return NextResponse.json({ error: 'Content must be a string' }, { status: 400 })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const result = writeMemoryFile(relativePath, content, expectedLastModified)
|
|
30
|
+
return NextResponse.json({ ok: true, ...result })
|
|
31
|
+
} catch (err) {
|
|
32
|
+
if (err instanceof PathValidationError) {
|
|
33
|
+
return NextResponse.json({ error: err.message }, { status: 400 })
|
|
34
|
+
}
|
|
35
|
+
const code = (err as NodeJS.ErrnoException).code
|
|
36
|
+
if (code === 'ENOENT') {
|
|
37
|
+
return NextResponse.json({ error: 'File not found' }, { status: 404 })
|
|
38
|
+
}
|
|
39
|
+
if (code === 'E2BIG') {
|
|
40
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 413 })
|
|
41
|
+
}
|
|
42
|
+
if (code === 'ECONFLICT') {
|
|
43
|
+
return NextResponse.json(
|
|
44
|
+
{ error: 'File was modified by another process. Refresh or overwrite.' },
|
|
45
|
+
{ status: 409 }
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
return apiErrorResponse(err, 'Failed to save memory file')
|
|
49
|
+
}
|
|
50
|
+
}
|