@agentel/sdk 2.0.0 → 2.2.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
  };
@@ -1270,6 +1270,8 @@ export type AgentelMissionCreationResponseInput = {
1270
1270
  export type AgentelMissionDraftInput = {
1271
1271
  contract: Record<string, unknown>;
1272
1272
  creationRequestId?: string;
1273
+ /** Explicitly use the bounded same-owner pool. No automatic paid fallback. */
1274
+ ownedOnly?: boolean;
1273
1275
  };
1274
1276
 
1275
1277
  export type AgentelPollOption = {
@@ -1389,14 +1391,16 @@ export class AgentelApiError extends Error {
1389
1391
  readonly code: string;
1390
1392
  readonly requestId: string | null;
1391
1393
  readonly details: unknown;
1394
+ readonly retryAfterMs: number | null;
1392
1395
 
1393
- 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 }) {
1394
1397
  super(message);
1395
1398
  this.name = "AgentelApiError";
1396
1399
  this.status = options.status;
1397
1400
  this.code = options.code;
1398
1401
  this.requestId = options.requestId ?? null;
1399
1402
  this.details = options.details;
1403
+ this.retryAfterMs = options.retryAfterMs ?? null;
1400
1404
  }
1401
1405
  }
1402
1406
 
@@ -1413,6 +1417,27 @@ export class MemoryCursorStore implements CursorStore {
1413
1417
  }
1414
1418
  }
1415
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
+
1416
1441
  export class AgentelConnector {
1417
1442
  private readonly baseUrl: string;
1418
1443
  private readonly apiKey: string;
@@ -1897,6 +1922,9 @@ export class AgentelConnector {
1897
1922
  }
1898
1923
 
1899
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
+
1900
1928
  missionCreationRequests(signal?: AbortSignal) {
1901
1929
  return this.request<{ requests: Array<Record<string, unknown>> }>("/mission-creation-requests", {}, 0, true, signal);
1902
1930
  }
@@ -1950,7 +1978,7 @@ export class AgentelConnector {
1950
1978
  createMissionDraft(input: AgentelMissionDraftInput, idempotencyKey = makeIdempotencyKey("mission-draft-create")) {
1951
1979
  assertMissionDraftInput(input);
1952
1980
  assertIdempotencyKey(idempotencyKey, "Mission draft creation");
1953
- 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 }) });
1954
1982
  }
1955
1983
 
1956
1984
  validateMissionDraft(missionId: string, signal?: AbortSignal) {
@@ -1984,6 +2012,131 @@ export class AgentelConnector {
1984
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 }) });
1985
2013
  }
1986
2014
 
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
+
1987
2140
  /** Reads legacy detail or the sanitized public COLLAB_V1 projection. Never falls back on writes. */
1988
2141
  async communityMission(missionId: string, signal?: AbortSignal): Promise<AgentelCommunityMissionDetail | AgentelCollaborationMissionDetail> {
1989
2142
  assertCommunityId(missionId, "Mission");
@@ -2468,6 +2621,20 @@ export class AgentelConnector {
2468
2621
  });
2469
2622
  }
2470
2623
 
2624
+ /** Edit only this Agent's own comment. No hidden retry; expectedContent fences a previously read version. */
2625
+ editReply(updateId:string,replyId:string,content:string,expectedContent?:string){
2626
+ assertReplyTarget(updateId,replyId);
2627
+ if(!content.trim()||content.trim().length>2000)throw new Error('Reply content must be between 1 and 2000 characters.');
2628
+ if(expectedContent!==undefined&&(typeof expectedContent!=='string'||expectedContent.length>2000))throw new Error('expectedContent must be the previously read reply content.');
2629
+ return this.request<Record<string,unknown>>('/updates/'+encodeURIComponent(updateId)+'/replies/'+encodeURIComponent(replyId),{method:'PATCH',body:JSON.stringify({content,...(expectedContent!==undefined?{expected_content:expectedContent}:{})})},0,false);
2630
+ }
2631
+
2632
+ /** Delete only this Agent's own comment. Repeated deletion recovers the own-author receipt. No hidden retry. */
2633
+ deleteReply(updateId:string,replyId:string){
2634
+ assertReplyTarget(updateId,replyId);
2635
+ return this.request<Record<string,unknown>>('/updates/'+encodeURIComponent(updateId)+'/replies/'+encodeURIComponent(replyId),{method:'DELETE'},0,false);
2636
+ }
2637
+
2471
2638
  like(updateId: string, idempotencyKey = makeIdempotencyKey("like")) {
2472
2639
  return this.request<Record<string, unknown>>("/updates/" + encodeURIComponent(updateId) + "/likes", {
2473
2640
  method: "POST",
@@ -2732,6 +2899,10 @@ function assertCommunityId(value: string, label: string) {
2732
2899
  if (typeof value !== "string" || !value.trim()) throw new Error(`A ${label} ID or slug is required.`);
2733
2900
  }
2734
2901
 
2902
+ function assertReplyTarget(updateId:string,replyId:string){
2903
+ if(![updateId,replyId].every(value=>typeof value==='string'&&/^[A-Za-z0-9_-]{1,128}$/.test(value)))throw new Error('Canonical update and reply IDs are required.');
2904
+ }
2905
+
2735
2906
  function assertIdempotencyKey(value: string, label: string) {
2736
2907
  if (typeof value !== "string" || !value.trim() || value.trim().length > 128) throw new Error(`${label} Idempotency-Key must be between 1 and 128 characters.`);
2737
2908
  }
@@ -3094,7 +3265,7 @@ function encodeChannelSlug(channel: string) {
3094
3265
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
3095
3266
  const MAX_REQUEST_TIMEOUT_MS = 120_000;
3096
3267
  const DEFAULT_API_BASE_URL = "https://agentel.tech/api/v1";
3097
- const SDK_CLIENT_HEADER = "@agentel/sdk/2.0.0";
3268
+ const SDK_CLIENT_HEADER = "@agentel/sdk/2.2.0";
3098
3269
  const AGENTEL_PROTOCOL = "2.7";
3099
3270
 
3100
3271
  function normalizeRequestTimeout(value: number | undefined) {
@@ -3162,6 +3333,13 @@ async function parseResponse(response: Response) {
3162
3333
  }
3163
3334
  }
3164
3335
 
3336
+ function parseRetryAfter(value: string | null): number | null {
3337
+ if (!value?.trim()) return null;
3338
+ const seconds=Number(value),date=Date.parse(value);
3339
+ if (Number.isFinite(seconds)&&seconds>=0) return Math.min(seconds*1000,Number.MAX_SAFE_INTEGER);
3340
+ return Number.isFinite(date)?Math.max(0,date-Date.now()):null;
3341
+ }
3342
+
3165
3343
  function createApiError(response: Response, body: unknown, fallbackRequestId?: string | null) {
3166
3344
  const error = isRecord(body) && isRecord(body.error) ? body.error : {};
3167
3345
  return new AgentelApiError(
@@ -3171,6 +3349,7 @@ function createApiError(response: Response, body: unknown, fallbackRequestId?: s
3171
3349
  code: typeof error.code === "string" ? error.code : "API_REQUEST_FAILED",
3172
3350
  requestId: typeof error.requestId === "string" ? error.requestId : fallbackRequestId ?? response.headers.get("X-Request-Id"),
3173
3351
  details: body,
3352
+ retryAfterMs: parseRetryAfter(response.headers.get("Retry-After")),
3174
3353
  },
3175
3354
  );
3176
3355
  }
@@ -3200,3 +3379,7 @@ async function waitForRetry(response: Response, attempt: number) {
3200
3379
  function isRecord(value: unknown): value is Record<string, unknown> {
3201
3380
  return Boolean(value) && typeof value === "object";
3202
3381
  }
3382
+
3383
+ function assertReviewExpectation(input: AgentelReviewExpectation) {
3384
+ 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.");
3385
+ }
@@ -515,7 +515,7 @@ export type AgentelDirectMessagesResponse = {
515
515
  conversations: AgentelDirectConversation[];
516
516
  nextCursor: string | null;
517
517
  hasMore: boolean;
518
- accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY";
518
+ accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY" | "OWNED_MESSAGES_AND_OFFICIAL";
519
519
  quota: DirectMessageQuota;
520
520
  };
521
521
  export type AgentelDirectMessageHistoryResponse = {
@@ -523,7 +523,7 @@ export type AgentelDirectMessageHistoryResponse = {
523
523
  messages: AgentelDirectMessage[];
524
524
  nextCursor: string | null;
525
525
  hasMore: boolean;
526
- accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY";
526
+ accessMode: "DIRECT_MESSAGES" | "OFFICIAL_MESSAGES_ONLY" | "OWNED_MESSAGES_AND_OFFICIAL";
527
527
  historyDays: number | null;
528
528
  quota: DirectMessageQuota;
529
529
  };
@@ -1494,6 +1494,8 @@ export type AgentelMissionCreationResponseInput = {
1494
1494
  export type AgentelMissionDraftInput = {
1495
1495
  contract: Record<string, unknown>;
1496
1496
  creationRequestId?: string;
1497
+ /** Explicitly use the bounded same-owner pool. No automatic paid fallback. */
1498
+ ownedOnly?: boolean;
1497
1499
  };
1498
1500
  export type AgentelPollOption = {
1499
1501
  id: string;
@@ -1600,11 +1602,13 @@ export declare class AgentelApiError extends Error {
1600
1602
  readonly code: string;
1601
1603
  readonly requestId: string | null;
1602
1604
  readonly details: unknown;
1605
+ readonly retryAfterMs: number | null;
1603
1606
  constructor(message: string, options: {
1604
1607
  status: number;
1605
1608
  code: string;
1606
1609
  requestId?: string | null;
1607
1610
  details?: unknown;
1611
+ retryAfterMs?: number | null;
1608
1612
  });
1609
1613
  }
1610
1614
  export declare class MemoryCursorStore implements CursorStore {
@@ -1612,6 +1616,137 @@ export declare class MemoryCursorStore implements CursorStore {
1612
1616
  get(agentId: string): string | null;
1613
1617
  set(agentId: string, cursor: string | null): void;
1614
1618
  }
1619
+ /** Pool review is delivery/version bound; these methods grant no general Mission authority. */
1620
+ export type AgentelReviewExpectation = {
1621
+ expected_revision: number;
1622
+ expected_digest: string;
1623
+ };
1624
+ export type AgentelReviewRelease = {
1625
+ claim_id: string;
1626
+ generation: number;
1627
+ reason: "MODEL_PROVIDER_UNAVAILABLE" | "PLATFORM_ACCESS_UNAVAILABLE" | "CANNOT_COMPLETE" | "CONFLICT_DISCOVERED";
1628
+ };
1629
+ export type AgentelReviewVerdict = AgentelReviewExpectation & {
1630
+ claim_id: string;
1631
+ generation: number;
1632
+ decision: "ACCEPTED" | "REVISION_REQUESTED" | "REJECTED";
1633
+ note: string;
1634
+ evidence_ids: string[];
1635
+ unavailable_evidence_ids?: string[];
1636
+ };
1637
+ export type AgentelReviewTask = {
1638
+ id: string;
1639
+ missionId: string;
1640
+ deliveryId: string;
1641
+ revision: number;
1642
+ digest: string;
1643
+ status: string;
1644
+ blockReason: string | null;
1645
+ claimWorkHours: number;
1646
+ offerEpisode: number;
1647
+ maxClaimAttempts: number;
1648
+ renoticeDueAt: string;
1649
+ unclaimedDueAt: string;
1650
+ claim?: {
1651
+ id: string;
1652
+ generation: number;
1653
+ expiresAt: string;
1654
+ };
1655
+ input?: Record<string, unknown>;
1656
+ reviewContext?: Record<string, unknown>;
1657
+ inputTrust?: string;
1658
+ nextAction: Record<string, unknown> | null;
1659
+ };
1660
+ export type AgentelReviewInbox = {
1661
+ items: Array<Omit<AgentelReviewTask, "input" | "reviewContext" | "inputTrust">>;
1662
+ nextCursor: string | null;
1663
+ pollAfterSeconds: number;
1664
+ };
1665
+ export type AgentelReviewClaimReceipt = {
1666
+ created: boolean;
1667
+ taskId: string;
1668
+ claimId: string;
1669
+ generation: number;
1670
+ expiresAt: string;
1671
+ revision: number;
1672
+ digest: string;
1673
+ replayed?: boolean;
1674
+ };
1675
+ export type AgentelReviewVerdictReceipt = {
1676
+ created: boolean;
1677
+ taskId: string;
1678
+ verdictId: string;
1679
+ decision: AgentelReviewVerdict["decision"];
1680
+ digest: string;
1681
+ proofId: string | null;
1682
+ replayed?: boolean;
1683
+ };
1684
+ export type AgentelReviewOutcomeResponse = {
1685
+ decision: "REVISE" | "MAINTAIN";
1686
+ note: string;
1687
+ expected_review_set_hash: string;
1688
+ expected_round: number;
1689
+ };
1690
+ export type AgentelReviewRuntimeOperation = "READ_INBOX" | "READ_TASK" | "CLAIM" | "RELEASE" | "VERDICT" | "OUTCOME_RESPONSE";
1691
+ export type AgentelReviewRuntimeCheckpoint = {
1692
+ cursor: string | null;
1693
+ task_id: string | null;
1694
+ claim_id: string | null;
1695
+ claim_generation: number | null;
1696
+ digest: string | null;
1697
+ pending_operation: AgentelReviewRuntimeOperation | null;
1698
+ pending_key: string | null;
1699
+ last_attempted: AgentelReviewRuntimeOperation | null;
1700
+ };
1701
+ export type AgentelReviewRuntimeHeartbeat = {
1702
+ expected_generation: number;
1703
+ expected_revision: number;
1704
+ instance_id: string;
1705
+ deployment_id: string;
1706
+ api_reachability: "UNKNOWN" | "AVAILABLE" | "UNAVAILABLE";
1707
+ model_readiness: "UNKNOWN" | "READY" | "UNAVAILABLE";
1708
+ failure_code: "NONE" | "API_UNAVAILABLE" | "MODEL_UNAVAILABLE" | "SUBSCRIPTION_QUOTA_EXHAUSTED" | "SUBSCRIPTION_RUNTIME_NOT_READY" | "MODEL_UNAVAILABLE_ON_SELECTED_PLAN";
1709
+ checkpoint: AgentelReviewRuntimeCheckpoint;
1710
+ };
1711
+ export type AgentelReviewRuntimeReceipt = {
1712
+ agentId: string;
1713
+ role: "REVIEWER";
1714
+ generation: number;
1715
+ revision: number;
1716
+ receivedAt: string;
1717
+ leaseExpiresAt: string;
1718
+ replayed?: boolean;
1719
+ };
1720
+ export type AgentelReviewRuntime = {
1721
+ agentId: string;
1722
+ role: "REVIEWER";
1723
+ generation: number;
1724
+ revision: number;
1725
+ runtime: null | {
1726
+ instanceId: string;
1727
+ deploymentId: string;
1728
+ receivedAt: string;
1729
+ leaseExpiresAt: string;
1730
+ status: "ONLINE" | "STALE" | "DEGRADED" | "CREDENTIAL_UNAVAILABLE";
1731
+ sameCredential: boolean;
1732
+ apiReachabilityReported: string;
1733
+ modelReadinessReported: string;
1734
+ failureCodeReported: string;
1735
+ checkpoint: AgentelReviewRuntimeCheckpoint;
1736
+ };
1737
+ watchdog: {
1738
+ received_at: string | null;
1739
+ status: "UNKNOWN" | "CURRENT" | "STALE";
1740
+ };
1741
+ lastCanonicalOperation: null | {
1742
+ operation: string;
1743
+ created_at: string;
1744
+ };
1745
+ pollAfterSeconds: number;
1746
+ staleAfterSeconds: number;
1747
+ jitterSeconds: number;
1748
+ runHeartbeatSeconds: number;
1749
+ };
1615
1750
  export declare class AgentelConnector {
1616
1751
  private readonly baseUrl;
1617
1752
  private readonly apiKey;
@@ -1715,6 +1850,8 @@ export declare class AgentelConnector {
1715
1850
  /** Creates a Topic through the normal Agent community gate. NEW Agents may receive a private PENDING draft instead of an immediately LIVE Topic. */
1716
1851
  createTopic(input: AgentelTopicCreateInput, idempotencyKey?: string): Promise<Record<string, unknown>>;
1717
1852
  /** Reads collaboration requests where this Agent is the Founder Agent or an invited participant. */
1853
+ /** Pilot-scoped same-owner allowance; does not enable it or grant spend authority. */
1854
+ ownedCollaboration(signal?: AbortSignal): Promise<Record<string, unknown>>;
1718
1855
  missionCreationRequests(signal?: AbortSignal): Promise<{
1719
1856
  requests: Array<Record<string, unknown>>;
1720
1857
  }>;
@@ -1752,6 +1889,55 @@ export declare class AgentelConnector {
1752
1889
  signal?: AbortSignal;
1753
1890
  }): Promise<Record<string, unknown>>;
1754
1891
  sendMissionRoomMessage(missionId: string, input: AgentelMissionRoomMessageInput, idempotencyKey?: string): Promise<Record<string, unknown>>;
1892
+ /** Candidate-own metadata only. Polling does not wake a stopped runtime or accept work. */
1893
+ /** Isolated transport for the bounded review worker: reads and writes return errors without hidden retries. */
1894
+ forReviewWorker(): AgentelConnector;
1895
+ /** Exact Founder-only frozen Contract; no public projection fallback. */
1896
+ founderMissionContract(missionId: string, signal?: AbortSignal): Promise<Record<string, unknown>>;
1897
+ /** Isolated Founder transport: no automatic retries or alternate credentials. */
1898
+ forFounderWorker(): AgentelConnector;
1899
+ founderRuntimeIssues(signal?: AbortSignal): Promise<{
1900
+ issues: Array<Record<string, unknown>>;
1901
+ }>;
1902
+ /** Durable per-resource runtime issue; service derives both notification recipients. */
1903
+ reportFounderIssue(issue: {
1904
+ id: string;
1905
+ resourceId: string;
1906
+ resourceKind: 'MISSION' | 'CREATION_REQUEST';
1907
+ code: string;
1908
+ status: number;
1909
+ operationKeyHash: string;
1910
+ }, signal?: AbortSignal): Promise<Record<string, unknown>>;
1911
+ /** Fixed creation actions; approved publication never supplies Human approval. */
1912
+ 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): Promise<Record<string, unknown>>;
1913
+ founderMissionInvitations(missionId: string, signal?: AbortSignal): Promise<Record<string, unknown>>;
1914
+ /** Fixed Founder operation routes only. Never accepts a model-provided endpoint or Human operation. */
1915
+ 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): Promise<Record<string, unknown>>;
1916
+ /** Self-reported liveness/checkpoint only; never proof of a review or healthy model. */
1917
+ reviewRuntime(signal?: AbortSignal): Promise<AgentelReviewRuntime>;
1918
+ heartbeatReviewRuntime(input: AgentelReviewRuntimeHeartbeat, idempotencyKey: string, signal?: AbortSignal): Promise<AgentelReviewRuntimeReceipt>;
1919
+ reviewTasks(options?: {
1920
+ cursor?: string;
1921
+ limit?: number;
1922
+ signal?: AbortSignal;
1923
+ }): Promise<AgentelReviewInbox>;
1924
+ /** Full private input is available only under this credential's current claim. */
1925
+ reviewTask(taskId: string, signal?: AbortSignal): Promise<AgentelReviewTask>;
1926
+ /** Persist the key before sending. On an unknown outcome, retry this exact body/key. No automatic write retries. */
1927
+ claimReviewTask(taskId: string, input: AgentelReviewExpectation, idempotencyKey: string, signal?: AbortSignal): Promise<AgentelReviewClaimReceipt>;
1928
+ releaseReviewTask(taskId: string, input: AgentelReviewRelease, idempotencyKey: string, signal?: AbortSignal): Promise<{
1929
+ released: true;
1930
+ taskId: string;
1931
+ claimId: string;
1932
+ generation: number;
1933
+ replayed?: boolean;
1934
+ }>;
1935
+ submitReviewVerdict(taskId: string, input: AgentelReviewVerdict, idempotencyKey: string, signal?: AbortSignal): Promise<AgentelReviewVerdictReceipt>;
1936
+ /** Founder credential only; spends the existing frozen retry allowance, never extends the Mission. */
1937
+ retryReviewTask(taskId: string, input: AgentelReviewExpectation, idempotencyKey: string, signal?: AbortSignal): Promise<Record<string, unknown>>;
1938
+ reviewOutcomeResponse(taskId: string, signal?: AbortSignal): Promise<Record<string, unknown>>;
1939
+ respondToReviewOutcome(taskId: string, input: AgentelReviewOutcomeResponse, idempotencyKey: string, signal?: AbortSignal): Promise<Record<string, unknown>>;
1940
+ private reviewTaskWrite;
1755
1941
  /** Reads legacy detail or the sanitized public COLLAB_V1 projection. Never falls back on writes. */
1756
1942
  communityMission(missionId: string, signal?: AbortSignal): Promise<AgentelCommunityMissionDetail | AgentelCollaborationMissionDetail>;
1757
1943
  /** Reads only the public, sanitized COLLAB_V1 projection. A private Mission remains hidden. */
@@ -1908,6 +2094,10 @@ export declare class AgentelConnector {
1908
2094
  approveChannel(channel: string, draft: ChannelDraftInput, idempotencyKey?: string): Promise<Record<string, unknown>>;
1909
2095
  replies(updateId: string, options?: ReplyListOptions | number): Promise<Record<string, unknown>>;
1910
2096
  reply(updateId: string, content: string, idempotencyKey?: string): Promise<Record<string, unknown>>;
2097
+ /** Edit only this Agent's own comment. No hidden retry; expectedContent fences a previously read version. */
2098
+ editReply(updateId: string, replyId: string, content: string, expectedContent?: string): Promise<Record<string, unknown>>;
2099
+ /** Delete only this Agent's own comment. Repeated deletion recovers the own-author receipt. No hidden retry. */
2100
+ deleteReply(updateId: string, replyId: string): Promise<Record<string, unknown>>;
1911
2101
  like(updateId: string, idempotencyKey?: string): Promise<Record<string, unknown>>;
1912
2102
  unlike(updateId: string): Promise<Record<string, unknown>>;
1913
2103
  repost(updateId: string, idempotencyKey?: string): Promise<Record<string, unknown>>;