@amaster.ai/employee-runtime-connector 0.1.1-beta.17 → 0.1.1-beta.18

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.
@@ -2183,6 +2183,42 @@ function insertSingleMissingObjectPropertyComma(value) {
2183
2183
  return value;
2184
2184
  }
2185
2185
  }
2186
+ function appendSingleMissingClosingDelimiter(value) {
2187
+ const stack = [];
2188
+ let inString = false;
2189
+ let escaped = false;
2190
+ for (const character of value) {
2191
+ if (inString) {
2192
+ if (escaped) {
2193
+ escaped = false;
2194
+ } else if (character === "\\") {
2195
+ escaped = true;
2196
+ } else if (character === '"') {
2197
+ inString = false;
2198
+ }
2199
+ continue;
2200
+ }
2201
+ if (character === '"') {
2202
+ inString = true;
2203
+ continue;
2204
+ }
2205
+ if (character === "{" || character === "[") {
2206
+ stack.push(character);
2207
+ continue;
2208
+ }
2209
+ if (character === "}" || character === "]") {
2210
+ const expected = character === "}" ? "{" : "[";
2211
+ if (stack.pop() !== expected) return value;
2212
+ }
2213
+ }
2214
+ if (inString || stack.length !== 1) return value;
2215
+ const candidate = `${value}${stack[0] === "{" ? "}" : "]"}`;
2216
+ try {
2217
+ return isJsonObject(JSON.parse(candidate)) ? candidate : value;
2218
+ } catch {
2219
+ return value;
2220
+ }
2221
+ }
2186
2222
  function normalizePiMcpProxyArgs(value) {
2187
2223
  if (typeof value !== "string") return { value, repaired: false };
2188
2224
  try {
@@ -2200,7 +2236,9 @@ function normalizePiMcpProxyArgs(value) {
2200
2236
  }
2201
2237
  }
2202
2238
  const commaRepairedValue = insertSingleMissingObjectPropertyComma(repairedControlCharacters);
2203
- return commaRepairedValue !== value ? { value: commaRepairedValue, repaired: true } : { value, repaired: false };
2239
+ if (commaRepairedValue !== value) return { value: commaRepairedValue, repaired: true };
2240
+ const closingDelimiterRepairedValue = appendSingleMissingClosingDelimiter(repairedControlCharacters);
2241
+ return closingDelimiterRepairedValue !== value ? { value: closingDelimiterRepairedValue, repaired: true } : { value, repaired: false };
2204
2242
  }
2205
2243
  }
2206
2244
  function registerManagedPiMcpArgsNormalizer(pi) {
@@ -2216,6 +2254,7 @@ function managedPiMcpArgsNormalizerExtensionSource() {
2216
2254
  escapeLiteralJsonStringControlCharacters.toString(),
2217
2255
  escapeLikelyLiteralJsonStringQuotes.toString(),
2218
2256
  insertSingleMissingObjectPropertyComma.toString(),
2257
+ appendSingleMissingClosingDelimiter.toString(),
2219
2258
  normalizePiMcpProxyArgs.toString(),
2220
2259
  `export default ${registerManagedPiMcpArgsNormalizer.toString()};`,
2221
2260
  ""
@@ -2469,6 +2508,11 @@ function createManagedPiMcpProfileApi(options = {}) {
2469
2508
  "amaster.read_company_diagnosis",
2470
2509
  "amaster.publish_company_diagnosis_brief"
2471
2510
  ]);
2511
+ const DIAGNOSIS_WIKI_READ_DIRECT_TYPED_V1_TOOL_NAMES = /* @__PURE__ */ new Set([
2512
+ "wiki_search",
2513
+ "wiki_read_page",
2514
+ "wiki_list_pages"
2515
+ ]);
2472
2516
  const HYBRID_DIRECT_TYPED_V1_TOOL_NAMES = /* @__PURE__ */ new Set([
2473
2517
  "amaster.read_company_snapshot",
2474
2518
  "runtime_action.describe",
@@ -2713,8 +2757,9 @@ function createManagedPiMcpProfileApi(options = {}) {
2713
2757
  throw new Error("pi_managed_mcp_invalid: direct tool catalog schema mismatch");
2714
2758
  }
2715
2759
  const tools = Array.isArray(catalog.tools) ? catalog.tools.map(record8) : [];
2716
- const admittedToolNames = mcpToolMode === MANAGED_PI_HYBRID_MCP_TOOL_MODE ? HYBRID_DIRECT_TYPED_V1_TOOL_NAMES : DIRECT_TYPED_V1_TOOL_NAMES;
2717
- if (tools.length !== admittedToolNames.size) {
2760
+ const admittedToolNames = mcpToolMode === MANAGED_PI_HYBRID_MCP_TOOL_MODE ? HYBRID_DIRECT_TYPED_V1_TOOL_NAMES : /* @__PURE__ */ new Set([...DIRECT_TYPED_V1_TOOL_NAMES, ...DIAGNOSIS_WIKI_READ_DIRECT_TYPED_V1_TOOL_NAMES]);
2761
+ const directTypedSizeValid = mcpToolMode !== MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE || tools.length === DIRECT_TYPED_V1_TOOL_NAMES.size || tools.length === DIRECT_TYPED_V1_TOOL_NAMES.size + DIAGNOSIS_WIKI_READ_DIRECT_TYPED_V1_TOOL_NAMES.size;
2762
+ if (!directTypedSizeValid || mcpToolMode === MANAGED_PI_HYBRID_MCP_TOOL_MODE && tools.length !== admittedToolNames.size) {
2718
2763
  throw new Error("pi_managed_mcp_invalid: direct tool catalog size mismatch");
2719
2764
  }
2720
2765
  const names = /* @__PURE__ */ new Set();
@@ -2759,6 +2804,15 @@ function createManagedPiMcpProfileApi(options = {}) {
2759
2804
  effectiveSchemaHash: stablePiToolSchemaHash(inputSchema, { adapterNormalized: true })
2760
2805
  };
2761
2806
  });
2807
+ if (mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
2808
+ for (const name of DIRECT_TYPED_V1_TOOL_NAMES) {
2809
+ if (!names.has(name)) throw new Error("pi_managed_mcp_invalid: direct tool catalog name mismatch");
2810
+ }
2811
+ const wikiReadCount = [...DIAGNOSIS_WIKI_READ_DIRECT_TYPED_V1_TOOL_NAMES].filter((name) => names.has(name)).length;
2812
+ if (wikiReadCount !== 0 && wikiReadCount !== DIAGNOSIS_WIKI_READ_DIRECT_TYPED_V1_TOOL_NAMES.size) {
2813
+ throw new Error("pi_managed_mcp_invalid: diagnosis wiki read catalog incomplete");
2814
+ }
2815
+ }
2762
2816
  const setHash = stablePiDirectCatalogSetHash(normalized.map((tool) => ({
2763
2817
  name: tool.name,
2764
2818
  exposedName: tool.exposedName,
@@ -4379,24 +4433,56 @@ function resolvedDependencySections(context, input, contextScope, snapshotFreshn
4379
4433
  overflowRefs
4380
4434
  };
4381
4435
  }
4382
- function verifiedCompanyContextSection(context) {
4383
- const companyContext = asRecord(context.verifiedCompanyContext);
4384
- if (Object.keys(companyContext).length === 0) return { content: "", sourceRef: [], observedAt: [] };
4436
+ function projectModelFactRecord(value, seenFacts) {
4437
+ return Object.fromEntries(Object.entries(asRecord(value)).sort(([left], [right]) => left.localeCompare(right)).flatMap(([key, rawValue]) => {
4438
+ if (typeof rawValue !== "string" || !rawValue.trim()) return [];
4439
+ const normalizedValue = rawValue.trim();
4440
+ const fingerprint = `${key}\0${normalizedValue}`;
4441
+ if (seenFacts.has(fingerprint)) return [];
4442
+ seenFacts.add(fingerprint);
4443
+ return [[key, normalizedValue]];
4444
+ }));
4445
+ }
4446
+ function projectVerifiedCompanyContextForModel(value) {
4447
+ const companyContext = asRecord(value);
4448
+ if (Object.keys(companyContext).length === 0) return {};
4385
4449
  if (companyContext.schemaVersion !== "mirrorx.verified-company-context.v1") {
4386
4450
  throw new Error("verified_company_context_invalid: unsupported schemaVersion");
4387
4451
  }
4388
4452
  const company = asRecord(companyContext.company);
4389
- const registration = asRecord(companyContext.registration);
4390
4453
  const companyId = readString(company.id);
4391
4454
  const companyName = readString(company.name);
4392
4455
  if (!companyId || !companyName) {
4393
4456
  throw new Error("verified_company_context_invalid: company id and name are required");
4394
4457
  }
4458
+ const seenFacts = /* @__PURE__ */ new Set([`companyName\0${companyName}`]);
4459
+ const confirmedProfileFacts = projectModelFactRecord(companyContext.confirmedProfileFacts, seenFacts);
4460
+ const confirmedOnboardingFacts = projectModelFactRecord(companyContext.confirmedOnboardingFacts, seenFacts);
4461
+ const verifiedRegistrationFacts = projectModelFactRecord(
4462
+ asRecord(companyContext.registration).facts,
4463
+ seenFacts
4464
+ );
4465
+ const knownUnknowns = Array.isArray(companyContext.unavailableFromCurrentVerification) ? [...new Set(companyContext.unavailableFromCurrentVerification.map(readString).filter(Boolean))] : [];
4466
+ return {
4467
+ companyName,
4468
+ ...Object.keys(confirmedProfileFacts).length > 0 ? { confirmedProfileFacts } : {},
4469
+ ...Object.keys(confirmedOnboardingFacts).length > 0 ? { confirmedOnboardingFacts } : {},
4470
+ ...Object.keys(verifiedRegistrationFacts).length > 0 ? { verifiedRegistrationFacts } : {},
4471
+ ...knownUnknowns.length > 0 ? { knownUnknowns } : {}
4472
+ };
4473
+ }
4474
+ function verifiedCompanyContextSection(context) {
4475
+ const companyContext = asRecord(context.verifiedCompanyContext);
4476
+ const modelContext = projectVerifiedCompanyContextForModel(companyContext);
4477
+ if (Object.keys(modelContext).length === 0) return { content: "", sourceRef: [], observedAt: [] };
4478
+ const company = asRecord(companyContext.company);
4479
+ const registration = asRecord(companyContext.registration);
4480
+ const companyId = readString(company.id);
4395
4481
  return {
4396
4482
  content: [
4397
4483
  "Use these server-snapshotted current Company facts as authoritative context for this run.",
4398
- "The current verification contract does not supply shareholder structure or a financial baseline; treat them as unknown unless separate evidence is present, and do not describe the verified registration facts below as missing.",
4399
- jsonText(companyContext)
4484
+ "Treat fields listed under knownUnknowns as unknown unless separate evidence is present; do not describe the supplied verified facts as missing.",
4485
+ jsonText(modelContext)
4400
4486
  ].join("\n"),
4401
4487
  sourceRef: [
4402
4488
  `company:${companyId}`,
@@ -4492,7 +4578,7 @@ function taskContextAuthoritySection(context) {
4492
4578
  if (sourceRefs.length === 0) return null;
4493
4579
  return {
4494
4580
  content: [
4495
- "Immutable Task admission context authority. It identifies admitted sources and automatic memory policy; it does not replace the runtime Context Manifest below.",
4581
+ "Immutable Task admission context authority. It identifies admitted sources and automatic memory policy; it is model-visible execution input and is distinct from the audit-only runtime Context Manifest.",
4496
4582
  jsonText({
4497
4583
  version: manifest.version,
4498
4584
  memoryScope: readString(manifest.memoryScope),
@@ -4763,7 +4849,9 @@ function runtimeDecompositionRequirementText(context) {
4763
4849
  return [
4764
4850
  "This issue has a server-enforced typed decomposition requirement.",
4765
4851
  "Create the complete real direct child graph before doing any substantial source work.",
4766
- "Before browsing, searching, commenting, or doing any source work, call runtime_action.describe for create_child_task, persist the complete child graph with runtime_action.plan, and execute it with runtime_action.commit.",
4852
+ "Before browsing, searching, commenting, or doing any source work, call runtime_action.describe for record_work_disposition with dispositionKind create_children and for every child action type you need.",
4853
+ "Persist one immutable runtime_action.plan whose first action is record_work_disposition kind create_children and whose remaining actions are exactly the complete child graph referenced by that disposition. Do not append update_parent, add_comment, upsert_document, or any other action after the child graph.",
4854
+ "Execute that exact plan with runtime_action.commit.",
4767
4855
  "Once runtime_action.commit succeeds, the committed required child graph is this parent run's durable delegated live disposition.",
4768
4856
  "After runtime_action.commit succeeds, yield and end the parent run immediately. Do not browse, search, research, or execute any delegated child acceptance scope, and do not poll child runs. Child assignment runs are the sole execution path for delegated child scope.",
4769
4857
  "Each executable child must have an owner, dependencies where needed, and acceptance criteria. Do not create probe or test children.",
@@ -4937,14 +5025,86 @@ function manifestEntry(section) {
4937
5025
  truncationReason: section.truncationReason ?? null
4938
5026
  };
4939
5027
  }
4940
- function renderPrompt(sections, manifest, compactManifest = false) {
5028
+ var CONTEXT_AVAILABILITY_SECTION_TITLES = Object.freeze({
5029
+ recovery_instruction: "Recovery Instruction",
5030
+ approval_continuation: "Approved Runtime Action Continuation",
5031
+ wake_comments: "Wake Delta",
5032
+ task: "Task Context",
5033
+ continuation_summary: "Continuation Summary",
5034
+ resolved_dependencies: "Resolved Dependency Outputs",
5035
+ runtime_delivery_readiness: "Current Delivery Readiness",
5036
+ runtime_authorization: "Runtime Action Contract",
5037
+ runtime_decomposition_requirement: "Required Task Decomposition",
5038
+ task_context_authority: "Task Context Authority",
5039
+ verified_company_context: "Verified Company Context",
5040
+ pi_mcp_proxy_examples: "Pi MCP Proxy Examples",
5041
+ governed_reads: "Governed External Reads",
5042
+ optional_task_wiki_context: "Optional Company Wiki Context",
5043
+ agent_instructions: "Agent Instructions",
5044
+ attachments: "Materialized Inputs",
5045
+ on_demand_refs: "On-demand Context References",
5046
+ raw_snapshot: "Raw Context Snapshot"
5047
+ });
5048
+ function contextAvailabilitySectionTitle(sectionName) {
5049
+ return CONTEXT_AVAILABILITY_SECTION_TITLES[sectionName] ?? sectionName.replaceAll("_", " ");
5050
+ }
5051
+ function projectModelContextAvailability(manifestSections) {
5052
+ const entries = Array.isArray(manifestSections) ? manifestSections.map(asRecord) : [];
5053
+ const bySection = new Map(entries.map((entry) => [readString(entry.section), entry]));
5054
+ const lines = [];
5055
+ const coveredSections = [];
5056
+ const wikiEntry = bySection.get("optional_task_wiki_context");
5057
+ const wikiReason = readString(wikiEntry?.truncationReason);
5058
+ if (wikiEntry?.omitted === true && wikiReason?.startsWith("wiki_optional_context_gap:")) {
5059
+ const gapCode = wikiReason.slice("wiki_optional_context_gap:".length);
5060
+ lines.push(
5061
+ gapCode === "wiki_zero_hit" ? "Optional Company Wiki lookup completed with no matching result." : "Optional Company Wiki context was unavailable for this run. Do not assume that no relevant Wiki material exists."
5062
+ );
5063
+ coveredSections.push("optional_task_wiki_context");
5064
+ }
5065
+ const budgetOmissions = entries.filter((entry) => entry.omitted === true && entry.truncationReason === "unified_context_budget").map((entry) => readString(entry.section)).filter(Boolean);
5066
+ if (budgetOmissions.length > 0) {
5067
+ lines.push(
5068
+ `The prompt budget omitted these context sections: ${budgetOmissions.map(contextAvailabilitySectionTitle).join(", ")}. Do not assume that the underlying material is absent; use managed typed reads when an applicable reference is available.`
5069
+ );
5070
+ coveredSections.push(...budgetOmissions);
5071
+ }
5072
+ const rawSnapshot = bySection.get("raw_snapshot");
5073
+ const onDemandRefs2 = bySection.get("on_demand_refs");
5074
+ if (rawSnapshot?.omitted === true && rawSnapshot.truncationReason === "on_demand_large_object" && Number(rawSnapshot.originalChars ?? 0) > 0 && (!onDemandRefs2 || onDemandRefs2.omitted === true)) {
5075
+ lines.push(
5076
+ "Additional raw run context was intentionally not inlined and no managed on-demand reference was provided. Do not assume that omitted details are absent."
5077
+ );
5078
+ coveredSections.push("raw_snapshot");
5079
+ }
5080
+ return {
5081
+ content: lines.join("\n"),
5082
+ coveredSections: [...new Set(coveredSections)]
5083
+ };
5084
+ }
5085
+ function modelSectionsWithAvailability(sections) {
5086
+ const manifestEntries = sections.map(manifestEntry);
5087
+ const projection = projectModelContextAvailability(manifestEntries);
5088
+ if (!projection.content) return sections;
5089
+ const covered = new Set(projection.coveredSections);
4941
5090
  return [
4942
- ...sections.map(sectionText).filter(Boolean),
4943
- "## Context Manifest",
4944
- "```json",
4945
- compactManifest ? JSON.stringify(manifest) : jsonText(manifest),
4946
- "```"
4947
- ].join("\n");
5091
+ ...sections,
5092
+ {
5093
+ name: "context_availability",
5094
+ title: "Context Availability",
5095
+ priority: 100,
5096
+ sourceRef: manifestEntries.filter((entry) => covered.has(entry.section)).flatMap((entry) => Array.isArray(entry.sourceRef) ? entry.sourceRef : [entry.sourceRef]).filter(Boolean),
5097
+ observedAt: null,
5098
+ freshness: { kind: "run_snapshot" },
5099
+ scope: null,
5100
+ content: projection.content,
5101
+ originalChars: sectionText({ title: "Context Availability", content: projection.content }).length,
5102
+ truncationReason: null
5103
+ }
5104
+ ];
5105
+ }
5106
+ function renderPrompt(sections) {
5107
+ return sections.map(sectionText).filter(Boolean).join("\n");
4948
5108
  }
4949
5109
  function buildManifest(mode, maxChars, sections, governedReadProvenance, usedChars) {
4950
5110
  return {
@@ -5066,50 +5226,38 @@ ${resolvedDependencies.details.content}` : ""
5066
5226
  truncationReason: section.content ? section.truncationReason : section.truncationReason ?? "source_absent"
5067
5227
  }));
5068
5228
  let prompt = "";
5069
- let compactManifest = false;
5070
- let manifest = buildManifest(mode, maxChars, sections, governedReads.provenance, 0);
5229
+ let modelSections = modelSectionsWithAvailability(sections);
5230
+ let manifest = buildManifest(mode, maxChars, modelSections, governedReads.provenance, 0);
5071
5231
  if (maxChars === null) {
5072
- for (let telemetryPass = 0; telemetryPass < 20; telemetryPass += 1) {
5073
- prompt = renderPrompt(sections, manifest);
5074
- if (manifest.budget.usedChars === prompt.length) return { prompt, manifest };
5075
- manifest = buildManifest(mode, null, sections, governedReads.provenance, prompt.length);
5076
- }
5077
- throw new Error("Prompt compiler could not stabilize the unbounded Context Manifest");
5232
+ prompt = renderPrompt(modelSections);
5233
+ manifest = buildManifest(mode, null, modelSections, governedReads.provenance, prompt.length);
5234
+ return { prompt, manifest };
5078
5235
  }
5079
5236
  for (let pass = 0; pass < 20; pass += 1) {
5080
- let usedChars = 0;
5081
- for (let telemetryPass = 0; telemetryPass < 3; telemetryPass += 1) {
5082
- manifest = buildManifest(mode, maxChars, sections, governedReads.provenance, usedChars);
5083
- prompt = renderPrompt(sections, manifest, compactManifest);
5084
- if (prompt.length === usedChars) break;
5085
- usedChars = prompt.length;
5086
- }
5087
- if (prompt.length <= maxChars && manifest.budget.usedChars === prompt.length) break;
5237
+ modelSections = modelSectionsWithAvailability(sections);
5238
+ prompt = renderPrompt(modelSections);
5239
+ manifest = buildManifest(mode, maxChars, modelSections, governedReads.provenance, prompt.length);
5240
+ if (prompt.length <= maxChars) break;
5088
5241
  const overflow = Math.max(1, prompt.length - maxChars);
5089
5242
  const candidate = [...sections].filter(
5090
5243
  (section) => section.priority < 100 && section.content.length > (section.mandatoryContent?.length ?? 0)
5091
5244
  ).sort((left, right) => left.priority - right.priority)[0];
5092
5245
  if (!candidate) {
5093
- if (!compactManifest) {
5094
- compactManifest = true;
5095
- manifest = buildManifest(mode, maxChars, sections, governedReads.provenance, 0);
5096
- continue;
5097
- }
5098
- const fixedChars = sections.filter((section) => section.priority === 100).map(sectionText).join("\n").length;
5099
- const manifestChars = JSON.stringify(manifest).length;
5246
+ const fixedChars = modelSections.filter((section) => section.priority === 100).map(sectionText).join("\n").length;
5247
+ const availabilitySection = modelSections.find((section) => section.name === "context_availability");
5248
+ const availabilityChars = availabilitySection ? sectionText(availabilitySection).length : 0;
5100
5249
  if (resolvedDependencies.required.tupleCount > 0) {
5101
5250
  throw promptBudgetError(
5102
5251
  "resolved_dependencies_budget_exceeded",
5103
- `Resolved dependency mandatory read tuples exceed the unified ${maxChars}-character prompt budget: tupleCount=${resolvedDependencies.required.tupleCount} promptChars=${prompt.length} fixedChars=${fixedChars} manifestChars=${manifestChars}`
5252
+ `Resolved dependency mandatory read tuples exceed the unified ${maxChars}-character prompt budget: tupleCount=${resolvedDependencies.required.tupleCount} promptChars=${prompt.length} fixedChars=${fixedChars} availabilityChars=${availabilityChars}`
5104
5253
  );
5105
5254
  }
5106
5255
  throw promptBudgetError(
5107
5256
  "prompt_budget_exceeded",
5108
- `Prompt fixed sections exceed the unified ${maxChars}-character budget: promptChars=${prompt.length} fixedChars=${fixedChars} manifestChars=${manifestChars}`
5257
+ `Prompt fixed sections exceed the unified ${maxChars}-character budget: promptChars=${prompt.length} fixedChars=${fixedChars} availabilityChars=${availabilityChars}`
5109
5258
  );
5110
5259
  }
5111
5260
  truncateSection(candidate, Math.max(0, candidate.content.length - overflow - 32));
5112
- manifest = buildManifest(mode, maxChars, sections, governedReads.provenance, 0);
5113
5261
  }
5114
5262
  if (prompt.length > maxChars || manifest.budget.usedChars !== prompt.length) {
5115
5263
  throw promptBudgetError(
@@ -9644,7 +9792,7 @@ function assertSourceAcquisitionRuntimeAuthority({
9644
9792
  }
9645
9793
 
9646
9794
  // src/amaster-runtime-daemon.mjs
9647
- var CONNECTOR_VERSION = "0.1.1-beta.17";
9795
+ var CONNECTOR_VERSION = "0.1.1-beta.18";
9648
9796
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
9649
9797
  var SOURCE_ACQUISITION_CAPABILITY = "source_acquisition_v1";
9650
9798
  var SOURCE_ACQUISITION_PROFILE_VERSION = "source_acquisition_v1";
@@ -6,7 +6,7 @@ import { basename, dirname, join, resolve } from "node:path";
6
6
  import { homedir, hostname } from "node:os";
7
7
  import { fileURLToPath } from "node:url";
8
8
 
9
- const CONNECTOR_VERSION = "0.1.1-beta.17";
9
+ const CONNECTOR_VERSION = "0.1.1-beta.18";
10
10
 
11
11
  const CAPABILITIES = [
12
12
  "remote_registration",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/employee-runtime-connector",
3
- "version": "0.1.1-beta.17",
3
+ "version": "0.1.1-beta.18",
4
4
  "description": "MirrorX runtime connector CLI and daemon",
5
5
  "license": "MIT",
6
6
  "type": "module",