@jini-ai/core 0.4.3 → 0.4.5
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 +8 -0
- package/dist/fetch/cache.js +12 -6
- package/dist/records.d.ts +24 -0
- package/dist/records.js +21 -0
- package/dist/registration-kit.d.ts +1 -16
- package/dist/registration-kit.js +2 -13
- package/package.json +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @jini-ai/core
|
|
2
2
|
|
|
3
|
+
## 0.4.5 — 2026-10-13
|
|
4
|
+
|
|
5
|
+
- `FetchQueryCache`: a `replace()` that lands after a read's transport resolves but before publication now wins; arbitration and publication share one continuation.
|
|
6
|
+
|
|
7
|
+
## 0.4.4 — 2026-10-12
|
|
8
|
+
|
|
9
|
+
- New `./records` subpath exports `isRecord` and `isNonArrayRecord` without loading the core barrel; the root and `registration-kit` keep re-exporting both.
|
|
10
|
+
|
|
3
11
|
## 0.4.2 — pending release
|
|
4
12
|
|
|
5
13
|
- Add source-backed `./plugin-directory` publisher identity and live metadata lookup. Warn and omit invalid advisory keywords; scope legacy `unknown/<name>` IDs to each plugin family, with optional family selection for ambiguous lookups.
|
package/dist/fetch/cache.js
CHANGED
|
@@ -91,20 +91,26 @@ export class FetchQueryCache {
|
|
|
91
91
|
this.publish(entry, { ...entry.state, isFetching: false });
|
|
92
92
|
return this.runOnline({ run });
|
|
93
93
|
}).then(value => {
|
|
94
|
-
const data = replacement === entry.replacement ? value : entry.state.data;
|
|
95
94
|
// Undefined is never successful query data, including an initial or background read.
|
|
96
|
-
|
|
95
|
+
// Thrown here so the rejection path below handles it (a replacement still supersedes it).
|
|
96
|
+
if (value === undefined)
|
|
97
97
|
throw new Error(`${JSON.stringify(entry.key)} data is undefined`);
|
|
98
|
-
return
|
|
99
|
-
}).then(
|
|
98
|
+
return value;
|
|
99
|
+
}).then(value => {
|
|
100
100
|
// Only the current request may publish or clear invalidation. An older transport
|
|
101
101
|
// need not support abort: its callers follow the replacement request instead.
|
|
102
102
|
if (entry.pending !== pending)
|
|
103
103
|
return (entry.pending ?? entry.state.data);
|
|
104
|
+
// Arbitration and publication share this continuation: a microtask between them would
|
|
105
|
+
// let an older result overwrite a replacement accepted after arbitration.
|
|
106
|
+
if (replacement !== entry.replacement) {
|
|
107
|
+
this.publish(entry, { ...entry.state, isFetching: false });
|
|
108
|
+
return entry.state.data;
|
|
109
|
+
}
|
|
104
110
|
entry.updatedAt = this.clock.nowMs();
|
|
105
111
|
entry.invalidated = false;
|
|
106
|
-
this.publish(entry, { data, error: null, status: 'success', isFetching: false });
|
|
107
|
-
return
|
|
112
|
+
this.publish(entry, { data: value, error: null, status: 'success', isFetching: false });
|
|
113
|
+
return value;
|
|
108
114
|
}, error => {
|
|
109
115
|
if (entry.pending !== pending)
|
|
110
116
|
return (entry.pending ?? entry.state.data);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** @file Pure object-shape predicates shared by tool input readers and render-time decoders. */
|
|
2
|
+
/** Accept any non-null object, including arrays; never sanitizes or reads properties.
|
|
3
|
+
* @complexity O(1) time and space.
|
|
4
|
+
* @example isRecord({ value: [] }); // true
|
|
5
|
+
*/
|
|
6
|
+
export declare function isRecord(required: {
|
|
7
|
+
value: unknown;
|
|
8
|
+
}, _optional?: Record<string, never>): required is {
|
|
9
|
+
value: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Accepts non-null, non-array objects, including class instances and null-prototype records.
|
|
13
|
+
* This is a shape check, not plain-object validation or sanitization. Keep `isRecord`'s
|
|
14
|
+
* broader contract: existing tool readers deliberately continue to accept arrays.
|
|
15
|
+
* @param required.value - The untrusted value whose object shape is checked.
|
|
16
|
+
* @complexity O(1) time and space.
|
|
17
|
+
* @example isNonArrayRecord({ value: [] }); // false
|
|
18
|
+
*/
|
|
19
|
+
export declare function isNonArrayRecord(required: {
|
|
20
|
+
value: unknown;
|
|
21
|
+
}, _optional?: Record<string, never>): required is {
|
|
22
|
+
value: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=records.d.ts.map
|
package/dist/records.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** @file Pure object-shape predicates shared by tool input readers and render-time decoders. */
|
|
2
|
+
/** Accept any non-null object, including arrays; never sanitizes or reads properties.
|
|
3
|
+
* @complexity O(1) time and space.
|
|
4
|
+
* @example isRecord({ value: [] }); // true
|
|
5
|
+
*/
|
|
6
|
+
export function isRecord(required, _optional = {}) {
|
|
7
|
+
const { value } = required;
|
|
8
|
+
return typeof value === "object" && value !== null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Accepts non-null, non-array objects, including class instances and null-prototype records.
|
|
12
|
+
* This is a shape check, not plain-object validation or sanitization. Keep `isRecord`'s
|
|
13
|
+
* broader contract: existing tool readers deliberately continue to accept arrays.
|
|
14
|
+
* @param required.value - The untrusted value whose object shape is checked.
|
|
15
|
+
* @complexity O(1) time and space.
|
|
16
|
+
* @example isNonArrayRecord({ value: [] }); // false
|
|
17
|
+
*/
|
|
18
|
+
export function isNonArrayRecord(required, _optional = {}) {
|
|
19
|
+
return isRecord(required) && !Array.isArray(required.value);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { isRecord, isNonArrayRecord } from "./records.js";
|
|
1
2
|
/**
|
|
2
3
|
* @file The cross-domain half of the agent-tool wiring split: everything a domain's own
|
|
3
4
|
* `tool-registrations.ts` needs that is NOT specific to that domain.
|
|
@@ -134,22 +135,6 @@ export declare function indexCatalogById<T extends {
|
|
|
134
135
|
}>(required: {
|
|
135
136
|
catalog: readonly T[];
|
|
136
137
|
}, _optional?: Record<string, never>): ReadonlyMap<string, T>;
|
|
137
|
-
export declare function isRecord(required: {
|
|
138
|
-
value: unknown;
|
|
139
|
-
}, _optional?: Record<string, never>): required is {
|
|
140
|
-
value: Record<string, unknown>;
|
|
141
|
-
};
|
|
142
|
-
/**
|
|
143
|
-
* Accepts non-null, non-array objects, including class instances and null-prototype records.
|
|
144
|
-
* This is a shape check, not plain-object validation or sanitization. Keep `isRecord`'s
|
|
145
|
-
* broader contract: existing tool readers deliberately continue to accept arrays.
|
|
146
|
-
* @param required.value - The untrusted value whose object shape is checked.
|
|
147
|
-
*/
|
|
148
|
-
export declare function isNonArrayRecord(required: {
|
|
149
|
-
value: unknown;
|
|
150
|
-
}, _optional?: Record<string, never>): required is {
|
|
151
|
-
value: Record<string, unknown>;
|
|
152
|
-
};
|
|
153
138
|
/** Narrows `ctx.input` to a record, refusing anything else. The first line of most handlers. */
|
|
154
139
|
export declare function requireInputRecord(required: {
|
|
155
140
|
input: unknown;
|
package/dist/registration-kit.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isRecord } from "./records.js";
|
|
2
|
+
export { isRecord, isNonArrayRecord } from "./records.js";
|
|
1
3
|
/**
|
|
2
4
|
* @file The cross-domain half of the agent-tool wiring split: everything a domain's own
|
|
3
5
|
* `tool-registrations.ts` needs that is NOT specific to that domain.
|
|
@@ -100,19 +102,6 @@ export function indexCatalogById(required, _optional = {}) {
|
|
|
100
102
|
// ---------------------------------------------------------------------------
|
|
101
103
|
// Input readers — the vocabulary every handler uses to read `ctx.input`.
|
|
102
104
|
// ---------------------------------------------------------------------------
|
|
103
|
-
export function isRecord(required, _optional = {}) {
|
|
104
|
-
const { value } = required;
|
|
105
|
-
return typeof value === "object" && value !== null;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Accepts non-null, non-array objects, including class instances and null-prototype records.
|
|
109
|
-
* This is a shape check, not plain-object validation or sanitization. Keep `isRecord`'s
|
|
110
|
-
* broader contract: existing tool readers deliberately continue to accept arrays.
|
|
111
|
-
* @param required.value - The untrusted value whose object shape is checked.
|
|
112
|
-
*/
|
|
113
|
-
export function isNonArrayRecord(required, _optional = {}) {
|
|
114
|
-
return isRecord(required) && !Array.isArray(required.value);
|
|
115
|
-
}
|
|
116
105
|
/** Narrows `ctx.input` to a record, refusing anything else. The first line of most handlers. */
|
|
117
106
|
export function requireInputRecord(required, _optional = {}) {
|
|
118
107
|
const { input } = required;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "The Jini kernel: typed DI tokens, pack composition and lifecycle, the tool registry, redaction, and origin/API-token auth primitives. Zero dependencies.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"./model-facing-tool-errors": "universal",
|
|
20
20
|
"./contribution-registry": "universal",
|
|
21
21
|
"./naming": "universal",
|
|
22
|
+
"./records": "universal",
|
|
22
23
|
"./primitives": "universal",
|
|
23
24
|
"./fetch": "universal",
|
|
24
25
|
"./text": "universal",
|
|
@@ -42,7 +43,8 @@
|
|
|
42
43
|
]
|
|
43
44
|
},
|
|
44
45
|
"shared": [
|
|
45
|
-
"src/tool-permissions.ts"
|
|
46
|
+
"src/tool-permissions.ts",
|
|
47
|
+
"src/records.ts"
|
|
46
48
|
],
|
|
47
49
|
"forbidden": {
|
|
48
50
|
"universal": [
|
|
@@ -101,6 +103,11 @@
|
|
|
101
103
|
"import": "./dist/naming.js",
|
|
102
104
|
"default": "./dist/naming.js"
|
|
103
105
|
},
|
|
106
|
+
"./records": {
|
|
107
|
+
"types": "./dist/records.d.ts",
|
|
108
|
+
"import": "./dist/records.js",
|
|
109
|
+
"default": "./dist/records.js"
|
|
110
|
+
},
|
|
104
111
|
"./primitives": {
|
|
105
112
|
"types": "./dist/primitives/index.d.ts",
|
|
106
113
|
"import": "./dist/primitives/index.js",
|