studioflow 0.1.4 → 0.2.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/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "studioflow",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
- "description": "Deterministic AI-assisted product demo automation CLI for Screen Studio workflows",
5
+ "description": "Deterministic AI-assisted product demo automation CLI for QuickTime and Screen Studio workflows",
6
6
  "type": "module",
7
7
  "engines": {
8
8
  "node": ">=22"
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "files": [
17
17
  "dist",
18
- "skills",
19
- "flows",
18
+ "assets",
19
+ "bundled",
20
20
  "scripts/sync-skills.mjs",
21
21
  "scripts/build.mjs",
22
22
  "tsconfig.json",
@@ -25,35 +25,35 @@
25
25
  "bin": {
26
26
  "studioflow": "dist/index.js"
27
27
  },
28
+ "dependencies": {
29
+ "playwright": "^1.55.0",
30
+ "yaml": "^2.8.1"
31
+ },
32
+ "devDependencies": {
33
+ "esbuild": "^0.25.11",
34
+ "kleur": "^4.1.5",
35
+ "tsx": "^4.20.5",
36
+ "@studioflow/adapters-playwright": "0.1.0",
37
+ "@studioflow/adapters-screenstudio": "0.1.0",
38
+ "@studioflow/adapters-desktop": "0.1.0",
39
+ "@studioflow/contracts": "0.1.0",
40
+ "@studioflow/flow-registry": "0.1.0",
41
+ "@studioflow/artifacts": "0.1.0",
42
+ "@studioflow/orchestrator": "0.1.0"
43
+ },
28
44
  "scripts": {
29
45
  "prepare:assets": "node scripts/sync-skills.mjs",
30
46
  "build": "node scripts/build.mjs",
31
- "prepack": "node scripts/sync-skills.mjs && node scripts/build.mjs",
32
47
  "demo": "tsx src/index.ts run",
33
48
  "config": "tsx src/index.ts config",
34
49
  "setup": "tsx src/index.ts setup",
35
50
  "install-skills": "tsx src/index.ts install-skills",
36
51
  "discover": "tsx src/index.ts discover",
37
52
  "bootstrap": "tsx src/index.ts bootstrap",
53
+ "quicktime-prep": "tsx src/index.ts quicktime-prep",
38
54
  "screenstudio-prep": "tsx src/index.ts screenstudio-prep",
39
55
  "validate": "tsx src/index.ts validate",
40
56
  "doctor": "tsx src/index.ts doctor",
41
57
  "list-flows": "tsx src/index.ts list-flows"
42
- },
43
- "dependencies": {
44
- "playwright": "^1.55.0",
45
- "yaml": "^2.8.1"
46
- },
47
- "devDependencies": {
48
- "@studioflow/adapters-desktop": "workspace:*",
49
- "@studioflow/adapters-playwright": "workspace:*",
50
- "@studioflow/adapters-screenstudio": "workspace:*",
51
- "@studioflow/artifacts": "workspace:*",
52
- "@studioflow/contracts": "workspace:*",
53
- "@studioflow/flow-registry": "workspace:*",
54
- "@studioflow/orchestrator": "workspace:*",
55
- "esbuild": "^0.25.11",
56
- "kleur": "^4.1.5",
57
- "tsx": "^4.20.5"
58
58
  }
59
- }
59
+ }
@@ -1,17 +1,78 @@
1
1
  #!/usr/bin/env node
2
+ import { createHash } from "node:crypto";
2
3
  import fs from "node:fs/promises";
3
4
  import path from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
 
6
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
8
  const packageRoot = path.resolve(__dirname, "..");
9
+ // Source-of-truth lives in the workspace; packaged runtime reads from bundled/.
8
10
  const sourceSkillsRoot = path.resolve(packageRoot, "../../skills");
9
- const targetSkillsRoot = path.join(packageRoot, "skills");
11
+ const bundledRoot = path.join(packageRoot, "bundled");
12
+ const targetSkillsRoot = path.join(bundledRoot, "skills");
10
13
  const sourceFlowsRoot = path.resolve(packageRoot, "../../packages/flow-registry/flows");
11
- const targetFlowsRoot = path.join(packageRoot, "flows");
14
+ const targetFlowsRoot = path.join(bundledRoot, "flows");
12
15
  const skillNames = ["studioflow-cli", "studioflow-investigate"];
13
16
  const flowNames = ["billing.yaml", "onboarding.yaml", "onboarding_billing.yaml"];
14
17
 
18
+ async function listFilesRecursively(rootDir) {
19
+ const entries = await fs.readdir(rootDir, { withFileTypes: true });
20
+ const files = [];
21
+
22
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
23
+ const fullPath = path.join(rootDir, entry.name);
24
+ if (entry.isDirectory()) {
25
+ files.push(...(await listFilesRecursively(fullPath)));
26
+ continue;
27
+ }
28
+ if (entry.isFile()) {
29
+ files.push(fullPath);
30
+ }
31
+ }
32
+
33
+ return files;
34
+ }
35
+
36
+ async function hashDirectoryContents(rootDir) {
37
+ const hasher = createHash("sha256");
38
+ const files = await listFilesRecursively(rootDir);
39
+
40
+ for (const filePath of files) {
41
+ const relativePath = path.relative(rootDir, filePath).split(path.sep).join("/");
42
+ hasher.update(relativePath);
43
+ hasher.update("\n");
44
+ hasher.update(await fs.readFile(filePath));
45
+ hasher.update("\n");
46
+ }
47
+
48
+ return hasher.digest("hex");
49
+ }
50
+
51
+ async function readPackageVersion() {
52
+ const packageJsonPath = path.join(packageRoot, "package.json");
53
+ const raw = await fs.readFile(packageJsonPath, "utf8");
54
+ const parsed = JSON.parse(raw);
55
+ return typeof parsed.version === "string" ? parsed.version : "0.0.0";
56
+ }
57
+
58
+ async function buildSkillsManifest() {
59
+ const skills = {};
60
+ for (const skillName of skillNames) {
61
+ const skillPath = path.join(sourceSkillsRoot, skillName);
62
+ skills[skillName] = {
63
+ hash: await hashDirectoryContents(skillPath)
64
+ };
65
+ }
66
+
67
+ return {
68
+ schemaVersion: 1,
69
+ packageName: "studioflow",
70
+ packageVersion: await readPackageVersion(),
71
+ generatedAt: new Date().toISOString(),
72
+ skills
73
+ };
74
+ }
75
+
15
76
  async function ensureSkillExists(skillName) {
16
77
  const skillPath = path.join(sourceSkillsRoot, skillName, "SKILL.md");
17
78
  await fs.access(skillPath);
@@ -26,6 +87,8 @@ async function main() {
26
87
  await Promise.all(skillNames.map(ensureSkillExists));
27
88
  await Promise.all(flowNames.map(ensureFlowExists));
28
89
 
90
+ await fs.mkdir(bundledRoot, { recursive: true });
91
+
29
92
  await fs.rm(targetSkillsRoot, { recursive: true, force: true });
30
93
  await fs.mkdir(targetSkillsRoot, { recursive: true });
31
94
 
@@ -34,6 +97,7 @@ async function main() {
34
97
  const target = path.join(targetSkillsRoot, skillName);
35
98
  await fs.cp(source, target, { recursive: true });
36
99
  }
100
+ await fs.writeFile(path.join(targetSkillsRoot, "manifest.json"), `${JSON.stringify(await buildSkillsManifest(), null, 2)}\n`);
37
101
 
38
102
  await fs.rm(targetFlowsRoot, { recursive: true, force: true });
39
103
  await fs.mkdir(targetFlowsRoot, { recursive: true });
@@ -44,7 +108,7 @@ async function main() {
44
108
  await fs.cp(source, target);
45
109
  }
46
110
 
47
- console.log(`Bundled assets synced: skills -> ${targetSkillsRoot}, flows -> ${targetFlowsRoot}`);
111
+ console.log(`Bundled assets synced: ${bundledRoot}`);
48
112
  }
49
113
 
50
114
  main().catch((error) => {
File without changes
File without changes