apcore-cli 0.8.0 → 0.8.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 +23 -0
- package/dist/bin/apcore-cli.js +20 -25
- package/dist/bin/apcore-cli.js.map +1 -1
- package/dist/index.js +19 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ All notable changes to apcore-cli (TypeScript SDK) will be documented in this fi
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.1] - 2026-05-09
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Init-time deadlock under Bun (`src/security/sandbox.ts`).** The
|
|
13
|
+
sandbox runner's 5 `await import('node:child_process|os|path|fs')`
|
|
14
|
+
calls were hoisted to static `import` statements at the top of
|
|
15
|
+
`sandbox.ts`. The dynamic-import pattern was a holdover from when
|
|
16
|
+
apcore-cli targeted both Node and browser; the CLI is Node-only by
|
|
17
|
+
nature (`#!/usr/bin/env node`, `process.argv[1]` re-exec, child-
|
|
18
|
+
process spawning), so deferring the imports added no value and
|
|
19
|
+
contributed to the Bun deadlock chain when the CLI was loaded via
|
|
20
|
+
`bun run dist/bin/apcore-cli.js`. Verified end-to-end on Bun 1.3.13:
|
|
21
|
+
`--version` returns in 108 ms (was: indefinite hang on Bun 1.2.x).
|
|
22
|
+
No public API change.
|
|
23
|
+
- **C-SNAKE/1 — schema kwargs forwarded under commander's camelCase keys instead of the schema's snake_case property names** (`src/main.ts:985-998`). Commander stores parsed flag values under camelCased attribute names (`--has-solution` → `options.hasSolution`); the action handler previously passed `Object.entries(options)` straight into `schemaKwargs`, so modules reading `input["has_solution"]` always saw `undefined`. Single-word flags (`--module`, `--page`) coincidentally worked because their camelCase form matches the schema name. Multi-word fields (`has_solution`, `sort_by`, `sort_order`) were silently dropped. The fix iterates `schemaOptions` and writes each value back under its original `propName`, matching Python click's auto-derived parameter name and Rust clap's explicit `Arg::new(prop_name)` semantics. Cross-SDK parity restored.
|
|
24
|
+
- **C-SNAKE/2 — boolean `--flag/--no-flag` pair was registered as a single comma-combined commander option** (`src/main.ts:957-975`). The schema-parser produced `flags: "--<flag>, --no-<flag>"` and the registration loop forwarded that string to `cmd.option(...)`. Commander does not parse the comma form the way Python click's `--flag/--no-flag` does — it routes both forms to the negated attribute and stores `false` for both, so `--has-solution` did not flip the value to `true`. Boolean schema flags now register as two separate `Option`s (`--<flag>` carrying the schema default + help, plus a hidden `--no-<flag>` companion); commander's auto-negation routes both to the same camelCase attribute and applies the correct value.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **`tests/conformance/snake-case-kwargs.test.ts`** — runs the cross-language Algorithm C-SNAKE fixture (`apcore-cli/conformance/fixtures/snake-case-kwargs/cases.json`) against `buildModuleCommand`. Five cases cover positive flag, negation, default fallback, snake_case string flags, and a multi-flag combination. The same fixture is consumed verbatim by the Python and Rust SDK runners.
|
|
29
|
+
|
|
30
|
+
|
|
8
31
|
## [0.8.0] - 2026-05-08
|
|
9
32
|
|
|
10
33
|
### Security
|
package/dist/bin/apcore-cli.js
CHANGED
|
@@ -157,6 +157,10 @@ __export(sandbox_exports, {
|
|
|
157
157
|
Sandbox: () => Sandbox,
|
|
158
158
|
runSandboxRunner: () => runSandboxRunner
|
|
159
159
|
});
|
|
160
|
+
import { spawn } from "child_process";
|
|
161
|
+
import { mkdtempSync, rmSync } from "fs";
|
|
162
|
+
import { tmpdir } from "os";
|
|
163
|
+
import { join, resolve as resolvePath } from "path";
|
|
160
164
|
async function runSandboxRunner(moduleId) {
|
|
161
165
|
const extensionsRoot = process.env.APCORE_EXTENSIONS_ROOT ?? "./extensions";
|
|
162
166
|
const apcore = await import("apcore-js").catch(() => {
|
|
@@ -260,13 +264,8 @@ var init_sandbox = __esm({
|
|
|
260
264
|
return this._sandboxedExecute(moduleId, inputData);
|
|
261
265
|
}
|
|
262
266
|
async _sandboxedExecute(moduleId, inputData) {
|
|
263
|
-
const
|
|
264
|
-
const { tmpdir } = await import("os");
|
|
265
|
-
const { join: join4 } = await import("path");
|
|
266
|
-
const { mkdtempSync, rmSync } = await import("fs");
|
|
267
|
-
const tmpDir = mkdtempSync(join4(tmpdir(), "apcore_sandbox_"));
|
|
267
|
+
const tmpDir = mkdtempSync(join(tmpdir(), "apcore_sandbox_"));
|
|
268
268
|
const env = buildSandboxEnv(tmpDir);
|
|
269
|
-
const { resolve: resolvePath } = await import("path");
|
|
270
269
|
if (this.extensionsRoot !== null) {
|
|
271
270
|
env.APCORE_EXTENSIONS_ROOT = resolvePath(this.extensionsRoot);
|
|
272
271
|
} else if (env.APCORE_EXTENSIONS_ROOT) {
|
|
@@ -4156,7 +4155,15 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
|
|
|
4156
4155
|
cmd.addHelpText("after", "\n" + footerParts.join("\n") + "\n");
|
|
4157
4156
|
}
|
|
4158
4157
|
for (const opt of schemaOptions) {
|
|
4159
|
-
if (opt.
|
|
4158
|
+
if (opt.isBooleanFlag) {
|
|
4159
|
+
const flagBase = opt.name.replace(/_/g, "-");
|
|
4160
|
+
cmd.addOption(
|
|
4161
|
+
new Option4(`--${flagBase}`, opt.description).default(
|
|
4162
|
+
opt.defaultValue
|
|
4163
|
+
)
|
|
4164
|
+
);
|
|
4165
|
+
cmd.addOption(new Option4(`--no-${flagBase}`).hideHelp());
|
|
4166
|
+
} else if (opt.parseArg) {
|
|
4160
4167
|
cmd.option(opt.flags, opt.description, opt.parseArg, opt.defaultValue);
|
|
4161
4168
|
} else {
|
|
4162
4169
|
cmd.option(opt.flags, opt.description, opt.defaultValue);
|
|
@@ -4180,24 +4187,12 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
|
|
|
4180
4187
|
);
|
|
4181
4188
|
const approvalToken = options.approvalToken;
|
|
4182
4189
|
const schemaKwargs = {};
|
|
4183
|
-
const
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
"sandbox",
|
|
4190
|
-
"verbose",
|
|
4191
|
-
"dryRun",
|
|
4192
|
-
"trace",
|
|
4193
|
-
"stream",
|
|
4194
|
-
"strategy",
|
|
4195
|
-
"approvalTimeout",
|
|
4196
|
-
"approvalToken"
|
|
4197
|
-
]);
|
|
4198
|
-
for (const [k, v] of Object.entries(options)) {
|
|
4199
|
-
if (!builtinKeys.has(k)) {
|
|
4200
|
-
schemaKwargs[k] = v;
|
|
4190
|
+
for (const opt of schemaOptions) {
|
|
4191
|
+
const commanderKey = opt.name.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
4192
|
+
if (commanderKey in options) {
|
|
4193
|
+
schemaKwargs[opt.name] = options[commanderKey];
|
|
4194
|
+
} else if (opt.name in options) {
|
|
4195
|
+
schemaKwargs[opt.name] = options[opt.name];
|
|
4201
4196
|
}
|
|
4202
4197
|
}
|
|
4203
4198
|
let merged = {};
|