@sylphx/flow 1.0.0 → 1.0.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.
@@ -0,0 +1,204 @@
1
+ import {
2
+ getAllTargetIDs,
3
+ getAllTargets,
4
+ getDefaultTargetUnsafe,
5
+ getImplementedTargetIDs,
6
+ getImplementedTargets,
7
+ getOrElse,
8
+ getTarget,
9
+ getTargetsWithMCPSupport,
10
+ isSome,
11
+ isTargetImplemented
12
+ } from "./chunk-qk8n91hw.js";
13
+ import {
14
+ success,
15
+ tryCatchAsync
16
+ } from "./chunk-nd5fdvaq.js";
17
+
18
+ // src/utils/settings.ts
19
+ import fs from "node:fs/promises";
20
+ import path from "node:path";
21
+ var SETTINGS_FILE = ".sylphx-flow/settings.json";
22
+ var CURRENT_VERSION = "1.0.0";
23
+ var getSettingsPath = (cwd = process.cwd()) => path.join(cwd, SETTINGS_FILE);
24
+ var settingsExists = async (cwd = process.cwd()) => {
25
+ try {
26
+ await fs.access(getSettingsPath(cwd));
27
+ return true;
28
+ } catch {
29
+ return false;
30
+ }
31
+ };
32
+ var loadSettings = async (cwd = process.cwd()) => {
33
+ const settingsPath = getSettingsPath(cwd);
34
+ return tryCatchAsync(async () => {
35
+ const content = await fs.readFile(settingsPath, "utf8");
36
+ return JSON.parse(content);
37
+ }, (error) => {
38
+ if (error.code === "ENOENT") {
39
+ return new Error("EMPTY_SETTINGS");
40
+ }
41
+ return new Error(`Failed to load settings: ${error.message}`);
42
+ }).then((result) => {
43
+ if (result._tag === "Failure" && result.error.message === "EMPTY_SETTINGS") {
44
+ return success({});
45
+ }
46
+ return result;
47
+ });
48
+ };
49
+ var saveSettings = async (settings, cwd = process.cwd()) => {
50
+ const settingsPath = getSettingsPath(cwd);
51
+ return tryCatchAsync(async () => {
52
+ await fs.mkdir(path.dirname(settingsPath), { recursive: true });
53
+ const settingsWithVersion = {
54
+ ...settings,
55
+ version: settings.version || CURRENT_VERSION
56
+ };
57
+ await fs.writeFile(settingsPath, `${JSON.stringify(settingsWithVersion, null, 2)}
58
+ `, "utf8");
59
+ }, (error) => new Error(`Failed to save settings: ${error.message}`));
60
+ };
61
+ var updateSettings = async (updates, cwd = process.cwd()) => {
62
+ const currentResult = await loadSettings(cwd);
63
+ if (currentResult._tag === "Failure") {
64
+ return currentResult;
65
+ }
66
+ const newSettings = { ...currentResult.value, ...updates };
67
+ return saveSettings(newSettings, cwd);
68
+ };
69
+ var getDefaultTarget = async (cwd = process.cwd()) => {
70
+ const result = await loadSettings(cwd);
71
+ return result._tag === "Success" ? result.value.defaultTarget : undefined;
72
+ };
73
+ var setDefaultTarget = async (target, cwd = process.cwd()) => updateSettings({ defaultTarget: target }, cwd);
74
+
75
+ class ProjectSettings {
76
+ cwd;
77
+ constructor(cwd = process.cwd()) {
78
+ this.cwd = cwd;
79
+ this.settingsPath = getSettingsPath(cwd);
80
+ }
81
+ async load() {
82
+ const result = await loadSettings(this.cwd);
83
+ if (result._tag === "Failure") {
84
+ throw result.error;
85
+ }
86
+ return result.value;
87
+ }
88
+ async save(settings) {
89
+ const result = await saveSettings(settings, this.cwd);
90
+ if (result._tag === "Failure") {
91
+ throw result.error;
92
+ }
93
+ }
94
+ async update(updates) {
95
+ const result = await updateSettings(updates, this.cwd);
96
+ if (result._tag === "Failure") {
97
+ throw result.error;
98
+ }
99
+ }
100
+ async getDefaultTarget() {
101
+ return getDefaultTarget(this.cwd);
102
+ }
103
+ async setDefaultTarget(target) {
104
+ const result = await setDefaultTarget(target, this.cwd);
105
+ if (result._tag === "Failure") {
106
+ throw result.error;
107
+ }
108
+ }
109
+ async exists() {
110
+ return settingsExists(this.cwd);
111
+ }
112
+ }
113
+ var projectSettings = new ProjectSettings;
114
+
115
+ // src/core/target-manager.ts
116
+ import inquirer from "inquirer";
117
+ function createTargetManager() {
118
+ const detectTargetFromEnvironment = () => {
119
+ try {
120
+ const implementedTargets = getImplementedTargets();
121
+ const nonDefaultTargets = implementedTargets.filter((target) => !target.isDefault);
122
+ const defaultTargets = implementedTargets.filter((target) => target.isDefault);
123
+ for (const target of nonDefaultTargets) {
124
+ const detected = target.detectFromEnvironment?.();
125
+ if (detected) {
126
+ return target.id;
127
+ }
128
+ }
129
+ for (const target of defaultTargets) {
130
+ const detected = target.detectFromEnvironment?.();
131
+ if (detected) {
132
+ return target.id;
133
+ }
134
+ }
135
+ return null;
136
+ } catch {
137
+ return null;
138
+ }
139
+ };
140
+ const promptForTargetSelection = async () => {
141
+ const availableTargets = getImplementedTargetIDs();
142
+ let defaultTarget = getDefaultTargetUnsafe().id;
143
+ try {
144
+ const savedDefaultTarget = await projectSettings.getDefaultTarget();
145
+ if (savedDefaultTarget && isSome(getTarget(savedDefaultTarget))) {
146
+ defaultTarget = savedDefaultTarget;
147
+ }
148
+ } catch {}
149
+ const answer = await inquirer.prompt([
150
+ {
151
+ type: "list",
152
+ name: "target",
153
+ message: "Select target platform:",
154
+ choices: availableTargets.map((id) => {
155
+ const targetOption = getTarget(id);
156
+ const target = getOrElse({ id, name: id })(targetOption);
157
+ return {
158
+ name: target.name || id,
159
+ value: id
160
+ };
161
+ }),
162
+ default: defaultTarget
163
+ }
164
+ ]);
165
+ return answer.target;
166
+ };
167
+ const resolveTarget = async (options) => {
168
+ if (options.target) {
169
+ if (!isSome(getTarget(options.target))) {
170
+ throw new Error(`Unknown target: ${options.target}. Available targets: ${getAllTargetIDs().join(", ")}`);
171
+ }
172
+ return options.target;
173
+ }
174
+ try {
175
+ const savedDefaultTarget = await projectSettings.getDefaultTarget();
176
+ if (savedDefaultTarget && isSome(getTarget(savedDefaultTarget))) {
177
+ return savedDefaultTarget;
178
+ }
179
+ } catch (_error) {}
180
+ const detectedTarget = detectTargetFromEnvironment();
181
+ if (detectedTarget) {
182
+ return detectedTarget;
183
+ }
184
+ if (options.allowSelection) {
185
+ return await promptForTargetSelection();
186
+ }
187
+ const defaultTarget = getDefaultTargetUnsafe();
188
+ return defaultTarget.id;
189
+ };
190
+ return {
191
+ getAllTargets: () => getAllTargets(),
192
+ getImplementedTargets: () => getImplementedTargets(),
193
+ getTarget: (id) => getTarget(id),
194
+ promptForTargetSelection,
195
+ resolveTarget,
196
+ isTargetImplemented: (targetId) => isTargetImplemented(targetId),
197
+ getTargetsWithMCPSupport: () => getTargetsWithMCPSupport(),
198
+ getImplementedTargetIDs: () => getImplementedTargetIDs(),
199
+ getAllTargetIDs: () => getAllTargetIDs()
200
+ };
201
+ }
202
+ var targetManager = createTargetManager();
203
+
204
+ export { projectSettings, targetManager };
@@ -0,0 +1,137 @@
1
+ import {
2
+ CONFIG_DIR,
3
+ USER_SETTINGS_FILE,
4
+ getProjectLocalSettingsFile,
5
+ getProjectSettingsFile
6
+ } from "./chunk-7eq34c42.js";
7
+ import"./chunk-5j4w74t6.js";
8
+
9
+ // src/services/config-service.ts
10
+ import fs from "node:fs/promises";
11
+ import path from "node:path";
12
+ class ConfigService {
13
+ static async loadConfiguration(cwd = process.cwd()) {
14
+ const userSettings = await this.loadHomeSettings();
15
+ const projectSettings = await this.loadProjectSettings(cwd);
16
+ const localSettings = await this.loadLocalSettings(cwd);
17
+ const choices = {
18
+ provider: localSettings.provider || userSettings.defaultProvider,
19
+ agent: localSettings.agent || projectSettings.defaultAgent || userSettings.defaultAgent
20
+ };
21
+ return {
22
+ user: userSettings,
23
+ project: projectSettings,
24
+ choices
25
+ };
26
+ }
27
+ static async loadSettings(cwd = process.cwd()) {
28
+ const config = await this.loadConfiguration(cwd);
29
+ return {
30
+ ...config.user,
31
+ ...config.project,
32
+ ...config.choices
33
+ };
34
+ }
35
+ static async loadHomeSettings() {
36
+ try {
37
+ const content = await fs.readFile(USER_SETTINGS_FILE, "utf-8");
38
+ return JSON.parse(content);
39
+ } catch {
40
+ return {};
41
+ }
42
+ }
43
+ static async saveHomeSettings(settings) {
44
+ await fs.mkdir(USER_SETTINGS_FILE.replace("/settings.json", ""), { recursive: true });
45
+ const existing = await this.loadHomeSettings();
46
+ const merged = { ...existing, ...settings };
47
+ await fs.writeFile(USER_SETTINGS_FILE, JSON.stringify(merged, null, 2) + `
48
+ `);
49
+ }
50
+ static async hasInitialSetup() {
51
+ const userSettings = await this.loadHomeSettings();
52
+ return !!(userSettings.hasCompletedSetup || userSettings.apiKeys && Object.keys(userSettings.apiKeys).length > 0);
53
+ }
54
+ static getAvailableProviders(userSettings) {
55
+ const providers = ["default"];
56
+ if (userSettings.apiKeys?.kimi)
57
+ providers.push("kimi");
58
+ if (userSettings.apiKeys?.["z.ai"])
59
+ providers.push("z.ai");
60
+ return providers;
61
+ }
62
+ static async loadProjectSettings(cwd = process.cwd()) {
63
+ try {
64
+ const configPath = getProjectSettingsFile(cwd);
65
+ const content = await fs.readFile(configPath, "utf-8");
66
+ return JSON.parse(content);
67
+ } catch {
68
+ return {};
69
+ }
70
+ }
71
+ static async saveProjectSettings(settings, cwd = process.cwd()) {
72
+ const configDir = path.join(cwd, CONFIG_DIR);
73
+ await fs.mkdir(configDir, { recursive: true });
74
+ const existing = await this.loadProjectSettings(cwd);
75
+ const merged = { ...existing, ...settings };
76
+ const configPath = getProjectSettingsFile(cwd);
77
+ await fs.writeFile(configPath, JSON.stringify(merged, null, 2) + `
78
+ `);
79
+ }
80
+ static async loadLocalSettings(cwd = process.cwd()) {
81
+ try {
82
+ const configPath = getProjectLocalSettingsFile(cwd);
83
+ const content = await fs.readFile(configPath, "utf-8");
84
+ return JSON.parse(content);
85
+ } catch {
86
+ return {};
87
+ }
88
+ }
89
+ static async saveLocalSettings(settings, cwd = process.cwd()) {
90
+ const configDir = path.join(cwd, CONFIG_DIR);
91
+ await fs.mkdir(configDir, { recursive: true });
92
+ const configPath = getProjectLocalSettingsFile(cwd);
93
+ await fs.writeFile(configPath, JSON.stringify(settings, null, 2) + `
94
+ `);
95
+ }
96
+ static async saveClaudeConfig(projectConfig, userConfig, cwd = process.cwd()) {
97
+ if (userConfig.claudeApiKey || userConfig.claudeProvider || userConfig.claudeProviderConfig) {
98
+ await this.saveHomeSettings(userConfig);
99
+ }
100
+ await this.saveProjectSettings(projectConfig, cwd);
101
+ await this.addGitignore(cwd);
102
+ }
103
+ static async addGitignore(cwd) {
104
+ const gitignorePath = path.join(cwd, ".gitignore");
105
+ const patterns = [
106
+ "",
107
+ "# Sylphx Flow - local settings (never commit)",
108
+ ".sylphx-flow/*.local.json"
109
+ ];
110
+ try {
111
+ const content = await fs.readFile(gitignorePath, "utf-8");
112
+ if (!content.includes(".sylphx-flow/*.local.json")) {
113
+ await fs.appendFile(gitignorePath, patterns.join(`
114
+ `) + `
115
+ `);
116
+ }
117
+ } catch {
118
+ await fs.writeFile(gitignorePath, patterns.join(`
119
+ `).trim() + `
120
+ `);
121
+ }
122
+ }
123
+ static async isInitialized(cwd = process.cwd()) {
124
+ try {
125
+ const configDir = path.join(cwd, CONFIG_DIR);
126
+ await fs.access(configDir);
127
+ return true;
128
+ } catch {
129
+ return false;
130
+ }
131
+ }
132
+ }
133
+ export {
134
+ ConfigService
135
+ };
136
+
137
+ export { ConfigService };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylphx/flow",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "AI-powered development workflow automation with autonomous loop mode and smart configuration",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,7 +13,8 @@
13
13
  "test": "vitest run",
14
14
  "test:watch": "vitest",
15
15
  "type-check": "tsc --noEmit",
16
- "clean": "rm -rf dist"
16
+ "clean": "rm -rf dist",
17
+ "prepublishOnly": "bun run build"
17
18
  },
18
19
  "dependencies": {
19
20
  "commander": "^14.0.2",