@zhama/tego-plugin-sdk 1.37.2 → 1.40.1
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/agent/guides/host-api-versions.md +3 -0
- package/agent/reference/plugin-sdk-api.md +1 -0
- package/dist/access.d.cts +1 -0
- package/dist/access.d.ts +1 -0
- package/dist/{chunk-EIVA5BR6.js → chunk-2KXEYXM2.js} +1 -1
- package/dist/{chunk-I5Z3ECC4.js → chunk-44LPR67H.js} +1 -1
- package/dist/chunk-66LDWN4T.cjs +1 -0
- package/dist/{chunk-HZ4YWRYX.cjs → chunk-6EKQMOYT.cjs} +2 -2
- package/dist/{chunk-SKNPNPJP.cjs → chunk-H6GXDFLP.cjs} +1 -1
- package/dist/{chunk-6HNG5OZI.cjs → chunk-IOZFHJ4F.cjs} +1 -1
- package/dist/chunk-JV2G2Z33.js +1 -0
- package/dist/{chunk-DRHBXEPK.cjs → chunk-QQOUNXLC.cjs} +7 -7
- package/dist/{chunk-IQNSBHBI.js → chunk-UZBWS5AR.js} +1 -1
- package/dist/{chunk-56QOZQTY.js → chunk-XOXUS4VI.js} +1 -1
- package/dist/decision-card-IF2c4wvM.d.cts +161 -0
- package/dist/decision-card-IF2c4wvM.d.ts +161 -0
- package/dist/dev.cjs +3 -3
- package/dist/dev.js +1 -1
- package/dist/doctor.cjs +6 -6
- package/dist/doctor.js +13 -13
- package/dist/hono.d.cts +1 -0
- package/dist/hono.d.ts +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +1 -1
- package/dist/manifest.cjs +1 -1
- package/dist/manifest.d.cts +654 -654
- package/dist/manifest.d.ts +654 -654
- package/dist/manifest.js +1 -1
- package/dist/pack.cjs +1 -1
- package/dist/pack.js +1 -1
- package/dist/publish.cjs +1 -1
- package/dist/publish.d.cts +6 -3
- package/dist/publish.d.ts +6 -3
- package/dist/publish.js +1 -1
- package/dist/scaffold.cjs +2 -2
- package/dist/scaffold.js +1 -1
- package/dist/server-runtime.cjs +1 -1
- package/dist/server-runtime.d.cts +1 -0
- package/dist/server-runtime.d.ts +1 -0
- package/dist/server-runtime.js +1 -1
- package/dist/server.cjs +1 -1
- package/dist/server.d.cts +58 -33
- package/dist/server.d.ts +58 -33
- package/dist/server.js +1 -1
- package/dist/testing.d.cts +1 -0
- package/dist/testing.d.ts +1 -0
- package/dist/vite.cjs +1 -1
- package/dist/vite.js +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-QKSPPMVN.js → chunk-CDJQ7OPA.js} +0 -0
- /package/dist/{chunk-BN6TGHSB.cjs → chunk-SR5V7ZC2.cjs} +0 -0
package/dist/manifest.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{PYTHON_LOCK_FILENAME,PYTHON_RUNNER_VERSION,PYTHON_WHEELS_DIR,checkPluginAccessCatalog,checkPythonVendoring,normalizePackageName,parseRequirementsLock,parseTegoPluginManifest,parseWheelFilename,tegoPluginManifestSchema}from"./chunk-
|
|
1
|
+
export{PYTHON_LOCK_FILENAME,PYTHON_RUNNER_VERSION,PYTHON_WHEELS_DIR,checkPluginAccessCatalog,checkPythonVendoring,normalizePackageName,parseRequirementsLock,parseTegoPluginManifest,parseWheelFilename,tegoPluginManifestSchema}from"./chunk-2KXEYXM2.js";export{LOCALE_FILENAME_PATTERN,MIGRATION_FILENAME_PATTERN,flattenLocaleKeys,verifyFrontendLocales,verifyMigrationNames}from"./chunk-2NTAWYCG.js";import"./chunk-IVJECPGG.js";import"./chunk-INCA3GFW.js";import"./chunk-XOXUS4VI.js";import"./chunk-VMCGDDGP.js";import"./chunk-SNUCO2MK.js";
|
package/dist/pack.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var u=Object.defineProperty;var e=(r,n)=>u(r,"name",{value:n,configurable:!0});var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var e=(r,n)=>u(r,"name",{value:n,configurable:!0});var chunkQQOUNXLC_cjs=require("./chunk-QQOUNXLC.cjs");require("./chunk-6EKQMOYT.cjs"),require("./chunk-H6GXDFLP.cjs"),require("./chunk-45Y4CR4R.cjs"),require("./chunk-2P6UEAPV.cjs"),require("./chunk-N4SXZZPY.cjs"),require("./chunk-IOZFHJ4F.cjs"),require("./chunk-AJY7ZHXK.cjs"),require("./chunk-OP64Y4IN.cjs"),Object.defineProperty(exports,"buildAgentTemplate",{enumerable:!0,get:e(function(){return chunkQQOUNXLC_cjs.buildAgentTemplate},"get")}),Object.defineProperty(exports,"buildPluginBackend",{enumerable:!0,get:e(function(){return chunkQQOUNXLC_cjs.buildPluginBackend},"get")}),Object.defineProperty(exports,"buildPluginTemplates",{enumerable:!0,get:e(function(){return chunkQQOUNXLC_cjs.buildPluginTemplates},"get")}),Object.defineProperty(exports,"lockPlugin",{enumerable:!0,get:e(function(){return chunkQQOUNXLC_cjs.lockPlugin},"get")}),Object.defineProperty(exports,"packPlugin",{enumerable:!0,get:e(function(){return chunkQQOUNXLC_cjs.packPlugin},"get")}),Object.defineProperty(exports,"readManifest",{enumerable:!0,get:e(function(){return chunkQQOUNXLC_cjs.readManifest},"get")}),Object.defineProperty(exports,"watchPluginFrontend",{enumerable:!0,get:e(function(){return chunkQQOUNXLC_cjs.watchPluginFrontend},"get")});
|
package/dist/pack.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{buildAgentTemplate,buildPluginBackend,buildPluginTemplates,lockPlugin,packPlugin,readManifest,watchPluginFrontend}from"./chunk-
|
|
1
|
+
export{buildAgentTemplate,buildPluginBackend,buildPluginTemplates,lockPlugin,packPlugin,readManifest,watchPluginFrontend}from"./chunk-UZBWS5AR.js";import"./chunk-44LPR67H.js";import"./chunk-2KXEYXM2.js";import"./chunk-2NTAWYCG.js";import"./chunk-IVJECPGG.js";import"./chunk-INCA3GFW.js";import"./chunk-XOXUS4VI.js";import"./chunk-VMCGDDGP.js";import"./chunk-SNUCO2MK.js";
|
package/dist/publish.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var $=Object.defineProperty;var
|
|
1
|
+
"use strict";var $=Object.defineProperty;var i=(e,n)=>$(e,"name",{value:n,configurable:!0});var chunkQQOUNXLC_cjs=require("./chunk-QQOUNXLC.cjs");require("./chunk-6EKQMOYT.cjs"),require("./chunk-H6GXDFLP.cjs"),require("./chunk-45Y4CR4R.cjs");var chunk2P6UEAPV_cjs=require("./chunk-2P6UEAPV.cjs");require("./chunk-N4SXZZPY.cjs"),require("./chunk-IOZFHJ4F.cjs"),require("./chunk-AJY7ZHXK.cjs"),require("./chunk-OP64Y4IN.cjs");var promises=require("fs/promises"),path=require("path"),API_PREFIX="/api/v1/tego-os";async function publishPlugin(e){const n=e.log===null?()=>{}:e.log??(r=>console.log(r)),a=await chunkQQOUNXLC_cjs.packPlugin({root:e.root,log:n});return publishPackedPlugin(a,e)}i(publishPlugin,"publishPlugin");async function publishPackedPlugin(e,n){const a=n.log===null?()=>{}:n.log??(p=>console.log(p)),r=n.fetchImpl??fetch,t=createCaller(n.server,n.token,r),s=await promises.readFile(e.file),o=path.basename(e.file);a("\u203A presigning upload");const c=await t("POST","/admin/runtime-plugins/presign-stream",{filename:o,mimeType:"application/zip",size:s.byteLength});a(`\u203A uploading ${o} (${s.byteLength} bytes)`),await putArchive(n.server,c.uploadUrl,s,r),a("\u203A inspecting package");const u=await t("POST","/admin/runtime-plugins/inspect",{uploadToken:c.uploadToken});a(` ${u.pluginId}@${u.semanticVersion} \u2014 ${describeParts(u)}${u.isUpgrade?" (upgrade)":""}${u.requiresConfig?", needs config":""}`),a("\u203A finalizing release");const g=await t("POST","/admin/runtime-plugins/upload",{uploadToken:c.uploadToken,...n.meta});let l=g.release;a(` release ${l.id} (${l.status})`),(n.approve??!0)&&(a("\u203A approving release"),l=await t("POST",`/admin/runtime-plugins/releases/${encodeURIComponent(l.id)}/approve`,{}),a(` release ${l.id} (${l.status})`));let d=null;if(n.install??!0){const p=chunk2P6UEAPV_cjs.resolvePluginScope(e.manifest),f=p==="avatar"?{releaseId:l.id,avatarIds:n.avatarIds??await currentAvatarIds(t,e.manifest.id,a)}:{releaseId:l.id};a(`\u203A installing for tenant (${p}-scoped)`),d=await t("POST","/admin/runtime-plugins/installs",f),reportInstall(d,a)}return{packed:e,preview:u,catalog:g.catalog,release:l,install:d}}i(publishPackedPlugin,"publishPackedPlugin");async function currentAvatarIds(e,n,a){const t=(await e("GET","/admin/runtime-plugins/installs")).find(s=>s.pluginId===n);return t?(a(` keeping the ${t.avatarIds.length} avatars it is installed on`),t.avatarIds):(a(" first install: no avatars selected (pass --avatar to choose)"),[])}i(currentAvatarIds,"currentAvatarIds");function describeParts(e){const n=[];return e.parts.frontend&&n.push(`frontend (${e.parts.frontend.locales.length} locales)`),e.parts.backend&&n.push(`backend (${e.parts.backend.migrationCount} migrations)`),e.parts.claw&&n.push("claw"),n.join(", ")||"no parts"}i(describeParts,"describeParts");function reportInstall(e,n){const a=e.avatars;if(!a||a.attempted===0){n(` installed ${e.pluginId}@${e.version}`);return}const r=a.attempted-a.failures.length;n(` installed ${e.pluginId}@${e.version} \u2014 ${r}/${a.attempted} avatars`);for(const t of a.failures)n(` \u2717 ${t.avatarId}: ${t.message}`)}i(reportInstall,"reportInstall");function createCaller(e,n,a){const r=e.replace(/\/+$/,"");return i(async function(s,o,c){const u=await a(`${r}${API_PREFIX}${o}`,{method:s,headers:{authorization:`Bearer ${n}`,...c===void 0?{}:{"content-type":"application/json"}},...c===void 0?{}:{body:JSON.stringify(c)}});return unwrap(u,`${s} ${o}`)},"call")}i(createCaller,"createCaller");async function putArchive(e,n,a,r){const t=e.replace(/\/+$/,""),s=await r(`${t}${n}`,{method:"PUT",headers:{"content-type":"application/zip"},body:a});await unwrap(s,"PUT upload")}i(putArchive,"putArchive");async function unwrap(e,n){let a;try{a=await e.json()}catch{a=null}if(!e.ok||!a?.success){const r=a?.error?.message??`HTTP ${e.status}`;throw new Error(`${n} failed: ${r}`)}return a.data}i(unwrap,"unwrap"),exports.publishPackedPlugin=publishPackedPlugin,exports.publishPlugin=publishPlugin;
|
package/dist/publish.d.cts
CHANGED
|
@@ -9,9 +9,12 @@ interface PublishPluginOptions {
|
|
|
9
9
|
/** Admin bearer token. The publish endpoints all sit behind `adminMiddleware`. */
|
|
10
10
|
token: string;
|
|
11
11
|
/**
|
|
12
|
-
* Avatars to install onto, for an avatar-scoped plugin
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Avatars to install onto, for an avatar-scoped plugin: the complete set, so
|
|
13
|
+
* any avatar left out is uninstalled. An empty array installs it for nobody,
|
|
14
|
+
* which is the server's own contract, not a no-op — it still creates the
|
|
15
|
+
* tenant install. Omitted, an upgrade keeps the avatars the plugin is
|
|
16
|
+
* installed on now and a first install selects none. Ignored for a
|
|
17
|
+
* tenant-scoped plugin.
|
|
15
18
|
*/
|
|
16
19
|
avatarIds?: string[];
|
|
17
20
|
/** Catalog metadata to stamp on the release. */
|
package/dist/publish.d.ts
CHANGED
|
@@ -9,9 +9,12 @@ interface PublishPluginOptions {
|
|
|
9
9
|
/** Admin bearer token. The publish endpoints all sit behind `adminMiddleware`. */
|
|
10
10
|
token: string;
|
|
11
11
|
/**
|
|
12
|
-
* Avatars to install onto, for an avatar-scoped plugin
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Avatars to install onto, for an avatar-scoped plugin: the complete set, so
|
|
13
|
+
* any avatar left out is uninstalled. An empty array installs it for nobody,
|
|
14
|
+
* which is the server's own contract, not a no-op — it still creates the
|
|
15
|
+
* tenant install. Omitted, an upgrade keeps the avatars the plugin is
|
|
16
|
+
* installed on now and a first install selects none. Ignored for a
|
|
17
|
+
* tenant-scoped plugin.
|
|
15
18
|
*/
|
|
16
19
|
avatarIds?: string[];
|
|
17
20
|
/** Catalog metadata to stamp on the release. */
|
package/dist/publish.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var v=Object.defineProperty;var s=(a,e)=>v(a,"name",{value:e,configurable:!0});import{packPlugin as h}from"./chunk-UZBWS5AR.js";import"./chunk-44LPR67H.js";import"./chunk-2KXEYXM2.js";import"./chunk-2NTAWYCG.js";import{resolvePluginScope as I}from"./chunk-IVJECPGG.js";import"./chunk-INCA3GFW.js";import"./chunk-XOXUS4VI.js";import"./chunk-VMCGDDGP.js";import"./chunk-SNUCO2MK.js";import{readFile as w}from"fs/promises";import{basename as P}from"path";var y="/api/v1/tego-os";async function T(a){const e=a.log===null?()=>{}:a.log??(i=>console.log(i)),t=await h({root:a.root,log:e});return f(t,a)}s(T,"publishPlugin");async function f(a,e){const t=e.log===null?()=>{}:e.log??(p=>console.log(p)),i=e.fetchImpl??fetch,n=S(e.server,e.token,i),r=await w(a.file),c=P(a.file);t("\u203A presigning upload");const u=await n("POST","/admin/runtime-plugins/presign-stream",{filename:c,mimeType:"application/zip",size:r.byteLength});t(`\u203A uploading ${c} (${r.byteLength} bytes)`),await z(e.server,u.uploadUrl,r,i),t("\u203A inspecting package");const l=await n("POST","/admin/runtime-plugins/inspect",{uploadToken:u.uploadToken});t(` ${l.pluginId}@${l.semanticVersion} \u2014 ${k(l)}${l.isUpgrade?" (upgrade)":""}${l.requiresConfig?", needs config":""}`),t("\u203A finalizing release");const g=await n("POST","/admin/runtime-plugins/upload",{uploadToken:u.uploadToken,...e.meta});let o=g.release;t(` release ${o.id} (${o.status})`),(e.approve??!0)&&(t("\u203A approving release"),o=await n("POST",`/admin/runtime-plugins/releases/${encodeURIComponent(o.id)}/approve`,{}),t(` release ${o.id} (${o.status})`));let d=null;if(e.install??!0){const p=I(a.manifest),$=p==="avatar"?{releaseId:o.id,avatarIds:e.avatarIds??await b(n,a.manifest.id,t)}:{releaseId:o.id};t(`\u203A installing for tenant (${p}-scoped)`),d=await n("POST","/admin/runtime-plugins/installs",$),A(d,t)}return{packed:a,preview:l,catalog:g.catalog,release:o,install:d}}s(f,"publishPackedPlugin");async function b(a,e,t){const n=(await a("GET","/admin/runtime-plugins/installs")).find(r=>r.pluginId===e);return n?(t(` keeping the ${n.avatarIds.length} avatars it is installed on`),n.avatarIds):(t(" first install: no avatars selected (pass --avatar to choose)"),[])}s(b,"currentAvatarIds");function k(a){const e=[];return a.parts.frontend&&e.push(`frontend (${a.parts.frontend.locales.length} locales)`),a.parts.backend&&e.push(`backend (${a.parts.backend.migrationCount} migrations)`),a.parts.claw&&e.push("claw"),e.join(", ")||"no parts"}s(k,"describeParts");function A(a,e){const t=a.avatars;if(!t||t.attempted===0){e(` installed ${a.pluginId}@${a.version}`);return}const i=t.attempted-t.failures.length;e(` installed ${a.pluginId}@${a.version} \u2014 ${i}/${t.attempted} avatars`);for(const n of t.failures)e(` \u2717 ${n.avatarId}: ${n.message}`)}s(A,"reportInstall");function S(a,e,t){const i=a.replace(/\/+$/,"");return s(async function(r,c,u){const l=await t(`${i}${y}${c}`,{method:r,headers:{authorization:`Bearer ${e}`,...u===void 0?{}:{"content-type":"application/json"}},...u===void 0?{}:{body:JSON.stringify(u)}});return m(l,`${r} ${c}`)},"call")}s(S,"createCaller");async function z(a,e,t,i){const n=a.replace(/\/+$/,""),r=await i(`${n}${e}`,{method:"PUT",headers:{"content-type":"application/zip"},body:t});await m(r,"PUT upload")}s(z,"putArchive");async function m(a,e){let t;try{t=await a.json()}catch{t=null}if(!a.ok||!t?.success){const i=t?.error?.message??`HTTP ${a.status}`;throw new Error(`${e} failed: ${i}`)}return t.data}s(m,"unwrap");export{f as publishPackedPlugin,T as publishPlugin};
|
package/dist/scaffold.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var g=Object.defineProperty;var o=(e,t)=>g(e,"name",{value:t,configurable:!0});var
|
|
1
|
+
"use strict";var g=Object.defineProperty;var o=(e,t)=>g(e,"name",{value:t,configurable:!0});var chunkIOZFHJ4F_cjs=require("./chunk-IOZFHJ4F.cjs"),fs=require("fs"),path=require("path"),ACCESS_SQL=`-- Generated by \`pnpm -F @tego/plugin-sdk access:sql\` from src/access/drizzle.ts. Do not edit.
|
|
2
2
|
CREATE TABLE IF NOT EXISTS "tego_access_assignments" (
|
|
3
3
|
"id" text PRIMARY KEY NOT NULL,
|
|
4
4
|
"tenant_id" text NOT NULL,
|
|
@@ -1220,4 +1220,4 @@ export default definePluginEntry({
|
|
|
1220
1220
|
// refuses the registration.
|
|
1221
1221
|
},
|
|
1222
1222
|
});
|
|
1223
|
-
`;return[{path:"claw/openclaw.plugin.json",contents:n},{path:"claw/package.json",contents:s},{path:"claw/tsconfig.json",contents:a},{path:"claw/types/openclaw-plugin-sdk.d.ts",contents:i},{path:"claw/src/index.ts",contents:r}]}o(clawFiles,"clawFiles");function buildPluginFiles(e,{dependencies:t="workspace"}={}){const n=[manifest(e),rootPackageJson(e,t),eslintConfig(t),...sharedFiles(t),vitestConfig(),readme(e,t),...agentFiles(e,t)];return t==="npm"&&n.push(...standaloneRootFiles()),e.parts.includes("frontend")&&n.push(...frontendFiles(e,t)),e.parts.includes("backend")&&n.push(...backendFiles(t,e)),standardAccess(e)&&n.push({path:"shared/access.json",contents:json(standardAccessCatalog(keyNamespaceFor(e.id)))}),e.parts.includes("claw")&&n.push(...clawFiles(e,t)),n}o(buildPluginFiles,"buildPluginFiles");var PLUGIN_ID_PATTERN=/^[a-z0-9][a-z0-9._-]*$/,PLUGIN_PARTS=["frontend","backend","claw"],PLUGIN_SCOPES=["avatar","tenant"],PLUGIN_ID_HINT="lowercase letters and digits, may contain . _ -, starting with a letter or digit";function validatePluginAnswers(e,t){if(typeof e!="object"||e===null||Array.isArray(e))throw new Error("answers must be a JSON object");const n=e,s=o(c=>{const d=n[c];if(typeof d!="string"||d.trim()==="")throw new Error(`${c} is required`);return d.trim()},"text"),a=s("id");if(!PLUGIN_ID_PATTERN.test(a))throw new Error(`id must be ${PLUGIN_ID_HINT}`);const i=n.parts;if(!Array.isArray(i)||i.length===0||i.some(c=>!PLUGIN_PARTS.includes(c)))throw new Error(`parts must be a non-empty list of ${PLUGIN_PARTS.join(", ")}`);const r=n.scope??"avatar";if(!PLUGIN_SCOPES.includes(r))throw new Error(`scope must be one of ${PLUGIN_SCOPES.join(", ")}`);const u=n.template??"standard";if(!PLUGIN_TEMPLATES.includes(u))throw new Error(`template must be one of ${PLUGIN_TEMPLATES.join(", ")}`);return{id:a,displayNameZh:s("displayNameZh"),displayNameEn:s("displayNameEn"),descriptionZh:s("descriptionZh"),descriptionEn:s("descriptionEn"),parts:[...new Set(i)],scope:r,hostApiRange:t,template:u}}o(validatePluginAnswers,"validatePluginAnswers");function writePlugin(e,t){return writePluginDirectory(path.join(e,"plugins"),t,buildPluginFiles(t))}o(writePlugin,"writePlugin");async function writeStandalonePlugin(e,t){return writePluginDirectory(e,t,await formatPluginFiles(buildPluginFiles(t,{dependencies:"npm"})))}o(writeStandalonePlugin,"writeStandalonePlugin");var FORMATTED=/\.(?:[cm]?[jt]sx?|json|css)$/;async function formatPluginFiles(e){const t=await import("prettier");return Promise.all(e.map(async n=>FORMATTED.test(n.path)?{...n,contents:await t.format(n.contents,{...STANDALONE_PRETTIER,filepath:n.path})}:n))}o(formatPluginFiles,"formatPluginFiles");function writePluginDirectory(e,t,n){const s=path.join(e,t.id);if(fs.existsSync(s))throw new Error(`${s} already exists \u2014 pick another id or remove it first`);fs.mkdirSync(e,{recursive:!0});const a=fs.mkdtempSync(path.join(e,`.${t.id}-`));try{for(const i of n){const r=path.join(a,i.path);fs.mkdirSync(path.dirname(r),{recursive:!0}),fs.writeFileSync(r,i.contents)}fs.renameSync(a,s)}catch(i){throw fs.rmSync(a,{recursive:!0,force:!0}),i}return{directory:s,files:n.map(i=>i.path)}}o(writePluginDirectory,"writePluginDirectory");async function createStandalonePlugin(e,t){let n;try{n=JSON.parse(e)}catch(a){throw new Error(`answers must be JSON: ${a instanceof Error?a.message:String(a)}`)}const s=validatePluginAnswers(n,`^${
|
|
1223
|
+
`;return[{path:"claw/openclaw.plugin.json",contents:n},{path:"claw/package.json",contents:s},{path:"claw/tsconfig.json",contents:a},{path:"claw/types/openclaw-plugin-sdk.d.ts",contents:i},{path:"claw/src/index.ts",contents:r}]}o(clawFiles,"clawFiles");function buildPluginFiles(e,{dependencies:t="workspace"}={}){const n=[manifest(e),rootPackageJson(e,t),eslintConfig(t),...sharedFiles(t),vitestConfig(),readme(e,t),...agentFiles(e,t)];return t==="npm"&&n.push(...standaloneRootFiles()),e.parts.includes("frontend")&&n.push(...frontendFiles(e,t)),e.parts.includes("backend")&&n.push(...backendFiles(t,e)),standardAccess(e)&&n.push({path:"shared/access.json",contents:json(standardAccessCatalog(keyNamespaceFor(e.id)))}),e.parts.includes("claw")&&n.push(...clawFiles(e,t)),n}o(buildPluginFiles,"buildPluginFiles");var PLUGIN_ID_PATTERN=/^[a-z0-9][a-z0-9._-]*$/,PLUGIN_PARTS=["frontend","backend","claw"],PLUGIN_SCOPES=["avatar","tenant"],PLUGIN_ID_HINT="lowercase letters and digits, may contain . _ -, starting with a letter or digit";function validatePluginAnswers(e,t){if(typeof e!="object"||e===null||Array.isArray(e))throw new Error("answers must be a JSON object");const n=e,s=o(c=>{const d=n[c];if(typeof d!="string"||d.trim()==="")throw new Error(`${c} is required`);return d.trim()},"text"),a=s("id");if(!PLUGIN_ID_PATTERN.test(a))throw new Error(`id must be ${PLUGIN_ID_HINT}`);const i=n.parts;if(!Array.isArray(i)||i.length===0||i.some(c=>!PLUGIN_PARTS.includes(c)))throw new Error(`parts must be a non-empty list of ${PLUGIN_PARTS.join(", ")}`);const r=n.scope??"avatar";if(!PLUGIN_SCOPES.includes(r))throw new Error(`scope must be one of ${PLUGIN_SCOPES.join(", ")}`);const u=n.template??"standard";if(!PLUGIN_TEMPLATES.includes(u))throw new Error(`template must be one of ${PLUGIN_TEMPLATES.join(", ")}`);return{id:a,displayNameZh:s("displayNameZh"),displayNameEn:s("displayNameEn"),descriptionZh:s("descriptionZh"),descriptionEn:s("descriptionEn"),parts:[...new Set(i)],scope:r,hostApiRange:t,template:u}}o(validatePluginAnswers,"validatePluginAnswers");function writePlugin(e,t){return writePluginDirectory(path.join(e,"plugins"),t,buildPluginFiles(t))}o(writePlugin,"writePlugin");async function writeStandalonePlugin(e,t){return writePluginDirectory(e,t,await formatPluginFiles(buildPluginFiles(t,{dependencies:"npm"})))}o(writeStandalonePlugin,"writeStandalonePlugin");var FORMATTED=/\.(?:[cm]?[jt]sx?|json|css)$/;async function formatPluginFiles(e){const t=await import("prettier");return Promise.all(e.map(async n=>FORMATTED.test(n.path)?{...n,contents:await t.format(n.contents,{...STANDALONE_PRETTIER,filepath:n.path})}:n))}o(formatPluginFiles,"formatPluginFiles");function writePluginDirectory(e,t,n){const s=path.join(e,t.id);if(fs.existsSync(s))throw new Error(`${s} already exists \u2014 pick another id or remove it first`);fs.mkdirSync(e,{recursive:!0});const a=fs.mkdtempSync(path.join(e,`.${t.id}-`));try{for(const i of n){const r=path.join(a,i.path);fs.mkdirSync(path.dirname(r),{recursive:!0}),fs.writeFileSync(r,i.contents)}fs.renameSync(a,s)}catch(i){throw fs.rmSync(a,{recursive:!0,force:!0}),i}return{directory:s,files:n.map(i=>i.path)}}o(writePluginDirectory,"writePluginDirectory");async function createStandalonePlugin(e,t){let n;try{n=JSON.parse(e)}catch(a){throw new Error(`answers must be JSON: ${a instanceof Error?a.message:String(a)}`)}const s=validatePluginAnswers(n,`^${chunkIOZFHJ4F_cjs.HOST_API_VERSION}`);return writeStandalonePlugin(path.resolve(t.cwd,t.parent),s)}o(createStandalonePlugin,"createStandalonePlugin"),exports.PLUGIN_ID_HINT=PLUGIN_ID_HINT,exports.PLUGIN_ID_PATTERN=PLUGIN_ID_PATTERN,exports.PLUGIN_PARTS=PLUGIN_PARTS,exports.PLUGIN_SCOPES=PLUGIN_SCOPES,exports.PLUGIN_TEMPLATES=PLUGIN_TEMPLATES,exports.PUBLISHED_SDK_PACKAGES=PUBLISHED_SDK_PACKAGES,exports.STANDALONE_PRETTIER=STANDALONE_PRETTIER,exports.STANDALONE_TSCONFIG_FILES=STANDALONE_TSCONFIG_FILES,exports.buildPluginFiles=buildPluginFiles,exports.createStandalonePlugin=createStandalonePlugin,exports.formatPluginFiles=formatPluginFiles,exports.packageNameFor=packageNameFor,exports.validatePluginAnswers=validatePluginAnswers,exports.writePlugin=writePlugin,exports.writeStandalonePlugin=writeStandalonePlugin;
|
package/dist/scaffold.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var I=Object.defineProperty;var o=(e,t)=>I(e,"name",{value:t,configurable:!0});import{HOST_API_VERSION as $}from"./chunk-
|
|
1
|
+
var I=Object.defineProperty;var o=(e,t)=>I(e,"name",{value:t,configurable:!0});import{HOST_API_VERSION as $}from"./chunk-XOXUS4VI.js";import{existsSync as j,mkdirSync as T,mkdtempSync as U,writeFileSync as q,renameSync as M,rmSync as H}from"fs";import{join as m,dirname as z,resolve as G}from"path";var K=`-- Generated by \`pnpm -F @tego/plugin-sdk access:sql\` from src/access/drizzle.ts. Do not edit.
|
|
2
2
|
CREATE TABLE IF NOT EXISTS "tego_access_assignments" (
|
|
3
3
|
"id" text PRIMARY KEY NOT NULL,
|
|
4
4
|
"tenant_id" text NOT NULL,
|
package/dist/server-runtime.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var S=Object.defineProperty;var n=(a,e)=>S(a,"name",{value:e,configurable:!0});var chunkIMAVYQ4U_cjs=require("./chunk-IMAVYQ4U.cjs"),chunkBN6TGHSB_cjs=require("./chunk-BN6TGHSB.cjs"),http=require("http");function toArrayBuffer(a){const e=new ArrayBuffer(a.byteLength);return new Uint8Array(e).set(a),e}n(toArrayBuffer,"toArrayBuffer");function readEnv(a){const e=n(s=>{const c=a[s];if(!c)throw new Error(`${s} is required but was not set`);return c},"require_");return{pluginId:e("TEGO_PLUGIN_ID"),tenantId:e("TEGO_TENANT_ID"),port:Number(e("TEGO_PLUGIN_PORT")),healthPath:a.TEGO_PLUGIN_HEALTH_PATH??"/healthz",hostApiUrl:e("TEGO_PLUGIN_HOST_API_URL"),hostApiToken:e("TEGO_PLUGIN_HOST_API_TOKEN"),databaseUrl:e("DATABASE_URL"),gatewayKey:e("TEGO_PLUGIN_GATEWAY_KEY")}}n(readEnv,"readEnv");function readUserContext(a,e){const s=n(f=>{const A=a[f],v=Array.isArray(A)?A[0]:A;return v&&v.length>0?v:null},"read"),c=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.userId),d=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.tenantId);if(!c||!d)return null;const l=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.signature),w=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.issuedAt);if(!l||!w)return null;const h=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.avatarId),y=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.roles),i=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.delegation),u={userId:c,tenantId:d,rolesHeader:y??"",avatarId:h??"",issuedAt:w,...i?{delegationHeader:i}:{}};if(!chunkIMAVYQ4U_cjs.verifyPluginContext({context:u,signature:l,key:e.key,nowMs:e.nowMs}))return null;let E=[];if(y)try{const f=JSON.parse(y);if(!Array.isArray(f))return null;E=f.filter(A=>typeof A=="string")}catch{return null}let m;if(i){if(!h)return null;try{const f=JSON.parse(i);if(!f||typeof f.id!="string"||!f.id||!Array.isArray(f.actions)||f.actions.some(A=>A!=="records.read"&&A!=="work.prepare"))return null;m={id:f.id,actions:f.actions}}catch{return null}}return{userId:c,tenantId:d,roles:E,...h?{avatarId:h}:{},...m?{delegation:m}:{}}}n(readUserContext,"readUserContext");function readPublicContext(a,e){const s=n(E=>{const m=a[E],f=Array.isArray(m)?m[0]:m;return f&&f.length>0?f:null},"read"),c=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.tenantId),d=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.installId),l=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.publicRoute),w=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.clientIp),h=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.avatarId),y=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.issuedAt),i=s(chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.signature);if(!c||!d||!l||!w||!y||!i)return null;const u={tenantId:c,installId:d,route:l,clientIp:w,...h?{avatarId:h}:{}};return chunkIMAVYQ4U_cjs.verifyPluginPublicContext({context:{...u,issuedAt:y},signature:i,key:e.key,nowMs:e.nowMs})?u:null}n(readPublicContext,"readPublicContext");function createHostClient(a){const e=n(async(t,o)=>{const r=await fetch(`${a.hostApiUrl}${t}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a.hostApiToken}`},body:JSON.stringify(o),...t.startsWith("/knowledge/collections/")||t.startsWith("/knowledge/admin/")?{signal:AbortSignal.timeout(12e4)}:t==="/mail/send"?{signal:AbortSignal.timeout(6e4)}:t.startsWith("/directory/")||t.startsWith("/knowledge/")||t.startsWith("/delegations/")||t.startsWith("/proactive/")||t==="/mail/status"||t==="/mail/unsubscribes"||t==="/events"?{signal:AbortSignal.timeout(1e4)}:{}});if(!r.ok){const p=await r.text();let g;try{if(g=JSON.parse(p)?.error?.details,typeof g=="string")try{g=JSON.parse(g)}catch{}}catch{}throw Object.assign(new Error(`Tego host API ${t} failed: ${r.status} ${p}`),{status:r.status,details:g,retryAfter:r.headers.get("retry-after")})}return r},"call"),s={debug:n((t,o)=>void c("debug",t,o),"debug"),info:n((t,o)=>void c("info",t,o),"info"),warn:n((t,o)=>void c("warn",t,o),"warn"),error:n((t,o)=>void c("error",t,o),"error")};async function c(t,o,r){try{await e("/log",{level:t,message:o,fields:r})}catch{}}n(c,"emitLog");const d=n((t,o)=>`${a.hostApiUrl}/storage/${t}?key=${encodeURIComponent(o)}`,"storageUrl"),l={copy:n(async(t,o)=>{const p=await(await e("/storage/copy",{sourceKey:t,destinationKey:o})).json();if(!p.data)throw new Error("Tego host API returned no copied object");return p.data},"copy"),getStream:n(async t=>{const o=await fetch(d("stream",t),{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(o.status===404)return null;if(!o.ok)throw new Error(`Tego storage stream failed: ${o.status}`);return o.body},"getStream"),putStream:n(async(t,o,r)=>{const p={method:"POST",duplex:"half",body:o,headers:{authorization:`Bearer ${a.hostApiToken}`,"content-length":String(r.sizeBytes),"content-type":r.contentType??"application/octet-stream"}},g=await fetch(d("stream",t),p);if(!g.ok)throw new Error(`Tego storage stream write failed: ${g.status}`)},"putStream"),put:n(async(t,o,r)=>{const p=await fetch(d("put",t),{method:"POST",headers:{authorization:`Bearer ${a.hostApiToken}`,"content-type":r??"application/octet-stream"},body:toArrayBuffer(o)});if(!p.ok)throw new Error(`Tego storage put failed: ${p.status}`)},"put"),get:n(async(t,o)=>{const r=o?.firstBytes,p=d("get",t),g=await fetch(r===void 0?p:`${p}&bytes=${r}`,{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(g.status===404)return null;if(!g.ok)throw new Error(`Tego storage get failed: ${g.status}`);return new Uint8Array(await g.arrayBuffer())},"get"),head:n(async t=>{const o=await fetch(`${a.hostApiUrl}/storage/head`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a.hostApiToken}`},body:JSON.stringify({key:t})});if(o.status===404)return null;if(!o.ok)throw new Error(`Tego storage head failed: ${o.status}`);const r=await o.json();if(!r.data)throw new Error("Tego host API returned no object head");return r.data},"head"),delete:n(async t=>{await e("/storage/delete",{key:t})},"delete"),signedUrl:n(async(t,o)=>{const g=(await(await e("/storage/signed-url",{key:t,ttlSeconds:o})).json()).data?.url;if(!g)throw new Error("Tego host API returned no signed url");return g},"signedUrl"),signedPath:n(async(t,o)=>{const g=(await(await e("/storage/signed-url",{key:t,ttlSeconds:o})).json()).data?.path;if(!g)throw new Error("Tego host API returned no signed path");return g},"signedPath"),managedPath:n(async(t,o,r)=>{const g=await(await e("/storage/signed-url",{key:t,policy:o,ttlSeconds:r})).json();if(!g.data?.path)throw new Error("Tego host API returned no managed path");return g.data.path},"managedPath"),uploadPath:n(async(t,o)=>{const p=await(await e("/storage/upload-url",{key:t,maxBytes:o?.maxBytes,ttlSeconds:o?.ttlSeconds})).json();if(!p.data?.path)throw new Error("Tego host API returned no upload path");return p.data},"uploadPath")},w={publish:n(async(t,o)=>{await e("/events",{name:t,payload:o})},"publish")},h={send:n(async t=>{const r=await(await e("/notifications",t)).json();if(!r.data?.id)throw new Error("Tego host API returned no notification id");return{id:r.data.id}},"send")},y={async emit(t){const r=await(await e("/proactive/emit",t)).json();if(!r.data)throw new Error("Tego proactive response is missing data");return r.data}},i=n(async(t,o)=>{const p=await(await e(t,o)).json();if(!p.data)throw new Error("Tego attention response is missing data");return p.data},"attentionStatus"),u={async request(t){const r=await(await e("/attention/requests",t)).json();if(!r.data?.itemId)throw new Error("Tego host API returned no attention item");return r.data},get:n(t=>i("/attention/requests/get",{itemId:t}),"get"),cancel:n(t=>i("/attention/requests/cancel",{itemId:t}),"cancel")},E={async send(t){const r=await(await e("/mail/send",t)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async status(t){const r=await(await e("/mail/status",{userId:t})).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async unsubscribes(t={}){const r=await(await e("/mail/unsubscribes",t)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data}};let m={};const A={current:n(()=>m,"current"),refresh:n(async()=>{const t=await fetch(`${a.hostApiUrl}/config`,{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(!t.ok)throw new Error(`Tego host API /config failed: ${t.status} ${await t.text()}`);return m=(await t.json()).data?.values??{},m},"refresh")},v={async read(t,o){return(await(await e("/sources/read",{id:t,...o})).json()).data}},I={async list(t){const r=await(await e("/delegations/list",{userId:t})).json();if(!r.data)throw new Error("Tego delegation response is missing data");return r.data}},P={async verify(t){const r=await(await e("/knowledge/verify",t)).json();if(!r.data)throw new Error("Tego knowledge response is missing data");return r.data},collections:{ensure:n(t=>T("ensure",t),"ensure"),permissions:n(t=>T("permissions",t),"permissions"),move:n(t=>T("move",t),"move"),access:n(t=>T("access",t),"access"),import:n(t=>T("import",t),"import"),importFiles:n(t=>T("import-files",t),"importFiles"),status:n(t=>T("status",t),"status"),delete:n(t=>T("delete",t),"delete"),documentsStatus:n(t=>T("documents-status",t),"documentsStatus"),documentContent:n(t=>T("document-content",t),"documentContent"),search:n(t=>T("search",t),"search"),remove:n(t=>T("remove",t),"remove")}};async function T(t,o){const p=await(await e(`/knowledge/collections/${t}`,o)).json();if(!p.data)throw new Error("Tego knowledge collection response is missing data");return p.data}n(T,"collectionCall");const _={async identity(t){const r=await(await e("/directory/identity",{userId:t})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async validate(t){const r=await(await e("/directory/validate",{principals:t})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async list(t){const r=await(await e("/directory/list",t)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async match(t){const r=await(await e("/directory/match",t)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data}},k={provisionUser:n(t=>b("/accounts/provision",t),"provisionUser"),resetPassword:n(t=>b("/accounts/password/reset",t),"resetPassword"),inviteUser:n(t=>b("/accounts/invite",t),"inviteUser"),getInvitation:n(t=>b("/accounts/get",{invitationId:t}),"getInvitation"),resendInvitation:n(t=>b("/accounts/resend",{invitationId:t}),"resendInvitation")};async function b(t,o){const p=await(await e(t,o)).json();if(!p.data)throw new Error("Tego account response is missing data");return p.data}return n(b,"collectionEnvelope"),{accounts:k,log:s,storage:l,diagrams:{status:n(async()=>{const o=await(await e("/diagrams/status",{})).json();if(!o.data)throw new Error("Tego host API returned no renderer status");return o.data},"status"),render:n(async t=>{const r=await(await e("/diagrams/render",t)).json();if(!r.data?.key)throw new Error("Tego host API returned no diagram artifact");return r.data},"render")},events:w,notifications:h,proactive:y,attention:u,mail:E,config:A,sources:v,directory:_,knowledge:P,knowledgeAdmin:{listManageableBases:n(t=>b("/knowledge/admin/list",t),"listManageableBases"),previewCreateBase:n(t=>b("/knowledge/admin/create-preview",t),"previewCreateBase"),createApprovedBase:n(t=>b("/knowledge/admin/create",t),"createApprovedBase"),prepareDocumentContent:n(t=>b("/knowledge/admin/prepare",t),"prepareDocumentContent"),previewDocumentBatch:n(t=>b("/knowledge/admin/preview",t),"previewDocumentBatch"),stageApprovedDocumentBatch:n(t=>b("/knowledge/admin/import",t),"stageApprovedDocumentBatch"),getTask:n(t=>b("/knowledge/admin/task",t),"getTask")},delegations:I}}n(createHostClient,"createHostClient");var ACQUIRE_TIMEOUT_MS=5e3,IDLE_IN_TRANSACTION_TIMEOUT_MS=15e3;function createScopedDb(a){let e=null;async function s(){if(e)return e;const c=await import("pg"),d=c.default?.Pool??c.Pool;if(!d)throw new Error('The "pg" module resolved without a Pool constructor. The plugin runtime expects the driver the runner image provides.');return e=new d({connectionString:a,connectionTimeoutMillis:ACQUIRE_TIMEOUT_MS}),e}return n(s,"ensurePool"),{query:n(async(c,d)=>(await(await s()).query(c,d)).rows,"query"),transaction:n(async c=>{const l=await(await s()).connect();let w=!0,h=!1;const y={query:n(async(i,u)=>{if(h)throw new Error("This transaction has already ended; its `tx` cannot be used afterwards.");return(await l.query(i,u)).rows},"query")};try{await l.query("BEGIN"),await l.query(`SET LOCAL idle_in_transaction_session_timeout = ${IDLE_IN_TRANSACTION_TIMEOUT_MS}`);const i=await c(y);return await l.query("COMMIT"),i}catch(i){try{await l.query("ROLLBACK")}catch{w=!1}throw i}finally{h=!0,l.release(w?void 0:!0)}},"transaction")}}n(createScopedDb,"createScopedDb");function toWebRequest(a,e){const s=`http://localhost${a.url??"/"}`,c=new Headers;for(const[l,w]of Object.entries(a.headers))w!==void 0&&c.set(l,Array.isArray(w)?w.join(", "):w);const d=a.method??"GET";return new Request(s,{method:d,headers:c,...d==="GET"||d==="HEAD"?{}:{body:e}})}n(toWebRequest,"toWebRequest");async function writeWebResponse(a,e){const s={};e.headers.forEach((c,d)=>{s[d]=c}),a.writeHead(e.status,s),a.end(Buffer.from(await e.arrayBuffer()))}n(writeWebResponse,"writeWebResponse");function readBody(a,e){return new Promise((s,c)=>{const d=[];let l=0;a.on("data",w=>{if(l+=w.length,e!==void 0&&l>e){c(new Error("Policy request body too large")),a.destroy();return}d.push(w)}),a.on("end",()=>{s(toArrayBuffer(Buffer.concat(d)))}),a.on("error",c)})}n(readBody,"readBody");function serveBackend(a){const e=readEnv(process.env),s={pluginId:e.pluginId,tenantId:e.tenantId,db:createScopedDb(e.databaseUrl),...createHostClient(e)},c=http.createServer((i,u)=>{(async()=>{try{const E=(i.url??"/").split("?")[0];if(E===e.healthPath){u.writeHead(200,{"content-type":"application/json"}),u.end('{"status":"ok"}');return}if(i.headers["x-tego-plugin-storage-policy"]==="1"){const v=await readBody(i,16384),I=n(T=>typeof i.headers[T]=="string"?i.headers[T]:"","header"),P={installId:I("x-tego-plugin-install-id"),tenantId:I("x-tego-plugin-tenant-id"),issuedAt:I("x-tego-plugin-issued-at"),bodyHash:I("x-tego-plugin-body-hash")};if(E!==chunkIMAVYQ4U_cjs.PLUGIN_STORAGE_POLICY_PATH||i.method!=="POST"||!P.installId||!P.tenantId||!chunkIMAVYQ4U_cjs.verifyPluginStoragePolicy({context:P,signature:I("x-tego-plugin-signature"),key:e.gatewayKey,nowMs:Date.now(),body:Buffer.from(v).toString("utf8")})){u.writeHead(401),u.end();return}if(!a.authorizeStorage){u.writeHead(404),u.end();return}await writeWebResponse(u,await a.authorizeStorage(toWebRequest(i,v),P,s));return}if(i.headers[chunkBN6TGHSB_cjs.PLUGIN_CONTEXT_HEADERS.public]==="1"){const v=readPublicContext(i.headers,{key:e.gatewayKey,nowMs:Date.now()});if(!v){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}if(!a.fetchPublic){u.writeHead(404,{"content-type":"application/json"}),u.end('{"error":"not found"}');return}const I=await readBody(i);await writeWebResponse(u,await a.fetchPublic(toWebRequest(i,I),v,s));return}const m=readUserContext(i.headers,{key:e.gatewayKey,nowMs:Date.now()});if(!m){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}const f=await readBody(i),A=await a.fetch(toWebRequest(i,f),m,s);await writeWebResponse(u,A)}catch(E){s.log.error("Unhandled error in plugin backend",{error:E instanceof Error?E.message:String(E)}),u.headersSent?u.end():(u.writeHead(500,{"content-type":"application/json"}),u.end('{"error":"plugin backend failed"}'))}})()});let d=!1,l=!1,w;const h=n(()=>(w??=Promise.resolve().then(()=>a.stop?.()),w),"stopModule"),y=(async()=>{const i=await startUp(s,e);if(i)throw new Error(i);d||(l=!0,await a.start?.(s),!d&&c.listen(e.port,()=>{s.log.info(`Plugin backend listening on ${e.port}`)}))})();y.catch(async i=>{console.error("Plugin backend startup failed",i);try{l&&await h()}catch(u){console.error("Plugin backend shutdown failed",u)}process.exit(1)}),process.on("SIGTERM",()=>{d||(d=!0,Promise.all([new Promise(i=>c.close(()=>i())),y.then(async()=>{l&&await h()})]).then(()=>process.exit(0)).catch(i=>{console.error("Plugin backend shutdown failed",i),process.exit(1)}))})}n(serveBackend,"serveBackend");async function startUp(a,e){const s=await checkDatabaseReachable(a.db,e.databaseUrl);if(s)return s;try{await a.config.refresh()}catch(c){return`Plugin backend cannot read its configuration from the host API: ${c instanceof Error?c.message:String(c)}`}return null}n(startUp,"startUp");async function checkDatabaseReachable(a,e){try{return await a.query("select 1"),null}catch(s){return`Plugin backend cannot reach its database at ${describeDatabaseTarget(e)}: ${s instanceof Error?s.message:String(s)}`}}n(checkDatabaseReachable,"checkDatabaseReachable");function describeDatabaseTarget(a){try{const e=new URL(a);return`${e.host}${e.pathname}`}catch{return"the address in DATABASE_URL"}}n(describeDatabaseTarget,"describeDatabaseTarget");function createMaintenance(a,e={}){const s=e.intervalMs??3e4,c=[];let d,l,w=!0;const h=n(i=>{w||(d&&clearTimeout(d),d=setTimeout(()=>void y(),i))},"schedule"),y=n(async()=>{if(d=void 0,l)return h(s);l=(async()=>{for(const i of c){if(w)break;try{await i.run()}catch(u){a.log.error(`maintenance step ${i.name} failed`,{error:u instanceof Error?u.message:String(u)})}}})(),await l,l=void 0,h(s)},"tick");return{step(i,u){c.push({name:i,run:u})},start(){w&&(w=!1,h(0))},wake(){h(0)},async stop(){w=!0,d&&clearTimeout(d),d=void 0,await l}}}n(createMaintenance,"createMaintenance"),exports.checkDatabaseReachable=checkDatabaseReachable,exports.createMaintenance=createMaintenance,exports.createScopedDb=createScopedDb,exports.readPublicContext=readPublicContext,exports.readUserContext=readUserContext,exports.serveBackend=serveBackend;
|
|
1
|
+
"use strict";var S=Object.defineProperty;var n=(o,t)=>S(o,"name",{value:t,configurable:!0});var chunkIMAVYQ4U_cjs=require("./chunk-IMAVYQ4U.cjs"),chunkSR5V7ZC2_cjs=require("./chunk-SR5V7ZC2.cjs");require("./chunk-66LDWN4T.cjs");var http=require("http");function toArrayBuffer(o){const t=new ArrayBuffer(o.byteLength);return new Uint8Array(t).set(o),t}n(toArrayBuffer,"toArrayBuffer");function readEnv(o){const t=n(s=>{const c=o[s];if(!c)throw new Error(`${s} is required but was not set`);return c},"require_");return{pluginId:t("TEGO_PLUGIN_ID"),tenantId:t("TEGO_TENANT_ID"),port:Number(t("TEGO_PLUGIN_PORT")),healthPath:o.TEGO_PLUGIN_HEALTH_PATH??"/healthz",hostApiUrl:t("TEGO_PLUGIN_HOST_API_URL"),hostApiToken:t("TEGO_PLUGIN_HOST_API_TOKEN"),databaseUrl:t("DATABASE_URL"),gatewayKey:t("TEGO_PLUGIN_GATEWAY_KEY")}}n(readEnv,"readEnv");function readUserContext(o,t){const s=n(f=>{const A=o[f],v=Array.isArray(A)?A[0]:A;return v&&v.length>0?v:null},"read"),c=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.userId),d=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.tenantId);if(!c||!d)return null;const l=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.signature),w=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.issuedAt);if(!l||!w)return null;const h=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.avatarId),y=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.roles),i=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.delegation),u={userId:c,tenantId:d,rolesHeader:y??"",avatarId:h??"",issuedAt:w,...i?{delegationHeader:i}:{}};if(!chunkIMAVYQ4U_cjs.verifyPluginContext({context:u,signature:l,key:t.key,nowMs:t.nowMs}))return null;let E=[];if(y)try{const f=JSON.parse(y);if(!Array.isArray(f))return null;E=f.filter(A=>typeof A=="string")}catch{return null}let m;if(i){if(!h)return null;try{const f=JSON.parse(i);if(!f||typeof f.id!="string"||!f.id||!Array.isArray(f.actions)||f.actions.some(A=>A!=="records.read"&&A!=="work.prepare"))return null;m={id:f.id,actions:f.actions}}catch{return null}}return{userId:c,tenantId:d,roles:E,...h?{avatarId:h}:{},...m?{delegation:m}:{}}}n(readUserContext,"readUserContext");function readPublicContext(o,t){const s=n(E=>{const m=o[E],f=Array.isArray(m)?m[0]:m;return f&&f.length>0?f:null},"read"),c=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.tenantId),d=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.installId),l=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.publicRoute),w=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.clientIp),h=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.avatarId),y=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.issuedAt),i=s(chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.signature);if(!c||!d||!l||!w||!y||!i)return null;const u={tenantId:c,installId:d,route:l,clientIp:w,...h?{avatarId:h}:{}};return chunkIMAVYQ4U_cjs.verifyPluginPublicContext({context:{...u,issuedAt:y},signature:i,key:t.key,nowMs:t.nowMs})?u:null}n(readPublicContext,"readPublicContext");function createHostClient(o){const t=n(async(e,a)=>{const r=await fetch(`${o.hostApiUrl}${e}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${o.hostApiToken}`},body:JSON.stringify(a),...e.startsWith("/knowledge/collections/")||e.startsWith("/knowledge/admin/")?{signal:AbortSignal.timeout(12e4)}:e==="/mail/send"?{signal:AbortSignal.timeout(6e4)}:e.startsWith("/directory/")||e.startsWith("/knowledge/")||e.startsWith("/delegations/")||e.startsWith("/proactive/")||e==="/mail/status"||e==="/mail/unsubscribes"||e==="/events"?{signal:AbortSignal.timeout(1e4)}:{}});if(!r.ok){const p=await r.text();let g;try{if(g=JSON.parse(p)?.error?.details,typeof g=="string")try{g=JSON.parse(g)}catch{}}catch{}throw Object.assign(new Error(`Tego host API ${e} failed: ${r.status} ${p}`),{status:r.status,details:g,retryAfter:r.headers.get("retry-after")})}return r},"call"),s={debug:n((e,a)=>void c("debug",e,a),"debug"),info:n((e,a)=>void c("info",e,a),"info"),warn:n((e,a)=>void c("warn",e,a),"warn"),error:n((e,a)=>void c("error",e,a),"error")};async function c(e,a,r){try{await t("/log",{level:e,message:a,fields:r})}catch{}}n(c,"emitLog");const d=n((e,a)=>`${o.hostApiUrl}/storage/${e}?key=${encodeURIComponent(a)}`,"storageUrl"),l={copy:n(async(e,a)=>{const p=await(await t("/storage/copy",{sourceKey:e,destinationKey:a})).json();if(!p.data)throw new Error("Tego host API returned no copied object");return p.data},"copy"),getStream:n(async e=>{const a=await fetch(d("stream",e),{headers:{authorization:`Bearer ${o.hostApiToken}`}});if(a.status===404)return null;if(!a.ok)throw new Error(`Tego storage stream failed: ${a.status}`);return a.body},"getStream"),putStream:n(async(e,a,r)=>{const p={method:"POST",duplex:"half",body:a,headers:{authorization:`Bearer ${o.hostApiToken}`,"content-length":String(r.sizeBytes),"content-type":r.contentType??"application/octet-stream"}},g=await fetch(d("stream",e),p);if(!g.ok)throw new Error(`Tego storage stream write failed: ${g.status}`)},"putStream"),put:n(async(e,a,r)=>{const p=await fetch(d("put",e),{method:"POST",headers:{authorization:`Bearer ${o.hostApiToken}`,"content-type":r??"application/octet-stream"},body:toArrayBuffer(a)});if(!p.ok)throw new Error(`Tego storage put failed: ${p.status}`)},"put"),get:n(async(e,a)=>{const r=a?.firstBytes,p=d("get",e),g=await fetch(r===void 0?p:`${p}&bytes=${r}`,{headers:{authorization:`Bearer ${o.hostApiToken}`}});if(g.status===404)return null;if(!g.ok)throw new Error(`Tego storage get failed: ${g.status}`);return new Uint8Array(await g.arrayBuffer())},"get"),head:n(async e=>{const a=await fetch(`${o.hostApiUrl}/storage/head`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${o.hostApiToken}`},body:JSON.stringify({key:e})});if(a.status===404)return null;if(!a.ok)throw new Error(`Tego storage head failed: ${a.status}`);const r=await a.json();if(!r.data)throw new Error("Tego host API returned no object head");return r.data},"head"),delete:n(async e=>{await t("/storage/delete",{key:e})},"delete"),signedUrl:n(async(e,a)=>{const g=(await(await t("/storage/signed-url",{key:e,ttlSeconds:a})).json()).data?.url;if(!g)throw new Error("Tego host API returned no signed url");return g},"signedUrl"),signedPath:n(async(e,a)=>{const g=(await(await t("/storage/signed-url",{key:e,ttlSeconds:a})).json()).data?.path;if(!g)throw new Error("Tego host API returned no signed path");return g},"signedPath"),managedPath:n(async(e,a,r)=>{const g=await(await t("/storage/signed-url",{key:e,policy:a,ttlSeconds:r})).json();if(!g.data?.path)throw new Error("Tego host API returned no managed path");return g.data.path},"managedPath"),uploadPath:n(async(e,a)=>{const p=await(await t("/storage/upload-url",{key:e,maxBytes:a?.maxBytes,ttlSeconds:a?.ttlSeconds})).json();if(!p.data?.path)throw new Error("Tego host API returned no upload path");return p.data},"uploadPath")},w={publish:n(async(e,a)=>{await t("/events",{name:e,payload:a})},"publish")},h={send:n(async e=>{const r=await(await t("/notifications",e)).json();if(!r.data?.id)throw new Error("Tego host API returned no notification id");return{id:r.data.id}},"send")},y={async emit(e){const r=await(await t("/proactive/emit",e)).json();if(!r.data)throw new Error("Tego proactive response is missing data");return r.data}},i=n(async(e,a)=>{const p=await(await t(e,a)).json();if(!p.data)throw new Error("Tego attention response is missing data");return p.data},"attentionStatus"),u={async request(e){const r=await(await t("/attention/requests",e)).json();if(!r.data?.itemId)throw new Error("Tego host API returned no attention item");return r.data},get:n(e=>i("/attention/requests/get",{itemId:e}),"get"),cancel:n(e=>i("/attention/requests/cancel",{itemId:e}),"cancel")},E={async send(e){const r=await(await t("/mail/send",e)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async status(e){const r=await(await t("/mail/status",{userId:e})).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async unsubscribes(e={}){const r=await(await t("/mail/unsubscribes",e)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data}};let m={};const A={current:n(()=>m,"current"),refresh:n(async()=>{const e=await fetch(`${o.hostApiUrl}/config`,{headers:{authorization:`Bearer ${o.hostApiToken}`}});if(!e.ok)throw new Error(`Tego host API /config failed: ${e.status} ${await e.text()}`);return m=(await e.json()).data?.values??{},m},"refresh")},v={async read(e,a){return(await(await t("/sources/read",{id:e,...a})).json()).data},async latestUserMessage(e){return(await(await t("/sources/latest-user-message",e)).json()).data}},I={async list(e){const r=await(await t("/delegations/list",{userId:e})).json();if(!r.data)throw new Error("Tego delegation response is missing data");return r.data}},P={async verify(e){const r=await(await t("/knowledge/verify",e)).json();if(!r.data)throw new Error("Tego knowledge response is missing data");return r.data},collections:{ensure:n(e=>T("ensure",e),"ensure"),permissions:n(e=>T("permissions",e),"permissions"),move:n(e=>T("move",e),"move"),access:n(e=>T("access",e),"access"),import:n(e=>T("import",e),"import"),importFiles:n(e=>T("import-files",e),"importFiles"),status:n(e=>T("status",e),"status"),delete:n(e=>T("delete",e),"delete"),documentsStatus:n(e=>T("documents-status",e),"documentsStatus"),documentContent:n(e=>T("document-content",e),"documentContent"),search:n(e=>T("search",e),"search"),remove:n(e=>T("remove",e),"remove")}};async function T(e,a){const p=await(await t(`/knowledge/collections/${e}`,a)).json();if(!p.data)throw new Error("Tego knowledge collection response is missing data");return p.data}n(T,"collectionCall");const _={async identity(e){const r=await(await t("/directory/identity",{userId:e})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async validate(e){const r=await(await t("/directory/validate",{principals:e})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async list(e){const r=await(await t("/directory/list",e)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async match(e){const r=await(await t("/directory/match",e)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data}},k={provisionUser:n(e=>b("/accounts/provision",e),"provisionUser"),resetPassword:n(e=>b("/accounts/password/reset",e),"resetPassword"),inviteUser:n(e=>b("/accounts/invite",e),"inviteUser"),getInvitation:n(e=>b("/accounts/get",{invitationId:e}),"getInvitation"),resendInvitation:n(e=>b("/accounts/resend",{invitationId:e}),"resendInvitation")};async function b(e,a){const p=await(await t(e,a)).json();if(!p.data)throw new Error("Tego account response is missing data");return p.data}return n(b,"collectionEnvelope"),{accounts:k,log:s,storage:l,diagrams:{status:n(async()=>{const a=await(await t("/diagrams/status",{})).json();if(!a.data)throw new Error("Tego host API returned no renderer status");return a.data},"status"),render:n(async e=>{const r=await(await t("/diagrams/render",e)).json();if(!r.data?.key)throw new Error("Tego host API returned no diagram artifact");return r.data},"render")},events:w,notifications:h,proactive:y,attention:u,mail:E,config:A,sources:v,directory:_,knowledge:P,knowledgeAdmin:{listManageableBases:n(e=>b("/knowledge/admin/list",e),"listManageableBases"),previewCreateBase:n(e=>b("/knowledge/admin/create-preview",e),"previewCreateBase"),createApprovedBase:n(e=>b("/knowledge/admin/create",e),"createApprovedBase"),prepareDocumentContent:n(e=>b("/knowledge/admin/prepare",e),"prepareDocumentContent"),previewDocumentBatch:n(e=>b("/knowledge/admin/preview",e),"previewDocumentBatch"),stageApprovedDocumentBatch:n(e=>b("/knowledge/admin/import",e),"stageApprovedDocumentBatch"),getTask:n(e=>b("/knowledge/admin/task",e),"getTask")},delegations:I}}n(createHostClient,"createHostClient");var ACQUIRE_TIMEOUT_MS=5e3,IDLE_IN_TRANSACTION_TIMEOUT_MS=15e3;function createScopedDb(o){let t=null;async function s(){if(t)return t;const c=await import("pg"),d=c.default?.Pool??c.Pool;if(!d)throw new Error('The "pg" module resolved without a Pool constructor. The plugin runtime expects the driver the runner image provides.');return t=new d({connectionString:o,connectionTimeoutMillis:ACQUIRE_TIMEOUT_MS}),t}return n(s,"ensurePool"),{query:n(async(c,d)=>(await(await s()).query(c,d)).rows,"query"),transaction:n(async c=>{const l=await(await s()).connect();let w=!0,h=!1;const y={query:n(async(i,u)=>{if(h)throw new Error("This transaction has already ended; its `tx` cannot be used afterwards.");return(await l.query(i,u)).rows},"query")};try{await l.query("BEGIN"),await l.query(`SET LOCAL idle_in_transaction_session_timeout = ${IDLE_IN_TRANSACTION_TIMEOUT_MS}`);const i=await c(y);return await l.query("COMMIT"),i}catch(i){try{await l.query("ROLLBACK")}catch{w=!1}throw i}finally{h=!0,l.release(w?void 0:!0)}},"transaction")}}n(createScopedDb,"createScopedDb");function toWebRequest(o,t){const s=`http://localhost${o.url??"/"}`,c=new Headers;for(const[l,w]of Object.entries(o.headers))w!==void 0&&c.set(l,Array.isArray(w)?w.join(", "):w);const d=o.method??"GET";return new Request(s,{method:d,headers:c,...d==="GET"||d==="HEAD"?{}:{body:t}})}n(toWebRequest,"toWebRequest");async function writeWebResponse(o,t){const s={};t.headers.forEach((c,d)=>{s[d]=c}),o.writeHead(t.status,s),o.end(Buffer.from(await t.arrayBuffer()))}n(writeWebResponse,"writeWebResponse");function readBody(o,t){return new Promise((s,c)=>{const d=[];let l=0;o.on("data",w=>{if(l+=w.length,t!==void 0&&l>t){c(new Error("Policy request body too large")),o.destroy();return}d.push(w)}),o.on("end",()=>{s(toArrayBuffer(Buffer.concat(d)))}),o.on("error",c)})}n(readBody,"readBody");function serveBackend(o){const t=readEnv(process.env),s={pluginId:t.pluginId,tenantId:t.tenantId,db:createScopedDb(t.databaseUrl),...createHostClient(t)},c=http.createServer((i,u)=>{(async()=>{try{const E=(i.url??"/").split("?")[0];if(E===t.healthPath){u.writeHead(200,{"content-type":"application/json"}),u.end('{"status":"ok"}');return}if(i.headers["x-tego-plugin-storage-policy"]==="1"){const v=await readBody(i,16384),I=n(T=>typeof i.headers[T]=="string"?i.headers[T]:"","header"),P={installId:I("x-tego-plugin-install-id"),tenantId:I("x-tego-plugin-tenant-id"),issuedAt:I("x-tego-plugin-issued-at"),bodyHash:I("x-tego-plugin-body-hash")};if(E!==chunkIMAVYQ4U_cjs.PLUGIN_STORAGE_POLICY_PATH||i.method!=="POST"||!P.installId||!P.tenantId||!chunkIMAVYQ4U_cjs.verifyPluginStoragePolicy({context:P,signature:I("x-tego-plugin-signature"),key:t.gatewayKey,nowMs:Date.now(),body:Buffer.from(v).toString("utf8")})){u.writeHead(401),u.end();return}if(!o.authorizeStorage){u.writeHead(404),u.end();return}await writeWebResponse(u,await o.authorizeStorage(toWebRequest(i,v),P,s));return}if(i.headers[chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS.public]==="1"){const v=readPublicContext(i.headers,{key:t.gatewayKey,nowMs:Date.now()});if(!v){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}if(!o.fetchPublic){u.writeHead(404,{"content-type":"application/json"}),u.end('{"error":"not found"}');return}const I=await readBody(i);await writeWebResponse(u,await o.fetchPublic(toWebRequest(i,I),v,s));return}const m=readUserContext(i.headers,{key:t.gatewayKey,nowMs:Date.now()});if(!m){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}const f=await readBody(i),A=await o.fetch(toWebRequest(i,f),m,s);await writeWebResponse(u,A)}catch(E){s.log.error("Unhandled error in plugin backend",{error:E instanceof Error?E.message:String(E)}),u.headersSent?u.end():(u.writeHead(500,{"content-type":"application/json"}),u.end('{"error":"plugin backend failed"}'))}})()});let d=!1,l=!1,w;const h=n(()=>(w??=Promise.resolve().then(()=>o.stop?.()),w),"stopModule"),y=(async()=>{const i=await startUp(s,t);if(i)throw new Error(i);d||(l=!0,await o.start?.(s),!d&&c.listen(t.port,()=>{s.log.info(`Plugin backend listening on ${t.port}`)}))})();y.catch(async i=>{console.error("Plugin backend startup failed",i);try{l&&await h()}catch(u){console.error("Plugin backend shutdown failed",u)}process.exit(1)}),process.on("SIGTERM",()=>{d||(d=!0,Promise.all([new Promise(i=>c.close(()=>i())),y.then(async()=>{l&&await h()})]).then(()=>process.exit(0)).catch(i=>{console.error("Plugin backend shutdown failed",i),process.exit(1)}))})}n(serveBackend,"serveBackend");async function startUp(o,t){const s=await checkDatabaseReachable(o.db,t.databaseUrl);if(s)return s;try{await o.config.refresh()}catch(c){return`Plugin backend cannot read its configuration from the host API: ${c instanceof Error?c.message:String(c)}`}return null}n(startUp,"startUp");async function checkDatabaseReachable(o,t){try{return await o.query("select 1"),null}catch(s){return`Plugin backend cannot reach its database at ${describeDatabaseTarget(t)}: ${s instanceof Error?s.message:String(s)}`}}n(checkDatabaseReachable,"checkDatabaseReachable");function describeDatabaseTarget(o){try{const t=new URL(o);return`${t.host}${t.pathname}`}catch{return"the address in DATABASE_URL"}}n(describeDatabaseTarget,"describeDatabaseTarget");function createMaintenance(o,t={}){const s=t.intervalMs??3e4,c=[];let d,l,w=!0;const h=n(i=>{w||(d&&clearTimeout(d),d=setTimeout(()=>void y(),i))},"schedule"),y=n(async()=>{if(d=void 0,l)return h(s);l=(async()=>{for(const i of c){if(w)break;try{await i.run()}catch(u){o.log.error(`maintenance step ${i.name} failed`,{error:u instanceof Error?u.message:String(u)})}}})(),await l,l=void 0,h(s)},"tick");return{step(i,u){c.push({name:i,run:u})},start(){w&&(w=!1,h(0))},wake(){h(0)},async stop(){w=!0,d&&clearTimeout(d),d=void 0,await l}}}n(createMaintenance,"createMaintenance"),exports.checkDatabaseReachable=checkDatabaseReachable,exports.createMaintenance=createMaintenance,exports.createScopedDb=createScopedDb,exports.readPublicContext=readPublicContext,exports.readUserContext=readUserContext,exports.serveBackend=serveBackend;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PluginUserContext } from './frontend.cjs';
|
|
2
2
|
import { PluginScopedDb, PluginHostApi, PluginPublicContext, PluginBackendModule } from './server.cjs';
|
|
3
3
|
import 'zod';
|
|
4
|
+
import './decision-card-IF2c4wvM.cjs';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Runs a backend part: the bridge between the container it lives in and the
|
package/dist/server-runtime.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PluginUserContext } from './frontend.js';
|
|
2
2
|
import { PluginScopedDb, PluginHostApi, PluginPublicContext, PluginBackendModule } from './server.js';
|
|
3
3
|
import 'zod';
|
|
4
|
+
import './decision-card-IF2c4wvM.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Runs a backend part: the bridge between the container it lives in and the
|
package/dist/server-runtime.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var H=Object.defineProperty;var n=(a,e)=>H(a,"name",{value:e,configurable:!0});import{verifyPluginContext as L,verifyPluginPublicContext as M,PLUGIN_STORAGE_POLICY_PATH as C,verifyPluginStoragePolicy as R}from"./chunk-WLTASJF6.js";import{PLUGIN_CONTEXT_HEADERS as T}from"./chunk-QKSPPMVN.js";import{createServer as D}from"http";function j(a){const e=new ArrayBuffer(a.byteLength);return new Uint8Array(e).set(a),e}n(j,"toArrayBuffer");function z(a){const e=n(s=>{const c=a[s];if(!c)throw new Error(`${s} is required but was not set`);return c},"require_");return{pluginId:e("TEGO_PLUGIN_ID"),tenantId:e("TEGO_TENANT_ID"),port:Number(e("TEGO_PLUGIN_PORT")),healthPath:a.TEGO_PLUGIN_HEALTH_PATH??"/healthz",hostApiUrl:e("TEGO_PLUGIN_HOST_API_URL"),hostApiToken:e("TEGO_PLUGIN_HOST_API_TOKEN"),databaseUrl:e("DATABASE_URL"),gatewayKey:e("TEGO_PLUGIN_GATEWAY_KEY")}}n(z,"readEnv");function O(a,e){const s=n(f=>{const A=a[f],I=Array.isArray(A)?A[0]:A;return I&&I.length>0?I:null},"read"),c=s(T.userId),d=s(T.tenantId);if(!c||!d)return null;const l=s(T.signature),w=s(T.issuedAt);if(!l||!w)return null;const h=s(T.avatarId),y=s(T.roles),i=s(T.delegation),u={userId:c,tenantId:d,rolesHeader:y??"",avatarId:h??"",issuedAt:w,...i?{delegationHeader:i}:{}};if(!L({context:u,signature:l,key:e.key,nowMs:e.nowMs}))return null;let b=[];if(y)try{const f=JSON.parse(y);if(!Array.isArray(f))return null;b=f.filter(A=>typeof A=="string")}catch{return null}let v;if(i){if(!h)return null;try{const f=JSON.parse(i);if(!f||typeof f.id!="string"||!f.id||!Array.isArray(f.actions)||f.actions.some(A=>A!=="records.read"&&A!=="work.prepare"))return null;v={id:f.id,actions:f.actions}}catch{return null}}return{userId:c,tenantId:d,roles:b,...h?{avatarId:h}:{},...v?{delegation:v}:{}}}n(O,"readUserContext");function U(a,e){const s=n(b=>{const v=a[b],f=Array.isArray(v)?v[0]:v;return f&&f.length>0?f:null},"read"),c=s(T.tenantId),d=s(T.installId),l=s(T.publicRoute),w=s(T.clientIp),h=s(T.avatarId),y=s(T.issuedAt),i=s(T.signature);if(!c||!d||!l||!w||!y||!i)return null;const u={tenantId:c,installId:d,route:l,clientIp:w,...h?{avatarId:h}:{}};return M({context:{...u,issuedAt:y},signature:i,key:e.key,nowMs:e.nowMs})?u:null}n(U,"readPublicContext");function W(a){const e=n(async(t,o)=>{const r=await fetch(`${a.hostApiUrl}${t}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a.hostApiToken}`},body:JSON.stringify(o),...t.startsWith("/knowledge/collections/")||t.startsWith("/knowledge/admin/")?{signal:AbortSignal.timeout(12e4)}:t==="/mail/send"?{signal:AbortSignal.timeout(6e4)}:t.startsWith("/directory/")||t.startsWith("/knowledge/")||t.startsWith("/delegations/")||t.startsWith("/proactive/")||t==="/mail/status"||t==="/mail/unsubscribes"||t==="/events"?{signal:AbortSignal.timeout(1e4)}:{}});if(!r.ok){const p=await r.text();let g;try{if(g=JSON.parse(p)?.error?.details,typeof g=="string")try{g=JSON.parse(g)}catch{}}catch{}throw Object.assign(new Error(`Tego host API ${t} failed: ${r.status} ${p}`),{status:r.status,details:g,retryAfter:r.headers.get("retry-after")})}return r},"call"),s={debug:n((t,o)=>void c("debug",t,o),"debug"),info:n((t,o)=>void c("info",t,o),"info"),warn:n((t,o)=>void c("warn",t,o),"warn"),error:n((t,o)=>void c("error",t,o),"error")};async function c(t,o,r){try{await e("/log",{level:t,message:o,fields:r})}catch{}}n(c,"emitLog");const d=n((t,o)=>`${a.hostApiUrl}/storage/${t}?key=${encodeURIComponent(o)}`,"storageUrl"),l={copy:n(async(t,o)=>{const p=await(await e("/storage/copy",{sourceKey:t,destinationKey:o})).json();if(!p.data)throw new Error("Tego host API returned no copied object");return p.data},"copy"),getStream:n(async t=>{const o=await fetch(d("stream",t),{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(o.status===404)return null;if(!o.ok)throw new Error(`Tego storage stream failed: ${o.status}`);return o.body},"getStream"),putStream:n(async(t,o,r)=>{const p={method:"POST",duplex:"half",body:o,headers:{authorization:`Bearer ${a.hostApiToken}`,"content-length":String(r.sizeBytes),"content-type":r.contentType??"application/octet-stream"}},g=await fetch(d("stream",t),p);if(!g.ok)throw new Error(`Tego storage stream write failed: ${g.status}`)},"putStream"),put:n(async(t,o,r)=>{const p=await fetch(d("put",t),{method:"POST",headers:{authorization:`Bearer ${a.hostApiToken}`,"content-type":r??"application/octet-stream"},body:j(o)});if(!p.ok)throw new Error(`Tego storage put failed: ${p.status}`)},"put"),get:n(async(t,o)=>{const r=o?.firstBytes,p=d("get",t),g=await fetch(r===void 0?p:`${p}&bytes=${r}`,{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(g.status===404)return null;if(!g.ok)throw new Error(`Tego storage get failed: ${g.status}`);return new Uint8Array(await g.arrayBuffer())},"get"),head:n(async t=>{const o=await fetch(`${a.hostApiUrl}/storage/head`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a.hostApiToken}`},body:JSON.stringify({key:t})});if(o.status===404)return null;if(!o.ok)throw new Error(`Tego storage head failed: ${o.status}`);const r=await o.json();if(!r.data)throw new Error("Tego host API returned no object head");return r.data},"head"),delete:n(async t=>{await e("/storage/delete",{key:t})},"delete"),signedUrl:n(async(t,o)=>{const g=(await(await e("/storage/signed-url",{key:t,ttlSeconds:o})).json()).data?.url;if(!g)throw new Error("Tego host API returned no signed url");return g},"signedUrl"),signedPath:n(async(t,o)=>{const g=(await(await e("/storage/signed-url",{key:t,ttlSeconds:o})).json()).data?.path;if(!g)throw new Error("Tego host API returned no signed path");return g},"signedPath"),managedPath:n(async(t,o,r)=>{const g=await(await e("/storage/signed-url",{key:t,policy:o,ttlSeconds:r})).json();if(!g.data?.path)throw new Error("Tego host API returned no managed path");return g.data.path},"managedPath"),uploadPath:n(async(t,o)=>{const p=await(await e("/storage/upload-url",{key:t,maxBytes:o?.maxBytes,ttlSeconds:o?.ttlSeconds})).json();if(!p.data?.path)throw new Error("Tego host API returned no upload path");return p.data},"uploadPath")},w={publish:n(async(t,o)=>{await e("/events",{name:t,payload:o})},"publish")},h={send:n(async t=>{const r=await(await e("/notifications",t)).json();if(!r.data?.id)throw new Error("Tego host API returned no notification id");return{id:r.data.id}},"send")},y={async emit(t){const r=await(await e("/proactive/emit",t)).json();if(!r.data)throw new Error("Tego proactive response is missing data");return r.data}},i=n(async(t,o)=>{const p=await(await e(t,o)).json();if(!p.data)throw new Error("Tego attention response is missing data");return p.data},"attentionStatus"),u={async request(t){const r=await(await e("/attention/requests",t)).json();if(!r.data?.itemId)throw new Error("Tego host API returned no attention item");return r.data},get:n(t=>i("/attention/requests/get",{itemId:t}),"get"),cancel:n(t=>i("/attention/requests/cancel",{itemId:t}),"cancel")},b={async send(t){const r=await(await e("/mail/send",t)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async status(t){const r=await(await e("/mail/status",{userId:t})).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async unsubscribes(t={}){const r=await(await e("/mail/unsubscribes",t)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data}};let v={};const A={current:n(()=>v,"current"),refresh:n(async()=>{const t=await fetch(`${a.hostApiUrl}/config`,{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(!t.ok)throw new Error(`Tego host API /config failed: ${t.status} ${await t.text()}`);return v=(await t.json()).data?.values??{},v},"refresh")},I={async read(t,o){return(await(await e("/sources/read",{id:t,...o})).json()).data}},P={async list(t){const r=await(await e("/delegations/list",{userId:t})).json();if(!r.data)throw new Error("Tego delegation response is missing data");return r.data}},k={async verify(t){const r=await(await e("/knowledge/verify",t)).json();if(!r.data)throw new Error("Tego knowledge response is missing data");return r.data},collections:{ensure:n(t=>m("ensure",t),"ensure"),permissions:n(t=>m("permissions",t),"permissions"),move:n(t=>m("move",t),"move"),access:n(t=>m("access",t),"access"),import:n(t=>m("import",t),"import"),importFiles:n(t=>m("import-files",t),"importFiles"),status:n(t=>m("status",t),"status"),delete:n(t=>m("delete",t),"delete"),documentsStatus:n(t=>m("documents-status",t),"documentsStatus"),documentContent:n(t=>m("document-content",t),"documentContent"),search:n(t=>m("search",t),"search"),remove:n(t=>m("remove",t),"remove")}};async function m(t,o){const p=await(await e(`/knowledge/collections/${t}`,o)).json();if(!p.data)throw new Error("Tego knowledge collection response is missing data");return p.data}n(m,"collectionCall");const N={async identity(t){const r=await(await e("/directory/identity",{userId:t})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async validate(t){const r=await(await e("/directory/validate",{principals:t})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async list(t){const r=await(await e("/directory/list",t)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async match(t){const r=await(await e("/directory/match",t)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data}},G={provisionUser:n(t=>E("/accounts/provision",t),"provisionUser"),resetPassword:n(t=>E("/accounts/password/reset",t),"resetPassword"),inviteUser:n(t=>E("/accounts/invite",t),"inviteUser"),getInvitation:n(t=>E("/accounts/get",{invitationId:t}),"getInvitation"),resendInvitation:n(t=>E("/accounts/resend",{invitationId:t}),"resendInvitation")};async function E(t,o){const p=await(await e(t,o)).json();if(!p.data)throw new Error("Tego account response is missing data");return p.data}return n(E,"collectionEnvelope"),{accounts:G,log:s,storage:l,diagrams:{status:n(async()=>{const o=await(await e("/diagrams/status",{})).json();if(!o.data)throw new Error("Tego host API returned no renderer status");return o.data},"status"),render:n(async t=>{const r=await(await e("/diagrams/render",t)).json();if(!r.data?.key)throw new Error("Tego host API returned no diagram artifact");return r.data},"render")},events:w,notifications:h,proactive:y,attention:u,mail:b,config:A,sources:I,directory:N,knowledge:k,knowledgeAdmin:{listManageableBases:n(t=>E("/knowledge/admin/list",t),"listManageableBases"),previewCreateBase:n(t=>E("/knowledge/admin/create-preview",t),"previewCreateBase"),createApprovedBase:n(t=>E("/knowledge/admin/create",t),"createApprovedBase"),prepareDocumentContent:n(t=>E("/knowledge/admin/prepare",t),"prepareDocumentContent"),previewDocumentBatch:n(t=>E("/knowledge/admin/preview",t),"previewDocumentBatch"),stageApprovedDocumentBatch:n(t=>E("/knowledge/admin/import",t),"stageApprovedDocumentBatch"),getTask:n(t=>E("/knowledge/admin/task",t),"getTask")},delegations:P}}n(W,"createHostClient");var K=5e3,J=15e3;function x(a){let e=null;async function s(){if(e)return e;const c=await import("pg"),d=c.default?.Pool??c.Pool;if(!d)throw new Error('The "pg" module resolved without a Pool constructor. The plugin runtime expects the driver the runner image provides.');return e=new d({connectionString:a,connectionTimeoutMillis:K}),e}return n(s,"ensurePool"),{query:n(async(c,d)=>(await(await s()).query(c,d)).rows,"query"),transaction:n(async c=>{const l=await(await s()).connect();let w=!0,h=!1;const y={query:n(async(i,u)=>{if(h)throw new Error("This transaction has already ended; its `tx` cannot be used afterwards.");return(await l.query(i,u)).rows},"query")};try{await l.query("BEGIN"),await l.query(`SET LOCAL idle_in_transaction_session_timeout = ${J}`);const i=await c(y);return await l.query("COMMIT"),i}catch(i){try{await l.query("ROLLBACK")}catch{w=!1}throw i}finally{h=!0,l.release(w?void 0:!0)}},"transaction")}}n(x,"createScopedDb");function S(a,e){const s=`http://localhost${a.url??"/"}`,c=new Headers;for(const[l,w]of Object.entries(a.headers))w!==void 0&&c.set(l,Array.isArray(w)?w.join(", "):w);const d=a.method??"GET";return new Request(s,{method:d,headers:c,...d==="GET"||d==="HEAD"?{}:{body:e}})}n(S,"toWebRequest");async function _(a,e){const s={};e.headers.forEach((c,d)=>{s[d]=c}),a.writeHead(e.status,s),a.end(Buffer.from(await e.arrayBuffer()))}n(_,"writeWebResponse");function $(a,e){return new Promise((s,c)=>{const d=[];let l=0;a.on("data",w=>{if(l+=w.length,e!==void 0&&l>e){c(new Error("Policy request body too large")),a.destroy();return}d.push(w)}),a.on("end",()=>{s(j(Buffer.concat(d)))}),a.on("error",c)})}n($,"readBody");function Y(a){const e=z(process.env),s={pluginId:e.pluginId,tenantId:e.tenantId,db:x(e.databaseUrl),...W(e)},c=D((i,u)=>{(async()=>{try{const b=(i.url??"/").split("?")[0];if(b===e.healthPath){u.writeHead(200,{"content-type":"application/json"}),u.end('{"status":"ok"}');return}if(i.headers["x-tego-plugin-storage-policy"]==="1"){const I=await $(i,16384),P=n(m=>typeof i.headers[m]=="string"?i.headers[m]:"","header"),k={installId:P("x-tego-plugin-install-id"),tenantId:P("x-tego-plugin-tenant-id"),issuedAt:P("x-tego-plugin-issued-at"),bodyHash:P("x-tego-plugin-body-hash")};if(b!==C||i.method!=="POST"||!k.installId||!k.tenantId||!R({context:k,signature:P("x-tego-plugin-signature"),key:e.gatewayKey,nowMs:Date.now(),body:Buffer.from(I).toString("utf8")})){u.writeHead(401),u.end();return}if(!a.authorizeStorage){u.writeHead(404),u.end();return}await _(u,await a.authorizeStorage(S(i,I),k,s));return}if(i.headers[T.public]==="1"){const I=U(i.headers,{key:e.gatewayKey,nowMs:Date.now()});if(!I){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}if(!a.fetchPublic){u.writeHead(404,{"content-type":"application/json"}),u.end('{"error":"not found"}');return}const P=await $(i);await _(u,await a.fetchPublic(S(i,P),I,s));return}const v=O(i.headers,{key:e.gatewayKey,nowMs:Date.now()});if(!v){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}const f=await $(i),A=await a.fetch(S(i,f),v,s);await _(u,A)}catch(b){s.log.error("Unhandled error in plugin backend",{error:b instanceof Error?b.message:String(b)}),u.headersSent?u.end():(u.writeHead(500,{"content-type":"application/json"}),u.end('{"error":"plugin backend failed"}'))}})()});let d=!1,l=!1,w;const h=n(()=>(w??=Promise.resolve().then(()=>a.stop?.()),w),"stopModule"),y=(async()=>{const i=await F(s,e);if(i)throw new Error(i);d||(l=!0,await a.start?.(s),!d&&c.listen(e.port,()=>{s.log.info(`Plugin backend listening on ${e.port}`)}))})();y.catch(async i=>{console.error("Plugin backend startup failed",i);try{l&&await h()}catch(u){console.error("Plugin backend shutdown failed",u)}process.exit(1)}),process.on("SIGTERM",()=>{d||(d=!0,Promise.all([new Promise(i=>c.close(()=>i())),y.then(async()=>{l&&await h()})]).then(()=>process.exit(0)).catch(i=>{console.error("Plugin backend shutdown failed",i),process.exit(1)}))})}n(Y,"serveBackend");async function F(a,e){const s=await B(a.db,e.databaseUrl);if(s)return s;try{await a.config.refresh()}catch(c){return`Plugin backend cannot read its configuration from the host API: ${c instanceof Error?c.message:String(c)}`}return null}n(F,"startUp");async function B(a,e){try{return await a.query("select 1"),null}catch(s){return`Plugin backend cannot reach its database at ${Q(e)}: ${s instanceof Error?s.message:String(s)}`}}n(B,"checkDatabaseReachable");function Q(a){try{const e=new URL(a);return`${e.host}${e.pathname}`}catch{return"the address in DATABASE_URL"}}n(Q,"describeDatabaseTarget");function X(a,e={}){const s=e.intervalMs??3e4,c=[];let d,l,w=!0;const h=n(i=>{w||(d&&clearTimeout(d),d=setTimeout(()=>void y(),i))},"schedule"),y=n(async()=>{if(d=void 0,l)return h(s);l=(async()=>{for(const i of c){if(w)break;try{await i.run()}catch(u){a.log.error(`maintenance step ${i.name} failed`,{error:u instanceof Error?u.message:String(u)})}}})(),await l,l=void 0,h(s)},"tick");return{step(i,u){c.push({name:i,run:u})},start(){w&&(w=!1,h(0))},wake(){h(0)},async stop(){w=!0,d&&clearTimeout(d),d=void 0,await l}}}n(X,"createMaintenance");export{B as checkDatabaseReachable,X as createMaintenance,x as createScopedDb,U as readPublicContext,O as readUserContext,Y as serveBackend};
|
|
1
|
+
var H=Object.defineProperty;var n=(a,e)=>H(a,"name",{value:e,configurable:!0});import{verifyPluginContext as L,verifyPluginPublicContext as M,PLUGIN_STORAGE_POLICY_PATH as C,verifyPluginStoragePolicy as R}from"./chunk-WLTASJF6.js";import{PLUGIN_CONTEXT_HEADERS as T}from"./chunk-CDJQ7OPA.js";import"./chunk-JV2G2Z33.js";import{createServer as D}from"http";function $(a){const e=new ArrayBuffer(a.byteLength);return new Uint8Array(e).set(a),e}n($,"toArrayBuffer");function z(a){const e=n(s=>{const c=a[s];if(!c)throw new Error(`${s} is required but was not set`);return c},"require_");return{pluginId:e("TEGO_PLUGIN_ID"),tenantId:e("TEGO_TENANT_ID"),port:Number(e("TEGO_PLUGIN_PORT")),healthPath:a.TEGO_PLUGIN_HEALTH_PATH??"/healthz",hostApiUrl:e("TEGO_PLUGIN_HOST_API_URL"),hostApiToken:e("TEGO_PLUGIN_HOST_API_TOKEN"),databaseUrl:e("DATABASE_URL"),gatewayKey:e("TEGO_PLUGIN_GATEWAY_KEY")}}n(z,"readEnv");function U(a,e){const s=n(f=>{const A=a[f],I=Array.isArray(A)?A[0]:A;return I&&I.length>0?I:null},"read"),c=s(T.userId),d=s(T.tenantId);if(!c||!d)return null;const l=s(T.signature),w=s(T.issuedAt);if(!l||!w)return null;const h=s(T.avatarId),y=s(T.roles),i=s(T.delegation),u={userId:c,tenantId:d,rolesHeader:y??"",avatarId:h??"",issuedAt:w,...i?{delegationHeader:i}:{}};if(!L({context:u,signature:l,key:e.key,nowMs:e.nowMs}))return null;let b=[];if(y)try{const f=JSON.parse(y);if(!Array.isArray(f))return null;b=f.filter(A=>typeof A=="string")}catch{return null}let v;if(i){if(!h)return null;try{const f=JSON.parse(i);if(!f||typeof f.id!="string"||!f.id||!Array.isArray(f.actions)||f.actions.some(A=>A!=="records.read"&&A!=="work.prepare"))return null;v={id:f.id,actions:f.actions}}catch{return null}}return{userId:c,tenantId:d,roles:b,...h?{avatarId:h}:{},...v?{delegation:v}:{}}}n(U,"readUserContext");function O(a,e){const s=n(b=>{const v=a[b],f=Array.isArray(v)?v[0]:v;return f&&f.length>0?f:null},"read"),c=s(T.tenantId),d=s(T.installId),l=s(T.publicRoute),w=s(T.clientIp),h=s(T.avatarId),y=s(T.issuedAt),i=s(T.signature);if(!c||!d||!l||!w||!y||!i)return null;const u={tenantId:c,installId:d,route:l,clientIp:w,...h?{avatarId:h}:{}};return M({context:{...u,issuedAt:y},signature:i,key:e.key,nowMs:e.nowMs})?u:null}n(O,"readPublicContext");function W(a){const e=n(async(t,o)=>{const r=await fetch(`${a.hostApiUrl}${t}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a.hostApiToken}`},body:JSON.stringify(o),...t.startsWith("/knowledge/collections/")||t.startsWith("/knowledge/admin/")?{signal:AbortSignal.timeout(12e4)}:t==="/mail/send"?{signal:AbortSignal.timeout(6e4)}:t.startsWith("/directory/")||t.startsWith("/knowledge/")||t.startsWith("/delegations/")||t.startsWith("/proactive/")||t==="/mail/status"||t==="/mail/unsubscribes"||t==="/events"?{signal:AbortSignal.timeout(1e4)}:{}});if(!r.ok){const p=await r.text();let g;try{if(g=JSON.parse(p)?.error?.details,typeof g=="string")try{g=JSON.parse(g)}catch{}}catch{}throw Object.assign(new Error(`Tego host API ${t} failed: ${r.status} ${p}`),{status:r.status,details:g,retryAfter:r.headers.get("retry-after")})}return r},"call"),s={debug:n((t,o)=>void c("debug",t,o),"debug"),info:n((t,o)=>void c("info",t,o),"info"),warn:n((t,o)=>void c("warn",t,o),"warn"),error:n((t,o)=>void c("error",t,o),"error")};async function c(t,o,r){try{await e("/log",{level:t,message:o,fields:r})}catch{}}n(c,"emitLog");const d=n((t,o)=>`${a.hostApiUrl}/storage/${t}?key=${encodeURIComponent(o)}`,"storageUrl"),l={copy:n(async(t,o)=>{const p=await(await e("/storage/copy",{sourceKey:t,destinationKey:o})).json();if(!p.data)throw new Error("Tego host API returned no copied object");return p.data},"copy"),getStream:n(async t=>{const o=await fetch(d("stream",t),{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(o.status===404)return null;if(!o.ok)throw new Error(`Tego storage stream failed: ${o.status}`);return o.body},"getStream"),putStream:n(async(t,o,r)=>{const p={method:"POST",duplex:"half",body:o,headers:{authorization:`Bearer ${a.hostApiToken}`,"content-length":String(r.sizeBytes),"content-type":r.contentType??"application/octet-stream"}},g=await fetch(d("stream",t),p);if(!g.ok)throw new Error(`Tego storage stream write failed: ${g.status}`)},"putStream"),put:n(async(t,o,r)=>{const p=await fetch(d("put",t),{method:"POST",headers:{authorization:`Bearer ${a.hostApiToken}`,"content-type":r??"application/octet-stream"},body:$(o)});if(!p.ok)throw new Error(`Tego storage put failed: ${p.status}`)},"put"),get:n(async(t,o)=>{const r=o?.firstBytes,p=d("get",t),g=await fetch(r===void 0?p:`${p}&bytes=${r}`,{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(g.status===404)return null;if(!g.ok)throw new Error(`Tego storage get failed: ${g.status}`);return new Uint8Array(await g.arrayBuffer())},"get"),head:n(async t=>{const o=await fetch(`${a.hostApiUrl}/storage/head`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a.hostApiToken}`},body:JSON.stringify({key:t})});if(o.status===404)return null;if(!o.ok)throw new Error(`Tego storage head failed: ${o.status}`);const r=await o.json();if(!r.data)throw new Error("Tego host API returned no object head");return r.data},"head"),delete:n(async t=>{await e("/storage/delete",{key:t})},"delete"),signedUrl:n(async(t,o)=>{const g=(await(await e("/storage/signed-url",{key:t,ttlSeconds:o})).json()).data?.url;if(!g)throw new Error("Tego host API returned no signed url");return g},"signedUrl"),signedPath:n(async(t,o)=>{const g=(await(await e("/storage/signed-url",{key:t,ttlSeconds:o})).json()).data?.path;if(!g)throw new Error("Tego host API returned no signed path");return g},"signedPath"),managedPath:n(async(t,o,r)=>{const g=await(await e("/storage/signed-url",{key:t,policy:o,ttlSeconds:r})).json();if(!g.data?.path)throw new Error("Tego host API returned no managed path");return g.data.path},"managedPath"),uploadPath:n(async(t,o)=>{const p=await(await e("/storage/upload-url",{key:t,maxBytes:o?.maxBytes,ttlSeconds:o?.ttlSeconds})).json();if(!p.data?.path)throw new Error("Tego host API returned no upload path");return p.data},"uploadPath")},w={publish:n(async(t,o)=>{await e("/events",{name:t,payload:o})},"publish")},h={send:n(async t=>{const r=await(await e("/notifications",t)).json();if(!r.data?.id)throw new Error("Tego host API returned no notification id");return{id:r.data.id}},"send")},y={async emit(t){const r=await(await e("/proactive/emit",t)).json();if(!r.data)throw new Error("Tego proactive response is missing data");return r.data}},i=n(async(t,o)=>{const p=await(await e(t,o)).json();if(!p.data)throw new Error("Tego attention response is missing data");return p.data},"attentionStatus"),u={async request(t){const r=await(await e("/attention/requests",t)).json();if(!r.data?.itemId)throw new Error("Tego host API returned no attention item");return r.data},get:n(t=>i("/attention/requests/get",{itemId:t}),"get"),cancel:n(t=>i("/attention/requests/cancel",{itemId:t}),"cancel")},b={async send(t){const r=await(await e("/mail/send",t)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async status(t){const r=await(await e("/mail/status",{userId:t})).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data},async unsubscribes(t={}){const r=await(await e("/mail/unsubscribes",t)).json();if(!r.data)throw new Error("Tego mail response is missing data");return r.data}};let v={};const A={current:n(()=>v,"current"),refresh:n(async()=>{const t=await fetch(`${a.hostApiUrl}/config`,{headers:{authorization:`Bearer ${a.hostApiToken}`}});if(!t.ok)throw new Error(`Tego host API /config failed: ${t.status} ${await t.text()}`);return v=(await t.json()).data?.values??{},v},"refresh")},I={async read(t,o){return(await(await e("/sources/read",{id:t,...o})).json()).data},async latestUserMessage(t){return(await(await e("/sources/latest-user-message",t)).json()).data}},P={async list(t){const r=await(await e("/delegations/list",{userId:t})).json();if(!r.data)throw new Error("Tego delegation response is missing data");return r.data}},k={async verify(t){const r=await(await e("/knowledge/verify",t)).json();if(!r.data)throw new Error("Tego knowledge response is missing data");return r.data},collections:{ensure:n(t=>m("ensure",t),"ensure"),permissions:n(t=>m("permissions",t),"permissions"),move:n(t=>m("move",t),"move"),access:n(t=>m("access",t),"access"),import:n(t=>m("import",t),"import"),importFiles:n(t=>m("import-files",t),"importFiles"),status:n(t=>m("status",t),"status"),delete:n(t=>m("delete",t),"delete"),documentsStatus:n(t=>m("documents-status",t),"documentsStatus"),documentContent:n(t=>m("document-content",t),"documentContent"),search:n(t=>m("search",t),"search"),remove:n(t=>m("remove",t),"remove")}};async function m(t,o){const p=await(await e(`/knowledge/collections/${t}`,o)).json();if(!p.data)throw new Error("Tego knowledge collection response is missing data");return p.data}n(m,"collectionCall");const N={async identity(t){const r=await(await e("/directory/identity",{userId:t})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async validate(t){const r=await(await e("/directory/validate",{principals:t})).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async list(t){const r=await(await e("/directory/list",t)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data},async match(t){const r=await(await e("/directory/match",t)).json();if(!r.data)throw new Error("Tego directory response is missing data");return r.data}},G={provisionUser:n(t=>E("/accounts/provision",t),"provisionUser"),resetPassword:n(t=>E("/accounts/password/reset",t),"resetPassword"),inviteUser:n(t=>E("/accounts/invite",t),"inviteUser"),getInvitation:n(t=>E("/accounts/get",{invitationId:t}),"getInvitation"),resendInvitation:n(t=>E("/accounts/resend",{invitationId:t}),"resendInvitation")};async function E(t,o){const p=await(await e(t,o)).json();if(!p.data)throw new Error("Tego account response is missing data");return p.data}return n(E,"collectionEnvelope"),{accounts:G,log:s,storage:l,diagrams:{status:n(async()=>{const o=await(await e("/diagrams/status",{})).json();if(!o.data)throw new Error("Tego host API returned no renderer status");return o.data},"status"),render:n(async t=>{const r=await(await e("/diagrams/render",t)).json();if(!r.data?.key)throw new Error("Tego host API returned no diagram artifact");return r.data},"render")},events:w,notifications:h,proactive:y,attention:u,mail:b,config:A,sources:I,directory:N,knowledge:k,knowledgeAdmin:{listManageableBases:n(t=>E("/knowledge/admin/list",t),"listManageableBases"),previewCreateBase:n(t=>E("/knowledge/admin/create-preview",t),"previewCreateBase"),createApprovedBase:n(t=>E("/knowledge/admin/create",t),"createApprovedBase"),prepareDocumentContent:n(t=>E("/knowledge/admin/prepare",t),"prepareDocumentContent"),previewDocumentBatch:n(t=>E("/knowledge/admin/preview",t),"previewDocumentBatch"),stageApprovedDocumentBatch:n(t=>E("/knowledge/admin/import",t),"stageApprovedDocumentBatch"),getTask:n(t=>E("/knowledge/admin/task",t),"getTask")},delegations:P}}n(W,"createHostClient");var K=5e3,J=15e3;function x(a){let e=null;async function s(){if(e)return e;const c=await import("pg"),d=c.default?.Pool??c.Pool;if(!d)throw new Error('The "pg" module resolved without a Pool constructor. The plugin runtime expects the driver the runner image provides.');return e=new d({connectionString:a,connectionTimeoutMillis:K}),e}return n(s,"ensurePool"),{query:n(async(c,d)=>(await(await s()).query(c,d)).rows,"query"),transaction:n(async c=>{const l=await(await s()).connect();let w=!0,h=!1;const y={query:n(async(i,u)=>{if(h)throw new Error("This transaction has already ended; its `tx` cannot be used afterwards.");return(await l.query(i,u)).rows},"query")};try{await l.query("BEGIN"),await l.query(`SET LOCAL idle_in_transaction_session_timeout = ${J}`);const i=await c(y);return await l.query("COMMIT"),i}catch(i){try{await l.query("ROLLBACK")}catch{w=!1}throw i}finally{h=!0,l.release(w?void 0:!0)}},"transaction")}}n(x,"createScopedDb");function S(a,e){const s=`http://localhost${a.url??"/"}`,c=new Headers;for(const[l,w]of Object.entries(a.headers))w!==void 0&&c.set(l,Array.isArray(w)?w.join(", "):w);const d=a.method??"GET";return new Request(s,{method:d,headers:c,...d==="GET"||d==="HEAD"?{}:{body:e}})}n(S,"toWebRequest");async function _(a,e){const s={};e.headers.forEach((c,d)=>{s[d]=c}),a.writeHead(e.status,s),a.end(Buffer.from(await e.arrayBuffer()))}n(_,"writeWebResponse");function j(a,e){return new Promise((s,c)=>{const d=[];let l=0;a.on("data",w=>{if(l+=w.length,e!==void 0&&l>e){c(new Error("Policy request body too large")),a.destroy();return}d.push(w)}),a.on("end",()=>{s($(Buffer.concat(d)))}),a.on("error",c)})}n(j,"readBody");function Y(a){const e=z(process.env),s={pluginId:e.pluginId,tenantId:e.tenantId,db:x(e.databaseUrl),...W(e)},c=D((i,u)=>{(async()=>{try{const b=(i.url??"/").split("?")[0];if(b===e.healthPath){u.writeHead(200,{"content-type":"application/json"}),u.end('{"status":"ok"}');return}if(i.headers["x-tego-plugin-storage-policy"]==="1"){const I=await j(i,16384),P=n(m=>typeof i.headers[m]=="string"?i.headers[m]:"","header"),k={installId:P("x-tego-plugin-install-id"),tenantId:P("x-tego-plugin-tenant-id"),issuedAt:P("x-tego-plugin-issued-at"),bodyHash:P("x-tego-plugin-body-hash")};if(b!==C||i.method!=="POST"||!k.installId||!k.tenantId||!R({context:k,signature:P("x-tego-plugin-signature"),key:e.gatewayKey,nowMs:Date.now(),body:Buffer.from(I).toString("utf8")})){u.writeHead(401),u.end();return}if(!a.authorizeStorage){u.writeHead(404),u.end();return}await _(u,await a.authorizeStorage(S(i,I),k,s));return}if(i.headers[T.public]==="1"){const I=O(i.headers,{key:e.gatewayKey,nowMs:Date.now()});if(!I){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}if(!a.fetchPublic){u.writeHead(404,{"content-type":"application/json"}),u.end('{"error":"not found"}');return}const P=await j(i);await _(u,await a.fetchPublic(S(i,P),I,s));return}const v=U(i.headers,{key:e.gatewayKey,nowMs:Date.now()});if(!v){u.writeHead(401,{"content-type":"application/json"}),u.end('{"error":"missing or unverifiable tego plugin context"}');return}const f=await j(i),A=await a.fetch(S(i,f),v,s);await _(u,A)}catch(b){s.log.error("Unhandled error in plugin backend",{error:b instanceof Error?b.message:String(b)}),u.headersSent?u.end():(u.writeHead(500,{"content-type":"application/json"}),u.end('{"error":"plugin backend failed"}'))}})()});let d=!1,l=!1,w;const h=n(()=>(w??=Promise.resolve().then(()=>a.stop?.()),w),"stopModule"),y=(async()=>{const i=await F(s,e);if(i)throw new Error(i);d||(l=!0,await a.start?.(s),!d&&c.listen(e.port,()=>{s.log.info(`Plugin backend listening on ${e.port}`)}))})();y.catch(async i=>{console.error("Plugin backend startup failed",i);try{l&&await h()}catch(u){console.error("Plugin backend shutdown failed",u)}process.exit(1)}),process.on("SIGTERM",()=>{d||(d=!0,Promise.all([new Promise(i=>c.close(()=>i())),y.then(async()=>{l&&await h()})]).then(()=>process.exit(0)).catch(i=>{console.error("Plugin backend shutdown failed",i),process.exit(1)}))})}n(Y,"serveBackend");async function F(a,e){const s=await B(a.db,e.databaseUrl);if(s)return s;try{await a.config.refresh()}catch(c){return`Plugin backend cannot read its configuration from the host API: ${c instanceof Error?c.message:String(c)}`}return null}n(F,"startUp");async function B(a,e){try{return await a.query("select 1"),null}catch(s){return`Plugin backend cannot reach its database at ${Q(e)}: ${s instanceof Error?s.message:String(s)}`}}n(B,"checkDatabaseReachable");function Q(a){try{const e=new URL(a);return`${e.host}${e.pathname}`}catch{return"the address in DATABASE_URL"}}n(Q,"describeDatabaseTarget");function X(a,e={}){const s=e.intervalMs??3e4,c=[];let d,l,w=!0;const h=n(i=>{w||(d&&clearTimeout(d),d=setTimeout(()=>void y(),i))},"schedule"),y=n(async()=>{if(d=void 0,l)return h(s);l=(async()=>{for(const i of c){if(w)break;try{await i.run()}catch(u){a.log.error(`maintenance step ${i.name} failed`,{error:u instanceof Error?u.message:String(u)})}}})(),await l,l=void 0,h(s)},"tick");return{step(i,u){c.push({name:i,run:u})},start(){w&&(w=!1,h(0))},wake(){h(0)},async stop(){w=!0,d&&clearTimeout(d),d=void 0,await l}}}n(X,"createMaintenance");export{B as checkDatabaseReachable,X as createMaintenance,x as createScopedDb,O as readPublicContext,U as readUserContext,Y as serveBackend};
|
package/dist/server.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var r=Object.defineProperty;var e=(t,n)=>r(t,"name",{value:n,configurable:!0});var
|
|
1
|
+
"use strict";var r=Object.defineProperty;var e=(t,n)=>r(t,"name",{value:n,configurable:!0});var chunkSR5V7ZC2_cjs=require("./chunk-SR5V7ZC2.cjs"),chunk66LDWN4T_cjs=require("./chunk-66LDWN4T.cjs");Object.defineProperty(exports,"PLUGIN_COLLECTION_CONTENT_PAGE_MAX",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.PLUGIN_COLLECTION_CONTENT_PAGE_MAX},"get")}),Object.defineProperty(exports,"PLUGIN_COLLECTION_IMPORT_MAX",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.PLUGIN_COLLECTION_IMPORT_MAX},"get")}),Object.defineProperty(exports,"PLUGIN_CONTEXT_HEADERS",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.PLUGIN_CONTEXT_HEADERS},"get")}),Object.defineProperty(exports,"accountInvitationSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.accountInvitationSchema},"get")}),Object.defineProperty(exports,"accountInviteSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.accountInviteSchema},"get")}),Object.defineProperty(exports,"accountPasswordResetSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.accountPasswordResetSchema},"get")}),Object.defineProperty(exports,"accountProvisionSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.accountProvisionSchema},"get")}),Object.defineProperty(exports,"definePluginBackend",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.definePluginBackend},"get")}),Object.defineProperty(exports,"directoryIdentitySchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.directoryIdentitySchema},"get")}),Object.defineProperty(exports,"directoryListSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.directoryListSchema},"get")}),Object.defineProperty(exports,"directoryMatchSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.directoryMatchSchema},"get")}),Object.defineProperty(exports,"directoryPrincipalSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.directoryPrincipalSchema},"get")}),Object.defineProperty(exports,"directoryValidateSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.directoryValidateSchema},"get")}),Object.defineProperty(exports,"pluginAdminActionSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginAdminActionSchema},"get")}),Object.defineProperty(exports,"pluginAdminProofSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginAdminProofSchema},"get")}),Object.defineProperty(exports,"pluginApprovalDigestSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginApprovalDigestSchema},"get")}),Object.defineProperty(exports,"pluginApprovedSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginApprovedSchema},"get")}),Object.defineProperty(exports,"pluginCollectionAccessSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionAccessSchema},"get")}),Object.defineProperty(exports,"pluginCollectionDeleteSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionDeleteSchema},"get")}),Object.defineProperty(exports,"pluginCollectionDocumentContentSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionDocumentContentSchema},"get")}),Object.defineProperty(exports,"pluginCollectionDocumentsStatusSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionDocumentsStatusSchema},"get")}),Object.defineProperty(exports,"pluginCollectionEnsureSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionEnsureSchema},"get")}),Object.defineProperty(exports,"pluginCollectionImportFilesSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionImportFilesSchema},"get")}),Object.defineProperty(exports,"pluginCollectionImportSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionImportSchema},"get")}),Object.defineProperty(exports,"pluginCollectionMoveSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionMoveSchema},"get")}),Object.defineProperty(exports,"pluginCollectionPermissionsSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionPermissionsSchema},"get")}),Object.defineProperty(exports,"pluginCollectionRemoveSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionRemoveSchema},"get")}),Object.defineProperty(exports,"pluginCollectionSearchSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionSearchSchema},"get")}),Object.defineProperty(exports,"pluginCollectionStatusSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginCollectionStatusSchema},"get")}),Object.defineProperty(exports,"pluginDiagramSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginDiagramSchema},"get")}),Object.defineProperty(exports,"pluginDocumentBatchInputSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginDocumentBatchInputSchema},"get")}),Object.defineProperty(exports,"pluginDocumentBatchItemSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginDocumentBatchItemSchema},"get")}),Object.defineProperty(exports,"pluginDocumentContentInputSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginDocumentContentInputSchema},"get")}),Object.defineProperty(exports,"pluginKnowledgeBaseInputSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginKnowledgeBaseInputSchema},"get")}),Object.defineProperty(exports,"pluginKnowledgeListInputSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginKnowledgeListInputSchema},"get")}),Object.defineProperty(exports,"pluginKnowledgeReferenceSchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginKnowledgeReferenceSchema},"get")}),Object.defineProperty(exports,"pluginKnowledgeVerifySchema",{enumerable:!0,get:e(function(){return chunkSR5V7ZC2_cjs.pluginKnowledgeVerifySchema},"get")}),Object.defineProperty(exports,"DECISION_CARD_FALLBACKS",{enumerable:!0,get:e(function(){return chunk66LDWN4T_cjs.DECISION_CARD_FALLBACKS},"get")}),Object.defineProperty(exports,"decisionCardPath",{enumerable:!0,get:e(function(){return chunk66LDWN4T_cjs.decisionCardPath},"get")}),Object.defineProperty(exports,"isDecisionCardBlock",{enumerable:!0,get:e(function(){return chunk66LDWN4T_cjs.isDecisionCardBlock},"get")}),Object.defineProperty(exports,"splitDecisionCardBlocks",{enumerable:!0,get:e(function(){return chunk66LDWN4T_cjs.splitDecisionCardBlocks},"get")}),Object.defineProperty(exports,"stripDecisionCardFallback",{enumerable:!0,get:e(function(){return chunk66LDWN4T_cjs.stripDecisionCardFallback},"get")});
|