@sulala/agent-os 0.1.33 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -154,6 +154,7 @@ async function readConfig() {
154
154
  const openrouter_api_key = o.openrouter_api_key;
155
155
  const telegram_bot_token = o.telegram_bot_token;
156
156
  const telegram_default_agent_id = o.telegram_default_agent_id;
157
+ const telegram_report_chat_id = o.telegram_report_chat_id;
157
158
  const slack_bot_token = o.slack_bot_token;
158
159
  const slack_signing_secret = o.slack_signing_secret;
159
160
  const slack_default_agent_id = o.slack_default_agent_id;
@@ -176,6 +177,7 @@ async function readConfig() {
176
177
  openrouter_api_key: typeof openrouter_api_key === "string" ? openrouter_api_key : undefined,
177
178
  telegram_bot_token: typeof telegram_bot_token === "string" ? telegram_bot_token : undefined,
178
179
  telegram_default_agent_id: typeof telegram_default_agent_id === "string" ? telegram_default_agent_id : undefined,
180
+ telegram_report_chat_id: typeof telegram_report_chat_id === "string" ? telegram_report_chat_id.trim() || undefined : undefined,
179
181
  slack_bot_token: typeof slack_bot_token === "string" ? slack_bot_token : undefined,
180
182
  slack_signing_secret: typeof slack_signing_secret === "string" ? slack_signing_secret : undefined,
181
183
  slack_default_agent_id: typeof slack_default_agent_id === "string" ? slack_default_agent_id : undefined,
@@ -225,6 +227,7 @@ async function writeConfig(updates) {
225
227
  openrouter_api_key: updates.openrouter_api_key !== undefined ? updates.openrouter_api_key : current.openrouter_api_key,
226
228
  telegram_bot_token: updates.telegram_bot_token !== undefined ? updates.telegram_bot_token : current.telegram_bot_token,
227
229
  telegram_default_agent_id: updates.telegram_default_agent_id !== undefined ? updates.telegram_default_agent_id : current.telegram_default_agent_id,
230
+ telegram_report_chat_id: updates.telegram_report_chat_id !== undefined ? updates.telegram_report_chat_id : current.telegram_report_chat_id,
228
231
  slack_bot_token: updates.slack_bot_token !== undefined ? updates.slack_bot_token : current.slack_bot_token,
229
232
  slack_signing_secret: updates.slack_signing_secret !== undefined ? updates.slack_signing_secret : current.slack_signing_secret,
230
233
  slack_default_agent_id: updates.slack_default_agent_id !== undefined ? updates.slack_default_agent_id : current.slack_default_agent_id,
@@ -251,6 +254,7 @@ async function writeConfig(updates) {
251
254
  openrouter_api_key: merged.openrouter_api_key ?? null,
252
255
  telegram_bot_token: merged.telegram_bot_token ?? null,
253
256
  telegram_default_agent_id: merged.telegram_default_agent_id ?? null,
257
+ telegram_report_chat_id: merged.telegram_report_chat_id ?? null,
254
258
  slack_bot_token: merged.slack_bot_token ?? null,
255
259
  slack_signing_secret: merged.slack_signing_secret ?? null,
256
260
  slack_default_agent_id: merged.slack_default_agent_id ?? null,
@@ -17914,6 +17918,7 @@ class MemoryStore {
17914
17918
  this.migrateMemoriesEmbedding();
17915
17919
  this.migrateAgentsScheduleEnabled();
17916
17920
  this.migrateConversationsGraphId();
17921
+ this.migrateAgentsScheduleReportTargets();
17917
17922
  }
17918
17923
  migrateMemoriesEmbedding() {
17919
17924
  try {
@@ -17930,6 +17935,11 @@ class MemoryStore {
17930
17935
  this.db.exec("ALTER TABLE conversations ADD COLUMN graph_id TEXT");
17931
17936
  } catch {}
17932
17937
  }
17938
+ migrateAgentsScheduleReportTargets() {
17939
+ try {
17940
+ this.db.exec("ALTER TABLE agents ADD COLUMN schedule_report_targets TEXT");
17941
+ } catch {}
17942
+ }
17933
17943
  insertMemory(args) {
17934
17944
  const embeddingJson = args.embedding && args.embedding.length > 0 ? JSON.stringify(args.embedding) : null;
17935
17945
  const stmt = this.db.prepare("INSERT INTO memories (user_id, agent_id, scope, text, tags, embedding) VALUES (?, ?, 'personal', ?, ?, ?)");
@@ -18051,6 +18061,7 @@ class MemoryStore {
18051
18061
  schedule: row.schedule ?? undefined,
18052
18062
  schedule_input: row.schedule_input ?? undefined,
18053
18063
  schedule_enabled: row.schedule_enabled !== undefined ? Number(row.schedule_enabled) === 1 : true,
18064
+ schedule_report_targets: row.schedule_report_targets ? JSON.parse(String(row.schedule_report_targets)) : undefined,
18054
18065
  avatar: row.avatar ?? undefined,
18055
18066
  user_created: Number(row.user_created) === 1,
18056
18067
  limits: row.limits ? JSON.parse(String(row.limits)) : undefined
@@ -18077,12 +18088,13 @@ class MemoryStore {
18077
18088
  const schedule = config.schedule != null ? String(config.schedule) : null;
18078
18089
  const schedule_input = config.schedule_input != null ? String(config.schedule_input) : null;
18079
18090
  const schedule_enabled = config.schedule_enabled === false ? 0 : 1;
18091
+ const schedule_report_targets = config.schedule_report_targets != null ? JSON.stringify(config.schedule_report_targets) : null;
18080
18092
  const avatar = config.avatar != null ? String(config.avatar) : null;
18081
18093
  const user_created = config.user_created === true ? 1 : 0;
18082
18094
  const limits = config.limits != null ? JSON.stringify(config.limits) : null;
18083
- const stmt = this.db.prepare(`INSERT INTO agents (id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, avatar, user_created, limits)
18084
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
18085
- stmt.run(id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, avatar, user_created, limits);
18095
+ const stmt = this.db.prepare(`INSERT INTO agents (id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, schedule_report_targets, avatar, user_created, limits)
18096
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
18097
+ stmt.run(id, name, model, description, personality, skills, tools, schedule, schedule_input, schedule_enabled, schedule_report_targets, avatar, user_created, limits);
18086
18098
  }
18087
18099
  updateAgent(id, updates) {
18088
18100
  const agent = this.getAgentById(id);
@@ -18099,8 +18111,9 @@ class MemoryStore {
18099
18111
  const schedule_input = updates.schedule_input !== undefined ? updates.schedule_input && String(updates.schedule_input).trim() ? String(updates.schedule_input).trim() : null : agent.schedule_input;
18100
18112
  const avatar = updates.avatar !== undefined ? updates.avatar && String(updates.avatar).trim() ? String(updates.avatar).trim() : null : agent.avatar;
18101
18113
  const schedule_enabled = updates.schedule_enabled !== undefined && updates.schedule_enabled !== null ? updates.schedule_enabled ? 1 : 0 : agent.schedule_enabled === true || agent.schedule_enabled === 1 ? 1 : 0;
18102
- const stmt = this.db.prepare("UPDATE agents SET name = ?, model = ?, description = ?, personality = ?, skills = ?, tools = ?, limits = ?, schedule = ?, schedule_input = ?, avatar = ?, schedule_enabled = ?, updated_at = datetime('now') WHERE id = ?");
18103
- stmt.run(name, model, description, personality, skills, tools, limits, schedule, schedule_input, avatar, schedule_enabled, id);
18114
+ const schedule_report_targets = updates.schedule_report_targets !== undefined ? updates.schedule_report_targets?.length ? JSON.stringify(updates.schedule_report_targets) : null : agent.schedule_report_targets != null ? typeof agent.schedule_report_targets === "string" ? agent.schedule_report_targets : JSON.stringify(agent.schedule_report_targets) : null;
18115
+ const stmt = this.db.prepare("UPDATE agents SET name = ?, model = ?, description = ?, personality = ?, skills = ?, tools = ?, limits = ?, schedule = ?, schedule_input = ?, avatar = ?, schedule_enabled = ?, schedule_report_targets = ?, updated_at = datetime('now') WHERE id = ?");
18116
+ stmt.run(name, model, description, personality, skills, tools, limits, schedule, schedule_input, avatar, schedule_enabled, schedule_report_targets, id);
18104
18117
  }
18105
18118
  deleteAgent(id) {
18106
18119
  const agent = this.getAgentById(id);
@@ -18456,6 +18469,9 @@ function validateAgentConfig(raw) {
18456
18469
  } else if (obj.schedule_enabled === true) {
18457
18470
  config.schedule_enabled = true;
18458
18471
  }
18472
+ if (Array.isArray(obj.schedule_report_targets)) {
18473
+ config.schedule_report_targets = obj.schedule_report_targets.filter((t) => t && typeof t === "object" && t.channel === "telegram" && typeof t.address === "string" && String(t.address).trim() !== "").map((t) => ({ channel: "telegram", address: String(t.address).trim() }));
18474
+ }
18459
18475
  if (obj.avatar != null && typeof obj.avatar === "string" && obj.avatar.trim()) {
18460
18476
  config.avatar = obj.avatar.trim();
18461
18477
  }
@@ -18704,6 +18720,9 @@ async function updateAgent(id, updates) {
18704
18720
  if (updates.schedule_enabled !== undefined && updates.schedule_enabled !== null) {
18705
18721
  parsed.schedule_enabled = updates.schedule_enabled;
18706
18722
  }
18723
+ if (updates.schedule_report_targets !== undefined) {
18724
+ parsed.schedule_report_targets = updates.schedule_report_targets ?? undefined;
18725
+ }
18707
18726
  const agent = parseAgentConfig(parsed);
18708
18727
  await writeFile2(path, JSON.stringify(parsed, null, 2), "utf-8");
18709
18728
  return agent;
@@ -28074,7 +28093,7 @@ async function getTaskById(id) {
28074
28093
  const task = await memoryTaskStore.getById(id);
28075
28094
  return task ?? undefined;
28076
28095
  }
28077
- async function enqueueTask(agent_id, input) {
28096
+ async function enqueueTask(agent_id, input, scheduled_run = false) {
28078
28097
  const id = randomUUID();
28079
28098
  const t = {
28080
28099
  id,
@@ -28082,12 +28101,13 @@ async function enqueueTask(agent_id, input) {
28082
28101
  input,
28083
28102
  status: "queued",
28084
28103
  created_at: nowIso(),
28085
- updated_at: nowIso()
28104
+ updated_at: nowIso(),
28105
+ ...scheduled_run && { scheduled_run: true }
28086
28106
  };
28087
28107
  await memoryTaskStore.enqueue(t);
28088
28108
  return t;
28089
28109
  }
28090
- async function enqueueGraphTask(graph_id, input) {
28110
+ async function enqueueGraphTask(graph_id, input, scheduled_run = false) {
28091
28111
  const id = randomUUID();
28092
28112
  const t = {
28093
28113
  id,
@@ -28095,7 +28115,8 @@ async function enqueueGraphTask(graph_id, input) {
28095
28115
  input,
28096
28116
  status: "queued",
28097
28117
  created_at: nowIso(),
28098
- updated_at: nowIso()
28118
+ updated_at: nowIso(),
28119
+ ...scheduled_run && { scheduled_run: true }
28099
28120
  };
28100
28121
  await memoryTaskStore.enqueue(t);
28101
28122
  return t;
@@ -28116,7 +28137,7 @@ function startScheduler(store = memoryTaskStore) {
28116
28137
  const current = await loadAgents();
28117
28138
  const a = current.find((x) => x.id === agentId);
28118
28139
  const input = a?.schedule_input?.trim() || "Scheduled run";
28119
- await enqueueTask(agentId, input);
28140
+ await enqueueTask(agentId, input, true);
28120
28141
  });
28121
28142
  }
28122
28143
  const graphSummaries = await listGraphs();
@@ -28128,7 +28149,7 @@ function startScheduler(store = memoryTaskStore) {
28128
28149
  import_node_cron.default.schedule(graph.schedule, async () => {
28129
28150
  const g = await loadGraph(gid);
28130
28151
  const input = g?.schedule_input?.trim() || "Scheduled run";
28131
- await enqueueGraphTask(gid, input);
28152
+ await enqueueGraphTask(gid, input, true);
28132
28153
  });
28133
28154
  }
28134
28155
  } catch (err) {
@@ -28607,6 +28628,7 @@ async function handleSettings(req) {
28607
28628
  has_openrouter_key: Boolean(config2.openrouter_api_key?.trim()),
28608
28629
  telegram_configured: Boolean(config2.telegram_bot_token?.trim()),
28609
28630
  telegram_default_agent_id: config2.telegram_default_agent_id ?? null,
28631
+ telegram_report_chat_id: config2.telegram_report_chat_id ?? null,
28610
28632
  slack_configured: Boolean(config2.slack_bot_token?.trim()),
28611
28633
  slack_default_agent_id: config2.slack_default_agent_id ?? null,
28612
28634
  discord_configured: Boolean(config2.discord_bot_token?.trim()),
@@ -28635,6 +28657,7 @@ async function handleSettings(req) {
28635
28657
  const openrouter_api_key = body.openrouter_api_key !== undefined ? typeof body.openrouter_api_key === "string" ? body.openrouter_api_key.trim() || undefined : undefined : current.openrouter_api_key;
28636
28658
  const telegram_bot_token = body.telegram_bot_token !== undefined ? typeof body.telegram_bot_token === "string" ? body.telegram_bot_token.trim() : undefined : current.telegram_bot_token;
28637
28659
  const telegram_default_agent_id = body.telegram_default_agent_id !== undefined ? typeof body.telegram_default_agent_id === "string" ? body.telegram_default_agent_id.trim() || undefined : undefined : current.telegram_default_agent_id;
28660
+ const telegram_report_chat_id = body.telegram_report_chat_id !== undefined ? typeof body.telegram_report_chat_id === "string" ? body.telegram_report_chat_id.trim() || undefined : undefined : current.telegram_report_chat_id;
28638
28661
  const slack_bot_token = body.slack_bot_token !== undefined ? typeof body.slack_bot_token === "string" ? body.slack_bot_token.trim() : undefined : current.slack_bot_token;
28639
28662
  const slack_signing_secret = body.slack_signing_secret !== undefined ? typeof body.slack_signing_secret === "string" ? body.slack_signing_secret.trim() : undefined : current.slack_signing_secret;
28640
28663
  const slack_default_agent_id = body.slack_default_agent_id !== undefined ? typeof body.slack_default_agent_id === "string" ? body.slack_default_agent_id.trim() || undefined : undefined : current.slack_default_agent_id;
@@ -28655,6 +28678,7 @@ async function handleSettings(req) {
28655
28678
  openrouter_api_key: openrouter_api_key ?? undefined,
28656
28679
  telegram_bot_token: telegram_bot_token || undefined,
28657
28680
  telegram_default_agent_id: telegram_default_agent_id || undefined,
28681
+ telegram_report_chat_id: telegram_report_chat_id ?? undefined,
28658
28682
  slack_bot_token: slack_bot_token || undefined,
28659
28683
  slack_signing_secret: slack_signing_secret ?? undefined,
28660
28684
  slack_default_agent_id: slack_default_agent_id || undefined,
@@ -29231,6 +29255,11 @@ async function processTelegramUpdate(memoryStore, body) {
29231
29255
  const botToken = config2.telegram_bot_token?.trim();
29232
29256
  if (!botToken)
29233
29257
  return;
29258
+ if (text === "/set_report_chat" || text === "/setreportchat") {
29259
+ await writeConfig({ telegram_report_chat_id: String(chatId) });
29260
+ await sendTelegramMessage(botToken, chatId, "\u2713 This chat will receive schedule reports. You can change it anytime by sending /set_report_chat from another chat.");
29261
+ return;
29262
+ }
29234
29263
  const agent = await getDefaultAgent(config2, "telegram_default_agent_id");
29235
29264
  if (!agent) {
29236
29265
  await sendTelegramMessage(botToken, chatId, "No agent configured. Set default agent in Settings.");
@@ -29794,6 +29823,95 @@ async function handleViberWebhook(req, memoryStore) {
29794
29823
  // src/server.ts
29795
29824
  init_config();
29796
29825
 
29826
+ // src/core/schedule-reports.ts
29827
+ init_config();
29828
+ var MAX_REPORT_LENGTH = 4000;
29829
+ function buildReportMessage(task, label) {
29830
+ const status = task.status === "completed" ? "\u2705 Completed" : "\u274C Failed";
29831
+ const output = task.result?.output?.trim() ?? "";
29832
+ const error2 = task.result?.error?.trim() ?? "";
29833
+ const body = task.status === "completed" ? output : error2 || output;
29834
+ const truncated = body.length > MAX_REPORT_LENGTH ? body.slice(0, MAX_REPORT_LENGTH) + "\u2026" : body;
29835
+ return [
29836
+ `[Schedule report] ${label}`,
29837
+ `Status: ${status}`,
29838
+ truncated ? `
29839
+ ${truncated}` : ""
29840
+ ].join(`
29841
+ `).trim();
29842
+ }
29843
+ async function sendTelegramReport(botToken, chatId, text) {
29844
+ console.log("[schedule-reports] Sending to Telegram chat_id:", chatId, "message length:", text.length);
29845
+ const url = `https://api.telegram.org/bot${botToken}/sendMessage`;
29846
+ const res = await fetch(url, {
29847
+ method: "POST",
29848
+ headers: { "Content-Type": "application/json" },
29849
+ body: JSON.stringify({
29850
+ chat_id: chatId,
29851
+ text: text.slice(0, 4096)
29852
+ })
29853
+ });
29854
+ if (res.ok) {
29855
+ console.log("[schedule-reports] Telegram sendMessage OK for chat_id:", chatId);
29856
+ } else {
29857
+ const err = await res.text();
29858
+ console.error("[schedule-reports] Telegram sendMessage failed:", res.status, "chat_id:", chatId, "error:", err);
29859
+ }
29860
+ }
29861
+ async function handleTaskFinished(event) {
29862
+ const task = event.data.task;
29863
+ console.log("[schedule-reports] handleTaskFinished task_id:", task.id, "status:", task.status, "scheduled_run:", task.scheduled_run, "agent_id:", task.agent_id, "graph_id:", task.graph_id);
29864
+ const targets = [];
29865
+ let label;
29866
+ if (task.agent_id) {
29867
+ const agent = await getAgent(task.agent_id);
29868
+ if (!agent?.schedule_report_targets?.length) {
29869
+ console.log("[schedule-reports] Agent", task.agent_id, "has no schedule_report_targets; skipping.");
29870
+ return;
29871
+ }
29872
+ targets.push(...agent.schedule_report_targets.filter((t) => t.channel === "telegram"));
29873
+ label = `Agent "${agent.name}" (${task.agent_id})`;
29874
+ } else if (task.graph_id) {
29875
+ const graph = await loadGraph(task.graph_id);
29876
+ if (!graph?.schedule_report_targets?.length) {
29877
+ console.log("[schedule-reports] Graph", task.graph_id, "has no schedule_report_targets; skipping.");
29878
+ return;
29879
+ }
29880
+ targets.push(...graph.schedule_report_targets.filter((t) => t.channel === "telegram"));
29881
+ label = `Graph "${task.graph_id}"`;
29882
+ } else {
29883
+ return;
29884
+ }
29885
+ if (targets.length === 0)
29886
+ return;
29887
+ const config2 = await readConfig();
29888
+ const botToken = config2.telegram_bot_token?.trim();
29889
+ if (!botToken) {
29890
+ console.warn("[schedule-reports] Telegram bot token not configured; skipping report.");
29891
+ return;
29892
+ }
29893
+ const defaultChatId = config2.telegram_report_chat_id?.trim();
29894
+ console.log("[schedule-reports] Sending report for", label, "targets:", targets.length, "defaultChatId from config:", defaultChatId ?? "(not set)");
29895
+ const message = buildReportMessage(task, label);
29896
+ for (const t of targets) {
29897
+ const address = t.address.trim();
29898
+ if (!address)
29899
+ continue;
29900
+ const chatId = address === "__default__" ? defaultChatId : address;
29901
+ if (!chatId) {
29902
+ if (address === "__default__") {
29903
+ console.warn("[schedule-reports] Schedule report target is 'from Settings' but no Telegram report chat is set. Send /set_report_chat to your bot in Telegram, then set it in Settings > Telegram.");
29904
+ }
29905
+ continue;
29906
+ }
29907
+ await sendTelegramReport(botToken, chatId, message);
29908
+ }
29909
+ }
29910
+ function initScheduleReports() {
29911
+ subscribe("task.completed", (event) => handleTaskFinished(event));
29912
+ subscribe("task.failed", (event) => handleTaskFinished(event));
29913
+ }
29914
+
29797
29915
  // src/core/plugins.ts
29798
29916
  import { readdir as readdir5, stat as stat2 } from "fs/promises";
29799
29917
  import { join as join12 } from "path";
@@ -29990,6 +30108,7 @@ function serveDashboard(pathname) {
29990
30108
  for (const type of EVENT_TYPES) {
29991
30109
  subscribe(type, broadcastEvent);
29992
30110
  }
30111
+ initScheduleReports();
29993
30112
  function createRoutes() {
29994
30113
  return {
29995
30114
  "/*": {
@@ -30021,6 +30140,7 @@ function createRoutes() {
30021
30140
  schedule: a.schedule ?? null,
30022
30141
  schedule_input: a.schedule_input ?? null,
30023
30142
  schedule_enabled: a.schedule_enabled ?? true,
30143
+ schedule_report_targets: a.schedule_report_targets ?? null,
30024
30144
  skills: a.skills ?? [],
30025
30145
  tools: a.tools ?? [],
30026
30146
  avatar: a.avatar ?? null,
@@ -30082,7 +30202,8 @@ function createRoutes() {
30082
30202
  schedule: body.schedule,
30083
30203
  schedule_input: body.schedule_input,
30084
30204
  avatar: body.avatar,
30085
- schedule_enabled: body.schedule_enabled
30205
+ schedule_enabled: body.schedule_enabled,
30206
+ schedule_report_targets: Array.isArray(body.schedule_report_targets) ? body.schedule_report_targets : undefined
30086
30207
  });
30087
30208
  return jsonResponse({
30088
30209
  ok: true,
@@ -30097,6 +30218,7 @@ function createRoutes() {
30097
30218
  schedule: agent.schedule ?? null,
30098
30219
  schedule_input: agent.schedule_input ?? null,
30099
30220
  schedule_enabled: agent.schedule_enabled ?? true,
30221
+ schedule_report_targets: agent.schedule_report_targets ?? null,
30100
30222
  avatar: agent.avatar ?? null,
30101
30223
  limits: agent.limits ?? null
30102
30224
  }
@@ -30188,7 +30310,8 @@ function createRoutes() {
30188
30310
  edges: Array.isArray(body.edges) ? body.edges : existing?.edges ?? [],
30189
30311
  schedule: body.schedule !== undefined ? body.schedule && String(body.schedule).trim() ? String(body.schedule).trim() : undefined : existing?.schedule,
30190
30312
  schedule_input: body.schedule_input !== undefined ? body.schedule_input && String(body.schedule_input).trim() ? String(body.schedule_input).trim() : undefined : existing?.schedule_input,
30191
- schedule_enabled: body.schedule_enabled !== undefined ? body.schedule_enabled : existing?.schedule_enabled !== false
30313
+ schedule_enabled: body.schedule_enabled !== undefined ? body.schedule_enabled : existing?.schedule_enabled !== false,
30314
+ schedule_report_targets: body.schedule_report_targets !== undefined ? Array.isArray(body.schedule_report_targets) ? body.schedule_report_targets.filter((t) => t?.channel === "telegram" && typeof t?.address === "string").map((t) => ({ channel: "telegram", address: String(t.address).trim() })).filter((t) => t.address.length > 0) : undefined : existing?.schedule_report_targets
30192
30315
  };
30193
30316
  if (!graph.nodes.length) {
30194
30317
  return jsonResponse({ error: "Graph must have at least one node" }, 400);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sulala/agent-os",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },