@clawos-dev/clawd 0.2.126-beta.252.5b08fb0 → 0.2.126-beta.253.542a917

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.
@@ -1,10 +1,13 @@
1
1
  import { Module } from '@nestjs/common';
2
- import { MessagesModule } from './messages/messages.module';
3
2
 
4
- // dev 模式:main.ts mount vite middleware 处理非 /api 路径(含 HMR);
5
- // prod 模式:main.ts express.static serve build 后的 web/dist。
6
- // 两种模式都不用 ServeStaticModule(vite middleware 跟它会撞),就近在 main.ts 处理。
3
+ // 默认空白骨架 —— 没有任何业务 controller / service / module 注册。
4
+ // 历史背景:之前导入 MessagesModule 自带留言板 API + Supabase repo,用户起 dev server 时 nest
5
+ // 启动会初始化 supabase 模块(控制台 noise + 旁边业务代码会暗示 assistant 沿用留言板风格)。
6
+ // 瘦身后只留启动骨架,业务逻辑由 assistant 按用户需求从零加(添 controller/module 进 imports 即可)。
7
+ //
8
+ // vite middleware / 静态资源 serve 路径仍由 main.ts 处理(dev mount vite,prod express.static),
9
+ // 不需要 ServeStaticModule。
7
10
  @Module({
8
- imports: [MessagesModule],
11
+ imports: [],
9
12
  })
10
13
  export class AppModule {}
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>留言板 · 全链路测试</title>
6
+ <title>App</title>
7
7
  </head>
8
8
  <body>
9
9
  <div id="root"></div>
@@ -1,161 +1,11 @@
1
- import React, { useEffect, useState } from 'react';
2
-
3
- const styles = {
4
- page: {
5
- minHeight: '100vh',
6
- margin: 0,
7
- background: 'linear-gradient(160deg, #0f172a 0%, #1e293b 100%)',
8
- color: '#e2e8f0',
9
- fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
10
- display: 'flex',
11
- justifyContent: 'center',
12
- padding: '48px 16px',
13
- },
14
- card: {
15
- width: '100%',
16
- maxWidth: 560,
17
- },
18
- title: { fontSize: 28, fontWeight: 700, margin: '0 0 4px' },
19
- subtitle: { color: '#94a3b8', margin: '0 0 24px', fontSize: 14 },
20
- form: { display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 28 },
21
- row: { display: 'flex', gap: 10 },
22
- input: {
23
- flex: 1,
24
- padding: '10px 12px',
25
- borderRadius: 8,
26
- border: '1px solid #334155',
27
- background: '#0f172a',
28
- color: '#e2e8f0',
29
- fontSize: 14,
30
- outline: 'none',
31
- },
32
- textarea: {
33
- padding: '10px 12px',
34
- borderRadius: 8,
35
- border: '1px solid #334155',
36
- background: '#0f172a',
37
- color: '#e2e8f0',
38
- fontSize: 14,
39
- outline: 'none',
40
- resize: 'vertical',
41
- minHeight: 64,
42
- },
43
- button: {
44
- padding: '10px 20px',
45
- borderRadius: 8,
46
- border: 'none',
47
- background: '#6366f1',
48
- color: '#fff',
49
- fontSize: 14,
50
- fontWeight: 600,
51
- cursor: 'pointer',
52
- },
53
- msg: {
54
- padding: '12px 14px',
55
- borderRadius: 10,
56
- background: '#1e293b',
57
- border: '1px solid #334155',
58
- marginBottom: 10,
59
- },
60
- msgHead: { display: 'flex', justifyContent: 'space-between', marginBottom: 4 },
61
- msgName: { fontWeight: 600, color: '#a5b4fc', fontSize: 14 },
62
- msgTime: { color: '#64748b', fontSize: 12 },
63
- msgBody: { fontSize: 14, lineHeight: 1.5, whiteSpace: 'pre-wrap' },
64
- error: { color: '#f87171', fontSize: 13, marginBottom: 12 },
65
- empty: { color: '#64748b', fontSize: 14, textAlign: 'center', padding: '24px 0' },
66
- };
67
-
1
+ // 默认空白页骨架 —— createProject + startDevServer 起来时 iframe 第一帧就是干净白板,
2
+ // 不会闪一下 demo 内容再被 assistant 改成用户实际想要的页面。
3
+ //
4
+ // 历史背景:之前模板自带留言板 demo(App.jsx + messages controller),用户从「新建项目 →
5
+ // 起 dev server → 假设 assistant 改 App.jsx 成 hello world」整个流程里第一眼看到的是留言板
6
+ // UI,HMR 替换后才变成真正的内容 —— 视觉闪动 + 业务代码被模板暗示带偏(spec follow-up
7
+ // 2026-06-03 老板拍)。瘦身后骨架只保留 vite + nest + react 可启动结构,内容由 assistant
8
+ // 按用户需求从零写。
68
9
  export default function App() {
69
- const [messages, setMessages] = useState([]);
70
- const [name, setName] = useState('');
71
- const [content, setContent] = useState('');
72
- const [error, setError] = useState('');
73
- const [loading, setLoading] = useState(false);
74
-
75
- async function load() {
76
- try {
77
- const res = await fetch(`${import.meta.env.BASE_URL}api/messages`);
78
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
79
- setMessages(await res.json());
80
- setError('');
81
- } catch (e) {
82
- setError(`加载失败: ${e.message}`);
83
- }
84
- }
85
-
86
- useEffect(() => {
87
- load();
88
- }, []);
89
-
90
- async function submit(e) {
91
- e.preventDefault();
92
- if (!content.trim()) return;
93
- setLoading(true);
94
- try {
95
- const res = await fetch(`${import.meta.env.BASE_URL}api/messages`, {
96
- method: 'POST',
97
- headers: { 'Content-Type': 'application/json' },
98
- body: JSON.stringify({ name, content }),
99
- });
100
- if (!res.ok) {
101
- const body = await res.json().catch(() => ({}));
102
- throw new Error(body.message || `HTTP ${res.status}`);
103
- }
104
- setContent('');
105
- await load();
106
- } catch (e) {
107
- setError(`提交失败: ${e.message}`);
108
- } finally {
109
- setLoading(false);
110
- }
111
- }
112
-
113
- return (
114
- <div style={styles.page}>
115
- <div style={styles.card}>
116
- <h1 style={styles.title}>留言板</h1>
117
- <p style={styles.subtitle}>
118
- 前端 React → NestJS → Supabase 全链路连通性测试
119
- </p>
120
-
121
- <form style={styles.form} onSubmit={submit}>
122
- <input
123
- style={styles.input}
124
- placeholder="你的名字(可选)"
125
- value={name}
126
- onChange={(e) => setName(e.target.value)}
127
- />
128
- <textarea
129
- style={styles.textarea}
130
- placeholder="写点什么…"
131
- value={content}
132
- onChange={(e) => setContent(e.target.value)}
133
- />
134
- <div style={styles.row}>
135
- <button style={styles.button} type="submit" disabled={loading}>
136
- {loading ? '提交中…' : '提交留言'}
137
- </button>
138
- </div>
139
- </form>
140
-
141
- {error && <div style={styles.error}>{error}</div>}
142
-
143
- {messages.length === 0 ? (
144
- <div style={styles.empty}>还没有留言,来写第一条吧</div>
145
- ) : (
146
- messages.map((m) => (
147
- <div key={m.id} style={styles.msg}>
148
- <div style={styles.msgHead}>
149
- <span style={styles.msgName}>{m.name}</span>
150
- <span style={styles.msgTime}>
151
- {new Date(m.created_at).toLocaleString('zh-CN')}
152
- </span>
153
- </div>
154
- <div style={styles.msgBody}>{m.content}</div>
155
- </div>
156
- ))
157
- )}
158
- </div>
159
- </div>
160
- );
10
+ return <div />;
161
11
  }
@@ -86,7 +86,14 @@ if [ -n "$DOM" ]; then
86
86
  # 整体失败 → daemon runner 走 publish-failed 路径 + 回灌 chat 让 assistant 接管修复。
87
87
  # 之前的 `|| true` 兜底已去掉,理由:线上挂了 prodUrl 仍写盘 = 老板看到"打开线上"按钮
88
88
  # 但点开 404,不如 fail-loud。
89
- "$KIT_DIR/scripts/verify.sh" "http://$DOM"
89
+ #
90
+ # 显式走 bash 解释器调用(不依赖 verify.sh 自己的 +x 权限):
91
+ # daemon 调 publish.sh / new-extension.sh 都是 `spawn('bash', [scriptPath, ...])`,所以即使脚本
92
+ # +x bit 丢了(历史上有过:OTA 解包 / cp -p 未带 / desktop 旧包 mode 不对)也能跑。但这一行
93
+ # 之前是 direct-exec `"$KIT_DIR/scripts/verify.sh"`,OS 会检查 +x —— verify.sh 因此成为唯一
94
+ # 暴露 +x 丢失问题的执行点(老板撞到过一次"verify.sh permission denied")。
95
+ # 改 bash 调用后永远不再依赖 fs +x bit。
96
+ bash "$KIT_DIR/scripts/verify.sh" "http://$DOM"
90
97
  else
91
98
  # 域名没拿到 = 部署本身有问题(fc3-domain 未成功),也算失败
92
99
  echo "❌ 部署完成但未取到自定义域名,检查 fc3-domain 是否成功" >&2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.126-beta.252.5b08fb0",
3
+ "version": "0.2.126-beta.253.542a917",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,27 +0,0 @@
1
- import {
2
- BadRequestException,
3
- Body,
4
- Controller,
5
- Get,
6
- Post,
7
- } from '@nestjs/common';
8
- import { MessagesService } from './messages.service';
9
-
10
- @Controller('messages')
11
- export class MessagesController {
12
- constructor(private readonly messages: MessagesService) {}
13
-
14
- @Get()
15
- list() {
16
- return this.messages.list();
17
- }
18
-
19
- @Post()
20
- create(@Body() body: { name?: string; content?: string }) {
21
- const content = body?.content?.trim();
22
- if (!content) {
23
- throw new BadRequestException('content 不能为空');
24
- }
25
- return this.messages.create(body.name?.trim() ?? '', content);
26
- }
27
- }
@@ -1,9 +0,0 @@
1
- import { Module } from '@nestjs/common';
2
- import { MessagesController } from './messages.controller';
3
- import { MessagesService } from './messages.service';
4
-
5
- @Module({
6
- controllers: [MessagesController],
7
- providers: [MessagesService],
8
- })
9
- export class MessagesModule {}
@@ -1,49 +0,0 @@
1
- import { Injectable } from '@nestjs/common';
2
- import { createClient, SupabaseClient } from '@supabase/supabase-js';
3
-
4
- const TABLE = 'guestbook_messages';
5
-
6
- // 模板示例 service。Supabase client **lazy 初始化**:
7
- // - constructor 不读 env / 不 throw —— 让整个 nest server 能起来即使 SUPABASE_URL/KEY 没配
8
- // (比如 fresh project 还没接 Supabase,老板只想看个 welcome 页面)
9
- // - 实际调 list / create 时再 require,缺 env 时只报给这条 API 的 caller,不阻塞 server 启动
10
- //
11
- // 老 bug:constructor 里硬 require + throw → 没配 env 时 NestApplication 启动直接 crash,
12
- // dev server 进 exit 1 → preview iframe upstream error 糊脸。
13
- @Injectable()
14
- export class MessagesService {
15
- private _supabase: SupabaseClient | null = null;
16
-
17
- private get supabase(): SupabaseClient {
18
- if (this._supabase) return this._supabase;
19
- const url = process.env.SUPABASE_URL;
20
- const key = process.env.SUPABASE_KEY;
21
- if (!url || !key) {
22
- throw new Error(
23
- 'SUPABASE_URL / SUPABASE_KEY 未配置 —— 请先接 Supabase 后端再调 /api/messages',
24
- );
25
- }
26
- this._supabase = createClient(url, key);
27
- return this._supabase;
28
- }
29
-
30
- async list() {
31
- const { data, error } = await this.supabase
32
- .from(TABLE)
33
- .select('*')
34
- .order('created_at', { ascending: false })
35
- .limit(100);
36
- if (error) throw new Error(`读取留言失败: ${error.message}`);
37
- return data;
38
- }
39
-
40
- async create(name: string, content: string) {
41
- const { data, error } = await this.supabase
42
- .from(TABLE)
43
- .insert({ name: name || 'anonymous', content })
44
- .select()
45
- .single();
46
- if (error) throw new Error(`写入留言失败: ${error.message}`);
47
- return data;
48
- }
49
- }