@on-mission/sdk 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FileRef, StagingProvenance, ToolCallInput } from '@mission/models';
2
- export { FileRef, FileRefStore, MAX_STAGING_UPLOAD_BYTES, StagingProvenance, Tool, ToolCallContext, ToolCallEnvelope, ToolCallInput, ToolFunction, ToolFunctionPermission, ToolKind, fileRefSchema } from '@mission/models';
2
+ export { AuthoredToolResultTransport, FileRef, FileRefStore, IdentityBearingKey, MAX_STAGING_UPLOAD_BYTES, StagingProvenance, TOOL_RESULT_TRANSPORT_MAX_BYTES, Tool, ToolCallContext, ToolCallEnvelope, ToolCallInput, ToolFunction, ToolFunctionPermission, ToolKind, ToolResultEnvelope, ToolResultTransport, fileRefSchema, toolResult } from '@mission/models';
3
3
  import { createTRPCProxyClient } from '@trpc/client';
4
4
 
5
5
  /**
@@ -153,6 +153,69 @@ type ConfigModule = {
153
153
  get: <T = Record<string, unknown>>(defaults?: Partial<T>) => Promise<T>;
154
154
  };
155
155
 
156
+ /**
157
+ * Content-identity test kit (MIS-649).
158
+ *
159
+ * Mission content-addresses tool results: the platform serializes a result,
160
+ * sha256s the bytes, and that digest becomes the sandbox filename, the GCS key,
161
+ * and the dedup key. A tool that echoes a volatile value INSIDE its result
162
+ * payload — a pagination cursor, a request id, a fetch timestamp — makes two
163
+ * byte-identical result SETS hash differently. Dedup silently fails and the
164
+ * model is handed N artifacts where it should have seen one.
165
+ *
166
+ * `toolResult(content, transport)` is the fix: the platform hashes `content`
167
+ * alone and excludes `transport`. But a tool only gets that property if it puts
168
+ * the volatile fields in the right half, and NOTHING about the return type can
169
+ * tell it apart from getting it wrong — both compile.
170
+ *
171
+ * `assertContentIdentityStable` is the check that can. It runs a tool's real
172
+ * invocations and asserts the two properties that matter:
173
+ *
174
+ * 1. Two calls that returned the SAME records with a DIFFERENT volatile value
175
+ * produce the SAME content identity.
176
+ * 2. A call that returned DIFFERENT records produces a DIFFERENT one.
177
+ *
178
+ * Property 2 is not decoration — without it, a tool that dumps its whole payload
179
+ * into `transport` (or returns a constant) passes property 1 perfectly and has
180
+ * destroyed the very identity the store depends on.
181
+ *
182
+ * It is framework-agnostic on purpose: it throws a plain `Error` on failure, so
183
+ * it works under vitest, node:test, or a plain script, and importing it never
184
+ * drags a test runner into a skill's runtime bundle.
185
+ */
186
+ /**
187
+ * The content identity the PLATFORM would compute for a tool result: sha256 over
188
+ * the serialized bytes of the hashed subject that `selectHashedContent` picks.
189
+ *
190
+ * BOTH halves are imported, not reimplemented. The selection
191
+ * (`selectHashedContent`) and the serialization (`serializeForIdentity`) are the
192
+ * platform's own definitions, so this function cannot report an address the
193
+ * platform will not produce. A local re-implementation of either half is exactly
194
+ * the defect this contract exists to eliminate, one level up.
195
+ */
196
+ declare const contentIdentity: (result: unknown) => string;
197
+ declare const assertContentIdentityContractLoaded: () => void;
198
+ type ContentIdentityStableInput = Readonly<{
199
+ /**
200
+ * Two invocations that returned THE SAME RECORDS but a different volatile
201
+ * value (page 1 fetched twice with a fresh cursor, the same query re-run with a
202
+ * new request id). Their content identity must match.
203
+ */
204
+ sameRecordsDifferentCursor: readonly [
205
+ () => Promise<unknown> | unknown,
206
+ () => Promise<unknown> | unknown
207
+ ];
208
+ /**
209
+ * An invocation that returned DIFFERENT records. Its content identity must
210
+ * differ from the pair above — the guard against a tool that has collapsed all
211
+ * of its results onto one address.
212
+ */
213
+ differentRecords: () => Promise<unknown> | unknown;
214
+ /** Optional label used in failure messages (e.g. the tool name). */
215
+ label?: string;
216
+ }>;
217
+ declare const assertContentIdentityStable: (input: ContentIdentityStableInput) => Promise<void>;
218
+
156
219
  /**
157
220
  * Debug Logging — Local Development
158
221
  *
@@ -888,4 +951,4 @@ type WebhookResult = {
888
951
  response?: WebhookResponse;
889
952
  };
890
953
 
891
- export { type AgentMessage, type ApiClient, type AttachmentLimits, type AuthCredentials, type AuthModule, type ConfigModule, EmailAttachments, type EventHandler, type EventHandlerRegistry, FileTransferTimeoutError, type FilesModule, type IngressHandler, type IngressModule, type IngressRequest, type IngressResponse, type IngressStreamEvents, type IngressUrl, type LogModule, type MimeBodyParts, type MissionSDK, type MissionSDKOptions, type OAuthCredentials, type RedeemedAttachment, type SendIntentClaimOutcome, type SendIntentCompletion, type SendIntentRecord, type SendIntentStatus, type SendIntentsModule, type SendMessageId, type SendMessageIdInput, type SkillContext, type SkillEvent, SkillToolHttpError, type ToolHandler, type ToolsModule, type WebhookRequest, type WebhookResponse, type WebhookResult, clearDebugLog, createMissionSDK, debugLog };
954
+ export { type AgentMessage, type ApiClient, type AttachmentLimits, type AuthCredentials, type AuthModule, type ConfigModule, type ContentIdentityStableInput, EmailAttachments, type EventHandler, type EventHandlerRegistry, FileTransferTimeoutError, type FilesModule, type IngressHandler, type IngressModule, type IngressRequest, type IngressResponse, type IngressStreamEvents, type IngressUrl, type LogModule, type MimeBodyParts, type MissionSDK, type MissionSDKOptions, type OAuthCredentials, type RedeemedAttachment, type SendIntentClaimOutcome, type SendIntentCompletion, type SendIntentRecord, type SendIntentStatus, type SendIntentsModule, type SendMessageId, type SendMessageIdInput, type SkillContext, type SkillEvent, SkillToolHttpError, type ToolHandler, type ToolsModule, type WebhookRequest, type WebhookResponse, type WebhookResult, assertContentIdentityContractLoaded, assertContentIdentityStable, clearDebugLog, contentIdentity, createMissionSDK, debugLog };
package/dist/index.js CHANGED
@@ -14256,7 +14256,6 @@ var hostFsOpSchema = external_exports.union([
14256
14256
  external_exports.literal("move"),
14257
14257
  external_exports.literal("delete")
14258
14258
  ]);
14259
- var wireGrantsSchema = external_exports.array(external_exports.unknown());
14260
14259
  var workingFileSchema = external_exports.strictObject({
14261
14260
  path: external_exports.string().min(1),
14262
14261
  name: external_exports.string().min(1),
@@ -14269,7 +14268,6 @@ var invokeFrameSchema = external_exports.object({
14269
14268
  particleId: particleIdSchema,
14270
14269
  action: external_exports.string().min(1),
14271
14270
  input: external_exports.unknown(),
14272
- grants: wireGrantsSchema,
14273
14271
  workingFile: workingFileSchema.optional()
14274
14272
  });
14275
14273
  var resultOutcomeSchema = external_exports.union([
@@ -14344,16 +14342,10 @@ var childToSupervisorFrameSchema = external_exports.discriminatedUnion("type", [
14344
14342
  heartbeatFrameSchema
14345
14343
  ]);
14346
14344
 
14345
+ // ../models/src/skill-runtime/fs-root.ts
14346
+ var rootSchema = external_exports.enum(["documents", "downloads", "desktop"]);
14347
+
14347
14348
  // ../models/src/skill-runtime/manifest-verbs.ts
14348
- var capabilityKindSchema = external_exports.union([
14349
- external_exports.literal("fs:read:scoped"),
14350
- external_exports.literal("fs:write:scoped"),
14351
- external_exports.literal("fs:read:host"),
14352
- external_exports.literal("fs:write:host"),
14353
- external_exports.literal("proc:read"),
14354
- external_exports.literal("net:egress"),
14355
- external_exports.literal("exec:subprocess")
14356
- ]);
14357
14349
  var manifestVerbPermissionSchema = external_exports.union([
14358
14350
  external_exports.literal("enabled"),
14359
14351
  external_exports.literal("disabled"),
@@ -14378,22 +14370,14 @@ var manifestVerbSchema = external_exports.object({
14378
14370
  action: external_exports.string().min(1),
14379
14371
  inputSchema: jsonObjectSchema,
14380
14372
  prompt: manifestVerbPromptSchema,
14381
- capability: capabilityKindSchema,
14382
14373
  permissions: manifestVerbPermissionFlagsSchema
14383
- });
14374
+ }).strict();
14384
14375
  var manifestDeviceBlockSchema = external_exports.object({
14385
14376
  eligibility: external_exports.object({
14386
14377
  os: external_exports.array(external_exports.string()),
14387
14378
  arch: external_exports.array(external_exports.string())
14388
- }),
14389
- roots: external_exports.array(
14390
- external_exports.union([
14391
- external_exports.literal("documents"),
14392
- external_exports.literal("downloads"),
14393
- external_exports.literal("desktop")
14394
- ])
14395
- )
14396
- });
14379
+ })
14380
+ }).strict();
14397
14381
  var manifestSandboxBlockSchema = external_exports.object({
14398
14382
  start: external_exports.string().min(1)
14399
14383
  });
@@ -14420,6 +14404,162 @@ var MAX = Number.MAX_SAFE_INTEGER;
14420
14404
  var MAX_BIGINT = BigInt(MAX);
14421
14405
 
14422
14406
  // ../models/src/tools.ts
14407
+ var TOOL_RESULT_TRANSPORT_MAX_BYTES = 4096;
14408
+ var utf8ByteLength = (value) => new TextEncoder().encode(value).length;
14409
+ var toolResultTransportSchema = external_exports.record(
14410
+ external_exports.string(),
14411
+ // `.optional()` (MIS-649 follow-up): an EXPLICITLY-undefined value is
14412
+ // accepted and stripped, so `{ cursor: maybeUndefined }` — the natural
14413
+ // spelling when a cursor may be absent — behaves exactly like an absent
14414
+ // key. Rejecting it made the whole result `malformed`, which on the inline
14415
+ // path handed the model the raw `{"kind":"tool-result-envelope",…}` wrapper
14416
+ // and lost dedup: a punishing outcome for the obvious spelling.
14417
+ external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.null()]).optional()
14418
+ ).refine(
14419
+ (value) => utf8ByteLength(JSON.stringify(value)) <= TOOL_RESULT_TRANSPORT_MAX_BYTES,
14420
+ {
14421
+ message: `transport exceeds ${TOOL_RESULT_TRANSPORT_MAX_BYTES} bytes when JSON-serialized`
14422
+ }
14423
+ );
14424
+ var toolResultEnvelopeTagSchema = external_exports.object({
14425
+ kind: external_exports.literal("tool-result-envelope")
14426
+ });
14427
+ var toolResultEnvelopeSchema = external_exports.object({
14428
+ kind: external_exports.literal("tool-result-envelope"),
14429
+ /**
14430
+ * `z.unknown()` is INTENTIONAL here and is not an R2 violation waiting to be
14431
+ * fixed. R2 bans `z.unknown()` in a schema that defines a contract with the
14432
+ * outside world — because the field then reaches downstream code untyped.
14433
+ * This contract deliberately ENDS at the envelope: the platform's whole job
14434
+ * is to serialize and hash `content` without knowing its shape, and the
14435
+ * moment the platform can describe that shape it has acquired knowledge of a
14436
+ * particular tool. There is no downstream code that reads a field off
14437
+ * `content`; modeling "the real shape" here is not merely unnecessary, it is
14438
+ * the exact coupling this type exists to prevent. Presence (not shape) is
14439
+ * what the platform requires, and the refinement below enforces it.
14440
+ */
14441
+ content: external_exports.unknown(),
14442
+ /** transport holds only values that would differ between two calls that returned
14443
+ * the same result — echoed cursors, request ids, fetch timestamps. If two results
14444
+ * differing only in this field are genuinely *different results*, it belongs in
14445
+ * `content` (`complete`, `capReached`, `truncated`, `total`, `exitCode` all belong
14446
+ * in `content`). Governs identity, not representation.
14447
+ *
14448
+ * TAINT-BEARING FIELDS BELONG IN `content`, NEVER IN `transport`. Downstream
14449
+ * taint admission parses `taintSources` off the tool result AFTER
14450
+ * `wrapToolResult` has run (see
14451
+ * `apps/temporal/src/workflows/agent-conversation/activities/conversation-history-taint.ts`),
14452
+ * and by then `transport` has been split off the hashed bytes and rides on the
14453
+ * reference instead. A tool that moved `taintSources` into `transport` would
14454
+ * lose its taint SILENTLY — no schema error, no log, just an untainted turn.
14455
+ * `transport` is for values the platform is contractually indifferent to;
14456
+ * taint is the opposite of indifferent. */
14457
+ transport: toolResultTransportSchema.optional()
14458
+ }).strict().refine((value) => value.content !== void 0, {
14459
+ message: "tool-result envelope `content` is missing or undefined"
14460
+ });
14461
+ var toolResult = (content, transport) => transport === void 0 ? { kind: "tool-result-envelope", content } : { kind: "tool-result-envelope", content, transport };
14462
+ var definedTransport = (transport) => {
14463
+ if (transport === void 0) return void 0;
14464
+ const entries = Object.entries(transport).filter(
14465
+ ([, value]) => value !== void 0
14466
+ );
14467
+ return entries.length === 0 ? void 0 : Object.fromEntries(entries);
14468
+ };
14469
+ var selectHashedContent = (input) => {
14470
+ const probe = () => {
14471
+ const claimsEnvelope = toolResultEnvelopeTagSchema.safeParse(input.result);
14472
+ if (!claimsEnvelope.success) {
14473
+ return {
14474
+ classification: "absent",
14475
+ hashed: input.offloadText ?? input.result
14476
+ };
14477
+ }
14478
+ const parsed = toolResultEnvelopeSchema.safeParse(input.result);
14479
+ if (!parsed.success) {
14480
+ return {
14481
+ classification: "malformed",
14482
+ hashed: input.offloadText ?? input.result,
14483
+ reason: parsed.error.issues.map((issue2) => `${issue2.path.join(".") || "<root>"}: ${issue2.message}`).join("; ")
14484
+ };
14485
+ }
14486
+ const transport = definedTransport(parsed.data.transport);
14487
+ return {
14488
+ classification: "valid",
14489
+ hashed: input.offloadText ?? parsed.data.content,
14490
+ transport
14491
+ };
14492
+ };
14493
+ try {
14494
+ return probe();
14495
+ } catch (err) {
14496
+ return {
14497
+ classification: "malformed",
14498
+ hashed: input.offloadText ?? input.result,
14499
+ reason: `envelope probe threw while reading the result: ${err instanceof Error ? err.message : String(err)}`
14500
+ };
14501
+ }
14502
+ };
14503
+ var serializeForIdentity = (value) => {
14504
+ if (value instanceof Uint8Array) {
14505
+ return {
14506
+ bytes: value,
14507
+ contentType: "application/octet-stream",
14508
+ ext: "bin",
14509
+ previewSource: `[binary ${value.length}b]`
14510
+ };
14511
+ }
14512
+ if (typeof value === "string") {
14513
+ const isJsonString = (s) => {
14514
+ try {
14515
+ JSON.parse(s);
14516
+ return true;
14517
+ } catch {
14518
+ return false;
14519
+ }
14520
+ };
14521
+ const isJson = isJsonString(value);
14522
+ return {
14523
+ bytes: new TextEncoder().encode(value),
14524
+ contentType: isJson ? "application/json" : "text/plain",
14525
+ ext: isJson ? "json" : "txt",
14526
+ previewSource: value
14527
+ };
14528
+ }
14529
+ const safeJson = (v) => {
14530
+ try {
14531
+ return JSON.stringify(
14532
+ v ?? null,
14533
+ (_, x) => typeof x === "bigint" ? x.toString() : x
14534
+ );
14535
+ } catch {
14536
+ return null;
14537
+ }
14538
+ };
14539
+ const json2 = safeJson(value);
14540
+ if (typeof json2 === "string") {
14541
+ return {
14542
+ bytes: new TextEncoder().encode(json2),
14543
+ contentType: "application/json",
14544
+ ext: "json",
14545
+ previewSource: json2
14546
+ };
14547
+ }
14548
+ const safeText = (v) => {
14549
+ try {
14550
+ return String(v);
14551
+ } catch {
14552
+ return `[unserializable ${typeof v}]`;
14553
+ }
14554
+ };
14555
+ const text = safeText(value);
14556
+ return {
14557
+ bytes: new TextEncoder().encode(text),
14558
+ contentType: "text/plain",
14559
+ ext: "txt",
14560
+ previewSource: text
14561
+ };
14562
+ };
14423
14563
  var DEVICE_WRITE_TOOL_NAME_LIST = [
14424
14564
  "file_write",
14425
14565
  "file_update",
@@ -14441,7 +14581,8 @@ var DEVICE_DELIVERABLE_TOOL_NAME_LIST = [
14441
14581
  var DEVICE_READ_TOOL_NAME_LIST = [
14442
14582
  "file_read",
14443
14583
  "file_list",
14444
- "file_find",
14584
+ // search_files — ripgrep-powered find-and-count; a read/extract verb.
14585
+ "search_files",
14445
14586
  "excel_read",
14446
14587
  "word_read",
14447
14588
  "pdf_read",
@@ -14489,8 +14630,83 @@ var PLATFORM_READ_OR_GATHER_TOOL_NAMES = new Set(
14489
14630
  PLATFORM_READ_OR_GATHER_TOOL_NAME_LIST
14490
14631
  );
14491
14632
 
14633
+ // src/content-identity.ts
14634
+ import { createHash } from "crypto";
14635
+ var contentIdentity = (result) => {
14636
+ assertNotWireWrapped(result, "contentIdentity");
14637
+ const { hashed } = selectHashedContent({ result });
14638
+ return createHash("sha256").update(serializeForIdentity(hashed).bytes).digest("hex");
14639
+ };
14640
+ var PROBE_CONTENT = { records: [{ id: "probe-1" }] };
14641
+ var PROBE_OTHER_CONTENT = { records: [{ id: "probe-2" }] };
14642
+ var staleBuildAdvice = "The loaded @on-mission/sdk build does not implement the content-identity envelope contract (MIS-649). This is almost certainly a STALE BUILD: `@mission/models` is source-only and is bundled into `packages/sdk/dist`, and the turbo `test` task does not depend on `build`, so editing `packages/models/src/tools.ts` leaves the dist that tests actually import untouched. Rebuild it \u2014 `yarn turbo build --filter=@on-mission/sdk` \u2014 and run again. If a fresh build still fails this check, the contract itself is broken and every content-identity assertion below it is meaningless.";
14643
+ var WIRE_WRAPPER_KEY = "result";
14644
+ var looksLikeUndecodedWireResponse = (value) => {
14645
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
14646
+ return false;
14647
+ }
14648
+ const keys = Object.keys(value);
14649
+ return keys.length === 1 && keys[0] === WIRE_WRAPPER_KEY;
14650
+ };
14651
+ var assertNotWireWrapped = (value, where) => {
14652
+ if (!looksLikeUndecodedWireResponse(value)) return;
14653
+ throw new Error(
14654
+ `${where}: the value handed to the content-identity module has exactly one key, \`result\` \u2014 which is the shape \`@on-mission/sdk\` puts on the WIRE (\`POST /_mission/tools/:toolName\` answers \`{ result: <handler return> }\`), not the shape a handler returns. The likely cause is an UN-DECODED SDK wire response: something passed \`await response.json()\` straight into identity instead of the platform's decoded result (\`parseSkillToolResponse\`). Hashing the wrapper is the MIS-649 production defect \u2014 the envelope tag probe tests the wrapper, classification is \`absent\`, and a volatile cursor stays in the hashed bytes. Pass the handler's own return value. (If your handler genuinely returns \`{ result: \u2026 }\` and nothing else, that shape is indistinguishable from the wrapper \u2014 give the payload a name.)`
14655
+ );
14656
+ };
14657
+ var assertContentIdentityContractLoaded = () => {
14658
+ const cursorA = contentIdentity(toolResult(PROBE_CONTENT, { offset: "A" }));
14659
+ const cursorB = contentIdentity(
14660
+ toolResult(PROBE_CONTENT, { offset: "B-TOTALLY-DIFFERENT" })
14661
+ );
14662
+ if (cursorA !== cursorB) {
14663
+ throw new Error(
14664
+ `content-identity contract NOT PRESENT in the loaded build: an identical \`content\` under two different \`transport\` values hashed differently (${cursorA} vs ${cursorB}); transport is supposed to be excluded from the digest entirely. ${staleBuildAdvice}`
14665
+ );
14666
+ }
14667
+ const other = contentIdentity(
14668
+ toolResult(PROBE_OTHER_CONTENT, { offset: "A" })
14669
+ );
14670
+ if (other === cursorA) {
14671
+ throw new Error(
14672
+ `content-identity contract NOT PRESENT in the loaded build: two DIFFERENT \`content\` values hashed to the same digest (${other}); the digest is not reading \`content\` at all. ${staleBuildAdvice}`
14673
+ );
14674
+ }
14675
+ const armed = (() => {
14676
+ try {
14677
+ contentIdentity({ result: PROBE_CONTENT });
14678
+ return false;
14679
+ } catch {
14680
+ return true;
14681
+ }
14682
+ })();
14683
+ if (!armed) {
14684
+ throw new Error(
14685
+ `content-identity contract NOT PRESENT in the loaded build: the wire-wrapper tripwire did not fire for \`{ result: \u2026 }\`, so an un-decoded SDK wire response would be hashed as if it were a tool result \u2014 the MIS-649 defect, undetected. ${staleBuildAdvice}`
14686
+ );
14687
+ }
14688
+ };
14689
+ var assertContentIdentityStable = async (input) => {
14690
+ assertContentIdentityContractLoaded();
14691
+ const where = input.label === void 0 ? "" : ` [${input.label}]`;
14692
+ const [firstCall, secondCall] = input.sameRecordsDifferentCursor;
14693
+ const first = contentIdentity(await firstCall());
14694
+ const second = contentIdentity(await secondCall());
14695
+ if (first !== second) {
14696
+ throw new Error(
14697
+ `content identity is NOT stable${where}: two calls returning the same records hashed differently (${first} vs ${second}). A volatile value \u2014 a cursor, a request id, a timestamp \u2014 is inside \`content\`. Move it to \`transport\`.`
14698
+ );
14699
+ }
14700
+ const other = contentIdentity(await input.differentRecords());
14701
+ if (other === first) {
14702
+ throw new Error(
14703
+ `content identity is NOT discriminating${where}: a call returning different records hashed to the same value (${other}). Records that distinguish one result from another belong in \`content\`, not \`transport\`.`
14704
+ );
14705
+ }
14706
+ };
14707
+
14492
14708
  // src/email-attachments.ts
14493
- import { createHash, randomBytes } from "crypto";
14709
+ import { createHash as createHash2, randomBytes } from "crypto";
14494
14710
  var GMAIL_ATTACHMENT_LIMITS = {
14495
14711
  provider: "Gmail",
14496
14712
  maxTotalRawBytes: 18 * 1024 * 1024
@@ -14642,7 +14858,7 @@ var assembleMimeMessage = (input, attachments) => {
14642
14858
  return [...headers, "", parts.join(CRLF)].join(CRLF);
14643
14859
  };
14644
14860
  var sendMessageId = (input) => {
14645
- const attachmentDigest = input.attachments.map((a) => createHash("sha256").update(a.bytes).digest("hex")).join(",");
14861
+ const attachmentDigest = input.attachments.map((a) => createHash2("sha256").update(a.bytes).digest("hex")).join(",");
14646
14862
  const idSeed = [
14647
14863
  input.workspaceId,
14648
14864
  [...input.to].sort().join(","),
@@ -14653,7 +14869,7 @@ var sendMessageId = (input) => {
14653
14869
  input.html ?? "",
14654
14870
  attachmentDigest
14655
14871
  ].join("|");
14656
- const hash2 = createHash("sha256").update(idSeed).digest("hex");
14872
+ const hash2 = createHash2("sha256").update(idSeed).digest("hex");
14657
14873
  return { hash: hash2, messageId: `<${hash2}@mission.send>` };
14658
14874
  };
14659
14875
  var EmailAttachments = {
@@ -14670,7 +14886,7 @@ var EmailAttachments = {
14670
14886
  };
14671
14887
 
14672
14888
  // src/files.ts
14673
- import { createHash as createHash2 } from "crypto";
14889
+ import { createHash as createHash3 } from "crypto";
14674
14890
  var FileTransferTimeoutError = class extends Error {
14675
14891
  constructor(operation) {
14676
14892
  super(`File transfer timed out: ${operation}`);
@@ -14736,7 +14952,7 @@ function createFilesModule(api2) {
14736
14952
  };
14737
14953
  const stageInboundBytes = async (input) => {
14738
14954
  const buffer2 = Buffer.isBuffer(input.bytes) ? input.bytes : Buffer.from(input.bytes);
14739
- const sha256 = createHash2("sha256").update(buffer2).digest("hex");
14955
+ const sha256 = createHash3("sha256").update(buffer2).digest("hex");
14740
14956
  const contentType = normalizeContentType(input.contentType);
14741
14957
  const filename = sanitizeStagedName(input.filename);
14742
14958
  const { uploadUrl, contentLengthRange, key } = await api2.trpc.skill.requestStagingUpload.mutate({
@@ -15836,9 +16052,14 @@ export {
15836
16052
  FileTransferTimeoutError,
15837
16053
  MAX_STAGING_UPLOAD_BYTES,
15838
16054
  SkillToolHttpError,
16055
+ TOOL_RESULT_TRANSPORT_MAX_BYTES,
16056
+ assertContentIdentityContractLoaded,
16057
+ assertContentIdentityStable,
15839
16058
  clearDebugLog,
16059
+ contentIdentity,
15840
16060
  createMissionSDK,
15841
16061
  debugLog,
15842
- fileRefSchema
16062
+ fileRefSchema,
16063
+ toolResult
15843
16064
  };
15844
16065
  //# sourceMappingURL=index.js.map