paperclip-plugin-supermemory-otomatik 0.2.1 → 0.2.3

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/README.md CHANGED
@@ -13,7 +13,7 @@ The plugin uses Paperclip's standard plugin slots (`settingsPage`, `page`, `side
13
13
 
14
14
  ## Install from Paperclip
15
15
 
16
- Package: [`paperclip-plugin-supermemory-otomatik`](https://www.npmjs.com/package/paperclip-plugin-supermemory-otomatik) **0.2.1**.
16
+ Package: [`paperclip-plugin-supermemory-otomatik`](https://www.npmjs.com/package/paperclip-plugin-supermemory-otomatik) **0.2.3**.
17
17
 
18
18
  1. In Paperclip, open **Settings → Plugins → Install Plugin**.
19
19
  2. Enter `paperclip-plugin-supermemory-otomatik` and install it for the instance.
@@ -26,16 +26,15 @@ The settings form uses the active Paperclip organization to load agents and comp
26
26
 
27
27
  ## Configure secrets and URLs
28
28
 
29
- Default OTOMATIK endpoints:
29
+ Default OTOMATIK gateway endpoint:
30
30
 
31
- - ACL gateway: `http://127.0.0.1:6768/mcp`
32
- - Supermemory Local API: `http://127.0.0.1:6767`
31
+ - `https://otomatik.tail77a9ab.ts.net:18443/mcp`
33
32
 
34
- Keep both services on a private network. The plugin rejects public hosts and nonstandard ports. If the Paperclip plugin worker runs in a separate container, set the private service address reachable from that container.
33
+ Paperclip reaches the gateway over Tailscale HTTPS. Tailscale Serve forwards tailnet requests to `127.0.0.1:6768`; Supermemory Local remains private at `127.0.0.1:6767` and the plugin never contacts it directly. The plugin accepts HTTPS `*.ts.net` URLs on port 443 or 18443. It upgrades the old default `http://127.0.0.1:6768/mcp` to the OTOMATIK Tailscale URL automatically.
35
34
 
36
35
  Create/import the gateway tokens in **Paperclip → Organization Settings → Secrets** first. There must be a distinct ACL token for each agent; the gateway must bind each token to the same Paperclip organization, agent and role. Use the individual token as that agent's secret reference.
37
36
 
38
- Store the Supermemory Local **master key** in a Paperclip company secret and select that secret in `Owner-only Supermemory Local API key`. The plugin resolves this value only inside Owner-checked management actions and after checking an agent's allowlist before a memory search. Never paste it into an agent prompt, instructions file, or memory document. The worker is a trusted enforcement boundary: it holds the broader key but chooses the namespace from trusted Paperclip context and the Owner's assignments; agents never supply a namespace.
37
+ Store the Supermemory Local **master key** in a Paperclip company secret and select it in `Secret con la chiave master Supermemory Local`. The plugin sends it only to the gateway after an Owner check, or after checking an agent's explicit assignment allowlist. The gateway uses the key server-side to call Supermemory Local; agents never receive it. Never paste it into an agent prompt, instructions file, or memory document. The worker chooses namespaces from trusted Paperclip context and the Owner's assignments; agents never supply a namespace.
39
38
 
40
39
  ## Namespaces and access rules
41
40
 
@@ -59,7 +58,7 @@ The page mirrors the Instructions layout: left content list, **Leggi / Modifica
59
58
 
60
59
  Text and URL content can be edited and reindexed. Binary file contents cannot be retrieved into the editor; delete the catalog item and upload a replacement to update one. Office, audio and video formats appear in some hosted Supermemory documentation but are not documented for the installed Supermemory Local server, so this plugin does not offer them as verified Local formats.
61
60
 
62
- The content is indexed as retrieval/reference material (`taskType: "superrag"`) rather than used to update a personal profile. Supermemory returns an asynchronous status; `queued` means indexing has started, not finished.
61
+ The content is indexed as retrieval/reference material (`taskType: "superrag"`) rather than used to update a personal profile. Text, URL, file, search, update, and delete requests all pass through the ACL gateway. The plugin sends file bytes as JSON/base64 through Paperclip; the gateway converts them to multipart before forwarding them to Local. Supermemory returns an asynchronous status; `queued` means indexing has started, not finished.
63
62
 
64
63
  ## Tools
65
64
 
package/dist/manifest.js CHANGED
@@ -9,7 +9,7 @@ var MEMORY_ROUTE = "memory";
9
9
  var manifest = {
10
10
  id: PLUGIN_ID,
11
11
  apiVersion: 1,
12
- version: "0.2.1",
12
+ version: "0.2.3",
13
13
  minimumHostVersion: "2026.1023.0",
14
14
  displayName: "Supermemory (self-hosted)",
15
15
  description: "Memory tools and an Owner-managed memory library for self-hosted Supermemory, with company-, agent-, and project-scoped access.",
@@ -35,23 +35,22 @@ var manifest = {
35
35
  properties: {
36
36
  gatewayUrl: {
37
37
  type: "string",
38
- title: "Self-hosted ACL gateway URL",
39
- description: "Private Paperclip ACL gateway used by legacy company/team memory and reviewed memory candidates. Defaults to the OTOMATIK loopback endpoint.",
40
- default: "http://127.0.0.1:6768/mcp"
38
+ title: "Gateway Supermemory su Tailscale HTTPS",
39
+ description: "URL HTTPS tailnet del gateway ACL e delle operazioni Owner. Esempio OTOMATIK: https://otomatik.tail77a9ab.ts.net:18443/mcp. Supermemory Local resta privato sul server.",
40
+ default: "https://otomatik.tail77a9ab.ts.net:18443/mcp"
41
41
  },
42
42
  localApiUrl: {
43
43
  type: "string",
44
- title: "Supermemory Local API URL",
45
- description: "Private Supermemory Local API used by Owner-managed namespace content and explicit agent/project memory. Defaults to the OTOMATIK loopback endpoint.",
46
- default: "http://127.0.0.1:6767"
44
+ title: "Legacy Supermemory Local API URL",
45
+ description: "Legacy value retained for existing configurations; ignored since plugin 0.2.3. The Local API is reached only by the server-side gateway."
47
46
  },
48
47
  adminApiKeyRef: {
49
48
  // Paperclip persists a secret-ref format as an object binding, even
50
49
  // though the format marker historically describes a string picker.
51
50
  type: ["string", "object"],
52
51
  format: "secret-ref",
53
- title: "Owner-only Supermemory Local API key",
54
- description: "Paperclip secret containing the Supermemory Local master API key. The plugin resolves it only for Owner-checked management actions and authorized agent searches; never paste it into instructions or agent prompts."
52
+ title: "Secret con la chiave master Supermemory Local",
53
+ description: "Usata come credenziale per le route Owner del gateway Tailscale. Viene risolta solo dopo il controllo Owner o per una ricerca con namespace assegnato esplicitamente; non viene esposta nei prompt."
55
54
  },
56
55
  agentGrants: {
57
56
  type: "array",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/manifest.ts"],
4
- "sourcesContent": ["import type { PaperclipPluginManifestV1 } from \"@paperclipai/plugin-sdk\";\n\nexport const PLUGIN_ID = \"paperclipai.supermemory\";\nexport const SEARCH_TOOL = \"search-approved-memory\";\nexport const SAVE_TOOL = \"submit-memory-candidate\";\nexport const MEMORY_SETTINGS_PAGE = \"supermemory-settings\";\nexport const MEMORY_PAGE = \"supermemory-memory\";\nexport const MEMORY_SIDEBAR = \"supermemory-sidebar\";\nexport const MEMORY_ROUTE = \"memory\";\n\nconst manifest: PaperclipPluginManifestV1 = {\n id: PLUGIN_ID,\n apiVersion: 1,\n version: \"0.2.1\",\n minimumHostVersion: \"2026.1023.0\",\n displayName: \"Supermemory (self-hosted)\",\n description: \"Memory tools and an Owner-managed memory library for self-hosted Supermemory, with company-, agent-, and project-scoped access.\",\n author: \"Otomatik\",\n categories: [\"connector\", \"automation\", \"ui\"],\n capabilities: [\n \"agent.tools.register\",\n \"agents.read\",\n \"projects.read\",\n \"access.members.read\",\n \"http.outbound\",\n \"instance.settings.register\",\n \"secrets.read-ref\",\n \"ui.page.register\",\n \"ui.sidebar.register\",\n ],\n entrypoints: {\n worker: \"./dist/worker.js\",\n ui: \"./dist/ui\",\n },\n instanceConfigSchema: {\n type: \"object\",\n properties: {\n gatewayUrl: {\n type: \"string\",\n title: \"Self-hosted ACL gateway URL\",\n description: \"Private Paperclip ACL gateway used by legacy company/team memory and reviewed memory candidates. Defaults to the OTOMATIK loopback endpoint.\",\n default: \"http://127.0.0.1:6768/mcp\",\n },\n localApiUrl: {\n type: \"string\",\n title: \"Supermemory Local API URL\",\n description: \"Private Supermemory Local API used by Owner-managed namespace content and explicit agent/project memory. Defaults to the OTOMATIK loopback endpoint.\",\n default: \"http://127.0.0.1:6767\",\n },\n adminApiKeyRef: {\n // Paperclip persists a secret-ref format as an object binding, even\n // though the format marker historically describes a string picker.\n type: [\"string\", \"object\"],\n format: \"secret-ref\",\n title: \"Owner-only Supermemory Local API key\",\n description: \"Paperclip secret containing the Supermemory Local master API key. The plugin resolves it only for Owner-checked management actions and authorized agent searches; never paste it into instructions or agent prompts.\",\n },\n agentGrants: {\n type: \"array\",\n title: \"Authorized agents\",\n description: \"Only listed Paperclip agents can use the memory tools. Each one uses its own ACL gateway token secret, already bound to the same agent, company, and role.\",\n items: {\n type: \"object\",\n title: \"Agent grant\",\n required: [\"agentId\", \"tokenRef\"],\n properties: {\n agentId: {\n type: \"string\",\n title: \"Paperclip agent\",\n minLength: 1,\n },\n tokenRef: {\n type: [\"string\", \"object\"],\n format: \"secret-ref\",\n title: \"This agent's ACL token secret\",\n description: \"Select the Paperclip company secret containing only this agent's Supermemory ACL token.\",\n },\n },\n },\n default: [],\n },\n },\n },\n tools: [\n {\n name: SEARCH_TOOL,\n displayName: \"Search approved Supermemory\",\n description: \"Search this agent's explicitly authorized company/team compartments and any assigned agent/project namespaces. Project memory is available only when the Paperclip run is in that project and the agent is on its explicit allowlist. Do not search for credentials or personal records.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", minLength: 1, maxLength: 300 },\n searchMode: { type: \"string\", enum: [\"hybrid\", \"memories\", \"chunks\"], default: \"hybrid\" },\n limit: { type: \"integer\", minimum: 1, maximum: 5, default: 3 },\n },\n required: [\"query\"],\n additionalProperties: false,\n },\n },\n {\n name: SAVE_TOOL,\n displayName: \"Submit a Supermemory candidate\",\n description: \"Submit one durable, non-sensitive fact or decision to this agent's role staging compartment for human review. This does not publish it to shared approved memory. Never submit credentials, personal data, customer cases, legal/health/workplace records, or full chat transcripts.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n content: { type: \"string\", minLength: 20, maxLength: 1200 },\n },\n required: [\"content\"],\n additionalProperties: false,\n },\n },\n ],\n ui: {\n slots: [\n {\n type: \"settingsPage\",\n id: MEMORY_SETTINGS_PAGE,\n displayName: \"Supermemory settings\",\n exportName: \"SupermemorySettingsPage\",\n },\n {\n type: \"page\",\n id: MEMORY_PAGE,\n displayName: \"Memory\",\n exportName: \"MemoryPage\",\n routePath: MEMORY_ROUTE,\n },\n {\n type: \"sidebar\",\n id: MEMORY_SIDEBAR,\n displayName: \"Memory\",\n exportName: \"MemorySidebarLink\",\n },\n ],\n },\n};\n\nexport default manifest;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { PaperclipPluginManifestV1 } from \"@paperclipai/plugin-sdk\";\n\nexport const PLUGIN_ID = \"paperclipai.supermemory\";\nexport const SEARCH_TOOL = \"search-approved-memory\";\nexport const SAVE_TOOL = \"submit-memory-candidate\";\nexport const MEMORY_SETTINGS_PAGE = \"supermemory-settings\";\nexport const MEMORY_PAGE = \"supermemory-memory\";\nexport const MEMORY_SIDEBAR = \"supermemory-sidebar\";\nexport const MEMORY_ROUTE = \"memory\";\n\nconst manifest: PaperclipPluginManifestV1 = {\n id: PLUGIN_ID,\n apiVersion: 1,\n version: \"0.2.3\",\n minimumHostVersion: \"2026.1023.0\",\n displayName: \"Supermemory (self-hosted)\",\n description: \"Memory tools and an Owner-managed memory library for self-hosted Supermemory, with company-, agent-, and project-scoped access.\",\n author: \"Otomatik\",\n categories: [\"connector\", \"automation\", \"ui\"],\n capabilities: [\n \"agent.tools.register\",\n \"agents.read\",\n \"projects.read\",\n \"access.members.read\",\n \"http.outbound\",\n \"instance.settings.register\",\n \"secrets.read-ref\",\n \"ui.page.register\",\n \"ui.sidebar.register\",\n ],\n entrypoints: {\n worker: \"./dist/worker.js\",\n ui: \"./dist/ui\",\n },\n instanceConfigSchema: {\n type: \"object\",\n properties: {\n gatewayUrl: {\n type: \"string\",\n title: \"Gateway Supermemory su Tailscale HTTPS\",\n description: \"URL HTTPS tailnet del gateway ACL e delle operazioni Owner. Esempio OTOMATIK: https://otomatik.tail77a9ab.ts.net:18443/mcp. Supermemory Local resta privato sul server.\",\n default: \"https://otomatik.tail77a9ab.ts.net:18443/mcp\",\n },\n localApiUrl: {\n type: \"string\",\n title: \"Legacy Supermemory Local API URL\",\n description: \"Legacy value retained for existing configurations; ignored since plugin 0.2.3. The Local API is reached only by the server-side gateway.\",\n },\n adminApiKeyRef: {\n // Paperclip persists a secret-ref format as an object binding, even\n // though the format marker historically describes a string picker.\n type: [\"string\", \"object\"],\n format: \"secret-ref\",\n title: \"Secret con la chiave master Supermemory Local\",\n description: \"Usata come credenziale per le route Owner del gateway Tailscale. Viene risolta solo dopo il controllo Owner o per una ricerca con namespace assegnato esplicitamente; non viene esposta nei prompt.\",\n },\n agentGrants: {\n type: \"array\",\n title: \"Authorized agents\",\n description: \"Only listed Paperclip agents can use the memory tools. Each one uses its own ACL gateway token secret, already bound to the same agent, company, and role.\",\n items: {\n type: \"object\",\n title: \"Agent grant\",\n required: [\"agentId\", \"tokenRef\"],\n properties: {\n agentId: {\n type: \"string\",\n title: \"Paperclip agent\",\n minLength: 1,\n },\n tokenRef: {\n type: [\"string\", \"object\"],\n format: \"secret-ref\",\n title: \"This agent's ACL token secret\",\n description: \"Select the Paperclip company secret containing only this agent's Supermemory ACL token.\",\n },\n },\n },\n default: [],\n },\n },\n },\n tools: [\n {\n name: SEARCH_TOOL,\n displayName: \"Search approved Supermemory\",\n description: \"Search this agent's explicitly authorized company/team compartments and any assigned agent/project namespaces. Project memory is available only when the Paperclip run is in that project and the agent is on its explicit allowlist. Do not search for credentials or personal records.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", minLength: 1, maxLength: 300 },\n searchMode: { type: \"string\", enum: [\"hybrid\", \"memories\", \"chunks\"], default: \"hybrid\" },\n limit: { type: \"integer\", minimum: 1, maximum: 5, default: 3 },\n },\n required: [\"query\"],\n additionalProperties: false,\n },\n },\n {\n name: SAVE_TOOL,\n displayName: \"Submit a Supermemory candidate\",\n description: \"Submit one durable, non-sensitive fact or decision to this agent's role staging compartment for human review. This does not publish it to shared approved memory. Never submit credentials, personal data, customer cases, legal/health/workplace records, or full chat transcripts.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n content: { type: \"string\", minLength: 20, maxLength: 1200 },\n },\n required: [\"content\"],\n additionalProperties: false,\n },\n },\n ],\n ui: {\n slots: [\n {\n type: \"settingsPage\",\n id: MEMORY_SETTINGS_PAGE,\n displayName: \"Supermemory settings\",\n exportName: \"SupermemorySettingsPage\",\n },\n {\n type: \"page\",\n id: MEMORY_PAGE,\n displayName: \"Memory\",\n exportName: \"MemoryPage\",\n routePath: MEMORY_ROUTE,\n },\n {\n type: \"sidebar\",\n id: MEMORY_SIDEBAR,\n displayName: \"Memory\",\n exportName: \"MemorySidebarLink\",\n },\n ],\n },\n};\n\nexport default manifest;\n"],
5
+ "mappings": ";AAEO,IAAM,YAAY;AAClB,IAAM,cAAc;AACpB,IAAM,YAAY;AAClB,IAAM,uBAAuB;AAC7B,IAAM,cAAc;AACpB,IAAM,iBAAiB;AACvB,IAAM,eAAe;AAE5B,IAAM,WAAsC;AAAA,EAC1C,IAAI;AAAA,EACJ,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,oBAAoB;AAAA,EACpB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY,CAAC,aAAa,cAAc,IAAI;AAAA,EAC5C,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,QAAQ;AAAA,IACR,IAAI;AAAA,EACN;AAAA,EACA,sBAAsB;AAAA,IACpB,MAAM;AAAA,IACN,YAAY;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,QACb,SAAS;AAAA,MACX;AAAA,MACA,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA,gBAAgB;AAAA;AAAA;AAAA,QAGd,MAAM,CAAC,UAAU,QAAQ;AAAA,QACzB,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,UACP,UAAU,CAAC,WAAW,UAAU;AAAA,UAChC,YAAY;AAAA,YACV,SAAS;AAAA,cACP,MAAM;AAAA,cACN,OAAO;AAAA,cACP,WAAW;AAAA,YACb;AAAA,YACA,UAAU;AAAA,cACR,MAAM,CAAC,UAAU,QAAQ;AAAA,cACzB,QAAQ;AAAA,cACR,OAAO;AAAA,cACP,aAAa;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS,CAAC;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,MACb,kBAAkB;AAAA,QAChB,MAAM;AAAA,QACN,YAAY;AAAA,UACV,OAAO,EAAE,MAAM,UAAU,WAAW,GAAG,WAAW,IAAI;AAAA,UACtD,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,UAAU,YAAY,QAAQ,GAAG,SAAS,SAAS;AAAA,UACxF,OAAO,EAAE,MAAM,WAAW,SAAS,GAAG,SAAS,GAAG,SAAS,EAAE;AAAA,QAC/D;AAAA,QACA,UAAU,CAAC,OAAO;AAAA,QAClB,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,MACb,kBAAkB;AAAA,QAChB,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS,EAAE,MAAM,UAAU,WAAW,IAAI,WAAW,KAAK;AAAA,QAC5D;AAAA,QACA,UAAU,CAAC,SAAS;AAAA,QACpB,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EACA,IAAI;AAAA,IACF,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,aAAa;AAAA,QACb,YAAY;AAAA,MACd;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,aAAa;AAAA,QACb,YAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,mBAAQ;",
6
6
  "names": []
7
7
  }
package/dist/ui/index.js CHANGED
@@ -13,8 +13,8 @@ var PLUGIN_ID = "paperclipai.supermemory";
13
13
 
14
14
  // src/ui/index.tsx
15
15
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
- var DEFAULT_GATEWAY = "http://127.0.0.1:6768/mcp";
17
- var DEFAULT_LOCAL_API = "http://127.0.0.1:6767";
16
+ var DEFAULT_GATEWAY = "https://otomatik.tail77a9ab.ts.net:18443/mcp";
17
+ var LEGACY_GATEWAYS = /* @__PURE__ */ new Set(["http://127.0.0.1:6768/mcp", "http://localhost:6768/mcp"]);
18
18
  var CONFIG_PATH = `/api/plugins/${encodeURIComponent(PLUGIN_ID)}/config`;
19
19
  var BINARY_MAX_BYTES = 6 * 1024 * 1024;
20
20
  var TEXT_EXTENSIONS = /* @__PURE__ */ new Set(["txt", "md", "markdown", "html", "htm", "json", "csv"]);
@@ -44,6 +44,17 @@ async function hostFetchJson(path, init = {}) {
44
44
  function secretId(value) {
45
45
  return typeof value === "object" && value !== null && value.type === "secret_ref" && typeof value.secretId === "string" ? value.secretId : "";
46
46
  }
47
+ function displayError(value) {
48
+ if (value instanceof Error) return value.message;
49
+ if (typeof value === "string") return value;
50
+ if (value && typeof value === "object") {
51
+ const error = value;
52
+ if (typeof error.message === "string" && error.message.trim()) return error.message;
53
+ if (typeof error.details === "string" && error.details.trim()) return error.details;
54
+ if (typeof error.code === "string" && error.code.trim()) return `Operazione non riuscita (${error.code}).`;
55
+ }
56
+ return "Operazione non riuscita. Riprova o controlla la configurazione del plugin.";
57
+ }
47
58
  function pluginConfig(configJson) {
48
59
  const config = configJson ?? {};
49
60
  const grants = Array.isArray(config.agentGrants) ? config.agentGrants.flatMap((entry) => {
@@ -55,8 +66,7 @@ function pluginConfig(configJson) {
55
66
  }) : [];
56
67
  const adminRef = secretId(config.adminApiKeyRef);
57
68
  return {
58
- gatewayUrl: typeof config.gatewayUrl === "string" ? config.gatewayUrl : DEFAULT_GATEWAY,
59
- localApiUrl: typeof config.localApiUrl === "string" ? config.localApiUrl : DEFAULT_LOCAL_API,
69
+ gatewayUrl: typeof config.gatewayUrl === "string" && !LEGACY_GATEWAYS.has(config.gatewayUrl.trim()) ? config.gatewayUrl : DEFAULT_GATEWAY,
60
70
  ...adminRef ? { adminApiKeyRef: { type: "secret_ref", secretId: adminRef } } : {},
61
71
  agentGrants: grants
62
72
  };
@@ -71,7 +81,7 @@ function SupermemorySettingsPage() {
71
81
  const { companyId } = useHostContext();
72
82
  const [agents, setAgents] = useState([]);
73
83
  const [secrets, setSecrets] = useState([]);
74
- const [config, setConfig] = useState({ gatewayUrl: DEFAULT_GATEWAY, localApiUrl: DEFAULT_LOCAL_API, agentGrants: [] });
84
+ const [config, setConfig] = useState({ gatewayUrl: DEFAULT_GATEWAY, agentGrants: [] });
75
85
  const [grantRows, setGrantRows] = useState([]);
76
86
  const [loading, setLoading] = useState(true);
77
87
  const [saving, setSaving] = useState(false);
@@ -100,7 +110,7 @@ function SupermemorySettingsPage() {
100
110
  setError(null);
101
111
  };
102
112
  void load().catch((cause) => {
103
- if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause));
113
+ if (!cancelled) setError(displayError(cause));
104
114
  }).finally(() => {
105
115
  if (!cancelled) setLoading(false);
106
116
  });
@@ -132,7 +142,6 @@ function SupermemorySettingsPage() {
132
142
  }
133
143
  const nextConfig = {
134
144
  gatewayUrl: config.gatewayUrl.trim() || DEFAULT_GATEWAY,
135
- localApiUrl: config.localApiUrl.trim() || DEFAULT_LOCAL_API,
136
145
  agentGrants: cleaned.map((row) => ({ agentId: row.agentId, tokenRef: { type: "secret_ref", secretId: row.tokenSecretId } }))
137
146
  };
138
147
  if (config.adminApiKeyRef?.secretId) nextConfig.adminApiKeyRef = config.adminApiKeyRef;
@@ -141,7 +150,7 @@ function SupermemorySettingsPage() {
141
150
  setGrantRows(cleaned.map((row, index) => ({ key: `grant-${index}-${row.agentId}`, agentId: row.agentId, tokenSecretId: row.tokenSecretId })));
142
151
  setSuccess(true);
143
152
  } catch (cause) {
144
- setError(cause instanceof Error ? cause.message : String(cause));
153
+ setError(displayError(cause));
145
154
  } finally {
146
155
  setSaving(false);
147
156
  }
@@ -160,12 +169,7 @@ function SupermemorySettingsPage() {
160
169
  /* @__PURE__ */ jsxs("label", { style: { display: "grid", gap: 6, fontSize: 13 }, children: [
161
170
  "Gateway ACL Paperclip",
162
171
  /* @__PURE__ */ jsx("input", { style: inputStyle, value: config.gatewayUrl, onChange: (event) => setConfig((current) => ({ ...current, gatewayUrl: event.target.value })) }),
163
- /* @__PURE__ */ jsx("span", { style: mutedStyle, children: "Default OTOMATIK: 127.0.0.1:6768/mcp" })
164
- ] }),
165
- /* @__PURE__ */ jsxs("label", { style: { display: "grid", gap: 6, fontSize: 13 }, children: [
166
- "API Supermemory Local",
167
- /* @__PURE__ */ jsx("input", { style: inputStyle, value: config.localApiUrl, onChange: (event) => setConfig((current) => ({ ...current, localApiUrl: event.target.value })) }),
168
- /* @__PURE__ */ jsx("span", { style: mutedStyle, children: "Default OTOMATIK: 127.0.0.1:6767. L\u2019endpoint deve rimanere su rete privata." })
172
+ /* @__PURE__ */ jsx("span", { style: mutedStyle, children: "Default OTOMATIK: HTTPS Tailscale `otomatik.tail77a9ab.ts.net:18443`. L\u2019API Supermemory resta interna al server." })
169
173
  ] }),
170
174
  /* @__PURE__ */ jsxs("label", { style: { display: "grid", gap: 6, fontSize: 13 }, children: [
171
175
  "Secret con la chiave master Supermemory Local",
@@ -180,7 +184,7 @@ function SupermemorySettingsPage() {
180
184
  ] }, secret.id))
181
185
  ] }),
182
186
  /* @__PURE__ */ jsxs("span", { style: mutedStyle, children: [
183
- "Serve solo per la libreria Memory e le ricerche negli spazi assegnati. Crea o importa il secret da ",
187
+ "Serve per autenticare il gateway nelle azioni Owner della libreria Memory e nelle ricerche di namespace assegnati. Crea o importa il secret da ",
184
188
  /* @__PURE__ */ jsx("a", { href: "/company/settings/secrets", style: { textDecoration: "underline" }, children: "Secrets" }),
185
189
  "."
186
190
  ] })
@@ -237,12 +241,12 @@ function MemorySidebarLink({ context }) {
237
241
  "aria-current": isActive ? "page" : void 0,
238
242
  className: `flex items-center gap-2.5 px-3 py-2 text-[13px] font-medium transition-colors ${isActive ? "bg-accent text-foreground" : "text-foreground/80 hover:bg-accent/50 hover:text-foreground"}`,
239
243
  children: [
240
- /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
244
+ /* @__PURE__ */ jsx("span", { "data-plugin-sidebar-icon": "true", "aria-hidden": "true", className: "flex h-4 w-4 shrink-0 items-center justify-center", children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
241
245
  /* @__PURE__ */ jsx("path", { d: "M9 3.5a3 3 0 0 0-3 3v.4a3 3 0 0 0-2.5 3v1.2a3 3 0 0 0 2.5 3v.4a3 3 0 0 0 3 3h1V3.5H9Z" }),
242
246
  /* @__PURE__ */ jsx("path", { d: "M15 3.5a3 3 0 0 1 3 3v.4a3 3 0 0 1 2.5 3v1.2a3 3 0 0 1-2.5 3v.4a3 3 0 0 1-3 3h-1V3.5h1Z" }),
243
247
  /* @__PURE__ */ jsx("path", { d: "M8 8h2m-2 5h2m4-5h2m-2 5h2" })
244
- ] }),
245
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: "Memory" })
248
+ ] }) }),
249
+ /* @__PURE__ */ jsx("span", { "data-plugin-sidebar-label": "true", className: "flex-1 truncate", children: "Memory" })
246
250
  ]
247
251
  }
248
252
  );
@@ -313,7 +317,7 @@ function MemoryPage() {
313
317
  setError(null);
314
318
  }).catch((cause) => {
315
319
  if (cancelled) return;
316
- setError(cause instanceof Error ? cause.message : String(cause));
320
+ setError(displayError(cause));
317
321
  }).finally(() => {
318
322
  if (!cancelled) setLoading(false);
319
323
  });
@@ -344,7 +348,7 @@ function MemoryPage() {
344
348
  setDirty(false);
345
349
  setMode("read");
346
350
  }).catch((cause) => {
347
- if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause));
351
+ if (!cancelled) setError(displayError(cause));
348
352
  }).finally(() => {
349
353
  if (!cancelled) setBusy(false);
350
354
  });
@@ -385,7 +389,7 @@ function MemoryPage() {
385
389
  toast({ tone: "success", title: "Memoria salvata", body: "Supermemory ha messo il contenuto in coda per l\u2019indicizzazione." });
386
390
  return true;
387
391
  } catch (cause) {
388
- const message = cause instanceof Error ? cause.message : String(cause);
392
+ const message = displayError(cause);
389
393
  setError(message);
390
394
  toast({ tone: "error", title: "Salvataggio non riuscito", body: message });
391
395
  } finally {
@@ -420,7 +424,7 @@ function MemoryPage() {
420
424
  setActiveDocumentKey(`${activeAssignment.id}:${result.document.id}`);
421
425
  toast({ tone: "success", title: "File caricato", body: "Supermemory ha messo il file in coda per l\u2019indicizzazione." });
422
426
  } catch (cause) {
423
- const message = cause instanceof Error ? cause.message : String(cause);
427
+ const message = displayError(cause);
424
428
  setError(message);
425
429
  toast({ tone: "error", title: "Caricamento non riuscito", body: message });
426
430
  } finally {
@@ -434,6 +438,10 @@ function MemoryPage() {
434
438
  }
435
439
  function onDrop(event) {
436
440
  event.preventDefault();
441
+ if (!activeAssignment) {
442
+ setError("Prima assegna o seleziona un namespace; poi puoi caricare il PDF.");
443
+ return;
444
+ }
437
445
  const file = event.dataTransfer.files.item(0);
438
446
  if (file) void handleFile(file);
439
447
  }
@@ -473,7 +481,7 @@ function MemoryPage() {
473
481
  setAllowedAgentIds([]);
474
482
  toast({ tone: "success", title: "Namespace assegnato", body: "Lo spazio di memoria \xE8 limitato all\u2019assegnazione e agli agenti indicati." });
475
483
  } catch (cause) {
476
- const message = cause instanceof Error ? cause.message : String(cause);
484
+ const message = displayError(cause);
477
485
  setError(message);
478
486
  } finally {
479
487
  setBusy(false);
@@ -489,7 +497,7 @@ function MemoryPage() {
489
497
  setActiveDocumentKey("");
490
498
  setDocument(null);
491
499
  } catch (cause) {
492
- setError(cause instanceof Error ? cause.message : String(cause));
500
+ setError(displayError(cause));
493
501
  } finally {
494
502
  setBusy(false);
495
503
  }
@@ -504,7 +512,7 @@ function MemoryPage() {
504
512
  setDocument(null);
505
513
  setActiveDocumentKey("");
506
514
  } catch (cause) {
507
- setError(cause instanceof Error ? cause.message : String(cause));
515
+ setError(displayError(cause));
508
516
  } finally {
509
517
  setBusy(false);
510
518
  }
@@ -626,7 +634,7 @@ function MemoryPage() {
626
634
  ] }),
627
635
  document ? /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: 4, border: "1px solid var(--border)", borderRadius: 7, padding: 3 }, children: ["read", "edit", "raw"].map((tab) => /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setMode(tab), style: { border: 0, borderRadius: 5, padding: "6px 10px", background: mode === tab ? "var(--accent, rgba(127,127,127,.18))" : "transparent", color: "var(--foreground)", cursor: "pointer", fontSize: 12 }, children: tab === "read" ? "Leggi" : tab === "edit" ? "Modifica" : "Raw" }, tab)) }) : null
628
636
  ] }),
629
- showUrlForm ? /* @__PURE__ */ jsxs("form", { onSubmit: addUrl, style: { margin: 14, padding: 14, display: "grid", gap: 9, border: "1px solid var(--border)", borderRadius: 8 }, children: [
637
+ showUrlForm && activeAssignment ? /* @__PURE__ */ jsxs("form", { onSubmit: addUrl, style: { margin: 14, padding: 14, display: "grid", gap: 9, border: "1px solid var(--border)", borderRadius: 8 }, children: [
630
638
  /* @__PURE__ */ jsx("strong", { style: { fontSize: 13 }, children: "Aggiungi pagina web" }),
631
639
  /* @__PURE__ */ jsx("input", { style: inputStyle, type: "url", required: true, placeholder: "https://example.com/documentazione", value: urlInput, onChange: (event) => setUrlInput(event.target.value) }),
632
640
  /* @__PURE__ */ jsx("span", { style: { ...mutedStyle, fontSize: 12 }, children: "L\u2019URL viene passato a Supermemory Local. L\u2019estrazione web richiede Firecrawl configurato e invia la pagina al servizio Firecrawl." }),
@@ -635,7 +643,11 @@ function MemoryPage() {
635
643
  /* @__PURE__ */ jsx("button", { type: "button", style: secondaryButtonStyle, onClick: () => setShowUrlForm(false), children: "Annulla" })
636
644
  ] })
637
645
  ] }) : null,
638
- !document ? /* @__PURE__ */ jsx("div", { onDragOver: (event) => event.preventDefault(), onDrop, style: { flex: 1, display: "grid", placeItems: "center", minHeight: 420, padding: 28 }, children: /* @__PURE__ */ jsxs("div", { style: { width: "min(100%, 600px)", border: "1px dashed var(--border)", borderRadius: 12, padding: 28, textAlign: "center" }, children: [
646
+ !activeAssignment ? /* @__PURE__ */ jsx("div", { style: { flex: 1, display: "grid", placeItems: "center", minHeight: 420, padding: 28 }, children: /* @__PURE__ */ jsxs("div", { style: { width: "min(100%, 600px)", border: "1px dashed var(--border)", borderRadius: 12, padding: 28, textAlign: "center" }, children: [
647
+ /* @__PURE__ */ jsx("strong", { children: "Prima assegna un namespace" }),
648
+ /* @__PURE__ */ jsx("p", { style: { ...mutedStyle, fontSize: 13, lineHeight: 1.55 }, children: "Non c\u2019\xE8 uno spazio di memoria attivo in questa organizzazione. Assegna un progetto o un agente; poi selezionalo e carica il PDF." }),
649
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => setShowAssignment(true), children: "\uFF0B Assegna namespace" })
650
+ ] }) }) : !document ? /* @__PURE__ */ jsx("div", { onDragOver: (event) => event.preventDefault(), onDrop, style: { flex: 1, display: "grid", placeItems: "center", minHeight: 420, padding: 28 }, children: /* @__PURE__ */ jsxs("div", { style: { width: "min(100%, 600px)", border: "1px dashed var(--border)", borderRadius: 12, padding: 28, textAlign: "center" }, children: [
639
651
  /* @__PURE__ */ jsx("div", { style: { fontSize: 28, marginBottom: 10 }, children: "\u21E7" }),
640
652
  /* @__PURE__ */ jsx("strong", { children: "Trascina qui un file" }),
641
653
  /* @__PURE__ */ jsx("p", { style: { ...mutedStyle, fontSize: 13, lineHeight: 1.55 }, children: "Testo: TXT, Markdown, HTML, JSON e CSV (max 1 MB). File binari verificati per Supermemory Local: PDF, PNG, JPG/JPEG, GIF e WebP (max 6 MiB in questa interfaccia). Puoi anche aggiungere un URL pubblico." }),