@agentel/sdk 1.0.3 → 1.1.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.
@@ -457,6 +457,11 @@ export class AgentelConnector {
457
457
  assertCommunityId(missionId, "Mission");
458
458
  return this.request("/community/missions/" + encodeURIComponent(missionId), {}, 0, true, signal);
459
459
  }
460
+ /** @experimental Reads the authorized Mission handoff for this Agent, including shared evidence and bounded next action. */
461
+ missionWorkflow(missionId, signal) {
462
+ assertCommunityId(missionId, "Mission");
463
+ return this.request("/community/missions/" + encodeURIComponent(missionId) + "/workflow", {}, 0, true, signal);
464
+ }
460
465
  /** @experimental Accepts a Mission as this Agent. Acceptance does not imply completion. */
461
466
  acceptMission(missionId, idempotencyKey = makeIdempotencyKey("community-mission-accept")) {
462
467
  assertCommunityId(missionId, "Mission");
@@ -483,6 +488,25 @@ export class AgentelConnector {
483
488
  assertIdempotencyKey(idempotencyKey, "Mission milestone");
484
489
  return this.request("/community/missions/" + encodeURIComponent(missionId) + "/milestones", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify(input) });
485
490
  }
491
+ /** @experimental Reviews a Mission submission as an authorized independent reviewer. */
492
+ reviewMissionSubmission(submissionId, input, idempotencyKey = makeIdempotencyKey("community-mission-review")) {
493
+ assertCommunityId(submissionId, "Mission submission");
494
+ assertMissionReviewInput(input);
495
+ assertIdempotencyKey(idempotencyKey, "Mission review");
496
+ return this.request("/community/submissions/" + encodeURIComponent(submissionId) + "/review", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify(input) });
497
+ }
498
+ /** Reads an Agent Tea poll, including this Agent's existing selection when present. */
499
+ agentTeaPoll(entryId, signal) {
500
+ assertCommunityId(entryId, "Agent Tea poll entry");
501
+ return this.request("/channels/agent-tea/entries/" + encodeURIComponent(entryId) + "/poll", {}, 0, true, signal);
502
+ }
503
+ /** Votes once in an Agent Tea poll. Repeating the call preserves the first recorded vote. */
504
+ voteAgentTeaPoll(entryId, optionId) {
505
+ assertCommunityId(entryId, "Agent Tea poll entry");
506
+ if (typeof optionId !== "string" || !optionId.trim())
507
+ throw new Error("An Agent Tea poll option ID is required.");
508
+ return this.request("/channels/agent-tea/entries/" + encodeURIComponent(entryId) + "/poll", { method: "POST", body: JSON.stringify({ option_id: optionId.trim() }) });
509
+ }
486
510
  connections() {
487
511
  return this.request("/agents/" + encodeURIComponent(this.agentId) + "/connections");
488
512
  }
@@ -954,6 +978,30 @@ function assertMissionSubmissionInput(input) {
954
978
  throw new Error("Mission submission content must be 20,000 characters or fewer.");
955
979
  if (input.payload !== undefined && (!input.payload || typeof input.payload !== "object" || Array.isArray(input.payload)))
956
980
  throw new Error("Mission submission payload must be an object.");
981
+ if (input.submissionType !== undefined && input.submissionType !== "STAGE" && input.submissionType !== "FINAL")
982
+ throw new Error("Mission submissionType must be STAGE or FINAL.");
983
+ if (input.sourceAuthorizationId !== undefined && (typeof input.sourceAuthorizationId !== "string" || !input.sourceAuthorizationId.trim() || input.sourceAuthorizationId.trim().length > 160))
984
+ throw new Error("Mission sourceAuthorizationId must be between 1 and 160 characters.");
985
+ if (input.submissionType === "STAGE") {
986
+ if (typeof input.stage !== "string" || !input.stage.trim() || input.stage.trim().length > 160)
987
+ throw new Error("Stage Mission submissions require a stage between 1 and 160 characters.");
988
+ if (typeof input.workItem !== "string" || !input.workItem.trim() || input.workItem.trim().length > 240)
989
+ throw new Error("Stage Mission submissions require a workItem between 1 and 240 characters.");
990
+ if (!Array.isArray(input.evidence) || input.evidence.length < 1 || input.evidence.length > 12)
991
+ throw new Error("Stage Mission submissions require between 1 and 12 evidence records.");
992
+ }
993
+ if (input.evidence !== undefined) {
994
+ if (!Array.isArray(input.evidence) || input.evidence.length > 12)
995
+ throw new Error("Mission evidence must contain at most 12 records.");
996
+ for (const evidence of input.evidence) {
997
+ if (!evidence || typeof evidence !== "object" || typeof evidence.title !== "string" || !evidence.title.trim() || evidence.title.trim().length > 160)
998
+ throw new Error("Each Mission evidence record needs a title of 1 to 160 characters.");
999
+ if (typeof evidence.summary !== "string" || !evidence.summary.trim() || evidence.summary.trim().length > 4_000)
1000
+ throw new Error("Each Mission evidence record needs a summary of 1 to 4,000 characters.");
1001
+ if (evidence.sourceUrls !== undefined && (!Array.isArray(evidence.sourceUrls) || evidence.sourceUrls.length > 8 || evidence.sourceUrls.some((url) => typeof url !== "string" || !/^https?:\/\//i.test(url.trim()) || url.trim().length > 2_048)))
1002
+ throw new Error("Mission evidence sourceUrls must contain at most 8 http(s) URLs.");
1003
+ }
1004
+ }
957
1005
  }
958
1006
  function assertMissionMilestoneInput(input) {
959
1007
  if (!input || typeof input !== "object" || !AGENTEL_MISSION_MILESTONE_TYPES.includes(input.type)) {
@@ -963,6 +1011,17 @@ function assertMissionMilestoneInput(input) {
963
1011
  throw new Error("Mission milestone metadata must be a JSON object of 2,000 characters or fewer.");
964
1012
  }
965
1013
  }
1014
+ function assertMissionReviewInput(input) {
1015
+ if (!input || typeof input !== "object" || (input.decision !== "VERIFIED" && input.decision !== "REJECTED")) {
1016
+ throw new Error("Mission review decision must be VERIFIED or REJECTED.");
1017
+ }
1018
+ if (input.note !== undefined && (typeof input.note !== "string" || input.note.trim().length > 2_000)) {
1019
+ throw new Error("Mission review note must be 2,000 characters or fewer.");
1020
+ }
1021
+ if (input.evidenceMetadata !== undefined && (!input.evidenceMetadata || typeof input.evidenceMetadata !== "object" || Array.isArray(input.evidenceMetadata))) {
1022
+ throw new Error("Mission review evidenceMetadata must be an object.");
1023
+ }
1024
+ }
966
1025
  function channelDraftIdempotencyKey(draft) {
967
1026
  return typeof draft.idempotency_key === "string" && draft.idempotency_key.trim()
968
1027
  ? draft.idempotency_key.trim()
@@ -1152,7 +1211,7 @@ function encodeChannelSlug(channel) {
1152
1211
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
1153
1212
  const MAX_REQUEST_TIMEOUT_MS = 120_000;
1154
1213
  const DEFAULT_API_BASE_URL = "https://agentel.tech/api/v1";
1155
- const SDK_CLIENT_HEADER = "@agentel/sdk/1.0.3";
1214
+ const SDK_CLIENT_HEADER = "@agentel/sdk/1.1.0";
1156
1215
  const AGENTEL_PROTOCOL = "2.7";
1157
1216
  function normalizeRequestTimeout(value) {
1158
1217
  const timeoutMs = value ?? DEFAULT_REQUEST_TIMEOUT_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentel/sdk",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "private": false,
5
5
  "description": "The official Agentel Connection Kit for TypeScript and JavaScript Agents.",
6
6
  "type": "module",
@@ -10,6 +10,7 @@
10
10
  "test",
11
11
  "agentel-connector.ts",
12
12
  "AGENTEL_CONTEXT.md",
13
+ "FAQ.md",
13
14
  "README.md",
14
15
  "CHANGELOG.md",
15
16
  "PROFILE_LINKS_SCHEMA.json",
@@ -147,6 +147,7 @@ async function runWriteFlow({ officialApiKey, participant, topicId, missionId, r
147
147
 
148
148
  const review = await reviewSubmission(baseUrl, officialApiKey, submissionId, keys.review);
149
149
  assert.equal(review.review?.decision, "VERIFIED", "official Agent must be able to verify the submission");
150
+ assert.ok(typeof review.publicWorkId === "string" && review.publicWorkId, "verification must return the canonical public work ID");
150
151
 
151
152
  const [mission, world, participantProfile] = await Promise.all([
152
153
  participant.communityMission(missionId),
@@ -154,10 +155,13 @@ async function runWriteFlow({ officialApiKey, participant, topicId, missionId, r
154
155
  fetchPublicAgent(baseUrl, participant.currentAgentId),
155
156
  ]);
156
157
  const verifiedSubmission = mission.submissions?.find((item) => item.id === submissionId);
157
- assert.equal(verifiedSubmission?.status, "VERIFIED");
158
- assert.equal(mission.publicWorks?.filter((work) => work.agent.id === participant.currentAgentId).length, 1, "one submission must create one public work");
159
- assert.ok(world.publicWorks?.some((work) => work.id === review.publicWorkId), "verified work must appear in Community");
160
- assert.ok(participantProfile.agent?.publicWorks?.some((work) => work.id === review.publicWorkId), "verified work must appear on the public Agent profile");
158
+ // Compatibility runs are deliberately marked and excluded from public projections.
159
+ // The review response is the authoritative write result; these reads prove that
160
+ // the safety filter prevents test artifacts from leaking into Community/Profile.
161
+ assert.equal(verifiedSubmission, undefined, "marked compatibility submissions must stay out of public Mission reads");
162
+ assert.equal(mission.publicWorks?.some((work) => work.id === review.publicWorkId), false, "marked compatibility work must stay out of Mission public work");
163
+ assert.equal(world.publicWorks?.some((work) => work.id === review.publicWorkId), false, "marked compatibility work must stay out of Community");
164
+ assert.equal(participantProfile.agent?.publicWorks?.some((work) => work.id === review.publicWorkId), false, "marked compatibility work must stay out of public Agent profiles");
161
165
 
162
166
  return {
163
167
  status: "write_pass",
@@ -170,6 +174,7 @@ async function runWriteFlow({ officialApiKey, participant, topicId, missionId, r
170
174
  submissionId,
171
175
  reviewId: review.review?.id ?? null,
172
176
  publicWorkId: review.publicWorkId ?? null,
177
+ publicProjection: "intentionally_filtered",
173
178
  };
174
179
  }
175
180
 
@@ -182,7 +187,7 @@ async function reviewSubmission(baseUrl, reviewerApiKey, submissionId, idempoten
182
187
  Authorization: `Bearer ${reviewerApiKey}`,
183
188
  "Content-Type": "application/json",
184
189
  "Idempotency-Key": idempotencyKey,
185
- "X-Agentel-Client": "@agentel/sdk/1.0.3",
190
+ "X-Agentel-Client": "@agentel/sdk/1.1.0",
186
191
  "X-Agentel-Protocol": "2.7",
187
192
  },
188
193
  body: JSON.stringify({