@gemigo/app-sdk 0.2.5

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,2 @@
1
+ import { StorageAPI } from '../types';
2
+ export declare const fallbackStorage: StorageAPI;
@@ -0,0 +1,272 @@
1
+ import { i as tryGetHost, n as createRPCProxy, t as callHost } from "./connection-DwOg1Kh5.js";
2
+ function createEventBus() {
3
+ let e = /* @__PURE__ */ new Map();
4
+ return {
5
+ on(x, S) {
6
+ return e.has(x) || e.set(x, /* @__PURE__ */ new Set()), e.get(x).add(S), () => e.get(x)?.delete(S);
7
+ },
8
+ emit(x, ...S) {
9
+ e.get(x)?.forEach((e) => e(...S));
10
+ },
11
+ off(x) {
12
+ x ? e.delete(x) : e.clear();
13
+ }
14
+ };
15
+ }
16
+ const sdkEventBus = createEventBus();
17
+ function createUnifiedAPI(S) {
18
+ let C = tryGetHost, T = {}, E = {};
19
+ if (S.rpc) {
20
+ let e = createRPCProxy(S.rpc.methods, {
21
+ mapping: S.rpc.mapping,
22
+ fallbacks: S.rpc.fallbacks
23
+ });
24
+ Object.assign(T, e);
25
+ }
26
+ if (S.events) if (Array.isArray(S.events)) for (let e of S.events) {
27
+ let x = e;
28
+ T[e] = (e) => (C?.(), sdkEventBus.on(x, e)), E[e] = (...e) => {
29
+ sdkEventBus.emit(x, ...e);
30
+ };
31
+ }
32
+ else for (let [e, x] of Object.entries(S.events)) {
33
+ if (!x) continue;
34
+ let S = x, D = typeof S == "string" ? S : S.event, O = typeof S == "object" && "childMethod" in S && S.childMethod ? S.childMethod : e;
35
+ T[e] = (e) => (C?.(), sdkEventBus.on(D, e)), E[O] = (...e) => {
36
+ sdkEventBus.emit(D, ...e);
37
+ };
38
+ }
39
+ return {
40
+ api: T,
41
+ childMethods: E
42
+ };
43
+ }
44
+ function createRPCAction(e, x) {
45
+ return async (...C) => {
46
+ try {
47
+ let w = await callHost(e, x.transform ? x.transform(...C) : C);
48
+ return x.onSuccess ? x.onSuccess(w) : w;
49
+ } catch {
50
+ return x.fallback(...C);
51
+ }
52
+ };
53
+ }
54
+ function createSDK(e) {
55
+ let x = e.statics ? { ...e.statics } : {}, S = {};
56
+ if (e.modules) for (let [C, w] of Object.entries(e.modules)) {
57
+ let { api: e, childMethods: E } = createUnifiedAPI(w);
58
+ x[C] = e, Object.assign(S, E);
59
+ }
60
+ if (e.actions) for (let [S, C] of Object.entries(e.actions)) {
61
+ let e = C;
62
+ x[S] = createRPCAction(e.method, e);
63
+ }
64
+ if (e.getters) for (let [S, C] of Object.entries(e.getters)) Object.defineProperty(x, S, {
65
+ get: C,
66
+ enumerable: !0,
67
+ configurable: !0
68
+ });
69
+ return {
70
+ sdk: x,
71
+ childMethods: S
72
+ };
73
+ }
74
+ async function bootstrapSDK(x, S = {}) {
75
+ let { initConnection: C } = await import("./connection-C-IGR2wz.js");
76
+ C(x, S);
77
+ let w = await tryGetHost();
78
+ if (w && typeof w.getProtocolInfo == "function") try {
79
+ return await w.getProtocolInfo();
80
+ } catch {
81
+ return null;
82
+ }
83
+ return null;
84
+ }
85
+ var localStoragePrefix = () => `gemigo:${typeof window > "u" ? "unknown" : window.location.origin.replace(/[:/]/g, "_")}:`;
86
+ const fallbackStorage = {
87
+ get: async (e) => {
88
+ if (typeof window > "u" || !window.localStorage) return null;
89
+ let x = window.localStorage.getItem(`${localStoragePrefix()}${e}`);
90
+ if (!x) return null;
91
+ try {
92
+ return JSON.parse(x);
93
+ } catch {
94
+ return null;
95
+ }
96
+ },
97
+ set: async (e, x) => {
98
+ typeof window > "u" || !window.localStorage || window.localStorage.setItem(`${localStoragePrefix()}${e}`, JSON.stringify(x));
99
+ },
100
+ delete: async (e) => {
101
+ typeof window > "u" || !window.localStorage || window.localStorage.removeItem(`${localStoragePrefix()}${e}`);
102
+ },
103
+ clear: async () => {
104
+ if (typeof window > "u" || !window.localStorage) return;
105
+ let e = localStoragePrefix();
106
+ for (let x = window.localStorage.length - 1; x >= 0; --x) {
107
+ let S = window.localStorage.key(x);
108
+ S && S.startsWith(e) && window.localStorage.removeItem(S);
109
+ }
110
+ }
111
+ }, fallbackNotify = async (e) => {
112
+ if (typeof window > "u" || typeof Notification > "u") return {
113
+ success: !1,
114
+ reason: "not_supported"
115
+ };
116
+ if (Notification.permission !== "granted") return {
117
+ success: !1,
118
+ reason: "permission_not_granted"
119
+ };
120
+ try {
121
+ return new Notification(e.title, {
122
+ body: e.message,
123
+ icon: e.icon
124
+ }), { success: !0 };
125
+ } catch {
126
+ return {
127
+ success: !1,
128
+ reason: "failed_to_notify"
129
+ };
130
+ }
131
+ }, fallbackNetwork = { request: async (e, x) => {
132
+ let { method: S = "GET", headers: C, body: w, responseType: T } = x ?? {}, E = await fetch(e, {
133
+ method: S,
134
+ headers: C,
135
+ body: w ? typeof w == "string" ? w : JSON.stringify(w) : void 0
136
+ }), D = {};
137
+ E.headers.forEach((e, x) => D[x] = e);
138
+ let O = T === "text" ? await E.text() : T === "arraybuffer" ? await E.arrayBuffer() : await E.json();
139
+ return {
140
+ status: E.status,
141
+ data: O,
142
+ headers: D
143
+ };
144
+ } };
145
+ var SDKError = class e extends Error {
146
+ constructor(x, S) {
147
+ super(S), this.code = x, this.name = "SDKError", Object.setPrototypeOf(this, e.prototype);
148
+ }
149
+ }, hostInfo = null, defaultCapabilities = {
150
+ storage: !0,
151
+ network: !1,
152
+ scheduler: !1,
153
+ fileWatch: !1,
154
+ fileWrite: !1,
155
+ notification: !0,
156
+ clipboard: !1,
157
+ ai: !1,
158
+ shell: !1,
159
+ extension: {
160
+ read: !1,
161
+ events: !1,
162
+ modify: !1,
163
+ capture: !1
164
+ }
165
+ };
166
+ const updateHostInfo = (e) => {
167
+ hostInfo = e;
168
+ };
169
+ var throwNotSupported = (e) => {
170
+ throw new SDKError("NOT_SUPPORTED", `${e} is not supported in this environment.`);
171
+ }, stubAsync = (e) => async () => throwNotSupported(e), stubHandler = (e) => () => throwNotSupported(e), aiAPI = {
172
+ chat: stubAsync("ai.chat"),
173
+ summarize: stubAsync("ai.summarize"),
174
+ translate: stubAsync("ai.translate")
175
+ }, clipboardAPI = {
176
+ readText: stubAsync("clipboard.readText"),
177
+ writeText: stubAsync("clipboard.writeText"),
178
+ readImage: stubAsync("clipboard.readImage"),
179
+ writeImage: stubAsync("clipboard.writeImage"),
180
+ onChange: stubHandler("clipboard.onChange")
181
+ }, dialogAPI = {
182
+ openFile: stubAsync("dialog.openFile"),
183
+ openDirectory: stubAsync("dialog.openDirectory"),
184
+ saveFile: stubAsync("dialog.saveFile"),
185
+ message: stubAsync("dialog.message")
186
+ }, fileAPI = {
187
+ readText: stubAsync("file.readText"),
188
+ readBinary: stubAsync("file.readBinary"),
189
+ write: stubAsync("file.write"),
190
+ append: stubAsync("file.append"),
191
+ exists: stubAsync("file.exists"),
192
+ stat: stubAsync("file.stat"),
193
+ copy: stubAsync("file.copy"),
194
+ move: stubAsync("file.move"),
195
+ remove: stubAsync("file.remove"),
196
+ list: stubAsync("file.list"),
197
+ mkdir: stubAsync("file.mkdir"),
198
+ persistPermission: stubAsync("file.persistPermission")
199
+ }, onNotificationAction = stubHandler("onNotificationAction"), onFileDrop = stubHandler("onFileDrop");
200
+ const { sdk, childMethods } = createSDK({
201
+ getters: {
202
+ platform: () => hostInfo?.platform ?? "web",
203
+ capabilities: () => hostInfo?.capabilities ?? defaultCapabilities
204
+ },
205
+ modules: {
206
+ storage: { rpc: {
207
+ methods: [
208
+ "get",
209
+ "set",
210
+ "delete",
211
+ "clear"
212
+ ],
213
+ mapping: {
214
+ get: "storageGet",
215
+ set: "storageSet",
216
+ delete: "storageDelete",
217
+ clear: "storageClear"
218
+ },
219
+ fallbacks: {
220
+ get: fallbackStorage.get,
221
+ set: fallbackStorage.set,
222
+ delete: fallbackStorage.delete,
223
+ clear: fallbackStorage.clear
224
+ }
225
+ } },
226
+ network: { rpc: {
227
+ methods: ["request"],
228
+ mapping: { request: "networkRequest" },
229
+ fallbacks: { request: fallbackNetwork.request }
230
+ } },
231
+ extension: {
232
+ rpc: { methods: [
233
+ "getPageInfo",
234
+ "getPageHTML",
235
+ "getPageText",
236
+ "getSelection",
237
+ "extractArticle",
238
+ "extractLinks",
239
+ "extractImages",
240
+ "queryElement",
241
+ "highlight",
242
+ "removeHighlight",
243
+ "insertWidget",
244
+ "updateWidget",
245
+ "removeWidget",
246
+ "injectCSS",
247
+ "removeCSS",
248
+ "captureVisible",
249
+ "getContextMenuEvent"
250
+ ] },
251
+ events: ["onContextMenu", "onSelectionChange"]
252
+ }
253
+ },
254
+ actions: { notify: {
255
+ method: "notify",
256
+ fallback: fallbackNotify
257
+ } },
258
+ statics: {
259
+ SDKError,
260
+ ai: aiAPI,
261
+ clipboard: clipboardAPI,
262
+ dialog: dialogAPI,
263
+ file: fileAPI,
264
+ onNotificationAction,
265
+ onFileDrop
266
+ }
267
+ });
268
+ bootstrapSDK(childMethods, { timeoutMs: 1500 }).then((e) => {
269
+ e && updateHostInfo(e);
270
+ }), sdk.SDKError = SDKError;
271
+ var src_default = sdk;
272
+ export { src_default as default };
@@ -0,0 +1 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.gemigo=t())})(this,function(){var e=Object.defineProperty,t=(e,t)=>()=>(e&&(t=e(e=0)),t),n=t=>{let n={};for(var r in t)e(n,r,{get:t[r],enumerable:!0});return n},r,i,a,o,s,c=t((()=>{(function(e){e.Call=`call`,e.Reply=`reply`,e.Syn=`syn`,e.SynAck=`synAck`,e.Ack=`ack`})(r||={}),(function(e){e.Fulfilled=`fulfilled`,e.Rejected=`rejected`})(i||={}),(function(e){e.ConnectionDestroyed=`ConnectionDestroyed`,e.ConnectionTimeout=`ConnectionTimeout`,e.NoIframeSrc=`NoIframeSrc`})(a||={}),(function(e){e.DataCloneError=`DataCloneError`})(o||={}),(function(e){e.Message=`message`})(s||={})})),l,u=t((()=>{l=(e,t)=>{let n=[],r=!1;return{destroy(i){r||(r=!0,t(`${e}: Destroying connection`),n.forEach(e=>{e(i)}))},onDestroy(e){r?e():n.push(e)}}}})),d,f=t((()=>{d=e=>(...t)=>{e&&console.log(`[Penpal]`,...t)}})),p,m,h=t((()=>{p=({name:e,message:t,stack:n})=>({name:e,message:t,stack:n}),m=e=>{let t=Error();return Object.keys(e).forEach(n=>t[n]=e[n]),t}})),g,_=t((()=>{h(),c(),g=(e,t,n)=>{let{localName:a,local:c,remote:l,originForSending:u,originForReceiving:d}=e,f=!1,m=e=>{if(e.source!==l||e.data.penpal!==r.Call)return;if(d!==`*`&&e.origin!==d){n(`${a} received message from origin ${e.origin} which did not match expected origin ${d}`);return}let{methodName:s,args:c,id:m}=e.data;n(`${a}: Received ${s}() call`);let h=e=>t=>{if(n(`${a}: Sending ${s}() reply`),f){n(`${a}: Unable to send ${s}() reply due to destroyed connection`);return}let c={penpal:r.Reply,id:m,resolution:e,returnValue:t};e===i.Rejected&&t instanceof Error&&(c.returnValue=p(t),c.returnValueIsError=!0);try{l.postMessage(c,u)}catch(e){if(e.name===o.DataCloneError){let t={penpal:r.Reply,id:m,resolution:i.Rejected,returnValue:p(e),returnValueIsError:!0};l.postMessage(t,u)}throw e}};new Promise(e=>e(t[s].apply(t,c))).then(h(i.Fulfilled),h(i.Rejected))};return c.addEventListener(s.Message,m),()=>{f=!0,c.removeEventListener(s.Message,m)}}})),v,y,ee=t((()=>{v=0,y=()=>++v})),b,x,S,C,w,T,E,D=t((()=>{b=`.`,x=e=>e?e.split(b):[],S=e=>e.join(b),C=(e,t)=>{let n=x(t||``);return n.push(e),S(n)},w=(e,t,n)=>{let r=x(t);return r.reduce((e,t,i)=>(e[t]===void 0&&(e[t]={}),i===r.length-1&&(e[t]=n),e[t]),e),e},T=(e,t)=>{let n={};return Object.keys(e).forEach(r=>{let i=e[r],a=C(r,t);typeof i==`object`&&Object.assign(n,T(i,a)),typeof i==`function`&&(n[a]=i)}),n},E=e=>{let t={};for(let n in e)w(t,n,e[n]);return t}})),O,k=t((()=>{ee(),h(),D(),c(),O=(e,t,n,o,c)=>{let{localName:l,local:u,remote:d,originForSending:f,originForReceiving:p}=t,h=!1;c(`${l}: Connecting call sender`);let g=e=>(...t)=>{c(`${l}: Sending ${e}() call`);let n;try{d.closed&&(n=!0)}catch{n=!0}if(n&&o(),h){let t=Error(`Unable to send ${e}() call due to destroyed connection`);throw t.code=a.ConnectionDestroyed,t}return new Promise((n,a)=>{let o=y(),h=t=>{if(t.source!==d||t.data.penpal!==r.Reply||t.data.id!==o)return;if(p!==`*`&&t.origin!==p){c(`${l} received message from origin ${t.origin} which did not match expected origin ${p}`);return}let f=t.data;c(`${l}: Received ${e}() reply`),u.removeEventListener(s.Message,h);let g=f.returnValue;f.returnValueIsError&&(g=m(g)),(f.resolution===i.Fulfilled?n:a)(g)};u.addEventListener(s.Message,h);let g={penpal:r.Call,id:o,methodName:e,args:t};d.postMessage(g,f)})},_=n.reduce((e,t)=>(e[t]=g(t),e),{});return Object.assign(e,E(_)),()=>{h=!0}}})),te=t((()=>{_(),k()})),ne=t((()=>{c()})),A,j=t((()=>{c(),A=(e,t)=>{let n;return e!==void 0&&(n=window.setTimeout(()=>{let n=Error(`Connection timed out after ${e}ms`);n.code=a.ConnectionTimeout,t(n)},e)),()=>{clearTimeout(n)}}})),re=t((()=>{c()})),ie=t((()=>{c(),te(),ne(),j(),re()})),M,ae=t((()=>{c(),_(),k(),M=(e,t,n,i)=>{let{destroy:a,onDestroy:o}=n;return n=>{if(!(e instanceof RegExp?e.test(n.origin):e===`*`||e===n.origin)){i(`Child: Handshake - Received SYN-ACK from origin ${n.origin} which did not match expected origin ${e}`);return}i(`Child: Handshake - Received SYN-ACK, responding with ACK`);let s=n.origin===`null`?`*`:n.origin,c={penpal:r.Ack,methodNames:Object.keys(t)};window.parent.postMessage(c,s);let l={localName:`Child`,local:window,remote:window.parent,originForSending:s,originForReceiving:n.origin};o(g(l,t,i));let u={};return o(O(u,l,n.data.methodNames,a,i)),u}}})),N,P,oe=t((()=>{u(),f(),c(),ae(),D(),j(),N=()=>{try{clearTimeout()}catch{return!1}return!0},P=(e={})=>{let{parentOrigin:t=`*`,methods:n={},timeout:i,debug:a=!1}=e,o=d(a),c=l(`Child`,o),{destroy:u,onDestroy:f}=c,p=M(t,T(n),c,o),m=()=>{o(`Child: Handshake - Sending SYN`);let e={penpal:r.Syn},n=t instanceof RegExp?`*`:t;window.parent.postMessage(e,n)};return{promise:new Promise((e,t)=>{let n=A(i,u),a=t=>{if(N()&&!(t.source!==parent||!t.data)&&t.data.penpal===r.SynAck){let r=p(t);r&&(window.removeEventListener(s.Message,a),n(),e(r))}};window.addEventListener(s.Message,a),m(),f(e=>{window.removeEventListener(s.Message,a),e&&t(e)})}),destroy(){u()}}}})),se=t((()=>{ie(),oe(),c()})),ce=n({callHost:()=>I,createRPCProxy:()=>L,getHost:()=>ue,hasConnectionFailed:()=>fe,initConnection:()=>pe,isConnected:()=>de,tryGetHost:()=>F,withFallback:()=>me});function le(){try{return window.self!==window.top}catch{return!0}}async function F(e,t){if(z)return z;if(B)return null;if(!le())return B=!0,null;if(!R){let n={},r=e??V;r&&Object.assign(n,r),R=P({methods:n,timeout:t?.timeoutMs??H}).promise.then(e=>(z=e,e)).catch(e=>(console.error(`[GemiGo Connection] Promise failed:`,e),B=!0,R=null,null))}return R}async function ue(){let e=await F();if(!e)throw Error(`Not connected to host. SDK may be running outside of a supported environment.`);return e}function de(){return z!==null}function fe(){return B}function pe(e,t){V=e,F(e,t)}async function I(e,t=[],n){let r=await F();if(r&&typeof r[e]==`function`){let i=await r[e](...t);if(i?.success!==!1)return i?.data===void 0?i?.value===void 0?i:i.value:i.data;if(n)return n(...t);throw Error(i?.error||`Host method ${String(e)} failed`)}if(n)return n(...t);throw Error(`Method ${String(e)} not supported in this environment`)}function L(e,t={}){let n={};for(let r of e){let e=t.mapping?.[r]||r,i=t.fallbacks?.[r];n[r]=(...t)=>I(e,t,i)}return n}function me(e,t){return async(...n)=>{try{return await e(...n)}catch{return t(...n)}}}var R,z,B,V,H,U=t((()=>{se(),R=null,z=null,B=!1,H=1500}));U();function W(){let e=new Map;return{on(t,n){return e.has(t)||e.set(t,new Set),e.get(t).add(n),()=>e.get(t)?.delete(n)},emit(t,...n){e.get(t)?.forEach(e=>e(...n))},off(t){t?e.delete(t):e.clear()}}}let G=W();function he(e){let t=F,n={},r={};if(e.rpc){let t=L(e.rpc.methods,{mapping:e.rpc.mapping,fallbacks:e.rpc.fallbacks});Object.assign(n,t)}if(e.events)if(Array.isArray(e.events))for(let i of e.events){let e=i;n[i]=n=>(t?.(),G.on(e,n)),r[i]=(...t)=>{G.emit(e,...t)}}else for(let[i,a]of Object.entries(e.events)){if(!a)continue;let e=a,o=typeof e==`string`?e:e.event,s=typeof e==`object`&&`childMethod`in e&&e.childMethod?e.childMethod:i;n[i]=e=>(t?.(),G.on(o,e)),r[s]=(...e)=>{G.emit(o,...e)}}return{api:n,childMethods:r}}function ge(e,t){return async(...n)=>{try{let r=await I(e,t.transform?t.transform(...n):n);return t.onSuccess?t.onSuccess(r):r}catch{return t.fallback(...n)}}}function _e(e){let t=e.statics?{...e.statics}:{},n={};if(e.modules)for(let[r,i]of Object.entries(e.modules)){let{api:e,childMethods:a}=he(i);t[r]=e,Object.assign(n,a)}if(e.actions)for(let[n,r]of Object.entries(e.actions)){let e=r;t[n]=ge(e.method,e)}if(e.getters)for(let[n,r]of Object.entries(e.getters))Object.defineProperty(t,n,{get:r,enumerable:!0,configurable:!0});return{sdk:t,childMethods:n}}async function ve(e,t={}){let{initConnection:n}=await Promise.resolve().then(()=>(U(),ce));n(e,t);let r=await F();if(r&&typeof r.getProtocolInfo==`function`)try{return await r.getProtocolInfo()}catch{return null}return null}U();var K=()=>`gemigo:${typeof window>`u`?`unknown`:window.location.origin.replace(/[:/]/g,`_`)}:`;let q={get:async e=>{if(typeof window>`u`||!window.localStorage)return null;let t=window.localStorage.getItem(`${K()}${e}`);if(!t)return null;try{return JSON.parse(t)}catch{return null}},set:async(e,t)=>{typeof window>`u`||!window.localStorage||window.localStorage.setItem(`${K()}${e}`,JSON.stringify(t))},delete:async e=>{typeof window>`u`||!window.localStorage||window.localStorage.removeItem(`${K()}${e}`)},clear:async()=>{if(typeof window>`u`||!window.localStorage)return;let e=K();for(let t=window.localStorage.length-1;t>=0;--t){let n=window.localStorage.key(t);n&&n.startsWith(e)&&window.localStorage.removeItem(n)}}},ye=async e=>{if(typeof window>`u`||typeof Notification>`u`)return{success:!1,reason:`not_supported`};if(Notification.permission!==`granted`)return{success:!1,reason:`permission_not_granted`};try{return new Notification(e.title,{body:e.message,icon:e.icon}),{success:!0}}catch{return{success:!1,reason:`failed_to_notify`}}},be={request:async(e,t)=>{let{method:n=`GET`,headers:r,body:i,responseType:a}=t??{},o=await fetch(e,{method:n,headers:r,body:i?typeof i==`string`?i:JSON.stringify(i):void 0}),s={};o.headers.forEach((e,t)=>s[t]=e);let c=a===`text`?await o.text():a===`arraybuffer`?await o.arrayBuffer():await o.json();return{status:o.status,data:c,headers:s}}};var J=class e extends Error{constructor(t,n){super(n),this.code=t,this.name=`SDKError`,Object.setPrototypeOf(this,e.prototype)}},Y=null,xe={storage:!0,network:!1,scheduler:!1,fileWatch:!1,fileWrite:!1,notification:!0,clipboard:!1,ai:!1,shell:!1,extension:{read:!1,events:!1,modify:!1,capture:!1}};let Se=e=>{Y=e};var X=e=>{throw new J(`NOT_SUPPORTED`,`${e} is not supported in this environment.`)},Z=e=>async()=>X(e),Q=e=>()=>X(e),Ce={chat:Z(`ai.chat`),summarize:Z(`ai.summarize`),translate:Z(`ai.translate`)},we={readText:Z(`clipboard.readText`),writeText:Z(`clipboard.writeText`),readImage:Z(`clipboard.readImage`),writeImage:Z(`clipboard.writeImage`),onChange:Q(`clipboard.onChange`)},Te={openFile:Z(`dialog.openFile`),openDirectory:Z(`dialog.openDirectory`),saveFile:Z(`dialog.saveFile`),message:Z(`dialog.message`)},Ee={readText:Z(`file.readText`),readBinary:Z(`file.readBinary`),write:Z(`file.write`),append:Z(`file.append`),exists:Z(`file.exists`),stat:Z(`file.stat`),copy:Z(`file.copy`),move:Z(`file.move`),remove:Z(`file.remove`),list:Z(`file.list`),mkdir:Z(`file.mkdir`),persistPermission:Z(`file.persistPermission`)},De=Q(`onNotificationAction`),Oe=Q(`onFileDrop`);let{sdk:$,childMethods:ke}=_e({getters:{platform:()=>Y?.platform??`web`,capabilities:()=>Y?.capabilities??xe},modules:{storage:{rpc:{methods:[`get`,`set`,`delete`,`clear`],mapping:{get:`storageGet`,set:`storageSet`,delete:`storageDelete`,clear:`storageClear`},fallbacks:{get:q.get,set:q.set,delete:q.delete,clear:q.clear}}},network:{rpc:{methods:[`request`],mapping:{request:`networkRequest`},fallbacks:{request:be.request}}},extension:{rpc:{methods:[`getPageInfo`,`getPageHTML`,`getPageText`,`getSelection`,`extractArticle`,`extractLinks`,`extractImages`,`queryElement`,`highlight`,`removeHighlight`,`insertWidget`,`updateWidget`,`removeWidget`,`injectCSS`,`removeCSS`,`captureVisible`,`getContextMenuEvent`]},events:[`onContextMenu`,`onSelectionChange`]}},actions:{notify:{method:`notify`,fallback:ye}},statics:{SDKError:J,ai:Ce,clipboard:we,dialog:Te,file:Ee,onNotificationAction:De,onFileDrop:Oe}});return ve(ke,{timeoutMs:1500}).then(e=>{e&&Se(e)}),$.SDKError=J,$});
@@ -0,0 +1,5 @@
1
+ import { sdk as gemigo } from './apis';
2
+ export default gemigo;
3
+ export type * from './types';
4
+ export type { SDKError, SDKErrorCode } from './types';
5
+ export type { HostMethods, ChildMethods } from './core';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * AI API types
3
+ */
4
+ /** Chat message */
5
+ export interface ChatMessage {
6
+ role: 'user' | 'assistant' | 'system';
7
+ content: string;
8
+ }
9
+ /** Chat response */
10
+ export interface ChatResponse {
11
+ role: 'assistant';
12
+ content: string;
13
+ }
14
+ /** Translation options */
15
+ export interface TranslateOptions {
16
+ /** Source language (auto-detect if not specified) */
17
+ from?: string;
18
+ /** Target language (required) */
19
+ to: string;
20
+ }
21
+ /** Translation result */
22
+ export interface TranslateResult {
23
+ text: string;
24
+ from: string;
25
+ to: string;
26
+ }
27
+ /** AI API for cloud model integration */
28
+ export interface AIAPI {
29
+ /**
30
+ * Multi-turn conversation
31
+ * @param messages - Conversation history
32
+ * @returns Assistant response
33
+ */
34
+ chat(messages: ChatMessage[]): Promise<ChatResponse>;
35
+ /**
36
+ * Summarize text content
37
+ * @param text - Text to summarize
38
+ * @returns Summary text
39
+ */
40
+ summarize(text: string): Promise<string>;
41
+ /**
42
+ * Translate text
43
+ * @param text - Text to translate
44
+ * @param options - Translation options
45
+ * @returns Translation result
46
+ */
47
+ translate(text: string, options: TranslateOptions): Promise<TranslateResult>;
48
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Clipboard API types
3
+ */
4
+ /** Clipboard content */
5
+ export interface ClipboardContent {
6
+ text?: string;
7
+ image?: Blob;
8
+ }
9
+ /** Clipboard change callback */
10
+ export type ClipboardChangeCallback = (content: ClipboardContent) => void;
11
+ /** Clipboard API */
12
+ export interface ClipboardAPI {
13
+ /**
14
+ * Read text from clipboard
15
+ * @returns Clipboard text content
16
+ */
17
+ readText(): Promise<string>;
18
+ /**
19
+ * Write text to clipboard
20
+ * @param text - Text to write
21
+ */
22
+ writeText(text: string): Promise<void>;
23
+ /**
24
+ * Read image from clipboard
25
+ * @returns Image blob or null
26
+ */
27
+ readImage(): Promise<Blob | null>;
28
+ /**
29
+ * Write image to clipboard
30
+ * @param blob - Image blob to write
31
+ */
32
+ writeImage(blob: Blob): Promise<void>;
33
+ /**
34
+ * Listen for clipboard content changes (desktop only)
35
+ * @param callback - Change callback
36
+ * @returns Unsubscribe function
37
+ */
38
+ onChange(callback: ClipboardChangeCallback): () => void;
39
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Common types used across the GemiGo SDK
3
+ */
4
+ /** Current platform type */
5
+ export type Platform = 'web' | 'desktop' | 'extension';
6
+ /** SDK Error Codes */
7
+ export type SDKErrorCode = 'NOT_SUPPORTED' | 'PERMISSION_DENIED' | 'NETWORK_NOT_ALLOWED' | 'TIMEOUT' | 'INTERNAL_ERROR' | 'NOT_CONNECTED';
8
+ /** Unified SDK Error class */
9
+ export declare class SDKError extends Error {
10
+ code: SDKErrorCode;
11
+ constructor(code: SDKErrorCode, message: string);
12
+ }
13
+ /** Environment capabilities */
14
+ export interface Capabilities {
15
+ /** Persistent key-value storage */
16
+ storage: boolean;
17
+ /** Cross-origin/network proxy capability (host mediated) */
18
+ network: boolean;
19
+ scheduler: boolean;
20
+ fileWatch: boolean;
21
+ fileWrite: boolean;
22
+ notification: boolean;
23
+ clipboard: boolean;
24
+ ai: boolean;
25
+ shell: boolean;
26
+ /** Extension-specific capability breakdown */
27
+ extension?: {
28
+ read: boolean;
29
+ events: boolean;
30
+ modify: boolean;
31
+ capture: boolean;
32
+ };
33
+ }
34
+ /** File entry information */
35
+ export interface FileEntry {
36
+ /** File name */
37
+ name: string;
38
+ /** Full path */
39
+ path: string;
40
+ /** Whether this is a file */
41
+ isFile: boolean;
42
+ /** Whether this is a directory */
43
+ isDirectory: boolean;
44
+ /** File size in bytes */
45
+ size: number;
46
+ /** Last modification timestamp */
47
+ mtime: number;
48
+ }
49
+ /** File stat information */
50
+ export interface FileStat {
51
+ size: number;
52
+ mtime: number;
53
+ ctime: number;
54
+ isFile: boolean;
55
+ isDirectory: boolean;
56
+ }
57
+ /**
58
+ * Base RPC result structure.
59
+ * All RPC methods that can fail should return this structure.
60
+ */
61
+ export interface RPCResult<T = void> {
62
+ success: boolean;
63
+ data?: T;
64
+ error?: string;
65
+ code?: string;
66
+ }
67
+ /**
68
+ * RPC result with required data (for successful operations).
69
+ */
70
+ export type RPCResultWithData<T> = RPCResult<T> & {
71
+ data: T;
72
+ };
@@ -0,0 +1,138 @@
1
+ import { NotifyOptions } from './notify';
2
+ /** Scheduler task configuration */
3
+ export interface SchedulerConfig {
4
+ /** Unique task ID */
5
+ id: string;
6
+ /** Interval (e.g. '30m', '1h', '2h', '1d') */
7
+ interval: string;
8
+ /** Start time (e.g. '08:00') */
9
+ startTime?: string;
10
+ /** End time (e.g. '22:00') */
11
+ endTime?: string;
12
+ /** Notification to show when task runs */
13
+ notification?: NotifyOptions;
14
+ }
15
+ /** Scheduler operation result */
16
+ export interface SchedulerResult {
17
+ success: boolean;
18
+ reason?: string;
19
+ }
20
+ /** Scheduler API for background tasks */
21
+ export interface SchedulerAPI {
22
+ /**
23
+ * Register a background scheduled task
24
+ * @param config - Task configuration
25
+ */
26
+ register(config: SchedulerConfig): Promise<SchedulerResult>;
27
+ /**
28
+ * Update an existing task
29
+ * @param id - Task ID
30
+ * @param config - Updated configuration
31
+ */
32
+ update(id: string, config: Partial<Omit<SchedulerConfig, 'id'>>): Promise<SchedulerResult>;
33
+ /**
34
+ * Cancel a scheduled task
35
+ * @param id - Task ID
36
+ */
37
+ cancel(id: string): Promise<void>;
38
+ /**
39
+ * List all scheduled tasks for this app
40
+ */
41
+ list(): Promise<SchedulerConfig[]>;
42
+ }
43
+ /** File watch event type */
44
+ export type FileWatchEventType = 'create' | 'modify' | 'delete';
45
+ /** File watch configuration */
46
+ export interface FileWatchConfig {
47
+ /** Unique watch ID */
48
+ id: string;
49
+ /** Path to watch (e.g. '~/Downloads') */
50
+ path: string;
51
+ /** Glob pattern (e.g. '*.png') */
52
+ pattern?: string;
53
+ /** Events to watch for */
54
+ events: FileWatchEventType[];
55
+ /** Action to perform */
56
+ action: {
57
+ type: 'callback';
58
+ callback: string;
59
+ };
60
+ }
61
+ /** File watch event */
62
+ export interface FileWatchEvent {
63
+ /** Watch ID */
64
+ id: string;
65
+ /** Changed file path */
66
+ path: string;
67
+ /** Event type */
68
+ event: FileWatchEventType;
69
+ }
70
+ /** FileWatch API for monitoring file system changes */
71
+ export interface FileWatchAPI {
72
+ /**
73
+ * Register a file watch
74
+ * @param config - Watch configuration
75
+ */
76
+ register(config: FileWatchConfig): Promise<{
77
+ success: boolean;
78
+ }>;
79
+ /**
80
+ * Cancel a file watch
81
+ * @param id - Watch ID
82
+ */
83
+ cancel(id: string): Promise<void>;
84
+ }
85
+ /** File watch callback handler */
86
+ export type FileWatchHandler = (callbackId: string, handler: (event: FileWatchEvent) => void) => void;
87
+ /** Shell API for system integration */
88
+ export interface ShellAPI {
89
+ /**
90
+ * Open URL in system default browser
91
+ * @param url - URL to open
92
+ */
93
+ openExternal(url: string): Promise<void>;
94
+ /**
95
+ * Show file in Finder/Explorer
96
+ * @param path - File path
97
+ */
98
+ showItemInFolder(path: string): Promise<void>;
99
+ /**
100
+ * Open file with system default application
101
+ * @param path - File path
102
+ */
103
+ openPath(path: string): Promise<void>;
104
+ }
105
+ /** GlobalShortcut API for system-level keyboard shortcuts */
106
+ export interface GlobalShortcutAPI {
107
+ /**
108
+ * Register a global shortcut
109
+ * @param accelerator - Key combination (e.g. 'Cmd+Shift+X', 'Ctrl+Alt+P')
110
+ * @param callback - Handler function
111
+ * @returns True if registration succeeded
112
+ */
113
+ register(accelerator: string, callback: () => void): Promise<boolean>;
114
+ /**
115
+ * Unregister a global shortcut
116
+ * @param accelerator - Key combination
117
+ */
118
+ unregister(accelerator: string): Promise<void>;
119
+ /**
120
+ * Unregister all shortcuts for this app
121
+ */
122
+ unregisterAll(): Promise<void>;
123
+ }
124
+ /** Autostart API for managing app launch on system startup */
125
+ export interface AutostartAPI {
126
+ /**
127
+ * Enable auto-start on system boot
128
+ */
129
+ enable(): Promise<void>;
130
+ /**
131
+ * Disable auto-start
132
+ */
133
+ disable(): Promise<void>;
134
+ /**
135
+ * Check if auto-start is enabled
136
+ */
137
+ isEnabled(): Promise<boolean>;
138
+ }
@@ -0,0 +1,65 @@
1
+ import { FileEntry } from './common';
2
+ /** File filter for save dialog */
3
+ export interface FileFilter {
4
+ name: string;
5
+ extensions: string[];
6
+ }
7
+ /** Open file dialog options */
8
+ export interface OpenFileOptions {
9
+ /** MIME type filter, e.g. 'image/*' */
10
+ accept?: string;
11
+ /** Allow multiple file selection */
12
+ multiple?: boolean;
13
+ }
14
+ /** Save file dialog options */
15
+ export interface SaveFileOptions {
16
+ /** Default file name */
17
+ defaultName?: string;
18
+ /** File type filters */
19
+ filters?: FileFilter[];
20
+ }
21
+ /** Message dialog options */
22
+ export interface MessageOptions {
23
+ /** Dialog title */
24
+ title: string;
25
+ /** Dialog message */
26
+ message: string;
27
+ /** Message type */
28
+ type?: 'info' | 'warning' | 'error';
29
+ /** Button labels */
30
+ buttons?: string[];
31
+ }
32
+ /** Dialog API */
33
+ export interface DialogAPI {
34
+ /**
35
+ * Open file selection dialog
36
+ * @param options - Dialog options
37
+ * @returns Selected file(s) or null if cancelled
38
+ */
39
+ openFile(options?: OpenFileOptions): Promise<FileEntry | FileEntry[] | null>;
40
+ /**
41
+ * Open directory selection dialog
42
+ * @returns Selected directory path or null if cancelled
43
+ */
44
+ openDirectory(): Promise<{
45
+ path: string;
46
+ } | null>;
47
+ /**
48
+ * Open save file dialog
49
+ * @param options - Dialog options
50
+ * @returns Selected save path or null if cancelled
51
+ */
52
+ saveFile(options?: SaveFileOptions): Promise<{
53
+ path: string;
54
+ } | null>;
55
+ /**
56
+ * Show a message dialog
57
+ * @param options - Message options
58
+ * @returns Index of clicked button
59
+ */
60
+ message(options: MessageOptions): Promise<number>;
61
+ }
62
+ /** File drop callback */
63
+ export type FileDropCallback = (files: FileEntry[]) => void;
64
+ /** File drop handler (top-level API) */
65
+ export type FileDropHandler = (callback: FileDropCallback) => () => void;