@acpfx/core 0.2.0 → 0.4.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 +36 -0
- package/LICENSE +15 -0
- package/README.md +28 -0
- package/package.json +1 -1
- package/src/acpfx-flags.ts +51 -0
- package/src/manifest.ts +114 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @acpfx/core
|
|
2
2
|
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 05c4208: Embed manifest.yaml via include_str in native binaries (no hardcoded inline). Fix realpathSync for npx symlink manifest resolution. Remove speaker dep from audio-player.
|
|
8
|
+
|
|
9
|
+
## 0.4.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 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.
|
|
14
|
+
|
|
15
|
+
## 0.3.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- a0320a1: Add manifest argument/env schema, config system, pipeline resolver, and onboarding TUI
|
|
20
|
+
|
|
21
|
+
- **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.
|
|
22
|
+
- **All 12 node manifests updated** with arguments and env declarations derived from source code audit.
|
|
23
|
+
- **Build-time validation**: `scripts/validate-manifests.ts` validates against generated Zod schema. Orchestrator validates settings at startup.
|
|
24
|
+
- **Config system**: `~/.acpfx/config.json` (global) and `.acpfx/config.json` (project) with env var layering. New CLI: `acpfx config`, `acpfx config set/get`.
|
|
25
|
+
- **Pipeline resolver**: `acpfx run [name]` resolves pipelines from .acpfx/pipelines/, ~/.acpfx/pipelines/, or bundled examples. `acpfx pipelines` lists available pipelines.
|
|
26
|
+
- **Onboarding TUI**: `acpfx onboard` for interactive pipeline creation from templates or scratch. Auto-triggered on first `acpfx run` with no default pipeline.
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- 79c6694: Consolidate mic-aec and mic-sox into unified mic-speaker node
|
|
31
|
+
|
|
32
|
+
- **Remove `node-mic-aec` and `node-mic-sox`**: Replaced by the native `node-mic-speaker` package with built-in AEC support.
|
|
33
|
+
- **Add `node-mic-speaker`**: Rust-based mic capture + speaker output with acoustic echo cancellation in a single node.
|
|
34
|
+
- **Simplify pipeline configs**: Remove deprecated AEC/sysvoice pipeline variants; update remaining configs to use `@acpfx/mic-speaker`.
|
|
35
|
+
- **Update audio-player**: Streamline to work with the new mic-speaker node.
|
|
36
|
+
- **Update orchestrator**: Onboarding, templates, and node runner adjusted for consolidated mic node.
|
|
37
|
+
- **Update tests**: Reflect removed packages and new node structure.
|
|
38
|
+
|
|
3
39
|
## 0.2.0
|
|
4
40
|
|
|
5
41
|
### Minor Changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 acpfx contributors
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# @acpfx/core
|
|
2
|
+
|
|
3
|
+
Shared types, Zod schemas, and manifest utilities for acpfx nodes. This package contains the generated TypeScript types and validation schemas derived from the canonical Rust schema definitions.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @acpfx/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What's Included
|
|
12
|
+
|
|
13
|
+
- **Generated types** -- TypeScript interfaces for all event types (`audio.chunk`, `speech.final`, `agent.delta`, etc.)
|
|
14
|
+
- **Zod schemas** -- Runtime validation for events
|
|
15
|
+
- **Manifest utilities** -- Helpers for loading and validating `manifest.yaml` files
|
|
16
|
+
- **Protocol helpers** -- Event construction and parsing
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { AudioChunkEvent, SpeechFinalEvent } from "@acpfx/core";
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Types are generated from the Rust schema crate via `cargo run -p acpfx-schema --bin acpfx-codegen`.
|
|
25
|
+
|
|
26
|
+
## License
|
|
27
|
+
|
|
28
|
+
ISC
|
package/package.json
CHANGED
|
@@ -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,48 +1,141 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Manifest
|
|
2
|
+
* Manifest types, Zod schemas, and acpfx flag handling for nodes.
|
|
3
3
|
*
|
|
4
|
-
* Call `
|
|
5
|
-
*
|
|
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 { fileURLToPath } from "node:url";
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
|
|
16
|
+
// ---- Manifest Types ----
|
|
17
|
+
|
|
18
|
+
export type ArgumentType = "string" | "number" | "boolean";
|
|
19
|
+
|
|
20
|
+
export interface ManifestArgument {
|
|
21
|
+
type: ArgumentType;
|
|
22
|
+
default?: unknown;
|
|
23
|
+
description?: string;
|
|
24
|
+
required?: boolean;
|
|
25
|
+
enum?: unknown[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ManifestEnvField {
|
|
29
|
+
required?: boolean;
|
|
30
|
+
description?: string;
|
|
31
|
+
}
|
|
10
32
|
|
|
11
33
|
export interface NodeManifest {
|
|
12
34
|
name: string;
|
|
13
35
|
description?: string;
|
|
14
36
|
consumes: string[];
|
|
15
37
|
emits: string[];
|
|
38
|
+
arguments?: Record<string, ManifestArgument>;
|
|
39
|
+
additional_arguments?: boolean;
|
|
40
|
+
env?: Record<string, ManifestEnvField>;
|
|
16
41
|
}
|
|
17
42
|
|
|
43
|
+
// ---- Manifest Zod Schemas ----
|
|
44
|
+
|
|
45
|
+
export const ArgumentTypeSchema = z.enum(["string", "number", "boolean"]);
|
|
46
|
+
|
|
47
|
+
export const ManifestArgumentSchema = z.object({
|
|
48
|
+
type: ArgumentTypeSchema,
|
|
49
|
+
default: z.unknown().optional(),
|
|
50
|
+
description: z.string().optional(),
|
|
51
|
+
required: z.boolean().optional(),
|
|
52
|
+
enum: z.array(z.unknown()).optional(),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const ManifestEnvFieldSchema = z.object({
|
|
56
|
+
required: z.boolean().optional(),
|
|
57
|
+
description: z.string().optional(),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const NodeManifestSchema = z.object({
|
|
61
|
+
name: z.string(),
|
|
62
|
+
description: z.string().optional(),
|
|
63
|
+
consumes: z.array(z.string()),
|
|
64
|
+
emits: z.array(z.string()),
|
|
65
|
+
arguments: z.record(z.string(), ManifestArgumentSchema).optional(),
|
|
66
|
+
additional_arguments: z.boolean().optional(),
|
|
67
|
+
env: z.record(z.string(), ManifestEnvFieldSchema).optional(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// ---- acpfx Flag Protocol Types ----
|
|
71
|
+
|
|
72
|
+
export type {
|
|
73
|
+
SetupCheckResponse,
|
|
74
|
+
SetupProgress,
|
|
75
|
+
UnsupportedFlagResponse,
|
|
76
|
+
} from "./acpfx-flags.js";
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
SetupCheckResponseSchema,
|
|
80
|
+
SetupProgressSchema,
|
|
81
|
+
UnsupportedFlagResponseSchema,
|
|
82
|
+
} from "./acpfx-flags.js";
|
|
83
|
+
|
|
84
|
+
// ---- Flag Handling ----
|
|
85
|
+
|
|
18
86
|
/**
|
|
19
|
-
*
|
|
20
|
-
* print it to stdout, and exit(0).
|
|
87
|
+
* Handle all `--acpfx-*` convention flags.
|
|
21
88
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
|
|
89
|
+
* Must be called at the top of every node's entry point (before any async work).
|
|
90
|
+
* Also supports legacy `--manifest` for backward compatibility.
|
|
91
|
+
*/
|
|
92
|
+
export function handleAcpfxFlags(manifestPath?: string): void {
|
|
93
|
+
const acpfxFlag = process.argv.find((a) => a.startsWith("--acpfx-"));
|
|
94
|
+
const legacyManifest = process.argv.includes("--manifest");
|
|
95
|
+
|
|
96
|
+
if (!acpfxFlag && !legacyManifest) return;
|
|
97
|
+
|
|
98
|
+
const flag = acpfxFlag ?? "--acpfx-manifest";
|
|
99
|
+
|
|
100
|
+
switch (flag) {
|
|
101
|
+
case "--acpfx-manifest":
|
|
102
|
+
printManifest(manifestPath);
|
|
103
|
+
break;
|
|
104
|
+
|
|
105
|
+
case "--acpfx-setup-check":
|
|
106
|
+
process.stdout.write(JSON.stringify({ needed: false }) + "\n");
|
|
107
|
+
process.exit(0);
|
|
108
|
+
break;
|
|
109
|
+
|
|
110
|
+
default:
|
|
111
|
+
process.stdout.write(
|
|
112
|
+
JSON.stringify({ unsupported: true, flag }) + "\n"
|
|
113
|
+
);
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @deprecated Use `handleAcpfxFlags()` instead.
|
|
26
120
|
*/
|
|
27
121
|
export function handleManifestFlag(manifestPath?: string): void {
|
|
28
|
-
|
|
122
|
+
handleAcpfxFlags(manifestPath);
|
|
123
|
+
}
|
|
29
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Print the co-located manifest JSON to stdout and exit.
|
|
127
|
+
*/
|
|
128
|
+
function printManifest(manifestPath?: string): void {
|
|
30
129
|
if (!manifestPath) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
readFileSync(colocated);
|
|
37
|
-
manifestPath = colocated;
|
|
38
|
-
} catch {
|
|
39
|
-
manifestPath = join(scriptDir, "manifest.json");
|
|
40
|
-
}
|
|
130
|
+
// Use import.meta.url to find the bundle's real location on disk.
|
|
131
|
+
// This works even when invoked via npx symlinks in .bin/ because
|
|
132
|
+
// import.meta.url resolves to the actual file, not the symlink.
|
|
133
|
+
const bundleDir = dirname(fileURLToPath(import.meta.url));
|
|
134
|
+
manifestPath = join(bundleDir, "manifest.json");
|
|
41
135
|
}
|
|
42
136
|
|
|
43
137
|
try {
|
|
44
138
|
const content = readFileSync(manifestPath, "utf8");
|
|
45
|
-
// Already JSON — just write it out
|
|
46
139
|
process.stdout.write(content.trim() + "\n");
|
|
47
140
|
process.exit(0);
|
|
48
141
|
} catch (err) {
|