agentlas 0.9.10 → 1.0.2
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 +106 -0
- package/README.md +319 -341
- package/bin/agentlas.cjs +32 -9
- package/engine/agentlas-banner.cjs +24 -3
- package/engine/agentlas-composer.cjs +239 -31
- package/engine/agentlas-config.cjs +103 -7
- package/engine/agentlas-core-harness.cjs +48 -4
- package/engine/agentlas-evolution.cjs +3 -4
- package/engine/agentlas-i18n.cjs +88 -32
- package/engine/agentlas-input.cjs +234 -18
- package/engine/agentlas-memory-governance.cjs +3 -5
- package/engine/agentlas-memory-import.cjs +3 -3
- package/engine/agentlas-native-host.cjs +200 -9
- package/engine/agentlas-onboard.cjs +112 -20
- package/engine/agentlas-permissions.cjs +14 -7
- package/engine/agentlas-sqlite-policy.cjs +34 -0
- package/engine/agentlas-ui.cjs +93 -42
- package/engine/agentlas-workforce.cjs +472 -58
- package/engine/agentlas-workload-routing.cjs +8 -3
- package/engine/agentlas.cjs +140 -12367
- package/engine/agents/files.cjs +61 -0
- package/engine/agents/import-local.cjs +237 -0
- package/engine/agents/registry.cjs +158 -0
- package/engine/agents/router.cjs +565 -0
- package/engine/agents/routes.cjs +43 -0
- package/engine/architecture.data.json +2 -2
- package/engine/automation/daemon.cjs +335 -0
- package/engine/automation/schedule.cjs +181 -0
- package/engine/automation/store.cjs +209 -0
- package/engine/cloud/auth.cjs +279 -0
- package/engine/cloud/hub-client.cjs +239 -0
- package/engine/cloud-assets/cargo.cjs +49 -0
- package/engine/cloud-assets/cas.cjs +235 -0
- package/engine/cloud-assets/commands.cjs +273 -0
- package/engine/cloud-assets/package.cjs +936 -0
- package/engine/cloud-assets/restore.cjs +172 -0
- package/engine/cloud-assets/state.cjs +268 -0
- package/engine/commands/automation.cjs +195 -0
- package/engine/commands/billing.cjs +96 -0
- package/engine/commands/browser.cjs +20 -0
- package/engine/commands/build.cjs +33 -0
- package/engine/commands/call.cjs +24 -0
- package/engine/commands/career-graph.cjs +51 -0
- package/engine/commands/cd.cjs +22 -0
- package/engine/commands/chat.cjs +12 -0
- package/engine/commands/chats.cjs +28 -0
- package/engine/commands/cloud.cjs +17 -0
- package/engine/commands/connect.cjs +20 -0
- package/engine/commands/context.cjs +66 -0
- package/engine/commands/creds.cjs +203 -0
- package/engine/commands/doctor.cjs +68 -0
- package/engine/commands/env.cjs +33 -0
- package/engine/commands/evolve.cjs +23 -0
- package/engine/commands/experience.cjs +34 -0
- package/engine/commands/film.cjs +8 -0
- package/engine/commands/firm.cjs +115 -0
- package/engine/commands/help.cjs +65 -0
- package/engine/commands/hep.cjs +23 -0
- package/engine/commands/import.cjs +35 -0
- package/engine/commands/index.cjs +136 -0
- package/engine/commands/install.cjs +27 -0
- package/engine/commands/journal.cjs +31 -0
- package/engine/commands/legacy-network.cjs +29 -0
- package/engine/commands/list.cjs +49 -0
- package/engine/commands/login.cjs +68 -0
- package/engine/commands/logout.cjs +28 -0
- package/engine/commands/mcp.cjs +91 -0
- package/engine/commands/memory.cjs +21 -0
- package/engine/commands/multimodal.cjs +91 -0
- package/engine/commands/native.cjs +34 -0
- package/engine/commands/netadmin.cjs +31 -0
- package/engine/commands/oberon.cjs +70 -0
- package/engine/commands/ontology.cjs +24 -0
- package/engine/commands/open.cjs +48 -0
- package/engine/commands/plugin.cjs +101 -0
- package/engine/commands/project.cjs +47 -0
- package/engine/commands/research.cjs +36 -0
- package/engine/commands/route.cjs +37 -0
- package/engine/commands/run.cjs +149 -0
- package/engine/commands/search.cjs +55 -0
- package/engine/commands/setup.cjs +45 -0
- package/engine/commands/storm.cjs +75 -0
- package/engine/commands/swarm.cjs +75 -0
- package/engine/commands/telegram.cjs +32 -0
- package/engine/commands/uninstall.cjs +68 -0
- package/engine/commands/update.cjs +54 -0
- package/engine/commands/upload.cjs +18 -0
- package/engine/commands/usage.cjs +35 -0
- package/engine/commands/variant.cjs +25 -0
- package/engine/commands/version.cjs +9 -0
- package/engine/commands/whoami.cjs +38 -0
- package/engine/commands/workforce.cjs +103 -0
- package/engine/core/db.cjs +160 -0
- package/engine/core/paths.cjs +35 -0
- package/engine/experience/build.cjs +181 -0
- package/engine/experience/intents.cjs +492 -0
- package/engine/experience/runtime.cjs +242 -0
- package/engine/experience/variant.cjs +196 -0
- package/engine/firms/orchestrate.cjs +333 -0
- package/engine/hephaestus/runtime.cjs +697 -0
- package/engine/hub/install.cjs +872 -0
- package/engine/hub/plugins.cjs +213 -0
- package/engine/mcp/consent.cjs +289 -0
- package/engine/mcp/contract.cjs +202 -0
- package/engine/mcp/index.cjs +43 -0
- package/engine/mcp/inventory.cjs +322 -0
- package/engine/mcp/plan.cjs +286 -0
- package/engine/mcp/probe.cjs +151 -0
- package/engine/memory-cli/curate.cjs +163 -0
- package/engine/oberon/common.cjs +69 -0
- package/engine/oberon/manifest.cjs +164 -0
- package/engine/oberon/outputs.cjs +70 -0
- package/engine/oberon/render.cjs +164 -0
- package/engine/project/career-graph.cjs +249 -0
- package/engine/project/credentials.cjs +262 -0
- package/engine/project/env-file.cjs +46 -0
- package/engine/project/index.cjs +27 -0
- package/engine/project/memory-context.cjs +453 -0
- package/engine/project/ontology.cjs +467 -0
- package/engine/project/paths.cjs +39 -0
- package/engine/project/seed.cjs +200 -0
- package/engine/project/state.cjs +403 -0
- package/engine/project/super-ontology-seed.json +3288 -0
- package/engine/runtimes/detect.cjs +54 -0
- package/engine/runtimes/overrides.cjs +139 -0
- package/engine/runtimes/resolve.cjs +64 -0
- package/engine/sessions/apply-fences.cjs +188 -0
- package/engine/sessions/fences.cjs +362 -0
- package/engine/sessions/orchestrator.cjs +170 -0
- package/engine/sessions/prompt.cjs +212 -0
- package/engine/sessions/session.cjs +245 -0
- package/engine/sessions/sink.cjs +54 -0
- package/engine/sessions/store.cjs +79 -0
- package/engine/storm/deps.cjs +88 -0
- package/engine/storm/storm.cjs +218 -0
- package/engine/storm/swarm.cjs +422 -0
- package/engine/ui/palette.cjs +105 -0
- package/engine/ui/renderer.cjs +85 -0
- package/engine/ui/repl.cjs +444 -0
- package/engine/workforce/capture.cjs +701 -0
- package/engine/workforce/deps.cjs +472 -0
- package/package.json +2 -6
- package/engine/agentlas-experience-mcp.cjs +0 -1709
- package/engine/agentlas-parity.cjs +0 -1499
- package/engine/agentlas-repl.cjs +0 -1780
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* project/credentials — 프로젝트 로컬 자격증명 스토어 (v1 monolith 3957–4182 포팅).
|
|
4
|
+
*
|
|
5
|
+
* 계약:
|
|
6
|
+
* - 값(비밀)은 절대 .agentlas/local-credentials.map.json 이나 soul memory에 기록하지
|
|
7
|
+
* 않는다. 여기엔 env 이름·상대 경로·owner·stale-check 메모만 남는다.
|
|
8
|
+
* - signing/, credentials/ 폴더와 .env* 는 ensureAgentlasCredentialIgnoreCli 가
|
|
9
|
+
* 프로젝트 .gitignore에 별도 블록으로 등록한다 (README만 예외로 커밋 허용).
|
|
10
|
+
*/
|
|
11
|
+
const fs = require("node:fs");
|
|
12
|
+
const path = require("node:path");
|
|
13
|
+
const { loadArch } = require("../core/db.cjs");
|
|
14
|
+
const { runCwd } = require("./paths.cjs");
|
|
15
|
+
|
|
16
|
+
function localCredentialConfigCli(arch) {
|
|
17
|
+
return {
|
|
18
|
+
mapFile: arch.localCredentialsMapFile || "local-credentials.map.json",
|
|
19
|
+
envExampleFile: arch.projectEnvExampleFile || ".env.example",
|
|
20
|
+
signingDir: arch.projectSigningDir || "signing",
|
|
21
|
+
credentialsDir: arch.projectCredentialsDir || "credentials",
|
|
22
|
+
readmeFile: arch.projectCredentialsReadmeFile || "README.md",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function projectEnvIdCli(projectPath) {
|
|
26
|
+
const raw = path.basename(projectPath || runCwd() || "project") || "project";
|
|
27
|
+
return raw.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "PROJECT";
|
|
28
|
+
}
|
|
29
|
+
function projectScopedGlobalEnvKeyCli(projectPath, key) {
|
|
30
|
+
return `AGENTLAS_PROJECT_${projectEnvIdCli(projectPath)}_${key}`;
|
|
31
|
+
}
|
|
32
|
+
function projectScopedEnvValuesCli(values, projectPath) {
|
|
33
|
+
const prefix = `AGENTLAS_PROJECT_${projectEnvIdCli(projectPath)}_`;
|
|
34
|
+
const result = {};
|
|
35
|
+
for (const [key, value] of Object.entries(values || {})) {
|
|
36
|
+
if (!key.startsWith(prefix)) continue;
|
|
37
|
+
const actualKey = key.slice(prefix.length);
|
|
38
|
+
if (/^[A-Z][A-Z0-9_]*$/.test(actualKey)) result[actualKey] = value;
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
function localCredentialsMapSkeletonCli(projectPath, projectName, cfg) {
|
|
43
|
+
const now = new Date().toISOString();
|
|
44
|
+
return {
|
|
45
|
+
schemaVersion: "1.0",
|
|
46
|
+
kind: "agentlas-local-credential-store",
|
|
47
|
+
projectName,
|
|
48
|
+
projectRoot: projectPath,
|
|
49
|
+
createdAt: now,
|
|
50
|
+
updatedAt: now,
|
|
51
|
+
envFiles: [".env", ".env.local"],
|
|
52
|
+
secretDirs: [cfg.signingDir, cfg.credentialsDir],
|
|
53
|
+
entries: [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const CREDENTIAL_INDEX_SECTION_CLI = "## Local Credential Index (read first)";
|
|
57
|
+
function credentialIndexSectionContentCli(arch) {
|
|
58
|
+
const cfg = localCredentialConfigCli(arch || loadArch());
|
|
59
|
+
const mapFile = (arch && arch.localCredentialsMapFile) || "local-credentials.map.json";
|
|
60
|
+
return `${CREDENTIAL_INDEX_SECTION_CLI}
|
|
61
|
+
|
|
62
|
+
- For deploy, release, store, billing, auth, API, or cloud work, read
|
|
63
|
+
.agentlas/${mapFile} before saying a credential is missing.
|
|
64
|
+
- Real values may live in .env, .env.local, ${cfg.signingDir}/,
|
|
65
|
+
${cfg.credentialsDir}/, local keychain/vault, or project-scoped global env
|
|
66
|
+
keys like AGENTLAS_PROJECT_<PROJECT>_<ENV_NAME>.
|
|
67
|
+
- Keep this memory value-free: record env names, local relative paths, owner,
|
|
68
|
+
stale-check notes, and validation commands only.
|
|
69
|
+
|
|
70
|
+
| Need | Look here first | Memory record |
|
|
71
|
+
|------|-----------------|---------------|
|
|
72
|
+
| Scalar env key | .env or .env.local | env name only |
|
|
73
|
+
| Store/signing file | ${cfg.signingDir}/ | relative path only |
|
|
74
|
+
| App/provider config | ${cfg.credentialsDir}/ | relative path only |
|
|
75
|
+
| Shared local env | AGENTLAS_PROJECT_<PROJECT>_<ENV_NAME> | project-scoped env name |
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
function projectSoulTemplateCli(projectName, arch) {
|
|
79
|
+
return `# Project Soul Memory: ${projectName}
|
|
80
|
+
|
|
81
|
+
Durable memory for this project folder, maintained by Agentlas.
|
|
82
|
+
|
|
83
|
+
${credentialIndexSectionContentCli(arch)}
|
|
84
|
+
|
|
85
|
+
## Project Purpose
|
|
86
|
+
|
|
87
|
+
## Current State
|
|
88
|
+
|
|
89
|
+
## Decisions
|
|
90
|
+
|
|
91
|
+
## Risks
|
|
92
|
+
|
|
93
|
+
## Auto-curated memory
|
|
94
|
+
`;
|
|
95
|
+
}
|
|
96
|
+
function ensureSoulCredentialIndexCli(projectPath, projectName, arch) {
|
|
97
|
+
const memoryDir = (arch && arch.memoryDir) || ".agentlas";
|
|
98
|
+
const soulFile = (arch && arch.soulFile) || "project-soul-memory.md";
|
|
99
|
+
const dir = path.join(projectPath, memoryDir);
|
|
100
|
+
const soul = path.join(dir, soulFile);
|
|
101
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
102
|
+
if (!fs.existsSync(soul)) {
|
|
103
|
+
fs.writeFileSync(soul, projectSoulTemplateCli(projectName, arch), "utf8");
|
|
104
|
+
return soul;
|
|
105
|
+
}
|
|
106
|
+
let content = "";
|
|
107
|
+
try { content = fs.readFileSync(soul, "utf8"); } catch { content = ""; }
|
|
108
|
+
if (!content.includes(CREDENTIAL_INDEX_SECTION_CLI)) {
|
|
109
|
+
const section = credentialIndexSectionContentCli(arch);
|
|
110
|
+
const marker = "\n## Project Purpose";
|
|
111
|
+
const next = content.includes(marker)
|
|
112
|
+
? content.replace(marker, `\n${section}\n## Project Purpose`)
|
|
113
|
+
: `${content.trimEnd()}\n\n${section}\n`;
|
|
114
|
+
fs.writeFileSync(soul, next.endsWith("\n") ? next : next + "\n", "utf8");
|
|
115
|
+
}
|
|
116
|
+
return soul;
|
|
117
|
+
}
|
|
118
|
+
function envExampleContentCli(cfg) {
|
|
119
|
+
return `# Agentlas local project environment.
|
|
120
|
+
# Copy this file to .env and fill real values only on this machine.
|
|
121
|
+
|
|
122
|
+
# File-path style for tools that expect a local JSON credential file.
|
|
123
|
+
SUPPLY_JSON_KEY=${cfg.signingDir}/google-play.json
|
|
124
|
+
|
|
125
|
+
# Inline JSON style for tools that support reading a credential directly from env.
|
|
126
|
+
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON=
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
129
|
+
function signingReadmeContentCli(cfg) {
|
|
130
|
+
return `# ${cfg.signingDir}/
|
|
131
|
+
|
|
132
|
+
Put release signing material here when this project needs local deploy or store
|
|
133
|
+
automation. This folder is ignored by git except for this README.
|
|
134
|
+
|
|
135
|
+
Examples:
|
|
136
|
+
|
|
137
|
+
- Google Play release JSON used by SUPPLY_JSON_KEY
|
|
138
|
+
- Apple signing certificates or provisioning profiles
|
|
139
|
+
- Notarization or release upload keys
|
|
140
|
+
|
|
141
|
+
Do not commit files from this folder.
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
144
|
+
function credentialsReadmeContentCli(cfg) {
|
|
145
|
+
return `# ${cfg.credentialsDir}/
|
|
146
|
+
|
|
147
|
+
Put app or service configuration files here when this project needs local runtime
|
|
148
|
+
access. This folder is ignored by git except for this README.
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
|
|
152
|
+
- Android google-services.json
|
|
153
|
+
- iOS GoogleService-Info.plist
|
|
154
|
+
- provider config files used only by this local project
|
|
155
|
+
|
|
156
|
+
Do not commit files from this folder.
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
function ensureAgentlasCredentialIgnoreCli(projectPath, cfg) {
|
|
160
|
+
const gitignorePath = path.join(projectPath, ".gitignore");
|
|
161
|
+
const marker = "# Agentlas local credentials";
|
|
162
|
+
const block = `${marker}
|
|
163
|
+
.env
|
|
164
|
+
.env.local
|
|
165
|
+
.env.*.local
|
|
166
|
+
._*
|
|
167
|
+
${cfg.signingDir}/*
|
|
168
|
+
!${cfg.signingDir}/
|
|
169
|
+
!${cfg.signingDir}/${cfg.readmeFile}
|
|
170
|
+
${cfg.credentialsDir}/*
|
|
171
|
+
!${cfg.credentialsDir}/
|
|
172
|
+
!${cfg.credentialsDir}/${cfg.readmeFile}
|
|
173
|
+
`;
|
|
174
|
+
let existing = "";
|
|
175
|
+
try { existing = fs.readFileSync(gitignorePath, "utf8"); } catch { existing = ""; }
|
|
176
|
+
if (existing.includes(marker)) {
|
|
177
|
+
if (!/^\._\*$/m.test(existing)) fs.writeFileSync(gitignorePath, `${existing.trimEnd()}\n._*\n`, "utf8");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const next = existing.trimEnd() ? `${existing.trimEnd()}\n\n${block}` : block;
|
|
181
|
+
fs.writeFileSync(gitignorePath, next.endsWith("\n") ? next : next + "\n", "utf8");
|
|
182
|
+
}
|
|
183
|
+
function ensureLocalCredentialStoreCli(projectPath, projectName, arch) {
|
|
184
|
+
const cfg = localCredentialConfigCli(arch || loadArch());
|
|
185
|
+
const dir = path.join(projectPath, (arch && arch.memoryDir) || ".agentlas");
|
|
186
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
187
|
+
fs.mkdirSync(path.join(projectPath, cfg.signingDir), { recursive: true });
|
|
188
|
+
fs.mkdirSync(path.join(projectPath, cfg.credentialsDir), { recursive: true });
|
|
189
|
+
const envExample = path.join(projectPath, cfg.envExampleFile);
|
|
190
|
+
if (!fs.existsSync(envExample)) fs.writeFileSync(envExample, envExampleContentCli(cfg), "utf8");
|
|
191
|
+
const signingReadme = path.join(projectPath, cfg.signingDir, cfg.readmeFile);
|
|
192
|
+
if (!fs.existsSync(signingReadme)) fs.writeFileSync(signingReadme, signingReadmeContentCli(cfg), "utf8");
|
|
193
|
+
const credentialsReadme = path.join(projectPath, cfg.credentialsDir, cfg.readmeFile);
|
|
194
|
+
if (!fs.existsSync(credentialsReadme)) fs.writeFileSync(credentialsReadme, credentialsReadmeContentCli(cfg), "utf8");
|
|
195
|
+
const mapPath = path.join(dir, cfg.mapFile);
|
|
196
|
+
if (!fs.existsSync(mapPath)) {
|
|
197
|
+
fs.writeFileSync(mapPath, JSON.stringify(localCredentialsMapSkeletonCli(projectPath, projectName, cfg), null, 2) + "\n", "utf8");
|
|
198
|
+
}
|
|
199
|
+
ensureAgentlasCredentialIgnoreCli(projectPath, cfg);
|
|
200
|
+
return { cfg, mapPath };
|
|
201
|
+
}
|
|
202
|
+
function readJsonObjectCli(file, fallback) {
|
|
203
|
+
try {
|
|
204
|
+
const parsed = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
205
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : fallback;
|
|
206
|
+
} catch {
|
|
207
|
+
return fallback;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function upsertLocalCredentialMapCli(projectPath, projectName, arch, entry) {
|
|
211
|
+
const { cfg, mapPath } = ensureLocalCredentialStoreCli(projectPath, projectName, arch || loadArch());
|
|
212
|
+
const data = readJsonObjectCli(mapPath, localCredentialsMapSkeletonCli(projectPath, projectName, cfg));
|
|
213
|
+
const now = new Date().toISOString();
|
|
214
|
+
data.updatedAt = now;
|
|
215
|
+
if (!Array.isArray(data.entries)) data.entries = [];
|
|
216
|
+
const id = entry.id || `${entry.provider || "credential"}:${(entry.env || []).join(",") || (entry.localFiles || []).join(",")}`;
|
|
217
|
+
const clean = {
|
|
218
|
+
id,
|
|
219
|
+
provider: entry.provider || "unknown",
|
|
220
|
+
env: Array.isArray(entry.env) ? [...new Set(entry.env.filter(Boolean))] : [],
|
|
221
|
+
localFiles: Array.isArray(entry.localFiles) ? [...new Set(entry.localFiles.filter(Boolean))] : [],
|
|
222
|
+
owner: entry.owner || "project",
|
|
223
|
+
valueMaterialized: Boolean(entry.valueMaterialized),
|
|
224
|
+
storage: Array.isArray(entry.storage) ? [...new Set(entry.storage.filter(Boolean))] : [],
|
|
225
|
+
requiredFor: Array.isArray(entry.requiredFor) ? [...new Set(entry.requiredFor.filter(Boolean))] : [],
|
|
226
|
+
lastVerified: entry.lastVerified || null,
|
|
227
|
+
staleCheck: entry.staleCheck || null,
|
|
228
|
+
updatedAt: now,
|
|
229
|
+
};
|
|
230
|
+
const idx = data.entries.findIndex((row) => row && row.id === id);
|
|
231
|
+
if (idx >= 0) data.entries[idx] = { ...data.entries[idx], ...clean };
|
|
232
|
+
else data.entries.push(clean);
|
|
233
|
+
fs.writeFileSync(mapPath, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
234
|
+
}
|
|
235
|
+
// v1은 fail()로 즉시 종료했다 — v2 규칙은 throw → 명령이 ctx.err + return 1 로 변환.
|
|
236
|
+
function safeCredentialDestRelCli(destRel) {
|
|
237
|
+
const rel = path.normalize(String(destRel || "")).replace(/\\/g, "/");
|
|
238
|
+
if (!rel || path.isAbsolute(rel) || rel === "." || rel.startsWith("../") || rel.includes("\0")) {
|
|
239
|
+
throw new Error("credential destination must be a relative path inside the project");
|
|
240
|
+
}
|
|
241
|
+
return rel;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
module.exports = {
|
|
245
|
+
CREDENTIAL_INDEX_SECTION_CLI,
|
|
246
|
+
localCredentialConfigCli,
|
|
247
|
+
projectEnvIdCli,
|
|
248
|
+
projectScopedGlobalEnvKeyCli,
|
|
249
|
+
projectScopedEnvValuesCli,
|
|
250
|
+
localCredentialsMapSkeletonCli,
|
|
251
|
+
credentialIndexSectionContentCli,
|
|
252
|
+
projectSoulTemplateCli,
|
|
253
|
+
ensureSoulCredentialIndexCli,
|
|
254
|
+
envExampleContentCli,
|
|
255
|
+
signingReadmeContentCli,
|
|
256
|
+
credentialsReadmeContentCli,
|
|
257
|
+
ensureAgentlasCredentialIgnoreCli,
|
|
258
|
+
ensureLocalCredentialStoreCli,
|
|
259
|
+
readJsonObjectCli,
|
|
260
|
+
upsertLocalCredentialMapCli,
|
|
261
|
+
safeCredentialDestRelCli,
|
|
262
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* project/env-file — .env 계열 파일 읽기/한 줄 갱신 헬퍼.
|
|
4
|
+
*
|
|
5
|
+
* readDotEnvFile은 commands/env.cjs에서 이관했다 (명령 파일끼리 import 금지 규칙
|
|
6
|
+
* 때문에 creds 명령이 공유하려면 기능 모듈로 내려와야 한다).
|
|
7
|
+
* upsertEnvLine은 v1 monolith 11226–11238 포팅.
|
|
8
|
+
*/
|
|
9
|
+
const fs = require("node:fs");
|
|
10
|
+
const path = require("node:path");
|
|
11
|
+
|
|
12
|
+
/** .env 파싱 — 값 보존 없이 키만 필요할 때도 같은 파서를 쓴다 (KEY=VALUE, # 주석). */
|
|
13
|
+
function readDotEnvFile(file) {
|
|
14
|
+
const result = {};
|
|
15
|
+
let raw;
|
|
16
|
+
try {
|
|
17
|
+
raw = fs.readFileSync(file, "utf8");
|
|
18
|
+
} catch {
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
22
|
+
const trimmed = line.trim();
|
|
23
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
24
|
+
const eq = trimmed.indexOf("=");
|
|
25
|
+
if (eq <= 0) continue;
|
|
26
|
+
const key = trimmed.slice(0, eq).trim();
|
|
27
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) result[key] = trimmed.slice(eq + 1);
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function upsertEnvLine(file, key, value) {
|
|
33
|
+
let body = "";
|
|
34
|
+
try { body = fs.readFileSync(file, "utf8"); } catch { /* new file */ }
|
|
35
|
+
const line = `${key}=${value}`;
|
|
36
|
+
const re = new RegExp("^" + key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "=.*$", "m");
|
|
37
|
+
if (re.test(body)) body = body.replace(re, line);
|
|
38
|
+
else body = body ? body.replace(/\n?$/, "\n") + line + "\n" : line + "\n";
|
|
39
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
40
|
+
// 이 헬퍼의 모든 호출자는 credential 값/경로를 기록한다. 새 파일뿐 아니라 기존 0644
|
|
41
|
+
// 파일도 매번 0600으로 수렴시켜 같은 머신의 다른 계정이 읽지 못하게 한다.
|
|
42
|
+
fs.writeFileSync(file, body, { encoding: "utf8", mode: 0o600 });
|
|
43
|
+
try { fs.chmodSync(file, 0o600); } catch { /* Windows/읽기전용 FS best-effort */ }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { readDotEnvFile, upsertEnvLine };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* project/index — 프로젝트 상태 서브시스템 배럴.
|
|
4
|
+
*
|
|
5
|
+
* test/project-bootstrap-contract.cjs (릴리스 게이트)가 v1 monolith 대신 이 표면을
|
|
6
|
+
* require 한다. 여기서 내보내는 이름/시그니처는 v1 계약 그대로다 — 바꾸면 게이트가
|
|
7
|
+
* 깨진다.
|
|
8
|
+
*/
|
|
9
|
+
const paths = require("./paths.cjs");
|
|
10
|
+
const envFile = require("./env-file.cjs");
|
|
11
|
+
const credentials = require("./credentials.cjs");
|
|
12
|
+
const seed = require("./seed.cjs");
|
|
13
|
+
const state = require("./state.cjs");
|
|
14
|
+
const memoryContext = require("./memory-context.cjs");
|
|
15
|
+
const ontology = require("./ontology.cjs");
|
|
16
|
+
const careerGraph = require("./career-graph.cjs");
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
...paths,
|
|
20
|
+
...envFile,
|
|
21
|
+
...credentials,
|
|
22
|
+
...seed,
|
|
23
|
+
...state,
|
|
24
|
+
...memoryContext,
|
|
25
|
+
...ontology,
|
|
26
|
+
...careerGraph,
|
|
27
|
+
};
|