@stamn/stamn-plugin 0.1.0-alpha.32 → 0.1.0-alpha.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
@@ -4472,7 +4472,7 @@ ${l}
4472
4472
  }
4473
4473
  } }).prompt();
4474
4474
 
4475
- // node_modules/.pnpm/@stamn+sdk@0.1.0-alpha.2/node_modules/@stamn/sdk/dist/index.js
4475
+ // node_modules/.pnpm/@stamn+sdk@0.1.0-alpha.3/node_modules/@stamn/sdk/dist/index.js
4476
4476
  var Resource = class {
4477
4477
  constructor(client) {
4478
4478
  this.client = client;
@@ -4676,6 +4676,42 @@ var ServicesResource = class extends Resource {
4676
4676
  );
4677
4677
  }
4678
4678
  };
4679
+ var RuntimeResource = class extends Resource {
4680
+ async listHosts() {
4681
+ const res = await this.client.request(
4682
+ "GET",
4683
+ "/v1/runtime/hosts"
4684
+ );
4685
+ return res.data;
4686
+ }
4687
+ async listFiles(scope, hostname2) {
4688
+ const params = new URLSearchParams({ scope });
4689
+ if (hostname2) params.set("hostname", hostname2);
4690
+ const res = await this.client.request("GET", `/v1/runtime/files?${params}`);
4691
+ return res.data.files;
4692
+ }
4693
+ async readFile(scope, path, hostname2) {
4694
+ const params = new URLSearchParams({ scope, path });
4695
+ if (hostname2) params.set("hostname", hostname2);
4696
+ const res = await this.client.request("GET", `/v1/runtime/files/read?${params}`);
4697
+ return res.data;
4698
+ }
4699
+ async writeFile(scope, path, content, hostname2) {
4700
+ const res = await this.client.request("PATCH", "/v1/runtime/files/write", { scope, path, content, hostname: hostname2 });
4701
+ return res.data;
4702
+ }
4703
+ async readConfig(hostname2) {
4704
+ const params = new URLSearchParams();
4705
+ if (hostname2) params.set("hostname", hostname2);
4706
+ const qs = params.toString();
4707
+ const res = await this.client.request("GET", `/v1/runtime/config${qs ? `?${qs}` : ""}`);
4708
+ return res.data;
4709
+ }
4710
+ async writeConfig(content, hostname2) {
4711
+ const res = await this.client.request("PATCH", "/v1/runtime/config", { content, hostname: hostname2 });
4712
+ return res.data;
4713
+ }
4714
+ };
4679
4715
  var StamnApiError = class extends Error {
4680
4716
  constructor(message, status) {
4681
4717
  super(message);
@@ -4702,6 +4738,7 @@ var StamnClient = class {
4702
4738
  leaderboard;
4703
4739
  health;
4704
4740
  services;
4741
+ runtime;
4705
4742
  constructor(options = {}) {
4706
4743
  this.apiKey = options.apiKey;
4707
4744
  this.retryOptions = { ...DEFAULT_RETRY, ...options.retry };
@@ -4713,6 +4750,7 @@ var StamnClient = class {
4713
4750
  this.leaderboard = new LeaderboardResource(this);
4714
4751
  this.health = new HealthResource(this);
4715
4752
  this.services = new ServicesResource(this);
4753
+ this.runtime = new RuntimeResource(this);
4716
4754
  }
4717
4755
  setApiKey(apiKey) {
4718
4756
  this.apiKey = apiKey;
@@ -4767,7 +4805,7 @@ var StamnClient = class {
4767
4805
  return Math.random() * capped;
4768
4806
  }
4769
4807
  sleep(ms) {
4770
- return new Promise((resolve2) => setTimeout(resolve2, ms));
4808
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
4771
4809
  }
4772
4810
  async parseErrorResponse(res) {
4773
4811
  const body = await res.text();
@@ -4781,7 +4819,7 @@ var StamnClient = class {
4781
4819
  }
4782
4820
  };
4783
4821
 
4784
- // node_modules/.pnpm/@stamn+cli@0.1.0-alpha.7/node_modules/@stamn/cli/dist/chunk-Z2IAJQOV.js
4822
+ // node_modules/.pnpm/@stamn+cli@0.1.0-alpha.10/node_modules/@stamn/cli/dist/chunk-VAKVDZRN.js
4785
4823
  import { execSync } from "child_process";
4786
4824
  import { mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
4787
4825
  import { join } from "path";
@@ -4862,7 +4900,7 @@ async function handleAgentRegister(opts, adapter) {
4862
4900
  const match = agents.find((a) => a.name === name);
4863
4901
  if (match) {
4864
4902
  s.stop("Agent found.");
4865
- adapter.writeConfig({ agentId: match.id, agentName: match.name });
4903
+ writeResult(adapter, name, match.id, match.name, config.apiKey);
4866
4904
  R2.success(`Agent "${match.name}" (${match.id}) already exists. Selected as active.`);
4867
4905
  Gt("Done!");
4868
4906
  process.exit(0);
@@ -4870,8 +4908,9 @@ async function handleAgentRegister(opts, adapter) {
4870
4908
  s.start("Registering agent...");
4871
4909
  const participant = await client.participants.create({ name });
4872
4910
  s.stop("Agent registered.");
4873
- adapter.writeConfig({ agentId: participant.id, agentName: participant.name });
4911
+ writeResult(adapter, name, participant.id, participant.name, config.apiKey);
4874
4912
  R2.success(`Agent "${participant.name}" (${participant.id})`);
4913
+ R2.info(`Bound to OpenClaw agent "${name}".`);
4875
4914
  Gt("Done!");
4876
4915
  process.exit(0);
4877
4916
  } catch (err) {
@@ -4880,6 +4919,10 @@ async function handleAgentRegister(opts, adapter) {
4880
4919
  process.exit(1);
4881
4920
  }
4882
4921
  }
4922
+ function writeResult(adapter, name, agentId, agentName, apiKey) {
4923
+ adapter.writeAgentBinding(name, { agentId, apiKey, agentName });
4924
+ adapter.writeConfig({ agentId, agentName });
4925
+ }
4883
4926
  async function handleAgentList(_opts, adapter) {
4884
4927
  Wt2("Stamn Agents");
4885
4928
  const config = adapter.readConfig();
@@ -4927,8 +4970,13 @@ async function handleAgentSelect(opts, adapter) {
4927
4970
  process.exit(1);
4928
4971
  return;
4929
4972
  }
4930
- adapter.writeConfig({ agentId: match.id, agentName: match.name });
4931
- R2.success(`Active agent set to "${match.name}" (${match.id})`);
4973
+ if (opts.bind) {
4974
+ adapter.writeAgentBinding(opts.bind, { agentId: match.id, apiKey: config.apiKey, agentName: match.name });
4975
+ R2.success(`Agent "${match.name}" (${match.id}) bound to OpenClaw agent "${opts.bind}".`);
4976
+ } else {
4977
+ adapter.writeConfig({ agentId: match.id, agentName: match.name });
4978
+ R2.success(`Active agent set to "${match.name}" (${match.id})`);
4979
+ }
4932
4980
  Gt("Done!");
4933
4981
  process.exit(0);
4934
4982
  } catch (err) {
@@ -5138,6 +5186,15 @@ function createOpenclawAdapter() {
5138
5186
  };
5139
5187
  writeJsonFile(getConfigPath(), config);
5140
5188
  },
5189
+ writeAgentBinding(openclawAgentId, binding) {
5190
+ const config = readOpenclawConfig();
5191
+ ensurePluginConfig(config);
5192
+ config.plugins.entries[PLUGIN_ID].enabled = true;
5193
+ const pluginConfig = config.plugins.entries[PLUGIN_ID].config;
5194
+ if (!pluginConfig.agents) pluginConfig.agents = {};
5195
+ pluginConfig.agents[openclawAgentId] = binding;
5196
+ writeJsonFile(getConfigPath(), config);
5197
+ },
5141
5198
  readStatusFile() {
5142
5199
  return readJsonFile(join3(homedir(), ".openclaw", "stamn-status.json"));
5143
5200
  },
@@ -5222,7 +5279,7 @@ function registerCli(api) {
5222
5279
  const agent = stamn.command("agent").description("Agent management");
5223
5280
  agent.command("register").description("Register a new agent or reconnect to an existing one").option("--name <name>", "Agent name").action((opts) => handleAgentRegister(opts, adapter));
5224
5281
  agent.command("list").description("List agents under your account").action(() => handleAgentList({}, adapter));
5225
- agent.command("select").description("Set active agent").argument("<nameOrId>", "Agent name or ID").action((nameOrId) => handleAgentSelect({ nameOrId }, adapter));
5282
+ agent.command("select").description("Set active agent").argument("<nameOrId>", "Agent name or ID").option("--bind <agentId>", "Bind to a specific OpenClaw agent ID (for multi-agent setups)").action((nameOrId, opts) => handleAgentSelect({ nameOrId, ...opts }, adapter));
5226
5283
  agent.command("config").description("View or update agent configuration").option("--name <name>", "Agent display name").option("--personality", "Open editor to set agent personality").action((opts) => handleConfig(opts, adapter));
5227
5284
  stamn.command("status").description("Show connection status and server health").action(() => handleStatus(adapter));
5228
5285
  stamn.command("update").description("Update the Stamn plugin to the latest version").action(() => handleUpdate());
@@ -5394,6 +5451,114 @@ function writeWorkspaceFile(relativePath, content) {
5394
5451
  return { path: relativePath, written: true };
5395
5452
  }
5396
5453
 
5454
+ // src/global-files.ts
5455
+ import { readdirSync as readdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync5, statSync as statSync3, mkdirSync as mkdirSync4, realpathSync as realpathSync2, existsSync as existsSync3 } from "fs";
5456
+ import { join as join7, resolve as resolve2, relative as relative2, dirname as dirname3 } from "path";
5457
+ import { homedir as homedir4 } from "os";
5458
+ var OPENCLAW_DIR = join7(homedir4(), ".openclaw");
5459
+ var CONFIG_FILE = join7(OPENCLAW_DIR, "openclaw.json");
5460
+ var SCOPE_DIRS = {
5461
+ skills: join7(OPENCLAW_DIR, "skills"),
5462
+ workspace: join7(OPENCLAW_DIR, "workspace"),
5463
+ config: OPENCLAW_DIR
5464
+ };
5465
+ function resolveBaseDir(scope) {
5466
+ const dir = SCOPE_DIRS[scope];
5467
+ if (!dir) throw new Error(`Invalid scope: ${scope}`);
5468
+ return dir;
5469
+ }
5470
+ function realBase(dir) {
5471
+ try {
5472
+ return realpathSync2(dir);
5473
+ } catch {
5474
+ return dir;
5475
+ }
5476
+ }
5477
+ function assertWithinScope(scope, relativePath) {
5478
+ const base = resolveBaseDir(scope);
5479
+ const full = resolve2(base, relativePath);
5480
+ if (!full.startsWith(base + "/") && full !== base) {
5481
+ throw new Error("Path outside scope");
5482
+ }
5483
+ const baseReal = realBase(base);
5484
+ try {
5485
+ const realFull = realpathSync2(full);
5486
+ if (!realFull.startsWith(baseReal + "/") && realFull !== baseReal) {
5487
+ throw new Error("Path outside scope");
5488
+ }
5489
+ } catch (err) {
5490
+ if (err.code === "ENOENT") {
5491
+ try {
5492
+ const parentReal = realpathSync2(dirname3(full));
5493
+ if (!parentReal.startsWith(baseReal + "/") && parentReal !== baseReal) {
5494
+ throw new Error("Path outside scope");
5495
+ }
5496
+ } catch {
5497
+ }
5498
+ } else {
5499
+ throw err;
5500
+ }
5501
+ }
5502
+ return full;
5503
+ }
5504
+ function walkDir2(dir, base) {
5505
+ const results = [];
5506
+ let entries;
5507
+ try {
5508
+ entries = readdirSync2(dir, { withFileTypes: true });
5509
+ } catch {
5510
+ return results;
5511
+ }
5512
+ for (const entry of entries) {
5513
+ const fullPath = join7(dir, entry.name);
5514
+ if (entry.isDirectory()) {
5515
+ results.push(...walkDir2(fullPath, base));
5516
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
5517
+ const stat = statSync3(fullPath);
5518
+ results.push({
5519
+ path: relative2(base, fullPath),
5520
+ size: stat.size,
5521
+ modifiedAt: stat.mtime.toISOString()
5522
+ });
5523
+ }
5524
+ }
5525
+ return results;
5526
+ }
5527
+ function listGlobalFiles(scope) {
5528
+ const base = resolveBaseDir(scope);
5529
+ return walkDir2(base, base);
5530
+ }
5531
+ function readGlobalFile(scope, relativePath) {
5532
+ const full = assertWithinScope(scope, relativePath);
5533
+ const content = readFileSync4(full, "utf-8");
5534
+ const stat = statSync3(full);
5535
+ return { path: relativePath, content, size: stat.size };
5536
+ }
5537
+ function writeGlobalFile(scope, relativePath, content) {
5538
+ const full = assertWithinScope(scope, relativePath);
5539
+ mkdirSync4(dirname3(full), { recursive: true });
5540
+ writeFileSync5(full, content, "utf-8");
5541
+ return { path: relativePath, written: true };
5542
+ }
5543
+ function readOpenclawConfig2() {
5544
+ if (!existsSync3(CONFIG_FILE)) {
5545
+ return { path: "openclaw.json", content: "{}", size: 2 };
5546
+ }
5547
+ const content = readFileSync4(CONFIG_FILE, "utf-8");
5548
+ const stat = statSync3(CONFIG_FILE);
5549
+ return { path: "openclaw.json", content, size: stat.size };
5550
+ }
5551
+ function writeOpenclawConfig(content) {
5552
+ try {
5553
+ JSON.parse(content);
5554
+ } catch {
5555
+ throw new Error("Invalid JSON: config must be valid JSON");
5556
+ }
5557
+ mkdirSync4(dirname3(CONFIG_FILE), { recursive: true });
5558
+ writeFileSync5(CONFIG_FILE, content, "utf-8");
5559
+ return { path: "openclaw.json", written: true };
5560
+ }
5561
+
5397
5562
  // src/ws-service.ts
5398
5563
  var MAX_EVENT_BUFFER_SIZE = 200;
5399
5564
  var BASE_RECONNECT_DELAY_MS = 1e3;
@@ -5583,6 +5748,26 @@ var StamnWsService = class {
5583
5748
  this.handleWriteFile(payload.params);
5584
5749
  return;
5585
5750
  }
5751
+ if (payload.command === "list_global_files") {
5752
+ this.handleListGlobalFiles(payload.params);
5753
+ return;
5754
+ }
5755
+ if (payload.command === "read_global_file") {
5756
+ this.handleReadGlobalFile(payload.params);
5757
+ return;
5758
+ }
5759
+ if (payload.command === "write_global_file") {
5760
+ this.handleWriteGlobalFile(payload.params);
5761
+ return;
5762
+ }
5763
+ if (payload.command === "read_openclaw_config") {
5764
+ this.handleReadOpenclawConfig(payload.params);
5765
+ return;
5766
+ }
5767
+ if (payload.command === "write_openclaw_config") {
5768
+ this.handleWriteOpenclawConfig(payload.params);
5769
+ return;
5770
+ }
5586
5771
  this.logger.info(`Command received: ${payload.command} (${payload.commandId})`);
5587
5772
  if (payload.command === "update_plugin") {
5588
5773
  this.handleUpdatePlugin();
@@ -5676,6 +5861,87 @@ var StamnWsService = class {
5676
5861
  });
5677
5862
  }
5678
5863
  }
5864
+ handleListGlobalFiles(params) {
5865
+ try {
5866
+ const files = listGlobalFiles(params.scope);
5867
+ this.sendMessage("participant:file_response", {
5868
+ requestId: params.requestId,
5869
+ files
5870
+ });
5871
+ } catch (err) {
5872
+ this.sendMessage("participant:file_response", {
5873
+ requestId: params.requestId,
5874
+ files: [],
5875
+ error: err.message
5876
+ });
5877
+ }
5878
+ }
5879
+ handleReadGlobalFile(params) {
5880
+ try {
5881
+ const result = readGlobalFile(params.scope, params.path);
5882
+ this.sendMessage("participant:file_response", {
5883
+ requestId: params.requestId,
5884
+ ...result
5885
+ });
5886
+ } catch (err) {
5887
+ this.sendMessage("participant:file_response", {
5888
+ requestId: params.requestId,
5889
+ path: params.path,
5890
+ content: "",
5891
+ size: 0,
5892
+ error: err.message
5893
+ });
5894
+ }
5895
+ }
5896
+ handleWriteGlobalFile(params) {
5897
+ try {
5898
+ const result = writeGlobalFile(params.scope, params.path, params.content);
5899
+ this.sendMessage("participant:file_response", {
5900
+ requestId: params.requestId,
5901
+ ...result
5902
+ });
5903
+ } catch (err) {
5904
+ this.sendMessage("participant:file_response", {
5905
+ requestId: params.requestId,
5906
+ path: params.path,
5907
+ written: false,
5908
+ error: err.message
5909
+ });
5910
+ }
5911
+ }
5912
+ handleReadOpenclawConfig(params) {
5913
+ try {
5914
+ const result = readOpenclawConfig2();
5915
+ this.sendMessage("participant:file_response", {
5916
+ requestId: params.requestId,
5917
+ ...result
5918
+ });
5919
+ } catch (err) {
5920
+ this.sendMessage("participant:file_response", {
5921
+ requestId: params.requestId,
5922
+ path: "openclaw.json",
5923
+ content: "",
5924
+ size: 0,
5925
+ error: err.message
5926
+ });
5927
+ }
5928
+ }
5929
+ handleWriteOpenclawConfig(params) {
5930
+ try {
5931
+ const result = writeOpenclawConfig(params.content);
5932
+ this.sendMessage("participant:file_response", {
5933
+ requestId: params.requestId,
5934
+ ...result
5935
+ });
5936
+ } catch (err) {
5937
+ this.sendMessage("participant:file_response", {
5938
+ requestId: params.requestId,
5939
+ path: "openclaw.json",
5940
+ written: false,
5941
+ error: err.message
5942
+ });
5943
+ }
5944
+ }
5679
5945
  onAuthError(payload) {
5680
5946
  this.authFailed = true;
5681
5947
  this.logger.error(`Authentication failed: ${payload.reason}`);