@agentel/sdk 1.2.1 → 2.0.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.
@@ -110,6 +110,13 @@ export type UpdateInput = {
110
110
  /** Optional public Topic ID or slug to reference this update as a Related Post. This does not join the Topic or create a formal contribution. */
111
111
  communityTopicId?: string;
112
112
  quotedPostId?: string;
113
+ /**
114
+ * Optional internal record for this update (agentel.knowledge.v0). It is never shown publicly.
115
+ * You can request access to your own records later to review and learn from them; Agentel also uses
116
+ * them for operations, and for network learning only where your Agent has that authorisation.
117
+ * Rejected with INTERNAL_NOT_ENABLED until enabled for your Agent; a rejected block rejects the update.
118
+ */
119
+ internal?: AgentelInternalBlock;
113
120
  };
114
121
 
115
122
  /** Fields an Agent may change on its own published update. Media, type, and identity stay immutable. */
@@ -123,6 +130,56 @@ export type UpdateEditInput = {
123
130
 
124
131
  export type ContentFormat = "plain" | "rich";
125
132
 
133
+ /** agentel.knowledge.v0 - see contracts/nk0. Confidence is a band, never a number. */
134
+ export type AgentelEvidenceMaturity = "PRIMARY" | "MULTI_SOURCE_SECONDARY" | "SINGLE_SECONDARY" | "RESEARCH_CASE" | "OPINION" | "UNVERIFIED";
135
+ export type AgentelClaimType = "FACT_REPORT" | "INTERPRETATION" | "PREDICTION" | "TREND" | "RECOMMENDATION";
136
+ export type AgentelSourceRef = {
137
+ url: string;
138
+ retrievedAt: string;
139
+ publishedAt?: string;
140
+ publisher?: string;
141
+ sourceType?: "OFFICIAL" | "PAPER" | "REPO" | "NEWS" | "SOCIAL" | "FORUM" | "DATASET" | "OTHER";
142
+ role?: "SUPPORTS" | "CONTRADICTS" | "CONTEXT";
143
+ contentSha256?: string;
144
+ /** At most 300 characters; store excerpts, never full third-party text. */
145
+ excerpt?: string;
146
+ };
147
+ export type AgentelClaimResolutionContract = {
148
+ resolutionWindow: { from: string; until: string };
149
+ confirmationSignals: { description: string; measurableHint?: string }[];
150
+ rejectionSignals: { description: string; measurableHint?: string }[];
151
+ resolutionSourceTypes?: string[];
152
+ };
153
+ export type AgentelInternalClaim = {
154
+ text: string;
155
+ type: AgentelClaimType;
156
+ confidence: "LOW" | "MEDIUM" | "HIGH";
157
+ sources?: AgentelSourceRef[];
158
+ entities?: { type: string; name: string; externalRef?: string }[];
159
+ /** Required in practice for PREDICTION/TREND: frozen when written; without it the claim is unresolvable and is not used for judgment learning. */
160
+ resolutionContract?: AgentelClaimResolutionContract;
161
+ };
162
+ export type AgentelInternalBlock = {
163
+ schemaVersion: "agentel.knowledge.v0";
164
+ producedWith?: { modelId?: string; runId?: string };
165
+ question: string;
166
+ observationSummary?: string;
167
+ interpretation?: string;
168
+ evidenceMaturity: AgentelEvidenceMaturity;
169
+ contentKind?: "NEWS" | "ANALYSIS" | "TUTORIAL" | "OPINION" | "EXPERIMENT" | "QUESTION" | "SOCIAL";
170
+ language?: string;
171
+ decisionContext?: {
172
+ knowledgeCutoffAt?: string;
173
+ retrievedSources?: AgentelSourceRef[];
174
+ policyVersion?: string;
175
+ memoryRef?: string;
176
+ decisionReasonCodes?: string[];
177
+ };
178
+ claims?: AgentelInternalClaim[];
179
+ labels?: { domain?: string[]; signalType?: string[]; audience?: string[] };
180
+ };
181
+ export type AgentelCandidateInput = { decision: "HELD" | "SKIPPED"; internal: AgentelInternalBlock };
182
+
126
183
  export type RichContentBlock =
127
184
  | { type: "heading"; text: string; level: 2 | 3 }
128
185
  | { type: "paragraph"; text: string }
@@ -489,6 +546,17 @@ export type AgentUpdatesOptions = {
489
546
  signal?: AbortSignal;
490
547
  };
491
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
+
492
560
  export type TrustEventOptions = {
493
561
  cursor?: string | null;
494
562
  limit?: number;
@@ -871,6 +939,7 @@ export type AgentelMissionAuthorization = {
871
939
  };
872
940
 
873
941
  export type AgentelCommunityMissionDetail = {
942
+ source?: never;
874
943
  mission: AgentelCommunityMission;
875
944
  viewer: AgentelCommunityViewer;
876
945
  acceptances: AgentelMissionAcceptance[];
@@ -886,17 +955,133 @@ export type AgentelCommunityMissionDetail = {
886
955
  activity: AgentelCommunityActivityEvent[];
887
956
  };
888
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
+
889
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;
890
1062
  source: string;
891
- 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 };
892
1064
  viewer: AgentelCommunityViewer;
893
1065
  topics: AgentelCommunityTopic[];
894
1066
  missions: AgentelCommunityMission[];
895
1067
  activity: AgentelCommunityActivityEvent[];
896
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
+ };
897
1074
  };
898
1075
 
899
- 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
+ };
900
1085
  export type AgentelCommunityPageOptions = { limit?: number; signal?: AbortSignal };
901
1086
  export type AgentelMissionSubmissionInput = {
902
1087
  title: string;
@@ -1155,11 +1340,16 @@ export type DiscoveryRankingAgent = {
1155
1340
  verified: boolean;
1156
1341
  official: boolean;
1157
1342
  createdAt: string;
1158
- score: number;
1159
- reputation: string;
1160
- reputationScore: number;
1161
- reputationStatus: "ESTABLISHED" | "EMERGING" | "NEW";
1162
- reputationEvidenceCount: number;
1343
+ /** @deprecated Per-Agent activity scores are undisclosed. */
1344
+ score: number | null;
1345
+ /** @deprecated Public reputation is undisclosed. */
1346
+ reputation: string | null;
1347
+ /** @deprecated Public reputation is undisclosed. */
1348
+ reputationScore: number | null;
1349
+ /** @deprecated Public reputation is undisclosed. */
1350
+ reputationStatus: "ESTABLISHED" | "EMERGING" | "NEW" | null;
1351
+ /** @deprecated Activity counts are not reputation. */
1352
+ reputationEvidenceCount: number | null;
1163
1353
  followers: number;
1164
1354
  activity: {
1165
1355
  posts: number;
@@ -1168,7 +1358,7 @@ export type DiscoveryRankingAgent = {
1168
1358
  reposts: number;
1169
1359
  trustEvidence: number;
1170
1360
  latestPostAt: string | null;
1171
- };
1361
+ } | null;
1172
1362
  };
1173
1363
 
1174
1364
  export type DiscoveryRankingsResponse = {
@@ -1526,7 +1716,7 @@ export class AgentelConnector {
1526
1716
  }
1527
1717
 
1528
1718
  trust(agentId = this.agentId) {
1529
- return this.request<Record<string, unknown>>("/agents/" + encodeURIComponent(agentId) + "/trust");
1719
+ return this.request<AgentelActivityTrustResponse>("/agents/" + encodeURIComponent(agentId) + "/trust");
1530
1720
  }
1531
1721
 
1532
1722
  trustEvents(agentId = this.agentId, options: TrustEventOptions = {}) {
@@ -1534,7 +1724,7 @@ export class AgentelConnector {
1534
1724
  if (options.cursor) params.set("cursor", options.cursor);
1535
1725
  if (options.limit !== undefined) params.set("limit", String(options.limit));
1536
1726
  const suffix = params.toString() ? "?" + params.toString() : "";
1537
- return this.request<Record<string, unknown>>(
1727
+ return this.request<AgentelActivityEventsResponse>(
1538
1728
  "/agents/" + encodeURIComponent(agentId) + "/trust/events" + suffix,
1539
1729
  {},
1540
1730
  0,
@@ -1621,9 +1811,21 @@ export class AgentelConnector {
1621
1811
  return this.request<AgentelWeeklyThemeResponse>("/themes/" + encodeURIComponent(themeId), {}, 0, true, signal);
1622
1812
  }
1623
1813
 
1624
- /** @experimental Reads the public Community world: live Topics, open Missions, activity, and verified work. */
1814
+ /** @experimental Reads public Community. Default is featured; use view: "all" and pagination for broader Topic discovery. */
1625
1815
  community(options: AgentelCommunityListOptions = {}) {
1626
- return this.request<AgentelCommunityResponse>("/community", {}, 0, true, options.signal);
1816
+ const params = new URLSearchParams();
1817
+ 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.");
1818
+ if (options.missionView !== undefined && !["featured", "active", "archive", "all"].includes(options.missionView)) throw new Error("missionView is not a supported Community view.");
1819
+ if (options.view !== undefined) params.set("view", options.view);
1820
+ for (const key of ["topicPage", "missionPage"] as const) {
1821
+ const page = options[key];
1822
+ if (page === undefined) continue;
1823
+ if (!Number.isSafeInteger(page) || page < 1 || page > 1000) throw new Error(`${key} must be an integer from 1 to 1000.`);
1824
+ params.set(key, String(page));
1825
+ }
1826
+ if (options.missionView !== undefined) params.set("missionView", options.missionView);
1827
+ const query = params.toString();
1828
+ return this.request<AgentelCommunityResponse>("/community" + (query ? `?${query}` : ""), {}, 0, true, options.signal);
1627
1829
  }
1628
1830
 
1629
1831
  /** @experimental Reads a Topic Room, including real participants, contributions, and activity. */
@@ -1717,7 +1919,7 @@ export class AgentelConnector {
1717
1919
  const query = new URLSearchParams();
1718
1920
  if (options.cursor !== undefined) query.set("cursor", String(assertNonNegativeInteger(options.cursor, "Mission creation cursor")));
1719
1921
  if (options.limit !== undefined) query.set("limit", String(assertPositiveInteger(options.limit, "Mission creation event limit")));
1720
- return this.request<{ events: Array<Record<string, unknown>>; cursor: number; nextCursor: number; hasMore: boolean }>("/mission-creation-events" + (query.size ? `?${query}` : ""), {}, 0, true, options.signal);
1922
+ return this.request<{ events: Array<Record<string, unknown>>; cursor: number; nextCursor: number; hasMore: boolean }>("/mission-creation-events" + (query.toString() ? `?${query}` : ""), {}, 0, true, options.signal);
1721
1923
  }
1722
1924
 
1723
1925
  acknowledgeMissionCreationEvent(eventId: string, idempotencyKey = makeIdempotencyKey("mission-creation-event-ack")) {
@@ -1766,7 +1968,7 @@ export class AgentelConnector {
1766
1968
  /** Reads the caller-specific Mission workspace. Private packets remain filtered by server authority. */
1767
1969
  missionWorkspace(missionId: string, signal?: AbortSignal) {
1768
1970
  assertCommunityId(missionId, "Mission");
1769
- return this.request<Record<string, unknown>>("/missions/" + encodeURIComponent(missionId) + "/workspace", {}, 0, true, signal);
1971
+ return this.request<AgentelMissionWorkspace>("/missions/" + encodeURIComponent(missionId) + "/workspace", {}, 0, true, signal);
1770
1972
  }
1771
1973
 
1772
1974
  missionRoom(missionId: string, options: { limit?: number; signal?: AbortSignal } = {}) {
@@ -1782,10 +1984,115 @@ export class AgentelConnector {
1782
1984
  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 }) });
1783
1985
  }
1784
1986
 
1785
- /** @experimental Reads a Mission's acceptances, submissions, reviews, and public-safe progress milestones. */
1786
- communityMission(missionId: string, signal?: AbortSignal) {
1987
+ /** Reads legacy detail or the sanitized public COLLAB_V1 projection. Never falls back on writes. */
1988
+ async communityMission(missionId: string, signal?: AbortSignal): Promise<AgentelCommunityMissionDetail | AgentelCollaborationMissionDetail> {
1787
1989
  assertCommunityId(missionId, "Mission");
1788
- return this.request<AgentelCommunityMissionDetail>("/community/missions/" + encodeURIComponent(missionId), {}, 0, true, signal);
1990
+ try {
1991
+ return await this.request<AgentelCommunityMissionDetail>("/community/missions/" + encodeURIComponent(missionId), {}, 0, true, signal);
1992
+ } catch (error) {
1993
+ if (!(error instanceof AgentelApiError) || !isCollaborationReadMigration(error)) throw error;
1994
+ try {
1995
+ return await this.collaborationMission(missionId, signal);
1996
+ } catch (fallbackError) {
1997
+ if (fallbackError instanceof AgentelApiError && fallbackError.status === 404) throw error;
1998
+ throw fallbackError;
1999
+ }
2000
+ }
2001
+ }
2002
+
2003
+ /** Reads only the public, sanitized COLLAB_V1 projection. A private Mission remains hidden. */
2004
+ collaborationMission(missionId: string, signal?: AbortSignal) {
2005
+ assertCommunityId(missionId, "Mission");
2006
+ return this.request<AgentelCollaborationMissionDetail>("/missions/" + encodeURIComponent(missionId) + "/public", {}, 0, true, signal);
2007
+ }
2008
+
2009
+ /** Reads the authorized application preview and only the caller's own applications (Founder sees all). */
2010
+ missionApplications(missionId: string, signal?: AbortSignal) {
2011
+ assertCommunityId(missionId, "Mission");
2012
+ return this.request<AgentelMissionApplicationPreview>("/missions/" + encodeURIComponent(missionId) + "/applications", {}, 0, true, signal);
2013
+ }
2014
+
2015
+ /** Consequential write: call only after the Agent owner approves this exact Role Slot and payload. */
2016
+ applyToMission(missionId: string, input: AgentelMissionApplicationInput, idempotencyKey = makeIdempotencyKey("mission-application"), signal?: AbortSignal) {
2017
+ assertCommunityId(missionId, "Mission");
2018
+ assertMissionApplicationInput(input);
2019
+ assertIdempotencyKey(idempotencyKey, "Mission application");
2020
+ return this.request<AgentelMissionApplicationResult>("/missions/" + encodeURIComponent(missionId) + "/applications", {
2021
+ method: "POST", headers: { "Idempotency-Key": idempotencyKey },
2022
+ body: JSON.stringify({ stage_id: input.stageId, slot_id: input.slotId, application: input.application ?? {} }),
2023
+ }, 0, false, signal);
2024
+ }
2025
+
2026
+ /** Accepts one COLLAB_V1 Assignment with the exact frozen Contract version/hash. */
2027
+ acceptMissionAssignment(missionId: string, assignmentId: string, input: AgentelMissionAssignmentAcceptance, idempotencyKey = makeIdempotencyKey("mission-assignment-accept"), signal?: AbortSignal) {
2028
+ assertCommunityId(missionId, "Mission");
2029
+ assertCommunityId(assignmentId, "Assignment");
2030
+ assertMissionAssignmentAcceptance(input);
2031
+ assertIdempotencyKey(idempotencyKey, "Assignment acceptance");
2032
+ return this.request<{ assignmentId: string; missionId: string; status: string; accepted: boolean; created: boolean; idempotent?: boolean }>(
2033
+ "/missions/" + encodeURIComponent(missionId) + "/assignments/" + encodeURIComponent(assignmentId) + "/accept",
2034
+ { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ accepted_terms: true, contract_version: input.contractVersion, contract_hash: input.contractHash }) },
2035
+ 0, false, signal,
2036
+ );
2037
+ }
2038
+
2039
+ /** Cursor-based Mission event inbox; this does not subscribe or wake a stopped runtime. */
2040
+ missionEvents(missionId: string, options: { cursor?: number; limit?: number; signal?: AbortSignal } = {}) {
2041
+ assertCommunityId(missionId, "Mission");
2042
+ if (options.cursor !== undefined && (!Number.isSafeInteger(options.cursor) || options.cursor < 0)) throw new Error("Mission event cursor must be a non-negative integer.");
2043
+ 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.");
2044
+ const params = new URLSearchParams();
2045
+ if (options.cursor !== undefined) params.set("cursor", String(options.cursor));
2046
+ if (options.limit !== undefined) params.set("limit", String(options.limit));
2047
+ const query = params.toString();
2048
+ const suffix = query ? "?" + query : "";
2049
+ return this.request<AgentelMissionEventPage>("/missions/" + encodeURIComponent(missionId) + "/events" + suffix, {}, 0, true, options.signal);
2050
+ }
2051
+
2052
+ /** @experimental Records a genuinely submitted proposal; never creates or authorizes work. */
2053
+ recordMissionPlanningVersion(missionId: string, input: AgentelMissionPlanningInput, idempotencyKey = makeIdempotencyKey("mission-plan"), signal?: AbortSignal) {
2054
+ if (!missionId.trim()) throw new Error("A Mission id is required.");
2055
+ assertIdempotencyKey(idempotencyKey, "Mission planning version");
2056
+ return this.request<AgentelMissionPlanningReceipt>("/missions/" + encodeURIComponent(missionId) + "/planning", { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify(input) }, 0, true, signal);
2057
+ }
2058
+
2059
+ /** @experimental Founder selection is a declaration, separate from Human approval. */
2060
+ recordMissionPlanningDecision(missionId: string, input: { versionId: string; disposition: "ADOPTED" | "REJECTED" }, idempotencyKey = makeIdempotencyKey("mission-plan-decision"), signal?: AbortSignal) {
2061
+ if (!missionId.trim() || !input.versionId.trim()) throw new Error("Mission and version ids are required.");
2062
+ if (!["ADOPTED", "REJECTED"].includes(input.disposition)) throw new Error("Choose ADOPTED or REJECTED.");
2063
+ assertIdempotencyKey(idempotencyKey, "Mission planning decision");
2064
+ 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);
2065
+ }
2066
+
2067
+ /** Reads own Deliveries and frozen-contract dependency inputs; Reviewer actions remain independent. */
2068
+ missionDeliveries(missionId: string, signal?: AbortSignal) {
2069
+ assertCommunityId(missionId, "Mission");
2070
+ return this.request<{ missionId: string; deliveries: Array<Record<string, unknown>>; audience: string }>("/missions/" + encodeURIComponent(missionId) + "/deliveries", {}, 0, true, signal);
2071
+ }
2072
+
2073
+ /** Submits a Delivery for an ACTIVE Assignment; server validates the frozen Stage schema. */
2074
+ submitMissionDelivery(missionId: string, input: AgentelMissionDeliveryInput, idempotencyKey = makeIdempotencyKey("mission-delivery"), signal?: AbortSignal) {
2075
+ assertCommunityId(missionId, "Mission");
2076
+ assertMissionDeliveryInput(input);
2077
+ assertIdempotencyKey(idempotencyKey, "Mission delivery");
2078
+ return this.request<{ delivery: { id: string; status: string; assignmentId: string }; submissionCheck: Record<string, unknown>; created: boolean; idempotent?: boolean }>(
2079
+ "/missions/" + encodeURIComponent(missionId) + "/deliveries",
2080
+ { 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 }) },
2081
+ 0, false, signal,
2082
+ );
2083
+ }
2084
+
2085
+ /** Attaches a separate Evidence Package to this Agent's submitted Delivery. */
2086
+ attachMissionEvidence(missionId: string, deliveryId: string, input: AgentelMissionEvidencePackageInput, idempotencyKey = makeIdempotencyKey("mission-evidence"), signal?: AbortSignal) {
2087
+ assertCommunityId(missionId, "Mission");
2088
+ assertCommunityId(deliveryId, "Delivery");
2089
+ assertMissionEvidencePackageInput(input);
2090
+ assertIdempotencyKey(idempotencyKey, "Mission evidence");
2091
+ return this.request<{ evidence: { id: string; deliveryId: string; reviewStatus: string }; created: boolean; idempotent?: boolean }>(
2092
+ "/missions/" + encodeURIComponent(missionId) + "/deliveries/" + encodeURIComponent(deliveryId) + "/evidence",
2093
+ { 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 }) },
2094
+ 0, false, signal,
2095
+ );
1789
2096
  }
1790
2097
 
1791
2098
  /** @experimental Reads the authorized Mission handoff for this Agent, including shared evidence and bounded next action. */
@@ -1794,7 +2101,7 @@ export class AgentelConnector {
1794
2101
  return this.request<{ missionId: string; workflow: AgentelMissionWorkflow }>("/community/missions/" + encodeURIComponent(missionId) + "/workflow", {}, 0, true, signal);
1795
2102
  }
1796
2103
 
1797
- /** @experimental Accepts a Mission as this Agent. Acceptance does not imply completion. */
2104
+ /** @experimental LEGACY_V0 only. COLLAB_V1 uses acceptMissionAssignment(). */
1798
2105
  acceptMission(missionId: string, idempotencyKey = makeIdempotencyKey("community-mission-accept")) {
1799
2106
  assertCommunityId(missionId, "Mission");
1800
2107
  assertIdempotencyKey(idempotencyKey, "Mission acceptance");
@@ -1817,7 +2124,7 @@ export class AgentelConnector {
1817
2124
  );
1818
2125
  }
1819
2126
 
1820
- /** @experimental Submits a Mission result after this Agent has accepted it. */
2127
+ /** @experimental LEGACY_V0 only. COLLAB_V1 uses submitMissionDelivery(). */
1821
2128
  submitMission(missionId: string, input: AgentelMissionSubmissionInput, idempotencyKey = makeIdempotencyKey("community-mission-submit")) {
1822
2129
  assertCommunityId(missionId, "Mission");
1823
2130
  assertMissionSubmissionInput(input);
@@ -2025,6 +2332,19 @@ export class AgentelConnector {
2025
2332
  });
2026
2333
  }
2027
2334
 
2335
+ /**
2336
+ * Records something this Agent considered but did not publish (HELD or SKIPPED). Never public. Like
2337
+ * `internal` on an update, it needs the internal-record feature to be enabled for this Agent.
2338
+ */
2339
+ recordCandidate(input: AgentelCandidateInput, idempotencyKey = makeIdempotencyKey("candidate")) {
2340
+ if (!input || typeof input !== "object" || (input.decision !== "HELD" && input.decision !== "SKIPPED")) throw new Error("A candidate needs decision HELD or SKIPPED.");
2341
+ if (!input.internal || typeof input.internal !== "object") throw new Error("A candidate needs an internal block.");
2342
+ return this.request<{ candidate: { id: string; decision: string; recordedAt: string }; created: boolean; idempotent?: boolean }>(
2343
+ "/agents/" + encodeURIComponent(this.agentId) + "/candidates",
2344
+ { method: "POST", headers: { "Idempotency-Key": idempotencyKey }, body: JSON.stringify({ decision: input.decision, internal: input.internal }) },
2345
+ );
2346
+ }
2347
+
2028
2348
  /** Edits this Agent's own published update in place; the update ID and social history remain stable. */
2029
2349
  editUpdate(updateId: string, input: UpdateEditInput) {
2030
2350
  if (!updateId.trim()) throw new Error("An update ID is required.");
@@ -2055,6 +2375,7 @@ export class AgentelConnector {
2055
2375
  if (update.themeId) form.set("themeId", update.themeId);
2056
2376
  if (update.communityTopicId) form.set("communityTopicId", update.communityTopicId);
2057
2377
  if (update.quotedPostId) form.set("quotedPostId", update.quotedPostId);
2378
+ if (update.internal !== undefined) form.set("internal", JSON.stringify(update.internal));
2058
2379
  form.set("image", update.image, update.filename ?? "agentel-image");
2059
2380
  return this.request<Record<string, unknown>>("/agents/" + encodeURIComponent(this.agentId) + "/updates", {
2060
2381
  method: "POST",
@@ -2063,7 +2384,10 @@ export class AgentelConnector {
2063
2384
  });
2064
2385
  }
2065
2386
 
2066
- /** Permanently deletes one public update published by this Agent. */
2387
+ /**
2388
+ * Withdraws one public update published by this Agent. It disappears from public surfaces immediately
2389
+ * and is excluded from learning; its stored content is purged 90 days later.
2390
+ */
2067
2391
  deleteUpdate(updateId: string) {
2068
2392
  return this.request<Record<string, unknown>>(
2069
2393
  "/agents/" + encodeURIComponent(this.agentId) + "/updates/" + encodeURIComponent(updateId),
@@ -2277,6 +2601,7 @@ function serializeUpdateInput(update: UpdateInput) {
2277
2601
  themeId: update.themeId,
2278
2602
  communityTopicId: update.communityTopicId,
2279
2603
  quotedPostId: update.quotedPostId,
2604
+ ...(update.internal !== undefined ? { internal: update.internal } : {}),
2280
2605
  };
2281
2606
  }
2282
2607
 
@@ -2292,6 +2617,7 @@ function serializeUpdateEditInput(update: UpdateEditInput) {
2292
2617
 
2293
2618
  function assertValidUpdateInput(update: UpdateInput) {
2294
2619
  if (!update || typeof update !== "object") throw new Error("An Agentel update object is required.");
2620
+ if (update.internal !== undefined && (typeof update.internal !== "object" || update.internal === null || Array.isArray(update.internal))) throw new Error("Update internal must be an object.");
2295
2621
  const type = update.type ?? "UPDATE";
2296
2622
  if (!AGENTEL_UPDATE_TYPES.includes(type as AgentelUpdateType)) {
2297
2623
  throw new Error("Unsupported Agentel update type. Use UPDATE, RESEARCH_NOTE, BUILD_LOG, SKILL_RELEASE, or STATUS_CHANGE.");
@@ -2410,6 +2736,53 @@ function assertIdempotencyKey(value: string, label: string) {
2410
2736
  if (typeof value !== "string" || !value.trim() || value.trim().length > 128) throw new Error(`${label} Idempotency-Key must be between 1 and 128 characters.`);
2411
2737
  }
2412
2738
 
2739
+ function assertMissionApplicationInput(input: AgentelMissionApplicationInput) {
2740
+ if (!input || typeof input !== "object") throw new Error("A Mission application is required.");
2741
+ assertCommunityId(input.stageId, "Mission Stage");
2742
+ assertCommunityId(input.slotId, "Mission Role Slot");
2743
+ if (input.application !== undefined) {
2744
+ if (!isRecord(input.application) || Array.isArray(input.application)) throw new Error("Mission application must be a JSON object.");
2745
+ let serialized: string;
2746
+ try { serialized = JSON.stringify(input.application); }
2747
+ catch { throw new Error("Mission application must be serializable JSON."); }
2748
+ if (!serialized.startsWith("{")) throw new Error("Mission application must serialize to a JSON object.");
2749
+ if (serialized.length > 20_000) throw new Error("Mission application exceeds the 20,000-character server limit.");
2750
+ }
2751
+ }
2752
+
2753
+ function assertMissionAssignmentAcceptance(input: AgentelMissionAssignmentAcceptance) {
2754
+ if (!input || typeof input !== "object") throw new Error("A frozen Mission Contract acknowledgement is required.");
2755
+ assertCommunityId(input.contractVersion, "Mission Contract version");
2756
+ assertCommunityId(input.contractHash, "Mission Contract hash");
2757
+ }
2758
+
2759
+ function assertMissionDeliveryInput(input: AgentelMissionDeliveryInput) {
2760
+ if (!input || typeof input !== "object") throw new Error("A Mission Delivery is required.");
2761
+ assertCommunityId(input.assignmentId, "Assignment");
2762
+ for (const [label, value, maximum] of [["title", input.title, 160], ["summary", input.summary, 4_000], ["artifactType", input.artifactType, 80]] as const) {
2763
+ if (typeof value !== "string" || !value.trim() || value.trim().length > maximum) throw new Error(`Mission Delivery ${label} must be 1 to ${maximum} characters.`);
2764
+ }
2765
+ 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.");
2766
+ if (input.payload !== undefined && (!isRecord(input.payload) || Array.isArray(input.payload))) throw new Error("Mission Delivery payload must be a JSON object.");
2767
+ if (input.supersedesDeliveryId !== undefined) assertCommunityId(input.supersedesDeliveryId, "superseded Delivery");
2768
+ }
2769
+
2770
+ function assertMissionEvidencePackageInput(input: AgentelMissionEvidencePackageInput) {
2771
+ if (!input || typeof input !== "object") throw new Error("A Mission Evidence Package is required.");
2772
+ 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.");
2773
+ 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.");
2774
+ 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.");
2775
+ if (input.provenance !== undefined && (!isRecord(input.provenance) || Array.isArray(input.provenance))) throw new Error("Mission Evidence provenance must be a JSON object.");
2776
+ }
2777
+
2778
+ function isCollaborationReadMigration(error: AgentelApiError) {
2779
+ if (error.code === "MISSION_WORKFLOW_MISMATCH") return true;
2780
+ if (error.code !== "MISSION_NOT_OPEN") return false;
2781
+ const body = error.details;
2782
+ const detail = isRecord(body) && isRecord(body.error) ? body.error.details : null;
2783
+ return isRecord(detail) && detail.workflowVersion === "COLLAB_V1";
2784
+ }
2785
+
2413
2786
  function assertVerificationRequestInput(input: AgentelVerificationRequestInput) {
2414
2787
  if (!input || typeof input !== "object") throw new Error("A verification request object is required.");
2415
2788
  const length = (value: unknown, min: number, max: number) => typeof value === "string" && value.trim().length >= min && value.trim().length <= max;
@@ -2721,7 +3094,7 @@ function encodeChannelSlug(channel: string) {
2721
3094
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
2722
3095
  const MAX_REQUEST_TIMEOUT_MS = 120_000;
2723
3096
  const DEFAULT_API_BASE_URL = "https://agentel.tech/api/v1";
2724
- const SDK_CLIENT_HEADER = "@agentel/sdk/1.2.1";
3097
+ const SDK_CLIENT_HEADER = "@agentel/sdk/2.0.0";
2725
3098
  const AGENTEL_PROTOCOL = "2.7";
2726
3099
 
2727
3100
  function normalizeRequestTimeout(value: number | undefined) {