Skip to content

Puter.js types and docs drift audit - 2026-06-15 #3261

@reynaldichernando

Description

@reynaldichernando

Deep drift audit of the puter.js SDK comparing implementation vs TypeScript types vs documentation. Each finding is reproducible against commit 900b0d7aa6e5af730883b4823da438e1862082a1 (branch claude/exciting-lamport-y8p7nv).

Legend: 🟡 types (impl/docs have it, types don't/wrong) · 🔵 docs (impl/types have it, docs don't/wrong) · 🔴 both · 🐛 impl-bug (code fix, type/doc advertises something impl ignores OR phantom method) · 🆕/🗑 manifest-drift.

Step 0 — manifest tripwire: Disk file set matches the Expected manifest exactly. No 🆕/🗑 manifest-drift (no added/removed modules, types, FS ops, networking, UI components, or doc pages).


AI

Function Item Issue Tag impl ref
chat option provider Impl reads userParams.providerrequestParams.provider, but ChatOptions has no provider field and chat.md never documents it. 🔴 both AI.js:800-802
chat option driver Typed but undocumented in chat.md. 🔵 docs AI.js:812-814
chat option image_config Documented + forwarded by impl, missing from ChatOptions. 🟡 types AI.js:817
chat option text_verbosity alias Docs advertise text/text_verbosity, impl only reads text and a separate verbosity key — text_verbosity never read. 🐛 impl-bug AI.js:817
chat option verbosity Impl reads + typed; chat.md only mentions text_verbosity. 🔵 docs AI.js:817
chat option response Forwarded + typed; not documented. 🔵 docs AI.js:817
txt2img option service Txt2ImgOptions.service declared in types but impl never reads it (phantom). 🐛 impl-bug AI.js:907-913
txt2img model aliases nano-banana/nano-banana-pro Impl rewrites these to Gemini model ids; not documented or typed as accepted values. 🔴 both AI.js:898-905
txt2img option driver Read + typed; undocumented. 🔵 docs AI.js:907-910
txt2img option input_images Documented (array) but Txt2ImgOptions only has input_image. 🟡 types AI.js (passthrough)
txt2vid option driver Read + typed; undocumented. 🔵 docs AI.js:986-990
txt2vid option duration alias Mapped to seconds, typed; undocumented. 🔵 docs AI.js:977-979
txt2vid options input_reference (String)/last_frame Docs (Veo) document String input_reference + last_frame; types declare only input_reference?: File, no last_frame. 🟡 types AI.js:996
speech2speech aliases voiceId/modelId/outputFormat/voiceSettings/fileFormat/removeBackgroundNoise/optimizeStreamingLatency/enableLogging (+ snake voice_id/model_id) Impl normalizes 9 camelCase→snake aliases; none in types or docs (one docs example even uses removeBackgroundNoise). 🔴 both AI.js:416-429
speech2txt stream: true rejection Docs say stream is rejected when true; impl has no guard, passes it through. 🐛 impl-bug AI.js:584
speech2txt provider aliases grok/x-ai Mapped to xai-speech2txt; undocumented. 🔵 docs AI.js:575-580
speech2txt string-shorthand return Docs say shorthand source returns a string; impl returns string only when response_format==='text'. 🐛 impl-bug AI.js:587-591
txt2speech engine→provider inference Impl infers provider from engine; undocumented, engine typed as plain string. 🔵 docs AI.js:268-282
txt2speech alias response_formatoutput_format (elevenlabs) Undocumented mapping. 🔵 docs AI.js:311-313
txt2speech MAX_INPUT_SIZE Impl hard-caps 3000 chars for all providers; xAI docs claim "15,000 characters". 🐛 impl-bug AI.js:206,353
txt2speech provider aliases (eleven/11labs/google/grok/polly/aws…) normalizeTTSProvider accepts many aliases; docs list only canonical names. 🔵 docs AI.js:4-15
txt2speech.listEngines method declaration Exists in impl + docs; entirely absent from ai.d.ts. 🟡 types AI.js:601-640
txt2speech.listVoices method declaration Exists in impl + docs; entirely absent from ai.d.ts. 🟡 types AI.js:647-689
img2txt nested { source: Blob } shape Supported by impl; undocumented + untyped. 🔴 both AI.js:158-161
img2txt 10 MB data-URI limit Enforced by impl; undocumented. 🔵 docs AI.js:109,165
ChatResponse field choices Interface has choices?; chatresponse.md doesn't list it. 🔵 docs ai.d.ts:34
ChatResponse message.images/thoughtSignature Documented in chat.md (Gemini image gen); absent from chatresponse.md + ChatMessage. 🔴 both chat.md:211-226
ChatResponseChunk field reasoning Interface has it; chatresponsechunk.md only documents text. 🔵 docs ai.d.ts:39
ChatResponseChunk streaming fields type/image/tool_use Used in chat.md streaming examples; absent from interface + chatresponsechunk.md. 🔴 both chat.md:255-272
ToolCall field type chat.md tool-call results include type:"function"; absent from ToolCall + toolcall.md. 🔴 both ai.d.ts:9-12
Speech2TxtResult fields duration/words xAI example reads them; absent from interface + speech2txtresult.md. 🔴 both speech2txt.md:128-133

Apps

Function Item Issue Tag impl ref
App (object) users() method Impl attaches + documented; absent from App interface. 🟡 types Apps.js:24
App (object) getUsers() method Impl attaches + documented; absent from App interface. 🟡 types Apps.js:20
checkName method Impl + types have it; no doc page / not in Apps.md. 🔵 docs Apps.js:206
getDeveloperProfile method Impl + types have it; no doc page / not in Apps.md. 🔵 docs Apps.js:232

Auth

Function Item Issue Tag impl ref
whoami method Impl + types have it; no doc page (only getUser documented). 🔵 docs Auth.js:211
getGlobalUsage method Impl has it; missing from types AND docs. 🔴 both Auth.js:338
getUser callback overload Impl accepts positional (success, error); types only declare options-object form. 🟡 types Auth.js:187-195
User (object) feature_flags / hasDevAccountAccess / otp Typed; not in user.md. 🔵 docs auth.d.ts:8-11

Perms

The entire documented + implemented request* family (16 methods) is absent from perms.d.ts — TS users get zero typing for the primary documented Perms surface.

Function Item Issue Tag impl ref
request, requestEmail, requestRead{Desktop,Documents,Pictures,Videos,Apps,Subdomains}, requestWrite{Desktop,Documents,Pictures,Videos}, requestManage{Apps,Subdomains} method Impl + docs have all; all missing from types. 🟡 types Perms.js:133-316
requestReadAppRootDir / requestWriteAppRootDir method Impl only; missing from types AND docs. 🔴 both Perms.js:333,346
grant*/revoke*/group mgmt methods Present in impl + types; none documented. 🔵 docs Perms.js:37-118
#requestAppRootDir access hardcoded Fetch body hardcodes access:'read', so requestWriteAppRootDir requests read access. 🐛 impl-bug Perms.js:361
#requestAppRootDir undefined var app_or_uuid References app_or_uuid (never defined; should be app_uid) → ReferenceError on error path. 🐛 impl-bug Perms.js:367
#requestAppRootDir typo Error message 'must be a strinkg'. 🐛 impl-bug Perms.js:355

FileSystem (FS)

Function Item Issue Tag impl ref
readdirSubdomains method Public method; absent from types AND docs. 🔴 both readdirSubdomains.js:11
revokeReadURL method Public method; absent from types AND docs. 🔴 both revokeReadUrl.js:10
sign method Typed; no FS/sign.md. 🔵 docs sign.js:15
space namespace space.md example calls puter.space(); method is puter.fs.space() (no top-level alias). 🔵 docs space.js:3
getReadURL expiresIn units Default is string '24h' (typed correctly); docs say expiresIn (Number) = milliseconds. 🔵 docs getReadUrl.js:4,32
copy newMetadata/createMissingParents/excludeSocketID Read + typed; undocumented. 🔵 docs copy.js:17-19
copy dedupeName dropped in positional form copy(src,dst,{dedupeName}) never extracts dedupeName/dedupe_name from args[2] → silently dropped. 🐛 impl-bug copy.js:12-23,56
move dedupeName phantom Docs list dedupeName; move.js never reads/sends dedupe_name. 🐛 impl-bug move.js:48-66
move newName/newMetadata/excludeSocketID Read + typed; undocumented. 🔵 docs move.js:17-20
mkdir rename/recursive aliases, shortcutTo Read + typed; undocumented in mkdir.md. 🔵 docs mkdir.js:51-54
delete descendants_only snake alias Read by impl; only descendantsOnly typed/documented. 🔴 both deleteFSEntry.js:55
read cache option Read by impl; missing from types AND docs. 🔴 both read.js:46
readdir no_subdomains Sent by impl; types declare only no_thumbs/no_assocs; docs mention none. 🔴 both readdir.js:59,128
readdir consistency Supported + typed; undocumented. 🔵 docs readdir.js:29
stat returnWorkers alias Read by impl (alias of returnSubdomains); missing from types AND docs. 🔴 both stat.js:54,126
upload generateThumbnails/thumbnailGenerator/thumbnail Read by impl; missing from types; docs list only overwrite/dedupeName/createMissingParents. 🔴 both upload.js:571-573
upload progress events (init/start/progress/abort) Fired by impl + typed; undocumented. 🔵 docs upload.js:405,632,667,757
upload dedupeName default Impl defaults true when not overwriting; docs say false. 🔵 docs upload.js:735
FSItem is_dir/parent_id/parent_uid/writable fsitem.md documents these; impl exposes isDirectory and has none of the others (types correct). 🔵 docs FSItem.js:17
FSItem readURL/writeURL/metadataURL Impl + types expose; fsitem.md documents none. 🔵 docs FSItem.js:5-7
FSItem.move boolean overwrite ignored FSItem.move(dest, overwrite, new_name) forwards boolean to fs.move which reads args[2]?.overwrite (expects object) → ignored. 🐛 impl-bug FSItem.js:89; move.js:13
FSItem.copy auto_rename/overwrite ignored Same positional/object mismatch with fs.copy. 🐛 impl-bug FSItem.js:93; copy.js:12-23

KV

Function Item Issue Tag impl ref
MAX_VALUE_SIZE constant value Impl is 399*1024 (~399KB); set.md states 400 KB. 🔵 docs KV.js:36
MAX_VALUE_SIZE/MAX_KEY_SIZE units Docs say "in bytes"; impl compares .length (char/element count). 🔵 docs KV.js:208,36
get missing-key return Impl + types resolve undefined; get.md says null. 🔵 docs KV.js:284,288
set batch overload Impl supports set([{key,value,expireAt}…]) / set({items:[…]}); no batch overload in types or docs. 🔴 both KV.js:124-155
set optConfig arg / null expireAt set.md never documents optConfig; impl also accepts expireAt===null (typed as number). 🔵 docs / 🟡 types KV.js:166,174-176
add default value Impl defaults value to 1; add.md never states the default. 🔵 docs KV.js:386
add/incr/decr/del/remove/update/expire/expireAt/list optConfig Accepted by impl + typed; undocumented across these methods. 🔵 docs KV.js (per method)
flush clear alias Impl + types expose clear; never documented. 🔵 docs KV.js:676

Hosting

Function Item Issue Tag impl ref
list workers filter Impl filters out workers.puter.* subdomains; undocumented. 🔵 docs Hosting.js:44
create root_dir not absolutized in object form Object form create({subdomain,root_dir}) skips getAbsolutePathForApp that the positional dirPath form applies. 🐛 impl-bug Hosting.js:76-77
create/update/get/delete *.puter.(site|com) stripping Impl strips full domain to bare subdomain; undocumented. 🔵 docs Hosting.js:90,113,129
update (example) broken sample Cleanup references undefined updatedSite in Hosting.md + Hosting/update.md. 🔵 docs Hosting.md:147

Workers

Function Item Issue Tag impl ref
create 3rd param appName Impl accepts an options object with sandbox boolean; types declare only appName?: string. 🟡 types Workers.js:21-24
create 3rd param Docs syntax lists only (workerName, filePath) — entire 3rd param undocumented. 🔵 docs Workers.js:10,37
getLoggingHandle method Impl + types have it; completely undocumented. 🔵 docs Workers.js:137
getLoggingHandle start/cancel on returned stream Typed handle omits start/cancel (only close typed). 🟡 types Workers.js:146-174
delete dead new Error new Error("Worker doesn't exist") constructed without throw. 🐛 impl-bug Workers.js:121

Peer

Function Item Issue Tag impl ref
PuterPeerConnectionErrorEvent error payload type Impl sets .error to an Error object; types declare error: string (doc example reads event.error?.message). 🔴 both Peer.js:211,306
PuterPeerServer message phantom method Types declare public message(data); impl has only private #message. 🐛 impl-bug Peer.js:104
PuterPeerConnection.setRemoteDescription return Impl async (Promise); types declare void. 🟡 types Peer.js:326
PuterPeerConnection.addIceCandidate return Impl async (Promise); types declare void. 🟡 types Peer.js:330

Networking

Function Item Issue Tag impl ref
PSocket/PTLSSocket 'drain' event Declared in types + SocketEvent, but never emitted by impl. 🟡 types PSocket.js:16; networking.d.ts:6
PSocket on('error') payload type Impl emits an Error object; types + docs say string. 🔴 both PSocket.js:52
PTLSSocket on('error') payload type Impl emits raw Error objects; types + docs say string. 🔴 both PTLS.js:67,86
PTLSSocket on tls* event overloads Impl accepts tlsopen/tlsdata/tlsclose (docs tell users to use them); PTLSSocket adds no on overloads — TLS usage untyped. 🟡 types PTLS.js:92-98
PTLSSocket on bare event remapping Impl silently remaps open/data/close to tls*; undocumented. 🔵 docs PTLS.js:92-98
puter.net.generateWispV1URL method Public on puter.net (impl + type); documented nowhere. 🔵 docs index.js:627
PSocket.write ArrayBuffer branch else if (data.resize) calls data.write(...) (not a method on ArrayBuffer) → throws despite docs/types accepting ArrayBuffer. 🐛 impl-bug PSocket.js:74-75
PWispHandler._continue missing streamID Called with no arg from PSocket → undefined.queue throws; breaks backpressure drain. 🐛 impl-bug PWispHandler.js:31,51-52
PWispHandler setup reconnect timer setTimeout(setup(), 1000) invokes immediately + passes undefined; reconnect broken. 🐛 impl-bug PWispHandler.js:23

UI

Function Item Issue Tag impl ref
exit phantom method on UI Types declare UI.exit(), but exit lives on the Puter class — puter.ui.exit() doesn't exist. 🐛 impl-bug index.js:1040
exit wrong namespace in UI.md UI.md lists puter.ui.exit(); correct is puter.exit(). 🔵 docs UI.md:36
on / events connection event Impl emits 'connection' with {conn,accept,reject}; absent from on() types AND docs. 🔴 both UI.js:251,546-571
showColorPicker defaultValue/default aliases Impl fallback accepts both; absent from types + docs. 🔴 both UI.js:884
showFontPicker default alias Impl fallback accepts it; absent from types + docs. 🔴 both UI.js:866
showSaveFilePicker 3rd param type Impl (content, suggestedName, type) selects url/move/copy; omitted from types AND docs. 🔴 both UI.js:898,906-910
showDirectoryPicker accept option IPC reads options.accept; only multiple typed/documented. 🔴 both IPC.js:567-570
setMenubar/menu item ops disableMenuItem/enableMenuItem In impl; absent from types AND docs (sibling setMenuItem* are typed but undocumented). 🔴 both UI.js:1113-1119
socialShare return type Impl returns a Promise; types declare void, docs have no Return section. 🔴 both UI.js:728-732
socialShare default left/top Docs say default 0; impl defaults to window top-left. 🔵 docs IPC.js:334-343
prompt cancel sentinel (standalone) Standalone PuterPrompt resolves false on cancel; docs/types say null. 🐛 impl-bug PuterPrompt.js:187,197,205
prompt options.defaultValue IPC reads it + typed; prompt.md omits the options arg. 🔵 docs IPC.js:253
alert return type Impl default button returns boolean true; types declare Promise<string>. 🟡 types PuterAlert.js:166
launchApp file_paths/items/pseudonym/callback/app_name alias/#(as) syntax Read + typed; launchApp.md documents only name+args. 🔵 docs UI.js:1299-1320
parentApp gui return Returns undefined (not null) in gui env. 🟡 types UI.js:264-266,1357
requestUpgrade doc page In impl + types; no doc page. 🔵 docs UI.js:892
notify type/duration Standalone component renders type/duration; missing from NotificationOptions + notify.md (GUI path ignores). 🔵 docs / 🟡 types PuterNotification.js:208,256
toggleWindow/instancesOpen/connectToInstance/requestEmailConfirmation/openDevPaymentsAccount methods In impl; absent from types + docs (mostly internal; toggleWindow plausibly public). 🟡 types UI.js:692,716,722,1086,1342

Utils

Function Item Issue Tag impl ref
puter.on / puter.off methods Public event API (gate puter.auth.reauth_required); absent from puter.d.ts + docs. 🔴 both index.js:972,979
puter.auth.reauth_required event Emitted {reason,auth_id}; no type surface, undocumented. 🔴 both index.js:846,950-957
print option escapeHTML Supported by impl + typed; docs document only code. 🔵 docs index.js:1258,1267
env enum completeness Impl/types also have web-worker/service-worker/nodejs; docs list only app/web/gui. 🔵 docs index.js:357-389
getUser positional callbacks Impl accepts (success, error); types only model options-object form. 🟡 types index.js:1217-1229
quiet property puter.quiet toggle (referenced in console); missing from puter.d.ts. 🟡 types index.js:173,1400
exit doc page Public method; not in Utils.md. 🔵 docs index.js:1040
appName doc page Typed property; not in Utils.md. 🔵 docs index.js:445

Drivers

Function Item Issue Tag impl ref
call 2-arg overload Impl supports call(iface, parameters) (method defaults to iface); types declare only 3/4-arg. 🟡 types Drivers.js:262-265
Drivers constructor signature Impl ctor is constructor(puter); types declare constructor(context:{authToken?;APIOrigin;appID?}). 🟡 types Drivers.js:135

OS

Function Item Issue Tag impl ref
user / version positional callbacks Impl accepts variadic (success, error); types model only options-object form. 🟡 types OS.js:41-53,70-83

(a) Highest-impact shortlist

  1. Perms types are essentially empty for the public surface — all 16 documented request* methods are missing from perms.d.ts. (🟡)
  2. requestWriteAppRootDir is broken — hardcodes access:'read' and the error path throws a ReferenceError (app_or_uuid undefined). (🐛)
  3. puter.ui.exit() is a phantom — typed on UI but only exists on the Puter class; runtime call fails. (🐛)
  4. UI 'connection' event is emitted by impl but absent from both on() types and docs. (🔴)
  5. Networking error payload is an Error object everywhere but typed/documented as string; PTLSSocket has no typed on overloads for its tls* events. (🔴/🟡)
  6. Peer error payload typed as string but is an Error; PuterPeerServer.message is a phantom public method. (🔴/🐛)
  7. puter.on/off + auth.reauth_required event — real public reauth API with zero type/doc coverage. (🔴)
  8. AI alias/param drift — chat provider undocumented+untyped; 9 speech2speech camelCase aliases in neither types nor docs; streaming ChatResponseChunk shape (type/image/tool_use) and ToolCall.type used in docs examples but missing from interfaces + Object docs.
  9. KV MAX_VALUE_SIZE docs say "400 KB" vs impl 399*1024; get missing-key returns undefined not the documented null; batch set overload undocumented + untyped.
  10. FS positional-vs-object arg bugscopy(src,dst,{dedupeName}), FSItem.move/FSItem.copy boolean positionals silently dropped; move docs advertise a dedupeName it never sends.

(b) 🐛 impl-bug bucket (code fixes, not doc/type edits)

Family Location Bug
AI AI.js:817 chat text_verbosity advertised but never read
AI AI.js:907-913 txt2img service typed but never read (phantom)
AI AI.js:584 speech2txt stream:true documented as rejected but passed through
AI AI.js:587-591 speech2txt shorthand documented to return string; only does when response_format==='text'
AI AI.js:206,353 txt2speech xAI "15,000 char" limit contradicted by hard 3000-char cap
Perms Perms.js:361 requestWriteAppRootDir hardcodes access:'read'
Perms Perms.js:367 undefined app_or_uuid → ReferenceError
Perms Perms.js:355 typo "strinkg" in error message
FS copy.js:12-23,56 copy(src,dst,{dedupeName}) drops dedupeName in positional form
FS move.js:48-66 docs advertise dedupeName move never sends
FS FSItem.js:89; move.js:13 FSItem.move boolean overwrite ignored (object expected)
FS FSItem.js:93; copy.js:12-23 FSItem.copy auto_rename/overwrite ignored
Hosting Hosting.js:76-77 object-form create({root_dir}) skips getAbsolutePathForApp
Workers Workers.js:121 dead new Error("Worker doesn't exist") never thrown
Peer Peer.js:104 PuterPeerServer.message phantom (only private #message)
Networking PSocket.js:74-75 ArrayBuffer branch calls data.write (not an ArrayBuffer method)
Networking PWispHandler.js:31,51-52 _continue() called with no streamID → throws
Networking PWispHandler.js:23 setTimeout(setup(), 1000) invokes immediately; reconnect broken
UI index.js:1040 puter.ui.exit() phantom (exit is on Puter class)
UI PuterPrompt.js:187,197,205 standalone prompt cancel resolves false, not documented null

(c) 🆕/🗑 manifest-drift

None. Disk file set matches the Expected manifest exactly across modules, FS operations, networking, UI components, types, and docs.

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions