@heybox/hb-sdk 0.6.9 → 0.7.0-alpha.2
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/CHANGELOG.md +51 -7
- package/README.md +83 -20
- package/dist/cli-chunks/{build-BtGxhrcV.cjs → build-DLIhlBQA.cjs} +4 -4
- package/dist/cli-chunks/{context-DX1KG-8A.cjs → context-Bl_Q4RKq.cjs} +15 -2
- package/dist/cli-chunks/{create-DAD0OF1r.cjs → create-C--pwY0l.cjs} +1 -1
- package/dist/cli-chunks/{dev-Dh4HY0I8.cjs → dev-B1tyT5ql.cjs} +197 -13
- package/dist/cli-chunks/{doctor-BfKdiD3H.cjs → doctor-D9M2scaJ.cjs} +1 -1
- package/dist/cli-chunks/{index-tCURDEx8.cjs → index-BnBeTd0B.cjs} +15 -14
- package/dist/cli-chunks/{index-DB6Q8HaC.cjs → index-HNB8i51C.cjs} +2 -2
- package/dist/cli-chunks/{login-D60EJLgs.cjs → login-DnX81kof.cjs} +2 -2
- package/dist/cli-chunks/{project-vite-DAUaP0_3.cjs → project-vite-CgnCpNDZ.cjs} +1 -1
- package/dist/cli-chunks/{remote-nQDniAUY.cjs → remote-CETqg77E.cjs} +6 -6
- package/dist/cli-chunks/{runtime-gate-BWlU-R4h.cjs → runtime-gate-CtV7rWyX.cjs} +1 -1
- package/dist/cli-chunks/{runtime-permission-env-DKrhgVM3.cjs → runtime-permission-env-D-8_jPG3.cjs} +2 -0
- package/dist/cli-chunks/{session-D6jOKXeu.cjs → session-Davw2CMd.cjs} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/devtools/mock-host/index.html +9 -2
- package/dist/devtools/mock-host/main.js +426 -802
- package/dist/index.cjs.js +46 -90
- package/dist/index.esm.js +46 -90
- package/dist/miniapp-publish.cjs.js +2 -0
- package/dist/miniapp-publish.esm.js +2 -1
- package/dist/protocol.cjs.js +98 -42
- package/dist/protocol.esm.js +93 -39
- package/dist/templates/vue3-vite-ts/README.md.ejs +1 -1
- package/dist/templates/vue3-vite-ts/src/App.vue +22 -17
- package/dist/templates/vue3-vite-ts/src/__tests__/App.spec.ts +37 -29
- package/dist/templates/vue3-vite-ts/src/auth-handoff.ts +46 -0
- package/dist/vite.cjs.js +2 -2
- package/dist/vite.esm.js +2 -2
- package/package.json +2 -2
- package/skill/SKILL.md +16 -12
- package/skill/references/api-protocol.md +22 -28
- package/skill/references/api-root.md +127 -112
- package/skill/references/cli.md +15 -20
- package/skill/references/examples.md +29 -17
- package/skill/references/recipes.md +180 -134
- package/skill/references/safety-boundaries.md +9 -3
- package/skill/scripts/sync-references.mjs +235 -139
- package/skill/scripts/validate-skill.mjs +18 -14
- package/skill/skill.json +4 -4
- package/types/index.d.ts +4 -4
- package/types/miniapp-publish/index.d.ts +1 -0
- package/types/modules/auth/index.d.ts +16 -28
- package/types/modules/cloud/index.d.ts +2 -2
- package/types/modules/network/index.d.ts +1 -2
- package/types/modules/user/get-info.d.ts +4 -4
- package/types/modules/user/get-local-identity.d.ts +9 -0
- package/types/modules/user/index.d.ts +13 -41
- package/types/modules/user/revoke-authorization.d.ts +7 -0
- package/types/modules/user/steam-game-list.d.ts +72 -0
- package/types/modules/user/types.d.ts +37 -302
- package/types/protocol/capabilities.d.ts +24 -49
- package/types/protocol/constants.d.ts +1 -1
- package/types/protocol/network-policy.d.ts +10 -0
- package/types/protocol/types.d.ts +10 -6
- package/types/protocol.d.ts +4 -3
- package/types/modules/user/get-current-user-detail.d.ts +0 -9
- package/types/modules/user/get-current-user-profile.d.ts +0 -9
- package/types/modules/user/get-platform-account-info.d.ts +0 -12
- package/types/modules/user/get-platform-account-overview.d.ts +0 -9
- package/types/modules/user/get-steam-game-list.d.ts +0 -12
|
@@ -3,6 +3,7 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import process from 'node:process';
|
|
6
|
+
import ts from 'typescript';
|
|
6
7
|
import { createSkillContentHash, createSkillManifest, normalizeSkillManifest } from './skill-metadata.mjs';
|
|
7
8
|
|
|
8
9
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -13,7 +14,9 @@ const checkMode = process.argv.includes('--check');
|
|
|
13
14
|
const TEXT_FILE_RE = /\.(?:md|mjs|js|cjs|ts|tsx|json|txt|sh|yaml|yml)$/i;
|
|
14
15
|
|
|
15
16
|
if (!repoRoot) {
|
|
16
|
-
console.error(
|
|
17
|
+
console.error(
|
|
18
|
+
'Cannot sync hb-sdk references outside the heybox-webapp repository. Run this script from a checkout that contains packages/hb-sdk/package.json.',
|
|
19
|
+
);
|
|
17
20
|
process.exit(1);
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -35,7 +38,7 @@ function read(relativePath) {
|
|
|
35
38
|
|
|
36
39
|
function extractSection(markdown, heading) {
|
|
37
40
|
const lines = markdown.split('\n');
|
|
38
|
-
const start = lines.findIndex(line => line.trim() === heading);
|
|
41
|
+
const start = lines.findIndex((line) => line.trim() === heading);
|
|
39
42
|
if (start === -1) return '';
|
|
40
43
|
const level = heading.match(/^#+/)?.[0].length ?? 2;
|
|
41
44
|
const out = [lines[start]];
|
|
@@ -67,7 +70,7 @@ function extractSection(markdown, heading) {
|
|
|
67
70
|
|
|
68
71
|
function fenced(language, value) {
|
|
69
72
|
const content = value.trimEnd();
|
|
70
|
-
const longestFence = Math.max(2, ...Array.from(content.matchAll(/`{3,}/g), match => match[0].length));
|
|
73
|
+
const longestFence = Math.max(2, ...Array.from(content.matchAll(/`{3,}/g), (match) => match[0].length));
|
|
71
74
|
const fence = '`'.repeat(longestFence + 1);
|
|
72
75
|
return `${fence}${language}\n${content}\n${fence}`;
|
|
73
76
|
}
|
|
@@ -80,7 +83,7 @@ function header(title, sources) {
|
|
|
80
83
|
'',
|
|
81
84
|
'## Sources',
|
|
82
85
|
'',
|
|
83
|
-
...sources.map(source => `- ${source}`),
|
|
86
|
+
...sources.map((source) => `- ${source}`),
|
|
84
87
|
'',
|
|
85
88
|
].join('\n');
|
|
86
89
|
}
|
|
@@ -99,10 +102,7 @@ function rewriteBundledRecipeLinks(markdown) {
|
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
function rewriteBundledCliLinks(markdown) {
|
|
102
|
-
return markdown.replaceAll(
|
|
103
|
-
'(./mini-program-publishing-rules)',
|
|
104
|
-
'(https://docs.xiaoheihe.cn/hb_sdk/guide/mini-program-publishing-rules)',
|
|
105
|
-
);
|
|
105
|
+
return markdown.replaceAll('(./mini-program-publishing-rules)', '(https://docs.xiaoheihe.cn/hb_sdk/guide/mini-program-publishing-rules)');
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
function rewriteBundledProtocolIndexLinks(markdown) {
|
|
@@ -114,14 +114,50 @@ function rewriteBundledProtocolIndexLinks(markdown) {
|
|
|
114
114
|
.replaceAll('(../guide/)', '(recipes.md)');
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
const INTERNAL_PROTOCOL_DIAGNOSTIC_EXPORTS = new Set([
|
|
118
|
+
'RUNTIME_LOCATION_PROBE_METHOD',
|
|
119
|
+
'RuntimeLocationProbePayload',
|
|
120
|
+
'SDK_CSP_VIOLATION_METHOD',
|
|
121
|
+
'SDK_LOCATION_REPORT_METHOD',
|
|
122
|
+
'SDKCSPBlockedResourceType',
|
|
123
|
+
'SDKCSPViolationPayload',
|
|
124
|
+
'SDKLocationReportPayload',
|
|
125
|
+
'SDKLocationReportTrigger',
|
|
126
|
+
]);
|
|
127
|
+
|
|
128
|
+
function omitNamedExports(source, omittedNames) {
|
|
129
|
+
const sourceFile = ts.createSourceFile('protocol.ts', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
130
|
+
const lineStarts = sourceFile.getLineStarts();
|
|
131
|
+
const removals = [];
|
|
132
|
+
|
|
133
|
+
for (const statement of sourceFile.statements) {
|
|
134
|
+
if (!ts.isExportDeclaration(statement) || !statement.exportClause || !ts.isNamedExports(statement.exportClause)) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (const element of statement.exportClause.elements) {
|
|
139
|
+
if (!omittedNames.has(element.name.text)) continue;
|
|
140
|
+
|
|
141
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(element.getStart(sourceFile));
|
|
142
|
+
const start = lineStarts[line];
|
|
143
|
+
const end = lineStarts[line + 1] ?? source.length;
|
|
144
|
+
const lineText = source.slice(start, end).trim();
|
|
145
|
+
const elementText = element.getText(sourceFile);
|
|
146
|
+
|
|
147
|
+
if (lineText !== `${elementText},` && lineText !== elementText) {
|
|
148
|
+
throw new Error(`Internal protocol export must occupy its own line: ${element.name.text}`);
|
|
149
|
+
}
|
|
150
|
+
removals.push({ start, end });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return removals
|
|
155
|
+
.sort((left, right) => right.start - left.start)
|
|
156
|
+
.reduce((result, { start, end }) => `${result.slice(0, start)}${result.slice(end)}`, source);
|
|
157
|
+
}
|
|
158
|
+
|
|
117
159
|
function contents(items) {
|
|
118
|
-
return [
|
|
119
|
-
'',
|
|
120
|
-
'## Contents',
|
|
121
|
-
'',
|
|
122
|
-
...items.map(([title, anchor]) => `- [${title}](#${anchor})`),
|
|
123
|
-
'',
|
|
124
|
-
].join('\n');
|
|
160
|
+
return ['', '## Contents', '', ...items.map(([title, anchor]) => `- [${title}](#${anchor})`), ''].join('\n');
|
|
125
161
|
}
|
|
126
162
|
|
|
127
163
|
function toPosix(value) {
|
|
@@ -183,7 +219,7 @@ function createCurrentSkillManifest(generatedReferences) {
|
|
|
183
219
|
];
|
|
184
220
|
const fileEntries = Array.from(new Set(distributableFiles))
|
|
185
221
|
.sort((left, right) => left.localeCompare(right))
|
|
186
|
-
.map(relativePath => ({
|
|
222
|
+
.map((relativePath) => ({
|
|
187
223
|
path: relativePath,
|
|
188
224
|
content: readGeneratedOrDiskSkillFile(relativePath, generatedReferences),
|
|
189
225
|
}));
|
|
@@ -194,7 +230,6 @@ function createCurrentSkillManifest(generatedReferences) {
|
|
|
194
230
|
});
|
|
195
231
|
}
|
|
196
232
|
|
|
197
|
-
|
|
198
233
|
const packageJson = JSON.parse(read('packages/hb-sdk/package.json'));
|
|
199
234
|
const rootEntry = read('packages/hb-sdk/src/index.ts');
|
|
200
235
|
const protocolEntry = read('packages/hb-sdk/src/protocol.ts');
|
|
@@ -212,6 +247,8 @@ const customInstance = frontmatterless(read('apps/docs/hb-sdk/recipes/custom-ins
|
|
|
212
247
|
const referenceHome = frontmatterless(read('apps/docs/hb-sdk/reference/index.md'));
|
|
213
248
|
const publicCapabilities = extractSection(readme, '## 能力概览');
|
|
214
249
|
const capabilityBoundaries = extractSection(readme, '## 关键约束');
|
|
250
|
+
const leaderboardSection = extractSection(readme, '## 云端排行榜');
|
|
251
|
+
const publicProtocolEntry = omitNamedExports(protocolEntry, INTERNAL_PROTOCOL_DIAGNOSTIC_EXPORTS);
|
|
215
252
|
const manifestSection = extractSection(cliGuide, '## 生产构建');
|
|
216
253
|
const cliCreateSection = extractSection(cliGuide, '## 创建工坊小程序');
|
|
217
254
|
const cliDevSection = extractSection(cliGuide, '## 推荐调试流程');
|
|
@@ -254,9 +291,12 @@ Removed: hb-sdk deploy`;
|
|
|
254
291
|
|
|
255
292
|
const cliRemoteEntitySection = `Developer account selection lives under \`hb-sdk remote entity\`:
|
|
256
293
|
|
|
257
|
-
${fenced(
|
|
294
|
+
${fenced(
|
|
295
|
+
'bash',
|
|
296
|
+
`hb-sdk remote entity list
|
|
258
297
|
hb-sdk remote entity current
|
|
259
|
-
hb-sdk remote entity switch <entity-id
|
|
298
|
+
hb-sdk remote entity switch <entity-id>`,
|
|
299
|
+
)}
|
|
260
300
|
|
|
261
301
|
Remote management commands use the current developer account. Use \`current\` to confirm it and \`switch\` to change it before creating, binding, or publishing a mini-program.`;
|
|
262
302
|
|
|
@@ -264,22 +304,25 @@ const cliRemoteEntityDeploySection = `Before publishing, \`hb-sdk remote deploy\
|
|
|
264
304
|
|
|
265
305
|
const files = new Map();
|
|
266
306
|
|
|
267
|
-
files.set(
|
|
268
|
-
'
|
|
269
|
-
'
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
[
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
307
|
+
files.set(
|
|
308
|
+
'api-root.md',
|
|
309
|
+
`${header('Root API reference', [
|
|
310
|
+
'packages/hb-sdk/package.json',
|
|
311
|
+
'packages/hb-sdk/src/index.ts',
|
|
312
|
+
'packages/hb-sdk/src/vite/index.ts',
|
|
313
|
+
'packages/hb-sdk/README.md',
|
|
314
|
+
'apps/docs/hb-sdk/guide/quick-start.md',
|
|
315
|
+
'apps/docs/hb-sdk/guide/error-handling.md',
|
|
316
|
+
'apps/docs/hb-sdk/guide/lifecycle.md',
|
|
317
|
+
'apps/docs/hb-sdk/guide/cli.md',
|
|
318
|
+
])}${contents([
|
|
319
|
+
['Package metadata', 'package-metadata'],
|
|
320
|
+
['Public root entrypoint', 'public-root-entrypoint'],
|
|
321
|
+
['Vite plugin export', 'vite-plugin-export'],
|
|
322
|
+
['App-facing concepts', 'app-facing-concepts'],
|
|
323
|
+
['Public modules', 'public-modules'],
|
|
324
|
+
['Cloud leaderboard', 'cloud-leaderboard'],
|
|
325
|
+
])}## Package metadata
|
|
283
326
|
|
|
284
327
|
- Package: \`${packageJson.name}\`
|
|
285
328
|
- Version at generation time: \`${packageJson.version}\`
|
|
@@ -310,53 +353,58 @@ ${rewriteBundledRecipeLinks(errorGuide)}
|
|
|
310
353
|
${publicCapabilities}
|
|
311
354
|
|
|
312
355
|
${rewriteBundledRecipeLinks(lifecycleGuide)}
|
|
313
|
-
`);
|
|
314
356
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
357
|
+
${leaderboardSection}
|
|
358
|
+
`,
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
files.set(
|
|
362
|
+
'api-protocol.md',
|
|
363
|
+
`${header('Protocol API reference', ['packages/hb-sdk/src/protocol.ts', 'apps/docs/hb-sdk/reference/index.md'])}${contents([
|
|
364
|
+
['Host/runtime-only warning', 'hostruntime-only-warning'],
|
|
365
|
+
['Public protocol entrypoint', 'public-protocol-entrypoint'],
|
|
366
|
+
['Generated reference index', 'generated-reference-index'],
|
|
367
|
+
])}## Host/runtime-only warning
|
|
323
368
|
|
|
324
369
|
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.
|
|
325
370
|
|
|
326
371
|
## Public protocol entrypoint
|
|
327
372
|
|
|
328
|
-
${fenced('ts',
|
|
373
|
+
${fenced('ts', publicProtocolEntry)}
|
|
329
374
|
|
|
330
375
|
## Generated reference index
|
|
331
376
|
|
|
332
377
|
${rewriteBundledProtocolIndexLinks(referenceHome)}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
'
|
|
338
|
-
'
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
[
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
378
|
+
`,
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
files.set(
|
|
382
|
+
'cli.md',
|
|
383
|
+
`${header('CLI reference', [
|
|
384
|
+
'packages/hb-sdk/package.json',
|
|
385
|
+
'packages/hb-sdk/src/cli/index.ts',
|
|
386
|
+
'packages/hb-sdk/src/cli/commands/create.ts',
|
|
387
|
+
'packages/hb-sdk/src/cli/commands/dev.ts',
|
|
388
|
+
'packages/hb-sdk/src/cli/commands/build.ts',
|
|
389
|
+
'packages/hb-sdk/src/cli/commands/login.ts',
|
|
390
|
+
'apps/docs/hb-sdk/guide/cli.md',
|
|
391
|
+
])}${contents([
|
|
392
|
+
['When to use the CLI', 'when-to-use-the-cli'],
|
|
393
|
+
['Command surface', 'command-surface'],
|
|
394
|
+
['Create a mini-program template', 'create-a-mini-program-template'],
|
|
395
|
+
['Local debugging', 'local-debugging'],
|
|
396
|
+
['Production build', 'production-build'],
|
|
397
|
+
['Deploy and publish', 'deploy-and-publish'],
|
|
398
|
+
['Developer account scope', 'developer-account-scope'],
|
|
399
|
+
['Remote management commands', 'remote-management-commands'],
|
|
400
|
+
['CLI login', 'cli-login'],
|
|
401
|
+
['Agent Skill doctor', 'agent-skill-doctor'],
|
|
402
|
+
['Update reminders', 'update-reminders'],
|
|
403
|
+
])}## When to use the CLI
|
|
356
404
|
|
|
357
405
|
Use the bundled \`hb-sdk\` CLI to create a workshop mini-program, open the local debugging page, test in the Heybox Mac or mobile App, or manage and publish a remote mini-program.
|
|
358
406
|
|
|
359
|
-
\`hb-sdk login\` is for development and publishing commands only. It does not change \`auth.login()\`, \`user.
|
|
407
|
+
\`hb-sdk login\` is for development and publishing commands only. It does not authorize mini-program users and does not change \`auth.login()\`, \`user.getLocalIdentity()\`, or \`network.request()\` inside a mini-program.
|
|
360
408
|
|
|
361
409
|
## Command surface
|
|
362
410
|
|
|
@@ -460,25 +508,28 @@ Agent rules:
|
|
|
460
508
|
|
|
461
509
|
${cliUpdateSection}
|
|
462
510
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
'
|
|
468
|
-
'
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
[
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
511
|
+
`,
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
files.set(
|
|
515
|
+
'recipes.md',
|
|
516
|
+
`${header('Recipes', [
|
|
517
|
+
'apps/docs/hb-sdk/guide/quick-start.md',
|
|
518
|
+
'apps/docs/hb-sdk/guide/auth.md',
|
|
519
|
+
'apps/docs/hb-sdk/guide/lifecycle.md',
|
|
520
|
+
'apps/docs/hb-sdk/guide/error-handling.md',
|
|
521
|
+
'apps/docs/hb-sdk/recipes/login-gate.md',
|
|
522
|
+
'apps/docs/hb-sdk/recipes/community-share.md',
|
|
523
|
+
'apps/docs/hb-sdk/recipes/custom-instance.md',
|
|
524
|
+
])}${contents([
|
|
525
|
+
['Quick start', 'quick-start'],
|
|
526
|
+
['User and login', 'user-and-login'],
|
|
527
|
+
['Lifecycle events', 'lifecycle-events'],
|
|
528
|
+
['Error handling', 'error-handling'],
|
|
529
|
+
['Login gate recipe', 'login-gate-recipe'],
|
|
530
|
+
['Community share recipe', 'community-share-recipe'],
|
|
531
|
+
['Custom instance recipe', 'custom-instance-recipe'],
|
|
532
|
+
])}## Quick start
|
|
482
533
|
|
|
483
534
|
${rewriteBundledRecipeLinks(quickStart)}
|
|
484
535
|
|
|
@@ -505,12 +556,12 @@ ${rewriteBundledRecipeLinks(communityShare)}
|
|
|
505
556
|
## Custom instance recipe
|
|
506
557
|
|
|
507
558
|
${rewriteBundledRecipeLinks(customInstance)}
|
|
508
|
-
|
|
559
|
+
`,
|
|
560
|
+
);
|
|
509
561
|
|
|
510
|
-
files.set(
|
|
511
|
-
'
|
|
512
|
-
'apps/docs/hb-sdk/guide/auth.md'
|
|
513
|
-
])}## Required boundaries
|
|
562
|
+
files.set(
|
|
563
|
+
'safety-boundaries.md',
|
|
564
|
+
`${header('Safety boundaries', ['packages/hb-sdk/README.md', 'apps/docs/hb-sdk/guide/auth.md'])}## Required boundaries
|
|
514
565
|
|
|
515
566
|
${capabilityBoundaries}
|
|
516
567
|
|
|
@@ -519,19 +570,22 @@ ${capabilityBoundaries}
|
|
|
519
570
|
- Do not instruct mini-program code to read, extract, forward, store, or depend on token, cookie, phone number, or private credentials.
|
|
520
571
|
- Negative safety statements that explain the SDK does not expose token/cookie/private credentials are correct and should be preserved.
|
|
521
572
|
- Do not use raw share protocol fields, JS callbacks, activity reporting, direct post publishing, custom buttons, or upload-only flows. Public \`share.*({ post })\` options only preset an editable client post flow.
|
|
522
|
-
- Do not use storage delete, clear, info listing,
|
|
573
|
+
- Do not use storage delete, clear, info listing, or global Heybox client storage access.
|
|
523
574
|
- Do not pass host-only protocol fields through \`network.request\`.
|
|
524
575
|
- Do not build raw \`postMessage\` bridge flows in iframe business code.
|
|
525
576
|
- Do not fetch deployed \`dist/manifest.json\` from business code; it is a build artifact for the release pipeline, not a CDN runtime asset.
|
|
526
577
|
- Do not import from internal hb-sdk implementation paths; only use documented package entrypoints.
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
'
|
|
532
|
-
'
|
|
533
|
-
|
|
534
|
-
|
|
578
|
+
`,
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
files.set(
|
|
582
|
+
'llms-index.md',
|
|
583
|
+
`${header('LLM documentation index', [
|
|
584
|
+
'apps/docs/hb-sdk/guide/**',
|
|
585
|
+
'apps/docs/hb-sdk/recipes/**',
|
|
586
|
+
'apps/docs/hb-sdk/reference/**',
|
|
587
|
+
'packages/hb-sdk/src/**',
|
|
588
|
+
])}## Offline references
|
|
535
589
|
|
|
536
590
|
The bundled references are generated directly from hand-maintained docs, generated API owner sources, and SDK/CLI sources. They do not depend on the docs site's \`.vitepress/public/llms\` mirrors.
|
|
537
591
|
|
|
@@ -545,49 +599,72 @@ The bundled references are generated directly from hand-maintained docs, generat
|
|
|
545
599
|
## Online supplement
|
|
546
600
|
|
|
547
601
|
Online \`llms.txt\` and markdown mirrors are optional supplements, not prerequisites for offline Skill use. Their canonical public URL is not frozen: on 2026-07-10 \`https://docs.xiaoheihe.cn/hb_sdk/llms.txt\` returned 404 and the legacy URL fetch timed out. Do not claim either endpoint is available without a fresh successful response.
|
|
548
|
-
|
|
602
|
+
`,
|
|
603
|
+
);
|
|
549
604
|
|
|
550
|
-
files.set(
|
|
551
|
-
'
|
|
552
|
-
'
|
|
553
|
-
|
|
554
|
-
|
|
605
|
+
files.set(
|
|
606
|
+
'examples.md',
|
|
607
|
+
`${header('Smoke examples and anti-examples', [
|
|
608
|
+
'packages/hb-sdk/README.md',
|
|
609
|
+
'apps/docs/hb-sdk/guide/**',
|
|
610
|
+
'apps/docs/hb-sdk/recipes/**',
|
|
611
|
+
])}## Positive examples
|
|
555
612
|
|
|
556
|
-
###
|
|
613
|
+
### Local identity for a network-disabled mini-program
|
|
557
614
|
|
|
558
|
-
${fenced(
|
|
615
|
+
${fenced(
|
|
616
|
+
'ts',
|
|
617
|
+
`import { ready, user, HbMiniProgramSDKError } from '@heybox/hb-sdk';
|
|
559
618
|
|
|
560
|
-
|
|
619
|
+
export async function getLocalIdentityFromUserAction() {
|
|
620
|
+
await ready();
|
|
561
621
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
622
|
+
try {
|
|
623
|
+
return await user.getLocalIdentity();
|
|
624
|
+
} catch (error) {
|
|
625
|
+
if (error instanceof HbMiniProgramSDKError && error.code === 'AUTHORIZATION_CANCELLED') {
|
|
626
|
+
return undefined;
|
|
627
|
+
}
|
|
628
|
+
throw error;
|
|
629
|
+
}
|
|
630
|
+
}`,
|
|
631
|
+
)}
|
|
566
632
|
|
|
567
|
-
###
|
|
633
|
+
### Developer server session for a network-enabled mini-program
|
|
568
634
|
|
|
569
|
-
${fenced(
|
|
635
|
+
${fenced(
|
|
636
|
+
'ts',
|
|
637
|
+
`import { auth, network, ready, HbMiniProgramSDKError } from '@heybox/hb-sdk';
|
|
570
638
|
|
|
571
|
-
export async function
|
|
639
|
+
export async function createServerSessionFromUserAction() {
|
|
572
640
|
await ready();
|
|
573
641
|
|
|
574
|
-
const current = await user.getInfo();
|
|
575
|
-
if (current.isLogin && current.userInfo) return current.userInfo;
|
|
576
|
-
|
|
577
642
|
try {
|
|
578
|
-
const
|
|
579
|
-
|
|
643
|
+
const result = await auth.login({ scopes: ['profile'] });
|
|
644
|
+
await exchangeCodeWithDeveloperServer(result.code);
|
|
645
|
+
return { status: 'ready' as const };
|
|
580
646
|
} catch (error) {
|
|
581
|
-
if (error instanceof HbMiniProgramSDKError) {
|
|
582
|
-
|
|
647
|
+
if (error instanceof HbMiniProgramSDKError && error.code === 'AUTHORIZATION_CANCELLED') {
|
|
648
|
+
return { status: 'cancelled' as const };
|
|
583
649
|
}
|
|
584
|
-
|
|
650
|
+
throw error;
|
|
585
651
|
}
|
|
586
|
-
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
async function exchangeCodeWithDeveloperServer(code: string) {
|
|
655
|
+
await network.request({
|
|
656
|
+
url: 'https://api.example.com/session/heybox',
|
|
657
|
+
method: 'POST',
|
|
658
|
+
data: { code },
|
|
659
|
+
});
|
|
660
|
+
}`,
|
|
661
|
+
)}
|
|
587
662
|
|
|
588
663
|
### Network request
|
|
589
664
|
|
|
590
|
-
${fenced(
|
|
665
|
+
${fenced(
|
|
666
|
+
'ts',
|
|
667
|
+
`import { ready, network, HbMiniProgramNetworkError, HbMiniProgramSDKError } from '@heybox/hb-sdk';
|
|
591
668
|
|
|
592
669
|
try {
|
|
593
670
|
await ready();
|
|
@@ -616,42 +693,55 @@ try {
|
|
|
616
693
|
// e.g. INVALID_PARAMS for unsupported multipart shape
|
|
617
694
|
console.warn(error.code, error.message);
|
|
618
695
|
}
|
|
619
|
-
}
|
|
696
|
+
}`,
|
|
697
|
+
)}
|
|
620
698
|
|
|
621
699
|
### Host/runtime protocol import
|
|
622
700
|
|
|
623
|
-
${fenced(
|
|
701
|
+
${fenced(
|
|
702
|
+
'ts',
|
|
703
|
+
`import { NETWORK_REQUEST_METHOD, type NetworkRequestPayload } from '@heybox/hb-sdk/protocol';
|
|
624
704
|
|
|
625
705
|
// Host/runtime integration only. Do not use this in iframe business code.
|
|
626
706
|
export function canHandleNetwork(method: string): method is typeof NETWORK_REQUEST_METHOD {
|
|
627
707
|
return method === NETWORK_REQUEST_METHOD;
|
|
628
|
-
}
|
|
708
|
+
}`,
|
|
709
|
+
)}
|
|
629
710
|
|
|
630
711
|
### CLI local mock development
|
|
631
712
|
|
|
632
|
-
${fenced(
|
|
713
|
+
${fenced(
|
|
714
|
+
'bash',
|
|
715
|
+
`hb-sdk create my-miniapp
|
|
633
716
|
cd my-miniapp
|
|
634
717
|
npm install
|
|
635
718
|
npm run dev
|
|
636
719
|
|
|
637
720
|
# In an existing project:
|
|
638
|
-
hb-sdk dev
|
|
721
|
+
hb-sdk dev`,
|
|
722
|
+
)}
|
|
639
723
|
|
|
640
724
|
### CLI login cache
|
|
641
725
|
|
|
642
|
-
${fenced(
|
|
726
|
+
${fenced(
|
|
727
|
+
'bash',
|
|
728
|
+
`hb-sdk login
|
|
643
729
|
hb-sdk login status
|
|
644
|
-
hb-sdk login clear
|
|
730
|
+
hb-sdk login clear`,
|
|
731
|
+
)}
|
|
645
732
|
|
|
646
733
|
### Vite manifest plugin
|
|
647
734
|
|
|
648
|
-
${fenced(
|
|
735
|
+
${fenced(
|
|
736
|
+
'ts',
|
|
737
|
+
`import { miniappManifest } from '@heybox/hb-sdk/vite';
|
|
649
738
|
import { defineConfig } from 'vite';
|
|
650
739
|
|
|
651
740
|
export default defineConfig({
|
|
652
741
|
base: './',
|
|
653
742
|
plugins: [miniappManifest()],
|
|
654
|
-
})
|
|
743
|
+
});`,
|
|
744
|
+
)}
|
|
655
745
|
|
|
656
746
|
## Negative examples
|
|
657
747
|
|
|
@@ -664,7 +754,8 @@ export default defineConfig({
|
|
|
664
754
|
- Do not treat \`hb-sdk login\` as iframe SDK authentication state.
|
|
665
755
|
- Do not create a second mock runtime package when \`hb-sdk dev\` is the supported local mock workflow.
|
|
666
756
|
- Do not import \`@heybox/hb-sdk/vite\` from iframe business code or fetch a deployed \`manifest.json\` directly.
|
|
667
|
-
|
|
757
|
+
`,
|
|
758
|
+
);
|
|
668
759
|
|
|
669
760
|
const skillManifest = normalizeSkillManifest(createCurrentSkillManifest(files));
|
|
670
761
|
|
|
@@ -691,7 +782,12 @@ if (currentSkillManifest !== skillManifest) {
|
|
|
691
782
|
}
|
|
692
783
|
|
|
693
784
|
if (checkMode && changed) {
|
|
694
|
-
console.error(
|
|
785
|
+
console.error(
|
|
786
|
+
`hb-sdk skill references are out of date. Run \`node ${path
|
|
787
|
+
.relative(repoRoot, fileURLToPath(import.meta.url))
|
|
788
|
+
.split(path.sep)
|
|
789
|
+
.join('/')}\`.`,
|
|
790
|
+
);
|
|
695
791
|
process.exit(1);
|
|
696
792
|
}
|
|
697
793
|
|
|
@@ -3,11 +3,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import process from 'node:process';
|
|
6
|
-
import {
|
|
7
|
-
HB_SDK_PACKAGE_NAME,
|
|
8
|
-
HB_SDK_SKILL_NAME,
|
|
9
|
-
validateSkillManifest,
|
|
10
|
-
} from './skill-metadata.mjs';
|
|
6
|
+
import { HB_SDK_PACKAGE_NAME, HB_SDK_SKILL_NAME, validateSkillManifest } from './skill-metadata.mjs';
|
|
11
7
|
|
|
12
8
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
13
9
|
const skillRoot = path.resolve(scriptDir, '..');
|
|
@@ -156,17 +152,18 @@ if (existsSync(skillMdPath)) {
|
|
|
156
152
|
}
|
|
157
153
|
|
|
158
154
|
const nestedReferenceFiles = existsSync(path.join(skillRoot, 'references'))
|
|
159
|
-
? walk(path.join(skillRoot, 'references')).filter(file =>
|
|
155
|
+
? walk(path.join(skillRoot, 'references')).filter((file) =>
|
|
156
|
+
path.dirname(path.relative(path.join(skillRoot, 'references'), file)).includes(path.sep),
|
|
157
|
+
)
|
|
160
158
|
: [];
|
|
161
159
|
for (const file of nestedReferenceFiles) fail(`References must be one level deep: ${skillRel(file)}`);
|
|
162
160
|
|
|
163
|
-
if (existsSync(path.join(skillRoot, 'README.md')))
|
|
161
|
+
if (existsSync(path.join(skillRoot, 'README.md')))
|
|
162
|
+
fail('Do not create README.md inside hb-sdk skill; keep human distribution docs outside the skill folder.');
|
|
164
163
|
if (existsSync(path.join(skillRoot, 'CHANGELOG.md'))) fail('Do not create CHANGELOG.md inside hb-sdk skill.');
|
|
165
164
|
if (existsSync(path.join(skillRoot, 'INSTALLATION_GUIDE.md'))) fail('Do not create INSTALLATION_GUIDE.md inside hb-sdk skill.');
|
|
166
165
|
|
|
167
|
-
const textFiles = existsSync(skillRoot)
|
|
168
|
-
? walk(skillRoot).filter(file => /\.(md|yaml|yml|json|txt)$/.test(file))
|
|
169
|
-
: [];
|
|
166
|
+
const textFiles = existsSync(skillRoot) ? walk(skillRoot).filter((file) => /\.(md|yaml|yml|json|txt)$/.test(file)) : [];
|
|
170
167
|
|
|
171
168
|
const negativeMarkers = [
|
|
172
169
|
'do not',
|
|
@@ -189,7 +186,8 @@ const negativeMarkers = [
|
|
|
189
186
|
'无',
|
|
190
187
|
'禁止',
|
|
191
188
|
];
|
|
192
|
-
const positiveCredentialPattern =
|
|
189
|
+
const positiveCredentialPattern =
|
|
190
|
+
/\b(read|extract|forward|store|persist|depend on|use|request|expose|get|parse|send)\b.*\b(token|cookie|credentials?|phone number|login state)\b/i;
|
|
193
191
|
const unsupportedStoragePattern = /\b(removeStorage|clearStorage|getStorageInfo|getStorageV2|delete storage|clear storage)\b/i;
|
|
194
192
|
const rawProtocolPattern = /\b(raw postMessage|construct bridge|bridge envelope|nonce handling|mutate bridge|sdk\.handshake)\b/i;
|
|
195
193
|
const removedUserLoginPattern = /\b(?:hbSDK\.)?user\.login\s*\(/;
|
|
@@ -199,10 +197,16 @@ for (const file of textFiles) {
|
|
|
199
197
|
const content = read(file);
|
|
200
198
|
if (file.endsWith('.md')) validateLocalMarkdownLinks(file, content);
|
|
201
199
|
if (removedUserLoginPattern.test(content)) {
|
|
202
|
-
fail(
|
|
200
|
+
fail(
|
|
201
|
+
`Removed API guidance found in ${relative}: use auth.login() for network-enabled server authentication or user.getLocalIdentity() for network-disabled local identity instead of user.login().`,
|
|
202
|
+
);
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
if (
|
|
205
|
+
if (
|
|
206
|
+
new RegExp(`${HB_SDK_PACKAGE_NAME.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\/(?!(?:protocol|vite|miniapp-publish)\\b)[A-Za-z0-9_./-]+`).test(
|
|
207
|
+
content,
|
|
208
|
+
)
|
|
209
|
+
) {
|
|
206
210
|
fail(
|
|
207
211
|
`Deep/internal hb-sdk import guidance found in ${relative}. Only @heybox/hb-sdk, @heybox/hb-sdk/protocol, @heybox/hb-sdk/vite, and @heybox/hb-sdk/miniapp-publish are allowed.`,
|
|
208
212
|
);
|
|
@@ -211,7 +215,7 @@ for (const file of textFiles) {
|
|
|
211
215
|
const lines = content.split('\n');
|
|
212
216
|
lines.forEach((line, index) => {
|
|
213
217
|
const lower = line.toLowerCase();
|
|
214
|
-
const isNegative = negativeMarkers.some(marker => lower.includes(marker));
|
|
218
|
+
const isNegative = negativeMarkers.some((marker) => lower.includes(marker));
|
|
215
219
|
if (positiveCredentialPattern.test(line) && !isNegative) {
|
|
216
220
|
fail(`Unsafe positive credential guidance in ${relative}:${index + 1}: ${line.trim()}`);
|
|
217
221
|
}
|