@framers/agentos 0.13.64 → 0.13.66
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/dist/cognition/emergent/EmergentAgentForge.d.ts.map +1 -1
- package/dist/cognition/emergent/EmergentAgentForge.js +5 -4
- package/dist/cognition/emergent/EmergentAgentForge.js.map +1 -1
- package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts +2 -0
- package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts.map +1 -1
- package/dist/cognition/emergent/EmergentCapabilityEngine.js +10 -0
- package/dist/cognition/emergent/EmergentCapabilityEngine.js.map +1 -1
- package/dist/cognition/emergent/ForgeToolMetaTool.d.ts +4 -1
- package/dist/cognition/emergent/ForgeToolMetaTool.d.ts.map +1 -1
- package/dist/cognition/emergent/ForgeToolMetaTool.js +14 -1
- package/dist/cognition/emergent/ForgeToolMetaTool.js.map +1 -1
- package/dist/cognition/emergent/SkillExporter.d.ts +44 -3
- package/dist/cognition/emergent/SkillExporter.d.ts.map +1 -1
- package/dist/cognition/emergent/SkillExporter.js +124 -18
- package/dist/cognition/emergent/SkillExporter.js.map +1 -1
- package/dist/cognition/emergent/ToolName.d.ts +63 -0
- package/dist/cognition/emergent/ToolName.d.ts.map +1 -0
- package/dist/cognition/emergent/ToolName.js +79 -0
- package/dist/cognition/emergent/ToolName.js.map +1 -0
- package/dist/cognition/emergent/index.d.ts +3 -1
- package/dist/cognition/emergent/index.d.ts.map +1 -1
- package/dist/cognition/emergent/index.js +2 -1
- package/dist/cognition/emergent/index.js.map +1 -1
- package/dist/cognition/memory/AgentMemory.d.ts +4 -2
- package/dist/cognition/memory/AgentMemory.d.ts.map +1 -1
- package/dist/cognition/memory/AgentMemory.js +3 -1
- package/dist/cognition/memory/AgentMemory.js.map +1 -1
- package/dist/cognition/memory/core/types.d.ts +1 -1
- package/dist/cognition/memory/core/types.d.ts.map +1 -1
- package/dist/cognition/memory/index.d.ts +1 -1
- package/dist/cognition/memory/index.d.ts.map +1 -1
- package/dist/cognition/memory/index.js.map +1 -1
- package/dist/cognition/memory/io/MarkdownExporter.d.ts +53 -9
- package/dist/cognition/memory/io/MarkdownExporter.d.ts.map +1 -1
- package/dist/cognition/memory/io/MarkdownExporter.js +208 -15
- package/dist/cognition/memory/io/MarkdownExporter.js.map +1 -1
- package/dist/cognition/memory/io/ObsidianExporter.d.ts +6 -4
- package/dist/cognition/memory/io/ObsidianExporter.d.ts.map +1 -1
- package/dist/cognition/memory/io/ObsidianExporter.js +5 -3
- package/dist/cognition/memory/io/ObsidianExporter.js.map +1 -1
- package/dist/cognition/memory/io/facade/Memory.d.ts +15 -3
- package/dist/cognition/memory/io/facade/Memory.d.ts.map +1 -1
- package/dist/cognition/memory/io/facade/Memory.js +20 -8
- package/dist/cognition/memory/io/facade/Memory.js.map +1 -1
- package/dist/cognition/memory/io/facade/index.d.ts +1 -1
- package/dist/cognition/memory/io/facade/index.d.ts.map +1 -1
- package/dist/cognition/memory/io/facade/types.d.ts +41 -0
- package/dist/cognition/memory/io/facade/types.d.ts.map +1 -1
- package/dist/cognition/memory/io/tools/MemoryAddTool.d.ts +4 -0
- package/dist/cognition/memory/io/tools/MemoryAddTool.d.ts.map +1 -1
- package/dist/cognition/memory/io/tools/MemoryAddTool.js +18 -4
- package/dist/cognition/memory/io/tools/MemoryAddTool.js.map +1 -1
- package/dist/cognition/substrate/memory/wiki/WikiCompiler.d.ts +5 -1
- package/dist/cognition/substrate/memory/wiki/WikiCompiler.d.ts.map +1 -1
- package/dist/cognition/substrate/memory/wiki/WikiCompiler.js +35 -10
- package/dist/cognition/substrate/memory/wiki/WikiCompiler.js.map +1 -1
- package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.d.ts +23 -4
- package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.d.ts.map +1 -1
- package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.js +66 -35
- package/dist/cognition/substrate/memory/wiki/WikiMemoryStore.js.map +1 -1
- package/dist/cognition/substrate/memory/wiki/WikiPageId.d.ts +9 -7
- package/dist/cognition/substrate/memory/wiki/WikiPageId.d.ts.map +1 -1
- package/dist/cognition/substrate/memory/wiki/WikiPageId.js +20 -32
- package/dist/cognition/substrate/memory/wiki/WikiPageId.js.map +1 -1
- package/dist/core/utils/linkFreeWrite.d.ts +66 -0
- package/dist/core/utils/linkFreeWrite.d.ts.map +1 -0
- package/dist/core/utils/linkFreeWrite.js +140 -0
- package/dist/core/utils/linkFreeWrite.js.map +1 -0
- package/dist/core/utils/pathName.d.ts +66 -0
- package/dist/core/utils/pathName.d.ts.map +1 -0
- package/dist/core/utils/pathName.js +91 -0
- package/dist/core/utils/pathName.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Writing below a folder whose contents another process may change: folders are made one name at a
|
|
3
|
+
* time and never through a link, and a file is opened for writing never through a link, never waiting, and only
|
|
4
|
+
* when it is a regular file with one name.
|
|
5
|
+
*
|
|
6
|
+
* The Markdown and Obsidian memory exporters write a file per trace below an export folder, and the skill exporter
|
|
7
|
+
* writes a tool's files below a skills folder. Whoever can write below such a folder could put there a link that
|
|
8
|
+
* leads elsewhere, a second name for a file elsewhere, or a named pipe that holds a writer up, so both write
|
|
9
|
+
* through the functions here. The folder itself is the caller's and may be a link. The checks run as each folder
|
|
10
|
+
* is made and each file opened; Node has no `openat`, so a process that swaps a folder for a link between a check
|
|
11
|
+
* and the write is outside what they stop.
|
|
12
|
+
*
|
|
13
|
+
* @module agentos/core/utils/linkFreeWrite
|
|
14
|
+
*/
|
|
15
|
+
import fs from 'node:fs/promises';
|
|
16
|
+
import { constants as fsConstants } from 'node:fs';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
/**
|
|
19
|
+
* The flags a file is opened with: for writing, made when missing, and, where the platform has each flag (Windows
|
|
20
|
+
* has neither), never through a symbolic link in the file's own place (`O_NOFOLLOW`) and never waiting
|
|
21
|
+
* (`O_NONBLOCK`). Without `O_NONBLOCK`, an open for writing of a named pipe that no process reads waits for a
|
|
22
|
+
* reader that may never come. The file is not emptied by the open: the caller empties it once the open file shows
|
|
23
|
+
* it is a regular file with no second name.
|
|
24
|
+
*/
|
|
25
|
+
const OPEN_FLAGS = fsConstants.O_WRONLY |
|
|
26
|
+
fsConstants.O_CREAT |
|
|
27
|
+
(fsConstants.O_NOFOLLOW !== undefined ? fsConstants.O_NOFOLLOW : 0) |
|
|
28
|
+
(fsConstants.O_NONBLOCK !== undefined ? fsConstants.O_NONBLOCK : 0);
|
|
29
|
+
/** The codes an open with `O_NOFOLLOW` fails with when a symbolic link holds the file's place (EMLINK on FreeBSD). */
|
|
30
|
+
const LINK_OPEN_CODES = new Set(['ELOOP', 'EMLINK']);
|
|
31
|
+
/**
|
|
32
|
+
* The codes an open for writing fails with when something other than a regular file holds the file's place:
|
|
33
|
+
* EISDIR for a folder; ENXIO for a named pipe that no process reads (under `O_NONBLOCK`), a device with no driver,
|
|
34
|
+
* or, on Linux, a socket; EOPNOTSUPP for a socket on macOS.
|
|
35
|
+
*/
|
|
36
|
+
const SPECIAL_OPEN_CODES = new Set(['EISDIR', 'ENXIO', 'EOPNOTSUPP']);
|
|
37
|
+
/**
|
|
38
|
+
* Make the folders `relative` names under `root`, one name at a time, and stop at a link. A folder this makes is
|
|
39
|
+
* never a link, so a file written into it stays under `root`.
|
|
40
|
+
*
|
|
41
|
+
* @param root - The folder the others are made in. It may itself be a link.
|
|
42
|
+
* @param relative - The folders' path under `root`.
|
|
43
|
+
* @returns True when every folder is in place and none of them is a link.
|
|
44
|
+
*/
|
|
45
|
+
export async function makeFoldersOutsideLinks(root, relative) {
|
|
46
|
+
let dir = root;
|
|
47
|
+
for (const name of relative.split(path.sep).filter((part) => part.length > 0)) {
|
|
48
|
+
dir = path.join(dir, name);
|
|
49
|
+
const entry = await lstatOrNull(dir);
|
|
50
|
+
if (entry) {
|
|
51
|
+
if (entry.isSymbolicLink())
|
|
52
|
+
return false;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
await fs.mkdir(dir);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err.code !== 'EEXIST')
|
|
60
|
+
throw err;
|
|
61
|
+
// Something was put there since the look: look again.
|
|
62
|
+
if ((await fs.lstat(dir)).isSymbolicLink())
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Look at a file's place without opening it. A caller that writes several files, all of them or none, looks at
|
|
70
|
+
* every place before it opens any file, so a refusal makes no file. The look does not see a change made after it;
|
|
71
|
+
* {@link openFileOutsideLinks} checks again.
|
|
72
|
+
*
|
|
73
|
+
* @param file - Absolute path of the file.
|
|
74
|
+
* @returns `link` when a symbolic link holds the place or the file there has a second name, `special` when
|
|
75
|
+
* something other than a regular file holds it, or null when the place is free or holds a regular file with one
|
|
76
|
+
* name.
|
|
77
|
+
* @throws Any error the look meets other than a missing file.
|
|
78
|
+
*/
|
|
79
|
+
export async function lookOutsideLinks(file) {
|
|
80
|
+
const entry = await lstatOrNull(file);
|
|
81
|
+
if (entry === null)
|
|
82
|
+
return null;
|
|
83
|
+
if (entry.isSymbolicLink())
|
|
84
|
+
return 'link';
|
|
85
|
+
if (!entry.isFile())
|
|
86
|
+
return 'special';
|
|
87
|
+
return entry.nlink > 1 ? 'link' : null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Open a file for writing, in a folder already made, and check what the open reached. A symbolic link in the
|
|
91
|
+
* file's place is refused before the open, and where the platform has `O_NOFOLLOW` the open refuses one put there
|
|
92
|
+
* since. A folder fails the open, and where the platform has `O_NONBLOCK` so does a named pipe that no process
|
|
93
|
+
* reads, at once. An open file that is not a regular file (a named pipe that a process reads, a device) is refused,
|
|
94
|
+
* and so is a file with a second name (a hard link), which is the same file as that name and may lie outside the
|
|
95
|
+
* folder. Nothing is emptied or written here; a refused file is closed.
|
|
96
|
+
*
|
|
97
|
+
* @param file - Absolute path of the file.
|
|
98
|
+
* @returns The open file and its identity, or the refusal.
|
|
99
|
+
* @throws Any other error the look or the open meets.
|
|
100
|
+
*/
|
|
101
|
+
export async function openFileOutsideLinks(file) {
|
|
102
|
+
if ((await lstatOrNull(file))?.isSymbolicLink())
|
|
103
|
+
return 'link';
|
|
104
|
+
const handle = await fs.open(file, OPEN_FLAGS).catch((err) => {
|
|
105
|
+
const code = String(err.code);
|
|
106
|
+
if (LINK_OPEN_CODES.has(code))
|
|
107
|
+
return 'link';
|
|
108
|
+
if (SPECIAL_OPEN_CODES.has(code))
|
|
109
|
+
return 'special';
|
|
110
|
+
throw err;
|
|
111
|
+
});
|
|
112
|
+
if (typeof handle === 'string')
|
|
113
|
+
return handle;
|
|
114
|
+
let handedOver = false;
|
|
115
|
+
try {
|
|
116
|
+
const stat = await handle.stat({ bigint: true });
|
|
117
|
+
if (!stat.isFile())
|
|
118
|
+
return 'special';
|
|
119
|
+
if (stat.nlink > 1n)
|
|
120
|
+
return 'link';
|
|
121
|
+
handedOver = true;
|
|
122
|
+
return { handle, identity: stat.ino === 0n ? null : `${stat.dev}:${stat.ino}` };
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
if (!handedOver)
|
|
126
|
+
await handle.close();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** The entry at `file` itself, a link not followed, or null when there is none. */
|
|
130
|
+
async function lstatOrNull(file) {
|
|
131
|
+
try {
|
|
132
|
+
return await fs.lstat(file);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (err.code === 'ENOENT')
|
|
136
|
+
return null;
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=linkFreeWrite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkFreeWrite.js","sourceRoot":"","sources":["../../../src/core/utils/linkFreeWrite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The rule for a file or folder name built from data, and the check that a path built from such
|
|
3
|
+
* names lies inside its folder.
|
|
4
|
+
*
|
|
5
|
+
* The memory wiki builds a page's path from its id, the Markdown and Obsidian memory exporters build a trace's
|
|
6
|
+
* path from its scope, type and id, and the skill exporter builds a forged tool's folder from its name. Those
|
|
7
|
+
* values come from files, imports and models, so every name taken from them is checked against one rule here,
|
|
8
|
+
* and every path built from them is checked to lie inside the folder it is written to.
|
|
9
|
+
*
|
|
10
|
+
* @module agentos/core/utils/pathName
|
|
11
|
+
*/
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
/**
|
|
14
|
+
* The most bytes, in UTF-8, one name may hold. Linux allows 255 bytes in a name, and Windows usually 255 UTF-16
|
|
15
|
+
* code units; a name never holds more code units than bytes, so 200 fits both and leaves room for the extension a
|
|
16
|
+
* caller adds, such as `.md`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const MAX_PATH_NAME_BYTES = 200;
|
|
19
|
+
/**
|
|
20
|
+
* Why a name was refused:
|
|
21
|
+
* - `'empty'`: the name is empty.
|
|
22
|
+
* - `'character'`: it holds a slash, a backslash, a colon, one of `"`, `*`, `<`, `>`, `?` and `|`, or a control
|
|
23
|
+
* character (U+0000 to U+001F, or U+007F), a NUL byte among them. A slash or a backslash separates folders; on
|
|
24
|
+
* Windows a colon names a drive (`C:name`) or a file's stream (`name:stream`), and Windows refuses the other six
|
|
25
|
+
* in a name.
|
|
26
|
+
* - `'dot'`: it starts with a dot, so it is `.`, `..` or a hidden name.
|
|
27
|
+
* - `'edge'`: it starts or ends with a space, or ends with a dot. Windows drops those from a name, so the name
|
|
28
|
+
* would be another's (`notes.` is `notes` there).
|
|
29
|
+
* - `'length'`: it holds more than {@link MAX_PATH_NAME_BYTES} bytes in UTF-8.
|
|
30
|
+
*/
|
|
31
|
+
export type PathNameProblem = 'empty' | 'character' | 'dot' | 'edge' | 'length';
|
|
32
|
+
/**
|
|
33
|
+
* A refused value as an error message shows it: a string quoted and escaped, cut to its first 64 characters, or
|
|
34
|
+
* the type of any other value.
|
|
35
|
+
*
|
|
36
|
+
* @param value - The refused value.
|
|
37
|
+
*/
|
|
38
|
+
export declare function describeRefusedName(value: unknown): string;
|
|
39
|
+
/**
|
|
40
|
+
* True when the character whose UTF-16 code is `code` may appear neither in a name nor anywhere in a path whose
|
|
41
|
+
* names are joined with `/`: a backslash, a colon, one of `"`, `*`, `<`, `>`, `?` and `|`, or a control character
|
|
42
|
+
* (U+0000 to U+001F, or U+007F).
|
|
43
|
+
*/
|
|
44
|
+
export declare function isRefusedPathCharacter(code: number): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The part of the name rule `name` breaks, or null when `name` may name one file or folder. A name the rule
|
|
47
|
+
* accepts holds no separator, is never `.` or `..`, and names no drive or file stream, so a path built from such
|
|
48
|
+
* names stays under the folder it starts from.
|
|
49
|
+
*
|
|
50
|
+
* @param name - The name to check.
|
|
51
|
+
*/
|
|
52
|
+
export declare function pathNameProblem(name: string): PathNameProblem | null;
|
|
53
|
+
/**
|
|
54
|
+
* The path that `relative` names under the folder `root`, resolved, or null when that path is not inside `root`.
|
|
55
|
+
* The paths are compared resolved, with the separator after the folder's own path, so a sibling folder whose name
|
|
56
|
+
* starts with the folder's (`/srv/memory-old` beside `/srv/memory`) is not inside it, and neither is the folder
|
|
57
|
+
* itself. The check is on the path as written: a link inside the folder is not followed.
|
|
58
|
+
*
|
|
59
|
+
* @param root - The folder.
|
|
60
|
+
* @param relative - The parts of the path under `root`, in order, as `path.resolve` takes them.
|
|
61
|
+
* @param paths - The path functions to resolve with: the platform's by default, `path.win32` or `path.posix` to
|
|
62
|
+
* pick one.
|
|
63
|
+
* @returns The absolute path, or null when it is outside `root`.
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveInsideFolder(root: string, relative: readonly string[], paths?: Pick<path.PlatformPath, 'resolve' | 'sep'>): string | null;
|
|
66
|
+
//# sourceMappingURL=pathName.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathName.d.ts","sourceRoot":"","sources":["../../../src/core/utils/pathName.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;AAmBhF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAK1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAWpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,KAAK,GAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,CAAQ,GACvD,MAAM,GAAG,IAAI,CAKf"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The rule for a file or folder name built from data, and the check that a path built from such
|
|
3
|
+
* names lies inside its folder.
|
|
4
|
+
*
|
|
5
|
+
* The memory wiki builds a page's path from its id, the Markdown and Obsidian memory exporters build a trace's
|
|
6
|
+
* path from its scope, type and id, and the skill exporter builds a forged tool's folder from its name. Those
|
|
7
|
+
* values come from files, imports and models, so every name taken from them is checked against one rule here,
|
|
8
|
+
* and every path built from them is checked to lie inside the folder it is written to.
|
|
9
|
+
*
|
|
10
|
+
* @module agentos/core/utils/pathName
|
|
11
|
+
*/
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
/**
|
|
14
|
+
* The most bytes, in UTF-8, one name may hold. Linux allows 255 bytes in a name, and Windows usually 255 UTF-16
|
|
15
|
+
* code units; a name never holds more code units than bytes, so 200 fits both and leaves room for the extension a
|
|
16
|
+
* caller adds, such as `.md`.
|
|
17
|
+
*/
|
|
18
|
+
export const MAX_PATH_NAME_BYTES = 200;
|
|
19
|
+
/** The slash's code: the folder separator everywhere. */
|
|
20
|
+
const SLASH = 0x2f;
|
|
21
|
+
/** The backslash's code: a folder separator on Windows. */
|
|
22
|
+
const BACKSLASH = 0x5c;
|
|
23
|
+
/** The colon's code: on Windows it names a drive (`C:name`) or a file's stream (`name:stream`). */
|
|
24
|
+
const COLON = 0x3a;
|
|
25
|
+
/** The codes of `"`, `*`, `<`, `>`, `?` and `|`, which Windows refuses in a name. */
|
|
26
|
+
const WINDOWS_RESERVED = new Set([0x22, 0x2a, 0x3c, 0x3e, 0x3f, 0x7c]);
|
|
27
|
+
const utf8 = new TextEncoder();
|
|
28
|
+
/** The most characters of a refused name that an error message shows. */
|
|
29
|
+
const SHOWN_NAME_CHARACTERS = 64;
|
|
30
|
+
/**
|
|
31
|
+
* A refused value as an error message shows it: a string quoted and escaped, cut to its first 64 characters, or
|
|
32
|
+
* the type of any other value.
|
|
33
|
+
*
|
|
34
|
+
* @param value - The refused value.
|
|
35
|
+
*/
|
|
36
|
+
export function describeRefusedName(value) {
|
|
37
|
+
if (typeof value !== 'string')
|
|
38
|
+
return `of type ${value === null ? 'null' : typeof value}`;
|
|
39
|
+
return JSON.stringify(value.length > SHOWN_NAME_CHARACTERS ? `${value.slice(0, SHOWN_NAME_CHARACTERS)}...` : value);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* True when the character whose UTF-16 code is `code` may appear neither in a name nor anywhere in a path whose
|
|
43
|
+
* names are joined with `/`: a backslash, a colon, one of `"`, `*`, `<`, `>`, `?` and `|`, or a control character
|
|
44
|
+
* (U+0000 to U+001F, or U+007F).
|
|
45
|
+
*/
|
|
46
|
+
export function isRefusedPathCharacter(code) {
|
|
47
|
+
return code <= 0x1f || code === 0x7f || code === BACKSLASH || code === COLON || WINDOWS_RESERVED.has(code);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The part of the name rule `name` breaks, or null when `name` may name one file or folder. A name the rule
|
|
51
|
+
* accepts holds no separator, is never `.` or `..`, and names no drive or file stream, so a path built from such
|
|
52
|
+
* names stays under the folder it starts from.
|
|
53
|
+
*
|
|
54
|
+
* @param name - The name to check.
|
|
55
|
+
*/
|
|
56
|
+
export function pathNameProblem(name) {
|
|
57
|
+
if (name.length === 0)
|
|
58
|
+
return 'empty';
|
|
59
|
+
for (let i = 0; i < name.length; i++) {
|
|
60
|
+
const code = name.charCodeAt(i);
|
|
61
|
+
if (code === SLASH || isRefusedPathCharacter(code))
|
|
62
|
+
return 'character';
|
|
63
|
+
}
|
|
64
|
+
if (name.startsWith('.'))
|
|
65
|
+
return 'dot';
|
|
66
|
+
if (name.startsWith(' ') || name.endsWith(' ') || name.endsWith('.'))
|
|
67
|
+
return 'edge';
|
|
68
|
+
// A string never has more UTF-16 code units than UTF-8 bytes, so a long one is refused before it is encoded.
|
|
69
|
+
if (name.length > MAX_PATH_NAME_BYTES || utf8.encode(name).byteLength > MAX_PATH_NAME_BYTES)
|
|
70
|
+
return 'length';
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The path that `relative` names under the folder `root`, resolved, or null when that path is not inside `root`.
|
|
75
|
+
* The paths are compared resolved, with the separator after the folder's own path, so a sibling folder whose name
|
|
76
|
+
* starts with the folder's (`/srv/memory-old` beside `/srv/memory`) is not inside it, and neither is the folder
|
|
77
|
+
* itself. The check is on the path as written: a link inside the folder is not followed.
|
|
78
|
+
*
|
|
79
|
+
* @param root - The folder.
|
|
80
|
+
* @param relative - The parts of the path under `root`, in order, as `path.resolve` takes them.
|
|
81
|
+
* @param paths - The path functions to resolve with: the platform's by default, `path.win32` or `path.posix` to
|
|
82
|
+
* pick one.
|
|
83
|
+
* @returns The absolute path, or null when it is outside `root`.
|
|
84
|
+
*/
|
|
85
|
+
export function resolveInsideFolder(root, relative, paths = path) {
|
|
86
|
+
const folder = paths.resolve(root);
|
|
87
|
+
const file = paths.resolve(folder, ...relative);
|
|
88
|
+
const inside = folder.endsWith(paths.sep) ? folder : folder + paths.sep;
|
|
89
|
+
return file.startsWith(inside) ? file : null;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=pathName.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathName.js","sourceRoot":"","sources":["../../../src/core/utils/pathName.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@framers/agentos",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.66",
|
|
4
4
|
"description": "AgentOS: open-source TypeScript framework for autonomous AI agents. Unified graph orchestration, cognitive memory, runtime tool forging, multi-tier guardrails, voice pipeline, and 11 LLM providers.",
|
|
5
5
|
"homepage": "https://agentos.sh",
|
|
6
6
|
"repository": {
|