toolcraft 0.0.107 → 0.0.109

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/composition.json CHANGED
@@ -53,7 +53,7 @@
53
53
  },
54
54
  {
55
55
  "name": "toolcraft",
56
- "version": "0.0.107",
56
+ "version": "0.0.109",
57
57
  "license": "MIT"
58
58
  },
59
59
  {
@@ -63,7 +63,7 @@
63
63
  },
64
64
  {
65
65
  "name": "toolcraft-schema",
66
- "version": "0.0.107",
66
+ "version": "0.0.109",
67
67
  "license": "MIT"
68
68
  }
69
69
  ]
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./node-require-shim.js";
2
2
  import { configureTheme } from "toolcraft-design";
3
- import type { Group, HandlerFs, LogLevel, RuntimeLoggerInput } from "./index.js";
3
+ import type { Command, Group, HandlerFs, LogLevel, RenderPrimitives, RuntimeLoggerInput } from "./index.js";
4
4
  import { type ErrorReportsOption } from "./error-report.js";
5
5
  import type { HumanInLoopRuntimeOptions } from "./human-in-loop/types.js";
6
6
  export { renderErrorReport } from "./error-report.js";
@@ -10,10 +10,21 @@ type Casing = "kebab" | "snake";
10
10
  export interface CLIControls {
11
11
  debug?: boolean;
12
12
  logLevel?: boolean;
13
- output?: boolean;
13
+ output?: boolean | CLIOutputControl;
14
14
  verbose?: boolean;
15
15
  yes?: boolean;
16
16
  }
17
+ export interface CLIOutputFormatContext {
18
+ command: Command<any, any, any, any>;
19
+ commandPath: string;
20
+ primitives: RenderPrimitives;
21
+ result: unknown;
22
+ }
23
+ export type CLIOutputFormatRenderer = (context: CLIOutputFormatContext) => string | undefined;
24
+ export type CLIOutputFormats = Readonly<Record<string, CLIOutputFormatRenderer>>;
25
+ export interface CLIOutputControl {
26
+ formats?: CLIOutputFormats;
27
+ }
17
28
  export interface RunCLIOptions<TServices extends object = Record<string, unknown>> {
18
29
  apiVersion?: string;
19
30
  approvals?: boolean;
@@ -48,6 +59,7 @@ export interface CLICommandTreeSnapshotOption {
48
59
  positional?: boolean;
49
60
  global?: boolean;
50
61
  dynamic?: boolean;
62
+ choices?: string[];
51
63
  }
52
64
  export interface CLICommandTreeSnapshotCommand {
53
65
  kind: "command";
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  import { Command as CommanderCommand, CommanderError, InvalidArgumentError, Option } from "commander";
5
5
  import { validate as validateSchema } from "toolcraft-schema";
6
6
  import { cancel, configureTheme, confirm, createLogger, formatCommandList, formatOptionList, getTheme, helpFormatterPlain, isCancel, note, promptText, renderTable, resetOutputFormatCache, select, text } from "toolcraft-design";
7
- import { ApprovalDeclinedError, UserError, assertCommandRequirements, getCommandSourcePath, hasMcpProxyConfig, resolveCommandSecrets } from "./index.js";
7
+ import { ApprovalDeclinedError, ToolcraftBugError, UserError, assertCommandRequirements, getCommandSourcePath, hasMcpProxyConfig, resolveCommandSecrets } from "./index.js";
8
8
  import { hasOwnErrorCode } from "./error-codes.js";
9
9
  import { writeErrorReport } from "./error-report.js";
10
10
  import { getExpectedNumberDescription, isValidNumberSchemaValue } from "./number-schema.js";
@@ -662,14 +662,35 @@ function createOption(field, globalLongOptionFlags) {
662
662
  return [option];
663
663
  }
664
664
  function resolveCLIControls(controls) {
665
+ const outputFormats = typeof controls?.output === "object" ? (controls.output.formats ?? {}) : {};
666
+ validateOutputFormats(outputFormats);
665
667
  return {
666
668
  debug: controls?.debug === true,
667
669
  logLevel: controls?.logLevel === true,
668
- output: controls?.output === true,
670
+ output: controls?.output === true || typeof controls?.output === "object",
671
+ outputFormats,
669
672
  verbose: controls?.verbose === true,
670
673
  yes: controls?.yes === true
671
674
  };
672
675
  }
676
+ const BUILT_IN_OUTPUT_FORMATS = ["rich", "md", "markdown", "json"];
677
+ function outputFormatNames(controls) {
678
+ return [...BUILT_IN_OUTPUT_FORMATS, ...Object.keys(controls.outputFormats)];
679
+ }
680
+ function validateOutputFormats(formats) {
681
+ for (const [name, renderer] of Object.entries(formats)) {
682
+ const hasWhitespace = name.split("").some((character) => character.trim() === "");
683
+ if (name.length === 0 || name.trim() !== name || hasWhitespace) {
684
+ throw new ToolcraftBugError(`Custom output format names must be non-empty and contain no whitespace: ${JSON.stringify(name)}.`);
685
+ }
686
+ if (BUILT_IN_OUTPUT_FORMATS.includes(name)) {
687
+ throw new ToolcraftBugError(`Custom output format "${name}" conflicts with a built-in format.`);
688
+ }
689
+ if (typeof renderer !== "function") {
690
+ throw new ToolcraftBugError(`Custom output format "${name}" must define a renderer function.`);
691
+ }
692
+ }
693
+ }
673
694
  function getGlobalLongOptionFlags(presetsEnabled, versionEnabled, controls) {
674
695
  const flags = [];
675
696
  if (presetsEnabled) {
@@ -1129,7 +1150,7 @@ function formatGlobalOptionsLine(ctx) {
1129
1150
  flags.push("--yes");
1130
1151
  }
1131
1152
  if (ctx.controls.output) {
1132
- flags.push("--output <format>");
1153
+ flags.push(`--output <${outputFormatNames(ctx.controls).join("|")}>`);
1133
1154
  }
1134
1155
  if (ctx.controls.verbose) {
1135
1156
  flags.push("-v, --verbose");
@@ -1535,13 +1556,15 @@ function createGlobalSnapshotOptions(presetsEnabled, versionEnabled, controls) {
1535
1556
  });
1536
1557
  }
1537
1558
  if (controls.output) {
1559
+ const choices = outputFormatNames(controls);
1538
1560
  options.push({
1539
1561
  name: "output",
1540
1562
  flags: ["--output"],
1541
1563
  type: "enum",
1542
1564
  required: false,
1543
1565
  hidden: true,
1544
- description: "Output format."
1566
+ description: "Output format.",
1567
+ choices
1545
1568
  });
1546
1569
  }
1547
1570
  if (controls.debug) {
@@ -1656,15 +1679,19 @@ function addGlobalOptions(command, presetsEnabled, controls) {
1656
1679
  options.push(new Option("--yes", "Accept defaults and skip prompts."));
1657
1680
  }
1658
1681
  if (controls.output) {
1659
- options.push(new Option("--output <format>", "Output format.").argParser((value) => {
1682
+ const choices = outputFormatNames(controls);
1683
+ options.push(new Option("--output <format>", "Output format.").choices(choices).argParser((value) => {
1660
1684
  if (value === "rich" || value === "md" || value === "json") {
1661
1685
  return value;
1662
1686
  }
1663
1687
  if (value === "markdown") {
1664
1688
  return "md";
1665
1689
  }
1666
- throw new InvalidArgumentError(formatInvalidEnumMessage("--output", value, ["rich", "md", "markdown", "json"], {
1667
- candidates: ["rich", "markdown", "json"],
1690
+ if (Object.hasOwn(controls.outputFormats, value)) {
1691
+ return value;
1692
+ }
1693
+ throw new InvalidArgumentError(formatInvalidEnumMessage("--output", value, choices, {
1694
+ candidates: ["rich", "markdown", "json", ...Object.keys(controls.outputFormats)],
1668
1695
  threshold: 3
1669
1696
  }));
1670
1697
  }));
@@ -1834,11 +1861,11 @@ function resolveOutput(resolvedFlags) {
1834
1861
  return "json";
1835
1862
  }
1836
1863
  if (resolvedFlags.output !== undefined) {
1837
- return resolvedFlags.output;
1864
+ return resolvedFlags.output === "markdown" ? "md" : resolvedFlags.output;
1838
1865
  }
1839
1866
  return "rich";
1840
1867
  }
1841
- function resolveOutputFromArgv(argv) {
1868
+ function resolveOutputFromArgv(argv, formats = {}) {
1842
1869
  for (let index = 0; index < argv.length; index += 1) {
1843
1870
  const token = argv[index] ?? "";
1844
1871
  if (token === "--json") {
@@ -1855,6 +1882,9 @@ function resolveOutputFromArgv(argv) {
1855
1882
  if (value === "markdown") {
1856
1883
  return "md";
1857
1884
  }
1885
+ if (value !== undefined && Object.hasOwn(formats, value)) {
1886
+ return value;
1887
+ }
1858
1888
  continue;
1859
1889
  }
1860
1890
  if (token.startsWith("--output=")) {
@@ -1865,17 +1895,21 @@ function resolveOutputFromArgv(argv) {
1865
1895
  if (value === "markdown") {
1866
1896
  return "md";
1867
1897
  }
1898
+ if (Object.hasOwn(formats, value)) {
1899
+ return value;
1900
+ }
1868
1901
  }
1869
1902
  }
1870
1903
  return "rich";
1871
1904
  }
1872
- const DESIGN_SYSTEM_OUTPUT_BY_MODE = {
1873
- rich: "terminal",
1874
- md: "markdown",
1875
- json: "json"
1876
- };
1877
1905
  function toDesignSystemOutput(output) {
1878
- return DESIGN_SYSTEM_OUTPUT_BY_MODE[output];
1906
+ if (output === "md") {
1907
+ return "markdown";
1908
+ }
1909
+ if (output === "json") {
1910
+ return "json";
1911
+ }
1912
+ return "terminal";
1879
1913
  }
1880
1914
  async function withOutputFormat(output, fn) {
1881
1915
  const previous = process.env.OUTPUT_FORMAT;
@@ -2994,17 +3028,18 @@ function getResolvedFlags(command) {
2994
3028
  const flags = command.optsWithGlobals();
2995
3029
  return flags;
2996
3030
  }
2997
- async function executeCommand(state, services, requirementOptions, runtimeFetch, runtimeOptions, runtimeEnv, runtimeFs, outputEmitter, promptStreams, diagnosticsOptions, onErrorReportContext) {
3031
+ async function executeCommand(state, services, requirementOptions, runtimeFetch, runtimeOptions, runtimeEnv, runtimeFs, outputEmitter, outputFormats, promptStreams, diagnosticsOptions, onErrorReportContext) {
2998
3032
  const logger = createLogger(outputEmitter);
3033
+ const optionValues = state.actionCommand.optsWithGlobals();
3034
+ const resolvedFlags = optionValues;
3035
+ const output = resolveOutput(resolvedFlags);
2999
3036
  const primitives = {
3000
3037
  logger,
3001
3038
  renderTable,
3002
3039
  getTheme,
3003
- note
3040
+ note,
3041
+ outputFormat: output
3004
3042
  };
3005
- const optionValues = state.actionCommand.optsWithGlobals();
3006
- const resolvedFlags = optionValues;
3007
- const output = resolveOutput(resolvedFlags);
3008
3043
  const diagnostics = createRuntimeLogger({
3009
3044
  level: resolvedFlags.logLevel ??
3010
3045
  (diagnosticsOptions.verboseControlEnabled && resolvedFlags.verbose
@@ -3021,7 +3056,7 @@ async function executeCommand(state, services, requirementOptions, runtimeFetch,
3021
3056
  ? {
3022
3057
  commandPath: state.commandPath,
3023
3058
  params: {},
3024
- output,
3059
+ output: "rich",
3025
3060
  stdinTTY,
3026
3061
  stdoutTTY
3027
3062
  }
@@ -3091,9 +3126,9 @@ async function executeCommand(state, services, requirementOptions, runtimeFetch,
3091
3126
  }
3092
3127
  }
3093
3128
  else {
3094
- renderResult(state.command, event, output, primitives, outputEmitter === undefined
3129
+ renderCLIResult(state.command, state.commandPath, event, output, primitives, outputFormats, outputEmitter === undefined
3095
3130
  ? undefined
3096
- : (chunk) => outputEmitter(chunk.endsWith("\n") ? chunk.slice(0, -1) : chunk));
3131
+ : (chunk) => outputEmitter(chunk.endsWith("\n") ? chunk.slice(0, -1) : chunk), outputEmitter);
3097
3132
  }
3098
3133
  }
3099
3134
  }
@@ -3137,9 +3172,9 @@ async function executeCommand(state, services, requirementOptions, runtimeFetch,
3137
3172
  renderHumanInLoopPending(result);
3138
3173
  return;
3139
3174
  }
3140
- const renderStatus = renderResult(state.command, result, output, primitives, outputEmitter === undefined
3175
+ const renderStatus = renderCLIResult(state.command, state.commandPath, result, output, primitives, outputFormats, outputEmitter === undefined
3141
3176
  ? undefined
3142
- : (chunk) => outputEmitter(chunk.endsWith("\n") ? chunk.slice(0, -1) : chunk));
3177
+ : (chunk) => outputEmitter(chunk.endsWith("\n") ? chunk.slice(0, -1) : chunk), outputEmitter);
3143
3178
  if (renderStatus.mcpError) {
3144
3179
  process.exitCode = 1;
3145
3180
  }
@@ -3155,6 +3190,25 @@ async function executeCommand(state, services, requirementOptions, runtimeFetch,
3155
3190
  throw error;
3156
3191
  }
3157
3192
  }
3193
+ function renderCLIResult(command, commandPath, result, output, primitives, outputFormats, write, emitExact) {
3194
+ const customRenderer = outputFormats[output];
3195
+ if (customRenderer === undefined) {
3196
+ return renderResult(command, result, output, primitives, write);
3197
+ }
3198
+ const payload = customRenderer({ command, commandPath, primitives, result });
3199
+ if (payload !== undefined && payload.length > 0) {
3200
+ if (emitExact !== undefined) {
3201
+ emitExact(payload);
3202
+ }
3203
+ else if (write === undefined) {
3204
+ process.stdout.write(payload);
3205
+ }
3206
+ else {
3207
+ write(payload);
3208
+ }
3209
+ }
3210
+ return { mcpError: false };
3211
+ }
3158
3212
  function isStringRecord(value) {
3159
3213
  return isPlainObject(value) && Object.values(value).every((entry) => typeof entry === "string");
3160
3214
  }
@@ -3723,7 +3777,7 @@ export async function runCLI(roots, options = {}) {
3723
3777
  const execute = async (state) => {
3724
3778
  lastActionCommand = state.actionCommand;
3725
3779
  resolvedCommandPath = formatCliCommandPath(state.commandPath);
3726
- await executeCommand(state, servicesWithBuiltIns, requirementOptions, runtimeFetch, runtimeOptions, options.env, options.fs, options.outputEmitter, {
3780
+ await executeCommand(state, servicesWithBuiltIns, requirementOptions, runtimeFetch, runtimeOptions, options.env, options.fs, options.outputEmitter, controls.outputFormats, {
3727
3781
  input: options.promptInput,
3728
3782
  output: options.promptOutput
3729
3783
  }, {
@@ -3785,7 +3839,9 @@ export async function runCLI(roots, options = {}) {
3785
3839
  debugStackMode: resolvedFlags !== undefined
3786
3840
  ? resolveDebugStackMode(resolvedFlags.debug)
3787
3841
  : getDebugStackModeFromArgv(argv),
3788
- output: resolvedFlags !== undefined ? resolveOutput(resolvedFlags) : resolveOutputFromArgv(argv),
3842
+ output: resolvedFlags !== undefined
3843
+ ? resolveOutput(resolvedFlags)
3844
+ : resolveOutputFromArgv(argv, controls.outputFormats),
3789
3845
  verbose: resolvedFlags ? Boolean(resolvedFlags.verbose) : argv.includes("--verbose"),
3790
3846
  program,
3791
3847
  argv,
@@ -53,7 +53,7 @@
53
53
  },
54
54
  {
55
55
  "name": "toolcraft",
56
- "version": "0.0.107",
56
+ "version": "0.0.109",
57
57
  "license": "MIT"
58
58
  },
59
59
  {
@@ -63,7 +63,7 @@
63
63
  },
64
64
  {
65
65
  "name": "toolcraft-schema",
66
- "version": "0.0.107",
66
+ "version": "0.0.109",
67
67
  "license": "MIT"
68
68
  }
69
69
  ]
package/dist/index.d.ts CHANGED
@@ -57,6 +57,7 @@ export interface RenderPrimitives {
57
57
  renderTable(options: RenderTableOptions): string;
58
58
  getTheme(): ThemePalette;
59
59
  note(message: string, title?: string): void;
60
+ outputFormat: string;
60
61
  }
61
62
  export interface CheckResult {
62
63
  ok: boolean;
@@ -1,5 +1,5 @@
1
1
  import type { Command, RenderPrimitives } from "./index.js";
2
- export type OutputMode = "rich" | "md" | "json";
2
+ export type OutputMode = "rich" | "md" | "json" | (string & {});
3
3
  type WriteStream = "stdout" | "stderr";
4
4
  type WriteFn = (chunk: string, stream?: WriteStream) => void;
5
5
  export interface RenderResultStatus {
@@ -4,6 +4,7 @@ import { type FetchRoute } from "./fakes.js";
4
4
  import { type FsChange, type MemoryFs } from "./memory-fs.js";
5
5
  import { type ParityResult } from "./parity.js";
6
6
  import { type StreamStatusEvent } from "../stream.js";
7
+ import { type CLIOutputFormats } from "../cli.js";
7
8
  export type PipelineStage = "resolve" | "secrets" | "requirements" | "params" | "confirm" | "handler" | "render";
8
9
  export type EffectEvent = {
9
10
  seq: number;
@@ -67,6 +68,7 @@ export interface RunResult<T> {
67
68
  };
68
69
  }
69
70
  export interface CommandTestHarness {
71
+ cli(args: string[], options?: HarnessCLIOptions): Promise<HarnessCLIResult>;
70
72
  run<T>(path: string[], params?: Record<string, unknown>): Promise<RunResult<T>>;
71
73
  stream<T>(path: string[], params?: Record<string, unknown>, options?: {
72
74
  limit?: number;
@@ -76,6 +78,14 @@ export interface CommandTestHarness {
76
78
  fs: MemoryFs;
77
79
  timeline: EffectEvent[];
78
80
  }
81
+ export interface HarnessCLIOptions {
82
+ formats?: CLIOutputFormats;
83
+ }
84
+ export interface HarnessCLIResult {
85
+ exitCode: number;
86
+ stdout: string;
87
+ stderr: string;
88
+ }
79
89
  export interface StreamRunResult<T> {
80
90
  ok: boolean;
81
91
  events: T[];
@@ -83,5 +93,5 @@ export interface StreamRunResult<T> {
83
93
  error?: unknown;
84
94
  }
85
95
  type EmptyHarnessServices = Record<string, never>;
86
- export declare function createCommandTestHarness<TServices extends object = EmptyHarnessServices>(root: Group, options?: HarnessOptions<TServices>): CommandTestHarness;
96
+ export declare function createCommandTestHarness<TServices extends object = EmptyHarnessServices>(root: Group<TServices>, options?: HarnessOptions<TServices>): CommandTestHarness;
87
97
  export {};
@@ -12,6 +12,7 @@ import { createMemoryFs } from "./memory-fs.js";
12
12
  import { runParity } from "./parity.js";
13
13
  import { createRenderCapture } from "./render-capture.js";
14
14
  import { createManagedStream } from "../stream.js";
15
+ import { runCLI } from "../cli.js";
15
16
  function isHandlerFs(value) {
16
17
  return typeof value.readFile === "function";
17
18
  }
@@ -186,6 +187,33 @@ export function createCommandTestHarness(root, options = {}) {
186
187
  return {
187
188
  fs: memoryFs,
188
189
  timeline: cumulativeTimeline,
190
+ async cli(args, cliOptions = {}) {
191
+ let stdout = "";
192
+ const previousExitCode = process.exitCode;
193
+ process.exitCode = undefined;
194
+ try {
195
+ await runCLI(root, {
196
+ argv: ["node", root.name, ...args],
197
+ controls: { output: { formats: cliOptions.formats } },
198
+ services,
199
+ env: Object.fromEntries(Object.entries(options.env ?? {}).flatMap(([key, value]) => value === undefined ? [] : [[key, value]])),
200
+ fs: memoryFs,
201
+ fetch: runtimeFetch,
202
+ logLevel: options.logLevel,
203
+ outputEmitter(entry) {
204
+ stdout += entry;
205
+ }
206
+ });
207
+ return {
208
+ exitCode: process.exitCode ?? 0,
209
+ stdout,
210
+ stderr: ""
211
+ };
212
+ }
213
+ finally {
214
+ process.exitCode = previousExitCode;
215
+ }
216
+ },
189
217
  async stream(requestedPath, inputParams = {}, streamOptions = {}) {
190
218
  const events = [];
191
219
  const statuses = [];
@@ -444,11 +472,11 @@ export function createCommandTestHarness(root, options = {}) {
444
472
  rendered.rich = capture.output();
445
473
  }
446
474
  if (command.render?.markdown) {
447
- const capture = createRenderCapture();
475
+ const capture = createRenderCapture("md");
448
476
  rendered.markdown = stripAnsi(command.render.markdown(invoked, capture.primitives));
449
477
  }
450
478
  if (command.render?.json) {
451
- const capture = createRenderCapture();
479
+ const capture = createRenderCapture("json");
452
480
  rendered.json = command.render.json(invoked, capture.primitives);
453
481
  }
454
482
  return result({ ok: true, failedAt: undefined });
@@ -1,4 +1,4 @@
1
- export { createCommandTestHarness, type CommandTestHarness, type ConfirmationRequest, type EffectEvent, type HarnessOptions, type PipelineStage, type RunResult, type StreamRunResult } from "./harness.js";
1
+ export { createCommandTestHarness, type CommandTestHarness, type ConfirmationRequest, type EffectEvent, type HarnessCLIOptions, type HarnessCLIResult, type HarnessOptions, type PipelineStage, type RunResult, type StreamRunResult } from "./harness.js";
2
2
  export { fakeFetch, fakeService, type FetchRoute, type ServiceCall } from "./fakes.js";
3
3
  export { createMemoryFs, type FsChange, type MemoryFs } from "./memory-fs.js";
4
4
  export type { ParityResult, SurfaceOutcome } from "./parity.js";
@@ -3,4 +3,4 @@ export interface RenderCapture {
3
3
  primitives: RenderPrimitives;
4
4
  output(): string;
5
5
  }
6
- export declare function createRenderCapture(): RenderCapture;
6
+ export declare function createRenderCapture(outputFormat?: string): RenderCapture;
@@ -32,7 +32,7 @@ function createCaptureTheme() {
32
32
  intro: (text) => ` Poe - ${text} `
33
33
  };
34
34
  }
35
- export function createRenderCapture() {
35
+ export function createRenderCapture(outputFormat = "rich") {
36
36
  const output = [];
37
37
  const captureTheme = createCaptureTheme();
38
38
  const emit = (message) => {
@@ -47,7 +47,8 @@ export function createRenderCapture() {
47
47
  maxWidth: captureWidth
48
48
  }))),
49
49
  getTheme: () => captureTheme,
50
- note: (message, title) => emit(title === undefined ? message : `${title}\n${message}`)
50
+ note: (message, title) => emit(title === undefined ? message : `${title}\n${message}`),
51
+ outputFormat
51
52
  },
52
53
  output: () => output.join("\n")
53
54
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft-schema",
3
- "version": "0.0.107",
3
+ "version": "0.0.109",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.107",
3
+ "version": "0.0.109",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -150,7 +150,7 @@
150
150
  "auth-store"
151
151
  ],
152
152
  "optionalDependencies": {
153
- "toolcraft-schema": "0.0.107",
153
+ "toolcraft-schema": "0.0.109",
154
154
  "toolcraft-design": "^0.0.2",
155
155
  "@poe-code/frontmatter": "*",
156
156
  "@poe-code/agent-mcp-config": "*",