@alfe.ai/agent-api-client 0.6.0 → 0.7.0
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.cjs +83 -42
- package/dist/index.d.cts +76 -39
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +76 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +83 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ const RETRYABLE_STATUS = new Set([
|
|
|
14
14
|
504
|
|
15
15
|
]);
|
|
16
16
|
const RETRY_DELAY_MS = 500;
|
|
17
|
+
const IMAGE_POLL_INTERVAL_MS = 2e3;
|
|
18
|
+
const IMAGE_JOB_TIMEOUT_MS = 18e4;
|
|
17
19
|
function sleep(ms) {
|
|
18
20
|
return new Promise((resolve) => {
|
|
19
21
|
setTimeout(resolve, ms);
|
|
@@ -591,36 +593,50 @@ var AgentApiClient = class {
|
|
|
591
593
|
}
|
|
592
594
|
/**
|
|
593
595
|
* Generate an image from a text prompt and get back a STABLE, public URL
|
|
594
|
-
* (served from the agent-assets CDN — it does not expire).
|
|
595
|
-
*
|
|
596
|
-
* markdown to show it to the user.
|
|
596
|
+
* (served from the agent-assets CDN — it does not expire). Embed the returned
|
|
597
|
+
* `imageUrl` in a reply as markdown to show it to the user.
|
|
597
598
|
*
|
|
598
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
599
|
+
* ASYNC: `gpt-image-1` routinely runs 30–60s, which exceeds the API Gateway
|
|
600
|
+
* 30s ceiling, so this enqueues a job (`POST /agent/images/generate` →
|
|
601
|
+
* `jobId`) then polls (`GET /agent/images/{jobId}`) until it completes. The
|
|
602
|
+
* worker's real failure message (e.g. an unsupported `size`) surfaces via the
|
|
603
|
+
* job's `error` field.
|
|
602
604
|
*/
|
|
603
605
|
async generateImage(args) {
|
|
604
606
|
const headers = new Headers();
|
|
605
607
|
headers.set("Authorization", `Bearer ${this.apiKey}`);
|
|
606
608
|
headers.set("Content-Type", "application/json");
|
|
607
|
-
const
|
|
609
|
+
const enqueueRes = await fetch(`${this.apiUrl}/agent/images/generate`, {
|
|
608
610
|
method: "POST",
|
|
609
611
|
headers,
|
|
610
612
|
body: JSON.stringify(args),
|
|
611
|
-
signal: AbortSignal.timeout(
|
|
613
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
612
614
|
});
|
|
613
|
-
if (!
|
|
614
|
-
|
|
615
|
-
|
|
615
|
+
if (!enqueueRes.ok) throw new Error(`Image generation failed to start (${String(enqueueRes.status)})`);
|
|
616
|
+
const { data: enqueued } = await enqueueRes.json();
|
|
617
|
+
const jobId = enqueued.jobId;
|
|
618
|
+
const deadline = Date.now() + IMAGE_JOB_TIMEOUT_MS;
|
|
619
|
+
while (Date.now() < deadline) {
|
|
620
|
+
await sleep(IMAGE_POLL_INTERVAL_MS);
|
|
621
|
+
let job;
|
|
616
622
|
try {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
|
|
623
|
+
job = await this.request(`/agent/images/${jobId}`);
|
|
624
|
+
} catch {
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (job.status === "completed") {
|
|
628
|
+
if (!job.imageUrl) throw new Error("Image generation completed without a URL");
|
|
629
|
+
return {
|
|
630
|
+
imageUrl: job.imageUrl,
|
|
631
|
+
model: job.model ?? args.model ?? "gpt-image-1"
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
if (job.status === "failed") {
|
|
635
|
+
const detail = job.error ? `: ${job.error.split("\n")[0]}` : "";
|
|
636
|
+
throw new Error(`Image generation failed${detail}`);
|
|
637
|
+
}
|
|
622
638
|
}
|
|
623
|
-
|
|
639
|
+
throw new Error("Image generation timed out");
|
|
624
640
|
}
|
|
625
641
|
async recordActivity(data) {
|
|
626
642
|
return this.request("/agent/activity", {
|
|
@@ -979,30 +995,6 @@ var AgentApiClient = class {
|
|
|
979
995
|
async getScopeProfile(scopeType, scopeId) {
|
|
980
996
|
return this.request(`/agent/org/profile/${encodeURIComponent(scopeType)}/${encodeURIComponent(scopeId)}`);
|
|
981
997
|
}
|
|
982
|
-
/** List a scope's facts (non-semantic, full enumeration). */
|
|
983
|
-
async listScopeFacts(scopeType, scopeId, opts) {
|
|
984
|
-
const qs = new URLSearchParams();
|
|
985
|
-
if (opts?.limit !== void 0) qs.set("limit", String(opts.limit));
|
|
986
|
-
if (opts?.cursor) qs.set("cursor", opts.cursor);
|
|
987
|
-
const query = qs.toString();
|
|
988
|
-
return this.request(`/agent/org/facts/${encodeURIComponent(scopeType)}/${encodeURIComponent(scopeId)}${query ? `?${query}` : ""}`);
|
|
989
|
-
}
|
|
990
|
-
/**
|
|
991
|
-
* Publish a fact at a scope. This is the deliberate cross-agent learning
|
|
992
|
-
* boundary — facts are attributable (the agent is recorded as author) and
|
|
993
|
-
* never an automatic merge. Membership is enforced server-side (403 for a
|
|
994
|
-
* non-member scope).
|
|
995
|
-
*/
|
|
996
|
-
async createScopeFact(scopeType, scopeId, text) {
|
|
997
|
-
return this.request(`/agent/org/facts/${encodeURIComponent(scopeType)}/${encodeURIComponent(scopeId)}`, {
|
|
998
|
-
method: "POST",
|
|
999
|
-
body: JSON.stringify({ text })
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
|
-
/** Delete a fact at a scope. */
|
|
1003
|
-
async deleteScopeFact(scopeType, scopeId, factId) {
|
|
1004
|
-
return this.request(`/agent/org/facts/${encodeURIComponent(scopeType)}/${encodeURIComponent(scopeId)}/${encodeURIComponent(factId)}`, { method: "DELETE" });
|
|
1005
|
-
}
|
|
1006
998
|
/** List a scope's docs (the org-files corpus; mirrored to shared/<scope>/). */
|
|
1007
999
|
async listScopeDocs(scopeType, scopeId, opts) {
|
|
1008
1000
|
const qs = new URLSearchParams();
|
|
@@ -1058,6 +1050,55 @@ var AgentApiClient = class {
|
|
|
1058
1050
|
}
|
|
1059
1051
|
return { filePath: presign.filePath };
|
|
1060
1052
|
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Open a change request against a scope's knowledge resource. For a doc
|
|
1055
|
+
* create/update, `services/org` returns a presigned staging PUT; this method
|
|
1056
|
+
* uploads the proposed `content` to it (echoing the same Content-Type that
|
|
1057
|
+
* was signed), mirroring `writeScopeDoc`. The staged body is applied to the
|
|
1058
|
+
* canonical doc — attributed to this agent — only when a reviewer approves.
|
|
1059
|
+
*/
|
|
1060
|
+
async proposeScopeChange(scopeType, scopeId, input) {
|
|
1061
|
+
const isDocBody = input.resourceType === "doc" && input.operation !== "delete";
|
|
1062
|
+
const contentType = input.contentType ?? "text/markdown";
|
|
1063
|
+
const result = await this.request(`/agent/org/change-requests/${encodeURIComponent(scopeType)}/${encodeURIComponent(scopeId)}`, {
|
|
1064
|
+
method: "POST",
|
|
1065
|
+
body: JSON.stringify({
|
|
1066
|
+
resourceType: input.resourceType,
|
|
1067
|
+
operation: input.operation,
|
|
1068
|
+
rationale: input.rationale,
|
|
1069
|
+
targetPath: input.targetPath,
|
|
1070
|
+
proposedContentType: isDocBody ? contentType : void 0,
|
|
1071
|
+
proposedValue: input.proposedValue
|
|
1072
|
+
})
|
|
1073
|
+
});
|
|
1074
|
+
if (isDocBody && result.uploadUrl) {
|
|
1075
|
+
const putHeaders = new Headers(result.requiredHeaders ?? {});
|
|
1076
|
+
putHeaders.set("Content-Type", contentType);
|
|
1077
|
+
const res = await fetch(result.uploadUrl, {
|
|
1078
|
+
method: "PUT",
|
|
1079
|
+
body: input.content ?? "",
|
|
1080
|
+
headers: putHeaders,
|
|
1081
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
1082
|
+
});
|
|
1083
|
+
if (!res.ok) {
|
|
1084
|
+
await res.text();
|
|
1085
|
+
throw new Error(`Change-request body upload failed (${String(res.status)})`);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return result.changeRequest;
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* List the agent's OWN change requests in a scope (filtered server-side to
|
|
1092
|
+
* this agent as proposer). Pass `status` to narrow to open / approved / etc.
|
|
1093
|
+
*/
|
|
1094
|
+
async listScopeChangeRequests(scopeType, scopeId, opts) {
|
|
1095
|
+
const qs = new URLSearchParams();
|
|
1096
|
+
if (opts?.status) qs.set("status", opts.status);
|
|
1097
|
+
if (opts?.limit !== void 0) qs.set("limit", String(opts.limit));
|
|
1098
|
+
if (opts?.cursor) qs.set("cursor", opts.cursor);
|
|
1099
|
+
const query = qs.toString();
|
|
1100
|
+
return this.request(`/agent/org/change-requests/${encodeURIComponent(scopeType)}/${encodeURIComponent(scopeId)}${query ? `?${query}` : ""}`);
|
|
1101
|
+
}
|
|
1061
1102
|
async registerDatabaseCredentials() {
|
|
1062
1103
|
return this.request("/agent/database/register", { method: "POST" });
|
|
1063
1104
|
}
|