@moxxy/sdk 0.12.0 → 0.13.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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Exhaustiveness guard for discriminated unions. Put it in the `default:` branch
3
+ * (or any spot the type system has narrowed to `never`): if a new union member
4
+ * is added without a matching case, the call becomes a **compile error** instead
5
+ * of a silent runtime no-op.
6
+ *
7
+ * ```ts
8
+ * switch (action.kind) {
9
+ * case 'a': return handleA(action);
10
+ * case 'b': return handleB(action);
11
+ * default: return assertNever(action);
12
+ * }
13
+ * ```
14
+ *
15
+ * At runtime — should the narrowing be defeated by an untyped caller — it throws
16
+ * with the offending value, surfacing the bug rather than swallowing it.
17
+ */
18
+ export declare function assertNever(value: never, message?: string): never;
19
+ //# sourceMappingURL=assert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../src/assert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAEjE"}
package/dist/assert.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Exhaustiveness guard for discriminated unions. Put it in the `default:` branch
3
+ * (or any spot the type system has narrowed to `never`): if a new union member
4
+ * is added without a matching case, the call becomes a **compile error** instead
5
+ * of a silent runtime no-op.
6
+ *
7
+ * ```ts
8
+ * switch (action.kind) {
9
+ * case 'a': return handleA(action);
10
+ * case 'b': return handleB(action);
11
+ * default: return assertNever(action);
12
+ * }
13
+ * ```
14
+ *
15
+ * At runtime — should the narrowing be defeated by an untyped caller — it throws
16
+ * with the offending value, surfacing the bug rather than swallowing it.
17
+ */
18
+ export function assertNever(value, message) {
19
+ throw new Error(message ?? `assertNever: unexpected value ${stringify(value)}`);
20
+ }
21
+ function stringify(value) {
22
+ try {
23
+ return JSON.stringify(value) ?? String(value);
24
+ }
25
+ catch {
26
+ return String(value);
27
+ }
28
+ }
29
+ //# sourceMappingURL=assert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert.js","sourceRoot":"","sources":["../src/assert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,WAAW,CAAC,KAAY,EAAE,OAAgB;IACxD,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,iCAAiC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -16,6 +16,14 @@ export interface WriteFileAtomicOptions {
16
16
  * tools) should call this instead of hand-rolling tmp+rename or writing in place.
17
17
  */
18
18
  export declare function writeFileAtomic(target: string, data: string | Uint8Array, opts?: WriteFileAtomicOptions): Promise<void>;
19
+ /**
20
+ * Synchronous twin of {@link writeFileAtomic}, for the few call sites that
21
+ * cannot be async — boot/bootstrap and self-update gates that run before the
22
+ * event loop is the right tool. Same crash-atomic guarantee: write a unique
23
+ * sibling temp file, then `rename` it over the target. Hand-rolled
24
+ * `mkdirSync + writeFileSync(tmp) + renameSync` copies should call this instead.
25
+ */
26
+ export declare function writeFileAtomicSync(target: string, data: string | Uint8Array, opts?: WriteFileAtomicOptions): void;
19
27
  /**
20
28
  * The moxxy home directory: `$MOXXY_HOME` when set, else `~/.moxxy`. Single
21
29
  * source of truth so the env override is honored uniformly — previously half
@@ -1 +1 @@
1
- {"version":3,"file":"fs-utils.d.ts","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,sBAAsB;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,kDAAkD;AAClD,wBAAgB,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvD"}
1
+ {"version":3,"file":"fs-utils.d.ts","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,sBAAsB;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,IAAI,GAAE,sBAA2B,GAChC,IAAI,CAiBN;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,kDAAkD;AAClD,wBAAgB,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvD"}
package/dist/fs-utils.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
+ import { chmodSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
2
3
  import { chmod, mkdir, rename, rm, writeFile } from 'node:fs/promises';
3
4
  import { homedir } from 'node:os';
4
5
  import { dirname, join } from 'node:path';
@@ -29,6 +30,34 @@ export async function writeFileAtomic(target, data, opts = {}) {
29
30
  throw err;
30
31
  }
31
32
  }
33
+ /**
34
+ * Synchronous twin of {@link writeFileAtomic}, for the few call sites that
35
+ * cannot be async — boot/bootstrap and self-update gates that run before the
36
+ * event loop is the right tool. Same crash-atomic guarantee: write a unique
37
+ * sibling temp file, then `rename` it over the target. Hand-rolled
38
+ * `mkdirSync + writeFileSync(tmp) + renameSync` copies should call this instead.
39
+ */
40
+ export function writeFileAtomicSync(target, data, opts = {}) {
41
+ mkdirSync(dirname(target), { recursive: true });
42
+ const tmp = `${target}.${process.pid}.${randomUUID()}.tmp`;
43
+ try {
44
+ writeFileSync(tmp, data, { encoding: opts.encoding ?? 'utf8' });
45
+ // chmod explicitly: writeFileSync's mode option is masked by umask, but a
46
+ // 0o600 secret file must be exactly 0o600 regardless of the host umask.
47
+ if (opts.mode != null)
48
+ chmodSync(tmp, opts.mode);
49
+ renameSync(tmp, target);
50
+ }
51
+ catch (err) {
52
+ try {
53
+ rmSync(tmp, { force: true });
54
+ }
55
+ catch {
56
+ /* best-effort cleanup */
57
+ }
58
+ throw err;
59
+ }
60
+ }
32
61
  /**
33
62
  * The moxxy home directory: `$MOXXY_HOME` when set, else `~/.moxxy`. Single
34
63
  * source of truth so the env override is honored uniformly — previously half
@@ -1 +1 @@
1
- {"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAS1C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,IAAyB,EACzB,OAA+B,EAAE;IAEjC,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAC;QAClE,sEAAsE;QACtE,wEAAwE;QACxE,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;YAAE,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,SAAS,CAAC,GAAG,QAAkB;IAC7C,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAS1C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,IAAyB,EACzB,OAA+B,EAAE;IAEjC,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAC;QAClE,sEAAsE;QACtE,wEAAwE;QACxE,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;YAAE,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAc,EACd,IAAyB,EACzB,OAA+B,EAAE;IAEjC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;IAC3D,IAAI,CAAC;QACH,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAC;QAChE,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;YAAE,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,SAAS,CAAC,GAAG,QAAkB;IAC7C,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC;AACxC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -16,12 +16,14 @@ export type { CacheStrategyDef, CacheStrategyContext } from './cache-strategy.js
16
16
  export type { DiffLine, DiffHunk, DiffRow, FileDiffDisplay, ToolDisplay, ToolDisplayResult, } from './tool-display.js';
17
17
  export { isToolDisplayResult, isToolDisplay, isFileDiffDisplay, fileDiffSummary, fileDiffVerb, diffGutterNo, toDiffRows, } from './tool-display.js';
18
18
  export type { ViewNode, ViewAction, ViewDoc, ViewParseError, ViewParseResult, AttrType, AttrSpec, ViewTagSpec, ViewRendererDef, } from './view-renderer.js';
19
- export { VIEW_PRIMITIVES, VIEW_COMPONENTS, DEFAULT_VIEW_TAGS, isSafeViewUrl } from './view-renderer.js';
19
+ export { VIEW_PRIMITIVES, VIEW_COMPONENTS, DEFAULT_VIEW_TAGS, isSafeViewUrl, countNodes } from './view-renderer.js';
20
20
  export type { TunnelProviderDef, TunnelHandle, TunnelOpenOptions, SpawnCliTunnelOptions, CliTunnelHandle, } from './tunnel.js';
21
21
  export { spawnCliTunnel, isCliTunnelAvailable } from './tunnel.js';
22
22
  export { isRetryableError, toFriendlyError, zodToJsonSchema, estimateTextTokens, type StopReason } from './provider-utils.js';
23
- export { writeFileAtomic, moxxyHome, moxxyPath, type WriteFileAtomicOptions } from './fs-utils.js';
23
+ export { writeFileAtomic, writeFileAtomicSync, moxxyHome, moxxyPath, type WriteFileAtomicOptions, } from './fs-utils.js';
24
24
  export { createMutex, type Mutex } from './mutex.js';
25
+ export { assertNever } from './assert.js';
26
+ export { compareSemver, parseSemverCore } from './semver.js';
25
27
  export { readRequestBody, bearerTokenMatches } from './http-utils.js';
26
28
  export { resolveChannelToken, rotateChannelToken, bearerGuard, encodeWsBearerProtocol, tokenFromWsProtocolHeader, MOXXY_WS_SUBPROTOCOL, MOXXY_WS_BEARER_PROTOCOL_PREFIX, type ChannelTokenOptions, } from './channel-auth.js';
27
29
  export { autoAllowResolver, denyByDefaultResolver, createCallbackResolver, createAllowListResolver, createDeferredPermissionResolver, evaluateToolRule, type CallbackResolverOptions, type PermissionPromptHandler, type DeferredPermissionResolver, type DeferredPermissionResolverOptions, } from './resolvers.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2,11 +2,13 @@ export { asEventId, asTurnId, asToolCallId, asSessionId, asPluginId, asSkillId }
2
2
  export { ISOLATION_RANK } from './isolation.js';
3
3
  export { encodeLoginPrompt, decodeLoginPrompt, createLoginStreamScanner, } from './provider-login-bridge.js';
4
4
  export { isToolDisplayResult, isToolDisplay, isFileDiffDisplay, fileDiffSummary, fileDiffVerb, diffGutterNo, toDiffRows, } from './tool-display.js';
5
- export { VIEW_PRIMITIVES, VIEW_COMPONENTS, DEFAULT_VIEW_TAGS, isSafeViewUrl } from './view-renderer.js';
5
+ export { VIEW_PRIMITIVES, VIEW_COMPONENTS, DEFAULT_VIEW_TAGS, isSafeViewUrl, countNodes } from './view-renderer.js';
6
6
  export { spawnCliTunnel, isCliTunnelAvailable } from './tunnel.js';
7
7
  export { isRetryableError, toFriendlyError, zodToJsonSchema, estimateTextTokens } from './provider-utils.js';
8
- export { writeFileAtomic, moxxyHome, moxxyPath } from './fs-utils.js';
8
+ export { writeFileAtomic, writeFileAtomicSync, moxxyHome, moxxyPath, } from './fs-utils.js';
9
9
  export { createMutex } from './mutex.js';
10
+ export { assertNever } from './assert.js';
11
+ export { compareSemver, parseSemverCore } from './semver.js';
10
12
  export { readRequestBody, bearerTokenMatches } from './http-utils.js';
11
13
  export { resolveChannelToken, rotateChannelToken, bearerGuard, encodeWsBearerProtocol, tokenFromWsProtocolHeader, MOXXY_WS_SUBPROTOCOL, MOXXY_WS_BEARER_PROTOCOL_PREFIX, } from './channel-auth.js';
12
14
  export { autoAllowResolver, denyByDefaultResolver, createCallbackResolver, createAllowListResolver, createDeferredPermissionResolver, evaluateToolRule, } from './resolvers.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAyGjG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA2BhD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAWpC,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,GACX,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAQxG,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAmB,MAAM,qBAAqB,CAAC;AAC9H,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAA+B,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,WAAW,EAAc,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,sBAAsB,EACtB,yBAAyB,EACzB,oBAAoB,EACpB,+BAA+B,GAEhC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,gBAAgB,GAKjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,GAOX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,0BAA0B,GAE3B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GAEvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,GAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,sBAAsB,EACtB,gCAAgC,EAChC,sBAAsB,EACtB,cAAc,EACd,gBAAgB,GAGjB,MAAM,uBAAuB,CAAC;AAmF/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA4C7C,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,WAAW,EACX,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,GAIlB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Minimal numeric `major.minor.patch` comparison. Any prerelease/build suffix
3
+ * (`-rc.1`, `+build2`) is ignored — moxxy release tags are bare `x.y.z`, so this
4
+ * is the precedence the update/check and release paths actually need, without
5
+ * pulling in a full semver dependency.
6
+ *
7
+ * Returns a negative number if `a < b`, positive if `a > b`, `0` if the numeric
8
+ * cores are equal. **When ordering a list where two entries can share a core**
9
+ * (e.g. build-metadata variants), add an explicit, deterministic tie-break at
10
+ * the call site — `Array.prototype.sort` is not guaranteed stable across all
11
+ * inputs, so a `0` here would leave their relative order unspecified.
12
+ */
13
+ export declare function compareSemver(a: string, b: string): number;
14
+ /** Parse the leading `major.minor.patch` of a version/tag into a 3-tuple. */
15
+ export declare function parseSemverCore(s: string): [number, number, number];
16
+ //# sourceMappingURL=semver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.d.ts","sourceRoot":"","sources":["../src/semver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAGnE"}
package/dist/semver.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Minimal numeric `major.minor.patch` comparison. Any prerelease/build suffix
3
+ * (`-rc.1`, `+build2`) is ignored — moxxy release tags are bare `x.y.z`, so this
4
+ * is the precedence the update/check and release paths actually need, without
5
+ * pulling in a full semver dependency.
6
+ *
7
+ * Returns a negative number if `a < b`, positive if `a > b`, `0` if the numeric
8
+ * cores are equal. **When ordering a list where two entries can share a core**
9
+ * (e.g. build-metadata variants), add an explicit, deterministic tie-break at
10
+ * the call site — `Array.prototype.sort` is not guaranteed stable across all
11
+ * inputs, so a `0` here would leave their relative order unspecified.
12
+ */
13
+ export function compareSemver(a, b) {
14
+ const pa = parseSemverCore(a);
15
+ const pb = parseSemverCore(b);
16
+ for (let i = 0; i < 3; i += 1) {
17
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
18
+ if (d !== 0)
19
+ return d < 0 ? -1 : 1;
20
+ }
21
+ return 0;
22
+ }
23
+ /** Parse the leading `major.minor.patch` of a version/tag into a 3-tuple. */
24
+ export function parseSemverCore(s) {
25
+ const parts = (s.split('-')[0] ?? '').split('.').map((n) => Number.parseInt(n, 10) || 0);
26
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
27
+ }
28
+ //# sourceMappingURL=semver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.js","sourceRoot":"","sources":["../src/semver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,CAAS,EAAE,CAAS;IAChD,MAAM,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,CAAS;IACvC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACzF,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,CAAC"}
@@ -109,4 +109,10 @@ export declare const VIEW_PRIMITIVES: ReadonlyArray<ViewTagSpec>;
109
109
  export declare const VIEW_COMPONENTS: ReadonlyArray<ViewTagSpec>;
110
110
  /** The default renderer's full allow-list (primitives + components). */
111
111
  export declare const DEFAULT_VIEW_TAGS: ReadonlyArray<ViewTagSpec>;
112
+ /**
113
+ * Count element + text nodes in a view tree (the `nodeCount` a `present_view`
114
+ * tool reports). Single source of truth: core's parser and the plugin-view tool
115
+ * both import this rather than re-implementing the recursion.
116
+ */
117
+ export declare function countNodes(node: ViewNode): number;
112
118
  //# sourceMappingURL=view-renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"view-renderer.d.ts","sourceRoot":"","sources":["../src/view-renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view-renderer.d.ts","sourceRoot":"","sources":["../src/view-renderer.ts"],"names":[],"mappings":"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"}
@@ -26,7 +26,14 @@
26
26
  * parties, so a `javascript:` link is click-XSS on a shared surface.
27
27
  */
28
28
  export function isSafeViewUrl(url, attr) {
29
- const u = url.trim().toLowerCase();
29
+ // Strip ALL ASCII whitespace + C0 control chars (U+0000–U+0020) anywhere in
30
+ // the URL before the scheme check — the HTML URL parser removes tab/newline/CR
31
+ // before resolving the scheme, so `java\tscript:` would otherwise pass this
32
+ // gate and then execute as `javascript:` on click (audit u72-1). The frontend
33
+ // copy in @moxxy/plugin-channel-web/src/frontend/url-safety.ts is a verbatim
34
+ // lockstep duplicate (the browser bundle can't import this root) — keep both
35
+ // in sync.
36
+ const u = url.replace(/[\u0000-\u0020]/g, '').toLowerCase();
30
37
  if (u.startsWith('javascript:') || u.startsWith('vbscript:'))
31
38
  return false;
32
39
  if (u.startsWith('data:'))
@@ -93,4 +100,14 @@ export const VIEW_COMPONENTS = [
93
100
  ];
94
101
  /** The default renderer's full allow-list (primitives + components). */
95
102
  export const DEFAULT_VIEW_TAGS = [...VIEW_PRIMITIVES, ...VIEW_COMPONENTS];
103
+ /**
104
+ * Count element + text nodes in a view tree (the `nodeCount` a `present_view`
105
+ * tool reports). Single source of truth: core's parser and the plugin-view tool
106
+ * both import this rather than re-implementing the recursion.
107
+ */
108
+ export function countNodes(node) {
109
+ if (node.kind === 'text')
110
+ return 1;
111
+ return 1 + node.children.reduce((sum, child) => sum + countNodes(child), 0);
112
+ }
96
113
  //# sourceMappingURL=view-renderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"view-renderer.js","sourceRoot":"","sources":["../src/view-renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view-renderer.js","sourceRoot":"","sources":["../src/view-renderer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moxxy/sdk",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Typed public surface for the moxxy framework: event types, define* factories, lifecycle hook signatures.",
5
5
  "keywords": [
6
6
  "moxxy",
@@ -65,8 +65,8 @@
65
65
  "typescript": "^5.7.3",
66
66
  "vitest": "^2.1.8",
67
67
  "zod": "^3.24.0",
68
- "@moxxy/vitest-preset": "0.0.0",
69
- "@moxxy/tsconfig": "0.0.0"
68
+ "@moxxy/tsconfig": "0.0.0",
69
+ "@moxxy/vitest-preset": "0.0.0"
70
70
  },
71
71
  "scripts": {
72
72
  "build": "tsc -p tsconfig.json",
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { assertNever } from './assert.js';
3
+
4
+ describe('assertNever', () => {
5
+ it('throws with the offending value embedded', () => {
6
+ // Cast through unknown: simulate an untyped caller defeating the never narrowing.
7
+ expect(() => assertNever('surprise' as unknown as never)).toThrow(/surprise/);
8
+ });
9
+
10
+ it('uses a custom message when provided', () => {
11
+ expect(() => assertNever(3 as unknown as never, 'bad kind')).toThrow('bad kind');
12
+ });
13
+
14
+ it('survives a value that cannot be JSON-stringified', () => {
15
+ const circular: Record<string, unknown> = {};
16
+ circular.self = circular;
17
+ expect(() => assertNever(circular as unknown as never)).toThrow(/assertNever/);
18
+ });
19
+
20
+ it('narrows exhaustively at compile time', () => {
21
+ type Shape = { kind: 'a' } | { kind: 'b' };
22
+ const area = (s: Shape): string => {
23
+ switch (s.kind) {
24
+ case 'a':
25
+ return 'a';
26
+ case 'b':
27
+ return 'b';
28
+ default:
29
+ return assertNever(s);
30
+ }
31
+ };
32
+ expect(area({ kind: 'a' })).toBe('a');
33
+ expect(area({ kind: 'b' })).toBe('b');
34
+ });
35
+ });
package/src/assert.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Exhaustiveness guard for discriminated unions. Put it in the `default:` branch
3
+ * (or any spot the type system has narrowed to `never`): if a new union member
4
+ * is added without a matching case, the call becomes a **compile error** instead
5
+ * of a silent runtime no-op.
6
+ *
7
+ * ```ts
8
+ * switch (action.kind) {
9
+ * case 'a': return handleA(action);
10
+ * case 'b': return handleB(action);
11
+ * default: return assertNever(action);
12
+ * }
13
+ * ```
14
+ *
15
+ * At runtime — should the narrowing be defeated by an untyped caller — it throws
16
+ * with the offending value, surfacing the bug rather than swallowing it.
17
+ */
18
+ export function assertNever(value: never, message?: string): never {
19
+ throw new Error(message ?? `assertNever: unexpected value ${stringify(value)}`);
20
+ }
21
+
22
+ function stringify(value: unknown): string {
23
+ try {
24
+ return JSON.stringify(value) ?? String(value);
25
+ } catch {
26
+ return String(value);
27
+ }
28
+ }
@@ -2,7 +2,7 @@ import { mkdtemp, readFile, readdir, stat } from 'node:fs/promises';
2
2
  import { tmpdir } from 'node:os';
3
3
  import { join } from 'node:path';
4
4
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
- import { moxxyHome, moxxyPath, writeFileAtomic } from './fs-utils.js';
5
+ import { moxxyHome, moxxyPath, writeFileAtomic, writeFileAtomicSync } from './fs-utils.js';
6
6
 
7
7
  describe('writeFileAtomic', () => {
8
8
  let dir: string;
@@ -41,6 +41,52 @@ describe('writeFileAtomic', () => {
41
41
  });
42
42
  });
43
43
 
44
+ describe('writeFileAtomicSync', () => {
45
+ let dir: string;
46
+ beforeEach(async () => {
47
+ dir = await mkdtemp(join(tmpdir(), 'moxxy-fss-'));
48
+ });
49
+
50
+ it('writes content and creates missing parent dirs', async () => {
51
+ const target = join(dir, 'nested', 'deep', 'file.json');
52
+ writeFileAtomicSync(target, '{"a":1}');
53
+ expect(await readFile(target, 'utf8')).toBe('{"a":1}');
54
+ });
55
+
56
+ it('overwrites an existing file and leaves no temp file behind', async () => {
57
+ const target = join(dir, 'file.txt');
58
+ writeFileAtomicSync(target, 'first');
59
+ writeFileAtomicSync(target, 'second');
60
+ expect(await readFile(target, 'utf8')).toBe('second');
61
+ const leftovers = (await readdir(dir)).filter((n) => n.includes('.tmp'));
62
+ expect(leftovers).toEqual([]);
63
+ });
64
+
65
+ it('enforces the requested mode past umask', async () => {
66
+ const target = join(dir, 'secret.json');
67
+ writeFileAtomicSync(target, 'shh', { mode: 0o600 });
68
+ const mode = (await stat(target)).mode & 0o777;
69
+ expect(mode).toBe(0o600);
70
+ });
71
+
72
+ it('writes binary data unchanged', async () => {
73
+ const target = join(dir, 'bytes.bin');
74
+ writeFileAtomicSync(target, new Uint8Array([0, 1, 2, 255]));
75
+ expect(Array.from(await readFile(target))).toEqual([0, 1, 2, 255]);
76
+ });
77
+
78
+ it('cleans up the temp file and throws when rename fails', async () => {
79
+ // A directory in place of the final file makes renameSync fail; the temp
80
+ // file must be removed and the error surfaced rather than swallowed.
81
+ const { mkdir } = await import('node:fs/promises');
82
+ const target = join(dir, 'as-dir');
83
+ await mkdir(target);
84
+ expect(() => writeFileAtomicSync(target, 'nope')).toThrow();
85
+ const leftovers = (await readdir(dir)).filter((n) => n.includes('.tmp'));
86
+ expect(leftovers).toEqual([]);
87
+ });
88
+ });
89
+
44
90
  describe('moxxyHome / moxxyPath', () => {
45
91
  const original = process.env.MOXXY_HOME;
46
92
  afterEach(() => {
package/src/fs-utils.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
+ import { chmodSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
2
3
  import { chmod, mkdir, rename, rm, writeFile } from 'node:fs/promises';
3
4
  import { homedir } from 'node:os';
4
5
  import { dirname, join } from 'node:path';
@@ -40,6 +41,36 @@ export async function writeFileAtomic(
40
41
  }
41
42
  }
42
43
 
44
+ /**
45
+ * Synchronous twin of {@link writeFileAtomic}, for the few call sites that
46
+ * cannot be async — boot/bootstrap and self-update gates that run before the
47
+ * event loop is the right tool. Same crash-atomic guarantee: write a unique
48
+ * sibling temp file, then `rename` it over the target. Hand-rolled
49
+ * `mkdirSync + writeFileSync(tmp) + renameSync` copies should call this instead.
50
+ */
51
+ export function writeFileAtomicSync(
52
+ target: string,
53
+ data: string | Uint8Array,
54
+ opts: WriteFileAtomicOptions = {},
55
+ ): void {
56
+ mkdirSync(dirname(target), { recursive: true });
57
+ const tmp = `${target}.${process.pid}.${randomUUID()}.tmp`;
58
+ try {
59
+ writeFileSync(tmp, data, { encoding: opts.encoding ?? 'utf8' });
60
+ // chmod explicitly: writeFileSync's mode option is masked by umask, but a
61
+ // 0o600 secret file must be exactly 0o600 regardless of the host umask.
62
+ if (opts.mode != null) chmodSync(tmp, opts.mode);
63
+ renameSync(tmp, target);
64
+ } catch (err) {
65
+ try {
66
+ rmSync(tmp, { force: true });
67
+ } catch {
68
+ /* best-effort cleanup */
69
+ }
70
+ throw err;
71
+ }
72
+ }
73
+
43
74
  /**
44
75
  * The moxxy home directory: `$MOXXY_HOME` when set, else `~/.moxxy`. Single
45
76
  * source of truth so the env override is honored uniformly — previously half
package/src/index.ts CHANGED
@@ -173,7 +173,7 @@ export type {
173
173
  ViewTagSpec,
174
174
  ViewRendererDef,
175
175
  } from './view-renderer.js';
176
- export { VIEW_PRIMITIVES, VIEW_COMPONENTS, DEFAULT_VIEW_TAGS, isSafeViewUrl } from './view-renderer.js';
176
+ export { VIEW_PRIMITIVES, VIEW_COMPONENTS, DEFAULT_VIEW_TAGS, isSafeViewUrl, countNodes } from './view-renderer.js';
177
177
  export type {
178
178
  TunnelProviderDef,
179
179
  TunnelHandle,
@@ -183,8 +183,16 @@ export type {
183
183
  } from './tunnel.js';
184
184
  export { spawnCliTunnel, isCliTunnelAvailable } from './tunnel.js';
185
185
  export { isRetryableError, toFriendlyError, zodToJsonSchema, estimateTextTokens, type StopReason } from './provider-utils.js';
186
- export { writeFileAtomic, moxxyHome, moxxyPath, type WriteFileAtomicOptions } from './fs-utils.js';
186
+ export {
187
+ writeFileAtomic,
188
+ writeFileAtomicSync,
189
+ moxxyHome,
190
+ moxxyPath,
191
+ type WriteFileAtomicOptions,
192
+ } from './fs-utils.js';
187
193
  export { createMutex, type Mutex } from './mutex.js';
194
+ export { assertNever } from './assert.js';
195
+ export { compareSemver, parseSemverCore } from './semver.js';
188
196
  export { readRequestBody, bearerTokenMatches } from './http-utils.js';
189
197
  export {
190
198
  resolveChannelToken,
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { compareSemver, parseSemverCore } from './semver.js';
3
+
4
+ describe('compareSemver', () => {
5
+ it('orders by major, then minor, then patch', () => {
6
+ expect(compareSemver('1.0.0', '2.0.0')).toBeLessThan(0);
7
+ expect(compareSemver('1.2.0', '1.1.9')).toBeGreaterThan(0);
8
+ expect(compareSemver('1.1.2', '1.1.10')).toBeLessThan(0);
9
+ expect(compareSemver('3.4.5', '3.4.5')).toBe(0);
10
+ });
11
+
12
+ it('normalizes to -1 / 0 / 1', () => {
13
+ expect(compareSemver('0.0.1', '0.0.2')).toBe(-1);
14
+ expect(compareSemver('0.0.2', '0.0.1')).toBe(1);
15
+ expect(compareSemver('0.0.1', '0.0.1')).toBe(0);
16
+ });
17
+
18
+ it('ignores prerelease/build suffixes (bare-tag precedence)', () => {
19
+ expect(compareSemver('1.0.0-rc.1', '1.0.0')).toBe(0);
20
+ expect(compareSemver('1.0.0+build2', '1.0.0')).toBe(0);
21
+ expect(compareSemver('1.0.0', '1.0.0+build9')).toBe(0);
22
+ });
23
+
24
+ it('treats missing/garbage segments as 0', () => {
25
+ expect(compareSemver('1', '1.0.0')).toBe(0);
26
+ expect(compareSemver('1.2', '1.2.0')).toBe(0);
27
+ expect(compareSemver('vX.Y.Z', '0.0.0')).toBe(0);
28
+ });
29
+
30
+ it('sorts ascending with a deterministic call-site tie-break', () => {
31
+ const tags = ['1.2.0', '1.10.0', '1.2.0+b', '1.1.0'];
32
+ const sorted = [...tags].sort((a, b) => compareSemver(a, b) || a.localeCompare(b));
33
+ expect(sorted).toEqual(['1.1.0', '1.2.0', '1.2.0+b', '1.10.0']);
34
+ });
35
+ });
36
+
37
+ describe('parseSemverCore', () => {
38
+ it('extracts the numeric core', () => {
39
+ expect(parseSemverCore('12.3.45-rc.1')).toEqual([12, 3, 45]);
40
+ expect(parseSemverCore('0.0.0')).toEqual([0, 0, 0]);
41
+ expect(parseSemverCore('7')).toEqual([7, 0, 0]);
42
+ });
43
+ });
package/src/semver.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Minimal numeric `major.minor.patch` comparison. Any prerelease/build suffix
3
+ * (`-rc.1`, `+build2`) is ignored — moxxy release tags are bare `x.y.z`, so this
4
+ * is the precedence the update/check and release paths actually need, without
5
+ * pulling in a full semver dependency.
6
+ *
7
+ * Returns a negative number if `a < b`, positive if `a > b`, `0` if the numeric
8
+ * cores are equal. **When ordering a list where two entries can share a core**
9
+ * (e.g. build-metadata variants), add an explicit, deterministic tie-break at
10
+ * the call site — `Array.prototype.sort` is not guaranteed stable across all
11
+ * inputs, so a `0` here would leave their relative order unspecified.
12
+ */
13
+ export function compareSemver(a: string, b: string): number {
14
+ const pa = parseSemverCore(a);
15
+ const pb = parseSemverCore(b);
16
+ for (let i = 0; i < 3; i += 1) {
17
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
18
+ if (d !== 0) return d < 0 ? -1 : 1;
19
+ }
20
+ return 0;
21
+ }
22
+
23
+ /** Parse the leading `major.minor.patch` of a version/tag into a 3-tuple. */
24
+ export function parseSemverCore(s: string): [number, number, number] {
25
+ const parts = (s.split('-')[0] ?? '').split('.').map((n) => Number.parseInt(n, 10) || 0);
26
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
27
+ }
@@ -3,11 +3,38 @@ import {
3
3
  VIEW_PRIMITIVES,
4
4
  VIEW_COMPONENTS,
5
5
  DEFAULT_VIEW_TAGS,
6
+ countNodes,
7
+ isSafeViewUrl,
6
8
  defineViewRenderer,
7
9
  defineTunnelProvider,
10
+ type ViewNode,
8
11
  type ViewTagSpec,
9
12
  } from './index.js';
10
13
 
14
+ describe('countNodes', () => {
15
+ const text = (value: string): ViewNode => ({ kind: 'text', value });
16
+ const el = (tag: string, children: ViewNode[] = []): ViewNode => ({
17
+ kind: 'element',
18
+ tag,
19
+ props: {},
20
+ children,
21
+ });
22
+
23
+ it('counts a single text node as 1', () => {
24
+ expect(countNodes(text('hi'))).toBe(1);
25
+ });
26
+
27
+ it('counts an element plus its descendants', () => {
28
+ const tree = el('col', [el('row', [text('a'), text('b')]), text('c')]);
29
+ // col + row + a + b + c = 5
30
+ expect(countNodes(tree)).toBe(5);
31
+ });
32
+
33
+ it('counts a leaf element as 1', () => {
34
+ expect(countNodes(el('hr'))).toBe(1);
35
+ });
36
+ });
37
+
11
38
  describe('view vocabulary integrity', () => {
12
39
  const all = DEFAULT_VIEW_TAGS;
13
40
 
@@ -88,3 +115,33 @@ describe('define factories freeze their specs', () => {
88
115
  expect(Object.isFrozen(def)).toBe(true);
89
116
  });
90
117
  });
118
+
119
+ describe('isSafeViewUrl', () => {
120
+ it('rejects javascript/vbscript/data-text schemes', () => {
121
+ expect(isSafeViewUrl('javascript:alert(1)', 'href')).toBe(false);
122
+ expect(isSafeViewUrl('vbscript:msgbox', 'href')).toBe(false);
123
+ expect(isSafeViewUrl('data:text/html,<x>', 'src')).toBe(false);
124
+ });
125
+
126
+ it('rejects schemes split by whitespace/control chars (audit u72-1)', () => {
127
+ // a browser strips tab/newline/CR before scheme resolution, so these
128
+ // collapse to javascript: on click; the gate must normalize the same way
129
+ expect(isSafeViewUrl('java\tscript:alert(1)', 'href')).toBe(false);
130
+ expect(isSafeViewUrl('java\nscript:alert(1)', 'href')).toBe(false);
131
+ expect(isSafeViewUrl('java\rscript:alert(1)', 'href')).toBe(false);
132
+ expect(isSafeViewUrl('\u0000javascript:alert(1)', 'href')).toBe(false);
133
+ expect(isSafeViewUrl(' javascript:alert(1)', 'href')).toBe(false);
134
+ });
135
+
136
+ it('allows safe schemes + relative + data-image src', () => {
137
+ expect(isSafeViewUrl('https://example.com/x', 'href')).toBe(true);
138
+ expect(isSafeViewUrl('http://example.com', 'href')).toBe(true);
139
+ expect(isSafeViewUrl('mailto:a@b.com', 'href')).toBe(true);
140
+ expect(isSafeViewUrl('tel:+1555', 'href')).toBe(true);
141
+ expect(isSafeViewUrl('/relative/path', 'href')).toBe(true);
142
+ expect(isSafeViewUrl('#frag', 'href')).toBe(true);
143
+ expect(isSafeViewUrl(' https://example.com ', 'href')).toBe(true);
144
+ expect(isSafeViewUrl('data:image/png;base64,AAAA', 'src')).toBe(true);
145
+ expect(isSafeViewUrl('data:image/png;base64,AAAA', 'href')).toBe(false);
146
+ });
147
+ });
@@ -108,7 +108,14 @@ export interface ViewRendererDef {
108
108
  * parties, so a `javascript:` link is click-XSS on a shared surface.
109
109
  */
110
110
  export function isSafeViewUrl(url: string, attr: string): boolean {
111
- const u = url.trim().toLowerCase();
111
+ // Strip ALL ASCII whitespace + C0 control chars (U+0000–U+0020) anywhere in
112
+ // the URL before the scheme check — the HTML URL parser removes tab/newline/CR
113
+ // before resolving the scheme, so `java\tscript:` would otherwise pass this
114
+ // gate and then execute as `javascript:` on click (audit u72-1). The frontend
115
+ // copy in @moxxy/plugin-channel-web/src/frontend/url-safety.ts is a verbatim
116
+ // lockstep duplicate (the browser bundle can't import this root) — keep both
117
+ // in sync.
118
+ const u = url.replace(/[\u0000-\u0020]/g, '').toLowerCase();
112
119
  if (u.startsWith('javascript:') || u.startsWith('vbscript:')) return false;
113
120
  if (u.startsWith('data:')) return attr === 'src' && u.startsWith('data:image/');
114
121
  if (/^[a-z][a-z0-9+.-]*:/.test(u)) return /^(https?:|mailto:|tel:)/.test(u);
@@ -176,3 +183,13 @@ export const VIEW_COMPONENTS: ReadonlyArray<ViewTagSpec> = [
176
183
 
177
184
  /** The default renderer's full allow-list (primitives + components). */
178
185
  export const DEFAULT_VIEW_TAGS: ReadonlyArray<ViewTagSpec> = [...VIEW_PRIMITIVES, ...VIEW_COMPONENTS];
186
+
187
+ /**
188
+ * Count element + text nodes in a view tree (the `nodeCount` a `present_view`
189
+ * tool reports). Single source of truth: core's parser and the plugin-view tool
190
+ * both import this rather than re-implementing the recursion.
191
+ */
192
+ export function countNodes(node: ViewNode): number {
193
+ if (node.kind === 'text') return 1;
194
+ return 1 + node.children.reduce((sum, child) => sum + countNodes(child), 0);
195
+ }