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)
- 🐛
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)
- 🐛 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)
- 🐛 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)
- 🔴 Whole public UI methods missing from types AND docs:
requestPermission, instancesOpen, connectToInstance, disableMenuItem, enableMenuItem. (UI.js)
- 🔴
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.
- 🔴
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.
- 🔴
fs.revokeReadURL missing from types — wired public method (index.js:44), no .d.ts declaration, no doc page; its counterpart getReadURL is fully documented.
- 🐛
Perms.#requestAppRootDir hardcodes access:'read' — requestWriteAppRootDir can never request write; both requestReadAppRootDir/requestWriteAppRootDir are also untyped + undocumented.
- 🔴
Auth.getGlobalUsage exists in impl only — absent from types and docs.
- 🟡
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 |
duration→seconds alias |
Impl maps duration→seconds; 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_format→output_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 streamID → streamMap.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.copy → autoRename 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
Audit scope: full deep audit of the puter.js SDK for TypeScript drift and documentation drift against the implementation.
Pinned commit:
24d700673cd8c18bd9d04d6a52c04172b67984b0(branchclaude/exciting-lamport-bsrxgf)Sources of truth: impl
src/puter-js/src/modules/+src/puter-js/src/index.js(+src/gui/src/IPC.jsfor the UI family) · typessrc/puter-js/types/· docssrc/docs/src/Tag legend
🌟 Highest-impact shortlist (cross-family)
FSItem.copy/FSItem.move/FSItem.mkdirsilently drop their params — these methods pass positional booleans (overwrite,autoRename,newName) into ops that expect an options object; incopy,overwriteis even consumed as the success callback. Documented params don't work. (FSItem.js:89-119)PSocket.writeArrayBuffer branch callsdata.write(...)on an ArrayBuffer (throws);PWispHandler._continue()is called with nostreamID(flow-control resume dead);PWispHandlerreconnect doessetTimeout(setup(), 1000)(fires immediately, schedulesundefined). (PSocket.js:74,PWispHandler.js:31,22)socialSharereturns a Promise the GUI never resolves (and throws ifoptionsomitted);toggleWindowandrequestUpgradepost messages no handler reads. (IPC.js:325,UI.js:1086,892)requestPermission,instancesOpen,connectToInstance,disableMenuItem,enableMenuItem. (UI.js)isDirvsisDirectory— the runtime FSItem property isisDirectory; bothfs-item.d.tsandfsitem.mdadvertiseisDir, which never exists on the instance.KV.MAX_VALUE_SIZE/ value limit is documented as "400 KB" everywhere but impl is399 * 1024(≈399 KB). A value between 399–400 KB is rejected contrary to docs/types.fs.revokeReadURLmissing from types — wired public method (index.js:44), no.d.tsdeclaration, no doc page; its counterpartgetReadURLis fully documented.Perms.#requestAppRootDirhardcodesaccess:'read'—requestWriteAppRootDircan never request write; bothrequestReadAppRootDir/requestWriteAppRootDirare also untyped + undocumented.Auth.getGlobalUsageexists in impl only — absent from types and docs.Drivers.callmissing its 2-arg overload (call(iface, params)), the documented convenience form; current typing mis-resolves it as a type error.AI
errorstream chunkpart.type==='error'+part.message;ChatResponseChunk.typelackserrorand has nomessageimagestream chunkpart.imageon stream chunks;ChatResponseChunkhas noimagefieldChatMessage.images{type:"file", puter_path}; not modeled inAIMessageContent{type:"web_search"};Toolinterface requiresfunctionprovider/driveroptionsserviceoptionTxt2ImgOptionsbut impl never reads it (phantom)nano-banana/nano-banana-promodelsdriveroptionduration→secondsaliasduration→seconds; alias undocumentedvoiceId/modelId/outputFormat/voiceSettings/fileFormat/removeBackgroundNoise/optimizeStreamingLatency/enableLogging;Speech2SpeechOptionsdeclares only snake_caseremoveBackgroundNoise; not in docs options listgrok/x-aiprovider aliasesengine:'openai'|'elevenlabs'|'gemini'|'xai'infers provider; undocumentedresponse_format→output_format(elevenlabs)🐛 AI impl-bug:
Txt2ImgOptions.serviceis a phantom option (declared, never read).🆕 AI manifest-drift:
Objects/ttsengine.md+Objects/ttsvoice.mdare real new files (backTTSEngine/TTSVoice, referenced from listEngines/listVoices) not in the expected AI-objects manifest.FileSystem (FS)
isDirisDirectory; types +fsitem.mdadvertiseisDir(never set)readURL/writeURL/metadataURL/uid/uuidfsitem.mdoverwrite/newNamemoveop which expects an options object atargs[2]→ droppedautoRename/overwriteargs[2]is a bool not options;overwriteconsumed as success callback → both brokenauto_renamededupeName/dedupe_namecreateMissingParentsdedupeName/movenever reads or sends any dedupe field (phantom doc option)original_client_socket_id, body sendsexcludeSocketID→ positional droppedcacheoptionReadOptionsand docsno_subdomainsReaddirOptionstype (and docs)no_thumbs/no_assocs/consistencyconsistencydefault'strong'undocumentedreturnWorkersreturnSubdomains; not inStatOptions, not in docsconsistencygenerateThumbnails/thumbnailGenerator/thumbnailUploadOptions, not in docsname/shortcutTo/appUID/strict/createFileParent/createMissingAncestors/parsedDataTransferItemsinit/start/progress/abortfired + typed; docs mention nonecreateMissingAncestors+ progress callbacksFS/doc pagegetReadURL,sign,space,revokeReadURL(pages exist for some)🐛 FS impl-bugs: FSItem.move/copy/mkdir param drop; fs.copy
dedupeName/createMissingParentsdropped; fs.move positional socket-id dropped.KV
399*1024(408576 B); types JSDoc + set.md say "400 KB" — wrongMAX_VALUE_SIZE.mdstates no numeric value (should be 408576 B / ≈399 KB)MAX_KEY_SIZE.mdstates no numeric value (impl = 1024)get.mdshows onlyget(key)del.mdomits itflush.mdsays "None"flushin impl + types; missing from KV.md function list, noKV/clear.mdNo KV impl-bugs. (Constants
add/incr/decrdefault-to-1 verified correct across all three.)UI (impl = UI.js + IPC.js)
getInstancesOpen); missing from types + docsoptions.leftwith no guard → throws ifoptionsomittedtoggleWindow; no IPC handler → silent no-op; untyped/undocumentedrequestUpgrade, no IPC handler → never resolves; no docopts.uid || nullsynchronously + double-resolves on close; contradictsPromise<string>defaultValue/defaultaliasesdefaultalias + return shapedefaultalias untyped/undocumented; GUI path return shape may not be{fontFamily}acceptoptionDirectoryPickerOptionsoptions.defaultValueprompt.mdomits the options arg entirely#(as)pseudonym +callback.undefinedOnCancelidputer.ui.exit()but it'sputer.exit🐛 UI impl-bugs:
socialShare(hung promise + unguardedoptions),toggleWindow(no handler),requestUpgrade(no handler),notifyfallback double/early resolve.🗑 UI:
menubar()(UI.js:1369) is a legacy DOM menubar builder superseded bysetMenubar— candidate for removal/internal tagging.onevent names verified correct (localeChanged/themeChanged/connection).Apps
title"(required)"titlerequired; impl defaults it tonameindexURLIndex URL is requiredif (!options.object.name)throws TypeError when called with no argsapps.d.ts; only documented in Objects + ui.d.tsAuth
getUser.mdsays "Parameters: None"; impl/types acceptoptions/callbacks(success, error); types declare only object formemail/uuidPerms.requestEmail/whoami rely onemail; not onUserinterface nor user.mdfeature_flags/hasDevAccountAccess/otpUserinterface; absent from user.mdtotal:numberconflicts with index signature[key]:APIUsage— internally inconsistentPerms
access:'read'→ write request impossibleapp_or_uuid(dead/broken logic)Workers
new Error("Worker doesn't exist")constructed but never thrown (missingthrow); duplicated nested guardx-puter-no-authheaderrouter.md/types.mdconfirmed as deployed-worker runtime docs (out of SDK-call scope). workerinfo/workerdeployment objects match interfaces.Hosting
{}to the driversubdomainoptionality(String)subdomainobject matches interface.setAuthToken/setAPIOriginare internal (incorrect@memberofJSDoc tags, cosmetic).Networking
data.write(...)on an ArrayBuffer (no such method) → throws on any ArrayBuffer write; should bewispInfo.handler.writethis._continue()with nostreamID→streamMap.get(undefined)throws; flow-control drain deadsetTimeout(setup(), 1000)invokessetup()immediately, schedulesundefined'drain'networking.d.ts; never emitted.on('data'|'open'|'close')are remapped totls*; works but undocumented/untypedErrorPeer
errorevent.errorto anErrorobject; types declareerror: string; docs example uses.error?.message#message(private) → no publicmessage()voidconstructor(puter)🐛 impl-bug bucket (code fixes, not doc/type edits)
FSItem.movepasses positional bool where op expects options object →overwrite/newNamedroppedFSItem.copy→autoRenamedropped,overwriteconsumed as success callbackFSItem.mkdiracceptsauto_renamethen ignores itfs.copydedupeName/dedupe_namenot mapped in positional branchfs.copycreateMissingParentsread but never sentfs.movepositional socket-id dropped (body usesexcludeSocketID)PSocket.writeArrayBuffer branch callsdata.write(...)→ throwsPWispHandler._continue()called with nostreamID→ throws; drain path deadPWispHandlerreconnectsetTimeout(setup(), 1000)fires immediatelysocialSharePromise never resolves (no IPC response) + throws ifoptionsomittedtoggleWindowposts a message no IPC handler reads (no-op)requestUpgradetyped as returning Promise; no IPC handler → never resolvesnotifyweb fallback resolvesuid||nullsynchronously + double-resolves on closegetDeveloperProfiledouble-nested Promise never settles on no-callback pathcreate()with zero args throws TypeError (options.object.name)#requestAppRootDirhardcodesaccess:'read'→ write request impossible#requestAppRootDirreferences undefinedapp_or_uuiddeleteconstructsnew Error("Worker doesn't exist")but never throws itupdate()builds payload only in string-arg branch; other shapes send{}Txt2ImgOptions.servicephantom option (declared, never read)🆕/🗑 manifest-drift
Files on disk but not in the Expected manifest (🆕 new):
src/docs/src/Objects/ttsengine.md— backsTTSEngine, referenced fromAI/txt2speech.listEngines.md(legitimate addition).src/docs/src/Objects/ttsvoice.md— backsTTSVoice, referenced fromAI/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 / noKV/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)requestPermission,instancesOpen,connectToInstance,disableMenuItem,enableMenuItem,requestEmailConfirmation,openDevPaymentsAccount,toggleWindow,isWorkingActive(missing from types + docs);setMenuItemIcon/IconActive/Checked,requestUpgrade(typed, no docs)puter.*:on,off,call,whoami,quiet,debugMode,triggerReauth(impl, missing fromputer.d.ts)PuterPeerServer.messageinpeer.d.ts(no public impl — method is#private)SocketEvent'drain'innetworking.d.ts(never emitted)UI.menubar()legacy DOM builder (superseded bysetMenubar)Utils / Drivers / OS
printmulti-argprint(...args); types/docs single-arg onlyprintescapeHTMLenvvaluesweb-worker/service-worker/nodejstoo; env.md lists only app/web/guiputer.on/puter.offputer.d.tsputer.call/whoami/quiet/debugMode/triggerReauthputer.d.tscall2-arg overloadcall(iface, params)documented convenience form not typed; current 3-arg-optional sig mis-resolves it{authToken, APIOrigin, appID}; impl takesputeruser/versionpositional callbacks(success, error); types model object form onlyNo 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