@stamn/stamn-plugin 0.1.0-alpha.27 → 0.1.0-alpha.29

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
@@ -5085,6 +5085,7 @@ function readOpenclawConfig() {
5085
5085
  return readJsonFile(getConfigPath()) ?? {};
5086
5086
  }
5087
5087
  var STAMN_TOOL_NAMES = [
5088
+ "stamn_ping",
5088
5089
  "stamn_world_status",
5089
5090
  "stamn_get_events",
5090
5091
  "stamn_get_balance",
@@ -5331,16 +5332,19 @@ function respondToService(ws) {
5331
5332
  properties: {
5332
5333
  requestId: param("string", "The requestId from the incoming event."),
5333
5334
  output: param("string", "The result/output of the service."),
5334
- success: param("string", "Whether it succeeded.", { enum: ["true", "false"] })
5335
+ success: param("string", "Whether it succeeded.", { enum: ["true", "false"] }),
5336
+ domain: param("string", 'Optional domain tag for experience tracking (e.g. "typescript-nestjs-monorepos").')
5335
5337
  },
5336
5338
  required: ["requestId", "output", "success"]
5337
5339
  },
5338
5340
  execute: (_id, args) => {
5339
- ws.send("participant:service_result", {
5341
+ const payload = {
5340
5342
  requestId: args.requestId,
5341
5343
  output: args.output,
5342
5344
  success: args.success === "true"
5343
- });
5345
+ };
5346
+ if (args.domain) payload.domain = args.domain;
5347
+ ws.send("participant:service_result", payload);
5344
5348
  return text(`Service response sent for request ${args.requestId}.`);
5345
5349
  }
5346
5350
  };
@@ -5550,6 +5554,272 @@ function spend(ws) {
5550
5554
  }
5551
5555
  };
5552
5556
  }
5557
+ function ping() {
5558
+ return {
5559
+ name: "stamn_ping",
5560
+ description: "Diagnostic ping. Returns OK if the Stamn plugin tools are loaded and reachable by the agent.",
5561
+ parameters: NO_PARAMS,
5562
+ execute: () => text("pong \u2014 stamn plugin tools are loaded and reachable.")
5563
+ };
5564
+ }
5565
+ function getReputation(ws) {
5566
+ return {
5567
+ name: "stamn_get_reputation",
5568
+ description: "Get your reputation score and reviews. Returns trust score (0-1000), completion rate, review average, and score breakdown.",
5569
+ parameters: NO_PARAMS,
5570
+ execute: () => {
5571
+ ws.send("participant:get_reviews", {});
5572
+ return text("Reputation request sent. Check events for the response (server:reviews).");
5573
+ }
5574
+ };
5575
+ }
5576
+ function reviewService(ws) {
5577
+ return {
5578
+ name: "stamn_review_service",
5579
+ description: "Rate a completed service you purchased. Only the buyer can review. Rating is 1-5 stars.",
5580
+ parameters: {
5581
+ type: "object",
5582
+ properties: {
5583
+ requestId: param("string", "The requestId of the completed service job."),
5584
+ rating: param("string", "Rating from 1 to 5.", { enum: ["1", "2", "3", "4", "5"] }),
5585
+ comment: param("string", "Optional review comment.")
5586
+ },
5587
+ required: ["requestId", "rating"]
5588
+ },
5589
+ execute: (_id, args) => {
5590
+ ws.send("participant:service_review", {
5591
+ requestId: args.requestId,
5592
+ rating: Number(args.rating),
5593
+ ...args.comment ? { comment: args.comment } : {}
5594
+ });
5595
+ return text(`Review submitted for request ${args.requestId}. Check events for confirmation.`);
5596
+ }
5597
+ };
5598
+ }
5599
+ function getReviews(ws) {
5600
+ return {
5601
+ name: "stamn_get_reviews",
5602
+ description: "Get reviews received for your services along with your reputation score.",
5603
+ parameters: NO_PARAMS,
5604
+ execute: () => {
5605
+ ws.send("participant:get_reviews", {});
5606
+ return text("Reviews request sent. Check events for the response (server:reviews).");
5607
+ }
5608
+ };
5609
+ }
5610
+ function getExperience(ws) {
5611
+ return {
5612
+ name: "stamn_get_experience",
5613
+ description: "Get your experience profiles \u2014 verifiable work history by service tag and domain. Shows jobs completed, success rate, volume, and response time.",
5614
+ parameters: NO_PARAMS,
5615
+ execute: () => {
5616
+ ws.send("participant:get_experience", {});
5617
+ return text("Experience request sent. Check events for the response (server:experience).");
5618
+ }
5619
+ };
5620
+ }
5621
+ function searchExperts(ws) {
5622
+ return {
5623
+ name: "stamn_search_experts",
5624
+ description: "Search for agents with proven experience in a domain or service tag. Find the best provider for a task based on verifiable track record.",
5625
+ parameters: {
5626
+ type: "object",
5627
+ properties: {
5628
+ domain: param("string", 'Domain to search for (e.g. "typescript", "data-analysis"). Partial match supported.'),
5629
+ serviceTag: param("string", "Exact service tag to filter by."),
5630
+ minJobs: param("number", "Minimum number of completed jobs."),
5631
+ minSuccessRate: param("number", "Minimum success rate (0-1, e.g. 0.95 for 95%)."),
5632
+ limit: param("number", "Max results to return (default 20).")
5633
+ }
5634
+ },
5635
+ execute: (_id, args) => {
5636
+ const payload = {};
5637
+ if (args.domain) payload.domain = args.domain;
5638
+ if (args.serviceTag) payload.serviceTag = args.serviceTag;
5639
+ if (args.minJobs) payload.minJobs = Number(args.minJobs);
5640
+ if (args.minSuccessRate) payload.minSuccessRate = Number(args.minSuccessRate);
5641
+ if (args.limit) payload.limit = Number(args.limit);
5642
+ ws.send("participant:search_experts", payload);
5643
+ return text("Expert search sent. Check events for the response (server:experts).");
5644
+ }
5645
+ };
5646
+ }
5647
+ function declareCapability(ws) {
5648
+ return {
5649
+ name: "stamn_declare_capability",
5650
+ description: "Declare a capability (tool, integration, hardware, access, or credential) that you have. This is stored in your profile and helps buyers find you.",
5651
+ parameters: {
5652
+ type: "object",
5653
+ properties: {
5654
+ capabilityType: param("string", "Type of capability.", { enum: ["tool", "integration", "hardware", "access", "credential"] }),
5655
+ name: param("string", 'Short name for the capability (e.g. "web-search", "github-api").'),
5656
+ description: param("string", "What this capability lets you do."),
5657
+ provider: param("string", 'Optional provider/platform (e.g. "Google", "GitHub").')
5658
+ },
5659
+ required: ["capabilityType", "name", "description"]
5660
+ },
5661
+ execute: (_id, args) => {
5662
+ const payload = {
5663
+ capabilityType: args.capabilityType,
5664
+ name: args.name,
5665
+ description: args.description
5666
+ };
5667
+ if (args.provider) payload.provider = args.provider;
5668
+ ws.send("participant:capability_declare", payload);
5669
+ return text(`Capability "${args.name}" declaration sent. Check events for confirmation (server:capability_declared).`);
5670
+ }
5671
+ };
5672
+ }
5673
+ function removeCapability(ws) {
5674
+ return {
5675
+ name: "stamn_remove_capability",
5676
+ description: "Remove a previously declared capability from your profile.",
5677
+ parameters: {
5678
+ type: "object",
5679
+ properties: {
5680
+ capabilityType: param("string", "Type of capability.", { enum: ["tool", "integration", "hardware", "access", "credential"] }),
5681
+ name: param("string", "Name of the capability to remove.")
5682
+ },
5683
+ required: ["capabilityType", "name"]
5684
+ },
5685
+ execute: (_id, args) => {
5686
+ ws.send("participant:capability_remove", {
5687
+ capabilityType: args.capabilityType,
5688
+ name: args.name
5689
+ });
5690
+ return text(`Capability removal sent. Check events for confirmation (server:capability_removed).`);
5691
+ }
5692
+ };
5693
+ }
5694
+ function listCapabilities(ws) {
5695
+ return {
5696
+ name: "stamn_list_capabilities",
5697
+ description: "List all capabilities you have declared.",
5698
+ parameters: NO_PARAMS,
5699
+ execute: () => {
5700
+ ws.send("participant:capability_list", {});
5701
+ return text("Capability list requested. Check events for the response (server:capability_list).");
5702
+ }
5703
+ };
5704
+ }
5705
+ function searchCapabilities(ws) {
5706
+ return {
5707
+ name: "stamn_search_capabilities",
5708
+ description: "Search for agents with specific capabilities. Find agents that have the tools or integrations you need.",
5709
+ parameters: {
5710
+ type: "object",
5711
+ properties: {
5712
+ capabilityType: param("string", "Filter by type.", { enum: ["tool", "integration", "hardware", "access", "credential"] }),
5713
+ name: param("string", "Search by capability name (partial match)."),
5714
+ provider: param("string", "Filter by provider (partial match)."),
5715
+ limit: param("number", "Max results (default 20).")
5716
+ }
5717
+ },
5718
+ execute: (_id, args) => {
5719
+ const payload = {};
5720
+ if (args.capabilityType) payload.capabilityType = args.capabilityType;
5721
+ if (args.name) payload.name = args.name;
5722
+ if (args.provider) payload.provider = args.provider;
5723
+ if (args.limit) payload.limit = Number(args.limit);
5724
+ ws.send("participant:search_capabilities", payload);
5725
+ return text("Capability search sent. Check events for the response (server:search_results).");
5726
+ }
5727
+ };
5728
+ }
5729
+ function setHybridMode(ws) {
5730
+ return {
5731
+ name: "stamn_set_hybrid_mode",
5732
+ description: "Set your hybrid mode: autonomous (fully AI), human_backed (AI with human escalation), or human_operated (human drives, AI assists).",
5733
+ parameters: {
5734
+ type: "object",
5735
+ properties: {
5736
+ mode: param("string", "The hybrid mode.", { enum: ["autonomous", "human_backed", "human_operated"] }),
5737
+ humanRole: param("string", 'Role of the human (e.g. "Senior Engineer", "Domain Expert").'),
5738
+ escalationTriggers: param("string", 'Comma-separated triggers for escalation (e.g. "complex-bug,security-review").'),
5739
+ humanAvailabilityHours: param("string", 'Availability window (e.g. "9am-5pm PST").')
5740
+ },
5741
+ required: ["mode"]
5742
+ },
5743
+ execute: (_id, args) => {
5744
+ const payload = {
5745
+ mode: args.mode
5746
+ };
5747
+ if (args.humanRole) payload.humanRole = args.humanRole;
5748
+ if (args.escalationTriggers) {
5749
+ payload.escalationTriggers = args.escalationTriggers.split(",").map((s) => s.trim());
5750
+ }
5751
+ if (args.humanAvailabilityHours) payload.humanAvailabilityHours = args.humanAvailabilityHours;
5752
+ ws.send("participant:set_hybrid_mode", payload);
5753
+ return text(`Hybrid mode update sent. Check events for confirmation (server:hybrid_mode_updated).`);
5754
+ }
5755
+ };
5756
+ }
5757
+ function addCredential(ws) {
5758
+ return {
5759
+ name: "stamn_add_credential",
5760
+ description: "Add a verified credential to your profile (e.g. certification, license, degree). Credentials are initially unverified.",
5761
+ parameters: {
5762
+ type: "object",
5763
+ properties: {
5764
+ credentialType: param("string", 'Type (e.g. "certification", "license", "degree", "membership").'),
5765
+ title: param("string", 'Title of the credential (e.g. "AWS Solutions Architect").'),
5766
+ issuer: param("string", 'Issuing organization (e.g. "Amazon Web Services").')
5767
+ },
5768
+ required: ["credentialType", "title", "issuer"]
5769
+ },
5770
+ execute: (_id, args) => {
5771
+ ws.send("participant:add_credential", {
5772
+ credentialType: args.credentialType,
5773
+ title: args.title,
5774
+ issuer: args.issuer
5775
+ });
5776
+ return text(`Credential submission sent. Check events for confirmation (server:credential_added).`);
5777
+ }
5778
+ };
5779
+ }
5780
+ function requestEscalation(ws) {
5781
+ return {
5782
+ name: "stamn_escalation_request",
5783
+ description: "Request human escalation for a task you cannot handle alone. Only relevant for human_backed or human_operated agents.",
5784
+ parameters: {
5785
+ type: "object",
5786
+ properties: {
5787
+ trigger: param("string", 'What triggered the escalation (e.g. "complex-bug", "security-review", "domain-expertise").'),
5788
+ context: param("string", "Context for the human \u2014 what you need help with."),
5789
+ serviceJobId: param("string", "Optional service job ID this escalation relates to.")
5790
+ },
5791
+ required: ["trigger", "context"]
5792
+ },
5793
+ execute: (_id, args) => {
5794
+ const payload = {
5795
+ trigger: args.trigger,
5796
+ context: args.context
5797
+ };
5798
+ if (args.serviceJobId) payload.serviceJobId = args.serviceJobId;
5799
+ ws.send("participant:escalation_request", payload);
5800
+ return text(`Escalation request sent. Check events for confirmation (server:escalation_created).`);
5801
+ }
5802
+ };
5803
+ }
5804
+ function resolveEscalation(ws) {
5805
+ return {
5806
+ name: "stamn_escalation_resolve",
5807
+ description: "Mark an escalation as resolved after human intervention is complete.",
5808
+ parameters: {
5809
+ type: "object",
5810
+ properties: {
5811
+ escalationId: param("string", "The escalation ID to resolve.")
5812
+ },
5813
+ required: ["escalationId"]
5814
+ },
5815
+ execute: (_id, args) => {
5816
+ ws.send("participant:escalation_resolved", {
5817
+ escalationId: args.escalationId
5818
+ });
5819
+ return text(`Escalation resolution sent. Check events for confirmation (server:escalation_resolved).`);
5820
+ }
5821
+ };
5822
+ }
5553
5823
  function allTools(ws, agentId) {
5554
5824
  return [
5555
5825
  worldStatus(ws),
@@ -5564,7 +5834,20 @@ function allTools(ws, agentId) {
5564
5834
  updateServiceListing(ws),
5565
5835
  listServiceListings(ws),
5566
5836
  chatReply(ws, agentId),
5567
- spend(ws)
5837
+ spend(ws),
5838
+ getReputation(ws),
5839
+ reviewService(ws),
5840
+ getReviews(ws),
5841
+ getExperience(ws),
5842
+ searchExperts(ws),
5843
+ declareCapability(ws),
5844
+ removeCapability(ws),
5845
+ listCapabilities(ws),
5846
+ searchCapabilities(ws),
5847
+ setHybridMode(ws),
5848
+ addCredential(ws),
5849
+ requestEscalation(ws),
5850
+ resolveEscalation(ws)
5568
5851
  ];
5569
5852
  }
5570
5853
  function withAuthGuard(tool, ws) {
@@ -5580,6 +5863,7 @@ function withAuthGuard(tool, ws) {
5580
5863
  };
5581
5864
  }
5582
5865
  function registerTools(api, wsService, config) {
5866
+ api.registerTool(ping());
5583
5867
  for (const tool of allTools(wsService, config.agentId)) {
5584
5868
  api.registerTool(withAuthGuard(tool, wsService));
5585
5869
  }
@@ -5733,7 +6017,8 @@ var ServerEvent = {
5733
6017
  HEARTBEAT_ACK: "server:heartbeat_ack",
5734
6018
  WORLD_UPDATE: "server:world_update",
5735
6019
  BALANCE: "server:balance",
5736
- OWNER_CHAT_MESSAGE: "server:owner_chat_message"
6020
+ OWNER_CHAT_MESSAGE: "server:owner_chat_message",
6021
+ SERVICE_INCOMING: "server:service_incoming"
5737
6022
  };
5738
6023
  var ClientEvent = {
5739
6024
  AUTHENTICATE: "participant:authenticate",
@@ -5759,6 +6044,7 @@ var StamnWsService = class {
5759
6044
  createSocket;
5760
6045
  ownerChatHandler;
5761
6046
  messageHandlers;
6047
+ serviceRequestHandler;
5762
6048
  constructor(opts) {
5763
6049
  this.config = opts.config;
5764
6050
  this.logger = opts.logger;
@@ -5772,7 +6058,8 @@ var StamnWsService = class {
5772
6058
  [ServerEvent.HEARTBEAT_ACK]: () => this.logger.debug("Heartbeat acknowledged"),
5773
6059
  [ServerEvent.WORLD_UPDATE]: (d) => this.onWorldUpdate(d),
5774
6060
  [ServerEvent.BALANCE]: (d) => this.onBalanceUpdate(d),
5775
- [ServerEvent.OWNER_CHAT_MESSAGE]: (d) => this.handleOwnerChat(d)
6061
+ [ServerEvent.OWNER_CHAT_MESSAGE]: (d) => this.handleOwnerChat(d),
6062
+ [ServerEvent.SERVICE_INCOMING]: (d) => this.handleServiceIncoming(d)
5776
6063
  };
5777
6064
  }
5778
6065
  async start() {
@@ -5815,6 +6102,9 @@ var StamnWsService = class {
5815
6102
  setOwnerChatHandler(handler) {
5816
6103
  this.ownerChatHandler = handler;
5817
6104
  }
6105
+ setServiceRequestHandler(handler) {
6106
+ this.serviceRequestHandler = handler;
6107
+ }
5818
6108
  connect() {
5819
6109
  this.logger.info(`Connecting to ${this.wsUrl}...`);
5820
6110
  try {
@@ -6013,6 +6303,11 @@ var StamnWsService = class {
6013
6303
  this.bufferEvent(ServerEvent.OWNER_CHAT_MESSAGE, payload);
6014
6304
  this.ownerChatHandler?.(payload);
6015
6305
  }
6306
+ handleServiceIncoming(payload) {
6307
+ this.logger.info(`Service request: ${payload.serviceTag} from ${payload.fromParticipantName} (${payload.requestId})`);
6308
+ this.bufferEvent(ServerEvent.SERVICE_INCOMING, payload);
6309
+ this.serviceRequestHandler?.(payload);
6310
+ }
6016
6311
  bufferEvent(event, data) {
6017
6312
  if (this.eventBuffer.length >= MAX_EVENT_BUFFER_SIZE) {
6018
6313
  this.eventBuffer.shift();
@@ -6168,6 +6463,9 @@ var index_default = {
6168
6463
  wsService.setOwnerChatHandler((payload) => {
6169
6464
  dispatchOwnerChat(api, wsService, payload, agentId);
6170
6465
  });
6466
+ wsService.setServiceRequestHandler((payload) => {
6467
+ dispatchServiceRequest(api, wsService, payload, agentId);
6468
+ });
6171
6469
  api.registerService({
6172
6470
  id: "stamn-ws",
6173
6471
  start: () => wsService.start(),
@@ -6235,6 +6533,59 @@ function dispatchOwnerChat(api, wsService, payload, agentId) {
6235
6533
  api.logger.error(`[stamn-channel] dispatchOwnerChat threw: ${err}`);
6236
6534
  }
6237
6535
  }
6536
+ function dispatchServiceRequest(api, _wsService, payload, agentId) {
6537
+ api.logger.info(
6538
+ `[stamn-channel] service request: ${payload.serviceTag} from ${payload.fromParticipantName}`
6539
+ );
6540
+ if (!api.runtime?.channel?.reply) {
6541
+ api.logger.warn("[stamn-channel] channel.reply not available \u2014 cannot dispatch service request");
6542
+ return;
6543
+ }
6544
+ const reply = api.runtime.channel.reply;
6545
+ try {
6546
+ const { dispatcher, replyOptions } = reply.createReplyDispatcherWithTyping({
6547
+ deliver: async () => {
6548
+ },
6549
+ channel: "stamn",
6550
+ accountId: agentId
6551
+ });
6552
+ const bodyForAgent = [
6553
+ `SERVICE REQUEST \u2014 You have an incoming paid service request. Process it immediately.`,
6554
+ ``,
6555
+ `Service: ${payload.serviceTag}`,
6556
+ `From: ${payload.fromParticipantName}`,
6557
+ `Price: ${payload.offeredPriceCents} cents USDC`,
6558
+ `Request ID: ${payload.requestId}`,
6559
+ ``,
6560
+ `Input:`,
6561
+ payload.input,
6562
+ ``,
6563
+ `Respond using stamn_service_respond with requestId "${payload.requestId}".`
6564
+ ].join("\n");
6565
+ reply.dispatchReplyFromConfig({
6566
+ ctx: {
6567
+ BodyForAgent: bodyForAgent,
6568
+ ChatType: "direct",
6569
+ MessageSid: payload.requestId,
6570
+ SessionKey: `agent:main:stamn:service:${agentId}`,
6571
+ Provider: "stamn",
6572
+ Surface: "stamn",
6573
+ From: payload.fromParticipantName
6574
+ },
6575
+ cfg: api.config,
6576
+ dispatcher,
6577
+ replyOptions
6578
+ }).then(() => {
6579
+ api.logger.info(
6580
+ `[stamn-channel] service request dispatched for ${payload.serviceTag} (${payload.requestId})`
6581
+ );
6582
+ }).catch((err) => {
6583
+ api.logger.error(`[stamn-channel] service request dispatch failed: ${err}`);
6584
+ });
6585
+ } catch (err) {
6586
+ api.logger.error(`[stamn-channel] dispatchServiceRequest threw: ${err}`);
6587
+ }
6588
+ }
6238
6589
  export {
6239
6590
  StamnWsService,
6240
6591
  createOpenclawAdapter,