@actiondock/core 2.9.1 → 2.10.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.
@@ -57,10 +57,13 @@ export class UndeclaredActionDependencyError extends ActionDockError {
57
57
  targetRef;
58
58
  caller;
59
59
  constructor(targetRef, caller, reason) {
60
+ const hint = caller
61
+ ? `Hint: Add '${targetRef}' to the 'uses' array of action '${caller}' in actiondock.json, then run 'ad validate'.`
62
+ : undefined;
60
63
  const msg = caller
61
- ? `UNDECLARED_ACTION_DEPENDENCY: Action '${caller}' 未在 'uses' 中声明对 '${targetRef}' 的跨包依赖`
64
+ ? `UNDECLARED_ACTION_DEPENDENCY: Action '${caller}' 未在 'uses' 中声明对 '${targetRef}' 的跨包依赖${hint ? `\n${hint}` : ""}`
62
65
  : `UNDECLARED_ACTION_DEPENDENCY: 根调用 Action '${targetRef}' 被拒绝: 目标包既非 actiondock.json 直接依赖,亦未被可见 Playbook 委托${reason ? ` (${reason})` : ""}`;
63
- super(UNDECLARED_ACTION_DEPENDENCY, msg);
66
+ super(UNDECLARED_ACTION_DEPENDENCY, msg, hint ? { hint } : undefined, undefined, hint);
64
67
  this.name = "UndeclaredActionDependencyError";
65
68
  this.targetRef = targetRef;
66
69
  this.caller = caller;
@@ -115,7 +115,7 @@ async function checkProjectActions(scope) {
115
115
  name: "Actions",
116
116
  status: "warn",
117
117
  message: `No actions found in '${config.actionsDir || "actions"}'`,
118
- fix: "Run 'ad action new <id>' to create your first action",
118
+ fix: "Run 'ad action create <id>' to create your first action",
119
119
  });
120
120
  }
121
121
  else {
@@ -155,7 +155,7 @@ function checkProjectManifest(scope) {
155
155
  name: "Action Manifest",
156
156
  status: "warn",
157
157
  message: `${MANIFEST_FILE_NAME} not found (${actionFiles.length} action source file(s) exist)`,
158
- fix: "Run 'ad validate' to generate or check manifest",
158
+ fix: "Run 'ad init' to initialize project manifest, or manually create 'actiondock.json'",
159
159
  });
160
160
  }
161
161
  }
@@ -174,7 +174,7 @@ function checkProjectManifest(scope) {
174
174
  name: "Action Manifest",
175
175
  status: "warn",
176
176
  message: `${missingFiles.length} action(s) in manifest point to missing files: ${missingFiles.join(", ")}`,
177
- fix: "Run 'ad validate' to check or update actiondock.json",
177
+ fix: "Update actiondock.json or use 'ad action create <id>'",
178
178
  });
179
179
  }
180
180
  else if (untracked.length > 0) {
@@ -184,7 +184,7 @@ function checkProjectManifest(scope) {
184
184
  name: "Action Manifest",
185
185
  status: "warn",
186
186
  message: `${untracked.length} action file(s) not declared in manifest: ${untracked.join(", ")}`,
187
- fix: "Run 'ad validate' to check or update actiondock.json",
187
+ fix: "Update actiondock.json or use 'ad action create <id>'",
188
188
  });
189
189
  }
190
190
  else {
@@ -88,7 +88,7 @@ export const checkLinkedPackageDependencies = {
88
88
  name: "Linked Package Dependencies",
89
89
  status: "warn",
90
90
  message: `${missingNodeModules.length} linked package(s) declare dependencies but miss node_modules: ${missingNodeModules.join(", ")}`,
91
- fix: "Run 'npm install' in the affected package directories, or execute 'ad run' to auto-install",
91
+ fix: "Run 'npm install --omit=dev' in the affected package directories",
92
92
  });
93
93
  }
94
94
  else {
package/dist/errors.d.ts CHANGED
@@ -262,8 +262,39 @@ export declare class ActionDockError<T = any> extends Error {
262
262
  readonly code: ErrorCode;
263
263
  readonly details?: T;
264
264
  readonly status?: number;
265
- constructor(code: ErrorCode, message: string, details?: T, status?: number);
265
+ readonly hint?: string;
266
+ constructor(code: ErrorCode, message: string, details?: T, status?: number, hint?: string);
266
267
  }
268
+ /**
269
+ * 结构化机器错误信封。
270
+ */
271
+ export interface ErrorEnvelope {
272
+ ok: false;
273
+ error: {
274
+ code: string;
275
+ message: string;
276
+ details?: unknown;
277
+ };
278
+ hint?: string;
279
+ meta?: Record<string, unknown>;
280
+ }
281
+ /**
282
+ * 统一构造机器错误信封。
283
+ */
284
+ export declare function createErrorEnvelope(code: string, message: string, details?: unknown, meta?: Record<string, unknown>, hint?: string): ErrorEnvelope;
285
+ /**
286
+ * 根据 Action 执行失败错误解析自愈指引提示文案。
287
+ *
288
+ * 作为 CLI 与独立分发器(StandaloneDispatcher)执行失败时提示解析的单一事实源。
289
+ *
290
+ * @param targetRef 目标 Action 引用标识(如 "greet" 或 "pkg/greet")
291
+ * @param error 执行失败错误对象
292
+ */
293
+ export declare function resolveExecutionHint(targetRef: string, error?: {
294
+ code?: string;
295
+ details?: unknown;
296
+ hint?: string;
297
+ }): string | undefined;
267
298
  /**
268
299
  * 集中定义的标准结构化错误码联合类型。
269
300
  */
package/dist/errors.js CHANGED
@@ -178,7 +178,7 @@ export function describeActionLoadFailure(err, context) {
178
178
  const rootCause = err instanceof Error ? err.message : String(err ?? "");
179
179
  const isMissingModule = isMissingModuleError(rootCause);
180
180
  const hint = isMissingModule
181
- ? `依赖未安装,在 '${context.projectRoot}' 执行 npm install 或先执行 'ad run ${context.packageId}/${context.actionId}'`
181
+ ? `项目依赖缺失,请在 '${context.projectRoot}' 目录下运行 'npm install --omit=dev' 安装依赖后再试。`
182
182
  : undefined;
183
183
  return {
184
184
  code: ACTION_LOAD_FAILED,
@@ -263,15 +263,75 @@ export class ActionDockError extends Error {
263
263
  code;
264
264
  details;
265
265
  status;
266
- constructor(code, message, details, status) {
266
+ hint;
267
+ constructor(code, message, details, status, hint) {
267
268
  super(message);
268
269
  this.name = "ActionDockError";
269
270
  this.code = code;
270
271
  this.details = details;
271
272
  this.status = status;
273
+ this.hint =
274
+ hint ??
275
+ (details && typeof details === "object" && typeof details.hint === "string"
276
+ ? details.hint
277
+ : undefined);
272
278
  Object.setPrototypeOf(this, ActionDockError.prototype);
273
279
  }
274
280
  }
281
+ /**
282
+ * 统一构造机器错误信封。
283
+ */
284
+ export function createErrorEnvelope(code, message, details, meta, hint) {
285
+ const effectiveHint = hint ??
286
+ (details && typeof details === "object" && typeof details.hint === "string"
287
+ ? details.hint
288
+ : undefined);
289
+ const result = {
290
+ ok: false,
291
+ error: {
292
+ code,
293
+ message,
294
+ ...(details !== undefined ? { details } : {}),
295
+ },
296
+ };
297
+ if (effectiveHint !== undefined) {
298
+ result.hint = effectiveHint;
299
+ }
300
+ if (meta && Object.keys(meta).length > 0) {
301
+ result.meta = meta;
302
+ }
303
+ return result;
304
+ }
305
+ /**
306
+ * 根据 Action 执行失败错误解析自愈指引提示文案。
307
+ *
308
+ * 作为 CLI 与独立分发器(StandaloneDispatcher)执行失败时提示解析的单一事实源。
309
+ *
310
+ * @param targetRef 目标 Action 引用标识(如 "greet" 或 "pkg/greet")
311
+ * @param error 执行失败错误对象
312
+ */
313
+ export function resolveExecutionHint(targetRef, error) {
314
+ if (!error)
315
+ return undefined;
316
+ if (error.code === INPUT_VALIDATION_FAILED) {
317
+ return `Tip: Run 'ad describe ${targetRef}' to inspect schema and syntax examples.`;
318
+ }
319
+ if (error.code === ACTION_NOT_FOUND) {
320
+ return "Tip: Run 'ad list' to discover available actions, or 'ad info' to inspect packages.";
321
+ }
322
+ if (error.code === ACTION_TIMEOUT) {
323
+ return "Tip: Increase timeout via '--timeout <duration>', or run in background via '--async' and track with 'ad runs show <runId>'.";
324
+ }
325
+ if (error.hint && typeof error.hint === "string") {
326
+ return error.hint;
327
+ }
328
+ if (error.details &&
329
+ typeof error.details === "object" &&
330
+ typeof error.details.hint === "string") {
331
+ return error.details.hint;
332
+ }
333
+ return undefined;
334
+ }
275
335
  /**
276
336
  * 进程领域结构化异常类。
277
337
  */
package/dist/host/host.js CHANGED
@@ -368,7 +368,9 @@ export class DefaultActionDockHost {
368
368
  declaredUses,
369
369
  }, { packageId: targetPackageId, actionId: targetActionId }, this.graph);
370
370
  if (authErr) {
371
- throw new ActionDockError(authErr.code, authErr.message, authErr.details);
371
+ const hint = authErr.details?.hint;
372
+ const msg = hint ? `${authErr.message}\n${hint}` : authErr.message;
373
+ throw new ActionDockError(authErr.code, msg, authErr.details, undefined, hint);
372
374
  }
373
375
  }
374
376
  // 调用嵌套深度限制校验
package/dist/index.d.ts CHANGED
@@ -20,4 +20,4 @@ export { initProject } from "./project/init.js";
20
20
  export { loadProjectConfig, findProjectRoot, } from "./project/loader.js";
21
21
  export type { ProjectConfig, } from "./project/types.js";
22
22
  export type { PackageGraph, } from "./catalog/graph.js";
23
- export { ActionDockError, ProcessError, type ErrorCode, type ActionDockErrorCode, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, INVOCATION_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, REMOTE_STREAM_UNAVAILABLE, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, STORAGE_WORKER_EXITED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, BAD_REQUEST, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, ACTIONS_LIST_ERROR, PLAYBOOKS_LIST_ERROR, RUNS_LIST_ERROR, RUNS_CLEAR_ERROR, INFO_ERROR, PACKAGES_INFO_ERROR, DOCTOR_ERROR, RUN_INTERRUPTED, CONFIG_ENV_ERROR, CONFIG_LIST_ERROR, CONFIG_SET_ERROR, CONFIG_DELETE_ERROR, STATE_LIST_ERROR, STATE_CLEAR_ERROR, STATE_KEY_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, UNSUPPORTED_STORAGE_SCHEMA, STORED_ERROR_DECODE_FAILED, PROCESS_FAILED, GENERATED_TYPES_OUTDATED, PROTOCOL_UNSUPPORTED, SERVICE_RESULT_UNKNOWN, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, UNSUPPORTED_CAPABILITY, CONTROL_BUSY, CONTROL_EXPIRED, CONTROL_REVOKED, PROCESS_QUARANTINED, PROCESS_LOST, REQUEST_CONFLICT, INPUT_OUTCOME_UNKNOWN, OUTPUT_GAP, OUTPUT_UNAVAILABLE, INVALID_CURSOR, QUEUE_FULL, QUOTA_EXCEEDED, INPUT_CLOSED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, IPC_ERROR, } from "./errors.js";
23
+ export { ActionDockError, ProcessError, type ErrorCode, type ActionDockErrorCode, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, INVOCATION_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, REMOTE_STREAM_UNAVAILABLE, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, STORAGE_WORKER_EXITED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, BAD_REQUEST, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, ACTIONS_LIST_ERROR, PLAYBOOKS_LIST_ERROR, RUNS_LIST_ERROR, RUNS_CLEAR_ERROR, INFO_ERROR, PACKAGES_INFO_ERROR, DOCTOR_ERROR, RUN_INTERRUPTED, CONFIG_ENV_ERROR, CONFIG_LIST_ERROR, CONFIG_SET_ERROR, CONFIG_DELETE_ERROR, STATE_LIST_ERROR, STATE_CLEAR_ERROR, STATE_KEY_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, UNSUPPORTED_STORAGE_SCHEMA, STORED_ERROR_DECODE_FAILED, PROCESS_FAILED, GENERATED_TYPES_OUTDATED, PROTOCOL_UNSUPPORTED, SERVICE_RESULT_UNKNOWN, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, UNSUPPORTED_CAPABILITY, CONTROL_BUSY, CONTROL_EXPIRED, CONTROL_REVOKED, PROCESS_QUARANTINED, PROCESS_LOST, REQUEST_CONFLICT, INPUT_OUTCOME_UNKNOWN, OUTPUT_GAP, OUTPUT_UNAVAILABLE, INVALID_CURSOR, QUEUE_FULL, QUOTA_EXCEEDED, INPUT_CLOSED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, IPC_ERROR, describeActionLoadFailure, type ActionLoadFailureContext, createErrorEnvelope, type ErrorEnvelope, resolveExecutionHint, } from "./errors.js";
package/dist/index.js CHANGED
@@ -18,4 +18,4 @@ export { startActionDockServer, } from "./server/server.js";
18
18
  export { initProject } from "./project/init.js";
19
19
  export { loadProjectConfig, findProjectRoot, } from "./project/loader.js";
20
20
  // 8. 统一错误模型与核心标准错误码常量
21
- export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, INVOCATION_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, REMOTE_STREAM_UNAVAILABLE, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, STORAGE_WORKER_EXITED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, BAD_REQUEST, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, ACTIONS_LIST_ERROR, PLAYBOOKS_LIST_ERROR, RUNS_LIST_ERROR, RUNS_CLEAR_ERROR, INFO_ERROR, PACKAGES_INFO_ERROR, DOCTOR_ERROR, RUN_INTERRUPTED, CONFIG_ENV_ERROR, CONFIG_LIST_ERROR, CONFIG_SET_ERROR, CONFIG_DELETE_ERROR, STATE_LIST_ERROR, STATE_CLEAR_ERROR, STATE_KEY_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, UNSUPPORTED_STORAGE_SCHEMA, STORED_ERROR_DECODE_FAILED, PROCESS_FAILED, GENERATED_TYPES_OUTDATED, PROTOCOL_UNSUPPORTED, SERVICE_RESULT_UNKNOWN, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, UNSUPPORTED_CAPABILITY, CONTROL_BUSY, CONTROL_EXPIRED, CONTROL_REVOKED, PROCESS_QUARANTINED, PROCESS_LOST, REQUEST_CONFLICT, INPUT_OUTCOME_UNKNOWN, OUTPUT_GAP, OUTPUT_UNAVAILABLE, INVALID_CURSOR, QUEUE_FULL, QUOTA_EXCEEDED, INPUT_CLOSED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, IPC_ERROR, } from "./errors.js";
21
+ export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, INVOCATION_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, REMOTE_STREAM_UNAVAILABLE, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, STORAGE_WORKER_EXITED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, BAD_REQUEST, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, ACTIONS_LIST_ERROR, PLAYBOOKS_LIST_ERROR, RUNS_LIST_ERROR, RUNS_CLEAR_ERROR, INFO_ERROR, PACKAGES_INFO_ERROR, DOCTOR_ERROR, RUN_INTERRUPTED, CONFIG_ENV_ERROR, CONFIG_LIST_ERROR, CONFIG_SET_ERROR, CONFIG_DELETE_ERROR, STATE_LIST_ERROR, STATE_CLEAR_ERROR, STATE_KEY_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, UNSUPPORTED_STORAGE_SCHEMA, STORED_ERROR_DECODE_FAILED, PROCESS_FAILED, GENERATED_TYPES_OUTDATED, PROTOCOL_UNSUPPORTED, SERVICE_RESULT_UNKNOWN, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, UNSUPPORTED_CAPABILITY, CONTROL_BUSY, CONTROL_EXPIRED, CONTROL_REVOKED, PROCESS_QUARANTINED, PROCESS_LOST, REQUEST_CONFLICT, INPUT_OUTCOME_UNKNOWN, OUTPUT_GAP, OUTPUT_UNAVAILABLE, INVALID_CURSOR, QUEUE_FULL, QUOTA_EXCEEDED, INPUT_CLOSED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, IPC_ERROR, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
@@ -47,6 +47,8 @@ export interface ActionDescribePayload {
47
47
  entry?: string;
48
48
  /** 统一输入模式建议 */
49
49
  inputAdvice: ActionDescribeAdvice;
50
+ /** 扁平输入通用语法速查行列表 */
51
+ syntaxReference?: string[];
50
52
  }
51
53
  /**
52
54
  * 构造 Action 描述载荷的可选选项。
@@ -82,6 +84,10 @@ export declare function buildActionDescribePayload(spec: {
82
84
  entry?: string;
83
85
  [key: string]: any;
84
86
  }, options?: BuildActionDescribePayloadOptions): ActionDescribePayload;
87
+ /**
88
+ * 扁平输入通用语法速查行列表。
89
+ */
90
+ export declare const ACTION_DESCRIBE_SYNTAX_REFERENCE: readonly string[];
85
91
  /**
86
92
  * 格式化渲染 Action 详情人类可读文本。
87
93
  * 普通 CLI 与 Standalone 统一复用该函数,避免长期排版漂移。
@@ -109,8 +109,26 @@ export function buildActionDescribePayload(spec, options) {
109
109
  ...(spec.entry !== undefined ? { entry: spec.entry } : {}),
110
110
  inputAdvice: computeActionDescribeAdvice(spec.inputSchema),
111
111
  };
112
+ const hasAssignments = Boolean(payload.inputAdvice.assignments &&
113
+ Object.keys(payload.inputAdvice.assignments).length > 0);
114
+ if (payload.inputAdvice.recommendedMode === "flat" || hasAssignments) {
115
+ payload.syntaxReference = [...ACTION_DESCRIBE_SYNTAX_REFERENCE];
116
+ }
112
117
  return payload;
113
118
  }
119
+ /**
120
+ * 扁平输入通用语法速查行列表。
121
+ */
122
+ export const ACTION_DESCRIBE_SYNTAX_REFERENCE = [
123
+ " # String assignment (= keeps raw string, no type coercion)",
124
+ ' key="value"',
125
+ " # Typed / JSON assignment (:= parses numbers, booleans, arrays, objects)",
126
+ " count:=10 enabled:=true",
127
+ " # Array structure (direct JSON array or sequential index)",
128
+ ' tags:=\'["a", "b"]\' (or tags.0="a" tags.1="b")',
129
+ " # Complex or multiline inputs (pass via JSON file)",
130
+ " --input-file input.json",
131
+ ];
114
132
  /**
115
133
  * 格式化渲染 Action 详情人类可读文本。
116
134
  * 普通 CLI 与 Standalone 统一复用该函数,避免长期排版漂移。
@@ -158,13 +176,20 @@ export function formatActionDetail(input) {
158
176
  if (payload.inputAdvice.reason) {
159
177
  lines.push(`Reason: ${payload.inputAdvice.reason}`);
160
178
  }
161
- if (payload.inputAdvice.assignments && Object.keys(payload.inputAdvice.assignments).length > 0) {
179
+ const hasAssignments = Boolean(payload.inputAdvice.assignments &&
180
+ Object.keys(payload.inputAdvice.assignments).length > 0);
181
+ if (hasAssignments) {
162
182
  lines.push("");
163
183
  lines.push("Assignments:");
164
184
  for (const [key, op] of Object.entries(payload.inputAdvice.assignments)) {
165
185
  lines.push(` ${key}${op}`);
166
186
  }
167
187
  }
188
+ if (payload.inputAdvice.recommendedMode === "flat" || hasAssignments) {
189
+ lines.push("");
190
+ lines.push("Syntax Reference:");
191
+ lines.push(...(payload.syntaxReference || ACTION_DESCRIBE_SYNTAX_REFERENCE));
192
+ }
168
193
  if (payload.inputAdvice.issues && payload.inputAdvice.issues.length > 0) {
169
194
  lines.push("");
170
195
  lines.push("Issues:");
@@ -173,7 +173,7 @@ export async function resolveActionInput(options) {
173
173
  if (hasFileJson)
174
174
  modeCount++;
175
175
  if (modeCount > 1) {
176
- const err = inputConflict("Input options conflict: flatArgs, input, and inputFile are mutually exclusive", {
176
+ const err = inputConflict("Input options conflict: flat arguments (-- key=val), inline JSON (-i/--input), and file (-f/--input-file) are mutually exclusive. Specify only one input mode.", {
177
177
  reason: "MULTIPLE_INPUT_MODES",
178
178
  hasFlatArgs: effectiveFlat,
179
179
  hasInput: hasInlineJson,
@@ -93,6 +93,7 @@ export class InvocationPolicy {
93
93
  ? graph.canCascadeCall(caller.packageId, caller.actionId, target.packageId, target.actionId)
94
94
  : usesList.some((u) => isUsesDeclared(u, target.packageId, target.actionId));
95
95
  if (!isAllowed) {
96
+ const hint = `Hint: Add '${targetRef}' to the 'uses' array of action '${caller.actionId}' in actiondock.json, then run 'ad validate'.`;
96
97
  return {
97
98
  code: UNDECLARED_ACTION_DEPENDENCY,
98
99
  message: `Undeclared cross-package dependency: Action '${caller.packageId}/${caller.actionId}' does not declare dependency on '${targetRef}' in 'uses'`,
@@ -100,6 +101,7 @@ export class InvocationPolicy {
100
101
  caller: `${caller.packageId}/${caller.actionId}`,
101
102
  target: targetRef,
102
103
  declaredUses: usesList,
104
+ hint,
103
105
  },
104
106
  };
105
107
  }
@@ -10,7 +10,7 @@ export * from "./types-generator.js";
10
10
  export { assertPathWithinRoot, isPathOutsideBoundary, getPackageSlug, parseDuration, traverseDirectory, type TraverseDirectoryEntry, type TraverseDirectoryOptions, } from "../utils/index.js";
11
11
  export { isSecretConfigKey, maskSecretValue, sanitizeConfigDefinitions, } from "../storage/mask.js";
12
12
  export { runDoctorChecks, } from "../doctor/doctor.js";
13
- export { resolveActionInput, buildActionInputAdvice, formatActionDetail, buildActionDescribePayload, mapInputValidationFailure, stripBom, readStdinBounded, type ResolveActionInputOptions, type ReadStdinBoundedOptions, } from "../input/index.js";
13
+ export { resolveActionInput, buildActionInputAdvice, formatActionDetail, buildActionDescribePayload, ACTION_DESCRIBE_SYNTAX_REFERENCE, mapInputValidationFailure, stripBom, readStdinBounded, type ResolveActionInputOptions, type ReadStdinBoundedOptions, } from "../input/index.js";
14
14
  export { validateActionInputValue } from "../json/value-validator.js";
15
15
  export { parseJson } from "../input/input-resolver.js";
16
16
  export { InputError, FlatInputError, } from "../input/flat-errors.js";
@@ -11,7 +11,7 @@ export { assertPathWithinRoot, isPathOutsideBoundary, getPackageSlug, parseDurat
11
11
  export { isSecretConfigKey, maskSecretValue, sanitizeConfigDefinitions, } from "../storage/mask.js";
12
12
  export { runDoctorChecks, } from "../doctor/doctor.js";
13
13
  // 动作入参解析、校验与格式化(含 BOM 剥离与标准输入有界读取的单一事实源转引)
14
- export { resolveActionInput, buildActionInputAdvice, formatActionDetail, buildActionDescribePayload, mapInputValidationFailure, stripBom, readStdinBounded, } from "../input/index.js";
14
+ export { resolveActionInput, buildActionInputAdvice, formatActionDetail, buildActionDescribePayload, ACTION_DESCRIBE_SYNTAX_REFERENCE, mapInputValidationFailure, stripBom, readStdinBounded, } from "../input/index.js";
15
15
  export { validateActionInputValue } from "../json/value-validator.js";
16
16
  export { parseJson } from "../input/input-resolver.js";
17
17
  export { InputError, FlatInputError, } from "../input/flat-errors.js";
@@ -86,10 +86,10 @@ export function initProject(targetDir, options = {}) {
86
86
  node: ">=24.12.0",
87
87
  },
88
88
  dependencies: {
89
- "@actiondock/sdk": "^2.9.1",
89
+ "@actiondock/sdk": "^2.10.0",
90
90
  },
91
91
  devDependencies: {
92
- "@actiondock/testing": "^2.9.1",
92
+ "@actiondock/testing": "^2.10.0",
93
93
  "@types/node": "^22.13.0",
94
94
  "tsx": "^4.19.0",
95
95
  "typescript": "^5.7.0",
@@ -214,7 +214,7 @@ export async function loadActions(projectRoot, _actionsDir = "actions", options
214
214
  entryPath,
215
215
  rootCause: msg,
216
216
  hint: isMissingModuleError(msg)
217
- ? `项目依赖缺失,请在 '${projectRoot}' 目录下运行 npm install 安装依赖。`
217
+ ? `项目依赖缺失,请在 '${projectRoot}' 目录下运行 'npm install --omit=dev' 安装依赖后再试。`
218
218
  : undefined,
219
219
  };
220
220
  throw error;
@@ -1,7 +1,7 @@
1
1
  import { decodeStateKey } from "@actiondock/sdk";
2
2
  import { filterWithFallbackInfo } from "../filter/index.js";
3
3
  import { createActionDock } from "../service/factory.js";
4
- import { STANDALONE_ASYNC_UNSUPPORTED } from "../errors.js";
4
+ import { STANDALONE_ASYNC_UNSUPPORTED, resolveExecutionHint, } from "../errors.js";
5
5
  import { resolveActionInput, formatActionDetail, buildActionDescribePayload, mapInputValidationFailure, } from "../input/index.js";
6
6
  import { validateActionInputValue } from "../json/value-validator.js";
7
7
  import { normalizeActionCollection } from "./action-collection.js";
@@ -62,6 +62,10 @@ export class StandaloneDispatcher {
62
62
  emitError(isJson, code, message, exitCode, options) {
63
63
  if (isJson) {
64
64
  const details = options?.details;
65
+ const hint = options?.hint ??
66
+ (details && typeof details === "object" && typeof details.hint === "string"
67
+ ? details.hint
68
+ : undefined);
65
69
  this.writeOut(JSON.stringify({
66
70
  ok: false,
67
71
  error: {
@@ -69,6 +73,7 @@ export class StandaloneDispatcher {
69
73
  message,
70
74
  ...(details !== undefined ? { details } : {}),
71
75
  },
76
+ ...(hint !== undefined ? { hint } : {}),
72
77
  }, null, 2));
73
78
  }
74
79
  else {
@@ -249,8 +254,11 @@ export class StandaloneDispatcher {
249
254
  description: a.description || "",
250
255
  }));
251
256
  const filterRes = filterWithFallbackInfo(list, effectiveIntent, [(a) => a.id, (a) => a.description], !noFallback);
257
+ const hints = [
258
+ "Tip: For composite or multi-step tasks, check 'ad playbook list' for standard operating procedures.",
259
+ ];
252
260
  if (isJson) {
253
- this.writeOut(JSON.stringify(filterRes.items, null, 2));
261
+ this.writeOut(JSON.stringify({ items: filterRes.items, hints }, null, 2));
254
262
  }
255
263
  else {
256
264
  let text = `Actions in ${this.options.packageId} (v${this.options.version}):\n\n`;
@@ -272,7 +280,11 @@ export class StandaloneDispatcher {
272
280
  action = await service.discovery.describeAction(id);
273
281
  }
274
282
  catch {
275
- return this.emitError(isJson, "INVALID_ARGUMENT", `Action '${id}' not found`, ExitCode.INVALID_ARGUMENT);
283
+ const hint = "Tip: Run 'ad list' to discover available actions.";
284
+ return this.emitError(isJson, "INVALID_ARGUMENT", `Action '${id}' not found`, ExitCode.INVALID_ARGUMENT, {
285
+ textMessage: `Error: Action '${id}' not found\n${hint}`,
286
+ hint,
287
+ });
276
288
  }
277
289
  const payload = buildActionDescribePayload(action, {
278
290
  packageId: this.options.packageId,
@@ -294,8 +306,12 @@ export class StandaloneDispatcher {
294
306
  let inputStr;
295
307
  let inputFile;
296
308
  let timeoutMs;
309
+ const recognizedFlags = new Set(["--json", "--async"]);
297
310
  for (let i = 0; i < subArgs.length; i++) {
298
311
  const arg = subArgs[i];
312
+ if (arg === id || recognizedFlags.has(arg)) {
313
+ continue;
314
+ }
299
315
  if (arg === "--timeout" && i + 1 < subArgs.length) {
300
316
  try {
301
317
  timeoutMs = parseDuration(subArgs[++i]);
@@ -318,12 +334,31 @@ export class StandaloneDispatcher {
318
334
  else if (arg.startsWith("--input=")) {
319
335
  inputStr = arg.slice(8);
320
336
  }
337
+ else if (arg === "-i" && i + 1 < subArgs.length) {
338
+ inputStr = subArgs[++i];
339
+ }
340
+ else if (arg.startsWith("-i=")) {
341
+ inputStr = arg.slice(3);
342
+ }
321
343
  else if (arg === "--input-file" && i + 1 < subArgs.length) {
322
344
  inputFile = subArgs[++i];
323
345
  }
324
346
  else if (arg.startsWith("--input-file=")) {
325
347
  inputFile = arg.slice(13);
326
348
  }
349
+ else if (arg === "-f" && i + 1 < subArgs.length) {
350
+ inputFile = subArgs[++i];
351
+ }
352
+ else if (arg.startsWith("-f=")) {
353
+ inputFile = arg.slice(3);
354
+ }
355
+ else if (arg.startsWith("-")) {
356
+ const hint = "Hint: Separate action inputs from CLI options using '--', e.g.: ad run <id> [options] -- <param>=<val> or <param>:=<json>.";
357
+ return this.emitError(isJson, "INVALID_ARGUMENT", `error: unknown option '${arg}'`, ExitCode.INVALID_ARGUMENT, {
358
+ textMessage: `error: unknown option '${arg}'\n${hint}`,
359
+ hint,
360
+ });
361
+ }
327
362
  }
328
363
  let input;
329
364
  try {
@@ -348,7 +383,14 @@ export class StandaloneDispatcher {
348
383
  timeoutMs,
349
384
  });
350
385
  if (isJson) {
351
- this.writeOut(JSON.stringify(result, null, 2));
386
+ if (!result.ok) {
387
+ const hint = resolveExecutionHint(id, result.error);
388
+ const machineOutput = hint !== undefined ? { ...result, hint } : result;
389
+ this.writeOut(JSON.stringify(machineOutput, null, 2));
390
+ }
391
+ else {
392
+ this.writeOut(JSON.stringify(result, null, 2));
393
+ }
352
394
  }
353
395
  else {
354
396
  if (result.ok) {
@@ -428,6 +470,10 @@ export class StandaloneDispatcher {
428
470
  ? result.error.details
429
471
  : JSON.stringify(result.error.details, null, 2));
430
472
  }
473
+ const hint = resolveExecutionHint(id, result.error);
474
+ if (hint) {
475
+ this.writeErr(hint);
476
+ }
431
477
  }
432
478
  }
433
479
  return result.ok ? ExitCode.SUCCESS : ExitCode.FAILURE;
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * ActionDock 核心版本号单一事实源。
3
3
  */
4
- export declare const ACTIONDOCK_VERSION = "2.9.1";
4
+ export declare const ACTIONDOCK_VERSION = "2.10.0";
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * ActionDock 核心版本号单一事实源。
3
3
  */
4
- export const ACTIONDOCK_VERSION = "2.9.1";
4
+ export const ACTIONDOCK_VERSION = "2.10.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actiondock/core",
3
- "version": "2.9.1",
3
+ "version": "2.10.0",
4
4
  "description": "ActionDock Core Engine - Project loader, runtime execution, SQLite storage, standalone builder, and skill exporter",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -66,7 +66,7 @@
66
66
  "test": "node ../../scripts/run-tests.ts"
67
67
  },
68
68
  "dependencies": {
69
- "@actiondock/sdk": "^2.9.1",
69
+ "@actiondock/sdk": "^2.10.0",
70
70
  "ajv": "^8.17.1",
71
71
  "ajv-formats": "^3.0.1",
72
72
  "undici": "^7.29.1"