@tianacloud/agent-skills 1.0.10 → 1.0.11

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.
@@ -12,7 +12,59 @@
12
12
 
13
13
  模板提供 `<div id="app"></div>`。`entry` 指定的模块按正常方式启动并渲染应用。需要数据库连接时,调用 `window.tiana.connection()` 获取连接元信息,使用 `window.tiana.auth` provider 提供动态凭据;凭据只保存在内存中。加载指示器是临时的,与应用样式隔离。
14
14
 
15
- ## 确认账号与数据库
15
+ ## 当前用户信息
16
+
17
+ 托管 Web App 使用 `GET ./_tiana/session` 读取当前登录用户,路径相对于应用入口 `/web/<web_id>/`,请求携带同源 Cookie。成功响应的关键字段如下:
18
+
19
+ | 字段 | 用途 |
20
+ | --- | --- |
21
+ | `status` | 登录有效时为 `SESSION_ACTIVE`。 |
22
+ | `user.user_id` | 稳定的用户 ID,用于关联应用内的用户资料。 |
23
+ | `user.username` | 账号用户名。 |
24
+ | `user.display_name` | 显示昵称;展示时优先用它,空值时使用 username。 |
25
+ | `tenant_id` | 当前访问用户的租户 ID。 |
26
+ | `app_tenant_id` | Web App 所属租户 ID;跨租户分享时可与 tenant_id 不同。 |
27
+ | `role` | 用户在其当前租户中的角色。 |
28
+ | `is_app_owner` | 当前用户是否为这个 Web App 的创建者;布尔值,与租户 role 独立。 |
29
+ | `membership_revision` | 当前租户成员关系的版本。 |
30
+ | `session.client`、`session.expires_at` | 会话类型(`web`)和到期时间。 |
31
+
32
+ 例如在入口中显示当前用户的昵称:
33
+
34
+ ```js
35
+ export async function mount(root) {
36
+ const response = await fetch('./_tiana/session', {
37
+ credentials: 'same-origin',
38
+ cache: 'no-store',
39
+ });
40
+ if (!response.ok) throw new Error('无法读取当前用户,请重新登录。');
41
+ const session = await response.json();
42
+ const nickname = session.user.display_name || session.user.username;
43
+ const greeting = document.createElement('p');
44
+ greeting.textContent = `你好,${nickname}`;
45
+ root.append(greeting);
46
+ }
47
+ ```
48
+
49
+ 只需身份 ID 时,托管运行时也提供 `window.tiana.user.id`、`window.tiana.user.tenantId` 和 `window.tiana.appTenantId`,或从 mount 的第二个参数 context 读取相同属性;context.user 当前只有 id 与 tenantId,昵称使用上述会话接口读取。
50
+
51
+ 当前 Site 会话接口不返回头像。需要应用内头像或自定义昵称时,以 user.user_id 关联应用自己的资料记录。会话失效时停止使用旧资料并提示重新登录;身份和资料只作为运行时数据,不固化到前端发布产物。
52
+
53
+ ### App 作者判断
54
+
55
+ 需要只向 App 作者展示初始化、成员或权限管理入口时,读取上面的同源会话后使用:
56
+
57
+ ```js
58
+ const canManageApp = session.is_app_owner === true;
59
+ ```
60
+
61
+ App 作者是当前 Web 的创建者,`role` 的 `tenant_owner` 表示访问者自己所选租户的所有者,不能用来判断 App 作者。模板安装产生的新 Web 以新创建者为作者。前端判断用于展示;敏感操作交给 [Tiana Function](../../tiana-function/references/go-backend.md#app-作者与初始权限)在后端通过 `caller.IsAppOwner()` 校验。初始化数据和权限管理接口在每次请求中检查,不能仅隐藏按钮。配套 CLI Web 本地预览也返回 `is_app_owner`,正式分享仍需用作者与其他账号分别验收。
62
+
63
+ ## 选择后端与确认资源
64
+
65
+ 简单应用优先采用下文的浏览器直连 SQLite;复杂或敏感应用必须按[带后端服务的 Web 开发流程](backend-apps.md)完成后端交接和前端接入。下面两个直连章节只适用于浏览器访问数据库的部分;后端模式完成该流程后继续本文件的体验、图标与发布步骤。
66
+
67
+ ## 直连 SQLite:确认账号与数据库
16
68
 
17
69
  已确认 CLI 具备本流程命令时直接使用。命令缺失时按[开始使用](../../tiana/references/getting-started.md)安装匹配版本。
18
70
 
@@ -20,9 +72,9 @@
20
72
  2. 项目已记录且已核实可用的数据库实例 ID 可直接复用,无需列举实例。否则用 `tiana sqlite list/show` 查找;确实没有可用数据库时执行一次 `tiana sqlite create NAME --wait`,保存完整实例 ID。中断后核实原请求和实例,不重复创建。
21
73
  3. 复用已提供的实际表结构;缺少时执行 `tiana sqlite shell INSTANCE -e "SELECT name, sql FROM sqlite_schema WHERE type='table' ORDER BY name LIMIT 100" --format json`。将表结构和迁移文件保存在项目中。对已核对的 SQL 文件执行 `tiana sqlite shell INSTANCE -f schema.sql --format json`。`-e` 接受一条语句,多语句使用 `-f`。动态数据按 [JavaScript 数据库连接](../../tiana-sqlite/references/js-sdk.md)使用参数化 SQL。
22
74
  4. 复用项目中已记录、已核实的 Web ID;未记录时先用 `tiana web list --json` 查找并核实,重名时依据实际 ID 确认归属;首次创建时执行一次 `tiana web create "应用名称" -m "应用描述" --entry assets/app.js --database-instance-id DATABASE_ID --json`,保存返回的 `data.id`。Web ID 仅由 MGR 生成;CLI 不生成或提交 Web ID;描述为可选元数据(`-m`/`--description`,最多 1024 个 UTF-8 字节),名称仅用于展示,不能用名称推导 ID,不能自行指定 ID。结果未知时保持名称、描述和所有创建参数不变,重复同一条 create 命令恢复原请求,不删除待完成记录、不另发创建请求。成功后继续构建、预览或发布时复用该 ID,不重复创建。
23
- 5. 将非敏感 Web ID 和数据库 ID 保存在项目交付记录中。entry 仅能在 create 指定,包括省略后的纯文件托管类型;创建后不可修改,publish/serve/update 都不能覆盖。数据库、Git、名称、描述可用带 expected_revision 的 web update 修改。
75
+ 5. 将非敏感 Web ID 和数据库 ID 保存在项目交付记录中。entry 仅能在 create 指定,包括省略后的纯文件托管类型;创建后不可修改,publish/serve 都不能覆盖。数据库和 Git 绑定在创建时确定;名称、备注在 Console 实例基础信息编辑。
24
76
 
25
- ## 运行时数据库连接
77
+ ## 直连 SQLite:运行时数据库连接
26
78
 
27
79
  SDK、参数化 SQL 和结果解析按 [JavaScript 数据库连接](../../tiana-sqlite/references/js-sdk.md)处理。应用必须使用支持 `auth` 的 SDK 和 `window.tiana.auth` provider;`window.tiana.connection()` 用于获取连接元信息。共享 provider 和 adapter,不读取 Token 快照,不保留旧 SDK、旧 Bootstrap 或实例 Token 回退路径。
28
80
 
@@ -48,7 +100,7 @@ CLI 本地预览优先复用已保存的 CLI 登录,通过一次性本地启
48
100
 
49
101
  输出浏览器可直接执行的 ES 模块、CSS 和资源,引用使用相对路径。Vite 库模式在顶层配置 `define: { 'process.env.NODE_ENV': JSON.stringify('production') }`,并验证产物无残留引用。入口与资源路径以实际工程的构建配置为准;入口模块自行加载 CSS。不要生成或读取 tiana.app.json,不提交 style、rendering、routing 参数。
50
102
 
51
- Site 参数来自 MGR 的 web_project:name、description、固定 entry、可选 database_instance_id、git_instance_id、source_commit。实例只保存通用 Serverless 属性。首次创建可传 `--entry assets/app.js --database-instance-id DATABASE_ID --git-instance-id GIT_ID`;Git commit 可以稍后用 `web update ID --expected-revision REV --source-commit FULL_COMMIT` 录入,完整小写 40/64 位 commit 要求已有 Git 绑定。MGR 验证关联实例属于当前租户、产品正确且可用。源码构建和远端引用核验见[源码发布](../../tiana-git/references/source-releases.md),参数更新与归档发布是分开的操作,不假称两者跨服务原子提交。
103
+ Site 参数来自 MGR 的 web_project:name、description、固定 entry、可选 database_instance_id 和 git_instance_id。首次创建可传 `--entry assets/app.js --database-instance-id DATABASE_ID --git-instance-id GIT_ID`,后端模式省略数据库绑定。已有项目沿用创建时的固定关联,名称、备注在 Console 实例基础信息编辑;后端绑定使用 `web functions get/set`。源码提交记录与远程引用核验见[源码发布](../../tiana-git/references/source-releases.md),从确定提交构建并保存对应发布回执。
52
104
 
53
105
  CLI 将目录打包为 ZIP Store/Deflate 的一个 `.tweb`,根目录是零字节 web.yaml 与 data/。web.yaml 预留 Web server 配置,与 Site 参数无关,目前为空。data/ 前缀不对外暴露,底层只提供 GET/HEAD 精确文件访问,没有目录索引、默认 index.html 或 SPA fallback;底层可托管 HTML,带 entry 的 Site 使用固定 CSR/hash Bootstrap。
54
106
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  CLI 文件操作要求 1.0.4 或更新正式版,使用 `tiana file --help` 核验命令入口。WebApp 文件能力还需目标环境提供配套的 MGR、Web 与 serverless-js Bootstrap;使用前核对目标环境能力。
4
4
 
5
+ 存储分工及静态小图片的 16 KiB 上限见[数据与素材存储](storage-and-assets.md)。
6
+ 外置预置素材按[模板素材文件](template-files.md)使用 `template-assets/` 相对路径,
7
+ 业务记录和文件关联信息使用数据库,文件二进制不放入 SQL 或 Web 包。
8
+
5
9
  ## 归属和创建顺序
6
10
 
7
11
  文件归当前租户,租户成员共享,用量与数据库共用存储配额。Console 和 CLI 展示整个租户文件目录;WebApp 使用其中的 `<WebApp ID>/` 子目录。应用只传相对路径,服务端确定 tenant 和 WebApp 根,不能从 JavaScript 修改授权范围。
@@ -0,0 +1,74 @@
1
+ # 带后端服务的 Web 模板
2
+
3
+ 配套 Function CLI 与模板安装扩展部署后使用。先确认 `tiana function --help`、`tiana web functions --help` 可用;未部署环境不能当作已支持。
4
+
5
+ ## 确认资源关系
6
+
7
+ 从目标 Web 的 `web functions get WEB_ID --json` 取得后端服务 ID,逐个 `function show` 读取源码 Git。每个 Git 固定一个 main commit;共享同一 Git 的前端和多个后端服务只取这一份快照。后端服务源码位置从元信息的 source_dir 取得。
8
+
9
+ 后端数据库依据后端服务参数和实际源码确认。读取参数名与 Endpoint,再用已知 SQLite ID 的元信息核对 Endpoint;不要因为 Web 未直接绑定数据库就认为没有数据库,也不要默认复制当前租户的任意数据库。源码动态选择数据库或依赖多个数据库、无法确认对应实例时,先向用户明确该依赖,本格式目前声明一个安装 SQLite。报告只包含实例 ID、参数名和用途,不打印 Token。
10
+
11
+ 沿用[分享模板](share-template.md)对结构、seed 和公开内容的筛选。后端服务参数只导出明确可公开的业务初值;数据库 Endpoint/Token 在安装时生成。源码、JSON、SQL、前端 bundle、source map 和展示材料均检查凭据和私有数据。
12
+
13
+ 第三方 API Key 等不能作为公开参数初值分发;在模板说明中列出参数名与用途,由安装者按 [Tiana Function 参数配置](../../tiana-function/references/commands.md#参数配置与生效)填写自己的值并验证。数据库参数映射不代替第三方密钥配置;尚未配置的功能明确标为待配置。
14
+
15
+ ## 组织 metadata.json
16
+
17
+ 将各仓库快照放在一个公开工作副本的 `repositories/<key>/` 下,根部放 metadata.json、showcase 和数据库初始化 SQL。同仓前后端保持原有目录布局。例如:
18
+
19
+ ```json
20
+ {
21
+ "name": "orders",
22
+ "display_name": "订单管理",
23
+ "description": "由后端服务处理业务并访问私有 SQLite",
24
+ "database_required": true,
25
+ "private_database": true,
26
+ "schema": "db/schema.sql",
27
+ "web_repository": "app",
28
+ "repositories": [{
29
+ "key": "app",
30
+ "path": "repositories/app",
31
+ "variables": [{
32
+ "name": "FUNCTION_ID:api",
33
+ "placeholder": "__TIANA_FUNCTION_API_91ad47ef__",
34
+ "description": "本次安装的订单后端服务 ID",
35
+ "files": ["src/app.js"]
36
+ }]
37
+ }],
38
+ "functions": [{
39
+ "key": "api",
40
+ "name": "订单接口",
41
+ "repository": "app",
42
+ "source_dir": "/services/orders",
43
+ "parameters": {"MESSAGE": "欢迎使用订单服务"},
44
+ "database": {"endpoint_parameter": "SQLITE_ENDPOINT", "token_parameter": "SQLITE_TOKEN"}
45
+ }],
46
+ "site_variables": [{
47
+ "name": "FUNCTION_ID:api",
48
+ "placeholder": "__TIANA_FUNCTION_API_91ad47ef__",
49
+ "description": "本次安装的订单后端服务 ID",
50
+ "files": ["app.js"]
51
+ }]
52
+ }
53
+ ```
54
+
55
+ - `private_database: true` 创建并初始化 SQLite,但不把它绑定到 Web 的浏览器连接。后端服务通过参数访问数据库。
56
+ - `repositories` 的 key 标识逻辑仓库,path 选择 source.zip 内的快照子树。每个后端服务引用一个 repository;Web 引用 web_repository。共享关系在安装后保持。
57
+ `source_dir` 填写服务元信息中保存的仓库内目录,支持 `/` 根目录;入口目录包含 package main 的 Go 文件,所属 go.mod 可位于入口目录或仓库内上级目录;多个入口可共享同一模块。安装保留仓库目录结构,为新服务 ID 关联同一个 source_dir,不改名源码目录。同仓同目录允许多个服务引用。源码 variables 的文件路径相对于原仓库,资源 ID 引用仍按声明替换;数据库 Token 只写入运行参数。
58
+ - `parameters` 只放公开业务初值,`database` 指定接收新数据库 Endpoint/Token 的参数名。可选 `cors` 使用后端服务 CORS 配置对象。
59
+ - 仓库 variables 的 files 相对于该仓库,保持原路径;site_variables 的 files 相对于前端 dist。必须检查构建后的真实文件名及占位符仍然存在,不能照抄 `app.js`。
60
+ - `FUNCTION_ID:<key>`、`GIT_INSTANCE_ID:<key>` 引用新资源,WEB_ID、SQLITE_INSTANCE_ID 沿用本次安装值。目录结构与相对模块引用保留,Token 不作为替换变量。
61
+
62
+ 前端直接调用 `context.functions.fetch('__TIANA_FUNCTION_API_91ad47ef__', '/orders', {...})`。占位符是普通字符串,干净构建后应保留在声明的 site_variables 文件中。数据库凭据只在后端服务运行参数中,不能进入这些文件。
63
+
64
+ ## 打包与安装验证
65
+
66
+ 从固定提交导出整个公开工作副本为 source.zip;在其中 `web_repository` 选择的目录安装依赖、干净构建,再给 [pack-template.py](../scripts/pack-template.py) 传入该 dist。脚本把这些字段写入 install.json。后端服务模板必须包含源码供安装时编译,不使用 `--without-source`。用户安装时可以不额外保留纯前端仓库;后端服务使用的 Git 始终创建,同仓 Web 保留该 Git 关联。
67
+
68
+ 安装会先创建 SQLite、各 Git 和后端服务,取得所有新 ID 后关联原 source_dir、替换声明值,再保存 Git。设置新数据库参数,逐个编译后端服务并绑定 Web 后发布前端。同仓后端服务顺序构建,后一个读取前一个依赖整理后的 commit。安装失败时保留资源和回执,通过安装任务的重试继续,不能重新执行一组无关联的创建命令。
69
+
70
+ 发布分享前用另一个租户实际安装:核对一个共享 Git、两个新后端服务的原 source_dir、实际发布版本和 Web 绑定;通过另一账号的 Site Cookie 打开分享应用,执行读写,确认访问的是新 SQLite、原数据库未变且浏览器不能取得 SQLite 连接或 Token。单纯编译通过不代表分享与隔离验收通过。
71
+
72
+ ## 下载源码后继续开发
73
+
74
+ `web init-template` / `init-share-template` 只解压,不代替资源安装。读到 repositories/functions 后按逻辑 key 创建或按用户指定复用资源:每个 Git 一份、后端服务关联对应 Git;创建时传入原 source_dir,保留目录结构并替换声明的变量。初始化目标数据库,把新凭据放入后端服务参数;从 web_repository 构建前端。用 `web functions set` 保存后端服务列表后预览与发布。保留真实资源回执,重试时复用;不得将原作者后端服务或数据库 ID 留作默认值。
@@ -2,11 +2,20 @@
2
2
 
3
3
  分享的是可独立安装的材料。发布流程在工作副本中准备材料,最后更新源 Web 的稳定分享链接。
4
4
 
5
+ 带后端服务时先读[后端服务模板](function-templates.md),核对 Web → Function → SQLite 和共享 Git 关系,再按以下公开材料流程准备。
6
+
5
7
  ## 1. 核实应用与交付范围
6
8
 
7
9
  读取 `tiana web publish-share-template --help` 和 `tiana web status-share-template --help`,确认当前 CLI 支持这组命令。读取目标 Web 详情,记录当前租户、真实 Web ID、固定入口、SQLite/Git 绑定和可构建源码位置。取得对应源码,在技能目录之外建立独立工作副本,保留用户原工程和数据。
8
10
 
9
- 默认分享源码;根据工程情况可让用户选择「包含源码,允许安装和做同款」或「仅安装,不分享源码」。仅安装仍需准备同份经过公开检查的构建、安装说明、预览和封面。明确 `database_required`:运行需要 SQLite 就填 `true`,纯前端且没有 SQLite 调用就填 `false`;是否有 schema.sql 不能代替这个判断。
11
+ 默认分享源码;先按[数据与素材存储](storage-and-assets.md)检查持久化和预置素材。
12
+ 含后端服务的模板必须包含经过公开检查的后端源码,供安装时编译;安装始终创建所需后端 Git,前端源码库按安装选择处理。
13
+ 没有后端服务且没有外置素材时,可根据用户选择制作「仅安装,不分享源码」的旧格式包。含素材的
14
+ 格式 2 包需要保留 source.zip 供服务端核对;没有后端服务的模板仍可直接安装,不创建源码库。
15
+ 发布者要求不提供源码时说明此边界,不默默公开源码或删除必要素材。
16
+ 两类包都准备经过公开检查的构建、安装说明、预览和封面。需要持久保存业务记录时
17
+ 接入 SQLite 并将 `database_required` 填为 `true`;只有确实不需要数据库持久化时才填
18
+ `false`,不能根据旧 localStorage 实现或缺少 schema 就推断无数据库需求。
10
19
 
11
20
  完成条件:应用身份、源码选择、SQLite 依赖、真实入口和构建方法都有依据。
12
21
 
@@ -21,7 +30,7 @@
21
30
  | 系统初值和用户自定义内容混合 | 只有可靠区分条件时才导出通用初值 |
22
31
  | 用途、归属或可公开性不明确 | 提问后再生成 seed |
23
32
 
24
- 有疑问时说明表和字段的用途,给出「留空」「合成示例」「仅保留列出的通用初值」供用户选择。问题与报告使用字段名和统计数量,不回显隐私值。分享应用不等于授权分享个人数据;不要直接把整库 dump 当作模板。用户文件默认不带,明确可公开且应用必需的静态素材才能进入材料。
33
+ 有疑问时说明表和字段的用途,给出「留空」「合成示例」「仅保留列出的通用初值」供用户选择。问题与报告使用字段名和统计数量,不回显隐私值。分享应用不等于授权分享个人数据;不要直接把整库 dump 当作模板。用户文件默认不带。必需且可公开的预置素材按[模板素材文件](template-files.md)进入 `template-files/` 和独立安装材料,源码和 SQL 只引用应用相对路径;不复制作者链接,不把外置文件塞入 Web 包或 SQL BLOB。小图片与平台图标按存储规则处理。
25
34
 
26
35
  在临时空 SQLite 中依次执行 schema、seed;遇到第一个错误就停止修正。核对行数、主外键、约束及应用首次启动。完成条件:每张 seed 表都有明确的数据来源说明,初始化可在空库成功完成。
27
36
 
@@ -61,15 +70,19 @@
61
70
  python3 /技能实际路径/scripts/pack-template.py --source /绝对路径/source.zip --dist /干净构建目录/dist --entry assets/app.js --output /绝对路径/install.zip
62
71
  ```
63
72
 
64
- 用户选择仅安装时增加 `--without-source`。脚本封装 install.json、site.tweb、预览、封面、实际提供的 SQL 和可选源码;它不代替数据和公开内容检查。
65
- 3. 复查脚本输出的大小、SHA-256、源码选择及数据库依赖。安装包上限 32 MiB,单材料 16 MiB,所有解析层累计展开 128 MiB、5,000 个条目;site.tweb 同时遵守 16 MiB 和 4,097 条目的 Web 归档限制。超限时先移除无用依赖、压缩资源或精简材料。
73
+ 没有外置素材且发布者选择不分享源码时增加 `--without-source`。声明素材时保留
74
+ source.zip,并生成与其逐字节相同的独立 `files/`、固定格式/能力及文件清单。
75
+ 复核目标环境已支持并启用该能力。脚本不替代数据、公开内容或应用行为检查。
76
+ 3. 复查脚本输出的大小、SHA-256、源码选择及数据库依赖。有素材时再核对 file_count、file_bytes、file_manifest_sha256、源/独立素材字节和干净构建。安装包上限 32 MiB,单材料 16 MiB,所有解析层累计展开 128 MiB、5,000 个条目;site.tweb 同时遵守 16 MiB 和 4,097 条目的 Web 归档限制。超限时先移除无用依赖、压缩资源或精简材料。
66
77
  4. 执行 `tiana web publish-share-template WEB_ID --file /绝对路径/install.zip --wait --json`。上传峰值包含原模板材料、中转 ZIP 和新材料,全部计入当前租户额度。CLI 申请精确对象授权、直传上传并提交异步发布。
67
- 5. 用 `tiana web status-share-template WEB_ID --json` 核对当前 `share.package_id`、Web ID、模板名称和 URL。上传响应未知或等待被中断时先查询该状态;发布失败时检查错误和清理进度,再准备新的发布。发布完成后后台立即清理中转 ZIP,确认删除后释放其占用额度;再次上传时重新申请授权。
78
+ 5. 用 `tiana web status-share-template WEB_ID --json` 核对当前 `share.package_id`、Web ID、模板名称和 URL。支持配套字段的 CLI 还会保留 share.version、material_version 和 manifest.files;材料版本应等于本次完整安装包摘要。上传响应未知或等待被中断时先查询原状态,不把新上传当作恢复。发布失败时核对错误和中转清理。完整历史能力上线后旧版发布材料继续保留和计费,中转 ZIP 确认删除后才释放其占用额度。
68
79
 
69
80
  完成条件:服务端当前分享指向本次发布的 package_id,才能报告发布成功。交付稳定安装链接、材料摘要、源码选择、数据库结构和 seed 处理说明。链接在应用详情的“分享模板”页可复制,并显示成功安装次数。更新模板沿用该链接;同租户再次安装会复用已安装的应用。
70
81
 
71
82
  ## 撤回和做同款
72
83
 
73
- 用户要求撤回时执行 `tiana web withdraw-share-template WEB_ID --json`,再查询状态说明当前分享和清理进度。撤回影响后续安装,已安装应用继续独立使用;重新发布保留链接和累计安装次数。
84
+ 用户要求撤回时执行 `tiana web withdraw-share-template WEB_ID --json`,再查询原状态。
85
+ 完整历史能力上线后,撤回停止新安装,保留历史材料和已受理任务的原版恢复资格;
86
+ 已有应用继续独立使用。不能把 cleanup_job_id 为 0 当作历史材料已经删除或存储已释放。
74
87
 
75
88
  用户拿分享链接要求做同款时,执行 `tiana web init-share-template LINK --dir PROJECT_DIR --json`。读取回执中的 prompt 和工程 metadata.json,再按[模板初始化](template-init.md)及普通 Web 开发流程创建自己的新应用。没有源码的分享只支持落地页安装。做同款从新工程开始,原模板的安装来源与统计不跟踪这次开发。
@@ -0,0 +1,49 @@
1
+ # 数据与素材存储
2
+
3
+ 制作或修改应用、制作可安装模板时,先检查当前代码、绑定与构建产物,再决定数据库
4
+ 和素材初始化。旧 metadata、来源应用的 localStorage 实现或已有截图不足以证明存储正确。
5
+
6
+ | 内容 | 正式应用的存放方式 |
7
+ | --- | --- |
8
+ | JavaScript、CSS、运行必需的代码依赖 | 随 Web 构建打包;CSS 可独立随包或内嵌 JS |
9
+ | 需要持久保存的记录、成绩、设置、文件业务关联 | Tiana 数据库;文件关联保存相对路径、名称及关联字段 |
10
+ | 随应用分发且单张不超过 16 KiB 的静态小图片 | 构建时内嵌 JS,复用同一份 data URL 或 SVG 字符串 |
11
+ | 其他需外置的图片、附件、音视频、字体、模型 | Tiana 文件存储,通过文件 API 访问 |
12
+ | 用户上传文件、需要长期保存的生成文件 | 不论大小,使用文件存储 |
13
+ | 尚未保存的输入、本局计算、短期缓存 | 可留在页面;缓存不能替代云端持久化 |
14
+
15
+ 应用需要持久业务记录时接入 SQLite,不能把 localStorage、IndexedDB 或文件 BLOB
16
+ 当作数据库,再据此声明 `database_required: false`。确实没有数据库持久化需求时
17
+ 可无库,不为临时计算增加业务数据。数据库连接遵循当前 SQLite 技能的动态账号鉴权。
18
+
19
+ 文件使用平台 `context.files`,详细调用见[文件存储](files.md)。数据库保存可重新解析
20
+ 的应用相对路径,不保存二进制/base64 正文、作者 URL 或临时授权 URL。文件访问保留
21
+ 当前租户与应用的授权范围,不能把文件存储当作跨租户匿名 CDN。
22
+
23
+ ## 静态小图片的大小
24
+
25
+ - 单张上限为 16,384 字节,等于上限仍可内嵌,16,385 字节及以上使用文件存储。
26
+ - 测量缩放、压缩、格式优化后的实际文件,位于 base64/data URL 编码之前。
27
+ SVG 测量优化后的完整 UTF-8 字节,不用像素数、原图或 HTTP 压缩后大小代替。
28
+ - 只适用于随应用分发的静态图片。用户上传图片和需长期保存的生成图片仍用文件存储。
29
+ - 检查干净构建中实际已进入 JS,不能只看 import,或把一张大图切碎来规避上限。
30
+
31
+ ## 随包例外与预览
32
+
33
+ 平台要求的根部 `icon.png` 按规范随包提供;不能据此把其他外置图片复制进 Web 包。
34
+ `showcase/preview.html` 保持自包含,使用合成示例和页面内状态,不访问作者或安装后
35
+ 应用的正式数据库、文件。保留“示例体验/恢复示例”工具条,恢复仅重置本页示例。
36
+
37
+ 临时绘制的 Canvas、图表或导出文件可以先在内存生成;用户需要长期保存时再写入
38
+ 文件存储,不因此扩大应用功能。按实际接入描述数据库与文件的保存位置,尚未验证
39
+ 的云端持久化不得写成已完成。
40
+
41
+ ## 预置素材和验收
42
+
43
+ 需外置的预置素材按[模板素材文件](template-files.md)进入当前安装的独立目录。
44
+ 程序用 `template-assets/<相对路径>` 访问,数据库保留同一路径。仅作者应用能访问,
45
+ 或仅源码中存在文件,都不足以证明新安装可用。
46
+
47
+ 检查源码和构建、平台图标及自包含预览的例外;实际写入业务记录,刷新并在另一
48
+ 授权会话读回。需要预置素材时核对新安装文件;有用户上传功能时另验证上传和原有
49
+ 预览/下载操作。按实际功能验收,不为测试添加规格外的文件管理界面。
@@ -0,0 +1,95 @@
1
+ # 模板素材文件
2
+
3
+ 本参考描述配套格式 2 的源码候选行为。实际使用前核对目标服务端已经部署并启用
4
+ `template_files_v1`;兼容版 C 会拒绝新格式。本地脚本存在或打包成功不代表已上线。
5
+ 程序、数据库、小图片与预览的分工见[数据与素材存储](storage-and-assets.md)。
6
+
7
+ ## 声明与路径
8
+
9
+ 有安装必需且可公开的外置素材时,在原有 `metadata.json` 增加
10
+ `"file_seeds": "template-files"`,将其实际字节放在工程根部 `template-files/`。
11
+ 保留原来的名称、说明、数据库需求与变量。目录内全部文件参与安装;不得混入用户
12
+ 附件、凭据、作者环境文件或私人记录。
13
+
14
+ | 位置 | 同一文件的路径 |
15
+ | --- | --- |
16
+ | 源码 | `template-files/images/cover.webp` |
17
+ | 安装包独立材料 | `files/images/cover.webp` |
18
+ | 应用和初始 SQL | `template-assets/images/cover.webp` |
19
+ | Console / CLI 租户目录 | `WEB_ID/template-assets/images/cover.webp` |
20
+
21
+ 素材为 1..256 个普通文件,单个和合计均不超过 16 MiB。路径为 UTF-8,相对路径
22
+ 最长 1,024 字节;拒绝重复、文件/目录冲突、软链接、特殊文件、绝对路径、`.`/`..`、
23
+ 反斜线、控制字符和百分号编码。未声明素材时省略字段与目录,不造空素材流程。
24
+
25
+ 程序按[文件 API](files.md)使用 `context.files`:
26
+
27
+ ```js
28
+ export async function mount(root, { files }) {
29
+ const image = document.createElement('img');
30
+ image.alt = '封面';
31
+ root.append(image);
32
+ const unbind = await files.bindImage(image, 'template-assets/images/cover.webp');
33
+ return () => unbind();
34
+ }
35
+ ```
36
+
37
+ 数据库保存这条应用相对路径。实际 Web ID 由当前应用上下文提供,不将作者 URL、
38
+ 临时授权 URL、租户前缀或 OSS key 固化到源码/SQL,也不替换二进制素材中的变量。
39
+
40
+ ## CLI 初始化后的普通开发
41
+
42
+ `web init-template` / `init-share-template` 校验并原样解压源码,其中的 `template-files/`
43
+ 仍在本地。它们不创建应用,也不上传素材。读取声明、确认每份素材和来源后,保存
44
+ 本次新建应用的真实 `data.id`,为这个尚未初始化的新目录逐项准备文件:
45
+
46
+ ```sh
47
+ tiana file put ./template-files/images/cover.webp WEB_ID/template-assets/images/cover.webp --json
48
+ tiana file put ./template-files/documents/guide.pdf WEB_ID/template-assets/documents/guide.pdf --json
49
+ tiana file list WEB_ID/template-assets/ --json
50
+ tiana file get WEB_ID/template-assets/images/cover.webp ./verified-cover.webp --json
51
+ ```
52
+
53
+ 把 `WEB_ID` 替换为创建回执中的真实 ID。下载目标必须不存在。核对字节数和 SHA-256,
54
+ 在 `web serve WEB_ID` 中实际读取,再普通发布。`web publish` 只更新程序包,不自动
55
+ 复制 `template-files/`。同名默认拒绝;未知上传先检查原上传标识,不能用 overwrite
56
+ 重试未知写入。已存在应用沿用其实际文件,不能因改名、更新程序或用户删除素材而
57
+ 重新灌入。用户明确要求修改的文件按普通文件操作单独处理。
58
+
59
+ ## 制作格式 2 安装包
60
+
61
+ 从同一个确定 Git 提交导出源码,在该提交的干净目录安装依赖、构建。
62
+ 使用[分享流程](share-template.md#4-打包和发布)中的打包脚本;素材从传入的固定
63
+ `source.zip` 读取,不能只存在于作者工作目录。声明素材时,脚本生成:
64
+
65
+ - `source.zip` 中的 `template-files/`,用于服务端逐字节核对。
66
+ - `files/` 中的独立素材,包含相同字节,供两种安装模式直接复制。
67
+ - `install.json` 的 `format_version: 2`、`requires: ["template_files_v1"]` 及 `files`。
68
+ 文件清单 version 为 1,root 固定 `template-assets/`,按路径的 UTF-8 字节顺序排列。
69
+ 每项包含路径、大小、SHA-256 和合法 Content-Type。
70
+
71
+ 清单摘要取 `files` 对象在安装清单中的原始 UTF-8 字节;整包摘要取最终完整
72
+ `install.zip`。不能把源码包摘要代替整包摘要,或重排 JSON 后重算清单摘要。
73
+ 支持两种安装模式的是这份完整包:安装者直接安装时不创建源码库,素材仍取自
74
+ 独立材料。发布者的 `--without-source` 则只支持无素材旧格式包,不能省略新格式
75
+ 用于核对的源码,也不能未经授权默默改为提供源码。
76
+
77
+ 检查干净 `dist` 和 `site.tweb`,排除外置素材目录、改名副本、原始字节和 base64
78
+ 内嵌;脚本能检查常见复制/内嵌,不能证明所有自定义编码或转换后的资源都已排除。
79
+ 平台根图标仍按例外保留,小图片按 16 KiB 规则确实进入 JS。由 Agent 复核源码、
80
+ 构建过程及实际文件访问。无素材包继续省略格式、必需能力与文件清单字段。
81
+
82
+ ## 实际验收与恢复
83
+
84
+ 至少覆盖“保留源码/直接安装 × 桌面/手机”四种组合。使用独立测试模板,包含
85
+ 超过 16 KiB 的图片、附件、内嵌小图片和引用相对路径的合成 SQL 记录。另验证
86
+ 无素材包跳过文件步骤且不占素材预留,不能用无素材样例替代素材验收。
87
+
88
+ 核对原任务/安装回执、文件数量与字节、CLI 路径、数据库和实际应用读回。
89
+ 首次打开、刷新、重开和另一授权会话均能访问;修改一份安装不影响其他安装,
90
+ 未授权租户无法读取,预览的恢复示例不修改真实应用。存在上传功能时另验证上传。
91
+
92
+ 安装失败或响应未知时刷新原安装记录,沿原根任务恢复,不新建安装替代未知结果。
93
+ 模板 V1 中断后发布 V2,恢复仍固定 V1 材料;重试不重复复制或入账。用户改动、
94
+ 删除已安装文件后,不自动补齐或覆盖。保存各组合的真实回执、哈希及读取证据,
95
+ 未验证步骤保留未完成状态,不将本地打包或脚本测试当作云端安装通过。
@@ -1,6 +1,6 @@
1
1
  # 使用模板工程
2
2
 
3
- 模板目录来自本次 `tiana web list-template --json` 实际返回的数据。每页 `data.items` 含 name、display_name、description、status 和变量摘要;CLI 的 `--after` 查询下一页。选择符合用户核心功能与数据结构的工程;没有匹配项时按通用 Web 方法制作。
3
+ 模板目录来自本次 `tiana web list-template --json` 实际返回的数据。每页 `data.items` 含 name、display_name、description、status 和变量摘要;CLI 的 `--after` 查询下一页。即使 items 为空,存在 next_cursor 时仍继续需要的页。选择符合用户核心功能与数据结构的工程;没有匹配项时按通用 Web 方法制作。
4
4
 
5
5
  新应用默认由 Agent 创建所需的 SQLite 和 Git,按当前应用命名并保存 CLI 返回的实际实例 ID;用户明确指定已有实例时核实后复用。保存资源回执后执行:
6
6
 
@@ -10,6 +10,8 @@ tiana web init-template NAME --dir PROJECT_DIR --json
10
10
 
11
11
  成功结果的 `data.directory` 是工程根目录,`data.metadata_path` 是元信息文件。CLI 负责下载校验和解压,工程仍保留占位符、SQL 和原始文件。下载失败先核对实际结果,再重新运行;不用链接地址当作创建成功依据。
12
12
 
13
+ metadata.json 包含 `repositories` 或 `functions` 时,按[后端服务模板的源码开发步骤](function-templates.md#下载源码后继续开发)保留资源关系;后端私有数据库不绑定给 Web。以下单仓库、Web 直连 SQLite 的步骤适用于相应模板。
14
+
13
15
  ## metadata.json 和变量
14
16
 
15
17
  读取根部 metadata.json、README、依赖锁文件及构建脚本,按实际工程开发。元信息示例:
@@ -19,6 +21,7 @@ tiana web init-template NAME --dir PROJECT_DIR --json
19
21
  "name": "notes",
20
22
  "display_name": "记事本",
21
23
  "description": "个人笔记、文件夹、全文搜索和自动保存。",
24
+ "database_required": true,
22
25
  "variables": [
23
26
  {
24
27
  "name": "SQLITE_INSTANCE_ID",
@@ -55,10 +58,18 @@ JSON 中要正确转义字符串,SQL 中按实际语法处理,源码中保
55
58
 
56
59
  SQL 返回失败、断线或未知结果时停止后续发布,用独立只读查询核对已完成的结构与数据,不自动重放写入。初始化成功后进行应用定制、依赖安装、源码同步、构建及发布;工程 README 中的步骤与实际帮助一起核对。
57
60
 
61
+ ## 预置素材
62
+
63
+ 按[数据与素材存储](storage-and-assets.md)检查声明及现有实现。`file_seeds` 为
64
+ `template-files` 时,按[模板素材文件](template-files.md)核对源字节、相对路径、
65
+ 当前 Web ID 的首次文件准备和干净构建。CLI 解压成功不会自动上传素材,普通
66
+ `web publish` 也不会灌入文件。没有素材声明时沿用原流程;已有应用不因再次发布
67
+ 而恢复被用户修改或删除的初始文件。
68
+
58
69
  ## 模板图标
59
70
 
60
71
  模板的源 `icon.png` 是用户应用的初始图标,复用工程的静态资源复制配置。变量替换时不把 PNG 当文本处理。新应用缺图、继承的是通用占位/标题首字图片或图形与本次功能不符时,按[应用图标](csr-apps.md#应用图标)优先调用 AI 生图制作并保存体现功能的图标,用户明确指定的图片优先。干净构建后确认产物根目录 `icon.png` 可以解码且与选定源图一致,再发布;以后更新模板本身不会直接改变已有用户应用的图标。
61
72
 
62
73
  ## 构建和来源
63
74
 
64
- 模板 `source.repository`、`source.commit` 说明下载包的源工程来源,区别于用户应用自己的 Git 提交。创建用户仓库后记录实际 git_instance_id;提交和构建按 [源码流程](../../tiana-git/references/source-releases.md)。按下载工程的 README 和构建脚本确定命令、入口与产物目录。若脚本接收源码提交号并输出 TIANA_PROJECT_PARAMS,核对其中的 entry、database_instance_id、git_instance_id 和 source_commit,再用于配置 MGR Web 项目;database_instance_id 必须与本次执行 schema/seeds 的 SQLite 一致。核对模块、资源及 MGR Web 项目的 SQLite/Git 绑定后执行 `web publish`,再用 publish_id 查询状态。
75
+ 模板 `source.repository`、`source.commit` 说明下载包的源工程来源,区别于用户应用自己的 Git 提交。创建用户仓库后记录实际 git_instance_id;提交和构建按 [源码流程](../../tiana-git/references/source-releases.md)。按下载工程的 README 和构建脚本确定命令、入口与产物目录。创建 Web 时传入实际 entry 和 Git 绑定;直连模式的数据库绑定必须与本次执行 schema/seeds 的 SQLite 一致。源码提交号记录为构建证据。核对模块、资源及 MGR Web 项目的 SQLite/Git 绑定后执行 `web publish`,再用 publish_id 查询状态。