@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 +357 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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,
|