@acpfx/core 0.2.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @acpfx/core
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0e6838e: Add local on-device STT and TTS nodes (no API keys required). Introduces --acpfx-\* flag convention with setup phase for first-time model downloads, dynamic release pipeline with dual CPU/CUDA builds, MLX acceleration on Mac, and TUI improvements for speech event display.
8
+
9
+ ## 0.3.0
10
+
11
+ ### Minor Changes
12
+
13
+ - a0320a1: Add manifest argument/env schema, config system, pipeline resolver, and onboarding TUI
14
+
15
+ - **Manifest schema**: Node manifests now declare typed `arguments` (string/number/boolean with defaults, enums, required) and `env` var requirements. Codegen produces TypeScript types + Zod schemas.
16
+ - **All 12 node manifests updated** with arguments and env declarations derived from source code audit.
17
+ - **Build-time validation**: `scripts/validate-manifests.ts` validates against generated Zod schema. Orchestrator validates settings at startup.
18
+ - **Config system**: `~/.acpfx/config.json` (global) and `.acpfx/config.json` (project) with env var layering. New CLI: `acpfx config`, `acpfx config set/get`.
19
+ - **Pipeline resolver**: `acpfx run [name]` resolves pipelines from .acpfx/pipelines/, ~/.acpfx/pipelines/, or bundled examples. `acpfx pipelines` lists available pipelines.
20
+ - **Onboarding TUI**: `acpfx onboard` for interactive pipeline creation from templates or scratch. Auto-triggered on first `acpfx run` with no default pipeline.
21
+
22
+ ### Patch Changes
23
+
24
+ - 79c6694: Consolidate mic-aec and mic-sox into unified mic-speaker node
25
+
26
+ - **Remove `node-mic-aec` and `node-mic-sox`**: Replaced by the native `node-mic-speaker` package with built-in AEC support.
27
+ - **Add `node-mic-speaker`**: Rust-based mic capture + speaker output with acoustic echo cancellation in a single node.
28
+ - **Simplify pipeline configs**: Remove deprecated AEC/sysvoice pipeline variants; update remaining configs to use `@acpfx/mic-speaker`.
29
+ - **Update audio-player**: Streamline to work with the new mic-speaker node.
30
+ - **Update orchestrator**: Onboarding, templates, and node runner adjusted for consolidated mic node.
31
+ - **Update tests**: Reflect removed packages and new node structure.
32
+
3
33
  ## 0.2.0
4
34
 
5
35
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acpfx/core",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -0,0 +1,51 @@
1
+ /**
2
+ * acpfx flag protocol types and handler.
3
+ *
4
+ * All orchestrator-reserved flags use the `--acpfx-` prefix.
5
+ * Nodes that receive an unrecognized `--acpfx-*` flag should emit
6
+ * an UnsupportedFlagResponse and exit 0 (forward compatibility).
7
+ */
8
+
9
+ import { z } from "zod";
10
+
11
+ // ---- Types ----
12
+
13
+ /** Response from `--acpfx-setup-check`. */
14
+ export interface SetupCheckResponse {
15
+ needed: boolean;
16
+ description?: string;
17
+ }
18
+
19
+ /** Progress line from `--acpfx-setup` (NDJSON on stdout). */
20
+ export type SetupProgress =
21
+ | { type: "progress"; message: string; pct?: number }
22
+ | { type: "complete"; message: string }
23
+ | { type: "error"; message: string };
24
+
25
+ /** Response for unrecognized `--acpfx-*` flags (forward compatibility). */
26
+ export interface UnsupportedFlagResponse {
27
+ unsupported: boolean;
28
+ flag: string;
29
+ }
30
+
31
+ // ---- Zod Schemas ----
32
+
33
+ export const SetupCheckResponseSchema = z.object({
34
+ needed: z.boolean(),
35
+ description: z.string().optional(),
36
+ });
37
+
38
+ export const SetupProgressSchema = z.discriminatedUnion("type", [
39
+ z.object({
40
+ type: z.literal("progress"),
41
+ message: z.string(),
42
+ pct: z.number().optional(),
43
+ }),
44
+ z.object({ type: z.literal("complete"), message: z.string() }),
45
+ z.object({ type: z.literal("error"), message: z.string() }),
46
+ ]);
47
+
48
+ export const UnsupportedFlagResponseSchema = z.object({
49
+ unsupported: z.boolean(),
50
+ flag: z.string(),
51
+ });
package/src/manifest.ts CHANGED
@@ -1,32 +1,130 @@
1
1
  /**
2
- * Manifest utilities for acpfx nodes.
2
+ * Manifest types, Zod schemas, and acpfx flag handling for nodes.
3
3
  *
4
- * Call `handleManifestFlag()` at the top of your node's entry point.
5
- * If `--manifest` is in argv, it prints the manifest as JSON and exits.
4
+ * Call `handleAcpfxFlags()` at the top of your node's entry point.
5
+ * It handles all `--acpfx-*` convention flags:
6
+ * --acpfx-manifest Print manifest JSON and exit
7
+ * --acpfx-setup-check Print {"needed": false} and exit (TS nodes don't need setup)
8
+ * --acpfx-* (unknown) Print {"unsupported": true, "flag": "..."} and exit
6
9
  */
7
10
 
8
11
  import { readFileSync } from "node:fs";
9
12
  import { join, dirname } from "node:path";
13
+ import { z } from "zod";
14
+
15
+ // ---- Manifest Types ----
16
+
17
+ export type ArgumentType = "string" | "number" | "boolean";
18
+
19
+ export interface ManifestArgument {
20
+ type: ArgumentType;
21
+ default?: unknown;
22
+ description?: string;
23
+ required?: boolean;
24
+ enum?: unknown[];
25
+ }
26
+
27
+ export interface ManifestEnvField {
28
+ required?: boolean;
29
+ description?: string;
30
+ }
10
31
 
11
32
  export interface NodeManifest {
12
33
  name: string;
13
34
  description?: string;
14
35
  consumes: string[];
15
36
  emits: string[];
37
+ arguments?: Record<string, ManifestArgument>;
38
+ additional_arguments?: boolean;
39
+ env?: Record<string, ManifestEnvField>;
16
40
  }
17
41
 
42
+ // ---- Manifest Zod Schemas ----
43
+
44
+ export const ArgumentTypeSchema = z.enum(["string", "number", "boolean"]);
45
+
46
+ export const ManifestArgumentSchema = z.object({
47
+ type: ArgumentTypeSchema,
48
+ default: z.unknown().optional(),
49
+ description: z.string().optional(),
50
+ required: z.boolean().optional(),
51
+ enum: z.array(z.unknown()).optional(),
52
+ });
53
+
54
+ export const ManifestEnvFieldSchema = z.object({
55
+ required: z.boolean().optional(),
56
+ description: z.string().optional(),
57
+ });
58
+
59
+ export const NodeManifestSchema = z.object({
60
+ name: z.string(),
61
+ description: z.string().optional(),
62
+ consumes: z.array(z.string()),
63
+ emits: z.array(z.string()),
64
+ arguments: z.record(z.string(), ManifestArgumentSchema).optional(),
65
+ additional_arguments: z.boolean().optional(),
66
+ env: z.record(z.string(), ManifestEnvFieldSchema).optional(),
67
+ });
68
+
69
+ // ---- acpfx Flag Protocol Types ----
70
+
71
+ export type {
72
+ SetupCheckResponse,
73
+ SetupProgress,
74
+ UnsupportedFlagResponse,
75
+ } from "./acpfx-flags.js";
76
+
77
+ export {
78
+ SetupCheckResponseSchema,
79
+ SetupProgressSchema,
80
+ UnsupportedFlagResponseSchema,
81
+ } from "./acpfx-flags.js";
82
+
83
+ // ---- Flag Handling ----
84
+
18
85
  /**
19
- * If `--manifest` is in process.argv, read the co-located manifest.json,
20
- * print it to stdout, and exit(0).
86
+ * Handle all `--acpfx-*` convention flags.
21
87
  *
22
- * Resolution order:
23
- * 1. Explicit `manifestPath` if provided
24
- * 2. `<script-base>.manifest.json` (bundled: dist/nodes/foo.js -> foo.manifest.json)
25
- * 3. `manifest.json` in the script's directory
88
+ * Must be called at the top of every node's entry point (before any async work).
89
+ * Also supports legacy `--manifest` for backward compatibility.
90
+ */
91
+ export function handleAcpfxFlags(manifestPath?: string): void {
92
+ const acpfxFlag = process.argv.find((a) => a.startsWith("--acpfx-"));
93
+ const legacyManifest = process.argv.includes("--manifest");
94
+
95
+ if (!acpfxFlag && !legacyManifest) return;
96
+
97
+ const flag = acpfxFlag ?? "--acpfx-manifest";
98
+
99
+ switch (flag) {
100
+ case "--acpfx-manifest":
101
+ printManifest(manifestPath);
102
+ break;
103
+
104
+ case "--acpfx-setup-check":
105
+ process.stdout.write(JSON.stringify({ needed: false }) + "\n");
106
+ process.exit(0);
107
+ break;
108
+
109
+ default:
110
+ process.stdout.write(
111
+ JSON.stringify({ unsupported: true, flag }) + "\n"
112
+ );
113
+ process.exit(0);
114
+ }
115
+ }
116
+
117
+ /**
118
+ * @deprecated Use `handleAcpfxFlags()` instead.
26
119
  */
27
120
  export function handleManifestFlag(manifestPath?: string): void {
28
- if (!process.argv.includes("--manifest")) return;
121
+ handleAcpfxFlags(manifestPath);
122
+ }
29
123
 
124
+ /**
125
+ * Print the co-located manifest JSON to stdout and exit.
126
+ */
127
+ function printManifest(manifestPath?: string): void {
30
128
  if (!manifestPath) {
31
129
  const script = process.argv[1];
32
130
  const scriptDir = dirname(script);
@@ -42,7 +140,6 @@ export function handleManifestFlag(manifestPath?: string): void {
42
140
 
43
141
  try {
44
142
  const content = readFileSync(manifestPath, "utf8");
45
- // Already JSON — just write it out
46
143
  process.stdout.write(content.trim() + "\n");
47
144
  process.exit(0);
48
145
  } catch (err) {