mobius-loop 1.0.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/.claude/commands/linear/define.md +22 -0
- package/.claude/commands/linear/execute.md +22 -0
- package/.claude/commands/linear/refine.md +22 -0
- package/.claude/commands/linear/verify.md +22 -0
- package/.claude/skills/define-linear-issue/SKILL.md +386 -0
- package/.claude/skills/execute-linear-issue/SKILL.md +629 -0
- package/.claude/skills/refine-linear-issue/SKILL.md +379 -0
- package/.claude/skills/verify-linear-issue/SKILL.md +663 -0
- package/AGENTS.md +70 -0
- package/LICENSE +21 -0
- package/README.md +457 -0
- package/dist/bin/mobius.d.ts +3 -0
- package/dist/bin/mobius.d.ts.map +1 -0
- package/dist/bin/mobius.js +75 -0
- package/dist/bin/mobius.js.map +1 -0
- package/dist/commands/config.d.ts +6 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +88 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +86 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/run.d.ts +10 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +62 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +131 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/lib/checks/cclean.d.ts +3 -0
- package/dist/lib/checks/cclean.d.ts.map +1 -0
- package/dist/lib/checks/cclean.js +23 -0
- package/dist/lib/checks/cclean.js.map +1 -0
- package/dist/lib/checks/claude.d.ts +3 -0
- package/dist/lib/checks/claude.d.ts.map +1 -0
- package/dist/lib/checks/claude.js +38 -0
- package/dist/lib/checks/claude.js.map +1 -0
- package/dist/lib/checks/config.d.ts +4 -0
- package/dist/lib/checks/config.d.ts.map +1 -0
- package/dist/lib/checks/config.js +45 -0
- package/dist/lib/checks/config.js.map +1 -0
- package/dist/lib/checks/docker.d.ts +3 -0
- package/dist/lib/checks/docker.d.ts.map +1 -0
- package/dist/lib/checks/docker.js +46 -0
- package/dist/lib/checks/docker.js.map +1 -0
- package/dist/lib/checks/linear-mcp.d.ts +3 -0
- package/dist/lib/checks/linear-mcp.d.ts.map +1 -0
- package/dist/lib/checks/linear-mcp.js +46 -0
- package/dist/lib/checks/linear-mcp.js.map +1 -0
- package/dist/lib/checks/path.d.ts +5 -0
- package/dist/lib/checks/path.d.ts.map +1 -0
- package/dist/lib/checks/path.js +49 -0
- package/dist/lib/checks/path.js.map +1 -0
- package/dist/lib/config.d.ts +37 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +145 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/paths.d.ts +39 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +117 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/mobius.config.yaml +38 -0
- package/package.json +56 -0
- package/scripts/mobius.sh +394 -0
- package/scripts/render-diagrams.sh +38 -0
- package/scripts/render-terminal.sh +49 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-mcp.d.ts","sourceRoot":"","sources":["../../../src/lib/checks/linear-mcp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE3D,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA8C3E"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
export async function checkLinearMcp(backend) {
|
|
3
|
+
const name = 'Linear MCP';
|
|
4
|
+
if (backend !== 'linear') {
|
|
5
|
+
return {
|
|
6
|
+
name,
|
|
7
|
+
status: 'skip',
|
|
8
|
+
message: `Not needed (using ${backend} backend)`,
|
|
9
|
+
required: false,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
// Try to check if Claude can access Linear MCP tools
|
|
13
|
+
// This is a lightweight check - we can't fully verify without running Claude
|
|
14
|
+
try {
|
|
15
|
+
// Check if claude has MCP configured by looking at settings
|
|
16
|
+
const { stdout } = await execa('claude', ['mcp', 'list'], {
|
|
17
|
+
timeout: 10000,
|
|
18
|
+
reject: false,
|
|
19
|
+
});
|
|
20
|
+
if (stdout.toLowerCase().includes('linear')) {
|
|
21
|
+
return {
|
|
22
|
+
name,
|
|
23
|
+
status: 'pass',
|
|
24
|
+
message: 'Linear MCP tools available',
|
|
25
|
+
required: false,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
name,
|
|
30
|
+
status: 'warn',
|
|
31
|
+
message: 'Linear MCP not detected in Claude config',
|
|
32
|
+
required: false,
|
|
33
|
+
details: 'Linear MCP may be configured at project level. Run a test task to verify.',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return {
|
|
38
|
+
name,
|
|
39
|
+
status: 'warn',
|
|
40
|
+
message: 'Could not verify Linear MCP status',
|
|
41
|
+
required: false,
|
|
42
|
+
details: 'Linear MCP may still work - run a test task to verify',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=linear-mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-mcp.js","sourceRoot":"","sources":["../../../src/lib/checks/linear-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAG9B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgB;IACnD,MAAM,IAAI,GAAG,YAAY,CAAC;IAE1B,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,qBAAqB,OAAO,WAAW;YAChD,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAED,qDAAqD;IACrD,6EAA6E;IAC7E,IAAI,CAAC;QACH,4DAA4D;QAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE;YACxD,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO;gBACL,IAAI;gBACJ,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,4BAA4B;gBACrC,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,0CAA0C;YACnD,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,2EAA2E;SACrF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,oCAAoC;YAC7C,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,uDAAuD;SACjE,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CheckResult } from '../../types.js';
|
|
2
|
+
import type { PathConfig } from '../../types.js';
|
|
3
|
+
export declare function checkPath(paths: PathConfig): Promise<CheckResult>;
|
|
4
|
+
export declare function checkSkills(paths: PathConfig): Promise<CheckResult>;
|
|
5
|
+
//# sourceMappingURL=path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/lib/checks/path.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAsB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAmBvE;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA+BzE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
export async function checkPath(paths) {
|
|
3
|
+
const name = 'Script path';
|
|
4
|
+
if (!existsSync(paths.scriptPath)) {
|
|
5
|
+
return {
|
|
6
|
+
name,
|
|
7
|
+
status: 'fail',
|
|
8
|
+
message: 'issue-loop.sh script not found',
|
|
9
|
+
required: true,
|
|
10
|
+
details: `Expected at: ${paths.scriptPath}`,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
name,
|
|
15
|
+
status: 'pass',
|
|
16
|
+
message: `Found at ${paths.scriptPath}`,
|
|
17
|
+
required: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export async function checkSkills(paths) {
|
|
21
|
+
const name = 'Skills';
|
|
22
|
+
if (!existsSync(paths.skillsPath)) {
|
|
23
|
+
return {
|
|
24
|
+
name,
|
|
25
|
+
status: 'fail',
|
|
26
|
+
message: `Skills directory not found at ${paths.skillsPath}`,
|
|
27
|
+
required: true,
|
|
28
|
+
details: "Run 'loop setup' to install skills",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Check for Linear skills specifically
|
|
32
|
+
const executeSkill = `${paths.skillsPath}/execute-linear-issue`;
|
|
33
|
+
if (!existsSync(executeSkill)) {
|
|
34
|
+
return {
|
|
35
|
+
name,
|
|
36
|
+
status: 'warn',
|
|
37
|
+
message: 'Linear execute skill not found',
|
|
38
|
+
required: false,
|
|
39
|
+
details: "Run 'loop setup' to install skills",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
name,
|
|
44
|
+
status: 'pass',
|
|
45
|
+
message: `Installed at ${paths.skillsPath}`,
|
|
46
|
+
required: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/lib/checks/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAiB;IAC/C,MAAM,IAAI,GAAG,aAAa,CAAC;IAE3B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,gCAAgC;YACzC,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,gBAAgB,KAAK,CAAC,UAAU,EAAE;SAC5C,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,YAAY,KAAK,CAAC,UAAU,EAAE;QACvC,QAAQ,EAAE,IAAI;KACf,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAiB;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC;IAEtB,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,iCAAiC,KAAK,CAAC,UAAU,EAAE;YAC5D,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,oCAAoC;SAC9C,CAAC;IACJ,CAAC;IAED,uCAAuC;IACvC,MAAM,YAAY,GAAG,GAAG,KAAK,CAAC,UAAU,uBAAuB,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,gCAAgC;YACzC,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,oCAAoC;SAC9C,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,gBAAgB,KAAK,CAAC,UAAU,EAAE;QAC3C,QAAQ,EAAE,IAAI;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { LoopConfig, PathConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read and parse config file, merging with defaults
|
|
4
|
+
*/
|
|
5
|
+
export declare function readConfig(configPath: string): LoopConfig;
|
|
6
|
+
/**
|
|
7
|
+
* Write config to file
|
|
8
|
+
*/
|
|
9
|
+
export declare function writeConfig(configPath: string, config: LoopConfig): void;
|
|
10
|
+
/**
|
|
11
|
+
* Copy skills from package to target directory
|
|
12
|
+
*/
|
|
13
|
+
export declare function copySkills(targetDir: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Copy commands from package to target directory
|
|
16
|
+
*/
|
|
17
|
+
export declare function copyCommands(paths: PathConfig): void;
|
|
18
|
+
/**
|
|
19
|
+
* Copy AGENTS.md template to project
|
|
20
|
+
*/
|
|
21
|
+
export declare function copyAgentsTemplate(targetDir: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Copy default config as template
|
|
24
|
+
*/
|
|
25
|
+
export declare function copyDefaultConfig(targetPath: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Check if config exists
|
|
28
|
+
*/
|
|
29
|
+
export declare function configExists(configPath: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Validate config structure
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateConfig(config: LoopConfig): {
|
|
34
|
+
valid: boolean;
|
|
35
|
+
errors: string[];
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU1D;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAsBzD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAexE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAalD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAkBpD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAgB1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CA2BvF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, cpSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { parse, stringify } from 'yaml';
|
|
4
|
+
import { DEFAULT_CONFIG } from '../types.js';
|
|
5
|
+
import { getBundledSkillsDir, getBundledCommandsDir, getDefaultConfigPath, getAgentsTemplatePath, getGlobalCommandsDir, } from './paths.js';
|
|
6
|
+
/**
|
|
7
|
+
* Read and parse config file, merging with defaults
|
|
8
|
+
*/
|
|
9
|
+
export function readConfig(configPath) {
|
|
10
|
+
if (!existsSync(configPath)) {
|
|
11
|
+
return { ...DEFAULT_CONFIG };
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
15
|
+
const parsed = parse(content);
|
|
16
|
+
// Deep merge with defaults
|
|
17
|
+
return {
|
|
18
|
+
backend: parsed.backend ?? DEFAULT_CONFIG.backend,
|
|
19
|
+
linear: parsed.linear,
|
|
20
|
+
jira: parsed.jira,
|
|
21
|
+
execution: {
|
|
22
|
+
...DEFAULT_CONFIG.execution,
|
|
23
|
+
...parsed.execution,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return { ...DEFAULT_CONFIG };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Write config to file
|
|
33
|
+
*/
|
|
34
|
+
export function writeConfig(configPath, config) {
|
|
35
|
+
const dir = dirname(configPath);
|
|
36
|
+
if (!existsSync(dir)) {
|
|
37
|
+
mkdirSync(dir, { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
const content = `# Loop Configuration
|
|
40
|
+
# Generated by 'loop setup'
|
|
41
|
+
#
|
|
42
|
+
# Environment variables override these settings:
|
|
43
|
+
# ISSUE_LOOP_BACKEND, ISSUE_LOOP_DELAY_SECONDS, etc.
|
|
44
|
+
|
|
45
|
+
${stringify(config)}`;
|
|
46
|
+
writeFileSync(configPath, content, 'utf-8');
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Copy skills from package to target directory
|
|
50
|
+
*/
|
|
51
|
+
export function copySkills(targetDir) {
|
|
52
|
+
const bundledDir = getBundledSkillsDir();
|
|
53
|
+
if (!existsSync(bundledDir)) {
|
|
54
|
+
throw new Error(`Bundled skills not found at ${bundledDir}`);
|
|
55
|
+
}
|
|
56
|
+
if (!existsSync(targetDir)) {
|
|
57
|
+
mkdirSync(targetDir, { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
// Copy each skill directory
|
|
60
|
+
cpSync(bundledDir, targetDir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Copy commands from package to target directory
|
|
64
|
+
*/
|
|
65
|
+
export function copyCommands(paths) {
|
|
66
|
+
const bundledDir = getBundledCommandsDir();
|
|
67
|
+
if (!existsSync(bundledDir)) {
|
|
68
|
+
// Commands are optional
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const targetDir = paths.type === 'local'
|
|
72
|
+
? join(dirname(paths.configPath), '.claude', 'commands')
|
|
73
|
+
: getGlobalCommandsDir();
|
|
74
|
+
if (!existsSync(targetDir)) {
|
|
75
|
+
mkdirSync(targetDir, { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
cpSync(bundledDir, targetDir, { recursive: true });
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Copy AGENTS.md template to project
|
|
81
|
+
*/
|
|
82
|
+
export function copyAgentsTemplate(targetDir) {
|
|
83
|
+
const templatePath = getAgentsTemplatePath();
|
|
84
|
+
const targetPath = join(targetDir, 'AGENTS.md');
|
|
85
|
+
if (!existsSync(templatePath)) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Only copy if target doesn't exist
|
|
89
|
+
if (!existsSync(targetPath)) {
|
|
90
|
+
const content = readFileSync(templatePath, 'utf-8');
|
|
91
|
+
writeFileSync(targetPath, content, 'utf-8');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Copy default config as template
|
|
96
|
+
*/
|
|
97
|
+
export function copyDefaultConfig(targetPath) {
|
|
98
|
+
const defaultPath = getDefaultConfigPath();
|
|
99
|
+
if (!existsSync(defaultPath)) {
|
|
100
|
+
// Create from DEFAULT_CONFIG if template missing
|
|
101
|
+
writeConfig(targetPath, DEFAULT_CONFIG);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const dir = dirname(targetPath);
|
|
105
|
+
if (!existsSync(dir)) {
|
|
106
|
+
mkdirSync(dir, { recursive: true });
|
|
107
|
+
}
|
|
108
|
+
const content = readFileSync(defaultPath, 'utf-8');
|
|
109
|
+
writeFileSync(targetPath, content, 'utf-8');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check if config exists
|
|
113
|
+
*/
|
|
114
|
+
export function configExists(configPath) {
|
|
115
|
+
return existsSync(configPath);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Validate config structure
|
|
119
|
+
*/
|
|
120
|
+
export function validateConfig(config) {
|
|
121
|
+
const errors = [];
|
|
122
|
+
if (!config.backend) {
|
|
123
|
+
errors.push('Missing required field: backend');
|
|
124
|
+
}
|
|
125
|
+
else if (!['linear', 'jira'].includes(config.backend)) {
|
|
126
|
+
errors.push(`Invalid backend: ${config.backend}. Must be 'linear' or 'jira'`);
|
|
127
|
+
}
|
|
128
|
+
if (!config.execution) {
|
|
129
|
+
errors.push('Missing required section: execution');
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
if (typeof config.execution.delay_seconds !== 'number' || config.execution.delay_seconds < 0) {
|
|
133
|
+
errors.push('execution.delay_seconds must be a non-negative number');
|
|
134
|
+
}
|
|
135
|
+
if (typeof config.execution.max_iterations !== 'number' ||
|
|
136
|
+
config.execution.max_iterations < 0) {
|
|
137
|
+
errors.push('execution.max_iterations must be a non-negative number');
|
|
138
|
+
}
|
|
139
|
+
if (!['opus', 'sonnet', 'haiku'].includes(config.execution.model)) {
|
|
140
|
+
errors.push(`Invalid model: ${config.execution.model}. Must be 'opus', 'sonnet', or 'haiku'`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return { valid: errors.length === 0, errors };
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PathConfig } from '../types.js';
|
|
2
|
+
/** Package root directory (where package.json lives) */
|
|
3
|
+
export declare function getPackageRoot(): string;
|
|
4
|
+
/** Global config directory (~/.config/mobius) */
|
|
5
|
+
export declare function getGlobalConfigDir(): string;
|
|
6
|
+
/** Global skills directory (~/.claude/skills) */
|
|
7
|
+
export declare function getGlobalSkillsDir(): string;
|
|
8
|
+
/** Global commands directory (~/.claude/commands) */
|
|
9
|
+
export declare function getGlobalCommandsDir(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Walk up from startDir looking for mobius.config.yaml
|
|
12
|
+
*/
|
|
13
|
+
export declare function findLocalConfig(startDir?: string): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve paths for local or global installation
|
|
16
|
+
* Priority: local config (walk up tree) > global config
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolvePaths(): PathConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Get paths for a specific installation type (used by setup)
|
|
21
|
+
*/
|
|
22
|
+
export declare function getPathsForType(type: 'local' | 'global', projectDir?: string): PathConfig;
|
|
23
|
+
/**
|
|
24
|
+
* Get bundled skills directory from package
|
|
25
|
+
*/
|
|
26
|
+
export declare function getBundledSkillsDir(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Get bundled commands directory from package
|
|
29
|
+
*/
|
|
30
|
+
export declare function getBundledCommandsDir(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Get default config template path
|
|
33
|
+
*/
|
|
34
|
+
export declare function getDefaultConfigPath(): string;
|
|
35
|
+
/**
|
|
36
|
+
* Get AGENTS.md template path
|
|
37
|
+
*/
|
|
38
|
+
export declare function getAgentsTemplatePath(): string;
|
|
39
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,wDAAwD;AACxD,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,qDAAqD;AACrD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAmB/E;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,UAAU,CAuBzC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAoBzF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
/** Package root directory (where package.json lives) */
|
|
8
|
+
export function getPackageRoot() {
|
|
9
|
+
// In dist/lib/paths.js, go up two levels to package root
|
|
10
|
+
return resolve(__dirname, '..', '..');
|
|
11
|
+
}
|
|
12
|
+
/** Global config directory (~/.config/mobius) */
|
|
13
|
+
export function getGlobalConfigDir() {
|
|
14
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join(homedir(), '.config');
|
|
15
|
+
return join(xdgConfig, 'mobius');
|
|
16
|
+
}
|
|
17
|
+
/** Global skills directory (~/.claude/skills) */
|
|
18
|
+
export function getGlobalSkillsDir() {
|
|
19
|
+
return join(homedir(), '.claude', 'skills');
|
|
20
|
+
}
|
|
21
|
+
/** Global commands directory (~/.claude/commands) */
|
|
22
|
+
export function getGlobalCommandsDir() {
|
|
23
|
+
return join(homedir(), '.claude', 'commands');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Walk up from startDir looking for mobius.config.yaml
|
|
27
|
+
*/
|
|
28
|
+
export function findLocalConfig(startDir = process.cwd()) {
|
|
29
|
+
let dir = resolve(startDir);
|
|
30
|
+
const root = dirname(dir);
|
|
31
|
+
while (dir !== root) {
|
|
32
|
+
const configPath = join(dir, 'mobius.config.yaml');
|
|
33
|
+
if (existsSync(configPath)) {
|
|
34
|
+
return configPath;
|
|
35
|
+
}
|
|
36
|
+
dir = dirname(dir);
|
|
37
|
+
}
|
|
38
|
+
// Check root as well
|
|
39
|
+
const rootConfig = join(root, 'mobius.config.yaml');
|
|
40
|
+
if (existsSync(rootConfig)) {
|
|
41
|
+
return rootConfig;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve paths for local or global installation
|
|
47
|
+
* Priority: local config (walk up tree) > global config
|
|
48
|
+
*/
|
|
49
|
+
export function resolvePaths() {
|
|
50
|
+
const packageRoot = getPackageRoot();
|
|
51
|
+
// Check for local config first
|
|
52
|
+
const localConfig = findLocalConfig();
|
|
53
|
+
if (localConfig) {
|
|
54
|
+
const projectRoot = dirname(localConfig);
|
|
55
|
+
return {
|
|
56
|
+
type: 'local',
|
|
57
|
+
configPath: localConfig,
|
|
58
|
+
skillsPath: join(projectRoot, '.claude', 'skills'),
|
|
59
|
+
scriptPath: join(packageRoot, 'scripts', 'mobius.sh'),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Fall back to global config
|
|
63
|
+
const globalConfigDir = getGlobalConfigDir();
|
|
64
|
+
return {
|
|
65
|
+
type: 'global',
|
|
66
|
+
configPath: join(globalConfigDir, 'config.yaml'),
|
|
67
|
+
skillsPath: getGlobalSkillsDir(),
|
|
68
|
+
scriptPath: join(packageRoot, 'scripts', 'mobius.sh'),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get paths for a specific installation type (used by setup)
|
|
73
|
+
*/
|
|
74
|
+
export function getPathsForType(type, projectDir) {
|
|
75
|
+
const packageRoot = getPackageRoot();
|
|
76
|
+
if (type === 'local') {
|
|
77
|
+
const dir = projectDir || process.cwd();
|
|
78
|
+
return {
|
|
79
|
+
type: 'local',
|
|
80
|
+
configPath: join(dir, 'mobius.config.yaml'),
|
|
81
|
+
skillsPath: join(dir, '.claude', 'skills'),
|
|
82
|
+
scriptPath: join(packageRoot, 'scripts', 'mobius.sh'),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const globalConfigDir = getGlobalConfigDir();
|
|
86
|
+
return {
|
|
87
|
+
type: 'global',
|
|
88
|
+
configPath: join(globalConfigDir, 'config.yaml'),
|
|
89
|
+
skillsPath: getGlobalSkillsDir(),
|
|
90
|
+
scriptPath: join(packageRoot, 'scripts', 'mobius.sh'),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get bundled skills directory from package
|
|
95
|
+
*/
|
|
96
|
+
export function getBundledSkillsDir() {
|
|
97
|
+
return join(getPackageRoot(), '.claude', 'skills');
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get bundled commands directory from package
|
|
101
|
+
*/
|
|
102
|
+
export function getBundledCommandsDir() {
|
|
103
|
+
return join(getPackageRoot(), '.claude', 'commands');
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get default config template path
|
|
107
|
+
*/
|
|
108
|
+
export function getDefaultConfigPath() {
|
|
109
|
+
return join(getPackageRoot(), 'mobius.config.yaml');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get AGENTS.md template path
|
|
113
|
+
*/
|
|
114
|
+
export function getAgentsTemplatePath() {
|
|
115
|
+
return join(getPackageRoot(), 'AGENTS.md');
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type Backend = 'linear' | 'jira';
|
|
2
|
+
export type Model = 'opus' | 'sonnet' | 'haiku';
|
|
3
|
+
export interface ExecutionConfig {
|
|
4
|
+
delay_seconds: number;
|
|
5
|
+
max_iterations: number;
|
|
6
|
+
model: Model;
|
|
7
|
+
sandbox: boolean;
|
|
8
|
+
container_name: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LinearConfig {
|
|
11
|
+
}
|
|
12
|
+
export interface JiraConfig {
|
|
13
|
+
base_url?: string;
|
|
14
|
+
project_key?: string;
|
|
15
|
+
auth_method?: 'api_token' | 'oauth';
|
|
16
|
+
}
|
|
17
|
+
export interface LoopConfig {
|
|
18
|
+
backend: Backend;
|
|
19
|
+
linear?: LinearConfig;
|
|
20
|
+
jira?: JiraConfig;
|
|
21
|
+
execution: ExecutionConfig;
|
|
22
|
+
}
|
|
23
|
+
export interface CheckResult {
|
|
24
|
+
name: string;
|
|
25
|
+
status: 'pass' | 'fail' | 'warn' | 'skip';
|
|
26
|
+
message: string;
|
|
27
|
+
required: boolean;
|
|
28
|
+
details?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface PathConfig {
|
|
31
|
+
type: 'local' | 'global';
|
|
32
|
+
configPath: string;
|
|
33
|
+
skillsPath: string;
|
|
34
|
+
scriptPath: string;
|
|
35
|
+
}
|
|
36
|
+
export declare const DEFAULT_CONFIG: LoopConfig;
|
|
37
|
+
export declare const BACKEND_SKILLS: Record<Backend, string>;
|
|
38
|
+
export declare const BACKEND_ID_PATTERNS: Record<Backend, RegExp>;
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AACxC,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;CAE5B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,EAAE,UAS5B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAGlD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAGvD,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const DEFAULT_CONFIG = {
|
|
2
|
+
backend: 'linear',
|
|
3
|
+
execution: {
|
|
4
|
+
delay_seconds: 3,
|
|
5
|
+
max_iterations: 50,
|
|
6
|
+
model: 'opus',
|
|
7
|
+
sandbox: true,
|
|
8
|
+
container_name: 'mobius-sandbox',
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export const BACKEND_SKILLS = {
|
|
12
|
+
linear: '/execute-linear-issue',
|
|
13
|
+
jira: '/execute-jira-issue',
|
|
14
|
+
};
|
|
15
|
+
export const BACKEND_ID_PATTERNS = {
|
|
16
|
+
linear: /^[A-Z]+-[0-9]+$/,
|
|
17
|
+
jira: /^[A-Z]+-[0-9]+$/,
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2CA,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,OAAO,EAAE,QAAQ;IACjB,SAAS,EAAE;QACT,aAAa,EAAE,CAAC;QAChB,cAAc,EAAE,EAAE;QAClB,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,IAAI;QACb,cAAc,EAAE,gBAAgB;KACjC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,MAAM,EAAE,uBAAuB;IAC/B,IAAI,EAAE,qBAAqB;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAA4B;IAC1D,MAAM,EAAE,iBAAiB;IACzB,IAAI,EAAE,iBAAiB;CACxB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Mobius Configuration
|
|
2
|
+
# Copy to ~/.config/mobius/config.yaml and customize
|
|
3
|
+
#
|
|
4
|
+
# Environment variables override these settings:
|
|
5
|
+
# MOBIUS_BACKEND, MOBIUS_DELAY_SECONDS, etc.
|
|
6
|
+
|
|
7
|
+
# Issue tracker backend: linear | jira
|
|
8
|
+
backend: linear
|
|
9
|
+
|
|
10
|
+
# Backend-specific settings
|
|
11
|
+
linear:
|
|
12
|
+
# Uses Linear MCP tools (auto-configured via Claude Code)
|
|
13
|
+
# No additional configuration required
|
|
14
|
+
|
|
15
|
+
jira:
|
|
16
|
+
# Future Jira integration
|
|
17
|
+
# Uncomment and configure when using Jira backend:
|
|
18
|
+
# base_url: https://yourcompany.atlassian.net
|
|
19
|
+
# project_key: PROJ
|
|
20
|
+
# auth_method: api_token # api_token | oauth
|
|
21
|
+
|
|
22
|
+
# Execution settings
|
|
23
|
+
execution:
|
|
24
|
+
# Seconds to wait between loop iterations
|
|
25
|
+
delay_seconds: 3
|
|
26
|
+
|
|
27
|
+
# Maximum iterations (0 = unlimited)
|
|
28
|
+
max_iterations: 50
|
|
29
|
+
|
|
30
|
+
# Claude model to use: opus | sonnet | haiku
|
|
31
|
+
model: opus
|
|
32
|
+
|
|
33
|
+
# Run in Docker sandbox by default (safer for autonomous execution)
|
|
34
|
+
# Set to false or use --local flag to run directly
|
|
35
|
+
sandbox: true
|
|
36
|
+
|
|
37
|
+
# Docker container name for sandbox mode
|
|
38
|
+
container_name: mobius-sandbox
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mobius-loop",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AI-Powered Development Workflow Tool - Execute Linear/Jira issues with Claude",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/bin/mobius.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mobius": "dist/bin/mobius.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/bin/mobius.js",
|
|
14
|
+
"clean": "rm -rf dist",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"claude",
|
|
19
|
+
"linear",
|
|
20
|
+
"jira",
|
|
21
|
+
"ai",
|
|
22
|
+
"automation",
|
|
23
|
+
"workflow",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"author": "Dustin Verzal <dustin@tubular.health>",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/Tubular-Health/mobius.git"
|
|
30
|
+
},
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18.0.0"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"scripts",
|
|
38
|
+
".claude",
|
|
39
|
+
"mobius.config.yaml",
|
|
40
|
+
"AGENTS.md"
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@inquirer/prompts": "^7.0.0",
|
|
44
|
+
"chalk": "^5.3.0",
|
|
45
|
+
"commander": "^12.0.0",
|
|
46
|
+
"execa": "^8.0.0",
|
|
47
|
+
"which": "^4.0.0",
|
|
48
|
+
"yaml": "^2.3.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@mermaid-js/mermaid-cli": "^11.0.0",
|
|
52
|
+
"@types/node": "^20.0.0",
|
|
53
|
+
"@types/which": "^3.0.0",
|
|
54
|
+
"typescript": "^5.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|