lua-cli 3.21.0 → 3.22.0

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/dist/index.js CHANGED
@@ -3012,6 +3012,18 @@ var init_skill_handler = __esm({
3012
3012
  return toolData;
3013
3013
  }).filter(Boolean);
3014
3014
  const sourceArchive = buildSourceArchive(archiveEntries);
3015
+ let condition;
3016
+ let conditionS3Hash;
3017
+ if (skill.hasCondition) {
3018
+ const skillCode = loadArtifact(skill, projectPath);
3019
+ if (bundleAccumulator) {
3020
+ const rawGzip = compressForPushRaw(skillCode);
3021
+ conditionS3Hash = hashBundle(rawGzip);
3022
+ bundleAccumulator.set(conditionS3Hash, rawGzip);
3023
+ } else {
3024
+ condition = compressForPush(skillCode);
3025
+ }
3026
+ }
3015
3027
  return {
3016
3028
  name: skill.name,
3017
3029
  description: skill.description,
@@ -3020,6 +3032,12 @@ var init_skill_handler = __esm({
3020
3032
  context: skill.context
3021
3033
  } : {},
3022
3034
  tools,
3035
+ ...condition ? {
3036
+ condition
3037
+ } : {},
3038
+ ...conditionS3Hash ? {
3039
+ conditionS3Hash
3040
+ } : {},
3023
3041
  ...sourceArchive ? {
3024
3042
  sourceArchive,
3025
3043
  archiveSchemaVersion: SOURCE_ARCHIVE_SCHEMA_VERSION
@@ -6934,14 +6952,24 @@ var init_skill_plugin = __esm({
6934
6952
  // 2. Residual super-edge cases — `stripSuperCallsInConstructors` covers
6935
6953
  // top-level `super(...)` only; `super.method()` mid-constructor and
6936
6954
  // `field = super.x` survive a strip and explode at runtime.
6937
- // MAINTENANCE: this whitelist also assumes skills are JSON-only artifacts (via
6938
- // `buildArtifact`). If skills ever migrate to bundled JS, this drop will silently
6939
- // lose `tools` from skill bundlesre-evaluate.
6955
+ // MAINTENANCE: a skill WITH a `condition` is bundled through esbuild (see
6956
+ // `buildArtifact`), so every field the runtime needs off the bundle must be
6957
+ // listed here or it is silently dropped. `tools` stays out by design the
6958
+ // compiler resolves tool refs separately via `resolveArrayRefs`. The
6959
+ // whitelist only governs config literals; `dropClassMembers` is the same
6960
+ // drop for the class-definition shape, where a `tools = [...]` field or a
6961
+ // `this.addTool(...)` call would otherwise keep the tool imports live.
6940
6962
  crossFileRewrite = {
6941
6963
  fields: [
6942
6964
  "name",
6943
6965
  "description",
6944
- "context"
6966
+ "context",
6967
+ "condition"
6968
+ ],
6969
+ dropClassMembers: [
6970
+ "tools",
6971
+ "addTool",
6972
+ "addTools"
6945
6973
  ]
6946
6974
  };
6947
6975
  supportsClassDefinition = true;
@@ -6998,7 +7026,12 @@ var init_skill_plugin = __esm({
6998
7026
  pattern: "class-definition",
6999
7027
  context,
7000
7028
  toolRefs,
7001
- toolRefSourcePaths: Object.keys(toolRefSourcePaths).length > 0 ? toolRefSourcePaths : void 0
7029
+ toolRefSourcePaths: Object.keys(toolRefSourcePaths).length > 0 ? toolRefSourcePaths : void 0,
7030
+ // Emitted only when present so a condition-less skill's JSON artifact
7031
+ // stays byte-identical to pre-feature output.
7032
+ ...findClassMember(classDecl, "condition", "either") !== void 0 ? {
7033
+ hasCondition: true
7034
+ } : {}
7002
7035
  }
7003
7036
  };
7004
7037
  }
@@ -7054,7 +7087,10 @@ var init_skill_plugin = __esm({
7054
7087
  pattern,
7055
7088
  context,
7056
7089
  toolRefs,
7057
- toolRefSourcePaths: Object.keys(toolRefSourcePaths).length > 0 ? toolRefSourcePaths : void 0
7090
+ toolRefSourcePaths: Object.keys(toolRefSourcePaths).length > 0 ? toolRefSourcePaths : void 0,
7091
+ ...config.getProperty("condition") !== void 0 ? {
7092
+ hasCondition: true
7093
+ } : {}
7058
7094
  }
7059
7095
  };
7060
7096
  }
@@ -7199,13 +7235,19 @@ var init_skill_plugin = __esm({
7199
7235
  return rest;
7200
7236
  }
7201
7237
  /**
7202
- * Skills have no executable code and their artifact is never loaded at
7203
- * runtime (see `SkillHandler.prepareForPush` — it loads tool artifacts
7204
- * but never the skill's own). Emit a JSON metadata artifact instead of
7205
- * running esbuild on `new LuaSkill({...})`, which would otherwise bundle
7206
- * a non-executable shell (LuaSkill is stripped as an external import).
7238
+ * A skill without a `condition` has no executable code and its artifact is
7239
+ * never loaded at runtime (see `SkillHandler.prepareForPush` — it loads tool
7240
+ * artifacts, plus the skill's own only when it has a condition). Emit a JSON
7241
+ * metadata artifact instead of running esbuild on `new LuaSkill({...})`,
7242
+ * which would otherwise bundle a non-executable shell (LuaSkill is stripped
7243
+ * as an external import).
7244
+ *
7245
+ * A skill WITH a condition returns undefined to fall through to the standard
7246
+ * `generateEntryPoint → bundler.bundle → postProcess` esbuild path, same as
7247
+ * `AgentPlugin` with a model resolver.
7207
7248
  */
7208
7249
  async buildArtifact(metadata) {
7250
+ if (metadata.metadata.hasCondition) return void 0;
7209
7251
  const code = JSON.stringify({
7210
7252
  kind: metadata.kind,
7211
7253
  name: metadata.name,
@@ -7222,6 +7264,32 @@ var init_skill_plugin = __esm({
7222
7264
  };
7223
7265
  }
7224
7266
  /**
7267
+ * Project the class instance onto the skill primitive shape. Binds
7268
+ * `condition` to the instance so `this` references resolve correctly,
7269
+ * mirroring `ToolPlugin`. Skills have no `execute`, so the base shape
7270
+ * doesn't apply.
7271
+ */
7272
+ getClassDefinitionPrimitiveShape(metadata) {
7273
+ return `{
7274
+ kind: 'skill',
7275
+ name: __lua_instance__.name ?? ${JSON.stringify(metadata.name)},
7276
+ description: __lua_instance__.description ?? ${JSON.stringify(metadata.description)},
7277
+ context: __lua_instance__.context,
7278
+ condition: typeof __lua_instance__.condition === 'function' ? __lua_instance__.condition.bind(__lua_instance__) : undefined,
7279
+ }`;
7280
+ }
7281
+ /**
7282
+ * Runtime validation — a skill only reaches the bundled path when it
7283
+ * declares a condition, so the bundle must expose a callable one.
7284
+ */
7285
+ getRuntimeValidation(metadata) {
7286
+ if (!metadata.metadata.hasCondition) return "";
7287
+ return `
7288
+ if (typeof primitive.primitive?.condition !== 'function') {
7289
+ throw new Error('[Lua] Invalid skill artifact: condition is not a function');
7290
+ }`;
7291
+ }
7292
+ /**
7225
7293
  * Resolve tool references from this skill.
7226
7294
  *
7227
7295
  * Skills reference tools by class/variable name. This method:
@@ -7305,7 +7373,8 @@ var init_skill_plugin = __esm({
7305
7373
  return {
7306
7374
  ...this.baseManifestFields(compiled),
7307
7375
  context: skillMetadata.context,
7308
- tools: toolNames
7376
+ tools: toolNames,
7377
+ hasCondition: skillMetadata.hasCondition || false
7309
7378
  };
7310
7379
  }
7311
7380
  };
@@ -8121,7 +8190,7 @@ function rewriteCrossFileCallsInSourceFile(sf, specs, sdkBaseClassNames) {
8121
8190
  node.replaceWithText(buildBareObjectLiteral(spec, objArg));
8122
8191
  progressed = true;
8123
8192
  }
8124
- stripSdkExtendsClauses(sf, sdkBaseClassNames, aliasMap);
8193
+ stripSdkExtendsClauses(sf, sdkBaseClassNames, aliasMap, specs);
8125
8194
  }
8126
8195
  function warnUnsupportedNamespaceImports(sf) {
8127
8196
  for (const imp of sf.getImportDeclarations()) {
@@ -8141,20 +8210,29 @@ function warnUnsupportedNamespaceImports(sf) {
8141
8210
  }));
8142
8211
  }
8143
8212
  }
8144
- function stripSdkExtendsClauses(sf, sdkBaseClassNames, aliasMap) {
8145
- const matchesSdkClass = /* @__PURE__ */ __name((text) => {
8213
+ function stripSdkExtendsClauses(sf, sdkBaseClassNames, aliasMap, specs) {
8214
+ const matchSdkClass = /* @__PURE__ */ __name((text) => {
8146
8215
  const canonical = aliasMap.get(text) ?? text;
8147
- return sdkBaseClassNames.has(canonical);
8148
- }, "matchesSdkClass");
8216
+ return sdkBaseClassNames.has(canonical) ? canonical : void 0;
8217
+ }, "matchSdkClass");
8218
+ const dropNamesFor = /* @__PURE__ */ __name((canonical) => {
8219
+ const spec = specs.find((s) => s.classNames.includes(canonical));
8220
+ if (!spec?.dropClassMembers?.length) return void 0;
8221
+ return new Set(spec.dropClassMembers);
8222
+ }, "dropNamesFor");
8223
+ const strip = /* @__PURE__ */ __name((classNode, canonical) => {
8224
+ classNode.removeExtends();
8225
+ const dropNames = dropNamesFor(canonical);
8226
+ if (dropNames) stripDroppedClassMembers(classNode, dropNames);
8227
+ stripSuperCallsInConstructors(classNode);
8228
+ }, "strip");
8149
8229
  for (const classDecl of sf.getClasses()) {
8150
8230
  const ext = classDecl.getExtends();
8151
8231
  if (!ext) continue;
8152
8232
  const expr = ext.getExpression();
8153
8233
  if (!Node15.isIdentifier(expr)) continue;
8154
- if (matchesSdkClass(expr.getText())) {
8155
- classDecl.removeExtends();
8156
- stripSuperCallsInConstructors(classDecl);
8157
- }
8234
+ const canonical = matchSdkClass(expr.getText());
8235
+ if (canonical) strip(classDecl, canonical);
8158
8236
  }
8159
8237
  sf.forEachDescendant((n) => {
8160
8238
  if (!Node15.isClassExpression(n)) return;
@@ -8162,11 +8240,31 @@ function stripSdkExtendsClauses(sf, sdkBaseClassNames, aliasMap) {
8162
8240
  if (!ext) return;
8163
8241
  const expr = ext.getExpression();
8164
8242
  if (!Node15.isIdentifier(expr)) return;
8165
- if (matchesSdkClass(expr.getText())) {
8166
- n.removeExtends();
8167
- stripSuperCallsInConstructors(n);
8168
- }
8243
+ const canonical = matchSdkClass(expr.getText());
8244
+ if (canonical) strip(n, canonical);
8245
+ });
8246
+ }
8247
+ function stripDroppedClassMembers(classNode, dropNames) {
8248
+ for (const prop of classNode.getProperties()) {
8249
+ if (dropNames.has(prop.getName())) prop.remove();
8250
+ }
8251
+ const statements = [];
8252
+ classNode.forEachDescendant((n) => {
8253
+ if (!Node15.isExpressionStatement(n)) return;
8254
+ if (isThisRootedCallTo(n.getExpression(), dropNames)) statements.push(n);
8169
8255
  });
8256
+ for (const stmt of statements) stmt.remove();
8257
+ }
8258
+ function isThisRootedCallTo(expression, dropNames) {
8259
+ let current = expression;
8260
+ let matched = false;
8261
+ while (Node15.isCallExpression(current)) {
8262
+ const callee = current.getExpression();
8263
+ if (!Node15.isPropertyAccessExpression(callee)) return false;
8264
+ if (dropNames.has(callee.getName())) matched = true;
8265
+ current = callee.getExpression();
8266
+ }
8267
+ return matched && current.getKind() === ts3.SyntaxKind.ThisKeyword;
8170
8268
  }
8171
8269
  function stripSuperCallsInConstructors(classNode) {
8172
8270
  for (const ctor of classNode.getConstructors()) {
@@ -8273,6 +8371,8 @@ function buildBareObjectLiteral(spec, arg) {
8273
8371
  if (init) parts.push(`${f}: ${init.getText()}`);
8274
8372
  } else if (prop && Node15.isShorthandPropertyAssignment(prop)) {
8275
8373
  parts.push(`${f}: ${prop.getName()}`);
8374
+ } else if (prop && Node15.isMethodDeclaration(prop)) {
8375
+ parts.push(prop.getText());
8276
8376
  }
8277
8377
  }
8278
8378
  return `{ ${parts.join(", ")} }`;
@@ -8342,6 +8442,8 @@ var init_primitive_rewrite = __esm({
8342
8442
  __name(rewriteCrossFileCallsInSourceFile, "rewriteCrossFileCallsInSourceFile");
8343
8443
  __name(warnUnsupportedNamespaceImports, "warnUnsupportedNamespaceImports");
8344
8444
  __name(stripSdkExtendsClauses, "stripSdkExtendsClauses");
8445
+ __name(stripDroppedClassMembers, "stripDroppedClassMembers");
8446
+ __name(isThisRootedCallTo, "isThisRootedCallTo");
8345
8447
  __name(stripSuperCallsInConstructors, "stripSuperCallsInConstructors");
8346
8448
  __name(warnRemainingSuperReferences, "warnRemainingSuperReferences");
8347
8449
  __name(buildSdkAliasMap, "buildSdkAliasMap");
@@ -8364,16 +8466,19 @@ function buildCrossFileSpecs(plugins = pluginRegistry.getAll()) {
8364
8466
  ...plugin.legacyClassNames
8365
8467
  ];
8366
8468
  const defineFunction = plugin.defineFunction || void 0;
8469
+ const dropClassMembers = plugin.crossFileRewrite.dropClassMembers;
8367
8470
  if ("copyAllFields" in plugin.crossFileRewrite && plugin.crossFileRewrite.copyAllFields) {
8368
8471
  specs.push({
8369
8472
  classNames,
8370
8473
  defineFunction,
8474
+ dropClassMembers,
8371
8475
  mode: "copyAllFields"
8372
8476
  });
8373
8477
  } else if ("fields" in plugin.crossFileRewrite) {
8374
8478
  specs.push({
8375
8479
  classNames,
8376
8480
  defineFunction,
8481
+ dropClassMembers,
8377
8482
  mode: "whitelist",
8378
8483
  fields: plugin.crossFileRewrite.fields
8379
8484
  });
@@ -20203,6 +20308,22 @@ function buildSandboxProcess(opts) {
20203
20308
  const nextTickFn = /* @__PURE__ */ __name4((cb, ...args2) => {
20204
20309
  process.nextTick(cb, ...args2);
20205
20310
  }, "nextTickFn");
20311
+ const buildStdioStub = /* @__PURE__ */ __name4((fd) => {
20312
+ const stub = {
20313
+ fd,
20314
+ isTTY: false,
20315
+ write: /* @__PURE__ */ __name4(() => true, "write"),
20316
+ end: /* @__PURE__ */ __name4(() => stub, "end"),
20317
+ on: /* @__PURE__ */ __name4(() => stub, "on"),
20318
+ once: /* @__PURE__ */ __name4(() => stub, "once"),
20319
+ removeListener: /* @__PURE__ */ __name4(() => stub, "removeListener"),
20320
+ cork: /* @__PURE__ */ __name4(() => {
20321
+ }, "cork"),
20322
+ uncork: /* @__PURE__ */ __name4(() => {
20323
+ }, "uncork")
20324
+ };
20325
+ return stub;
20326
+ }, "buildStdioStub");
20206
20327
  const proc = {
20207
20328
  env: opts.envVars,
20208
20329
  version: process.version,
@@ -20212,6 +20333,8 @@ function buildSandboxProcess(opts) {
20212
20333
  platform: process.platform,
20213
20334
  arch: process.arch,
20214
20335
  pid: process.pid,
20336
+ stdout: buildStdioStub(1),
20337
+ stderr: buildStdioStub(2),
20215
20338
  nextTick: nextTickFn,
20216
20339
  hrtime: hrtimeFn,
20217
20340
  // Lie — don't leak host filesystem layout. Skills should not depend on