Skip to content

Puter.js types and docs drift audit - 2026-06-22 #3280

Description

@reynaldichernando

Audit scope: full deep audit of the puter.js SDK for TypeScript drift and documentation drift against the implementation.
Pinned commit: 24d700673cd8c18bd9d04d6a52c04172b67984b0 (branch claude/exciting-lamport-bsrxgf)
Sources of truth: impl src/puter-js/src/modules/ + src/puter-js/src/index.js (+ src/gui/src/IPC.js for the UI family) · types src/puter-js/types/ · docs src/docs/src/

Tag legend

  • 🟡 types — impl/docs have it, types don't (or types are wrong)
  • 🔵 docs — impl/types have it, docs don't (or docs are wrong)
  • 🔴 both — missing/wrong in types and docs
  • 🐛 impl-bug — type/doc advertises a param the impl ignores, OR types declare a phantom method (code fix, not a doc/type edit)
  • 🆕/🗑 manifest-drift — file/method added or removed vs the expected manifest

🌟 Highest-impact shortlist (cross-family)

  1. 🐛 FSItem.copy / FSItem.move / FSItem.mkdir silently drop their params — these methods pass positional booleans (overwrite, autoRename, newName) into ops that expect an options object; in copy, overwrite is even consumed as the success callback. Documented params don't work. (FSItem.js:89-119)
  2. 🐛 Networking is broken in three places: PSocket.write ArrayBuffer branch calls data.write(...) on an ArrayBuffer (throws); PWispHandler._continue() is called with no streamID (flow-control resume dead); PWispHandler reconnect does setTimeout(setup(), 1000) (fires immediately, schedules undefined). (PSocket.js:74, PWispHandler.js:31,22)
  3. 🐛 UI methods with no IPC handler / hung promises: socialShare returns a Promise the GUI never resolves (and throws if options omitted); toggleWindow and requestUpgrade post messages no handler reads. (IPC.js:325, UI.js:1086,892)
  4. 🔴 Whole public UI methods missing from types AND docs: requestPermission, instancesOpen, connectToInstance, disableMenuItem, enableMenuItem. (UI.js)
  5. 🔴 isDir vs isDirectory — the runtime FSItem property is isDirectory; both fs-item.d.ts and fsitem.md advertise isDir, which never exists on the instance.
  6. 🔴 KV.MAX_VALUE_SIZE / value limit is documented as "400 KB" everywhere but impl is 399 * 1024 (≈399 KB). A value between 399–400 KB is rejected contrary to docs/types.
  7. 🔴 fs.revokeReadURL missing from types — wired public method (index.js:44), no .d.ts declaration, no doc page; its counterpart getReadURL is fully documented.
  8. 🐛 Perms.#requestAppRootDir hardcodes access:'read'requestWriteAppRootDir can never request write; both requestReadAppRootDir/requestWriteAppRootDir are also untyped + undocumented.
  9. 🔴 Auth.getGlobalUsage exists in impl only — absent from types and docs.
  10. 🟡 Drivers.call missing its 2-arg overload (call(iface, params)), the documented convenience form; current typing mis-resolves it as a type error.

AI

Function Item Issue Tag impl ref
chat error stream chunk Docs/examples use part.type==='error' + part.message; ChatResponseChunk.type lacks error and has no message 🔴 chat.md:227
chat image stream chunk Docs show part.image on stream chunks; ChatResponseChunk has no image field 🔴 chat.md:376
chat ChatMessage.images Declared required in interface; impl/docs treat it as optional response-only — breaks every constructed message 🟡 ai.d.ts:14
chat file content block Docs describe {type:"file", puter_path}; not modeled in AIMessageContent 🟡 chat.md:60
chat web_search tool Docs allow {type:"web_search"}; Tool interface requires function 🟡 chat.md:155
chat provider / driver options Read by impl, typed, but absent from chat.md options list 🔵 AI.js:800,812
txt2img service option Declared in Txt2ImgOptions but impl never reads it (phantom) 🐛 ai.d.ts:180
txt2img nano-banana/nano-banana-pro models Impl maps these aliases; not in types, not listed as usable model values 🔴 AI.js:900
txt2img / txt2vid driver option Selects service in impl, typed, but undocumented in option tables 🔵 AI.js:909,988
txt2vid durationseconds alias Impl maps durationseconds; alias undocumented 🔵 AI.js:979
speech2speech camelCase aliases Impl accepts voiceId/modelId/outputFormat/voiceSettings/fileFormat/removeBackgroundNoise/optimizeStreamingLatency/enableLogging; Speech2SpeechOptions declares only snake_case 🟡 AI.js:416
speech2speech camelCase aliases Example uses removeBackgroundNoise; not in docs options list 🔵 AI.js:421
speech2txt grok/x-ai provider aliases Impl routes them to xai; undocumented 🔵 AI.js:577
txt2speech engine-as-provider inference engine:'openai'|'elevenlabs'|'gemini'|'xai' infers provider; undocumented 🔵 AI.js:268
txt2speech response_formatoutput_format (elevenlabs) Impl maps alias; not documented for elevenlabs 🔵 AI.js:311

🐛 AI impl-bug: Txt2ImgOptions.service is a phantom option (declared, never read).
🆕 AI manifest-drift: Objects/ttsengine.md + Objects/ttsvoice.md are real new files (back TTSEngine/TTSVoice, referenced from listEngines/listVoices) not in the expected AI-objects manifest.


FileSystem (FS)

Function Item Issue Tag impl ref
FSItem object isDir Runtime prop is isDirectory; types + fsitem.md advertise isDir (never set) 🔴 FSItem.js:17
FSItem object readURL/writeURL/metadataURL/uid/uuid Public props omitted from fsitem.md 🔵 FSItem.js:5
FSItem.move overwrite/newName Passed as positional booleans into move op which expects an options object at args[2] → dropped 🐛 FSItem.js:89
FSItem.copy autoRename/overwrite args[2] is a bool not options; overwrite consumed as success callback → both broken 🐛 FSItem.js:93
FSItem.mkdir auto_rename Accepted in signature then ignored 🐛 FSItem.js:110
fs.copy dedupeName/dedupe_name Not mapped in positional-args branch (only object form reaches the wire) 🐛 copy.js:11
fs.copy createMissingParents Read but never sent in xhr body 🐛 copy.js:17
fs.move dedupeName move.md documents it; /move never reads or sends any dedupe field (phantom doc option) 🔵 move.md:34
fs.move socket id Positional id stored as original_client_socket_id, body sends excludeSocketID → positional dropped 🐛 move.js:20
fs.read cache option Read by impl; absent from ReadOptions and docs 🔴 read.js:46
fs.readdir no_subdomains Read by impl; missing from ReaddirOptions type (and docs) 🟡 readdir.js:60
fs.readdir no_thumbs/no_assocs/consistency Read/typed but undocumented; consistency default 'strong' undocumented 🔵 readdir.js:57
fs.stat returnWorkers Alias of returnSubdomains; not in StatOptions, not in docs 🔴 stat.js:54
fs.stat consistency Read + typed; omitted from doc 🔵 stat.js:31
fs.upload generateThumbnails/thumbnailGenerator/thumbnail Read by impl; not in UploadOptions, not in docs 🔴 upload.js:571
fs.upload name/shortcutTo/appUID/strict/createFileParent/createMissingAncestors/parsedDataTransferItems Read + typed; undocumented 🔵 upload.js:433-737
fs.upload progress events init/start/progress/abort fired + typed; docs mention none 🔵 upload.js:405
fs.write createMissingAncestors + progress callbacks Forwarded to upload + typed; docs omit 🔵 write.js:63
fs.sign doc page In impl + types, no FS/ doc page 🔵 sign.js:15
fs.revokeReadURL existence Wired public method; missing from types AND docs 🔴 revokeReadUrl.js:10
fs.readdirSubdomains existence Wired; missing from types + docs (likely internal batch helper) 🟡 readdirSubdomains.js:11
FS.md index function list Omits getReadURL, sign, space, revokeReadURL (pages exist for some) 🔵 FS.md:299

🐛 FS impl-bugs: FSItem.move/copy/mkdir param drop; fs.copy dedupeName/createMissingParents dropped; fs.move positional socket-id dropped.


KV

Function Item Issue Tag impl ref
MAX_VALUE_SIZE constant value Impl 399*1024 (408576 B); types JSDoc + set.md say "400 KB" — wrong 🔴 KV.js:36
set value limit text set.md + types say "400 KB"; impl enforces 399*1024 🔴 KV.js:208
MAX_VALUE_SIZE doc page MAX_VALUE_SIZE.md states no numeric value (should be 408576 B / ≈399 KB) 🔵 KV.js:36
MAX_KEY_SIZE doc page MAX_KEY_SIZE.md states no numeric value (impl = 1024) 🔵 KV.js:35
get optConfig param Supported in impl + types; get.md shows only get(key) 🔵 KV.js:266
del optConfig param Supported in impl + types; del.md omits it 🔵 KV.js:549
flush optConfig param Supported in impl + types; flush.md says "None" 🔵 KV.js:643
clear existence Alias of flush in impl + types; missing from KV.md function list, no KV/clear.md 🆕 KV.js:676

No KV impl-bugs. (Constants add/incr/decr default-to-1 verified correct across all three.)


UI (impl = UI.js + IPC.js)

Function Item Issue Tag impl ref
disableMenuItem existence Impl + IPC handler; missing from types AND docs 🔴 UI.js:1113
enableMenuItem existence Impl + IPC handler; missing from types AND docs 🔴 UI.js:1117
requestPermission existence Impl + IPC handler; missing from types AND docs 🔴 UI.js:1103
instancesOpen existence Impl + IPC (getInstancesOpen); missing from types + docs 🔴 UI.js:722
connectToInstance existence Impl returns AppConnection; missing from types + docs 🔴 UI.js:1342
requestEmailConfirmation existence Impl + IPC; missing from types + docs (arguably internal) 🔴 UI.js:692
openDevPaymentsAccount existence Impl only; missing from types + docs 🔴 UI.js:716
setMenuItemIcon / IconActive / Checked doc page In types + impl + IPC; no doc pages 🔵 UI.js:1121-1129
socialShare hung Promise / throw IPC handler posts no response → Promise never resolves; derefs options.left with no guard → throws if options omitted 🐛 IPC.js:325
toggleWindow no handler Posts toggleWindow; no IPC handler → silent no-op; untyped/undocumented 🐛 UI.js:1086
requestUpgrade no handler Typed as returning Promise; posts requestUpgrade, no IPC handler → never resolves; no doc 🐛 UI.js:892
notify fallback return Web fallback resolves opts.uid || null synchronously + double-resolves on close; contradicts Promise<string> 🟡 UI.js:773
showColorPicker defaultValue/default aliases Accepted in fallback only; not in IPC, types, or docs 🟡 UI.js:884
showFontPicker default alias + return shape default alias untyped/undocumented; GUI path return shape may not be {fontFamily} 🟡 UI.js:864
showDirectoryPicker accept option Read by IPC; absent from DirectoryPickerOptions 🟡 IPC.js:567
prompt options.defaultValue Read by IPC + typed; prompt.md omits the options arg entirely 🔵 IPC.js:253
launchApp #(as) pseudonym + callback Pseudonym syntax + options.callback undocumented/untyped 🔵 UI.js:1318
showOpen/SaveFilePicker .undefinedOnCancel Cancel-aware promise variant undocumented 🔵 UI.js:852
setMenubar item id Needed to target items for enable/disable/setMenuItem*; omitted from setMenubar.md 🔵 IPC.js:744
exit location Index labels it puter.ui.exit() but it's puter.exit 🔵 IPC.js:1954

🐛 UI impl-bugs: socialShare (hung promise + unguarded options), toggleWindow (no handler), requestUpgrade (no handler), notify fallback double/early resolve.
🗑 UI: menubar() (UI.js:1369) is a legacy DOM menubar builder superseded by setMenubar — candidate for removal/internal tagging.

on event names verified correct (localeChanged/themeChanged/connection).


Apps

Function Item Issue Tag impl ref
checkName existence Typed public method; undocumented 🔵 Apps.js:206
getDeveloperProfile existence + bug Typed; undocumented. Also structurally broken: double-nested Promise never settles on the default (no-callback) path 🐛 Apps.js:232
create title "(required)" Doc heading marks title required; impl defaults it to name 🔵 Apps.js:90
create indexURL Doc says omitting → no index page; impl throws Index URL is required 🔵 Apps.js:135
create zero-arg call if (!options.object.name) throws TypeError when called with no args 🐛(minor) Apps.js:126
AppConnection type No TS interface in apps.d.ts; only documented in Objects + ui.d.ts 🟡 (ui module)

Auth

Function Item Issue Tag impl ref
getGlobalUsage existence Impl only; missing from types AND docs 🔴 Auth.js:338
getMonthlyUsage index listing Has page + type; missing from Auth.md "Functions" list 🔵 Auth.js:258
getDetailedAppUsage index listing Has page + type; missing from Auth.md "Functions" list 🔵 Auth.js:296
getUser params getUser.md says "Parameters: None"; impl/types accept options/callbacks 🔵 Auth.js:184
getUser positional overload Impl supports (success, error); types declare only object form 🟡 Auth.js:189
whoami existence Public method in impl + types; undocumented 🔵 Auth.js:211
User object email/uuid Perms.requestEmail/whoami rely on email; not on User interface nor user.md 🔴 Perms.js:154
User object feature_flags/hasDevAccountAccess/otp In User interface; absent from user.md 🔵 auth.d.ts:15
DetailedAppUsage type total:number conflicts with index signature [key]:APIUsage — internally inconsistent 🟡 auth.d.ts:75

Perms

Function Item Issue Tag impl ref
requestReadAppRootDir existence Impl only; missing from types AND docs 🔴 Perms.js:333
requestWriteAppRootDir existence Impl only; missing from types AND docs 🔴 Perms.js:346
#requestAppRootDir hardcoded access Body hardcodes access:'read' → write request impossible 🐛 Perms.js:359
#requestAppRootDir undefined var References undefined app_or_uuid (dead/broken logic) 🐛 Perms.js:367
grant*/revoke*/createGroup/addUsersToGroup/removeUsersFromGroup/listGroups docs 11+ typed public methods with zero docs 🔵 Perms.js:37-116

Workers

Function Item Issue Tag impl ref
getLoggingHandle existence In impl + types; absent from all docs (not in Workers.md list, no page) 🆕/🔵 Workers.js:137
delete unthrown Error new Error("Worker doesn't exist") constructed but never thrown (missing throw); duplicated nested guard 🐛 Workers.js:119
exec x-puter-no-auth header Auth-skip escape hatch honored by impl; undocumented 🔵 Workers.js:70

router.md/types.md confirmed as deployed-worker runtime docs (out of SDK-call scope). workerinfo/workerdeployment objects match interfaces.


Hosting

Function Item Issue Tag impl ref
update empty payload Only the string-arg branch builds a payload; other call shapes send empty {} to the driver 🐛 Hosting.js:83
create subdomain optionality Types require it; create.md implies optional (String) 🔵 Hosting.js:76

subdomain object matches interface. setAuthToken/setAPIOrigin are internal (incorrect @memberof JSDoc tags, cosmetic).


Networking

Function Item Issue Tag impl ref
PSocket.write ArrayBuffer branch Calls data.write(...) on an ArrayBuffer (no such method) → throws on any ArrayBuffer write; should be wispInfo.handler.write 🐛 PSocket.js:74
PWispHandler._continue missing arg Called as this._continue() with no streamIDstreamMap.get(undefined) throws; flow-control drain dead 🐛 PWispHandler.js:31
PWispHandler reconnect setTimeout(setup(), 1000) invokes setup() immediately, schedules undefined 🐛 PWispHandler.js:22
SocketEvent 'drain' dead event Declared in ctor + networking.d.ts; never emitted 🟡/🗑 PSocket.js:16
PTLSSocket.on plain-name aliases .on('data'|'open'|'close') are remapped to tls*; works but undocumented/untyped 🔵 PTLS.js:92
generateWispV1URL docs In impl + types; no doc page under Networking 🔵 index.js:627
pFetch reject type Rejects with string, not Error (minor) requests.js:63

Peer

Function Item Issue Tag impl ref
PuterPeerConnection error event payload type Impl sets .error to an Error object; types declare error: string; docs example uses .error?.message 🔴 Peer.js:33
PuterPeerServer.close existence In impl; missing from types AND docs 🔴 Peer.js:170
PuterPeerServer.message phantom Typed as public method; impl method is #message (private) → no public message() 🟡/🗑 peer.d.ts:67
setRemoteDescription / addIceCandidate return Impl async (returns Promise); types declare void 🟡 Peer.js:326
Peer ctor JSDoc Doc-comment documents 3 string params; signature is constructor(puter) 🐛(doc-comment) Peer.js:350

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

Area Bug ref
FS FSItem.move passes positional bool where op expects options object → overwrite/newName dropped FSItem.js:89
FS FSItem.copyautoRename dropped, overwrite consumed as success callback FSItem.js:93
FS FSItem.mkdir accepts auto_rename then ignores it FSItem.js:110
FS fs.copy dedupeName/dedupe_name not mapped in positional branch copy.js:11
FS fs.copy createMissingParents read but never sent copy.js:17
FS fs.move positional socket-id dropped (body uses excludeSocketID) move.js:20
Networking PSocket.write ArrayBuffer branch calls data.write(...) → throws PSocket.js:74
Networking PWispHandler._continue() called with no streamID → throws; drain path dead PWispHandler.js:31
Networking PWispHandler reconnect setTimeout(setup(), 1000) fires immediately PWispHandler.js:22
UI socialShare Promise never resolves (no IPC response) + throws if options omitted IPC.js:325
UI toggleWindow posts a message no IPC handler reads (no-op) UI.js:1086
UI requestUpgrade typed as returning Promise; no IPC handler → never resolves UI.js:892
UI notify web fallback resolves uid||null synchronously + double-resolves on close UI.js:773
Apps getDeveloperProfile double-nested Promise never settles on no-callback path Apps.js:246
Apps create() with zero args throws TypeError (options.object.name) Apps.js:126
Perms #requestAppRootDir hardcodes access:'read' → write request impossible Perms.js:359
Perms #requestAppRootDir references undefined app_or_uuid Perms.js:367
Workers delete constructs new Error("Worker doesn't exist") but never throws it Workers.js:119
Hosting update() builds payload only in string-arg branch; other shapes send {} Hosting.js:83
AI Txt2ImgOptions.service phantom option (declared, never read) ai.d.ts:180

🆕/🗑 manifest-drift

Files on disk but not in the Expected manifest (🆕 new):

  • src/docs/src/Objects/ttsengine.md — backs TTSEngine, referenced from AI/txt2speech.listEngines.md (legitimate addition).
  • src/docs/src/Objects/ttsvoice.md — backs TTSVoice, referenced from AI/txt2speech.listVoices.md (legitimate addition).

All other impl/types/docs files on disk match the manifest's stable roots. No manifest files are missing from disk (🗑 none at the file level).

Method-level manifest drift (impl/types ahead of docs/types):

  • 🆕 KV.clear (impl + types, no KV.md entry / no KV/clear.md)
  • 🆕 Workers.getLoggingHandle (impl + types, no docs)
  • 🆕 fs.revokeReadURL, fs.readdirSubdomains, fs.sign (impl ahead of types/docs to varying degrees)
  • 🆕 Auth.getGlobalUsage (impl only)
  • 🆕 Perms.requestReadAppRootDir / requestWriteAppRootDir, plus grant*/revoke*/group methods (impl/types ahead of docs)
  • 🆕 UI: requestPermission, instancesOpen, connectToInstance, disableMenuItem, enableMenuItem, requestEmailConfirmation, openDevPaymentsAccount, toggleWindow, isWorkingActive (missing from types + docs); setMenuItemIcon/IconActive/Checked, requestUpgrade (typed, no docs)
  • 🆕 top-level puter.*: on, off, call, whoami, quiet, debugMode, triggerReauth (impl, missing from puter.d.ts)
  • 🗑 PuterPeerServer.message in peer.d.ts (no public impl — method is #private)
  • 🗑 SocketEvent 'drain' in networking.d.ts (never emitted)
  • 🗑 UI.menubar() legacy DOM builder (superseded by setMenubar)

Utils / Drivers / OS

Area Item Issue Tag impl ref
Utils print multi-arg Impl variadic print(...args); types/docs single-arg only 🔴 index.js:1251
Utils print escapeHTML Supported + typed; print.md omits it 🔵 index.js:1258
Utils env values Impl returns web-worker/service-worker/nodejs too; env.md lists only app/web/gui 🔵 index.js:357
Utils puter.on/puter.off Public SDK event API; missing from puter.d.ts 🟡 index.js:972
Utils puter.call/whoami/quiet/debugMode/triggerReauth Wired top-level; missing from puter.d.ts 🟡 index.js / Drivers.js:147
Drivers call 2-arg overload call(iface, params) documented convenience form not typed; current 3-arg-optional sig mis-resolves it 🟡 Drivers.js:262
Drivers ctor signature Types say {authToken, APIOrigin, appID}; impl takes puter 🟡 Drivers.js:135
OS user/version positional callbacks Impl supports (success, error); types model object form only 🟡 OS.js:41

No Utils/Drivers/OS impl-bugs. No unexpected OS/Drivers docs family appeared (correct).


Generated by the puter.js types & docs drift audit routine. Every finding is reproducible against commit 24d700673cd8c18bd9d04d6a52c04172b67984b0.

🤖 Generated with Claude Code

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