@arnilo/prism 0.0.1
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 +31 -0
- package/LICENSE +21 -0
- package/README.md +139 -0
- package/dist/agents.d.ts +5 -0
- package/dist/agents.js +439 -0
- package/dist/cli-runner.d.ts +33 -0
- package/dist/cli-runner.js +167 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +10 -0
- package/dist/compaction.d.ts +9 -0
- package/dist/compaction.js +67 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +69 -0
- package/dist/contracts.d.ts +670 -0
- package/dist/contracts.js +2 -0
- package/dist/contributions.d.ts +35 -0
- package/dist/contributions.js +47 -0
- package/dist/credentials.d.ts +22 -0
- package/dist/credentials.js +63 -0
- package/dist/extensions.d.ts +25 -0
- package/dist/extensions.js +131 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +28 -0
- package/dist/input.d.ts +57 -0
- package/dist/input.js +225 -0
- package/dist/manifests.d.ts +28 -0
- package/dist/manifests.js +108 -0
- package/dist/middleware.d.ts +15 -0
- package/dist/middleware.js +49 -0
- package/dist/mock-provider.d.ts +6 -0
- package/dist/mock-provider.js +14 -0
- package/dist/models.d.ts +8 -0
- package/dist/models.js +25 -0
- package/dist/node/config.d.ts +9 -0
- package/dist/node/config.js +51 -0
- package/dist/node/session-store-jsonl.d.ts +17 -0
- package/dist/node/session-store-jsonl.js +134 -0
- package/dist/node/settings.d.ts +7 -0
- package/dist/node/settings.js +26 -0
- package/dist/node/trust.d.ts +13 -0
- package/dist/node/trust.js +56 -0
- package/dist/provider-events.d.ts +15 -0
- package/dist/provider-events.js +30 -0
- package/dist/provider-packages.d.ts +4 -0
- package/dist/provider-packages.js +12 -0
- package/dist/provider-request-policy.d.ts +9 -0
- package/dist/provider-request-policy.js +49 -0
- package/dist/providers/openai-compatible.d.ts +9 -0
- package/dist/providers/openai-compatible.js +197 -0
- package/dist/providers.d.ts +8 -0
- package/dist/providers.js +25 -0
- package/dist/redaction.d.ts +11 -0
- package/dist/redaction.js +68 -0
- package/dist/resources.d.ts +5 -0
- package/dist/resources.js +30 -0
- package/dist/retry.d.ts +11 -0
- package/dist/retry.js +48 -0
- package/dist/rpc.d.ts +18 -0
- package/dist/rpc.js +187 -0
- package/dist/security.d.ts +51 -0
- package/dist/security.js +60 -0
- package/dist/session-stores.d.ts +25 -0
- package/dist/session-stores.js +116 -0
- package/dist/settings.d.ts +3 -0
- package/dist/settings.js +26 -0
- package/dist/skills.d.ts +8 -0
- package/dist/skills.js +34 -0
- package/dist/system-prompts.d.ts +6 -0
- package/dist/system-prompts.js +47 -0
- package/dist/testing/provider-conformance.d.ts +36 -0
- package/dist/testing/provider-conformance.js +164 -0
- package/dist/tools.d.ts +25 -0
- package/dist/tools.js +109 -0
- package/docs/agent-session-runtime.md +167 -0
- package/docs/api-page-template.md +32 -0
- package/docs/cli-rpc.md +140 -0
- package/docs/compaction-and-retry.md +177 -0
- package/docs/compaction-llm.md +108 -0
- package/docs/compaction-observational-memory.md +123 -0
- package/docs/configuration-and-manifests.md +142 -0
- package/docs/context-and-skills.md +113 -0
- package/docs/contribution-registries.md +118 -0
- package/docs/credentials-and-redaction.md +122 -0
- package/docs/extensions.md +139 -0
- package/docs/index.md +56 -0
- package/docs/input-and-prompt-assembly.md +168 -0
- package/docs/middleware-hooks.md +123 -0
- package/docs/node-filesystem-config.md +85 -0
- package/docs/node-jsonl-session-store.md +81 -0
- package/docs/provider-conformance.md +109 -0
- package/docs/provider-layer.md +172 -0
- package/docs/provider-packages.md +171 -0
- package/docs/providers/kimi.md +110 -0
- package/docs/providers/openai-compatible.md +125 -0
- package/docs/providers/openai.md +131 -0
- package/docs/providers/opencode-go.md +103 -0
- package/docs/providers/openrouter.md +105 -0
- package/docs/providers/zai.md +108 -0
- package/docs/public-contracts.md +375 -0
- package/docs/release-and-install.md +141 -0
- package/docs/resource-loading.md +97 -0
- package/docs/session-stores-and-branching.md +119 -0
- package/docs/settings-auth-trust-security.md +73 -0
- package/docs/system-prompts.md +116 -0
- package/docs/tools.md +151 -0
- package/package.json +93 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { createAgent, createMockProvider, providerDone, providerTextDelta } from "./index.js";
|
|
2
|
+
import { runRpcServer } from "./rpc.js";
|
|
3
|
+
export const usage = `Usage: prism [--mode print|json|rpc] [-p prompt] [options]
|
|
4
|
+
|
|
5
|
+
Options:
|
|
6
|
+
-p, --prompt <text> Prompt to run in print/json mode
|
|
7
|
+
--provider <name> Explicit provider id (mock is built in for smoke tests)
|
|
8
|
+
--model <name> Explicit model name
|
|
9
|
+
--session <id> Session id
|
|
10
|
+
--config <path> Explicit config path (recorded, not auto-loaded)
|
|
11
|
+
--resource <uri> Explicit resource URI (recorded, not auto-loaded)
|
|
12
|
+
--extension <name> Explicit extension name (recorded, not auto-loaded)
|
|
13
|
+
--tool <name> Explicit tool name (recorded, not auto-enabled)
|
|
14
|
+
--system <text> System instructions
|
|
15
|
+
--context <text> Context text
|
|
16
|
+
--compact <entries> Auto-compaction threshold
|
|
17
|
+
--max-tool-rounds <n> Maximum tool rounds
|
|
18
|
+
-h, --help Show this help
|
|
19
|
+
`;
|
|
20
|
+
const valueFlags = new Set(["--prompt", "--mode", "--provider", "--model", "--session", "--config", "--resource", "--extension", "--tool", "--system", "--context", "--compact", "--max-tool-rounds"]);
|
|
21
|
+
export function parseCliArgs(argv) {
|
|
22
|
+
let mode = "print";
|
|
23
|
+
let prompt;
|
|
24
|
+
let provider;
|
|
25
|
+
let model;
|
|
26
|
+
let session;
|
|
27
|
+
let system;
|
|
28
|
+
let compact;
|
|
29
|
+
let maxToolRounds;
|
|
30
|
+
let help = false;
|
|
31
|
+
const config = [];
|
|
32
|
+
const resources = [];
|
|
33
|
+
const extensions = [];
|
|
34
|
+
const tools = [];
|
|
35
|
+
const context = [];
|
|
36
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
37
|
+
const flag = argv[i];
|
|
38
|
+
if (flag === "-h" || flag === "--help") {
|
|
39
|
+
help = true;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const name = flag === "-p" ? "--prompt" : flag;
|
|
43
|
+
if (!valueFlags.has(name))
|
|
44
|
+
throw new CliUsageError(`Unknown flag: ${flag}`);
|
|
45
|
+
const value = argv[i + 1];
|
|
46
|
+
if (value === undefined || value.startsWith("--"))
|
|
47
|
+
throw new CliUsageError(`Missing value for ${flag}`);
|
|
48
|
+
i += 1;
|
|
49
|
+
switch (name) {
|
|
50
|
+
case "--prompt":
|
|
51
|
+
prompt = value;
|
|
52
|
+
break;
|
|
53
|
+
case "--mode":
|
|
54
|
+
if (value !== "print" && value !== "json" && value !== "rpc")
|
|
55
|
+
throw new CliUsageError(`Invalid mode: ${value}`);
|
|
56
|
+
mode = value;
|
|
57
|
+
break;
|
|
58
|
+
case "--provider":
|
|
59
|
+
provider = value;
|
|
60
|
+
break;
|
|
61
|
+
case "--model":
|
|
62
|
+
model = value;
|
|
63
|
+
break;
|
|
64
|
+
case "--session":
|
|
65
|
+
session = value;
|
|
66
|
+
break;
|
|
67
|
+
case "--config":
|
|
68
|
+
config.push(value);
|
|
69
|
+
break;
|
|
70
|
+
case "--resource":
|
|
71
|
+
resources.push(value);
|
|
72
|
+
break;
|
|
73
|
+
case "--extension":
|
|
74
|
+
extensions.push(value);
|
|
75
|
+
break;
|
|
76
|
+
case "--tool":
|
|
77
|
+
tools.push(value);
|
|
78
|
+
break;
|
|
79
|
+
case "--system":
|
|
80
|
+
system = value;
|
|
81
|
+
break;
|
|
82
|
+
case "--context":
|
|
83
|
+
context.push(value);
|
|
84
|
+
break;
|
|
85
|
+
case "--compact":
|
|
86
|
+
compact = positiveInt(value, flag);
|
|
87
|
+
break;
|
|
88
|
+
case "--max-tool-rounds":
|
|
89
|
+
maxToolRounds = positiveInt(value, flag);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { mode, prompt, provider, model, session, config, resources, extensions, tools, system, context, compact, maxToolRounds, help };
|
|
94
|
+
}
|
|
95
|
+
export async function runCli(argv, runtime) {
|
|
96
|
+
let options;
|
|
97
|
+
try {
|
|
98
|
+
options = parseCliArgs(argv);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
write(runtime.stderr, `${error instanceof Error ? error.message : String(error)}\n${usage}`);
|
|
102
|
+
return 2;
|
|
103
|
+
}
|
|
104
|
+
if (options.help) {
|
|
105
|
+
write(runtime.stdout, usage);
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
if (options.mode === "rpc") {
|
|
110
|
+
await runRpcServer({ stdin: runtime.stdin, stdout: runtime.stdout, createSession: (id) => (runtime.createSession ?? defaultCreateSession)({ ...options, session: id ?? options.session }), commands: runtime.commands });
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
if (!options.prompt)
|
|
114
|
+
throw new CliUsageError("Missing prompt: use -p or --prompt");
|
|
115
|
+
const session = (runtime.createSession ?? defaultCreateSession)(options);
|
|
116
|
+
await runPromptMode(session, options, runtime.stdout, options.mode);
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
121
|
+
if (error instanceof CliUsageError) {
|
|
122
|
+
write(runtime.stderr, `${message}\n${usage}`);
|
|
123
|
+
return 2;
|
|
124
|
+
}
|
|
125
|
+
if (options.mode === "json")
|
|
126
|
+
write(runtime.stdout, `${JSON.stringify({ type: "error", error: { message } })}\n`);
|
|
127
|
+
else
|
|
128
|
+
write(runtime.stderr, `${message}\n`);
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export async function runPromptMode(session, options, stdout, mode) {
|
|
133
|
+
const events = (async () => {
|
|
134
|
+
for await (const event of session.subscribe()) {
|
|
135
|
+
if (mode === "json")
|
|
136
|
+
write(stdout, `${JSON.stringify({ type: "event", sessionId: event.sessionId, runId: "runId" in event ? event.runId : undefined, event })}\n`);
|
|
137
|
+
else if (event.type === "message_delta" && event.content.type === "text")
|
|
138
|
+
write(stdout, event.content.text);
|
|
139
|
+
}
|
|
140
|
+
})();
|
|
141
|
+
await session.run(options.prompt ?? "", runOptions(options));
|
|
142
|
+
await events;
|
|
143
|
+
}
|
|
144
|
+
export class CliUsageError extends Error {
|
|
145
|
+
}
|
|
146
|
+
function defaultCreateSession(options) {
|
|
147
|
+
if (options.provider !== "mock")
|
|
148
|
+
throw new CliUsageError("No provider configured. Pass --provider mock for a smoke test or embed Prism with an explicit provider.");
|
|
149
|
+
const model = { provider: "mock", model: options.model ?? "mock" };
|
|
150
|
+
return createAgent({ model, provider: createMockProvider([providerTextDelta("Hello"), providerDone()]), instructions: options.system }).createSession({ id: options.session });
|
|
151
|
+
}
|
|
152
|
+
function runOptions(options) {
|
|
153
|
+
return {
|
|
154
|
+
maxToolRounds: options.maxToolRounds,
|
|
155
|
+
compaction: options.compact ? { thresholdEntries: options.compact } : undefined,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function positiveInt(value, flag) {
|
|
159
|
+
const parsed = Number(value);
|
|
160
|
+
if (!Number.isInteger(parsed) || parsed < 0)
|
|
161
|
+
throw new CliUsageError(`Invalid value for ${flag}: ${value}`);
|
|
162
|
+
return parsed;
|
|
163
|
+
}
|
|
164
|
+
function write(stream, text) {
|
|
165
|
+
stream.write(text);
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=cli-runner.js.map
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { runCli } from "./cli-runner.js";
|
|
4
|
+
const code = await runCli(process.argv.slice(2), {
|
|
5
|
+
stdin: process.stdin,
|
|
6
|
+
stdout: process.stdout,
|
|
7
|
+
stderr: process.stderr,
|
|
8
|
+
});
|
|
9
|
+
process.exitCode = code;
|
|
10
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CompactionEntryData, CompactionStrategy } from "./contracts.js";
|
|
2
|
+
export interface DefaultCompactionStrategyOptions {
|
|
3
|
+
readonly name?: string;
|
|
4
|
+
readonly keepRecentEntries?: number;
|
|
5
|
+
readonly maxSummaryChars?: number;
|
|
6
|
+
readonly secrets?: readonly (string | undefined)[];
|
|
7
|
+
}
|
|
8
|
+
export declare function createDefaultCompactionStrategy(options?: DefaultCompactionStrategyOptions): CompactionStrategy;
|
|
9
|
+
export declare function isCompactionEntryData(value: unknown): value is CompactionEntryData;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { redactSecrets } from "./redaction.js";
|
|
2
|
+
import { createSessionEntry } from "./session-stores.js";
|
|
3
|
+
export function createDefaultCompactionStrategy(options = {}) {
|
|
4
|
+
const name = options.name ?? "default-compaction";
|
|
5
|
+
return {
|
|
6
|
+
name,
|
|
7
|
+
compact(context) {
|
|
8
|
+
const keepRecentEntries = Math.max(0, context.keepRecentEntries ?? options.keepRecentEntries ?? 8);
|
|
9
|
+
const maxSummaryChars = Math.max(0, options.maxSummaryChars ?? 4000);
|
|
10
|
+
const messages = context.entries.filter((entry) => entry.kind === "message" && entry.message);
|
|
11
|
+
const keepEntryIds = keepRecentEntries === 0 ? [] : messages.slice(-keepRecentEntries).map((entry) => entry.id);
|
|
12
|
+
const firstKept = keepEntryIds[0];
|
|
13
|
+
const firstKeptIndex = firstKept ? context.entries.findIndex((entry) => entry.id === firstKept) : context.entries.length;
|
|
14
|
+
const oldEntries = context.entries.slice(0, firstKeptIndex < 0 ? context.entries.length : firstKeptIndex);
|
|
15
|
+
const throughEntryId = oldEntries.at(-1)?.id;
|
|
16
|
+
const summary = truncate(redactSecrets(summarize(oldEntries), [...(options.secrets ?? []), ...(context.secrets ?? [])]), maxSummaryChars);
|
|
17
|
+
const data = { throughEntryId, keepEntryIds, strategy: name, trigger: context.trigger };
|
|
18
|
+
const parentId = context.entries.at(-1)?.id;
|
|
19
|
+
return {
|
|
20
|
+
summary,
|
|
21
|
+
entries: [createSessionEntry({ sessionId: context.sessionId, parentId, kind: "compaction", summary, data })],
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function isCompactionEntryData(value) {
|
|
27
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
28
|
+
return false;
|
|
29
|
+
const data = value;
|
|
30
|
+
return (data.throughEntryId === undefined || typeof data.throughEntryId === "string")
|
|
31
|
+
&& (data.keepEntryIds === undefined || (Array.isArray(data.keepEntryIds) && data.keepEntryIds.every((item) => typeof item === "string")))
|
|
32
|
+
&& (data.strategy === undefined || typeof data.strategy === "string")
|
|
33
|
+
&& (data.trigger === undefined || typeof data.trigger === "string");
|
|
34
|
+
}
|
|
35
|
+
function summarize(entries) {
|
|
36
|
+
const lines = entries.flatMap((entry) => entryText(entry));
|
|
37
|
+
return lines.length ? lines.join("\n") : "No older session entries to summarize.";
|
|
38
|
+
}
|
|
39
|
+
function entryText(entry) {
|
|
40
|
+
if (entry.kind === "message" && entry.message)
|
|
41
|
+
return [`${entry.message.role}: ${messageText(entry.message)}`];
|
|
42
|
+
if (entry.kind === "summary" && entry.summary)
|
|
43
|
+
return [`summary: ${entry.summary}`];
|
|
44
|
+
if (entry.kind === "model_change" && entry.model)
|
|
45
|
+
return [`model changed to ${entry.model.provider}/${entry.model.model}`];
|
|
46
|
+
if (entry.kind === "label" && entry.label)
|
|
47
|
+
return [`label: ${entry.label}`];
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
function messageText(message) {
|
|
51
|
+
return message.content.map(blockText).filter(Boolean).join(" ");
|
|
52
|
+
}
|
|
53
|
+
function blockText(block) {
|
|
54
|
+
if (block.type === "text" || block.type === "thinking")
|
|
55
|
+
return block.text;
|
|
56
|
+
if (block.type === "tool_call")
|
|
57
|
+
return `[tool_call ${block.name}]`;
|
|
58
|
+
if (block.type === "tool_result")
|
|
59
|
+
return `[tool_result ${block.name}]`;
|
|
60
|
+
return "[image]";
|
|
61
|
+
}
|
|
62
|
+
function truncate(text, max) {
|
|
63
|
+
if (max === 0 || text.length <= max)
|
|
64
|
+
return text;
|
|
65
|
+
return `${text.slice(0, Math.max(0, max - 1))}…`;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=compaction.js.map
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JsonObject } from "./contracts.js";
|
|
2
|
+
export interface ConfigLoadContext {
|
|
3
|
+
readonly signal?: AbortSignal;
|
|
4
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
5
|
+
}
|
|
6
|
+
export interface ConfigProvider {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
load(context?: ConfigLoadContext): Promise<JsonObject | undefined> | JsonObject | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface ConfigLayer {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly config: JsonObject;
|
|
13
|
+
}
|
|
14
|
+
export declare function isJsonObject(value: unknown): value is JsonObject;
|
|
15
|
+
export declare function assertJsonObject(value: unknown, label?: string): asserts value is JsonObject;
|
|
16
|
+
export declare function loadConfigLayers(providers: readonly ConfigProvider[], context?: ConfigLoadContext): Promise<ConfigLayer[]>;
|
|
17
|
+
export declare function mergeConfigLayers(layers: readonly ConfigLayer[]): JsonObject;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export function isJsonObject(value) {
|
|
2
|
+
return isPlainObject(value) && isJsonValue(value);
|
|
3
|
+
}
|
|
4
|
+
export function assertJsonObject(value, label = "value") {
|
|
5
|
+
if (!isJsonObject(value))
|
|
6
|
+
throw new Error(`${label} must be a JSON object`);
|
|
7
|
+
}
|
|
8
|
+
export async function loadConfigLayers(providers, context) {
|
|
9
|
+
const layers = [];
|
|
10
|
+
for (const provider of providers) {
|
|
11
|
+
const config = await provider.load(context);
|
|
12
|
+
if (config !== undefined) {
|
|
13
|
+
assertJsonObject(config, `config provider ${provider.name}`);
|
|
14
|
+
layers.push({ name: provider.name, config });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return layers;
|
|
18
|
+
}
|
|
19
|
+
export function mergeConfigLayers(layers) {
|
|
20
|
+
let merged = {};
|
|
21
|
+
for (const layer of layers) {
|
|
22
|
+
assertJsonObject(layer.config, `config layer ${layer.name}`);
|
|
23
|
+
merged = mergeObjects(merged, layer.config);
|
|
24
|
+
}
|
|
25
|
+
return merged;
|
|
26
|
+
}
|
|
27
|
+
function mergeObjects(base, override) {
|
|
28
|
+
const result = { ...cloneJsonObject(base) };
|
|
29
|
+
for (const [key, value] of Object.entries(override)) {
|
|
30
|
+
const current = result[key];
|
|
31
|
+
result[key] = isPlainObject(current) && isPlainObject(value)
|
|
32
|
+
? mergeObjects(current, value)
|
|
33
|
+
: cloneJsonValue(value);
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
function cloneJsonObject(value) {
|
|
38
|
+
const result = {};
|
|
39
|
+
for (const [key, entry] of Object.entries(value))
|
|
40
|
+
result[key] = cloneJsonValue(entry);
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
function cloneJsonValue(value) {
|
|
44
|
+
if (Array.isArray(value))
|
|
45
|
+
return value.map(cloneJsonValue);
|
|
46
|
+
if (isPlainObject(value))
|
|
47
|
+
return cloneJsonObject(value);
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
function isJsonValue(value) {
|
|
51
|
+
if (value === null)
|
|
52
|
+
return true;
|
|
53
|
+
if (typeof value === "string" || typeof value === "boolean")
|
|
54
|
+
return true;
|
|
55
|
+
if (typeof value === "number")
|
|
56
|
+
return Number.isFinite(value);
|
|
57
|
+
if (Array.isArray(value))
|
|
58
|
+
return value.every(isJsonValue);
|
|
59
|
+
if (isPlainObject(value))
|
|
60
|
+
return Object.values(value).every(isJsonValue);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
function isPlainObject(value) {
|
|
64
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
65
|
+
return false;
|
|
66
|
+
const prototype = Object.getPrototypeOf(value);
|
|
67
|
+
return prototype === Object.prototype || prototype === null;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=config.js.map
|