odoo-forge 0.1.4 → 0.1.6
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/bin/odoo-forge.js +0 -0
- package/package.json +2 -2
- package/src/codex.js +98 -12
package/bin/odoo-forge.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "odoo-forge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "CLI installer and updater for Odoo Forge internal 1.0.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"odoo-forge-bundle": "0.1.
|
|
7
|
+
"odoo-forge-bundle": "0.1.6"
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
10
|
"odoo-forge": "bin/odoo-forge.js"
|
package/src/codex.js
CHANGED
|
@@ -12,25 +12,112 @@ export function buildCodexManagedBlock({ token }) {
|
|
|
12
12
|
type = "stdio"
|
|
13
13
|
command = "npx"
|
|
14
14
|
args = ["-y", "flowus-mcp-server@latest"]
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
[mcp_servers.flowus.env]
|
|
17
|
+
FLOWUS_TOKEN = "${token}"
|
|
16
18
|
${CODEX_END_MARKER}`;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
function stripManagedBlock({
|
|
20
22
|
originalContent,
|
|
21
23
|
startMarker,
|
|
22
24
|
endMarker,
|
|
23
|
-
block,
|
|
24
25
|
}) {
|
|
25
26
|
const startIndex = originalContent.indexOf(startMarker);
|
|
26
27
|
const endIndex = originalContent.indexOf(endMarker);
|
|
27
28
|
|
|
28
|
-
if (startIndex
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
|
|
30
|
+
return originalContent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const blockEnd = endIndex + endMarker.length;
|
|
34
|
+
return `${originalContent.slice(0, startIndex)}${originalContent.slice(blockEnd)}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isFlowusSectionHeader(headerName) {
|
|
38
|
+
return headerName === "mcp_servers.flowus" || headerName.startsWith("mcp_servers.flowus.");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function removeFlowusSections(originalContent) {
|
|
42
|
+
const lines = originalContent.split("\n");
|
|
43
|
+
const keptLines = [];
|
|
44
|
+
let skipCurrentSection = false;
|
|
45
|
+
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
const sectionMatch = line.match(/^\s*\[([^\]]+)\]\s*$/);
|
|
48
|
+
if (sectionMatch) {
|
|
49
|
+
skipCurrentSection = isFlowusSectionHeader(sectionMatch[1]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!skipCurrentSection) {
|
|
53
|
+
keptLines.push(line);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return keptLines.join("\n");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function readSectionContent({ originalContent, sectionName }) {
|
|
61
|
+
const lines = originalContent.split("\n");
|
|
62
|
+
const collected = [];
|
|
63
|
+
let inSection = false;
|
|
64
|
+
|
|
65
|
+
for (const line of lines) {
|
|
66
|
+
const sectionMatch = line.match(/^\s*\[([^\]]+)\]\s*$/);
|
|
67
|
+
if (sectionMatch) {
|
|
68
|
+
if (inSection) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
inSection = sectionMatch[1] === sectionName;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (inSection) {
|
|
76
|
+
collected.push(line);
|
|
77
|
+
}
|
|
31
78
|
}
|
|
32
79
|
|
|
33
|
-
|
|
80
|
+
return inSection ? collected.join("\n") : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function extractTokenFromContent(originalContent) {
|
|
84
|
+
const flowusSection = readSectionContent({
|
|
85
|
+
originalContent,
|
|
86
|
+
sectionName: "mcp_servers.flowus",
|
|
87
|
+
});
|
|
88
|
+
const envSection = readSectionContent({
|
|
89
|
+
originalContent,
|
|
90
|
+
sectionName: "mcp_servers.flowus.env",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const candidates = [envSection, flowusSection, originalContent];
|
|
94
|
+
for (const candidate of candidates) {
|
|
95
|
+
if (!candidate) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const inlineMatch = candidate.match(/FLOWUS_TOKEN\s*=\s*"([^"]+)"/);
|
|
100
|
+
if (inlineMatch) {
|
|
101
|
+
return inlineMatch[1];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function upsertManagedBlock({
|
|
109
|
+
originalContent,
|
|
110
|
+
startMarker,
|
|
111
|
+
endMarker,
|
|
112
|
+
block,
|
|
113
|
+
}) {
|
|
114
|
+
const withoutManagedBlock = stripManagedBlock({
|
|
115
|
+
originalContent,
|
|
116
|
+
startMarker,
|
|
117
|
+
endMarker,
|
|
118
|
+
});
|
|
119
|
+
const withoutFlowusSections = removeFlowusSections(withoutManagedBlock);
|
|
120
|
+
const trimmed = withoutFlowusSections.trimEnd();
|
|
34
121
|
return trimmed ? `${trimmed}\n\n${block}\n` : `${block}\n`;
|
|
35
122
|
}
|
|
36
123
|
|
|
@@ -43,13 +130,12 @@ export function readCodexManagedToken({ homeDir }) {
|
|
|
43
130
|
const content = fs.readFileSync(configPath, "utf8");
|
|
44
131
|
const startIndex = content.indexOf(CODEX_START_MARKER);
|
|
45
132
|
const endIndex = content.indexOf(CODEX_END_MARKER);
|
|
46
|
-
if (startIndex
|
|
47
|
-
|
|
133
|
+
if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
|
|
134
|
+
const managedBlock = content.slice(startIndex, endIndex + CODEX_END_MARKER.length);
|
|
135
|
+
return extractTokenFromContent(managedBlock);
|
|
48
136
|
}
|
|
49
137
|
|
|
50
|
-
|
|
51
|
-
const match = managedBlock.match(/FLOWUS_TOKEN\s*=\s*"([^"]+)"/);
|
|
52
|
-
return match?.[1] ?? null;
|
|
138
|
+
return extractTokenFromContent(content);
|
|
53
139
|
}
|
|
54
140
|
|
|
55
141
|
export function installCodexWiring({ homeDir, token }) {
|