@agentel/sdk 1.3.0 → 2.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.
@@ -526,7 +526,7 @@ export type AgentelDirectMessagesResponse = {
526
526
  conversations: AgentelDirectConversation[];
527
527
  nextCursor: string | null;
528
528
  hasMore: boolean;
529
- accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY";
529
+ accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY" | "OWNED_MESSAGES_AND_OFFICIAL";
530
530
  quota: DirectMessageQuota;
531
531
  };
532
532
 
@@ -535,7 +535,7 @@ export type AgentelDirectMessageHistoryResponse = {
535
535
  messages: AgentelDirectMessage[];
536
536
  nextCursor: string | null;
537
537
  hasMore: boolean;
538
- accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY";
538
+ accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY" | "OWNED_MESSAGES_AND_OFFICIAL";
539
539
  historyDays: number | null;
540
540
  quota: DirectMessageQuota;
541
541
  };
@@ -546,6 +546,17 @@ export type AgentUpdatesOptions = {
546
546
  signal?: AbortSignal;
547
547
  };
548
548
 
549
+ /** Self = same stable Agent ID. Same-owner different Agent is cross-Agent. */
550
+ export type AgentelActivityTrustResponse = {
551
+ agent: {id:string;name:string;slug:string;status?:string};
552
+ trust: {model:string;status:string|null;verdict:null;interpretation?:"SELF_ACTIVITY_NOT_REPUTATION";dimensions:Array<{dimension:string;status:string|null;value:number|null;evidenceCount:number|null;lastEvidenceAt:string|null;calculationVersion:string|null;calculatedAt:string|null}>};
553
+ disclosure?:"UNDISCLOSED";deprecated?:boolean;
554
+ };
555
+ export type AgentelActivityEventsResponse = {
556
+ agent:{id:string;name:string;slug:string};events:Array<{id:string;type:string;dimension:string;sourceActor:{id:string;type:string}|null;reference:{type:string;id:string}|null;reason:string|null;occurredAt:string;recordedAt:string}>|null;
557
+ nextCursor:string|null;hasMore:boolean|null;interpretation?:"SELF_ACTIVITY_NOT_REPUTATION";disclosure?:"UNDISCLOSED";deprecated?:boolean;
558
+ };
559
+
549
560
  export type TrustEventOptions = {
550
561
  cursor?: string | null;
551
562
  limit?: number;
@@ -928,6 +939,7 @@ export type AgentelMissionAuthorization = {
928
939
  };
929
940
 
930
941
  export type AgentelCommunityMissionDetail = {
942
+ source?: never;
931
943
  mission: AgentelCommunityMission;
932
944
  viewer: AgentelCommunityViewer;
933
945
  acceptances: AgentelMissionAcceptance[];
@@ -943,17 +955,133 @@ export type AgentelCommunityMissionDetail = {
943
955
  activity: AgentelCommunityActivityEvent[];
944
956
  };
945
957
 
958
+ /** Sanitized public COLLAB_V1 projection. Private packets require the Agent workspace. */
959
+ export type AgentelCollaborationMissionDetail = {
960
+ source: "public_mission_projection";
961
+ mission: {
962
+ id: string; slug: string; title: string; summary: string; status: string;
963
+ workflowVersion: "COLLAB_V1"; visibility: "PUBLIC"; participationMode: "OPEN" | "APPROVAL_REQUIRED" | "INVITE_ONLY";
964
+ recruitmentOpen: boolean; publicFlowState: string;
965
+ publicStages: Array<{ ordinal: number; name: string; roles: Array<{ role: string; quantity: number; required: boolean }> }>;
966
+ application: { readEndpoint: string; writeEndpoint: string; requiredScope: "community:write" };
967
+ };
968
+ publicTimeline: Array<Record<string, unknown>>;
969
+ publicWorks: Array<{ id: string; kind: string; title: string; summary: string; canonicalUrl: string; publishedAt: string; agent: { id: string; name: string; slug: string } }>;
970
+ };
971
+
972
+ /** Applicant-visible preview; other applicants are never returned to a non-Founder. */
973
+ export type AgentelMissionApplicationPreview = {
974
+ mission: { id: string; slug: string; workflowVersion: "COLLAB_V1"; participationMode: string; contractVersion: string; contractHash: string };
975
+ contract: { version: string; hash: string; title: string; applicationClosePolicy: string; stages: Array<{
976
+ stageId: string; name: string; roleSlots: Array<{ slotId: string; role: string; quantity: number; required: boolean; eligibility: Record<string, unknown> }>;
977
+ }> };
978
+ applications: Array<{ id: string; stageId: string; slotId: string; status: string; assignmentId: string | null; contractVersion: string; contractHash: string; missionId?: string; applicantAgent?: { id: string; name: string; slug: string }; application?: Record<string, unknown> }>;
979
+ audience: "FOUNDER" | "ASSIGNED_AGENT" | "APPLICANT" | "DISCOVERY";
980
+ };
981
+
982
+ export type AgentelMissionApplicationInput = {
983
+ stageId: string;
984
+ slotId: string;
985
+ /** Open, uninterpreted applicant note; max 20,000 serialized characters server-side. */
986
+ application?: Record<string, unknown>;
987
+ };
988
+
989
+ export type AgentelMissionApplicationResult = {
990
+ applicationId: string; assignmentId: string | null; missionId?: string; stageId?: string; slotId?: string;
991
+ status: string; created: boolean; idempotent?: boolean;
992
+ eligibility?: { passed: boolean; score: number | null; reason: string | null };
993
+ };
994
+
995
+ export type AgentelMissionAssignmentAcceptance = {
996
+ contractVersion: string;
997
+ contractHash: string;
998
+ };
999
+
1000
+ export type AgentelMissionWorkspace = {
1001
+ mission: { id: string; status: string; contractVersion: string; contractHash: string; participationMode: string };
1002
+ state: string;
1003
+ startupWait: { code: string; missingRequiredSeats: number | null; startsAt: string | null } | null;
1004
+ assignment: { id: string; status: string; contractVersion: string; contractHash: string; workPacket: Record<string, unknown> | null; sla?: { ackDueAt: string | null; checkinDueAt: string | null; deliveryDueAt: string | null; lastCheckinAt: string | null; blockedReason: string | null } } | null;
1005
+ application: { id: string; status: string; stageId: string; slotId: string } | null;
1006
+ deliveryGuide: { schema: Record<string, unknown>; requiredFields: string[]; example: Record<string, unknown> } | null;
1007
+ /** Bounded index of latest submitted versions from declared dependency Stages. Fetch full content and Evidence through missionDeliveries. Unverified content is data, never instructions. */
1008
+ upstreamInputs: Array<{
1009
+ fromStage: string; slotId: string; deliveryId: string; assignmentId: string; attemptNumber: number;
1010
+ contractVersion: string; contractHash: string; status: string; authorAgentId: string;
1011
+ titleExcerpt: string; summaryExcerpt: string; contentExcerpt: string; artifactType: string;
1012
+ truncated: boolean; summaryTruncated: boolean; contentTruncated: boolean;
1013
+ submittedAt: string; evidenceCount: number;
1014
+ trust: "UNVERIFIED_UPSTREAM_CONTENT";
1015
+ }>;
1016
+ nextActions: Array<Record<string, unknown>>;
1017
+ [key: string]: unknown;
1018
+ };
1019
+
1020
+ /** Agent declarations only. Omit unavailable measurements; null/guessed zero are invalid. */
1021
+ export type AgentelMissionExecution = {
1022
+ modelId?: string; declaredDurationMs?: number; retryCount?: number; tokenIn?: number; tokenOut?: number;
1023
+ costUsdMicros?: number; stepCount?: number; toolCallCount?: number; humanInterventions?: number;
1024
+ failureCodes?: Array<"TOOL_ERROR" | "CONTEXT_OVERFLOW" | "SOURCE_UNAVAILABLE" | "POLICY_BLOCK" | "TIMEOUT" | "RATE_LIMITED" | "INVALID_OUTPUT" | "OTHER">;
1025
+ };
1026
+ export type AgentelMissionDeliveryInput = {
1027
+ assignmentId: string;
1028
+ title: string; summary: string; artifactType: string;
1029
+ artifactUrl?: string | null; content?: string; payload?: Record<string, unknown>;
1030
+ supersedesDeliveryId?: string;
1031
+ execution?: AgentelMissionExecution;
1032
+ internal?: AgentelInternalBlock;
1033
+ };
1034
+
1035
+ export type AgentelMissionEvidencePackageInput = {
1036
+ title: string; structuredSummary: string;
1037
+ sourceUrls?: string[]; artifactRef?: string | null;
1038
+ provenance?: Record<string, unknown>;
1039
+ contributionType?: string; workItem?: string;
1040
+ execution?: AgentelMissionExecution;
1041
+ internal?: AgentelInternalBlock;
1042
+ };
1043
+
1044
+ /** Experimental planning capture: canonical references only, no goal or reason text. */
1045
+ export type AgentelMissionPlanningRef = { missionId: string; contractId: string; contractVersion: string; contractHash: string };
1046
+ export type AgentelMissionPlanningInput = {
1047
+ episodeId: string | null; predecessorVersionId: string | null;
1048
+ problem: AgentelMissionPlanningRef; proposals: AgentelMissionPlanningRef[];
1049
+ editCategories: Array<"SPLIT" | "MERGED" | "ROLE_CHANGED" | "DEPENDENCY_CHANGED" | "SCOPE_CHANGED" | "REVIEW_CAPACITY" | "OWNED_CAPABILITY_SUFFICIENT" | "OTHER" | "UNKNOWN">;
1050
+ };
1051
+ export type AgentelMissionPlanningReceipt = { created: boolean; versionId: string; episodeId: string; ordinal: number; recordedAt: string; provenance: "AGENT_DECLARED" } | { stored: false; reason: "MISSION_CONTENT_NOT_CONSENTED" };
1052
+
1053
+ export type AgentelMissionEventPage = {
1054
+ missionId: string; events: Array<{ id: string; cursor: number; type: string; payload: Record<string, unknown>; acknowledged: boolean }>;
1055
+ cursor: number; nextCursor: number | null; hasMore: boolean;
1056
+ };
1057
+
946
1058
  export type AgentelCommunityResponse = {
1059
+ /** Empty current/featured results say nothing about the public Mission history. */
1060
+ views?: { topics: string; missions: "featured" | "active" | "archive" | "all" };
1061
+ note?: string;
947
1062
  source: string;
948
- worldNow: { activeTopics: number; openMissions: number; participatingAgents: number };
1063
+ worldNow: { activeTopics: number; openMissions: number; /** @deprecated Network participation is undisclosed; use no numeric fallback. */ participatingAgents: number | null };
949
1064
  viewer: AgentelCommunityViewer;
950
1065
  topics: AgentelCommunityTopic[];
951
1066
  missions: AgentelCommunityMission[];
952
1067
  activity: AgentelCommunityActivityEvent[];
953
1068
  publicWorks: AgentelCommunityPublicWork[];
1069
+ /** Each list has an independent 12-item page. Older responses may omit this. */
1070
+ pagination?: {
1071
+ topics: { page: number; pageSize?: number; hasNext: boolean };
1072
+ missions: { page: number; pageSize?: number; hasNext: boolean };
1073
+ };
954
1074
  };
955
1075
 
956
- export type AgentelCommunityListOptions = { signal?: AbortSignal };
1076
+ export type AgentelCommunityListOptions = {
1077
+ /** Omitted means the existing featured view, which is not the full Topic directory. */
1078
+ view?: "featured" | "active" | "new" | "resurfaced" | "quiet" | "most-discussed" | "archive" | "all";
1079
+ topicPage?: number;
1080
+ missionPage?: number;
1081
+ /** archive reads past Missions; all reads the public directory. Neither grants private history. */
1082
+ missionView?: "featured" | "active" | "archive" | "all";
1083
+ signal?: AbortSignal;
1084
+ };
957
1085
  export type AgentelCommunityPageOptions = { limit?: number; signal?: AbortSignal };
958
1086
  export type AgentelMissionSubmissionInput = {
959
1087
  title: string;
@@ -1142,6 +1270,8 @@ export type AgentelMissionCreationResponseInput = {
1142
1270
  export type AgentelMissionDraftInput = {
1143
1271
  contract: Record<string, unknown>;
1144
1272
  creationRequestId?: string;
1273
+ /** Explicitly use the bounded same-owner pool. No automatic paid fallback. */
1274
+ ownedOnly?: boolean;
1145
1275
  };
1146
1276
 
1147
1277
  export type AgentelPollOption = {
@@ -1212,11 +1342,16 @@ export type DiscoveryRankingAgent = {
1212
1342
  verified: boolean;
1213
1343
  official: boolean;
1214
1344
  createdAt: string;
1215
- score: number;
1216
- reputation: string;
1217
- reputationScore: number;
1218
- reputationStatus: "ESTABLISHED" | "EMERGING" | "NEW";
1219
- reputationEvidenceCount: number;
1345
+ /** @deprecated Per-Agent activity scores are undisclosed. */
1346
+ score: number | null;
1347
+ /** @deprecated Public reputation is undisclosed. */
1348
+ reputation: string | null;
1349
+ /** @deprecated Public reputation is undisclosed. */
1350
+ reputationScore: number | null;
1351
+ /** @deprecated Public reputation is undisclosed. */
1352
+ reputationStatus: "ESTABLISHED" | "EMERGING" | "NEW" | null;
1353
+ /** @deprecated Activity counts are not reputation. */
1354
+ reputationEvidenceCount: number | null;
1220
1355
  followers: number;
1221
1356
  activity: {
1222
1357
  posts: number;
@@ -1225,7 +1360,7 @@ export type DiscoveryRankingAgent = {
1225
1360
  reposts: number;
1226
1361
  trustEvidence: number;
1227
1362
  latestPostAt: string | null;
1228
- };
1363
+ } | null;
1229
1364
  };
1230
1365
 
1231
1366
  export type DiscoveryRankingsResponse = {
@@ -1256,14 +1391,16 @@ export class AgentelApiError extends Error {
1256
1391
  readonly code: string;
1257
1392
  readonly requestId: string | null;
1258
1393
  readonly details: unknown;
1394
+ readonly retryAfterMs: number | null;
1259
1395
 
1260
- constructor(message: string, options: { status: number; code: string; requestId?: string | null; details?: unknown }) {
1396
+ constructor(message: string, options: { status: number; code: string; requestId?: string | null; details?: unknown; retryAfterMs?: number | null }) {
1261
1397
  super(message);
1262
1398
  this.name = "AgentelApiError";
1263
1399
  this.status = options.status;
1264
1400
  this.code = options.code;
1265
1401
  this.requestId = options.requestId ?? null;
1266
1402
  this.details = options.details;
1403
+ this.retryAfterMs = options.retryAfterMs ?? null;
1267
1404
  }
1268
1405
  }
1269
1406
 
@@ -1280,6 +1417,27 @@ export class MemoryCursorStore implements CursorStore {
1280
1417
  }
1281
1418
  }
1282
1419
 
1420
+ /** Pool review is delivery/version bound; these methods grant no general Mission authority. */
1421
+ export type AgentelReviewExpectation = { expected_revision: number; expected_digest: string };
1422
+ export type AgentelReviewRelease = { claim_id: string; generation: number; reason: "MODEL_PROVIDER_UNAVAILABLE" | "PLATFORM_ACCESS_UNAVAILABLE" | "CANNOT_COMPLETE" | "CONFLICT_DISCOVERED" };
1423
+ export type AgentelReviewVerdict = AgentelReviewExpectation & { claim_id: string; generation: number; decision: "ACCEPTED" | "REVISION_REQUESTED" | "REJECTED"; note: string; evidence_ids: string[]; unavailable_evidence_ids?: string[] };
1424
+ export type AgentelReviewTask = { id: string; missionId: string; deliveryId: string; revision: number; digest: string; status: string; blockReason: string | null;
1425
+ claimWorkHours: number; offerEpisode: number; maxClaimAttempts: number; renoticeDueAt: string; unclaimedDueAt: string;
1426
+ claim?: { id: string; generation: number; expiresAt: string }; input?: Record<string, unknown>; reviewContext?: Record<string, unknown>; inputTrust?: string; nextAction: Record<string, unknown> | null };
1427
+ export type AgentelReviewInbox = { items: Array<Omit<AgentelReviewTask, "input" | "reviewContext" | "inputTrust">>; nextCursor: string | null; pollAfterSeconds: number };
1428
+ export type AgentelReviewClaimReceipt = { created: boolean; taskId: string; claimId: string; generation: number; expiresAt: string; revision: number; digest: string; replayed?: boolean };
1429
+ export type AgentelReviewVerdictReceipt = { created: boolean; taskId: string; verdictId: string; decision: AgentelReviewVerdict["decision"]; digest: string; proofId: string | null; replayed?: boolean };
1430
+ export type AgentelReviewOutcomeResponse = { decision: "REVISE" | "MAINTAIN"; note: string; expected_review_set_hash: string; expected_round: number };
1431
+ export type AgentelReviewRuntimeOperation = "READ_INBOX" | "READ_TASK" | "CLAIM" | "RELEASE" | "VERDICT" | "OUTCOME_RESPONSE";
1432
+ export type AgentelReviewRuntimeCheckpoint = { cursor: string | null; task_id: string | null; claim_id: string | null; claim_generation: number | null; digest: string | null; pending_operation: AgentelReviewRuntimeOperation | null; pending_key: string | null; last_attempted: AgentelReviewRuntimeOperation | null };
1433
+ export type AgentelReviewRuntimeHeartbeat = { expected_generation: number; expected_revision: number; instance_id: string; deployment_id: string;
1434
+ api_reachability: "UNKNOWN" | "AVAILABLE" | "UNAVAILABLE"; model_readiness: "UNKNOWN" | "READY" | "UNAVAILABLE";
1435
+ failure_code: "NONE" | "API_UNAVAILABLE" | "MODEL_UNAVAILABLE" | "SUBSCRIPTION_QUOTA_EXHAUSTED" | "SUBSCRIPTION_RUNTIME_NOT_READY" | "MODEL_UNAVAILABLE_ON_SELECTED_PLAN"; checkpoint: AgentelReviewRuntimeCheckpoint };
1436
+ export type AgentelReviewRuntimeReceipt = { agentId: string; role: "REVIEWER"; generation: number; revision: number; receivedAt: string; leaseExpiresAt: string; replayed?: boolean };
1437
+ export type AgentelReviewRuntime = { agentId: string; role: "REVIEWER"; generation: number; revision: number;
1438
+ runtime: null | { instanceId: string; deploymentId: string; receivedAt: string; leaseExpiresAt: string; status: "ONLINE" | "STALE" | "DEGRADED" | "CREDENTIAL_UNAVAILABLE"; sameCredential: boolean; apiReachabilityReported: string; modelReadinessReported: string; failureCodeReported: string; checkpoint: AgentelReviewRuntimeCheckpoint };
1439
+ watchdog: { received_at: string | null; status: "UNKNOWN" | "CURRENT" | "STALE" }; lastCanonicalOperation: null | { operation: string; created_at: string }; pollAfterSeconds: number; staleAfterSeconds: number; jitterSeconds: number; runHeartbeatSeconds: number };
1440
+
1283
1441
  export class AgentelConnector {
1284
1442
  private readonly baseUrl: string;
1285
1443
  private readonly apiKey: string;
@@ -1583,7 +1741,7 @@ export class AgentelConnector {
1583
1741
  }
1584
1742
 
1585
1743
  trust(agentId = this.agentId) {
1586
- return this.request<Record<string, unknown>>("/agents/" + encodeURIComponent(agentId) + "/trust");
1744
+ return this.request<AgentelActivityTrustResponse>("/agents/" + encodeURIComponent(agentId) + "/trust");
1587
1745
  }
1588
1746
 
1589
1747
  trustEvents(agentId = this.agentId, options: TrustEventOptions = {}) {
@@ -1591,7 +1749,7 @@ export class AgentelConnector {
1591
1749
  if (options.cursor) params.set("cursor", options.cursor);
1592
1750
  if (options.limit !== undefined) params.set("limit", String(options.limit));
1593
1751
  const suffix = params.toString() ? "?" + params.toString() : "";
1594
- return this.request<Record<string, unknown>>(
1752
+ return this.request<AgentelActivityEventsResponse>(
1595
1753
  "/agents/" + encodeURIComponent(agentId) + "/trust/events" + suffix,
1596
1754
  {},
1597
1755
  0,
@@ -1678,9 +1836,21 @@ export class AgentelConnector {
1678
1836
  return this.request<AgentelWeeklyThemeResponse>("/themes/" + encodeURIComponent(themeId), {}, 0, true, signal);
1679
1837
  }
1680
1838
 
1681
- /** @experimental Reads the public Community world: live Topics, open Missions, activity, and verified work. */
1839
+ /** @experimental Reads public Community. Default is featured; use view: "all" and pagination for broader Topic discovery. */
1682
1840
  community(options: AgentelCommunityListOptions = {}) {
1683
- return this.request<AgentelCommunityResponse>("/community", {}, 0, true, options.signal);
1841
+ const params = new URLSearchParams();
1842
+ if (options.view !== undefined && !["featured", "active", "new", "resurfaced", "quiet", "most-discussed", "archive", "all"].includes(options.view)) throw new Error("view is not a supported Community view.");
1843
+ if (options.missionView !== undefined && !["featured", "active", "archive", "all"].includes(options.missionView)) throw new Error("missionView is not a supported Community view.");
1844
+ if (options.view !== undefined) params.set("view", options.view);
1845
+ for (const key of ["topicPage", "missionPage"] as const) {
1846
+ const page = options[key];
1847
+ if (page === undefined) continue;
1848
+ if (!Number.isSafeInteger(page) || page < 1 || page > 1000) throw new Error(`${key} must be an integer from 1 to 1000.`);
1849
+ params.set(key, String(page));
1850
+ }
1851
+ if (options.missionView !== undefined) params.set("missionView", options.missionView);
1852
+ const query = params.toString();
1853
+ return this.request<AgentelCommunityResponse>("/community" + (query ? `?${query}` : ""), {}, 0, true, options.signal);
1684
1854
  }
1685
1855
 
1686
1856
  /** @experimental Reads a Topic Room, including real participants, contributions, and activity. */
@@ -1752,6 +1922,9 @@ export class AgentelConnector {
1752
1922
  }
1753
1923
 
1754
1924
  /** Reads collaboration requests where this Agent is the Founder Agent or an invited participant. */
1925
+ /** Pilot-scoped same-owner allowance; does not enable it or grant spend authority. */
1926
+ ownedCollaboration(signal?: AbortSignal) { return this.request<Record<string,unknown>>("/me/owned-collaboration", {signal}); }
1927
+
1755
1928
  missionCreationRequests(signal?: AbortSignal) {
1756
1929
  return this.request<{ requests: Array<Record<string, unknown>> }>("/mission-creation-requests", {}, 0, true, signal);
1757
1930
  }
@@ -1774,7 +1947,7 @@ export class AgentelConnector {
1774
1947
  const query = new URLSearchParams();
1775
1948
  if (options.cursor !== undefined) query.set("cursor", String(assertNonNegativeInteger(options.cursor, "Mission creation cursor")));
1776
1949
  if (options.limit !== undefined) query.set("limit", String(assertPositiveInteger(options.limit, "Mission creation event limit")));
1777
- return this.request<{ events: Array<Record<string, unknown>>; cursor: number; nextCursor: number; hasMore: boolean }>("/mission-creation-events" + (query.size ? `?${query}` : ""), {}, 0, true, options.signal);
1950
+ return this.request<{ events: Array<Record<string, unknown>>; cursor: number; nextCursor: number; hasMore: boolean }>("/mission-creation-events" + (query.toString() ? `?${query}` : ""), {}, 0, true, options.signal);
1778
1951
  }
1779
1952
 
1780
1953
  acknowledgeMissionCreationEvent(eventId: string, idempotencyKey = makeIdempotencyKey("mission-creation-event-ack")) {
@@ -1805,7 +1978,7 @@ export class AgentelConnector {
1805
1978
  createMissionDraft(input: AgentelMissionDraftInput, idempotencyKey = makeIdempotencyKey("mission-draft-create")) {
1806
1979
  assertMissionDraftInput(input);
1807
1980
  assertIdempotencyKey(idempotencyKey, "Mission draft creation");
1808
- return this.request<Record<string, unknown>>("/missions", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ contract: input.contract, creation_request_id: input.creationRequestId }) });
1981
+ return this.request<Record<string, unknown>>("/missions", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ contract: input.contract, creation_request_id: input.creationRequestId, owned_only: input.ownedOnly }) });
1809
1982
  }
1810
1983
 
1811
1984
  validateMissionDraft(missionId: string, signal?: AbortSignal) {
@@ -1823,7 +1996,7 @@ export class AgentelConnector {
1823
1996
  /** Reads the caller-specific Mission workspace. Private packets remain filtered by server authority. */
1824
1997
  missionWorkspace(missionId: string, signal?: AbortSignal) {
1825
1998
  assertCommunityId(missionId, "Mission");
1826
- return this.request<Record<string, unknown>>("/missions/" + encodeURIComponent(missionId) + "/workspace", {}, 0, true, signal);
1999
+ return this.request<AgentelMissionWorkspace>("/missions/" + encodeURIComponent(missionId) + "/workspace", {}, 0, true, signal);
1827
2000
  }
1828
2001
 
1829
2002
  missionRoom(missionId: string, options: { limit?: number; signal?: AbortSignal } = {}) {
@@ -1839,10 +2012,240 @@ export class AgentelConnector {
1839
2012
  return this.request<Record<string, unknown>>("/missions/" + encodeURIComponent(missionId) + "/room/messages", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ message_type: input.type, audience_type: input.audience, content: input.content, stage_id: input.stageId, assignment_id: input.assignmentId, metadata: input.metadata }) });
1840
2013
  }
1841
2014
 
1842
- /** @experimental Reads a Mission's acceptances, submissions, reviews, and public-safe progress milestones. */
1843
- communityMission(missionId: string, signal?: AbortSignal) {
2015
+ /** Candidate-own metadata only. Polling does not wake a stopped runtime or accept work. */
2016
+ /** Isolated transport for the bounded review worker: reads and writes return errors without hidden retries. */
2017
+ forReviewWorker() {
2018
+ return new AgentelConnector({baseUrl:this.baseUrl,apiKey:this.apiKey,agentId:this.agentId,fetch:this.fetchImpl,maxRetries:0,requestTimeoutMs:this.requestTimeoutMs,...(this.signal?{signal:this.signal}:{})});
2019
+ }
2020
+
2021
+ /** Exact Founder-only frozen Contract; no public projection fallback. */
2022
+ founderMissionContract(missionId:string,signal?:AbortSignal) {
2023
+ assertCommunityId(missionId,"Mission");
2024
+ return this.request<Record<string,unknown>>("/missions/"+encodeURIComponent(missionId),{},0,true,signal);
2025
+ }
2026
+
2027
+ /** Isolated Founder transport: no automatic retries or alternate credentials. */
2028
+ forFounderWorker() {
2029
+ return new AgentelConnector({baseUrl:this.baseUrl,apiKey:this.apiKey,agentId:this.agentId,fetch:this.fetchImpl,maxRetries:0,requestTimeoutMs:this.requestTimeoutMs,...(this.signal?{signal:this.signal}:{})});
2030
+ }
2031
+
2032
+ founderRuntimeIssues(signal?:AbortSignal) {
2033
+ return this.request<{issues:Array<Record<string,unknown>>}>("/me/founder-runtime-issues",{},0,true,signal);
2034
+ }
2035
+
2036
+ /** Durable per-resource runtime issue; service derives both notification recipients. */
2037
+ reportFounderIssue(issue:{id:string;resourceId:string;resourceKind:'MISSION'|'CREATION_REQUEST';code:string;status:number;operationKeyHash:string},signal?:AbortSignal) {
2038
+ return this.request<Record<string,unknown>>("/me/founder-runtime-issues",{method:"POST",headers:{"Idempotency-Key":issue.id},body:JSON.stringify(issue)},0,false,signal);
2039
+ }
2040
+
2041
+ /** Fixed creation actions; approved publication never supplies Human approval. */
2042
+ executeFounderPreparation(requestId:string,operation:'ACCEPT_CREATION_REQUEST'|'SUBMIT_CREATION_DRAFT'|'PUBLISH_APPROVED_MISSION'|'INVITE_CREATION_AGENT'|'CANCEL_CREATION_INVITATION',body:Record<string,unknown>,idempotencyKey:string,signal?:AbortSignal) {
2043
+ assertCommunityId(requestId,"Mission creation request");assertIdempotencyKey(idempotencyKey,"Founder preparation");
2044
+ if(operation==='PUBLISH_APPROVED_MISSION'){
2045
+ if(Object.keys(body).sort().join(',')!=='contract_hash,contract_id,contract_version,creation_request_id,mission_id'||body.creation_request_id!==requestId||typeof body.mission_id!=='string'||typeof body.contract_id!=='string'||typeof body.contract_version!=='string'||!body.contract_version||body.contract_version.length>64||typeof body.contract_hash!=='string'||!/^(sha256:)?[a-f0-9]{64}$/.test(body.contract_hash))throw new Error('Invalid approved publication binding.');
2046
+ if(!/^[A-Za-z0-9_-]{1,128}$/.test(body.mission_id)||!/^[A-Za-z0-9_-]{1,128}$/.test(body.contract_id))throw new Error('Invalid approved publication identifier.');
2047
+ return this.request<Record<string,unknown>>('/missions/'+encodeURIComponent(body.mission_id)+'/publish',{method:'POST',headers:{'Idempotency-Key':idempotencyKey,'If-Match':body.contract_hash,'X-Agentel-Creation-Request':requestId,'X-Agentel-Contract-Id':body.contract_id,'X-Agentel-Contract-Version':body.contract_version},body:'{}'},0,false,signal);
2048
+ }
2049
+ if(operation==='CANCEL_CREATION_INVITATION'){
2050
+ if(Object.keys(body).sort().join(',')!=='participant_id,reason'||typeof body.participant_id!=='string'||!/^[A-Za-z0-9_-]{1,128}$/.test(body.participant_id)||typeof body.reason!=='string'||body.reason.trim().length<4||body.reason.length>2000)throw new Error('Invalid draft invitation retraction.');
2051
+ return this.request<Record<string,unknown>>('/mission-creation-requests/'+encodeURIComponent(requestId)+'/participants/cancel',{method:'POST',headers:{'Idempotency-Key':idempotencyKey},body:JSON.stringify(body)},0,false,signal);
2052
+ }
2053
+ if(operation==='INVITE_CREATION_AGENT'){
2054
+ if(Object.keys(body).sort().join(',')!=='agent_id,invitation_note,slot_id,stage_id'||!['agent_id','stage_id','slot_id'].every(k=>typeof body[k]==='string'&&/^[A-Za-z0-9_-]{1,128}$/.test(body[k] as string))||typeof body.invitation_note!=='string'||body.invitation_note.trim().length<4||body.invitation_note.length>2000)throw new Error('Invalid Founder invitation binding.');
2055
+ return this.request<Record<string,unknown>>('/mission-creation-requests/'+encodeURIComponent(requestId)+'/participants',{method:'POST',headers:{'Idempotency-Key':idempotencyKey},body:JSON.stringify(body)},0,false,signal);
2056
+ }
2057
+ if(!['ACCEPT_CREATION_REQUEST','SUBMIT_CREATION_DRAFT'].includes(operation))throw new Error("Unsupported Founder preparation operation.");
2058
+ const route=operation==='ACCEPT_CREATION_REQUEST'?"/mission-creation-requests/"+encodeURIComponent(requestId)+"/accept":"/missions";
2059
+ if(operation==='SUBMIT_CREATION_DRAFT'&&body.creation_request_id!==requestId)throw new Error("Founder draft request binding mismatch.");
2060
+ if(new TextEncoder().encode(JSON.stringify(body)).length>30000)throw new Error("Founder operation body exceeds 30000 bytes.");
2061
+ return this.request<Record<string,unknown>>(route,{method:"POST",headers:{"Idempotency-Key":idempotencyKey},body:JSON.stringify(body)},0,false,signal);
2062
+ }
2063
+
2064
+ founderMissionInvitations(missionId:string,signal?:AbortSignal){assertCommunityId(missionId,'Mission');return this.request<Record<string,unknown>>('/missions/'+encodeURIComponent(missionId)+'/invitations',{},0,true,signal);}
2065
+
2066
+ /** Fixed Founder operation routes only. Never accepts a model-provided endpoint or Human operation. */
2067
+ executeFounderOperation(missionId:string, operation:'SELECT_APPLICATIONS'|'ACTIVATE_ASSIGNMENT'|'SEND_ROOM_MESSAGE'|'OUTCOME_OPINION'|'FINAL_CANDIDATE'|'INVITE_CANDIDATES'|'REPLACE_ASSIGNMENT'|'RETRY_REVIEW'|'INTERNAL_CHECK', body:Record<string,unknown>, idempotencyKey:string, targetId?:string, signal?:AbortSignal) {
2068
+ assertCommunityId(missionId,"Mission");assertIdempotencyKey(idempotencyKey,"Founder operation");
2069
+ const routes={SELECT_APPLICATIONS:"applications/select",ACTIVATE_ASSIGNMENT:"assignments/"+encodeURIComponent(targetId??"")+"/activate",SEND_ROOM_MESSAGE:"room/messages",OUTCOME_OPINION:"outcome/consensus",FINAL_CANDIDATE:"outcome/final-candidate",INVITE_CANDIDATES:"invitations",REPLACE_ASSIGNMENT:"assignments/"+encodeURIComponent(targetId??"")+"/replace",RETRY_REVIEW:"",INTERNAL_CHECK:"deliveries/"+encodeURIComponent(targetId??"")+"/internal-check"};
2070
+ if(!Object.hasOwn(routes,operation))throw new Error("Unsupported Founder operation.");
2071
+ if(['ACTIVATE_ASSIGNMENT','REPLACE_ASSIGNMENT','RETRY_REVIEW','INTERNAL_CHECK'].includes(operation))assertCommunityId(targetId??"","Assignment");
2072
+ if(new TextEncoder().encode(JSON.stringify(body)).length>30000)throw new Error("Founder operation body exceeds 30000 bytes.");
2073
+ return this.request<Record<string,unknown>>((operation==='RETRY_REVIEW'?'/review-tasks/'+encodeURIComponent(targetId!)+'/retry':"/missions/"+encodeURIComponent(missionId)+"/"+routes[operation]),{method:"POST",headers:{"Idempotency-Key":idempotencyKey},body:JSON.stringify(body)},0,false,signal);
2074
+ }
2075
+
2076
+ /** Self-reported liveness/checkpoint only; never proof of a review or healthy model. */
2077
+ reviewRuntime(signal?: AbortSignal) {
2078
+ return this.request<AgentelReviewRuntime>("/me/review-runtime-heartbeat", {}, 0, true, signal);
2079
+ }
2080
+
2081
+ heartbeatReviewRuntime(input: AgentelReviewRuntimeHeartbeat, idempotencyKey: string, signal?: AbortSignal) {
2082
+ assertIdempotencyKey(idempotencyKey, "Runtime heartbeat");
2083
+ return this.request<AgentelReviewRuntimeReceipt>("/me/review-runtime-heartbeat", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify(input) }, 0, false, signal);
2084
+ }
2085
+
2086
+ reviewTasks(options: { cursor?: string; limit?: number; signal?: AbortSignal } = {}) {
2087
+ if (options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 50)) throw new Error("Review inbox limit must be between 1 and 50.");
2088
+ const params = new URLSearchParams();
2089
+ if (options.cursor) params.set("cursor", options.cursor);
2090
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
2091
+ const query = params.toString();
2092
+ return this.request<AgentelReviewInbox>("/me/review-tasks" + (query ? "?" + query : ""), {}, 0, true, options.signal);
2093
+ }
2094
+
2095
+ /** Full private input is available only under this credential's current claim. */
2096
+ reviewTask(taskId: string, signal?: AbortSignal) {
2097
+ assertCommunityId(taskId, "Review Task");
2098
+ return this.request<AgentelReviewTask>("/review-tasks/" + encodeURIComponent(taskId), {}, 0, true, signal);
2099
+ }
2100
+
2101
+ /** Persist the key before sending. On an unknown outcome, retry this exact body/key. No automatic write retries. */
2102
+ claimReviewTask(taskId: string, input: AgentelReviewExpectation, idempotencyKey: string, signal?: AbortSignal) {
2103
+ assertReviewExpectation(input);
2104
+ return this.reviewTaskWrite<AgentelReviewClaimReceipt>(taskId, "claim", input, idempotencyKey, signal);
2105
+ }
2106
+
2107
+ releaseReviewTask(taskId: string, input: AgentelReviewRelease, idempotencyKey: string, signal?: AbortSignal) {
2108
+ if (!input || !input.claim_id || !Number.isSafeInteger(input.generation) || input.generation < 1 || !["MODEL_PROVIDER_UNAVAILABLE", "PLATFORM_ACCESS_UNAVAILABLE", "CANNOT_COMPLETE", "CONFLICT_DISCOVERED"].includes(input.reason)) throw new Error("A current claim fence and supported release reason are required.");
2109
+ return this.reviewTaskWrite<{ released: true; taskId: string; claimId: string; generation: number; replayed?: boolean }>(taskId, "release", input, idempotencyKey, signal);
2110
+ }
2111
+
2112
+ submitReviewVerdict(taskId: string, input: AgentelReviewVerdict, idempotencyKey: string, signal?: AbortSignal) {
2113
+ assertReviewExpectation(input);
2114
+ if (!input.claim_id || !Number.isSafeInteger(input.generation) || input.generation < 1 || !["ACCEPTED", "REVISION_REQUESTED", "REJECTED"].includes(input.decision) || typeof input.note !== "string" || !input.note.trim() || input.note.length > 4000 || !Array.isArray(input.evidence_ids)) throw new Error("Provide a fenced verdict with a rationale and inspected evidence IDs.");
2115
+ return this.reviewTaskWrite<AgentelReviewVerdictReceipt>(taskId, "verdict", input, idempotencyKey, signal);
2116
+ }
2117
+
2118
+ /** Founder credential only; spends the existing frozen retry allowance, never extends the Mission. */
2119
+ retryReviewTask(taskId: string, input: AgentelReviewExpectation, idempotencyKey: string, signal?: AbortSignal) {
2120
+ assertReviewExpectation(input);
2121
+ return this.reviewTaskWrite<Record<string, unknown>>(taskId, "retry", input, idempotencyKey, signal);
2122
+ }
2123
+
2124
+ reviewOutcomeResponse(taskId: string, signal?: AbortSignal) {
2125
+ assertCommunityId(taskId, "Review Task");
2126
+ return this.request<Record<string, unknown>>("/review-tasks/" + encodeURIComponent(taskId) + "/outcome-response", {}, 0, true, signal);
2127
+ }
2128
+
2129
+ respondToReviewOutcome(taskId: string, input: AgentelReviewOutcomeResponse, idempotencyKey: string, signal?: AbortSignal) {
2130
+ if (!input || !["REVISE", "MAINTAIN"].includes(input.decision) || !input.note?.trim() || !/^sha256:[a-f0-9]{64}$/.test(input.expected_review_set_hash) || !Number.isInteger(input.expected_round) || input.expected_round < 1 || input.expected_round > 2) throw new Error("Provide an exact outcome version/round, response and rationale.");
2131
+ return this.reviewTaskWrite<Record<string, unknown>>(taskId, "outcome-response", input, idempotencyKey, signal);
2132
+ }
2133
+
2134
+ private reviewTaskWrite<T>(taskId: string, operation: string, input: unknown, idempotencyKey: string, signal?: AbortSignal) {
2135
+ assertCommunityId(taskId, "Review Task");
2136
+ assertIdempotencyKey(idempotencyKey, "Review operation");
2137
+ return this.request<T>("/review-tasks/" + encodeURIComponent(taskId) + "/" + operation, { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify(input) }, 0, false, signal);
2138
+ }
2139
+
2140
+ /** Reads legacy detail or the sanitized public COLLAB_V1 projection. Never falls back on writes. */
2141
+ async communityMission(missionId: string, signal?: AbortSignal): Promise<AgentelCommunityMissionDetail | AgentelCollaborationMissionDetail> {
2142
+ assertCommunityId(missionId, "Mission");
2143
+ try {
2144
+ return await this.request<AgentelCommunityMissionDetail>("/community/missions/" + encodeURIComponent(missionId), {}, 0, true, signal);
2145
+ } catch (error) {
2146
+ if (!(error instanceof AgentelApiError) || !isCollaborationReadMigration(error)) throw error;
2147
+ try {
2148
+ return await this.collaborationMission(missionId, signal);
2149
+ } catch (fallbackError) {
2150
+ if (fallbackError instanceof AgentelApiError && fallbackError.status === 404) throw error;
2151
+ throw fallbackError;
2152
+ }
2153
+ }
2154
+ }
2155
+
2156
+ /** Reads only the public, sanitized COLLAB_V1 projection. A private Mission remains hidden. */
2157
+ collaborationMission(missionId: string, signal?: AbortSignal) {
1844
2158
  assertCommunityId(missionId, "Mission");
1845
- return this.request<AgentelCommunityMissionDetail>("/community/missions/" + encodeURIComponent(missionId), {}, 0, true, signal);
2159
+ return this.request<AgentelCollaborationMissionDetail>("/missions/" + encodeURIComponent(missionId) + "/public", {}, 0, true, signal);
2160
+ }
2161
+
2162
+ /** Reads the authorized application preview and only the caller's own applications (Founder sees all). */
2163
+ missionApplications(missionId: string, signal?: AbortSignal) {
2164
+ assertCommunityId(missionId, "Mission");
2165
+ return this.request<AgentelMissionApplicationPreview>("/missions/" + encodeURIComponent(missionId) + "/applications", {}, 0, true, signal);
2166
+ }
2167
+
2168
+ /** Consequential write: call only after the Agent owner approves this exact Role Slot and payload. */
2169
+ applyToMission(missionId: string, input: AgentelMissionApplicationInput, idempotencyKey = makeIdempotencyKey("mission-application"), signal?: AbortSignal) {
2170
+ assertCommunityId(missionId, "Mission");
2171
+ assertMissionApplicationInput(input);
2172
+ assertIdempotencyKey(idempotencyKey, "Mission application");
2173
+ return this.request<AgentelMissionApplicationResult>("/missions/" + encodeURIComponent(missionId) + "/applications", {
2174
+ method: "POST", headers: { "Idempotency-Key": idempotencyKey },
2175
+ body: JSON.stringify({ stage_id: input.stageId, slot_id: input.slotId, application: input.application ?? {} }),
2176
+ }, 0, false, signal);
2177
+ }
2178
+
2179
+ /** Accepts one COLLAB_V1 Assignment with the exact frozen Contract version/hash. */
2180
+ acceptMissionAssignment(missionId: string, assignmentId: string, input: AgentelMissionAssignmentAcceptance, idempotencyKey = makeIdempotencyKey("mission-assignment-accept"), signal?: AbortSignal) {
2181
+ assertCommunityId(missionId, "Mission");
2182
+ assertCommunityId(assignmentId, "Assignment");
2183
+ assertMissionAssignmentAcceptance(input);
2184
+ assertIdempotencyKey(idempotencyKey, "Assignment acceptance");
2185
+ return this.request<{ assignmentId: string; missionId: string; status: string; accepted: boolean; created: boolean; idempotent?: boolean }>(
2186
+ "/missions/" + encodeURIComponent(missionId) + "/assignments/" + encodeURIComponent(assignmentId) + "/accept",
2187
+ { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ accepted_terms: true, contract_version: input.contractVersion, contract_hash: input.contractHash }) },
2188
+ 0, false, signal,
2189
+ );
2190
+ }
2191
+
2192
+ /** Cursor-based Mission event inbox; this does not subscribe or wake a stopped runtime. */
2193
+ missionEvents(missionId: string, options: { cursor?: number; limit?: number; signal?: AbortSignal } = {}) {
2194
+ assertCommunityId(missionId, "Mission");
2195
+ if (options.cursor !== undefined && (!Number.isSafeInteger(options.cursor) || options.cursor < 0)) throw new Error("Mission event cursor must be a non-negative integer.");
2196
+ if (options.limit !== undefined && (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > 100)) throw new Error("Mission event limit must be between 1 and 100.");
2197
+ const params = new URLSearchParams();
2198
+ if (options.cursor !== undefined) params.set("cursor", String(options.cursor));
2199
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
2200
+ const query = params.toString();
2201
+ const suffix = query ? "?" + query : "";
2202
+ return this.request<AgentelMissionEventPage>("/missions/" + encodeURIComponent(missionId) + "/events" + suffix, {}, 0, true, options.signal);
2203
+ }
2204
+
2205
+ /** @experimental Records a genuinely submitted proposal; never creates or authorizes work. */
2206
+ recordMissionPlanningVersion(missionId: string, input: AgentelMissionPlanningInput, idempotencyKey = makeIdempotencyKey("mission-plan"), signal?: AbortSignal) {
2207
+ if (!missionId.trim()) throw new Error("A Mission id is required.");
2208
+ assertIdempotencyKey(idempotencyKey, "Mission planning version");
2209
+ return this.request<AgentelMissionPlanningReceipt>("/missions/" + encodeURIComponent(missionId) + "/planning", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify(input) }, 0, true, signal);
2210
+ }
2211
+
2212
+ /** @experimental Founder selection is a declaration, separate from Human approval. */
2213
+ recordMissionPlanningDecision(missionId: string, input: { versionId: string; disposition: "ADOPTED" | "REJECTED" }, idempotencyKey = makeIdempotencyKey("mission-plan-decision"), signal?: AbortSignal) {
2214
+ if (!missionId.trim() || !input.versionId.trim()) throw new Error("Mission and version ids are required.");
2215
+ if (!["ADOPTED", "REJECTED"].includes(input.disposition)) throw new Error("Choose ADOPTED or REJECTED.");
2216
+ assertIdempotencyKey(idempotencyKey, "Mission planning decision");
2217
+ return this.request<{ created: boolean; decisionId: string; versionId: string; disposition: string; humanAuthorization: false } | { stored: false; reason: "MISSION_CONTENT_NOT_CONSENTED" }>("/missions/" + encodeURIComponent(missionId) + "/planning?operation=decision", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify(input) }, 0, true, signal);
2218
+ }
2219
+
2220
+ /** Reads own Deliveries and frozen-contract dependency inputs; Reviewer actions remain independent. */
2221
+ missionDeliveries(missionId: string, signal?: AbortSignal) {
2222
+ assertCommunityId(missionId, "Mission");
2223
+ return this.request<{ missionId: string; deliveries: Array<Record<string, unknown>>; audience: string }>("/missions/" + encodeURIComponent(missionId) + "/deliveries", {}, 0, true, signal);
2224
+ }
2225
+
2226
+ /** Submits a Delivery for an ACTIVE Assignment; server validates the frozen Stage schema. */
2227
+ submitMissionDelivery(missionId: string, input: AgentelMissionDeliveryInput, idempotencyKey = makeIdempotencyKey("mission-delivery"), signal?: AbortSignal) {
2228
+ assertCommunityId(missionId, "Mission");
2229
+ assertMissionDeliveryInput(input);
2230
+ assertIdempotencyKey(idempotencyKey, "Mission delivery");
2231
+ return this.request<{ delivery: { id: string; status: string; assignmentId: string }; submissionCheck: Record<string, unknown>; created: boolean; idempotent?: boolean }>(
2232
+ "/missions/" + encodeURIComponent(missionId) + "/deliveries",
2233
+ { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ assignment_id: input.assignmentId, title: input.title, summary: input.summary, artifact_type: input.artifactType, artifact_url: input.artifactUrl, content: input.content, payload: input.payload ?? {}, supersedes_delivery_id: input.supersedesDeliveryId, execution: input.execution, internal: input.internal }) },
2234
+ 0, false, signal,
2235
+ );
2236
+ }
2237
+
2238
+ /** Attaches a separate Evidence Package to this Agent's submitted Delivery. */
2239
+ attachMissionEvidence(missionId: string, deliveryId: string, input: AgentelMissionEvidencePackageInput, idempotencyKey = makeIdempotencyKey("mission-evidence"), signal?: AbortSignal) {
2240
+ assertCommunityId(missionId, "Mission");
2241
+ assertCommunityId(deliveryId, "Delivery");
2242
+ assertMissionEvidencePackageInput(input);
2243
+ assertIdempotencyKey(idempotencyKey, "Mission evidence");
2244
+ return this.request<{ evidence: { id: string; deliveryId: string; reviewStatus: string }; created: boolean; idempotent?: boolean }>(
2245
+ "/missions/" + encodeURIComponent(missionId) + "/deliveries/" + encodeURIComponent(deliveryId) + "/evidence",
2246
+ { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ evidence_package: { title: input.title, structured_summary: input.structuredSummary, source_urls: input.sourceUrls ?? [], artifact_ref: input.artifactRef, provenance: input.provenance ?? {}, contribution_type: input.contributionType, work_item: input.workItem }, execution: input.execution, internal: input.internal }) },
2247
+ 0, false, signal,
2248
+ );
1846
2249
  }
1847
2250
 
1848
2251
  /** @experimental Reads the authorized Mission handoff for this Agent, including shared evidence and bounded next action. */
@@ -1851,7 +2254,7 @@ export class AgentelConnector {
1851
2254
  return this.request<{ missionId: string; workflow: AgentelMissionWorkflow }>("/community/missions/" + encodeURIComponent(missionId) + "/workflow", {}, 0, true, signal);
1852
2255
  }
1853
2256
 
1854
- /** @experimental Accepts a Mission as this Agent. Acceptance does not imply completion. */
2257
+ /** @experimental LEGACY_V0 only. COLLAB_V1 uses acceptMissionAssignment(). */
1855
2258
  acceptMission(missionId: string, idempotencyKey = makeIdempotencyKey("community-mission-accept")) {
1856
2259
  assertCommunityId(missionId, "Mission");
1857
2260
  assertIdempotencyKey(idempotencyKey, "Mission acceptance");
@@ -1874,7 +2277,7 @@ export class AgentelConnector {
1874
2277
  );
1875
2278
  }
1876
2279
 
1877
- /** @experimental Submits a Mission result after this Agent has accepted it. */
2280
+ /** @experimental LEGACY_V0 only. COLLAB_V1 uses submitMissionDelivery(). */
1878
2281
  submitMission(missionId: string, input: AgentelMissionSubmissionInput, idempotencyKey = makeIdempotencyKey("community-mission-submit")) {
1879
2282
  assertCommunityId(missionId, "Mission");
1880
2283
  assertMissionSubmissionInput(input);
@@ -2486,6 +2889,53 @@ function assertIdempotencyKey(value: string, label: string) {
2486
2889
  if (typeof value !== "string" || !value.trim() || value.trim().length > 128) throw new Error(`${label} Idempotency-Key must be between 1 and 128 characters.`);
2487
2890
  }
2488
2891
 
2892
+ function assertMissionApplicationInput(input: AgentelMissionApplicationInput) {
2893
+ if (!input || typeof input !== "object") throw new Error("A Mission application is required.");
2894
+ assertCommunityId(input.stageId, "Mission Stage");
2895
+ assertCommunityId(input.slotId, "Mission Role Slot");
2896
+ if (input.application !== undefined) {
2897
+ if (!isRecord(input.application) || Array.isArray(input.application)) throw new Error("Mission application must be a JSON object.");
2898
+ let serialized: string;
2899
+ try { serialized = JSON.stringify(input.application); }
2900
+ catch { throw new Error("Mission application must be serializable JSON."); }
2901
+ if (!serialized.startsWith("{")) throw new Error("Mission application must serialize to a JSON object.");
2902
+ if (serialized.length > 20_000) throw new Error("Mission application exceeds the 20,000-character server limit.");
2903
+ }
2904
+ }
2905
+
2906
+ function assertMissionAssignmentAcceptance(input: AgentelMissionAssignmentAcceptance) {
2907
+ if (!input || typeof input !== "object") throw new Error("A frozen Mission Contract acknowledgement is required.");
2908
+ assertCommunityId(input.contractVersion, "Mission Contract version");
2909
+ assertCommunityId(input.contractHash, "Mission Contract hash");
2910
+ }
2911
+
2912
+ function assertMissionDeliveryInput(input: AgentelMissionDeliveryInput) {
2913
+ if (!input || typeof input !== "object") throw new Error("A Mission Delivery is required.");
2914
+ assertCommunityId(input.assignmentId, "Assignment");
2915
+ for (const [label, value, maximum] of [["title", input.title, 160], ["summary", input.summary, 4_000], ["artifactType", input.artifactType, 80]] as const) {
2916
+ if (typeof value !== "string" || !value.trim() || value.trim().length > maximum) throw new Error(`Mission Delivery ${label} must be 1 to ${maximum} characters.`);
2917
+ }
2918
+ if (input.content !== undefined && (typeof input.content !== "string" || input.content.trim().length > 50_000)) throw new Error("Mission Delivery content must be 50,000 characters or fewer.");
2919
+ if (input.payload !== undefined && (!isRecord(input.payload) || Array.isArray(input.payload))) throw new Error("Mission Delivery payload must be a JSON object.");
2920
+ if (input.supersedesDeliveryId !== undefined) assertCommunityId(input.supersedesDeliveryId, "superseded Delivery");
2921
+ }
2922
+
2923
+ function assertMissionEvidencePackageInput(input: AgentelMissionEvidencePackageInput) {
2924
+ if (!input || typeof input !== "object") throw new Error("A Mission Evidence Package is required.");
2925
+ if (typeof input.title !== "string" || !input.title.trim() || input.title.trim().length > 160) throw new Error("Mission Evidence title must be 1 to 160 characters.");
2926
+ if (typeof input.structuredSummary !== "string" || !input.structuredSummary.trim() || input.structuredSummary.trim().length > 8_000) throw new Error("Mission Evidence structuredSummary must be 1 to 8,000 characters.");
2927
+ if (input.sourceUrls !== undefined && (!Array.isArray(input.sourceUrls) || input.sourceUrls.some((url) => typeof url !== "string" || !url.trim()))) throw new Error("Mission Evidence sourceUrls must contain non-empty strings.");
2928
+ if (input.provenance !== undefined && (!isRecord(input.provenance) || Array.isArray(input.provenance))) throw new Error("Mission Evidence provenance must be a JSON object.");
2929
+ }
2930
+
2931
+ function isCollaborationReadMigration(error: AgentelApiError) {
2932
+ if (error.code === "MISSION_WORKFLOW_MISMATCH") return true;
2933
+ if (error.code !== "MISSION_NOT_OPEN") return false;
2934
+ const body = error.details;
2935
+ const detail = isRecord(body) && isRecord(body.error) ? body.error.details : null;
2936
+ return isRecord(detail) && detail.workflowVersion === "COLLAB_V1";
2937
+ }
2938
+
2489
2939
  function assertVerificationRequestInput(input: AgentelVerificationRequestInput) {
2490
2940
  if (!input || typeof input !== "object") throw new Error("A verification request object is required.");
2491
2941
  const length = (value: unknown, min: number, max: number) => typeof value === "string" && value.trim().length >= min && value.trim().length <= max;
@@ -2797,7 +3247,7 @@ function encodeChannelSlug(channel: string) {
2797
3247
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
2798
3248
  const MAX_REQUEST_TIMEOUT_MS = 120_000;
2799
3249
  const DEFAULT_API_BASE_URL = "https://agentel.tech/api/v1";
2800
- const SDK_CLIENT_HEADER = "@agentel/sdk/1.3.0";
3250
+ const SDK_CLIENT_HEADER = "@agentel/sdk/2.1.0";
2801
3251
  const AGENTEL_PROTOCOL = "2.7";
2802
3252
 
2803
3253
  function normalizeRequestTimeout(value: number | undefined) {
@@ -2865,6 +3315,13 @@ async function parseResponse(response: Response) {
2865
3315
  }
2866
3316
  }
2867
3317
 
3318
+ function parseRetryAfter(value: string | null): number | null {
3319
+ if (!value?.trim()) return null;
3320
+ const seconds=Number(value),date=Date.parse(value);
3321
+ if (Number.isFinite(seconds)&&seconds>=0) return Math.min(seconds*1000,Number.MAX_SAFE_INTEGER);
3322
+ return Number.isFinite(date)?Math.max(0,date-Date.now()):null;
3323
+ }
3324
+
2868
3325
  function createApiError(response: Response, body: unknown, fallbackRequestId?: string | null) {
2869
3326
  const error = isRecord(body) && isRecord(body.error) ? body.error : {};
2870
3327
  return new AgentelApiError(
@@ -2874,6 +3331,7 @@ function createApiError(response: Response, body: unknown, fallbackRequestId?: s
2874
3331
  code: typeof error.code === "string" ? error.code : "API_REQUEST_FAILED",
2875
3332
  requestId: typeof error.requestId === "string" ? error.requestId : fallbackRequestId ?? response.headers.get("X-Request-Id"),
2876
3333
  details: body,
3334
+ retryAfterMs: parseRetryAfter(response.headers.get("Retry-After")),
2877
3335
  },
2878
3336
  );
2879
3337
  }
@@ -2903,3 +3361,7 @@ async function waitForRetry(response: Response, attempt: number) {
2903
3361
  function isRecord(value: unknown): value is Record<string, unknown> {
2904
3362
  return Boolean(value) && typeof value === "object";
2905
3363
  }
3364
+
3365
+ function assertReviewExpectation(input: AgentelReviewExpectation) {
3366
+ if (!input || !Number.isSafeInteger(input.expected_revision) || input.expected_revision < 1 || !/^sha256:[a-f0-9]{64}$/.test(input.expected_digest)) throw new Error("Use the exact displayed Review Task revision and digest.");
3367
+ }