{"_id":"@kontourai/thread","_rev":"5-8cfd944f166c93452a520bd5968534d9","name":"@kontourai/thread","dist-tags":{"latest":"0.5.0"},"versions":{"0.1.0":{"name":"@kontourai/thread","version":"0.1.0","keywords":["ai","conversation","thread","schema","llm","agent"],"license":"Apache-2.0","_id":"@kontourai/thread@0.1.0","maintainers":[{"name":"briananderson1222","email":"brian.anderson1222@gmail.com"}],"homepage":"https://github.com/kontourai/thread#readme","bugs":{"url":"https://github.com/kontourai/thread/issues"},"dist":{"shasum":"9e5b3ba50761f7d7d21c1c2fa7379a682b291003","tarball":"https://registry.npmjs.org/@kontourai/thread/-/thread-0.1.0.tgz","fileCount":11,"integrity":"sha512-EIzNhaF5y9Th40fpR9cF9tPNsUSuGU9gTlmLhoHRua0g/5PZ9URxcX1QAakJmQV/g5WMaFceeKV5RZBm6vMHcQ==","signatures":[{"sig":"MEUCIQD7Z+OmBXmupcJP8oimu6iTkn5Xq7mgfwKNAVGRgk+HRAIgGYrJbkggV6i+V9eA4Qcmn0NAdlcH0qfd6t7sgE+D2Tk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":125808},"type":"module","engines":{"node":">=22"},"exports":{".":{"types":"./dist/src/index.d.ts","default":"./dist/src/index.js"}},"gitHead":"7da3fffd6e1aaaf002bffd2b608810c28a997cb5","scripts":{"test":"npm run build && vitest run","build":"rm -rf dist && tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"briananderson1222","email":"brian.anderson1222@gmail.com"},"repository":{"url":"git+https://github.com/kontourai/thread.git","type":"git","directory":"packages/thread"},"_npmVersion":"11.17.0","description":"Canonical AI conversation schema — a portable message format for agent threads","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.23.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.8.0"},"_npmOperationalInternal":{"tmp":"tmp/thread_0.1.0_1786224766784_0.6300262169566588","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@kontourai/thread","version":"0.2.0","keywords":["ai","conversation","thread","schema","llm","agent"],"license":"Apache-2.0","_id":"@kontourai/thread@0.2.0","maintainers":[{"name":"briananderson1222","email":"brian.anderson1222@gmail.com"}],"homepage":"https://github.com/kontourai/thread#readme","bugs":{"url":"https://github.com/kontourai/thread/issues"},"dist":{"shasum":"1f6c835b6da7a15f637e67c753f6092d7c958168","tarball":"https://registry.npmjs.org/@kontourai/thread/-/thread-0.2.0.tgz","fileCount":15,"integrity":"sha512-8Ol0O81/RSsN8BJ2DNPD/RKf131RbtRyfjT01Hbq9Dbt2rZ47tmE14jydP5q80/PSo8H95cihJoBusxHfXHFjQ==","signatures":[{"sig":"MEYCIQD+6rHXDn4vfltkZ8WC6tTBFhlZdI2w9ji11cKbcKhQqAIhAPaUKMAtAFR7yunuAaNVKsVvxvTEw2ozT3g0Po30Xwvt","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@kontourai%2fthread@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":133802},"type":"module","engines":{"node":">=22"},"exports":{".":{"types":"./dist/src/index.d.ts","default":"./dist/src/index.js"}},"gitHead":"19de4863619e648ad9518302f961d2574222138b","scripts":{"test":"npm run build && vitest run","build":"rm -rf dist && tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:98997a14-510b-450b-a705-3c5a0ec0ca0f"}},"repository":{"url":"git+https://github.com/kontourai/thread.git","type":"git","directory":"packages/thread"},"_npmVersion":"11.16.0","description":"Canonical AI conversation schema — a portable message format for agent threads","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^3.23.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.8.0"},"_npmOperationalInternal":{"tmp":"tmp/thread_0.2.0_1786290029723_0.5692119785142427","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@kontourai/thread","version":"0.3.0","keywords":["ai","conversation","thread","schema","llm","agent"],"license":"Apache-2.0","_id":"@kontourai/thread@0.3.0","maintainers":[{"name":"briananderson1222","email":"brian.anderson1222@gmail.com"}],"homepage":"https://github.com/kontourai/thread#readme","bugs":{"url":"https://github.com/kontourai/thread/issues"},"dist":{"shasum":"996984a35400d955975c738bfa3f61b9a1960a01","tarball":"https://registry.npmjs.org/@kontourai/thread/-/thread-0.3.0.tgz","fileCount":15,"integrity":"sha512-Q8gHtMtV5sGgOgl1O55AvX3lNJwVQU/yxRfe15O1591DxPCt7nQe9Htw2MJWKj1rIf6nh+6SqbpL30o+zot5PA==","signatures":[{"sig":"MEYCIQCWuldTHoxL4VPBc3Q/idiGIREivZ4uox0fUqP99vHYbAIhAL9XqjX4z84FiBsAIAOBjSN8hezLbfeLB3rAHlHUTb+P","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@kontourai%2fthread@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":72642},"type":"module","engines":{"node":">=22"},"exports":{".":{"types":"./dist/src/index.d.ts","default":"./dist/src/index.js"}},"gitHead":"bc0a8a2f6f90328162815f805ca9012fe18b7ba9","scripts":{"test":"npm run build && vitest run","build":"rm -rf dist && tsc","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:98997a14-510b-450b-a705-3c5a0ec0ca0f"}},"repository":{"url":"git+https://github.com/kontourai/thread.git","type":"git","directory":"packages/thread"},"_npmVersion":"11.16.0","description":"Canonical AI conversation schema — a portable message format for agent threads","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^4.4.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^7.0.2"},"_npmOperationalInternal":{"tmp":"tmp/thread_0.3.0_1786294368268_0.1300723972436304","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@kontourai/thread","version":"0.4.0","keywords":["ai","conversation","thread","schema","llm","agent"],"license":"Apache-2.0","_id":"@kontourai/thread@0.4.0","maintainers":[{"name":"briananderson1222","email":"brian.anderson1222@gmail.com"}],"homepage":"https://github.com/kontourai/thread#readme","bugs":{"url":"https://github.com/kontourai/thread/issues"},"dist":{"shasum":"c04cf5b00cbb648fb435f7fc3ea8417f76f2f8c3","tarball":"https://registry.npmjs.org/@kontourai/thread/-/thread-0.4.0.tgz","fileCount":15,"integrity":"sha512-ojKvVIfUpUgLfaDGYgnyB13cGkotD3dVL5x6viPR4EcPVTb/dxHK6cTXqd+9iC2IBAyLZOX8e68wPtngP5SysA==","signatures":[{"sig":"MEQCIGcio8nxwWBPcvDF/V6vr7HK5+wuoZh13dR0H6aSQJ97AiAlpIfYlncRF//NpUHxkpGa4jcPpTtrettKjfHYoZB95w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@kontourai%2fthread@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":130713},"type":"module","engines":{"node":">=22"},"exports":{".":{"types":"./dist/src/index.d.ts","default":"./dist/src/index.js"}},"gitHead":"ff828ed3d4a5c5ed131effb8197f87f3548d1d5b","scripts":{"test":"npm run build && vitest run && npm run test:pack","build":"rm -rf dist && tsc","test:pack":"node tests/pack-smoke.mjs","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:98997a14-510b-450b-a705-3c5a0ec0ca0f"}},"repository":{"url":"git+https://github.com/kontourai/thread.git","type":"git","directory":"packages/thread"},"_npmVersion":"11.17.0","description":"Canonical AI conversation schema — a portable message format for agent threads","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^4.4.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^7.0.2"},"_npmOperationalInternal":{"tmp":"tmp/thread_0.4.0_1787634163347_0.09431562100486723","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@kontourai/thread","version":"0.5.0","description":"Canonical AI conversation schema — a portable message format for agent threads","license":"Apache-2.0","type":"module","exports":{".":{"types":"./dist/src/index.d.ts","default":"./dist/src/index.js"},"./answer":{"types":"./dist/src/answer.d.ts","default":"./dist/src/answer.js"}},"scripts":{"build":"rm -rf dist && tsc","typecheck":"tsc -p tsconfig.typecheck.json","test":"npm run build && vitest run && npm run test:pack && npm run test:tree-shaking","test:pack":"node tests/pack-smoke.mjs","test:tree-shaking":"node tests/tree-shaking-smoke.mjs"},"keywords":["ai","conversation","thread","schema","llm","agent"],"repository":{"type":"git","url":"git+https://github.com/kontourai/thread.git","directory":"packages/thread"},"engines":{"node":">=22"},"dependencies":{"zod":"^4.4.3"},"devDependencies":{"esbuild":"^0.27.4","typescript":"^7.0.2","vitest":"^4.1.10"},"publishConfig":{"access":"public"},"gitHead":"06173f50204e76643d04fc735fccbb1348491008","_id":"@kontourai/thread@0.5.0","bugs":{"url":"https://github.com/kontourai/thread/issues"},"homepage":"https://github.com/kontourai/thread#readme","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-MhHKngKoKAWIEkvANx4YMrdYgBH5pRAGU3ocMiKRW1qcw6eluUyDB659vEgxFFcYy+FUXUrWb2EGt/7cI0WgIg==","shasum":"f682a4cede8c929a55976f66757917e6639249d2","tarball":"https://registry.npmjs.org/@kontourai/thread/-/thread-0.5.0.tgz","fileCount":19,"unpackedSize":172668,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@kontourai%2fthread@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGivGVewK4WL33QmA7SfosWnpdq2uH6bIqjcdioIiiPAAiEAlcBEioX4mnd7jrccv5uW744lIm/7ajaGlIcc9I1PYE0="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:98997a14-510b-450b-a705-3c5a0ec0ca0f"}},"directories":{},"maintainers":[{"name":"briananderson1222","email":"brian.anderson1222@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/thread_0.5.0_1787679524805_0.4480264354070016"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-08T21:32:46.650Z","modified":"2026-08-25T17:38:45.247Z","0.1.0":"2026-08-08T21:32:46.944Z","0.2.0":"2026-08-09T15:40:29.872Z","0.3.0":"2026-08-09T16:52:48.407Z","0.4.0":"2026-08-25T05:02:43.481Z","0.5.0":"2026-08-25T17:38:44.938Z"},"bugs":{"url":"https://github.com/kontourai/thread/issues"},"license":"Apache-2.0","homepage":"https://github.com/kontourai/thread#readme","keywords":["ai","conversation","thread","schema","llm","agent"],"repository":{"type":"git","url":"git+https://github.com/kontourai/thread.git","directory":"packages/thread"},"description":"Canonical AI conversation schema — a portable message format for agent threads","maintainers":[{"name":"briananderson1222","email":"brian.anderson1222@gmail.com"}],"readme":"# @kontourai/thread\n\nCanonical Zod schema for AI conversations — messages, tool calls and results,\nreasoning, attachments, token usage — plus type guards, factories, and\nvalidated JSON serialization.\n\nSchema 1.2.0 also supports owner-issued tool-result identity. Legacy imported\nresults remain valid, but only results carrying both `resultId` and\n`terminalStatus` can be safely retained for later dereference. Use\n`projectToolResult` when passing one to another consumer: it produces a\nbounded inert view (32 parts, 64 KiB of UTF-8 text, and 72 KiB of projected\nstring data) and intentionally omits payload bytes, URLs, annotations, and\nstructured result data. Any dropped text or projected metadata is declared by\nthe mandatory omission counters on the projection.\n\n## Assistant-answer references\n\n`ThreadAnswerRef` is an exact, portable identity for one owner-issued assistant\nmessage: `{ authority: \"@kontourai/thread\", schemaVersion: \"1.2.0\",\nkind: \"assistant-message\", standing: \"observed\", threadId, messageId }`. It is separate from the\nserialized Thread/Message schema, so this additive API does **not** change the\nThread schema version or require Ferry adapters to invent source identities.\n\nThe producer creates `createObservedMessageIdentity(threadId, messageId)` only\nwhen it byte-observed the owner-issued tuple, then passes that fact to\n`createThreadAnswerRef(identity)`. Thread never infers observation from an ID's\nshape, a correlation, an adapter position, or an ID that happens to match.\nSynthetic, adapter-fallback, and unknown identity facts cannot create or parse\nas a `ThreadAnswerRef`.\n\nIDs are opaque Unicode strings: they may look like paths, URLs, or percent\nencodings. Thread never normalizes or dereferences them, so `%2f` and `%2F`\nremain different IDs.\n\nUse the total `projectAssistantAnswer(ref, unknownMessage)` at a\nconsumer boundary. It returns a typed unavailable reason for bad input, a\nnon-assistant message, an identity mismatch, corrupt text, or an answer with\nno visible text; it does not throw a Zod error for those inputs.\n\nThe available form retains ordered, inert text parts only. It never exposes\nreasoning, tool calls or arguments, structured results, image/file payloads,\nannotations, attachment paths or bytes, or source/private metadata. Markdown,\nHTML, and URLs remain strings. The contract caps visible text at 32 parts,\n16 KiB per part, 64 KiB total text, and 72 KiB across the ref plus content.\n`truncated`, `omittedParts`, and `omittedTextBytes` describe capacity loss among\nvisible text candidates only; intentionally excluded reasoning/tools are not\nmisreported as truncation. Source metadata has an explicit zero-byte budget.\n\n```ts\nimport { createObservedMessageIdentity, createThreadAnswerRef, projectAssistantAnswer } from \"@kontourai/thread/answer\";\n\nconst observed = createObservedMessageIdentity(\"source-thread-42\", \"source-message-7\");\nconst ref = createThreadAnswerRef(observed);\nconst outcome = projectAssistantAnswer(ref, importedMessage);\nif (outcome.state === \"available\") {\n  // Render outcome.answer.content as plain inert text, not executable markup.\n  console.log(outcome.answer.content);\n}\n```\n\n```ts\nimport { threadFromJson, getToolCalls, isAssistantMessage } from \"@kontourai/thread\";\n\nconst thread = threadFromJson(json); // validates, throws on schema violations\nfor (const msg of thread.messages) {\n  if (isAssistantMessage(msg)) console.log(getToolCalls(msg));\n}\n```\n\n```ts\nimport { createToolResult, projectToolResult } from \"@kontourai/thread\";\n\nconst result = createToolResult({\n  resultId: \"provider-result-42\", // supplied by the result owner\n  terminalStatus: \"cancelled\",\n  toolCallId: \"provider-call-9\",\n  name: \"shell\",\n  content: [{ type: \"text\", text: \"cancelled by user\" }],\n});\n\nconst projection = projectToolResult(result);\n// { state: \"available\", result: { resultId, terminalStatus, content, ... } }\n```\n\nUse [`@kontourai/ferry`](https://www.npmjs.com/package/@kontourai/ferry) to\nimport transcripts from Claude Code, Codex, OpenCode, or ChatGPT exports into\nthis format, and to export back out to provider API formats.\n\nLicense: Apache-2.0\n","readmeFilename":"README.md"}