@heybox/hb-sdk 0.1.3 → 0.2.0-alpha.1
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 +149 -345
- package/bin/hb-sdk.cjs +3 -0
- package/dist/cli.cjs +10117 -0
- package/dist/devtools/mock-host/index.html +252 -0
- package/dist/devtools/mock-host/main.js +975 -0
- package/dist/index.cjs.js +474 -85
- package/dist/index.esm.js +465 -71
- package/dist/protocol.cjs.js +163 -0
- package/dist/protocol.esm.js +148 -0
- package/dist/templates/vue3-vite-ts/.gitignore.ejs +5 -0
- package/dist/templates/vue3-vite-ts/README.md.ejs +42 -0
- package/dist/templates/vue3-vite-ts/index.html.ejs +12 -0
- package/dist/templates/vue3-vite-ts/package.json.ejs +28 -0
- package/dist/templates/vue3-vite-ts/src/App.vue +63 -0
- package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +67 -0
- package/dist/templates/vue3-vite-ts/src/main.ts +5 -0
- package/dist/templates/vue3-vite-ts/src/styles.css +60 -0
- package/dist/templates/vue3-vite-ts/src/vite-env.d.ts +1 -0
- package/dist/templates/vue3-vite-ts/tsconfig.app.json +17 -0
- package/dist/templates/vue3-vite-ts/tsconfig.json +11 -0
- package/dist/templates/vue3-vite-ts/tsconfig.node.json +11 -0
- package/dist/templates/vue3-vite-ts/vite.config.ts +6 -0
- package/dist/templates/vue3-vite-ts/vitest.config.ts +10 -0
- package/package.json +30 -5
- package/skill/SKILL.md +95 -0
- package/skill/references/api-protocol.md +135 -0
- package/skill/references/api-root.md +346 -0
- package/skill/references/cli.md +360 -0
- package/skill/references/examples.md +107 -0
- package/skill/references/llms-index.md +44 -0
- package/skill/references/recipes.md +374 -0
- package/skill/references/safety-boundaries.md +28 -0
- package/skill/references/smoke-evaluation.md +24 -0
- package/skill/scripts/check-references.mjs +14 -0
- package/skill/scripts/package-skill.mjs +60 -0
- package/skill/scripts/package-skill.sh +6 -0
- package/skill/scripts/skill-metadata.mjs +74 -0
- package/skill/scripts/sync-references.mjs +541 -0
- package/skill/scripts/validate-skill.mjs +233 -0
- package/skill/skill.json +11 -0
- package/types/core/client.d.ts +23 -3
- package/types/core/errors.d.ts +45 -2
- package/types/core/sdk.d.ts +78 -10
- package/types/core/singleton.d.ts +33 -7
- package/types/core/utils.d.ts +2 -0
- package/types/index.d.ts +14 -6
- package/types/modules/auth/index.d.ts +35 -0
- package/types/modules/network/index.d.ts +120 -0
- package/types/modules/share/index.d.ts +9 -5
- package/types/modules/share/screenshot.d.ts +9 -3
- package/types/modules/share/show-share-menu.d.ts +9 -3
- package/types/modules/share/types.d.ts +24 -4
- package/types/modules/storage/index.d.ts +56 -0
- package/types/modules/user/get-info.d.ts +6 -2
- package/types/modules/user/index.d.ts +8 -10
- package/types/modules/user/types.d.ts +1 -0
- package/types/modules/viewport/index.d.ts +71 -0
- package/types/protocol/capabilities.d.ts +180 -0
- package/types/protocol/guards.d.ts +6 -1
- package/types/protocol/types.d.ts +19 -4
- package/types/protocol.d.ts +13 -0
- package/types/modules/system/get-storage.d.ts +0 -15
- package/types/modules/system/get-window-info.d.ts +0 -16
- package/types/modules/system/index.d.ts +0 -23
- package/types/modules/system/set-storage.d.ts +0 -12
- package/types/modules/system/types.d.ts +0 -34
- package/types/modules/user/login.d.ts +0 -18
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { createSkillContentHash, createSkillManifest, normalizeSkillManifest } from './skill-metadata.mjs';
|
|
7
|
+
|
|
8
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const skillRoot = path.resolve(scriptDir, '..');
|
|
10
|
+
const referencesRoot = path.join(skillRoot, 'references');
|
|
11
|
+
const repoRoot = findRepoRoot(process.cwd()) ?? findRepoRoot(skillRoot);
|
|
12
|
+
const checkMode = process.argv.includes('--check');
|
|
13
|
+
const TEXT_FILE_RE = /\.(?:md|mjs|js|cjs|ts|tsx|json|txt|sh|yaml|yml)$/i;
|
|
14
|
+
|
|
15
|
+
if (!repoRoot) {
|
|
16
|
+
console.error('Cannot sync hb-sdk references outside the heybox-webapp repository. Run this script from a checkout that contains packages/hb-sdk/package.json.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function findRepoRoot(startDir) {
|
|
21
|
+
let dir = path.resolve(startDir);
|
|
22
|
+
while (true) {
|
|
23
|
+
if (existsSync(path.join(dir, 'package.json')) && existsSync(path.join(dir, 'packages/hb-sdk/package.json'))) {
|
|
24
|
+
return dir;
|
|
25
|
+
}
|
|
26
|
+
const parent = path.dirname(dir);
|
|
27
|
+
if (parent === dir) return null;
|
|
28
|
+
dir = parent;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function read(relativePath) {
|
|
33
|
+
return readFileSync(path.join(repoRoot, relativePath), 'utf8').trimEnd();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function extractSection(markdown, heading) {
|
|
37
|
+
const lines = markdown.split('\n');
|
|
38
|
+
const start = lines.findIndex(line => line.trim() === heading);
|
|
39
|
+
if (start === -1) return '';
|
|
40
|
+
const level = heading.match(/^#+/)?.[0].length ?? 2;
|
|
41
|
+
const out = [lines[start]];
|
|
42
|
+
let fenceChar = '';
|
|
43
|
+
for (let index = start + 1; index < lines.length; index += 1) {
|
|
44
|
+
const line = lines[index];
|
|
45
|
+
const fenceMatch = line.match(/^\s*(`{3,}|~{3,})/);
|
|
46
|
+
|
|
47
|
+
if (fenceChar) {
|
|
48
|
+
out.push(line);
|
|
49
|
+
if (fenceMatch?.[1]?.startsWith(fenceChar)) {
|
|
50
|
+
fenceChar = '';
|
|
51
|
+
}
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (fenceMatch) {
|
|
56
|
+
fenceChar = fenceMatch[1][0];
|
|
57
|
+
out.push(line);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const headingMatch = line.match(/^(#+)\s/);
|
|
62
|
+
if (headingMatch && headingMatch[1].length <= level) break;
|
|
63
|
+
out.push(line);
|
|
64
|
+
}
|
|
65
|
+
return out.join('\n').trimEnd();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function fenced(language, value) {
|
|
69
|
+
const content = value.trimEnd();
|
|
70
|
+
const longestFence = Math.max(2, ...Array.from(content.matchAll(/`{3,}/g), match => match[0].length));
|
|
71
|
+
const fence = '`'.repeat(longestFence + 1);
|
|
72
|
+
return `${fence}${language}\n${content}\n${fence}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function header(title, sources) {
|
|
76
|
+
return [
|
|
77
|
+
`# ${title}`,
|
|
78
|
+
'',
|
|
79
|
+
'> Generated by `node packages/hb-sdk/skill/scripts/sync-references.mjs` from the public hb-sdk source/docs. Do not edit by hand; update sources or this generator instead.',
|
|
80
|
+
'',
|
|
81
|
+
'## Sources',
|
|
82
|
+
'',
|
|
83
|
+
...sources.map(source => `- ${source}`),
|
|
84
|
+
'',
|
|
85
|
+
].join('\n');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function frontmatterless(markdown) {
|
|
89
|
+
return markdown.replace(/^---\n[\s\S]*?\n---\n/, '').trimEnd();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function contents(items) {
|
|
93
|
+
return [
|
|
94
|
+
'',
|
|
95
|
+
'## Contents',
|
|
96
|
+
'',
|
|
97
|
+
...items.map(([title, anchor]) => `- [${title}](#${anchor})`),
|
|
98
|
+
'',
|
|
99
|
+
].join('\n');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function toPosix(value) {
|
|
103
|
+
return value.split(path.sep).join('/');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function walkDistributableSkillFiles(dir, relativeBase = '') {
|
|
107
|
+
const out = [];
|
|
108
|
+
|
|
109
|
+
if (!existsSync(dir)) {
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
114
|
+
if (entry.name.startsWith('.')) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const fullPath = path.join(dir, entry.name);
|
|
119
|
+
const relativePath = toPosix(path.join(relativeBase, entry.name));
|
|
120
|
+
|
|
121
|
+
if (entry.isDirectory()) {
|
|
122
|
+
out.push(...walkDistributableSkillFiles(fullPath, relativePath));
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!entry.isFile()) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (relativePath === 'skill.json' || /\.zip$/i.test(relativePath) || !TEXT_FILE_RE.test(relativePath)) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
out.push(relativePath);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function readGeneratedOrDiskSkillFile(relativePath, generatedReferences) {
|
|
141
|
+
if (relativePath.startsWith('references/')) {
|
|
142
|
+
const generated = generatedReferences.get(relativePath.slice('references/'.length));
|
|
143
|
+
|
|
144
|
+
if (generated !== undefined) {
|
|
145
|
+
return `${generated.trimEnd()}\n`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return readFileSync(path.join(skillRoot, ...relativePath.split('/')));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function createCurrentSkillManifest(generatedReferences) {
|
|
153
|
+
const distributableFiles = [
|
|
154
|
+
'SKILL.md',
|
|
155
|
+
...walkDistributableSkillFiles(path.join(skillRoot, 'references'), 'references'),
|
|
156
|
+
...walkDistributableSkillFiles(path.join(skillRoot, 'scripts'), 'scripts'),
|
|
157
|
+
...walkDistributableSkillFiles(path.join(skillRoot, 'assets'), 'assets'),
|
|
158
|
+
];
|
|
159
|
+
const fileEntries = Array.from(new Set(distributableFiles))
|
|
160
|
+
.sort((left, right) => left.localeCompare(right))
|
|
161
|
+
.map(relativePath => ({
|
|
162
|
+
path: relativePath,
|
|
163
|
+
content: readGeneratedOrDiskSkillFile(relativePath, generatedReferences),
|
|
164
|
+
}));
|
|
165
|
+
|
|
166
|
+
return createSkillManifest({
|
|
167
|
+
contentHash: createSkillContentHash(fileEntries),
|
|
168
|
+
sdkVersion: packageJson.version,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
const packageJson = JSON.parse(read('packages/hb-sdk/package.json'));
|
|
174
|
+
const rootEntry = read('packages/hb-sdk/src/index.ts');
|
|
175
|
+
const protocolEntry = read('packages/hb-sdk/src/protocol.ts');
|
|
176
|
+
const cliEntry = read('packages/hb-sdk/src/cli/index.ts');
|
|
177
|
+
const cliTemplateReadme = read('packages/hb-sdk/src/cli/templates/vue3-vite-ts/README.md.ejs');
|
|
178
|
+
const readme = read('packages/hb-sdk/README.md');
|
|
179
|
+
const cliGuide = frontmatterless(read('apps/h5/docs/hb_sdk/src/guide/cli.md'));
|
|
180
|
+
const llmsTxt = read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms.txt');
|
|
181
|
+
const quickStart = frontmatterless(read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/quick-start.md'));
|
|
182
|
+
const authGuide = frontmatterless(read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/auth.md'));
|
|
183
|
+
const lifecycleGuide = frontmatterless(read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/lifecycle.md'));
|
|
184
|
+
const errorGuide = frontmatterless(read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/error-handling.md'));
|
|
185
|
+
const loginGate = frontmatterless(read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms/recipes/login-gate.md'));
|
|
186
|
+
const customInstance = frontmatterless(read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms/recipes/custom-instance.md'));
|
|
187
|
+
const referenceHome = frontmatterless(read('apps/h5/docs/hb_sdk/src/.vuepress/public/llms/reference/README.md'));
|
|
188
|
+
|
|
189
|
+
const quickStartSection = extractSection(readme, '## 快速开始');
|
|
190
|
+
const runtimeEnvironment = extractSection(readme, '## 运行环境');
|
|
191
|
+
const publicCapabilities = extractSection(readme, '## 常用能力');
|
|
192
|
+
const lifecycleEvents = extractSection(readme, '## 生命周期事件');
|
|
193
|
+
const standardErrors = extractSection(readme, '## 错误处理');
|
|
194
|
+
const sdkRuntimeRelation = extractSection(readme, '## SDK 与 Runtime');
|
|
195
|
+
const capabilityBoundaries = extractSection(readme, '## 能力边界');
|
|
196
|
+
const cliSummarySection = extractSection(readme, '## CLI');
|
|
197
|
+
const repositoryDevelopment = extractSection(readme, '## 本仓库开发');
|
|
198
|
+
const cliCreateSection = extractSection(cliGuide, '## 创建外部小程序模板');
|
|
199
|
+
const cliDevSection = [
|
|
200
|
+
extractSection(cliGuide, '## 本地开发模式'),
|
|
201
|
+
extractSection(cliGuide, '## Mock runtime 边界'),
|
|
202
|
+
].filter(Boolean).join('\n\n');
|
|
203
|
+
const cliLoginSection = extractSection(cliGuide, '## CLI 登录态');
|
|
204
|
+
const cliDoctorSection = extractSection(cliGuide, '## Agent Skill doctor');
|
|
205
|
+
const cliUpdateSection = extractSection(cliGuide, '## 版本提醒');
|
|
206
|
+
|
|
207
|
+
const files = new Map();
|
|
208
|
+
|
|
209
|
+
files.set('api-root.md', `${header('Root API reference', [
|
|
210
|
+
'packages/hb-sdk/package.json',
|
|
211
|
+
'packages/hb-sdk/src/index.ts',
|
|
212
|
+
'packages/hb-sdk/README.md',
|
|
213
|
+
])}${contents([
|
|
214
|
+
['Package metadata', 'package-metadata'],
|
|
215
|
+
['Public root entrypoint', 'public-root-entrypoint'],
|
|
216
|
+
['App-facing concepts', 'app-facing-concepts'],
|
|
217
|
+
['Public modules', 'public-modules'],
|
|
218
|
+
])}## Package metadata
|
|
219
|
+
|
|
220
|
+
- Package: \`${packageJson.name}\`
|
|
221
|
+
- Version at generation time: \`${packageJson.version}\`
|
|
222
|
+
- Public root export: \`@heybox/hb-sdk\`
|
|
223
|
+
- Protocol export: \`@heybox/hb-sdk/protocol\`
|
|
224
|
+
|
|
225
|
+
## Public root entrypoint
|
|
226
|
+
|
|
227
|
+
${fenced('ts', rootEntry)}
|
|
228
|
+
|
|
229
|
+
## App-facing concepts
|
|
230
|
+
|
|
231
|
+
${quickStartSection}
|
|
232
|
+
|
|
233
|
+
${runtimeEnvironment}
|
|
234
|
+
|
|
235
|
+
${standardErrors}
|
|
236
|
+
|
|
237
|
+
## Public modules
|
|
238
|
+
|
|
239
|
+
${publicCapabilities}
|
|
240
|
+
|
|
241
|
+
${lifecycleEvents}
|
|
242
|
+
`);
|
|
243
|
+
|
|
244
|
+
files.set('api-protocol.md', `${header('Protocol API reference', [
|
|
245
|
+
'packages/hb-sdk/src/protocol.ts',
|
|
246
|
+
'packages/hb-sdk/README.md',
|
|
247
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/reference/README.md',
|
|
248
|
+
])}${contents([
|
|
249
|
+
['Host/runtime-only warning', 'hostruntime-only-warning'],
|
|
250
|
+
['Public protocol entrypoint', 'public-protocol-entrypoint'],
|
|
251
|
+
['Protocol context', 'protocol-context'],
|
|
252
|
+
['Generated reference index', 'generated-reference-index'],
|
|
253
|
+
])}## Host/runtime-only warning
|
|
254
|
+
|
|
255
|
+
Use \`@heybox/hb-sdk/protocol\` only for parent-container runtime, bridge-server, protocol-contract, or \`@heybox/hb-sdk-runtime\` integration tasks. Iframe mini-program business code must use root SDK APIs and must not construct bridge envelopes, nonce handling, or raw \`postMessage\` flows.
|
|
256
|
+
|
|
257
|
+
## Public protocol entrypoint
|
|
258
|
+
|
|
259
|
+
${fenced('ts', protocolEntry)}
|
|
260
|
+
|
|
261
|
+
## Protocol context
|
|
262
|
+
|
|
263
|
+
${sdkRuntimeRelation}
|
|
264
|
+
|
|
265
|
+
## Generated reference index
|
|
266
|
+
|
|
267
|
+
${referenceHome}
|
|
268
|
+
`);
|
|
269
|
+
|
|
270
|
+
files.set('cli.md', `${header('CLI reference', [
|
|
271
|
+
'packages/hb-sdk/package.json',
|
|
272
|
+
'packages/hb-sdk/src/cli/index.ts',
|
|
273
|
+
'packages/hb-sdk/src/cli/commands/create.ts',
|
|
274
|
+
'packages/hb-sdk/src/cli/commands/dev.ts',
|
|
275
|
+
'packages/hb-sdk/src/cli/commands/login.ts',
|
|
276
|
+
'packages/hb-sdk/src/cli/templates/vue3-vite-ts/README.md.ejs',
|
|
277
|
+
'apps/h5/docs/hb_sdk/src/guide/cli.md',
|
|
278
|
+
'packages/hb-sdk/README.md',
|
|
279
|
+
])}${contents([
|
|
280
|
+
['When to use the CLI', 'when-to-use-the-cli'],
|
|
281
|
+
['Command surface', 'command-surface'],
|
|
282
|
+
['Create a mini-program template', 'create-a-mini-program-template'],
|
|
283
|
+
['Local dev and mock runtime', 'local-dev-and-mock-runtime'],
|
|
284
|
+
['CLI login cache', 'cli-login-cache'],
|
|
285
|
+
['Agent Skill doctor', 'agent-skill-doctor'],
|
|
286
|
+
['Update reminders', 'update-reminders'],
|
|
287
|
+
['Repository validation commands', 'repository-validation-commands'],
|
|
288
|
+
['Generated template README', 'generated-template-readme'],
|
|
289
|
+
])}## When to use the CLI
|
|
290
|
+
|
|
291
|
+
Use the bundled \`hb-sdk\` CLI when the task is about creating an external mini-program project, starting local Vite development, debugging SDK calls in a browser mock runtime host, or managing the CLI's own Heybox auth cache.
|
|
292
|
+
|
|
293
|
+
Do not use the CLI to replace iframe SDK calls. \`hb-sdk login\` is for CLI commands only and does not change \`auth.login()\`, \`user.getInfo()\`, \`network.request()\`, or mock-host user state.
|
|
294
|
+
|
|
295
|
+
The CLI, templates, and mock host are owned by \`${packageJson.name}\`. Do not create a second mock runtime package or move CLI guidance outside this package unless the package boundary changes.
|
|
296
|
+
|
|
297
|
+
## Command surface
|
|
298
|
+
|
|
299
|
+
${fenced('ts', cliEntry)}
|
|
300
|
+
|
|
301
|
+
## Create a mini-program template
|
|
302
|
+
|
|
303
|
+
${cliCreateSection}
|
|
304
|
+
|
|
305
|
+
Agent rules:
|
|
306
|
+
|
|
307
|
+
- Prefer \`hb-sdk create <project-name>\` for a new standalone external mini-program template.
|
|
308
|
+
- After creation, the expected next steps are \`npm install\` and \`npm run dev\`.
|
|
309
|
+
- Do not claim the CLI installs dependencies, initializes git, opens an editor, or overwrites non-empty directories.
|
|
310
|
+
- Treat \`project-name\` as an unscoped npm package name and project directory.
|
|
311
|
+
|
|
312
|
+
## Local dev and mock runtime
|
|
313
|
+
|
|
314
|
+
${cliDevSection}
|
|
315
|
+
|
|
316
|
+
Use \`hb-sdk dev\` for local browser SDK debugging. Use the Mock runtime host's "在 Mac 版 APP 中启动" button when the page needs to be loaded by the real Heybox mini-program container.
|
|
317
|
+
|
|
318
|
+
## CLI login cache
|
|
319
|
+
|
|
320
|
+
${cliLoginSection}
|
|
321
|
+
|
|
322
|
+
Agent rules:
|
|
323
|
+
|
|
324
|
+
- Keep CLI auth cache separate from iframe SDK login state.
|
|
325
|
+
- It is correct to say status output is redacted.
|
|
326
|
+
- Do not expose or template pkey, cookie, token, or private credential values.
|
|
327
|
+
- Use \`hb-sdk login clear\` only to clear the \`hb-sdk\` CLI namespace.
|
|
328
|
+
|
|
329
|
+
## Agent Skill doctor
|
|
330
|
+
|
|
331
|
+
${cliDoctorSection}
|
|
332
|
+
|
|
333
|
+
Agent rules:
|
|
334
|
+
|
|
335
|
+
- Use \`hb-sdk doctor\` for read-only diagnosis of local SDK, remote latest skill metadata, and local skill metadata.
|
|
336
|
+
- Do not use \`hb-sdk doctor\` to auto-install skills; when installation or refresh is needed, tell the user to run \`npx skills add https://open.xiaoheihe.cn/agent-skills/hb-sdk\`.
|
|
337
|
+
- If doctor reports \`SDK_MISMATCH\`, tell the user to upgrade \`${packageJson.name}@latest\` before reinstalling the skill.
|
|
338
|
+
- The supported local skill path is \`$CODEX_HOME/skills/hb-sdk/skill.json\`, falling back to \`~/.codex/skills/hb-sdk/skill.json\`.
|
|
339
|
+
|
|
340
|
+
## Update reminders
|
|
341
|
+
|
|
342
|
+
${cliUpdateSection}
|
|
343
|
+
|
|
344
|
+
## Repository validation commands
|
|
345
|
+
|
|
346
|
+
${repositoryDevelopment}
|
|
347
|
+
|
|
348
|
+
## Generated template README
|
|
349
|
+
|
|
350
|
+
${fenced('md', cliTemplateReadme)}
|
|
351
|
+
`);
|
|
352
|
+
|
|
353
|
+
files.set('recipes.md', `${header('Recipes', [
|
|
354
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/quick-start.md',
|
|
355
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/auth.md',
|
|
356
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/lifecycle.md',
|
|
357
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/error-handling.md',
|
|
358
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/recipes/login-gate.md',
|
|
359
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/recipes/custom-instance.md',
|
|
360
|
+
])}${contents([
|
|
361
|
+
['Quick start', 'quick-start'],
|
|
362
|
+
['User and login', 'user-and-login'],
|
|
363
|
+
['Lifecycle events', 'lifecycle-events'],
|
|
364
|
+
['Error handling', 'error-handling'],
|
|
365
|
+
['Login gate recipe', 'login-gate-recipe'],
|
|
366
|
+
['Custom instance recipe', 'custom-instance-recipe'],
|
|
367
|
+
])}## Quick start
|
|
368
|
+
|
|
369
|
+
${quickStart}
|
|
370
|
+
|
|
371
|
+
## User and login
|
|
372
|
+
|
|
373
|
+
${authGuide}
|
|
374
|
+
|
|
375
|
+
## Lifecycle events
|
|
376
|
+
|
|
377
|
+
${lifecycleGuide}
|
|
378
|
+
|
|
379
|
+
## Error handling
|
|
380
|
+
|
|
381
|
+
${errorGuide}
|
|
382
|
+
|
|
383
|
+
## Login gate recipe
|
|
384
|
+
|
|
385
|
+
${loginGate}
|
|
386
|
+
|
|
387
|
+
## Custom instance recipe
|
|
388
|
+
|
|
389
|
+
${customInstance}
|
|
390
|
+
`);
|
|
391
|
+
|
|
392
|
+
files.set('safety-boundaries.md', `${header('Safety boundaries', [
|
|
393
|
+
'packages/hb-sdk/README.md',
|
|
394
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/guide/auth.md',
|
|
395
|
+
])}## Required boundaries
|
|
396
|
+
|
|
397
|
+
${capabilityBoundaries}
|
|
398
|
+
|
|
399
|
+
## Agent rules
|
|
400
|
+
|
|
401
|
+
- Do not instruct mini-program code to read, extract, forward, store, or depend on token, cookie, phone number, or private credentials.
|
|
402
|
+
- Negative safety statements that explain the SDK does not expose token/cookie/private credentials are correct and should be preserved.
|
|
403
|
+
- Do not use raw share protocol fields, JS callbacks, activity reporting, post publishing, custom buttons, or upload-only flows.
|
|
404
|
+
- Do not use storage delete, clear, info listing, V2, or global Heybox client storage access.
|
|
405
|
+
- Do not pass host-only protocol fields through \`network.request\`.
|
|
406
|
+
- Do not build raw \`postMessage\` bridge flows in iframe business code.
|
|
407
|
+
- Do not import from internal hb-sdk implementation paths; only use documented package entrypoints.
|
|
408
|
+
`);
|
|
409
|
+
|
|
410
|
+
files.set('llms-index.md', `${header('LLM documentation index', [
|
|
411
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms.txt',
|
|
412
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/',
|
|
413
|
+
])}## Local generated docs entrypoint
|
|
414
|
+
|
|
415
|
+
The docs site maintains \`llms.txt\` and markdown mirrors under \`apps/h5/docs/hb_sdk/src/.vuepress/public/llms/\`. Read \`llms.txt\` first for navigation, then the specific guide/reference/recipe markdown needed for the task.
|
|
416
|
+
|
|
417
|
+
${fenced('md', llmsTxt)}
|
|
418
|
+
`);
|
|
419
|
+
|
|
420
|
+
files.set('examples.md', `${header('Smoke examples and anti-examples', [
|
|
421
|
+
'packages/hb-sdk/README.md',
|
|
422
|
+
'apps/h5/docs/hb_sdk/src/.vuepress/public/llms/',
|
|
423
|
+
])}## Positive examples
|
|
424
|
+
|
|
425
|
+
### Minimal user info
|
|
426
|
+
|
|
427
|
+
${fenced('ts', `import { ready, user } from '@heybox/hb-sdk';
|
|
428
|
+
|
|
429
|
+
await ready();
|
|
430
|
+
|
|
431
|
+
const result = await user.getInfo();
|
|
432
|
+
if (result.isLogin && result.userInfo) {
|
|
433
|
+
console.log(result.userInfo.nickname);
|
|
434
|
+
}`)}
|
|
435
|
+
|
|
436
|
+
### Login gate
|
|
437
|
+
|
|
438
|
+
${fenced('ts', `import { auth, ready, user, HbMiniProgramSDKError } from '@heybox/hb-sdk';
|
|
439
|
+
|
|
440
|
+
export async function ensureLogin() {
|
|
441
|
+
await ready();
|
|
442
|
+
|
|
443
|
+
const current = await user.getInfo();
|
|
444
|
+
if (current.isLogin && current.userInfo) return current.userInfo;
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
const loginResult = await auth.login();
|
|
448
|
+
return loginResult.userInfo;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
if (error instanceof HbMiniProgramSDKError) {
|
|
451
|
+
console.warn(error.code, error.message);
|
|
452
|
+
}
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
}`)}
|
|
456
|
+
|
|
457
|
+
### Network request
|
|
458
|
+
|
|
459
|
+
${fenced('ts', `import { ready, network, HbMiniProgramNetworkError } from '@heybox/hb-sdk';
|
|
460
|
+
|
|
461
|
+
try {
|
|
462
|
+
await ready();
|
|
463
|
+
|
|
464
|
+
const response = await network.request<{ ok: boolean }>({
|
|
465
|
+
url: 'https://api.example.com/demo',
|
|
466
|
+
method: 'GET',
|
|
467
|
+
validateStatus: status => status >= 200 && status < 400,
|
|
468
|
+
});
|
|
469
|
+
console.log(response.data.ok);
|
|
470
|
+
} catch (error) {
|
|
471
|
+
if (error instanceof HbMiniProgramNetworkError) {
|
|
472
|
+
console.warn(error.status, error.response?.data);
|
|
473
|
+
}
|
|
474
|
+
}`)}
|
|
475
|
+
|
|
476
|
+
### Host/runtime protocol import
|
|
477
|
+
|
|
478
|
+
${fenced('ts', `import { NETWORK_REQUEST_METHOD, type NetworkRequestPayload } from '@heybox/hb-sdk/protocol';
|
|
479
|
+
|
|
480
|
+
// Host/runtime integration only. Do not use this in iframe business code.
|
|
481
|
+
export function canHandleNetwork(method: string): method is typeof NETWORK_REQUEST_METHOD {
|
|
482
|
+
return method === NETWORK_REQUEST_METHOD;
|
|
483
|
+
}`)}
|
|
484
|
+
|
|
485
|
+
### CLI local mock development
|
|
486
|
+
|
|
487
|
+
${fenced('bash', `hb-sdk create my-miniapp
|
|
488
|
+
cd my-miniapp
|
|
489
|
+
npm install
|
|
490
|
+
npm run dev
|
|
491
|
+
|
|
492
|
+
# In an existing project:
|
|
493
|
+
hb-sdk dev`)}
|
|
494
|
+
|
|
495
|
+
### CLI login cache
|
|
496
|
+
|
|
497
|
+
${fenced('bash', `hb-sdk login
|
|
498
|
+
hb-sdk login status
|
|
499
|
+
hb-sdk login clear`)}
|
|
500
|
+
|
|
501
|
+
## Negative examples
|
|
502
|
+
|
|
503
|
+
- Do not import from internal hb-sdk implementation paths.
|
|
504
|
+
- Do not read cookies, tokens, phone numbers, or private credentials.
|
|
505
|
+
- Do not create raw \`postMessage\` bridge envelopes in business pages.
|
|
506
|
+
- Do not call unsupported storage delete/clear/info operations.
|
|
507
|
+
- Do not pass raw internal share/network protocol fields from mini-program code.
|
|
508
|
+
- Do not treat \`hb-sdk login\` as iframe SDK authentication state.
|
|
509
|
+
- Do not create a second mock runtime package when \`hb-sdk dev\` is the supported local mock workflow.
|
|
510
|
+
`);
|
|
511
|
+
|
|
512
|
+
const skillManifest = normalizeSkillManifest(createCurrentSkillManifest(files));
|
|
513
|
+
|
|
514
|
+
if (!existsSync(referencesRoot)) mkdirSync(referencesRoot, { recursive: true });
|
|
515
|
+
|
|
516
|
+
let changed = false;
|
|
517
|
+
for (const [fileName, content] of files.entries()) {
|
|
518
|
+
const target = path.join(referencesRoot, fileName);
|
|
519
|
+
const normalized = `${content.trimEnd()}\n`;
|
|
520
|
+
const current = existsSync(target) ? readFileSync(target, 'utf8') : '';
|
|
521
|
+
if (current !== normalized) {
|
|
522
|
+
changed = true;
|
|
523
|
+
if (!checkMode) writeFileSync(target, normalized);
|
|
524
|
+
console.error(`${checkMode ? 'outdated' : 'updated'} ${path.relative(repoRoot, target)}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const skillManifestPath = path.join(skillRoot, 'skill.json');
|
|
529
|
+
const currentSkillManifest = existsSync(skillManifestPath) ? readFileSync(skillManifestPath, 'utf8') : '';
|
|
530
|
+
if (currentSkillManifest !== skillManifest) {
|
|
531
|
+
changed = true;
|
|
532
|
+
if (!checkMode) writeFileSync(skillManifestPath, skillManifest);
|
|
533
|
+
console.error(`${checkMode ? 'outdated' : 'updated'} ${path.relative(repoRoot, skillManifestPath)}`);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (checkMode && changed) {
|
|
537
|
+
console.error(`hb-sdk skill references are out of date. Run \`node ${path.relative(repoRoot, fileURLToPath(import.meta.url)).split(path.sep).join('/')}\`.`);
|
|
538
|
+
process.exit(1);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
console.log(JSON.stringify({ ok: true, changed, references: [...files.keys()], skillVersion: JSON.parse(skillManifest).skillVersion }));
|