@tbox.cn/app-sdk-server 0.21.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tbox.cn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @tbox.cn/app-sdk-server
2
+
3
+ tbox AI Agent 平台 SDK server 轴:agent 引擎(Mastra)、鉴权(统一登录/WS 鉴权/scope 会话)、
4
+ conversation、TTS WS 代理、ASR/上传/反馈哑中继、记忆(BM25 检索层)、技能/工具/出卡管线、
5
+ integrations/provider catalog、dev 平台设施(inspector)。
6
+
7
+ 含 `src/upstream/`:`@tbox-dev-js/sdk` 消费面内化真源(上游冻结,本仓为活真源——行为钉死契约见
8
+ `tests/upstream-fidelity.test.ts` 与 Agent Note 2026-09-20-upstream-internalization)。
9
+
10
+ 公开入口:`.` / `./server` / `./platform`(inspector;bin `tbox-inspector-check` 接线守卫)。
11
+ 工具:`npx tbox-inspector-check`(生成应用 platform 接线三态校验)。
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * tbox-inspector-check — 平台基础设施守卫(随 @tbox.cn/app-sdk-server 分发;code-inspect 面随 @tbox.cn/app-sdk-client)。
4
+ *
5
+ * 校验宿主应用的 inspector 接线未被破坏(断言与 src/platform/inspector.ts 头部
6
+ * 契约声明一一对应;SDK 侧导出/常量自检归 tests/platform-inspector.test.ts):
7
+ * 1. apps/server/src/{index,app}.ts 候选任一(同一文件内)从 @tbox.cn/app-sdk-server/platform
8
+ * import 并调用 installInspector(app)(候选只增不删:index.ts=单文件布局/存量应用,
9
+ * app.ts=入口分离布局——装配主体所在;dev.ts 非候选:有 import 无调用,合取防假阳性)
10
+ * 2. apps/client/index.html 含 /__vs_inspector__.js 脚本标签
11
+ * 3. apps/client/vite.config.ts 接入 @tbox.cn/app-sdk-client/platform/code-inspect babel plugin
12
+ *
13
+ * 约定:cwd = 应用根(pnpm run 注入保证)。纯 node:fs 实现,零依赖、零 SDK import——
14
+ * workspace 源态与发布态行为一致。路径断言只增不删(模板布局演进时新旧位置并认)。
15
+ */
16
+ import { readFileSync } from 'node:fs';
17
+ import path from 'node:path';
18
+
19
+ const appDir = process.cwd();
20
+ const SERVER_ENTRY_CANDIDATES = ['apps/server/src/index.ts', 'apps/server/src/app.ts'];
21
+ const AGENT_HTML = path.join(appDir, 'apps/client/index.html');
22
+ const VITE_CFG = path.join(appDir, 'apps/client/vite.config.ts');
23
+
24
+ const failures = [];
25
+
26
+ function checkFile(file, label) {
27
+ try {
28
+ return readFileSync(file, 'utf8');
29
+ } catch {
30
+ failures.push(`缺失文件 ${label}`);
31
+ return null;
32
+ }
33
+ }
34
+
35
+ // 1. server 入口链:候选任一文件内 import + installInspector(app) 调用合取成立
36
+ // (形态级:调用须为行首语句,防注释文本绕过;合取防 dev.ts 假阳性——有 import 无调用)
37
+ const entrySources = SERVER_ENTRY_CANDIDATES.map((rel) => {
38
+ const file = path.join(appDir, rel);
39
+ try {
40
+ return { content: readFileSync(file, 'utf8') };
41
+ } catch {
42
+ return null;
43
+ }
44
+ });
45
+ if (entrySources.every((s) => s === null)) {
46
+ failures.push(`缺失文件 ${SERVER_ENTRY_CANDIDATES.join(' | ')}`);
47
+ } else {
48
+ const wired = entrySources.some(
49
+ (s) =>
50
+ s !== null &&
51
+ /from\s+['"]@tbox\.cn\/(app-sdk-server|app-agent-sdk-server)\/platform['"]/.test(s.content) &&
52
+ /^\s*installInspector\s*\(\s*app\s*[,)]/m.test(s.content),
53
+ );
54
+ if (!wired) {
55
+ failures.push('server 入口链未接线 installInspector(候选 index.ts/app.ts 均未同时满足 import + 调用)');
56
+ }
57
+ }
58
+
59
+ // 2. client 入口页:runtime 脚本标签(RUNTIME_PATH 约定不变;断言标签形态——注释提及不计数)
60
+ const agentHtml = checkFile(AGENT_HTML, 'apps/client/index.html');
61
+ if (agentHtml !== null && !/<script[^>]*src="\/__vs_inspector__\.js"/.test(agentHtml)) {
62
+ failures.push('apps/client/index.html 缺少 /__vs_inspector__.js 脚本标签');
63
+ }
64
+
65
+ // 3. vite:code-inspect plugin 接入(断言 import 语句形态,防注释绕过)
66
+ const viteCfg = checkFile(VITE_CFG, 'apps/client/vite.config.ts');
67
+ if (
68
+ viteCfg !== null &&
69
+ !/from\s+['"]@tbox\.cn\/(app-sdk-client|app-agent-sdk-client)\/platform\/code-inspect['"]/.test(viteCfg)
70
+ ) {
71
+ failures.push('apps/client/vite.config.ts 未接入 code-inspect plugin');
72
+ }
73
+
74
+ if (failures.length > 0) {
75
+ console.error('');
76
+ console.error('❌ [tbox-inspector-check] 平台基础设施校验失败:');
77
+ for (const f of failures) console.error(` - ${f}`);
78
+ console.error('');
79
+ console.error(' tbox 平台微调能力(点选元素 → 写入聊天框)是平台基础设施,AI agent 不得删除。');
80
+ console.error(' 接线契约见 @tbox.cn/app-sdk-server/src/platform/inspector.ts 头部声明;模板参考布局(apps/*)。');
81
+ console.error('');
82
+ process.exitCode = 1;
83
+ } else {
84
+ console.log('✅ [tbox-inspector-check] 平台基础设施校验通过');
85
+ }
@@ -0,0 +1,9 @@
1
+ import { Express } from 'express';
2
+
3
+ declare const RUNTIME_PATH = "/__vs_inspector__.js";
4
+ declare const SCRIPT_TAG = "<script src=\"/__vs_inspector__.js\" defer></script>";
5
+ declare function injectScript(html: string): string;
6
+ declare function isReady(): boolean;
7
+ declare function installInspector(app: Express): void;
8
+
9
+ export { RUNTIME_PATH, SCRIPT_TAG, injectScript, installInspector, isReady };
@@ -0,0 +1 @@
1
+ var m="https://env-00jx4e7pq1un-static.normal.cloudstatic.cn/asset/codingbox/inspector.umd.js",f="/__vs_inspector__.js",d=`<script src="${f}" defer></script>`,a="",l=!1;async function w(t=3){for(let r=0;r<t;r++)try{let e=await fetch(m);if(!e.ok)throw new Error(`HTTP ${e.status}`);a=await e.text(),l=!0,console.log(`[inspector] runtime loaded (${a.length} bytes)`);return}catch(e){console.warn(`[inspector] fetch failed (attempt ${r+1}/${t}):`,e.message),r<t-1&&await new Promise(c=>setTimeout(c,1e3*(r+1)))}console.error("[inspector] runtime unavailable; inspector script will be skipped")}function x(t){if(t.includes(f))return t;let r=t.search(/<\/head\s*>/i);if(r!==-1)return t.slice(0,r)+d+t.slice(r);let e=t.search(/<body[\s>]/i);return e!==-1?t.slice(0,e)+d+t.slice(e):t}function T(){return l}function _(t){w(),t.get(f,(r,e)=>{if(!a){e.status(503).type("application/javascript").send("// inspector runtime not ready");return}e.type("application/javascript").set("Cache-Control","no-cache").send(a)}),t.use((r,e,c)=>{if(!l)return c();let s=[],R=e.write.bind(e),u=e.end.bind(e),o=!1,g=()=>{let n=String(e.getHeader("content-type")||""),i=String(e.getHeader("content-encoding")||"");return n.includes("text/html")&&!i};e.write=((n,...i)=>(!o&&!s.length&&(o=g()),o&&n?(s.push(Buffer.isBuffer(n)?n:Buffer.from(n)),!0):R(n,...i))),e.end=((n,...i)=>{if(!o&&!s.length&&(o=g()),o){n&&s.push(Buffer.isBuffer(n)?n:Buffer.from(n));try{let p=Buffer.concat(s).toString("utf8"),y=x(p);return e.setHeader("Content-Length",Buffer.byteLength(y)),u(y,...i)}catch(p){return console.warn("[inspector] inject failed, fallback to original:",p.message),u(Buffer.concat(s),...i)}}return u(n,...i)}),c()})}export{f as RUNTIME_PATH,d as SCRIPT_TAG,x as injectScript,_ as installInspector,T as isReady};