ugly-app 0.1.696 → 0.1.698

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.
@@ -1,2 +1,2 @@
1
- export declare const CLI_VERSION = "0.1.696";
1
+ export declare const CLI_VERSION = "0.1.698";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.696";
2
+ export const CLI_VERSION = "0.1.698";
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defineTask.d.ts","sourceRoot":"","sources":["../../src/native/defineTask.ts"],"names":[],"mappings":"AAeA,iGAAiG;AACjG,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;CACxE;AAED,uFAAuF;AACvF,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,4EAA4E;IAC5E,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1C,4EAA4E;IAC5E,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CACtC;AAwBD,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAEpD;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,CAezD"}
1
+ {"version":3,"file":"defineTask.d.ts","sourceRoot":"","sources":["../../src/native/defineTask.ts"],"names":[],"mappings":"AAiBA,iGAAiG;AACjG,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;CACxE;AAED,uFAAuF;AACvF,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,4EAA4E;IAC5E,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1C,4EAA4E;IAC5E,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CACtC;AA4BD,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAEpD;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,CAezD"}
@@ -1 +1 @@
1
- {"version":3,"file":"defineTask.js","sourceRoot":"","sources":["../../src/native/defineTask.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,4FAA4F;AAC5F,0FAA0F;AAC1F,0FAA0F;AAC1F,EAAE;AACF,+DAA+D;AAC/D,qDAAqD;AACrD,iBAAiB;AACjB,gBAAgB;AAChB,6FAA6F;AAC7F,+DAA+D;AAC/D,SAAS;AACT,QAAQ;AACR,qCAAqC;AA+BrC,SAAS,WAAW;IAClB,MAAM,CAAC,GAAG,UAA6C,CAAC;IACxD,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,qEAAqE;YACnE,wEAAwE,CAC3E,CAAC;IACJ,CAAC;IACD,OAAO,CAAgB,CAAC;AAC1B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,UAAU,CAAC,GAAmB;IAC5C,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,GAAG,WAAW,EAAE,CAAC,QAAQ,CAAC;IACjC,OAAO;QACL,IAAI,EAAE;YACJ,OAAO,CAAC,CAAC,EAAE,CAAC;QACd,CAAC;QACD,IAAI,IAAI;YACN,OAAO,CAAC,CAAC,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,MAAM;YACR,OAAO,CAAC,CAAC,MAAW,CAAC;QACvB,CAAC;QACD,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC;QAC1C,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC;KACnD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"defineTask.js","sourceRoot":"","sources":["../../src/native/defineTask.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,4FAA4F;AAC5F,0FAA0F;AAC1F,0FAA0F;AAC1F,EAAE;AACF,+DAA+D;AAC/D,qDAAqD;AACrD,iBAAiB;AACjB,gBAAgB;AAChB,6FAA6F;AAC7F,+DAA+D;AAC/D,SAAS;AACT,QAAQ;AACR,qCAAqC;AAqCrC,SAAS,WAAW;IAClB,MAAM,CAAC,GAAG,UAA6C,CAAC;IACxD,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,qEAAqE;YACnE,wEAAwE,CAC3E,CAAC;IACJ,CAAC;IACD,OAAO,CAAgB,CAAC;AAC1B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,UAAU,CAAC,GAAmB;IAC5C,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,GAAG,WAAW,EAAE,CAAC,QAAQ,CAAC;IACjC,OAAO;QACL,IAAI,EAAE;YACJ,OAAO,CAAC,CAAC,EAAE,CAAC;QACd,CAAC;QACD,IAAI,IAAI;YACN,OAAO,CAAC,CAAC,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,MAAM;YACR,OAAO,CAAC,CAAC,MAAW,CAAC;QACvB,CAAC;QACD,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC;QAC1C,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC;KACnD,CAAC;AACJ,CAAC"}
@@ -1,4 +1,4 @@
1
- export type { NativeContract, Channel, NativeEvent, PayloadOf, ResultOf, DataOf, Namespace, WorkoutLAState, CardioLAState, HostDirent, HostStat, UpdateStatus, GrantState, SpawnOpts, SandboxMode, SandboxStatus, SandboxResult, SafeAreaInsets, ExtractFormat, ExtractedPage, PageLink, BrowseSession, BrowseOpenOptions, McpTransport, McpServerConfig, McpAuthState, McpServerStatus, McpServerInfo, McpToolInfo, McpCallContentPart, McpCallResult, McpCatalogEntry, TaskInfo, } from './contract.js';
1
+ export type { NativeContract, Channel, NativeEvent, PayloadOf, ResultOf, DataOf, Namespace, WorkoutLAState, CardioLAState, HostDirent, HostStat, UpdateStatus, GrantState, SpawnOpts, SandboxMode, SandboxStatus, SandboxResult, SafeAreaInsets, ExtractFormat, ExtractedPage, PageLink, BrowseSession, BrowseOpenOptions, McpTransport, McpServerConfig, McpAuthState, McpServerStatus, McpServerInfo, McpToolInfo, McpCallContentPart, McpCallResult, McpCatalogEntry, TaskInfo, WebAuthnUser, WebAuthnCredParam, WebAuthnCreatePayload, WebAuthnCreateResult, WebAuthnGetPayload, WebAuthnGetResult, WebAuthnListedCredential, } from './contract.js';
2
2
  export { namespaceOf } from './contract.js';
3
3
  export type { Platform, Fallback } from './contract-meta.js';
4
4
  export { CHANNEL_FALLBACK, NAMESPACES, fallbackFor } from './contract-meta.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,OAAO,EACP,WAAW,EACX,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,cAAc,EACd,aAAa,EACb,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC/E,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtF,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACX,QAAQ,EACR,UAAU,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACvI,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACnF,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,OAAO,EACP,WAAW,EACX,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,cAAc,EACd,aAAa,EACb,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC/E,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtF,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACX,QAAQ,EACR,UAAU,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACvI,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACnF,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE/E,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,0EAA0E;AAC1E,wFAAwF;AACxF,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAUtF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,gFAAgF;AAChF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,mDAAmD;AACnD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAQnE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvI,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"AA0CA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE/E,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,0EAA0E;AAC1E,wFAAwF;AACxF,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAUtF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,gFAAgF;AAChF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,mDAAmD;AACnD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAQnE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvI,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/native/node.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAYhD,wBAAgB,oBAAoB,IAAI,UAAU,CAwFjD"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/native/node.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,eAAe,CAAC;AAmChE,wBAAgB,oBAAoB,IAAI,UAAU,CAwGjD"}
@@ -1,13 +1,19 @@
1
- // Node-backed UglyNative for background-task children. A task bundle runs in a plain Node
2
- // child process (full Node API, OS-confined by the host), so inside it `native.fs.*` /
3
- // `native.process.*` resolve to node:fs / child_process here — no host round-trip and no
4
- // permission gate (the process boundary IS the boundary). A task bundle installs it before
5
- // importing the framework facade: globalThis.UglyNative = createNodeUglyNative().
6
- // Device caps + other desktop namespaces (net/serve/workers/browse/mcp/...) aren't provided
7
- // and reject with NativeUnavailableError.
8
- import { promises as fsp, realpathSync } from 'node:fs';
9
- import { spawn } from 'node:child_process';
10
1
  import { NativeUnavailableError } from './protocol.js';
2
+ let nodeModsPromise = null;
3
+ function loadNodeMods() {
4
+ if (!nodeModsPromise) {
5
+ nodeModsPromise = (async () => {
6
+ const fs = await import('node:fs');
7
+ const cp = await import('node:child_process');
8
+ return { fsp: fs.promises, realpathSync: fs.realpathSync, spawn: cp.spawn };
9
+ })();
10
+ }
11
+ return nodeModsPromise;
12
+ }
13
+ /** The host bridge the task runner injects on `globalThis.uglyTask.host`, if any. */
14
+ function hostBridge() {
15
+ return globalThis.uglyTask?.host;
16
+ }
11
17
  // node = full local access, so every gated namespace reports granted (the facade's
12
18
  // permissions.ensure() reads this before fs/process calls).
13
19
  const ALL_GRANTED = {
@@ -30,7 +36,7 @@ export function createNodeUglyNative() {
30
36
  };
31
37
  const procs = new Map();
32
38
  let seq = 0;
33
- function spawnProc(cmd, args, opts) {
39
+ function spawnProc(spawn, cmd, args, opts) {
34
40
  const id = `n${seq++}`;
35
41
  const env = opts?.replaceEnv ? (opts.env ?? {}) : { ...process.env, ...(opts?.env ?? {}) };
36
42
  const child = spawn(cmd, args, { cwd: opts?.cwd, env, detached: opts?.detached ?? false });
@@ -45,12 +51,17 @@ export function createNodeUglyNative() {
45
51
  const p = (payload ?? {});
46
52
  const str = (k) => String(p[k] ?? '');
47
53
  switch (channel) {
48
- // permissions — node grants everything (process isolation is the boundary)
54
+ // permissions — node grants everything (process isolation is the boundary). Handled
55
+ // before loading node builtins so the (frequent) permission check stays cheap.
49
56
  case 'permissions.query':
50
57
  case 'permissions.request':
51
58
  return ALL_GRANTED;
52
59
  case 'permissions.revoke':
53
60
  return undefined;
61
+ }
62
+ // Anything past here that we service locally needs node:fs / node:child_process.
63
+ const { fsp, realpathSync, spawn } = await loadNodeMods();
64
+ switch (channel) {
54
65
  // fs (text)
55
66
  case 'fs.readFile':
56
67
  return { content: await fsp.readFile(str('path'), 'utf8') };
@@ -94,7 +105,7 @@ export function createNodeUglyNative() {
94
105
  return undefined;
95
106
  // process (id-stream; stdout/stderr/exit/error arrive as process.<kind>:<id> events)
96
107
  case 'process.spawn':
97
- return spawnProc(str('cmd'), p.args ?? [], p.opts);
108
+ return spawnProc(spawn, str('cmd'), p.args ?? [], p.opts);
98
109
  case 'process.write':
99
110
  procs.get(str('id'))?.stdin?.write(String(p.data ?? ''));
100
111
  return undefined;
@@ -107,8 +118,14 @@ export function createNodeUglyNative() {
107
118
  }
108
119
  catch { /* dead */ }
109
120
  return undefined;
110
- default:
121
+ default: {
122
+ // Not serviceable in the Node child — proxy to the host if it gave us a bridge,
123
+ // else surface the standalone "needs a native shell" error.
124
+ const host = hostBridge();
125
+ if (host)
126
+ return host.invoke(channel, payload);
111
127
  throw new NativeUnavailableError(channel);
128
+ }
112
129
  }
113
130
  }
114
131
  return {
@@ -116,6 +133,13 @@ export function createNodeUglyNative() {
116
133
  invoke: ((channel, payload) => invoke(channel, payload)),
117
134
  subscribe: ((event, cb) => {
118
135
  const key = event;
136
+ // `process.*` streams are emitted locally by spawnProc; everything else (browse/mcp/…
137
+ // events) originates host-side, so forward the subscription over the bridge when present.
138
+ if (!key.startsWith('process.')) {
139
+ const host = hostBridge();
140
+ if (host)
141
+ return host.subscribe(key, cb);
142
+ }
119
143
  let s = listeners.get(key);
120
144
  if (!s) {
121
145
  s = new Set();
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/native/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/native/node.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,19 @@ export interface UglyNative {
12
12
  invoke<C extends Channel>(channel: C, payload: PayloadOf<C>): Promise<ResultOf<C>>;
13
13
  subscribe<E extends NativeEvent>(event: E, cb: (data: DataOf<E>) => void): () => void;
14
14
  }
15
+ /**
16
+ * A task child's bridge to the host's real UglyNative. The host task runner injects this on
17
+ * `globalThis.uglyTask.host` so a Node-child task can proxy any channel it can't service
18
+ * locally — browse/capture/clipboard/mcp/terminal/net/… — back to the parent Ugly Studio
19
+ * process, which executes it against the desktop native bridge (`routeUglyNative`). `fs.*` /
20
+ * `process.*` stay local in the child (no round-trip); everything else forwards here.
21
+ * Untyped (string channels/events) because it spans the whole contract and crosses the IPC
22
+ * boundary; `createNodeUglyNative` adapts it to the typed `UglyNative` surface.
23
+ */
24
+ export interface TaskHostBridge {
25
+ invoke(channel: string, payload: unknown): Promise<unknown>;
26
+ subscribe(event: string, cb: (data: unknown) => void): () => void;
27
+ }
15
28
  export interface AndroidTransport {
16
29
  invoke(requestId: string, channel: string, payloadJson: string): void;
17
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/native/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAElG,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC;AAEnE,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;gBAClB,SAAS,EAAE,SAAS;CAKjC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,MAAM,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,SAAS,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACvF;AAQD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACvE;AACD,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,MAAM,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE;YAAE,UAAU,CAAC,EAAE,eAAe,CAAA;SAAE,CAAA;KAAE,CAAC;IAChE,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACpF"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/native/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAElG,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC;AAEnE,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;gBAClB,SAAS,EAAE,SAAS;CAKjC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,MAAM,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,SAAS,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACvF;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACnE;AAQD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACvE;AACD,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,MAAM,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE;YAAE,UAAU,CAAC,EAAE,eAAe,CAAA;SAAE,CAAA;KAAE,CAAC;IAChE,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACpF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugly-app",
3
- "version": "0.1.696",
3
+ "version": "0.1.698",
4
4
  "type": "module",
5
5
  "comment:files": "Allowlist what ships to npm. dist = runtime; src = sourcemap targets (dist/*.js.map reference ../../src/); templates = CLI scaffold. Everything else at repo root (.pgdata local Postgres, coverage, assets/icons sources, test/, test-results/) is excluded by omission. The !negations strip the scaffold's installed deps + cruft (templates/node_modules is 200MB+ and must never ship). package.json/README/LICENSE ship automatically.",
6
6
  "files": [
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.696";
2
+ export const CLI_VERSION = "0.1.698";
@@ -13,6 +13,8 @@
13
13
  // });
14
14
  // t.setSnapshot({ turn: 'idle' });
15
15
 
16
+ import type { TaskHostBridge } from './protocol.js';
17
+
16
18
  /** A task's request/response methods, callable via the task facade's `call(method, payload)`. */
17
19
  export interface TaskDefinition {
18
20
  onCall: Record<string, (payload: never) => unknown | Promise<unknown>>;
@@ -39,6 +41,10 @@ interface TaskGlobals {
39
41
  params: unknown;
40
42
  emit(event: string, data?: unknown): void;
41
43
  setSnapshot(snapshot: unknown): void;
44
+ // Injected by the host task runner so `createNodeUglyNative` can proxy non-local
45
+ // channels (browse/capture/clipboard/mcp/…) back to the parent process. Absent when
46
+ // a bundle runs outside a host that supports it (then those channels reject).
47
+ host?: TaskHostBridge;
42
48
  };
43
49
  }
44
50
 
@@ -32,6 +32,13 @@ export type {
32
32
  McpCallResult,
33
33
  McpCatalogEntry,
34
34
  TaskInfo,
35
+ WebAuthnUser,
36
+ WebAuthnCredParam,
37
+ WebAuthnCreatePayload,
38
+ WebAuthnCreateResult,
39
+ WebAuthnGetPayload,
40
+ WebAuthnGetResult,
41
+ WebAuthnListedCredential,
35
42
  } from './contract.js';
36
43
  export { namespaceOf } from './contract.js';
37
44
  export type { Platform, Fallback } from './contract-meta.js';
@@ -1,4 +1,4 @@
1
- import { describe, it, expect, afterAll } from 'vitest';
1
+ import { describe, it, expect, afterAll, beforeEach, afterEach } from 'vitest';
2
2
  import { promises as fsp } from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
@@ -58,3 +58,58 @@ describe('createNodeUglyNative', () => {
58
58
  if (dir) await fsp.rm(dir, { recursive: true, force: true });
59
59
  });
60
60
  });
61
+
62
+ describe('createNodeUglyNative with a host bridge', () => {
63
+ const g = globalThis as unknown as { uglyTask?: unknown };
64
+ const invokeCalls: { channel: string; payload: unknown }[] = [];
65
+ const subCalls: string[] = [];
66
+ const subCbs = new Map<string, (d: unknown) => void>();
67
+
68
+ beforeEach(() => {
69
+ invokeCalls.length = 0; subCalls.length = 0; subCbs.clear();
70
+ g.uglyTask = {
71
+ host: {
72
+ invoke: (channel: string, payload: unknown) => {
73
+ invokeCalls.push({ channel, payload });
74
+ return Promise.resolve({ proxied: channel });
75
+ },
76
+ subscribe: (event: string, cb: (d: unknown) => void) => {
77
+ subCalls.push(event); subCbs.set(event, cb);
78
+ return () => subCbs.delete(event);
79
+ },
80
+ },
81
+ };
82
+ });
83
+ afterEach(() => { delete g.uglyTask; });
84
+
85
+ it('forwards non-local channels to the host bridge instead of throwing', async () => {
86
+ const hn = createNodeUglyNative();
87
+ const r = await hn.invoke('browse.read' as never, { url: 'x' } as never);
88
+ expect(r).toEqual({ proxied: 'browse.read' });
89
+ expect(invokeCalls).toEqual([{ channel: 'browse.read', payload: { url: 'x' } }]);
90
+ });
91
+
92
+ it('still services fs/process/permissions locally (no forward)', async () => {
93
+ const hn = createNodeUglyNative();
94
+ const r = (await hn.invoke('permissions.query', undefined)) as { granted: Record<string, string> };
95
+ expect(r.granted.fs).toBe('full');
96
+ expect(invokeCalls).toHaveLength(0);
97
+ });
98
+
99
+ it('forwards non-process event subscriptions to the host bridge', () => {
100
+ const hn = createNodeUglyNative();
101
+ const seen: unknown[] = [];
102
+ const off = hn.subscribe('mcp.event:1' as never, ((d: unknown) => seen.push(d)) as never);
103
+ expect(subCalls).toContain('mcp.event:1');
104
+ subCbs.get('mcp.event:1')?.({ hi: true });
105
+ expect(seen).toEqual([{ hi: true }]);
106
+ off();
107
+ expect(subCbs.has('mcp.event:1')).toBe(false);
108
+ });
109
+
110
+ it('keeps process.* event subscriptions local even with a bridge', () => {
111
+ const hn = createNodeUglyNative();
112
+ hn.subscribe('process.stdout:n0' as never, (() => {}) as never);
113
+ expect(subCalls).not.toContain('process.stdout:n0');
114
+ });
115
+ });
@@ -3,14 +3,46 @@
3
3
  // `native.process.*` resolve to node:fs / child_process here — no host round-trip and no
4
4
  // permission gate (the process boundary IS the boundary). A task bundle installs it before
5
5
  // importing the framework facade: globalThis.UglyNative = createNodeUglyNative().
6
- // Device caps + other desktop namespaces (net/serve/workers/browse/mcp/...) aren't provided
7
- // and reject with NativeUnavailableError.
8
- import { promises as fsp, realpathSync } from 'node:fs';
9
- import { spawn, type ChildProcess } from 'node:child_process';
6
+ //
7
+ // Other namespaces (browse/capture/clipboard/mcp/terminal/net/...) have no local Node impl.
8
+ // When the host task runner injected a bridge on `globalThis.uglyTask.host`, those channels
9
+ // (and their events) are FORWARDED to the parent Ugly Studio process, which executes them
10
+ // against the real desktop native bridge — so a task gets the full UglyNative API, not just
11
+ // fs/process. Standalone (no host bridge) they still reject with NativeUnavailableError.
12
+ //
13
+ // `node:fs` / `node:child_process` are loaded LAZILY (dynamic import inside the methods, not
14
+ // a static top-level import). This module is re-exported from the `ugly-app/native` barrel,
15
+ // which app SHELLS import for the browser-side facade — a static `node:*` import there breaks
16
+ // the client bundle (rollup can't resolve `node:child_process` for the browser). The lazy
17
+ // load keeps the module browser-IMPORT-safe; it's only ever CALLED inside a real Node task.
18
+ import type { ChildProcess } from 'node:child_process';
10
19
  import type { Channel, DataOf, HostDirent, HostStat, NativeEvent, PayloadOf, ResultOf, SpawnOpts } from './contract.js';
11
- import type { UglyNative } from './protocol.js';
20
+ import type { TaskHostBridge, UglyNative } from './protocol.js';
12
21
  import { NativeUnavailableError } from './protocol.js';
13
22
 
23
+ /** Node builtins, resolved once on first use (never at import time → browser-safe). */
24
+ interface NodeMods {
25
+ fsp: typeof import('node:fs')['promises'];
26
+ realpathSync: typeof import('node:fs')['realpathSync'];
27
+ spawn: typeof import('node:child_process')['spawn'];
28
+ }
29
+ let nodeModsPromise: Promise<NodeMods> | null = null;
30
+ function loadNodeMods(): Promise<NodeMods> {
31
+ if (!nodeModsPromise) {
32
+ nodeModsPromise = (async (): Promise<NodeMods> => {
33
+ const fs = await import('node:fs');
34
+ const cp = await import('node:child_process');
35
+ return { fsp: fs.promises, realpathSync: fs.realpathSync, spawn: cp.spawn };
36
+ })();
37
+ }
38
+ return nodeModsPromise;
39
+ }
40
+
41
+ /** The host bridge the task runner injects on `globalThis.uglyTask.host`, if any. */
42
+ function hostBridge(): TaskHostBridge | undefined {
43
+ return (globalThis as unknown as { uglyTask?: { host?: TaskHostBridge } }).uglyTask?.host;
44
+ }
45
+
14
46
  // node = full local access, so every gated namespace reports granted (the facade's
15
47
  // permissions.ensure() reads this before fs/process calls).
16
48
  const ALL_GRANTED = {
@@ -30,7 +62,7 @@ export function createNodeUglyNative(): UglyNative {
30
62
  const procs = new Map<string, ChildProcess>();
31
63
  let seq = 0;
32
64
 
33
- function spawnProc(cmd: string, args: string[], opts?: SpawnOpts): { id: string; pid: number | null } {
65
+ function spawnProc(spawn: NodeMods['spawn'], cmd: string, args: string[], opts?: SpawnOpts): { id: string; pid: number | null } {
34
66
  const id = `n${seq++}`;
35
67
  const env = opts?.replaceEnv ? (opts.env ?? {}) : { ...process.env, ...(opts?.env ?? {}) };
36
68
  const child = spawn(cmd, args, { cwd: opts?.cwd, env, detached: opts?.detached ?? false });
@@ -46,12 +78,17 @@ export function createNodeUglyNative(): UglyNative {
46
78
  const p = (payload ?? {}) as Record<string, unknown>;
47
79
  const str = (k: string): string => String(p[k] ?? '');
48
80
  switch (channel) {
49
- // permissions — node grants everything (process isolation is the boundary)
81
+ // permissions — node grants everything (process isolation is the boundary). Handled
82
+ // before loading node builtins so the (frequent) permission check stays cheap.
50
83
  case 'permissions.query':
51
84
  case 'permissions.request':
52
85
  return ALL_GRANTED;
53
86
  case 'permissions.revoke':
54
87
  return undefined;
88
+ }
89
+ // Anything past here that we service locally needs node:fs / node:child_process.
90
+ const { fsp, realpathSync, spawn } = await loadNodeMods();
91
+ switch (channel) {
55
92
  // fs (text)
56
93
  case 'fs.readFile':
57
94
  return { content: await fsp.readFile(str('path'), 'utf8') };
@@ -84,15 +121,20 @@ export function createNodeUglyNative(): UglyNative {
84
121
  await fsp.writeFile(str('path'), Buffer.from(str('data'), 'latin1')); return undefined;
85
122
  // process (id-stream; stdout/stderr/exit/error arrive as process.<kind>:<id> events)
86
123
  case 'process.spawn':
87
- return spawnProc(str('cmd'), (p.args as string[]) ?? [], p.opts as SpawnOpts | undefined);
124
+ return spawnProc(spawn, str('cmd'), (p.args as string[]) ?? [], p.opts as SpawnOpts | undefined);
88
125
  case 'process.write':
89
126
  procs.get(str('id'))?.stdin?.write(String(p.data ?? '')); return undefined;
90
127
  case 'process.closeStdin':
91
128
  procs.get(str('id'))?.stdin?.end(); return undefined;
92
129
  case 'process.kill':
93
130
  try { procs.get(str('id'))?.kill((p.signal as NodeJS.Signals | undefined)); } catch { /* dead */ } return undefined;
94
- default:
131
+ default: {
132
+ // Not serviceable in the Node child — proxy to the host if it gave us a bridge,
133
+ // else surface the standalone "needs a native shell" error.
134
+ const host = hostBridge();
135
+ if (host) return host.invoke(channel, payload);
95
136
  throw new NativeUnavailableError(channel);
137
+ }
96
138
  }
97
139
  }
98
140
 
@@ -102,6 +144,12 @@ export function createNodeUglyNative(): UglyNative {
102
144
  invoke(channel, payload) as Promise<ResultOf<C>>) as UglyNative['invoke'],
103
145
  subscribe: (<E extends NativeEvent>(event: E, cb: (data: DataOf<E>) => void) => {
104
146
  const key = event as string;
147
+ // `process.*` streams are emitted locally by spawnProc; everything else (browse/mcp/…
148
+ // events) originates host-side, so forward the subscription over the bridge when present.
149
+ if (!key.startsWith('process.')) {
150
+ const host = hostBridge();
151
+ if (host) return host.subscribe(key, cb as (d: unknown) => void);
152
+ }
105
153
  let s = listeners.get(key);
106
154
  if (!s) { s = new Set(); listeners.set(key, s); }
107
155
  s.add(cb as (d: unknown) => void);
@@ -24,6 +24,20 @@ export interface UglyNative {
24
24
  subscribe<E extends NativeEvent>(event: E, cb: (data: DataOf<E>) => void): () => void;
25
25
  }
26
26
 
27
+ /**
28
+ * A task child's bridge to the host's real UglyNative. The host task runner injects this on
29
+ * `globalThis.uglyTask.host` so a Node-child task can proxy any channel it can't service
30
+ * locally — browse/capture/clipboard/mcp/terminal/net/… — back to the parent Ugly Studio
31
+ * process, which executes it against the desktop native bridge (`routeUglyNative`). `fs.*` /
32
+ * `process.*` stay local in the child (no round-trip); everything else forwards here.
33
+ * Untyped (string channels/events) because it spans the whole contract and crosses the IPC
34
+ * boundary; `createNodeUglyNative` adapts it to the typed `UglyNative` surface.
35
+ */
36
+ export interface TaskHostBridge {
37
+ invoke(channel: string, payload: unknown): Promise<unknown>;
38
+ subscribe(event: string, cb: (data: unknown) => void): () => void;
39
+ }
40
+
27
41
  // Low-level transports install.ts normalises into one `window.UglyNative`.
28
42
  // desktop: Electron contextBridge injects `window.UglyNative` directly (no adapter).
29
43
  // iOS: window.webkit.messageHandlers.uglyInvoke (WKScriptMessageHandlerWithReply)