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 CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/clawport-ui.svg)](https://www.npmjs.com/package/clawport-ui)
10
10
  [![license](https://img.shields.io/npm/l/clawport-ui.svg)](LICENSE)
11
- [![tests](https://img.shields.io/badge/tests-536%20passed-brightgreen)](#testing)
11
+ [![tests](https://img.shields.io/badge/tests-771%20passed-brightgreen)](#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 # 536 tests across 24 suites (Vitest)
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
  ```
@@ -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
+ }
@@ -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
- return NextResponse.json({ files, config, status, stats })
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
+ }