@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.
- package/dist/assert.d.ts +19 -0
- package/dist/assert.d.ts.map +1 -0
- package/dist/assert.js +29 -0
- package/dist/assert.js.map +1 -0
- package/dist/fs-utils.d.ts +8 -0
- package/dist/fs-utils.d.ts.map +1 -1
- package/dist/fs-utils.js +29 -0
- package/dist/fs-utils.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/semver.d.ts +16 -0
- package/dist/semver.d.ts.map +1 -0
- package/dist/semver.js +28 -0
- package/dist/semver.js.map +1 -0
- package/dist/view-renderer.d.ts +6 -0
- package/dist/view-renderer.d.ts.map +1 -1
- package/dist/view-renderer.js +18 -1
- package/dist/view-renderer.js.map +1 -1
- package/package.json +3 -3
- package/src/assert.test.ts +35 -0
- package/src/assert.ts +28 -0
- package/src/fs-utils.test.ts +47 -1
- package/src/fs-utils.ts +31 -0
- package/src/index.ts +10 -2
- package/src/semver.test.ts +43 -0
- package/src/semver.ts +27 -0
- package/src/view-renderer.test.ts +57 -0
- package/src/view-renderer.ts +18 -1
package/dist/assert.d.ts
ADDED
|
@@ -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"}
|
package/dist/fs-utils.d.ts
CHANGED
|
@@ -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
|
package/dist/fs-utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-utils.d.ts","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":"
|
|
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
|
package/dist/fs-utils.js.map
CHANGED
|
@@ -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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/semver.d.ts
ADDED
|
@@ -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"}
|
package/dist/view-renderer.d.ts
CHANGED
|
@@ -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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"}
|
package/dist/view-renderer.js
CHANGED
|
@@ -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
|
-
|
|
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":"AAAA;;;;;;;;;;;;GAYG;AAmFH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY;IACrD,MAAM,CAAC,GAAG,GAAG,CAAC,
|
|
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.
|
|
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/
|
|
69
|
-
"@moxxy/
|
|
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
|
+
}
|
package/src/fs-utils.test.ts
CHANGED
|
@@ -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 {
|
|
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
|
+
});
|
package/src/view-renderer.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
+
}
|