@linkedclaw/cli 0.1.5 → 0.1.7
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/bin.js +141 -38
- package/dist/bin.js.map +1 -1
- package/package.json +4 -4
package/dist/bin.js
CHANGED
|
@@ -4287,7 +4287,8 @@ var SessionSchema = external_exports.object({
|
|
|
4287
4287
|
max_credits: external_exports.number().int(),
|
|
4288
4288
|
agreed_quote: external_exports.record(external_exports.unknown()).nullable().optional(),
|
|
4289
4289
|
manifest_id: external_exports.string().nullable().optional(),
|
|
4290
|
-
arbitrator: external_exports.string().nullable().optional()
|
|
4290
|
+
arbitrator: external_exports.string().nullable().optional(),
|
|
4291
|
+
on_behalf_of_id: external_exports.string().nullable().optional()
|
|
4291
4292
|
}).passthrough();
|
|
4292
4293
|
var TrustScoreSchema = external_exports.object({
|
|
4293
4294
|
score: external_exports.number().int(),
|
|
@@ -4424,7 +4425,8 @@ var ReceiptSchema = external_exports.object({
|
|
|
4424
4425
|
requester_rating: external_exports.number().int().nullable().optional(),
|
|
4425
4426
|
rating_comment: external_exports.string().nullable().optional(),
|
|
4426
4427
|
verified: external_exports.boolean().optional(),
|
|
4427
|
-
finalized: external_exports.boolean().optional()
|
|
4428
|
+
finalized: external_exports.boolean().optional(),
|
|
4429
|
+
on_behalf_of_id: external_exports.string().nullable().optional()
|
|
4428
4430
|
}).passthrough();
|
|
4429
4431
|
var RateReceiptResultSchema = external_exports.object({
|
|
4430
4432
|
receipt_id: external_exports.string().optional(),
|
|
@@ -4570,17 +4572,50 @@ var CommonsLogEventSchema = external_exports.object({
|
|
|
4570
4572
|
}).passthrough();
|
|
4571
4573
|
|
|
4572
4574
|
// ../../sdk/consumer-ts/dist/client.js
|
|
4575
|
+
var GigTaskCreationError = class extends Error {
|
|
4576
|
+
mandate;
|
|
4577
|
+
cause;
|
|
4578
|
+
constructor(mandate, cause) {
|
|
4579
|
+
super(`Gig task creation failed after mandate ${mandate.mandate_id} was issued: ${cause.message}`);
|
|
4580
|
+
this.mandate = mandate;
|
|
4581
|
+
this.cause = cause;
|
|
4582
|
+
this.name = "GigTaskCreationError";
|
|
4583
|
+
}
|
|
4584
|
+
};
|
|
4573
4585
|
var ConsumerClient = class {
|
|
4574
|
-
|
|
4586
|
+
// Substrate / network surface — identity, sessions, mandates, registration.
|
|
4587
|
+
networkUrl;
|
|
4588
|
+
// First-party service product surface — where Gig PA et al expose their
|
|
4589
|
+
// resource APIs. Distinct from networkUrl per LAYER_SYSTEM §8: services are
|
|
4590
|
+
// L5 service agents, not the network.
|
|
4591
|
+
serviceUrl;
|
|
4575
4592
|
apiKey;
|
|
4576
4593
|
fetchImpl;
|
|
4577
|
-
|
|
4578
|
-
|
|
4594
|
+
_gigPaAgentIdCache;
|
|
4595
|
+
constructor(networkUrl, apiKey, options) {
|
|
4596
|
+
this.networkUrl = networkUrl.replace(/\/+$/, "");
|
|
4597
|
+
this.serviceUrl = options?.serviceUrl !== void 0 ? options.serviceUrl.replace(/\/+$/, "") : void 0;
|
|
4579
4598
|
this.apiKey = apiKey;
|
|
4580
4599
|
this.fetchImpl = options?.fetch ?? fetch;
|
|
4581
4600
|
}
|
|
4601
|
+
async _resolveGigPaAgentId() {
|
|
4602
|
+
if (!this._gigPaAgentIdCache) {
|
|
4603
|
+
const data = await this.request("/api/v1/resolve/gig-pa-operator/gig-platform-agent", { method: "GET" }, AgentSchema);
|
|
4604
|
+
this._gigPaAgentIdCache = data.agent_id;
|
|
4605
|
+
}
|
|
4606
|
+
return this._gigPaAgentIdCache;
|
|
4607
|
+
}
|
|
4582
4608
|
async request(path2, init, schema) {
|
|
4583
|
-
|
|
4609
|
+
return this._call(this.networkUrl, path2, init, schema);
|
|
4610
|
+
}
|
|
4611
|
+
async serviceRequest(path2, init, schema) {
|
|
4612
|
+
if (this.serviceUrl === void 0) {
|
|
4613
|
+
throw new Error("ConsumerClient.serviceUrl is not set. Methods that talk to first-party service surfaces (e.g. Gig PA's /api/v1/gig-tasks/*) require a serviceUrl because services are L5 service agents, not part of the network. Pass { serviceUrl: <gig_pa_url> } in options.");
|
|
4614
|
+
}
|
|
4615
|
+
return this._call(this.serviceUrl, path2, init, schema);
|
|
4616
|
+
}
|
|
4617
|
+
async _call(baseUrl, path2, init, schema) {
|
|
4618
|
+
const res = await this.fetchImpl(`${baseUrl}${path2}`, {
|
|
4584
4619
|
...init,
|
|
4585
4620
|
headers: {
|
|
4586
4621
|
"Content-Type": "application/json",
|
|
@@ -4609,7 +4644,7 @@ var ConsumerClient = class {
|
|
|
4609
4644
|
}
|
|
4610
4645
|
// ───────── Identity / Auth ─────────
|
|
4611
4646
|
/** @implements POST /api/v1/register */
|
|
4612
|
-
static async register(
|
|
4647
|
+
static async register(networkUrl, params = {}, options) {
|
|
4613
4648
|
const fetchImpl = options?.fetch ?? fetch;
|
|
4614
4649
|
const body = { role: params.role ?? "requester" };
|
|
4615
4650
|
if (params.email !== void 0)
|
|
@@ -4618,7 +4653,7 @@ var ConsumerClient = class {
|
|
|
4618
4653
|
body.handle = params.handle;
|
|
4619
4654
|
if (params.displayName !== void 0)
|
|
4620
4655
|
body.display_name = params.displayName;
|
|
4621
|
-
const res = await fetchImpl(`${
|
|
4656
|
+
const res = await fetchImpl(`${networkUrl.replace(/\/+$/, "")}/api/v1/register`, {
|
|
4622
4657
|
method: "POST",
|
|
4623
4658
|
headers: {
|
|
4624
4659
|
"Content-Type": "application/json"
|
|
@@ -4682,6 +4717,10 @@ var ConsumerClient = class {
|
|
|
4682
4717
|
})
|
|
4683
4718
|
}, InvokeResultSchema);
|
|
4684
4719
|
}
|
|
4720
|
+
/** @implements POST /api/v1/agents/{agent_id}/messages */
|
|
4721
|
+
async deliverAgentMessage(agentId, payload) {
|
|
4722
|
+
return this.request(`/api/v1/agents/${encodeURIComponent(agentId)}/messages`, { method: "POST", body: JSON.stringify({ payload }) }, external_exports.record(external_exports.unknown()));
|
|
4723
|
+
}
|
|
4685
4724
|
async getTrustScore(agentId, options) {
|
|
4686
4725
|
return this.request(`/api/v1/agents/${agentId}/trust${this.queryString({
|
|
4687
4726
|
capability: options?.capability
|
|
@@ -4715,6 +4754,16 @@ var ConsumerClient = class {
|
|
|
4715
4754
|
async getSession(sessionId) {
|
|
4716
4755
|
return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}`, { method: "GET" }, SessionSchema);
|
|
4717
4756
|
}
|
|
4757
|
+
/** @implements POST /api/v1/sessions/{session_id}/activate
|
|
4758
|
+
*
|
|
4759
|
+
* Required by the requester after WS SESSION_ACCEPT to flip the DB-side
|
|
4760
|
+
* session record from `pending` to `active`. Without this call, subsequent
|
|
4761
|
+
* `POST /messages` will reject with 409 once cloud notices the WS dropped
|
|
4762
|
+
* (status flips `pending` → `interrupted` on heartbeat watchdog).
|
|
4763
|
+
*/
|
|
4764
|
+
async activateSession(sessionId) {
|
|
4765
|
+
return this.request(`/api/v1/sessions/${encodeURIComponent(sessionId)}/activate`, { method: "POST", body: JSON.stringify({}) }, external_exports.record(external_exports.unknown()));
|
|
4766
|
+
}
|
|
4718
4767
|
/** @implements POST /api/v1/sessions/{session_id}/end */
|
|
4719
4768
|
async endSession(sessionId, options) {
|
|
4720
4769
|
const body = {};
|
|
@@ -4736,40 +4785,88 @@ var ConsumerClient = class {
|
|
|
4736
4785
|
})}`, { method: "GET" }, SessionEventListSchema);
|
|
4737
4786
|
}
|
|
4738
4787
|
// ───────── Gig PA (requester) ─────────
|
|
4739
|
-
/** @implements GET /api/v1/
|
|
4788
|
+
/** @implements GET /api/v1/gig-tasks/ */
|
|
4740
4789
|
async listGigTasks(options) {
|
|
4741
|
-
return this.
|
|
4790
|
+
return this.serviceRequest(`/api/v1/gig-tasks/${this.queryString({
|
|
4742
4791
|
status: options?.status,
|
|
4743
4792
|
capability: options?.capability
|
|
4744
4793
|
})}`, { method: "GET" }, external_exports.array(GigTaskSchema));
|
|
4745
4794
|
}
|
|
4746
|
-
/** @implements POST /api/v1/
|
|
4795
|
+
/** @implements POST /api/v1/gig-tasks/ */
|
|
4747
4796
|
async createGigTask(body) {
|
|
4748
|
-
return this.
|
|
4797
|
+
return this.serviceRequest("/api/v1/gig-tasks/", { method: "POST", body: JSON.stringify(body) }, GigTaskSchema);
|
|
4798
|
+
}
|
|
4799
|
+
async createGigTaskWithMandate(options) {
|
|
4800
|
+
const { principal_agent_id, capability, instruction, target_providers, credits_per_provider, mandate_expires_at, gig_pa_agent_id, deadline, idempotency_key, mandate_id: preIssuedMandateId, ...taskExtra } = options;
|
|
4801
|
+
let issuedMandate;
|
|
4802
|
+
let resolvedMandateId = preIssuedMandateId;
|
|
4803
|
+
if (!resolvedMandateId) {
|
|
4804
|
+
const gigPaAgentId = gig_pa_agent_id ?? await this._resolveGigPaAgentId();
|
|
4805
|
+
const mandateHeaders = {};
|
|
4806
|
+
if (idempotency_key)
|
|
4807
|
+
mandateHeaders["Idempotency-Key"] = `${idempotency_key}:mandate`;
|
|
4808
|
+
issuedMandate = await this.request("/api/v1/mandates", {
|
|
4809
|
+
method: "POST",
|
|
4810
|
+
body: JSON.stringify({
|
|
4811
|
+
principal_agent_id,
|
|
4812
|
+
delegate_agent_id: gigPaAgentId,
|
|
4813
|
+
scope: ["session.open"],
|
|
4814
|
+
scope_params: { "session.open": { max_credits_per_op: credits_per_provider } },
|
|
4815
|
+
budget: target_providers * credits_per_provider,
|
|
4816
|
+
expires_at: mandate_expires_at
|
|
4817
|
+
}),
|
|
4818
|
+
headers: mandateHeaders
|
|
4819
|
+
}, MandateRecordSchema);
|
|
4820
|
+
resolvedMandateId = issuedMandate.mandate_id;
|
|
4821
|
+
}
|
|
4822
|
+
const taskHeaders = {};
|
|
4823
|
+
if (idempotency_key)
|
|
4824
|
+
taskHeaders["Idempotency-Key"] = idempotency_key;
|
|
4825
|
+
const taskBody = {
|
|
4826
|
+
capability,
|
|
4827
|
+
instruction,
|
|
4828
|
+
target_providers,
|
|
4829
|
+
credits_per_provider,
|
|
4830
|
+
mandate_id: resolvedMandateId,
|
|
4831
|
+
...taskExtra
|
|
4832
|
+
};
|
|
4833
|
+
if (deadline)
|
|
4834
|
+
taskBody.deadline = deadline;
|
|
4835
|
+
let task;
|
|
4836
|
+
try {
|
|
4837
|
+
task = await this.serviceRequest("/api/v1/gig-tasks/", { method: "POST", body: JSON.stringify(taskBody), headers: taskHeaders }, GigTaskSchema);
|
|
4838
|
+
} catch (err) {
|
|
4839
|
+
if (issuedMandate && err instanceof Error) {
|
|
4840
|
+
throw new GigTaskCreationError(issuedMandate, err);
|
|
4841
|
+
}
|
|
4842
|
+
throw err;
|
|
4843
|
+
}
|
|
4844
|
+
const mandate = issuedMandate ?? { mandate_id: resolvedMandateId };
|
|
4845
|
+
return { task, mandate };
|
|
4749
4846
|
}
|
|
4750
|
-
/** @implements GET /api/v1/
|
|
4847
|
+
/** @implements GET /api/v1/gig-tasks/policy */
|
|
4751
4848
|
async getGigTaskPolicy() {
|
|
4752
|
-
return this.
|
|
4849
|
+
return this.serviceRequest("/api/v1/gig-tasks/policy", { method: "GET" }, GigTaskPolicySchema);
|
|
4753
4850
|
}
|
|
4754
|
-
/** @implements GET /api/v1/
|
|
4851
|
+
/** @implements GET /api/v1/gig-tasks/{task_id} */
|
|
4755
4852
|
async getGigTask(taskId) {
|
|
4756
|
-
return this.
|
|
4853
|
+
return this.serviceRequest(`/api/v1/gig-tasks/${encodeURIComponent(taskId)}`, { method: "GET" }, GigTaskSchema);
|
|
4757
4854
|
}
|
|
4758
|
-
/** @implements POST /api/v1/
|
|
4855
|
+
/** @implements POST /api/v1/gig-tasks/{task_id}/results/{result_id}/verify */
|
|
4759
4856
|
async verifyGigTaskResult(taskId, resultId, body) {
|
|
4760
|
-
return this.
|
|
4857
|
+
return this.serviceRequest(`/api/v1/gig-tasks/${encodeURIComponent(taskId)}/results/${encodeURIComponent(resultId)}/verify`, { method: "POST", body: JSON.stringify(body ?? {}) }, GigTaskVerifyResultSchema);
|
|
4761
4858
|
}
|
|
4762
|
-
/** @implements POST /api/v1/
|
|
4859
|
+
/** @implements POST /api/v1/gig-tasks/{task_id}/results/{result_id}/review */
|
|
4763
4860
|
async reviewGigTaskResult(taskId, resultId, body) {
|
|
4764
|
-
return this.
|
|
4861
|
+
return this.serviceRequest(`/api/v1/gig-tasks/${encodeURIComponent(taskId)}/results/${encodeURIComponent(resultId)}/review`, { method: "POST", body: JSON.stringify(body) }, GigTaskVerifyResultSchema);
|
|
4765
4862
|
}
|
|
4766
|
-
/** @implements POST /api/v1/
|
|
4863
|
+
/** @implements POST /api/v1/gig-tasks/{task_id}/release */
|
|
4767
4864
|
async releaseGigTask(taskId) {
|
|
4768
|
-
return this.
|
|
4865
|
+
return this.serviceRequest(`/api/v1/gig-tasks/${encodeURIComponent(taskId)}/release`, { method: "POST", body: JSON.stringify({}) }, GigTaskActionResultSchema);
|
|
4769
4866
|
}
|
|
4770
|
-
/** @implements POST /api/v1/
|
|
4867
|
+
/** @implements POST /api/v1/gig-tasks/{task_id}/cancel */
|
|
4771
4868
|
async cancelGigTask(taskId, reason) {
|
|
4772
|
-
return this.
|
|
4869
|
+
return this.serviceRequest(`/api/v1/gig-tasks/${encodeURIComponent(taskId)}/cancel`, { method: "POST", body: JSON.stringify(reason !== void 0 ? { reason } : {}) }, GigTaskActionResultSchema);
|
|
4773
4870
|
}
|
|
4774
4871
|
// ───────── Credits ─────────
|
|
4775
4872
|
/** @implements GET /api/v1/credits */
|
|
@@ -4883,10 +4980,6 @@ var ConsumerClient = class {
|
|
|
4883
4980
|
async revokeMandate(mandateId) {
|
|
4884
4981
|
await this.request(`/api/v1/mandates/${encodeURIComponent(mandateId)}`, { method: "DELETE" }, external_exports.unknown());
|
|
4885
4982
|
}
|
|
4886
|
-
/** @implements POST /api/v1/mandates/transport */
|
|
4887
|
-
async createTransportMandate(body) {
|
|
4888
|
-
return this.request("/api/v1/mandates/transport", { method: "POST", body: JSON.stringify(body) }, MandateRecordSchema);
|
|
4889
|
-
}
|
|
4890
4983
|
// ───────── Observability ─────────
|
|
4891
4984
|
/** @implements GET /api/v1/events/verify */
|
|
4892
4985
|
async verifyEvents(options) {
|
|
@@ -4905,21 +4998,21 @@ var ConsumerClient = class {
|
|
|
4905
4998
|
// ───────── Health (no auth required) ─────────
|
|
4906
4999
|
/** @implements GET /health */
|
|
4907
5000
|
async health() {
|
|
4908
|
-
const res = await this.fetchImpl(`${this.
|
|
5001
|
+
const res = await this.fetchImpl(`${this.networkUrl}/health`, { method: "GET" });
|
|
4909
5002
|
if (!res.ok)
|
|
4910
5003
|
throw new Error(`LinkedClaw /health ${res.status}`);
|
|
4911
5004
|
return HealthStatusSchema.parse(await res.json());
|
|
4912
5005
|
}
|
|
4913
5006
|
/** @implements GET /health/ready */
|
|
4914
5007
|
async healthReady() {
|
|
4915
|
-
const res = await this.fetchImpl(`${this.
|
|
5008
|
+
const res = await this.fetchImpl(`${this.networkUrl}/health/ready`, { method: "GET" });
|
|
4916
5009
|
if (!res.ok)
|
|
4917
5010
|
throw new Error(`LinkedClaw /health/ready ${res.status}`);
|
|
4918
5011
|
return HealthStatusSchema.parse(await res.json());
|
|
4919
5012
|
}
|
|
4920
5013
|
/** @implements GET /metrics */
|
|
4921
5014
|
async metrics() {
|
|
4922
|
-
const res = await this.fetchImpl(`${this.
|
|
5015
|
+
const res = await this.fetchImpl(`${this.networkUrl}/metrics`, { method: "GET" });
|
|
4923
5016
|
if (!res.ok)
|
|
4924
5017
|
throw new Error(`LinkedClaw /metrics ${res.status}`);
|
|
4925
5018
|
return res.text();
|
|
@@ -5648,11 +5741,15 @@ var RequesterFlows = class {
|
|
|
5648
5741
|
return this.client.discover({ capability, ...extra });
|
|
5649
5742
|
}
|
|
5650
5743
|
/**
|
|
5651
|
-
* Open a session.
|
|
5744
|
+
* Open a session.
|
|
5745
|
+
*
|
|
5746
|
+
* Default: pure HTTP — `POST /sessions` then `POST /activate`. Cloud
|
|
5747
|
+
* drives the SESSION_CREATE handshake to the provider server-side. No
|
|
5748
|
+
* WebSocket opens on the requester side; no `agentId` registration
|
|
5749
|
+
* required.
|
|
5652
5750
|
*
|
|
5653
|
-
*
|
|
5654
|
-
*
|
|
5655
|
-
* /acp first; on opt-in, falls back to /ws when the recipient isn't on /acp.
|
|
5751
|
+
* `tryAcp: true` opts into the legacy WS handshake path for OpenClaw
|
|
5752
|
+
* sub-agent / ACP-routed scenarios — see {@link HireParams.tryAcp}.
|
|
5656
5753
|
*/
|
|
5657
5754
|
async hire(params) {
|
|
5658
5755
|
const session = await this.client.createSession({
|
|
@@ -5662,9 +5759,9 @@ var RequesterFlows = class {
|
|
|
5662
5759
|
...params.referredBy !== void 0 ? { referred_by: params.referredBy } : {}
|
|
5663
5760
|
});
|
|
5664
5761
|
if (params.autoActivate === false) return { session, activated: false };
|
|
5665
|
-
const relayUrl = params.relayUrl ?? DEFAULT_RELAY_URL;
|
|
5666
5762
|
try {
|
|
5667
5763
|
if (params.tryAcp) {
|
|
5764
|
+
const relayUrl = params.relayUrl ?? DEFAULT_RELAY_URL;
|
|
5668
5765
|
const acpUrl = relayUrl.replace(/\/ws$/, "/acp");
|
|
5669
5766
|
try {
|
|
5670
5767
|
await this.attemptHandshake(acpUrl, session.session_id, params, ACP_CONNECT_TIMEOUT_MS);
|
|
@@ -5672,9 +5769,8 @@ var RequesterFlows = class {
|
|
|
5672
5769
|
if (!(err instanceof TransportMissError)) throw err;
|
|
5673
5770
|
await this.attemptHandshake(relayUrl, session.session_id, params, SESSION_ACCEPT_TIMEOUT_MS);
|
|
5674
5771
|
}
|
|
5675
|
-
} else {
|
|
5676
|
-
await this.attemptHandshake(relayUrl, session.session_id, params, SESSION_ACCEPT_TIMEOUT_MS);
|
|
5677
5772
|
}
|
|
5773
|
+
await this.client.activateSession(session.session_id);
|
|
5678
5774
|
} catch (err) {
|
|
5679
5775
|
await this.client.endSession(session.session_id, {}).catch(() => {
|
|
5680
5776
|
});
|
|
@@ -5685,7 +5781,14 @@ var RequesterFlows = class {
|
|
|
5685
5781
|
}
|
|
5686
5782
|
return { session, activated: true };
|
|
5687
5783
|
}
|
|
5784
|
+
// tryAcp:true path only. Default `hire()` no longer calls this — see the
|
|
5785
|
+
// method comment on `hire`. Kept for OpenClaw sub-agent integration.
|
|
5688
5786
|
async attemptHandshake(url, sessionId, params, connectTimeoutMs) {
|
|
5787
|
+
if (!params.agentId) {
|
|
5788
|
+
throw new Error(
|
|
5789
|
+
"attemptHandshake (tryAcp:true) requires `agentId` in HireParams \u2014 the WS IDENTIFY frame validates listing ownership. Use the default HTTP path (omit tryAcp) if you don't have a registered agent listing."
|
|
5790
|
+
);
|
|
5791
|
+
}
|
|
5689
5792
|
const ws = new WebSocket2(url);
|
|
5690
5793
|
try {
|
|
5691
5794
|
await new Promise((resolve3, reject) => {
|