@jini-ai/platform 0.5.8 → 0.5.9
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/CHANGELOG.md +5 -0
- package/dist/fs/atomic-write.d.ts +25 -2
- package/dist/fs/atomic-write.js +59 -20
- package/dist/fs/durable-json.d.ts +3 -1
- package/dist/fs/durable-json.js +6 -3
- package/dist/fs/verified-directory-move.d.ts +2 -1
- package/dist/fs/verified-directory-move.js +6 -17
- package/dist/fs/verified-file-relocation.d.ts +2 -1
- package/dist/fs/verified-file-relocation.js +4 -9
- package/dist/web/web-page.d.ts +1 -1
- package/dist/web/web-page.js +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# @jini-ai/platform
|
|
2
2
|
|
|
3
|
+
## 0.5.9 — 2026-10-16
|
|
4
|
+
|
|
5
|
+
- `fs`: best-effort directory fsync, so Windows site creation stops failing with EPERM (87720117).
|
|
6
|
+
- `./web` fetch default window is 20,000 characters so one result fits an MCP budget (939300e3).
|
|
7
|
+
|
|
3
8
|
## 0.5.8 — 2026-10-15
|
|
4
9
|
|
|
5
10
|
- SECURITY: the guarded HTTP client forwards only `accept`, `accept-language` and `user-agent` on a cross-origin redirect (4de69b67). It used to strip only Authorization/Cookie, so custom credential headers (`x-api-key`, `X-Shopify-Access-Token`, …) followed a redirect to another origin. Same-origin hops keep all headers.
|
|
@@ -72,10 +72,33 @@ export interface AtomicWriteOptions {
|
|
|
72
72
|
export declare function createNodeAtomicFilesystem(_required: Record<string, never>, { filesystem }?: {
|
|
73
73
|
filesystem?: AtomicNativeFilesystem;
|
|
74
74
|
}): AtomicFilesystemPort;
|
|
75
|
+
/** Flush directory metadata where supported; Windows cannot fsync directory handles.
|
|
76
|
+
* Unsupported open/sync errors are ignored because replacement has already landed.
|
|
77
|
+
* Other failures propagate, and an opened descriptor is always closed.
|
|
78
|
+
* @complexity O(1) filesystem calls and space.
|
|
79
|
+
*/
|
|
80
|
+
export declare function syncDirectoryBestEffort({ directory, open, sync, close }: {
|
|
81
|
+
directory: string;
|
|
82
|
+
open: (path: string, flags: "r") => number;
|
|
83
|
+
sync: (descriptor: number) => void;
|
|
84
|
+
close: (descriptor: number) => void;
|
|
85
|
+
}, { platform }: {
|
|
86
|
+
platform: NodeJS.Platform;
|
|
87
|
+
}): void;
|
|
88
|
+
/** Async directory flush with the same unsupported-error and handle-ownership contract.
|
|
89
|
+
* @complexity O(1) filesystem calls and space.
|
|
90
|
+
*/
|
|
91
|
+
export declare function syncDirectoryBestEffortAsync({ directory, open }: {
|
|
92
|
+
directory: string;
|
|
93
|
+
open: (path: string, flags: "r") => Promise<Pick<fsPromises.FileHandle, "sync" | "close">>;
|
|
94
|
+
}, { platform }: {
|
|
95
|
+
platform: NodeJS.Platform;
|
|
96
|
+
}): Promise<void>;
|
|
75
97
|
/** Same-directory rename; preserve existing mode exactly, default new files to 0600.
|
|
76
98
|
* Only ENOENT means absent. Stat/write/chmod failures propagate before any rename.
|
|
77
|
-
* Flush file bytes before rename so metadata cannot precede content;
|
|
78
|
-
*
|
|
99
|
+
* Flush file bytes before rename so metadata cannot precede content; directory flush is best-effort:
|
|
100
|
+
* skip Windows and ignore unsupported-code failures (EPERM/EISDIR/EINVAL/EACCES/ENOTSUP).
|
|
101
|
+
* Other directory-flush failures are reported after replacement, because rename cannot be rolled back safely.
|
|
79
102
|
*/
|
|
80
103
|
export declare function writeFileAtomic(required: AtomicWriteRequired, options?: AtomicWriteOptions): void;
|
|
81
104
|
/** Pretty JSON delegates to the same mode-preserving atomic primitive. */
|
package/dist/fs/atomic-write.js
CHANGED
|
@@ -42,18 +42,65 @@ function assertNotSymlink(info, options) {
|
|
|
42
42
|
if (info.isSymbolicLink())
|
|
43
43
|
throw new Error((options.messages ?? defaultPlatformMessages).atomicSymlinkRefused());
|
|
44
44
|
}
|
|
45
|
-
function assertOwnerOnly(mode, options) {
|
|
45
|
+
function assertOwnerOnly(mode, options, platform) {
|
|
46
46
|
// Windows has no POSIX group/other bits; secret stores skip this verification there.
|
|
47
|
-
if (options.verifyOwnerOnly &&
|
|
47
|
+
if (options.verifyOwnerOnly && platform !== "win32" && (mode & 0o077) !== 0)
|
|
48
48
|
throw new Error((options.messages ?? defaultPlatformMessages).atomicPermissionsRefused());
|
|
49
49
|
}
|
|
50
|
+
function isDirectorySyncUnsupported(error) {
|
|
51
|
+
return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" && ["EPERM", "EISDIR", "EINVAL", "EACCES", "ENOTSUP"].includes(error.code);
|
|
52
|
+
}
|
|
53
|
+
/** Flush directory metadata where supported; Windows cannot fsync directory handles.
|
|
54
|
+
* Unsupported open/sync errors are ignored because replacement has already landed.
|
|
55
|
+
* Other failures propagate, and an opened descriptor is always closed.
|
|
56
|
+
* @complexity O(1) filesystem calls and space.
|
|
57
|
+
*/
|
|
58
|
+
export function syncDirectoryBestEffort({ directory, open, sync, close }, { platform }) {
|
|
59
|
+
if (platform === "win32")
|
|
60
|
+
return;
|
|
61
|
+
let descriptor;
|
|
62
|
+
try {
|
|
63
|
+
descriptor = open(directory, "r");
|
|
64
|
+
sync(descriptor);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (!isDirectorySyncUnsupported(error))
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
if (descriptor !== undefined)
|
|
72
|
+
close(descriptor);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Async directory flush with the same unsupported-error and handle-ownership contract.
|
|
76
|
+
* @complexity O(1) filesystem calls and space.
|
|
77
|
+
*/
|
|
78
|
+
export async function syncDirectoryBestEffortAsync({ directory, open }, { platform }) {
|
|
79
|
+
if (platform === "win32")
|
|
80
|
+
return;
|
|
81
|
+
let handle;
|
|
82
|
+
try {
|
|
83
|
+
handle = await open(directory, "r");
|
|
84
|
+
await handle.sync();
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (!isDirectorySyncUnsupported(error))
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
if (handle !== undefined)
|
|
92
|
+
await handle.close();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
50
95
|
/** Same-directory rename; preserve existing mode exactly, default new files to 0600.
|
|
51
96
|
* Only ENOENT means absent. Stat/write/chmod failures propagate before any rename.
|
|
52
|
-
* Flush file bytes before rename so metadata cannot precede content;
|
|
53
|
-
*
|
|
97
|
+
* Flush file bytes before rename so metadata cannot precede content; directory flush is best-effort:
|
|
98
|
+
* skip Windows and ignore unsupported-code failures (EPERM/EISDIR/EINVAL/EACCES/ENOTSUP).
|
|
99
|
+
* Other directory-flush failures are reported after replacement, because rename cannot be rolled back safely.
|
|
54
100
|
*/
|
|
55
101
|
export function writeFileAtomic(required, options = {}) {
|
|
56
102
|
const { filePath, content, fs: filesystem } = required;
|
|
103
|
+
const platform = options.platform ?? process.platform;
|
|
57
104
|
let existingMode;
|
|
58
105
|
try {
|
|
59
106
|
if (options.refuseSymlink) {
|
|
@@ -77,7 +124,7 @@ export function writeFileAtomic(required, options = {}) {
|
|
|
77
124
|
try {
|
|
78
125
|
filesystem.write({ descriptor, content });
|
|
79
126
|
filesystem.chmod({ path: temporary, mode });
|
|
80
|
-
assertOwnerOnly(filesystem.stat({ path: temporary }).mode, options);
|
|
127
|
+
assertOwnerOnly(filesystem.stat({ path: temporary }).mode, options, platform);
|
|
81
128
|
filesystem.sync({ descriptor });
|
|
82
129
|
const fileDescriptor = descriptor;
|
|
83
130
|
descriptor = undefined;
|
|
@@ -93,13 +140,10 @@ export function writeFileAtomic(required, options = {}) {
|
|
|
93
140
|
}
|
|
94
141
|
filesystem.rename({ from: temporary, to: filePath });
|
|
95
142
|
renamed = true;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
filesystem.sync({ descriptor:
|
|
99
|
-
}
|
|
100
|
-
finally {
|
|
101
|
-
filesystem.close({ descriptor: directory });
|
|
102
|
-
}
|
|
143
|
+
syncDirectoryBestEffort({ directory: path.dirname(filePath),
|
|
144
|
+
open: (path, flags) => filesystem.open({ path, flags }),
|
|
145
|
+
sync: descriptor => filesystem.sync({ descriptor }), close: descriptor => filesystem.close({ descriptor }),
|
|
146
|
+
}, { platform });
|
|
103
147
|
}
|
|
104
148
|
catch (error) {
|
|
105
149
|
if (descriptor !== undefined) {
|
|
@@ -129,6 +173,7 @@ export function writeJsonFileAtomic(required, options = {}) {
|
|
|
129
173
|
* Parent creation supports runtime-state and secret stores without another writer implementation. */
|
|
130
174
|
export async function writeFileAtomicAsync(required, options = {}) {
|
|
131
175
|
const { filePath, content } = required;
|
|
176
|
+
const platform = options.platform ?? process.platform;
|
|
132
177
|
const filesystem = options.fs ?? fsPromises;
|
|
133
178
|
if (options.createParent)
|
|
134
179
|
await filesystem.mkdir(path.dirname(filePath), { recursive: true });
|
|
@@ -151,7 +196,7 @@ export async function writeFileAtomicAsync(required, options = {}) {
|
|
|
151
196
|
try {
|
|
152
197
|
await handle.writeFile(content, "utf8");
|
|
153
198
|
await handle.chmod(mode);
|
|
154
|
-
assertOwnerOnly((await handle.stat()).mode, options);
|
|
199
|
+
assertOwnerOnly((await handle.stat()).mode, options, platform);
|
|
155
200
|
await handle.sync();
|
|
156
201
|
await handle.close();
|
|
157
202
|
closed = true;
|
|
@@ -166,13 +211,7 @@ export async function writeFileAtomicAsync(required, options = {}) {
|
|
|
166
211
|
}
|
|
167
212
|
await filesystem.rename(temporary, filePath);
|
|
168
213
|
renamed = true;
|
|
169
|
-
|
|
170
|
-
try {
|
|
171
|
-
await directory.sync();
|
|
172
|
-
}
|
|
173
|
-
finally {
|
|
174
|
-
await directory.close();
|
|
175
|
-
}
|
|
214
|
+
await syncDirectoryBestEffortAsync({ directory: path.dirname(filePath), open: (path, flags) => filesystem.open(path, flags) }, { platform });
|
|
176
215
|
}
|
|
177
216
|
catch (error) {
|
|
178
217
|
if (!closed) {
|
|
@@ -74,7 +74,9 @@ export interface DurableJsonFile {
|
|
|
74
74
|
}
|
|
75
75
|
/** Atomic replacement, distinct corrupt reads, quarantine, and token-owned synchronous locks.
|
|
76
76
|
* Lock stealing rechecks inode, bytes and mtime; conditional unlink is not available on all hosts.
|
|
77
|
-
* File fsync precedes rename; directory
|
|
77
|
+
* File fsync precedes rename; directory flush afterwards is best-effort: skipped on Windows,
|
|
78
|
+
* unsupported-code failures ignored (EPERM/EISDIR/EINVAL/EACCES/ENOTSUP), other failures reported
|
|
79
|
+
* after replacement. Persistence remains filesystem-dependent.
|
|
78
80
|
*/
|
|
79
81
|
export declare function createDurableJsonFile({ filePath, filesystem: fs, clock, sleep, process, random, report, notices }: DurableJsonPorts & {
|
|
80
82
|
filePath: string;
|
package/dist/fs/durable-json.js
CHANGED
|
@@ -36,7 +36,9 @@ export function createNodeDurableJsonPorts(_required) {
|
|
|
36
36
|
}
|
|
37
37
|
/** Atomic replacement, distinct corrupt reads, quarantine, and token-owned synchronous locks.
|
|
38
38
|
* Lock stealing rechecks inode, bytes and mtime; conditional unlink is not available on all hosts.
|
|
39
|
-
* File fsync precedes rename; directory
|
|
39
|
+
* File fsync precedes rename; directory flush afterwards is best-effort: skipped on Windows,
|
|
40
|
+
* unsupported-code failures ignored (EPERM/EISDIR/EINVAL/EACCES/ENOTSUP), other failures reported
|
|
41
|
+
* after replacement. Persistence remains filesystem-dependent.
|
|
40
42
|
*/
|
|
41
43
|
export function createDurableJsonFile({ filePath, filesystem: fs, clock, sleep, process, random, report, notices }, { pollMs = 10, staleMs = 30000 } = {}) {
|
|
42
44
|
if (!filePath)
|
|
@@ -70,8 +72,9 @@ export function createDurableJsonFile({ filePath, filesystem: fs, clock, sleep,
|
|
|
70
72
|
return `${filePath}.${pid}.tmp`;
|
|
71
73
|
}
|
|
72
74
|
// Same-directory rename gives readers complete old/new versions rather than a torn intermediate.
|
|
73
|
-
// Flush bytes before rename so metadata cannot precede content. The canonical writer
|
|
74
|
-
//
|
|
75
|
+
// Flush bytes before rename so metadata cannot precede content. The canonical writer's parent
|
|
76
|
+
// directory flush is best-effort: skipped on Windows, unsupported-code failures ignored
|
|
77
|
+
// (EPERM/EISDIR/EINVAL/EACCES/ENOTSUP), other failures reported after replacement.
|
|
75
78
|
// Keep the legacy temp path, pretty JSON bytes and new-file create mode for these shared stores.
|
|
76
79
|
function writeJson(filePath, value) {
|
|
77
80
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
@@ -19,7 +19,7 @@ export declare function moveDirectoryVerified({ from, to, commit }: {
|
|
|
19
19
|
from: string;
|
|
20
20
|
to: string;
|
|
21
21
|
commit: () => void;
|
|
22
|
-
}, { excluded, filesystem, prepareDestination, relocateFiles, verifyFile, backupId }?: {
|
|
22
|
+
}, { excluded, filesystem, prepareDestination, relocateFiles, verifyFile, backupId, platform }?: {
|
|
23
23
|
excluded?: readonly string[];
|
|
24
24
|
filesystem?: typeof fs;
|
|
25
25
|
prepareDestination?: (required: {
|
|
@@ -33,5 +33,6 @@ export declare function moveDirectoryVerified({ from, to, commit }: {
|
|
|
33
33
|
path: string;
|
|
34
34
|
}) => string;
|
|
35
35
|
backupId?: () => string;
|
|
36
|
+
platform?: NodeJS.Platform;
|
|
36
37
|
}): void;
|
|
37
38
|
//# sourceMappingURL=verified-directory-move.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { stageVerifiedFileRelocation } from "./verified-file-relocation.js";
|
|
2
|
+
import { syncDirectoryBestEffort } from "./atomic-write.js";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -45,7 +46,7 @@ export function directoryFingerprint({ dir }, { excluded = [], filesystem = fs }
|
|
|
45
46
|
* Same-filesystem failures roll the rename back. Commit must atomically update the host registry.
|
|
46
47
|
* @complexity O(bytes + entries log entries), with two verification passes.
|
|
47
48
|
*/
|
|
48
|
-
export function moveDirectoryVerified({ from, to, commit }, { excluded = [], filesystem = fs, prepareDestination, relocateFiles, verifyFile, backupId = randomUUID } = {}) {
|
|
49
|
+
export function moveDirectoryVerified({ from, to, commit }, { excluded = [], filesystem = fs, prepareDestination, relocateFiles, verifyFile, backupId = randomUUID, platform = process.platform } = {}) {
|
|
49
50
|
const source = filesystem.realpathSync(from);
|
|
50
51
|
const target = path.resolve(to);
|
|
51
52
|
if (target === source || target.startsWith(source + path.sep))
|
|
@@ -88,7 +89,7 @@ export function moveDirectoryVerified({ from, to, commit }, { excluded = [], fil
|
|
|
88
89
|
if (relocateFiles) {
|
|
89
90
|
if (!verifyFile)
|
|
90
91
|
throw new Error("File relocation requires a verification port.");
|
|
91
|
-
staged = stageVerifiedFileRelocation({ groups: relocateFiles({ source, target }), verify: verifyFile }, { filesystem, backupId, backupCovered: ({ from }) => copied && path.resolve(from).startsWith(target + path.sep) });
|
|
92
|
+
staged = stageVerifiedFileRelocation({ groups: relocateFiles({ source, target }), verify: verifyFile }, { filesystem, backupId, platform, backupCovered: ({ from }) => copied && path.resolve(from).startsWith(target + path.sep) });
|
|
92
93
|
}
|
|
93
94
|
if (copied) {
|
|
94
95
|
const backupRoot = path.join(path.dirname(source), `.relocation-${backupId()}-backup`);
|
|
@@ -100,23 +101,11 @@ export function moveDirectoryVerified({ from, to, commit }, { excluded = [], fil
|
|
|
100
101
|
filesystem.mkdirSync(backupRoot);
|
|
101
102
|
filesystem.renameSync(source, backup);
|
|
102
103
|
retiredSource = backup;
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
filesystem.fsyncSync(fd);
|
|
106
|
-
}
|
|
107
|
-
finally {
|
|
108
|
-
filesystem.closeSync(fd);
|
|
109
|
-
}
|
|
104
|
+
syncDirectoryBestEffort({ directory: backupRoot, open: filesystem.openSync, sync: filesystem.fsyncSync, close: filesystem.closeSync }, { platform });
|
|
110
105
|
}
|
|
111
|
-
//
|
|
106
|
+
// Where supported, persist directory-name changes for same-filesystem renames as well as EXDEV retirement.
|
|
112
107
|
for (const directory of new Set([path.dirname(source), path.dirname(target)])) {
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
filesystem.fsyncSync(fd);
|
|
116
|
-
}
|
|
117
|
-
finally {
|
|
118
|
-
filesystem.closeSync(fd);
|
|
119
|
-
}
|
|
108
|
+
syncDirectoryBestEffort({ directory, open: filesystem.openSync, sync: filesystem.fsyncSync, close: filesystem.closeSync }, { platform });
|
|
120
109
|
}
|
|
121
110
|
commit();
|
|
122
111
|
}
|
|
@@ -14,12 +14,13 @@ export declare function stageVerifiedFileRelocation({ groups, verify }: {
|
|
|
14
14
|
verify: (required: {
|
|
15
15
|
path: string;
|
|
16
16
|
}) => string;
|
|
17
|
-
}, { filesystem, backupCovered, backupId }?: {
|
|
17
|
+
}, { filesystem, backupCovered, backupId, platform }?: {
|
|
18
18
|
filesystem?: typeof fs;
|
|
19
19
|
backupCovered?: (required: {
|
|
20
20
|
from: string;
|
|
21
21
|
}) => boolean;
|
|
22
22
|
backupId?: () => string;
|
|
23
|
+
platform?: NodeJS.Platform;
|
|
23
24
|
}): {
|
|
24
25
|
rollback: () => void;
|
|
25
26
|
finalize: () => void;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { syncDirectoryBestEffort } from "./atomic-write.js";
|
|
4
5
|
/** Stage related files together while both directory identities are reserved by the host. Raw
|
|
5
6
|
* sources remain intact through inspection so even WAL/SHM bytes are retained. Verification opens only
|
|
6
7
|
* stopped databases through an injected read-only inspector; the filesystem owner never uses SQL.
|
|
7
8
|
* @complexity O(total bytes + verification cost), bounded memory via native file copies.
|
|
8
9
|
*/
|
|
9
|
-
export function stageVerifiedFileRelocation({ groups, verify }, { filesystem = fs, backupCovered = () => false, backupId = randomUUID } = {}) {
|
|
10
|
+
export function stageVerifiedFileRelocation({ groups, verify }, { filesystem = fs, backupCovered = () => false, backupId = randomUUID, platform = process.platform } = {}) {
|
|
10
11
|
const created = [], retired = [], markers = [], redundantBackups = [];
|
|
11
12
|
const backupSuffix = `.relocation-${backupId()}-backup`;
|
|
12
13
|
const copyExclusive = (from, to) => {
|
|
@@ -26,14 +27,8 @@ export function stageVerifiedFileRelocation({ groups, verify }, { filesystem = f
|
|
|
26
27
|
syncParent(to);
|
|
27
28
|
};
|
|
28
29
|
const syncParent = (file) => {
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
filesystem.fsyncSync(fd);
|
|
33
|
-
}
|
|
34
|
-
finally {
|
|
35
|
-
filesystem.closeSync(fd);
|
|
36
|
-
}
|
|
30
|
+
// Where supported, directory fsync persists retirement/marker ordering before the host commits its catalog.
|
|
31
|
+
syncDirectoryBestEffort({ directory: path.dirname(file), open: filesystem.openSync, sync: filesystem.fsyncSync, close: filesystem.closeSync }, { platform });
|
|
37
32
|
};
|
|
38
33
|
const rollback = () => {
|
|
39
34
|
for (const item of [...retired].reverse()) {
|
package/dist/web/web-page.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { type PageImage, type PageLink } from "./html-document.js";
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const WEB_FETCH_FORMATS: readonly ["markdown", "text", "html", "raw"];
|
|
11
11
|
export type WebFetchFormat = (typeof WEB_FETCH_FORMATS)[number];
|
|
12
|
-
export declare const DEFAULT_MAX_CHARS =
|
|
12
|
+
export declare const DEFAULT_MAX_CHARS = 20000;
|
|
13
13
|
export declare const MAX_MAX_CHARS = 200000;
|
|
14
14
|
export declare const MAX_URL_LENGTH = 2048;
|
|
15
15
|
export declare const DEFAULT_TIMEOUT_MS = 15000;
|
package/dist/web/web-page.js
CHANGED
|
@@ -10,7 +10,8 @@ import { htmlToText, readHtmlDocument, stripActiveHtml, MAX_LINKS, MAX_IMAGES }
|
|
|
10
10
|
* This module only pre-validates the URL so the common mistakes get a precise message.
|
|
11
11
|
*/
|
|
12
12
|
export const WEB_FETCH_FORMATS = ["markdown", "text", "html", "raw"];
|
|
13
|
-
|
|
13
|
+
// Leave room for page facts inside an agent CLI's MCP result budget.
|
|
14
|
+
export const DEFAULT_MAX_CHARS = 20_000;
|
|
14
15
|
export const MAX_MAX_CHARS = 200_000;
|
|
15
16
|
export const MAX_URL_LENGTH = 2048;
|
|
16
17
|
export const DEFAULT_TIMEOUT_MS = 15_000;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/platform",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
4
4
|
"description": "Generic OS/platform primitives: process exec and lifecycle, filesystem containment, HTTP readiness polling, toolchain discovery, blob storage, AWS signing, and an SSRF-safe asset cache.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|