toolcraft 0.0.801 → 0.0.803

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/composition.json CHANGED
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "name": "toolcraft",
141
- "version": "0.0.801",
141
+ "version": "0.0.803",
142
142
  "license": "MIT"
143
143
  },
144
144
  {
@@ -148,7 +148,7 @@
148
148
  },
149
149
  {
150
150
  "name": "toolcraft-schema",
151
- "version": "0.0.801",
151
+ "version": "0.0.803",
152
152
  "license": "MIT"
153
153
  },
154
154
  {
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "name": "toolcraft",
141
- "version": "0.0.801",
141
+ "version": "0.0.803",
142
142
  "license": "MIT"
143
143
  },
144
144
  {
@@ -148,7 +148,7 @@
148
148
  },
149
149
  {
150
150
  "name": "toolcraft-schema",
151
- "version": "0.0.801",
151
+ "version": "0.0.803",
152
152
  "license": "MIT"
153
153
  },
154
154
  {
@@ -1,3 +1,4 @@
1
+ import { plainDevicePathResolvers } from "./plain-path.js";
1
2
  import { FsError, isFsError } from "../../contracts/errors.js";
2
3
  import { pathByteLength, validatePath } from "../../contracts/virtual-path.js";
3
4
  import { capturePathNamespace, pathNamespace } from "../path-namespace.js";
@@ -146,6 +147,11 @@ export async function resolveDevicePath(filesystem, path, options, followFinal =
146
147
  const fast = tryResolveMemoryDevicePath(filesystem, path, resizeCreate);
147
148
  if (fast !== undefined)
148
149
  return fast;
150
+ if (followFinal && resizeCreate === undefined && traversal === undefined && isCleanAbsolutePath(path) && path !== "/" && path !== "/dev" && !path.startsWith("/dev/")) {
151
+ const resolved = await plainDevicePathResolvers.get(filesystem)?.(path, options);
152
+ if (resolved !== undefined)
153
+ return resolved;
154
+ }
149
155
  }
150
156
  const namespace = capturePathNamespace(filesystem, options);
151
157
  if (resizeCreate !== undefined)
@@ -0,0 +1,2 @@
1
+ import type { FileSystem, FsOptions } from "../../contracts/filesystem.js";
2
+ export declare const plainDevicePathResolvers: WeakMap<FileSystem, (path: string, options: FsOptions) => Promise<string | undefined>>;
@@ -0,0 +1,3 @@
1
+ // Private backend hooks, not cached path observations. A hook may only accept
2
+ // an ordinary existing path after freshly checking every component for symlinks.
3
+ export const plainDevicePathResolvers = new WeakMap();
@@ -1,3 +1,4 @@
1
+ import { plainDevicePathResolvers } from "../devices/plain-path.js";
1
2
  import { platform } from "#safe-fs-platform";
2
3
  import { snapshotStagingCreation } from "../staging-cleanup.js";
3
4
  import { snapshotConditionalChmod } from "../conditional-chmod.js";
@@ -121,6 +122,30 @@ export class RealFileSystem {
121
122
  throw new FsError("ENOTSUP", { syscall: "root", message: "this backend requires a POSIX host" });
122
123
  }
123
124
  this.configuredRoot = root;
125
+ if (Object.getPrototypeOf(this) === RealFileSystem.prototype) {
126
+ plainDevicePathResolvers.set(this, async (path, options) => {
127
+ if (this.lstat !== realImplementation.lstat?.value || this.readlink !== realImplementation.readlink?.value)
128
+ return undefined;
129
+ try {
130
+ let target = await this.root(options);
131
+ const components = path.slice(1).split("/");
132
+ for (let index = 0; index < components.length; index++) {
133
+ options.signal?.throwIfAborted();
134
+ target = join(target, components[index]);
135
+ const stat = await native.lstat(target);
136
+ options.signal?.throwIfAborted();
137
+ if ((!stat.isFile() && !stat.isDirectory()) || (index < components.length - 1 && !stat.isDirectory()))
138
+ return undefined;
139
+ }
140
+ return path;
141
+ }
142
+ catch {
143
+ options.signal?.throwIfAborted();
144
+ // Missing entries, symlinks and other failures use generic routing.
145
+ return undefined;
146
+ }
147
+ });
148
+ }
124
149
  this.renameNoReplace = typeof options === "string" ? undefined : options.renameNoReplace;
125
150
  if (this.renameNoReplace !== undefined) {
126
151
  if (!platform.nativeFileSystem.atomicRename)
@@ -140,10 +165,15 @@ export class RealFileSystem {
140
165
  })();
141
166
  const root = await this.rootPromise;
142
167
  options.signal?.throwIfAborted();
143
- if (await native.realpath(root) !== root)
168
+ const [canonical, metadata] = await Promise.allSettled([native.realpath(root), native.stat(root)]);
169
+ if (canonical.status === "rejected")
170
+ throw canonical.reason;
171
+ if (canonical.value !== root)
144
172
  throw new FsError("EACCES");
145
173
  options.signal?.throwIfAborted();
146
- if (!(await native.stat(root)).isDirectory())
174
+ if (metadata.status === "rejected")
175
+ throw metadata.reason;
176
+ if (!metadata.value.isDirectory())
147
177
  throw new FsError("ENOTDIR");
148
178
  options.signal?.throwIfAborted();
149
179
  return root;
@@ -8,7 +8,7 @@
8
8
  },
9
9
  {
10
10
  "name": "toolcraft-schema",
11
- "version": "0.0.801",
11
+ "version": "0.0.803",
12
12
  "license": "MIT"
13
13
  }
14
14
  ]
@@ -6,7 +6,7 @@ export function prepareDetailContent(content, width) {
6
6
  return { text: "", lines: [[]] };
7
7
  }
8
8
  width = Math.max(1, width);
9
- const key = `${contentHash(content)}:${width}`;
9
+ const key = `${width}:${content}`;
10
10
  const cached = markdownCache.get(key);
11
11
  if (cached !== undefined)
12
12
  return cached;
@@ -22,11 +22,3 @@ export function prepareDetailContent(content, width) {
22
22
  markdownCache.set(key, prepared);
23
23
  return prepared;
24
24
  }
25
- function contentHash(content) {
26
- let hash = 2166136261;
27
- for (let index = 0; index < content.length; index += 1) {
28
- hash ^= content.charCodeAt(index);
29
- hash = Math.imul(hash, 16777619);
30
- }
31
- return hash >>> 0;
32
- }
@@ -112,6 +112,6 @@ function canonical(value) { return value.trim().toLowerCase().replace("control+"
112
112
  function eventKey(event) {
113
113
  const name = event.name ?? event.ch ?? "";
114
114
  const modifiers = [event.ctrl ? "ctrl" : "", event.meta ? "meta" : "", event.shift ? "shift" : ""].filter(Boolean);
115
- const normalized = name === "return" ? "return" : name.toLowerCase();
115
+ const normalized = name === " " ? "space" : name.toLowerCase();
116
116
  return [...modifiers, normalized].join("+");
117
117
  }
@@ -941,7 +941,7 @@ function isBackspace(key) {
941
941
  return key.name === "backspace" || key.name === "delete";
942
942
  }
943
943
  function isSelectionSpace(key) {
944
- return key.name === "space" || key.ch === " ";
944
+ return key.name !== "paste" && (key.name === "space" || key.ch === " ");
945
945
  }
946
946
  function isConfirmYes(key) {
947
947
  return key.ch === "y" || key.ch === "Y";
@@ -101,7 +101,8 @@ class ExplorerRuntime {
101
101
  for (const ch of event.text.replaceAll("\n", "").replaceAll("\r", "")) {
102
102
  this.dispatch({
103
103
  type: "key",
104
- key: { ch, name: ch, ctrl: false, meta: false, shift: false }
104
+ // Pasted characters are text, even when they have a key binding.
105
+ key: { ch, name: "paste", ctrl: false, meta: false, shift: false }
105
106
  });
106
107
  }
107
108
  return;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft-schema",
3
- "version": "0.0.801",
3
+ "version": "0.0.803",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.801",
3
+ "version": "0.0.803",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -177,7 +177,7 @@
177
177
  "saxes"
178
178
  ],
179
179
  "optionalDependencies": {
180
- "toolcraft-schema": "0.0.801",
180
+ "toolcraft-schema": "0.0.803",
181
181
  "toolcraft-design": "*",
182
182
  "@poe-code/frontmatter": "*",
183
183
  "@poe-code/agent-mcp-config": "*",