@lawrencehui/citio 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/.dockerignore +8 -0
- package/Dockerfile +47 -0
- package/LICENSE +21 -0
- package/README.md +305 -0
- package/citio.example.yaml +43 -0
- package/dist/adapters/slack.d.ts +22 -0
- package/dist/adapters/slack.d.ts.map +1 -0
- package/dist/adapters/slack.js +624 -0
- package/dist/adapters/slack.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +1464 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/ops.d.ts +13 -0
- package/dist/cli/ops.d.ts.map +1 -0
- package/dist/cli/ops.js +167 -0
- package/dist/cli/ops.js.map +1 -0
- package/dist/config/schema.d.ts +81 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +65 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/agent-runner.d.ts +38 -0
- package/dist/core/agent-runner.d.ts.map +1 -0
- package/dist/core/agent-runner.js +531 -0
- package/dist/core/agent-runner.js.map +1 -0
- package/dist/core/mcp-entry.d.ts +7 -0
- package/dist/core/mcp-entry.d.ts.map +1 -0
- package/dist/core/mcp-entry.js +390 -0
- package/dist/core/mcp-entry.js.map +1 -0
- package/dist/core/provider-config.d.ts +2 -0
- package/dist/core/provider-config.d.ts.map +1 -0
- package/dist/core/provider-config.js +53 -0
- package/dist/core/provider-config.js.map +1 -0
- package/dist/core/session-manager.d.ts +15 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +78 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/skills.d.ts +24 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +111 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/workspace.d.ts +13 -0
- package/dist/core/workspace.d.ts.map +1 -0
- package/dist/core/workspace.js +238 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +152 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/app-state.d.ts +5 -0
- package/dist/utils/app-state.d.ts.map +1 -0
- package/dist/utils/app-state.js +35 -0
- package/dist/utils/app-state.js.map +1 -0
- package/dist/utils/claude.d.ts +4 -0
- package/dist/utils/claude.d.ts.map +1 -0
- package/dist/utils/claude.js +65 -0
- package/dist/utils/claude.js.map +1 -0
- package/dist/utils/codex.d.ts +5 -0
- package/dist/utils/codex.d.ts.map +1 -0
- package/dist/utils/codex.js +17 -0
- package/dist/utils/codex.js.map +1 -0
- package/dist/utils/env.d.ts +2 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +16 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/installer-state.d.ts +33 -0
- package/dist/utils/installer-state.d.ts.map +1 -0
- package/dist/utils/installer-state.js +152 -0
- package/dist/utils/installer-state.js.map +1 -0
- package/dist/utils/runtime-env.d.ts +3 -0
- package/dist/utils/runtime-env.d.ts.map +1 -0
- package/dist/utils/runtime-env.js +24 -0
- package/dist/utils/runtime-env.js.map +1 -0
- package/dist/utils/secret-store.d.ts +18 -0
- package/dist/utils/secret-store.d.ts.map +1 -0
- package/dist/utils/secret-store.js +78 -0
- package/dist/utils/secret-store.js.map +1 -0
- package/dist/utils/slack-onboarding.d.ts +22 -0
- package/dist/utils/slack-onboarding.d.ts.map +1 -0
- package/dist/utils/slack-onboarding.js +205 -0
- package/dist/utils/slack-onboarding.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { mkdtempSync, rmSync, readFileSync } from "fs";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
const CLAUDE_AUTH_PROMPT = "Reply with exactly OK";
|
|
6
|
+
export function normalizeClaudeOauthToken(token) {
|
|
7
|
+
const compact = token.replace(/\s+/g, "");
|
|
8
|
+
const match = compact.match(/sk-ant-oat01-[A-Za-z0-9_-]+/);
|
|
9
|
+
return match ? match[0] : compact;
|
|
10
|
+
}
|
|
11
|
+
function stripAnsi(text) {
|
|
12
|
+
return text
|
|
13
|
+
.replace(/\u001B\[[0-9;?]*[ -/]*[@-~]/g, "")
|
|
14
|
+
.replace(/\u001B[@-_]/g, "")
|
|
15
|
+
.replace(/\r/g, "\n");
|
|
16
|
+
}
|
|
17
|
+
export function extractClaudeOauthTokenFromTranscript(transcriptPath) {
|
|
18
|
+
const raw = readFileSync(transcriptPath, "utf-8");
|
|
19
|
+
const cleaned = stripAnsi(raw);
|
|
20
|
+
const startMarker = "Your OAuth token";
|
|
21
|
+
const endMarker = "Store this token securely";
|
|
22
|
+
const startIndex = cleaned.indexOf(startMarker);
|
|
23
|
+
if (startIndex === -1) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const afterStart = cleaned.slice(startIndex);
|
|
27
|
+
const endIndex = afterStart.indexOf(endMarker);
|
|
28
|
+
const tokenBlock = endIndex === -1 ? afterStart : afterStart.slice(0, endIndex);
|
|
29
|
+
const lines = tokenBlock
|
|
30
|
+
.split("\n")
|
|
31
|
+
.map((line) => line.trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
const tokenLines = lines.filter((line) => line.includes("sk-ant-oat01-") || /^[A-Za-z0-9_-]+$/.test(line));
|
|
34
|
+
if (tokenLines.length === 0) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const candidate = normalizeClaudeOauthToken(tokenLines.join(""));
|
|
38
|
+
return candidate.startsWith("sk-ant-oat01-") ? candidate : null;
|
|
39
|
+
}
|
|
40
|
+
export function validateClaudeOauthToken(token) {
|
|
41
|
+
const normalizedToken = normalizeClaudeOauthToken(token);
|
|
42
|
+
const tempHome = mkdtempSync(path.join(os.tmpdir(), "citio-claude-token-"));
|
|
43
|
+
try {
|
|
44
|
+
const output = execFileSync("claude", ["-p", "--output-format", "text", CLAUDE_AUTH_PROMPT], {
|
|
45
|
+
encoding: "utf-8",
|
|
46
|
+
env: {
|
|
47
|
+
HOME: tempHome,
|
|
48
|
+
PATH: process.env.PATH || "/usr/local/bin:/usr/bin:/bin",
|
|
49
|
+
TERM: process.env.TERM || "xterm-256color",
|
|
50
|
+
NODE_ENV: process.env.NODE_ENV || "production",
|
|
51
|
+
CLAUDE_CODE_OAUTH_TOKEN: normalizedToken,
|
|
52
|
+
},
|
|
53
|
+
timeout: 120000,
|
|
54
|
+
maxBuffer: 1024 * 1024,
|
|
55
|
+
}).trim();
|
|
56
|
+
return output === "OK";
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
rmSync(tempHome, { recursive: true, force: true });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/utils/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function getCodexAuthPath(home?: string): string;
|
|
2
|
+
export declare function hasCodexCredentials(env?: NodeJS.ProcessEnv): boolean;
|
|
3
|
+
export declare function formatCodexAuthHint(home?: string): string;
|
|
4
|
+
export declare function isLikelyCodexAuthError(text: string): boolean;
|
|
5
|
+
//# sourceMappingURL=codex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/utils/codex.ts"],"names":[],"mappings":"AAEA,wBAAgB,gBAAgB,CAAC,IAAI,SAAoC,GAAG,MAAM,CAEjF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAMjF;AAED,wBAAgB,mBAAmB,CAAC,IAAI,SAAoC,GAAG,MAAM,CAEpF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
export function getCodexAuthPath(home = process.env.HOME || "/home/citio") {
|
|
3
|
+
return `${home}/.codex/auth.json`;
|
|
4
|
+
}
|
|
5
|
+
export function hasCodexCredentials(env = process.env) {
|
|
6
|
+
if (env.OPENAI_API_KEY) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
return existsSync(getCodexAuthPath(env.HOME || "/home/citio"));
|
|
10
|
+
}
|
|
11
|
+
export function formatCodexAuthHint(home = process.env.HOME || "/home/citio") {
|
|
12
|
+
return `Codex credentials not found. Expected OAuth credentials at ${getCodexAuthPath(home)} or OPENAI_API_KEY in the container environment.`;
|
|
13
|
+
}
|
|
14
|
+
export function isLikelyCodexAuthError(text) {
|
|
15
|
+
return /auth|login|logged in|token|OPENAI_API_KEY|credential/i.test(text);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/utils/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,MAAM,UAAU,gBAAgB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,aAAa;IACvE,OAAO,GAAG,IAAI,mBAAmB,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,IAAI,aAAa,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,aAAa;IAC1E,OAAO,8DAA8D,gBAAgB,CAAC,IAAI,CAAC,kDAAkD,CAAC;AAChJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,uDAAuD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAapD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function resolveEnvVars(obj) {
|
|
2
|
+
if (typeof obj === "string") {
|
|
3
|
+
return obj.replace(/\$\{(\w+)\}/g, (_, key) => process.env[key] || "");
|
|
4
|
+
}
|
|
5
|
+
if (Array.isArray(obj))
|
|
6
|
+
return obj.map(resolveEnvVars);
|
|
7
|
+
if (obj && typeof obj === "object") {
|
|
8
|
+
const result = {};
|
|
9
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
10
|
+
result[key] = resolveEnvVars(value);
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
return obj;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACvD,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type InstallerSecrets, type SecretStore } from "./secret-store.js";
|
|
2
|
+
export interface SavedInstallerState {
|
|
3
|
+
provider?: "codex" | "claude";
|
|
4
|
+
authMethod?: "oauth" | "api_key";
|
|
5
|
+
slackBotToken?: string;
|
|
6
|
+
slackAppToken?: string;
|
|
7
|
+
slackChannelId?: string;
|
|
8
|
+
githubToken?: string;
|
|
9
|
+
repos: Array<{
|
|
10
|
+
url: string;
|
|
11
|
+
branch: string;
|
|
12
|
+
}>;
|
|
13
|
+
rules: string[];
|
|
14
|
+
skills: string[];
|
|
15
|
+
gitUserEmail?: string;
|
|
16
|
+
awsRegion?: string;
|
|
17
|
+
awsProfile?: string;
|
|
18
|
+
enableEfs?: boolean;
|
|
19
|
+
claudeOauthToken?: string;
|
|
20
|
+
openAiApiKey?: string;
|
|
21
|
+
anthropicApiKey?: string;
|
|
22
|
+
secretBackend: "keychain" | "file";
|
|
23
|
+
}
|
|
24
|
+
interface InstallerStateOptions {
|
|
25
|
+
statePath?: string;
|
|
26
|
+
localYamlPath?: string;
|
|
27
|
+
localEnvPath?: string;
|
|
28
|
+
secretStore?: SecretStore;
|
|
29
|
+
}
|
|
30
|
+
export declare function loadSavedInstallerState(cwd: string, options?: InstallerStateOptions): Promise<SavedInstallerState>;
|
|
31
|
+
export declare function saveInstallerState(state: Omit<SavedInstallerState, "secretBackend" | keyof InstallerSecrets>, secrets: InstallerSecrets, options?: InstallerStateOptions): Promise<"keychain" | "file">;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=installer-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer-state.d.ts","sourceRoot":"","sources":["../../src/utils/installer-state.ts"],"names":[],"mappings":"AAKA,OAAO,EAA8C,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAExH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,UAAU,GAAG,MAAM,CAAC;CACpC;AAED,UAAU,qBAAqB;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAuGD,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAgC5H;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,GAAG,MAAM,gBAAgB,CAAC,EAC1E,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,CAuB9B"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, chmodSync } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { parse as parseDotenv } from "dotenv";
|
|
4
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
5
|
+
import { getInstallerStatePath } from "./app-state.js";
|
|
6
|
+
import { loadInstallerSecrets, saveInstallerSecrets } from "./secret-store.js";
|
|
7
|
+
function asString(value) {
|
|
8
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
9
|
+
}
|
|
10
|
+
function asBoolean(value) {
|
|
11
|
+
return typeof value === "boolean" ? value : undefined;
|
|
12
|
+
}
|
|
13
|
+
function asStringArray(value) {
|
|
14
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
15
|
+
}
|
|
16
|
+
function asRepoArray(value) {
|
|
17
|
+
if (!Array.isArray(value)) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return value.flatMap((item) => {
|
|
21
|
+
if (!item || typeof item !== "object") {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const repo = item;
|
|
25
|
+
const url = asString(repo.url);
|
|
26
|
+
if (!url) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
return [{
|
|
30
|
+
url,
|
|
31
|
+
branch: asString(repo.branch) || "main",
|
|
32
|
+
}];
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function loadYamlState(filePath) {
|
|
36
|
+
if (!existsSync(filePath)) {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const parsed = parseYaml(readFileSync(filePath, "utf-8"));
|
|
41
|
+
const slack = parsed?.slack;
|
|
42
|
+
const engine = parsed?.engine;
|
|
43
|
+
const workspace = parsed?.workspace;
|
|
44
|
+
const skills = parsed?.skills;
|
|
45
|
+
const deploy = parsed?.deploy;
|
|
46
|
+
const aws = deploy?.aws;
|
|
47
|
+
const git = workspace?.git;
|
|
48
|
+
const repos = asRepoArray(parsed?.repos);
|
|
49
|
+
const workspaceRepos = asRepoArray(workspace?.repos);
|
|
50
|
+
const rules = asStringArray(parsed?.rules);
|
|
51
|
+
const workspaceRules = asStringArray(workspace?.rules);
|
|
52
|
+
const installedSkills = asStringArray(parsed?.skills);
|
|
53
|
+
const configSkills = asStringArray(skills?.installed);
|
|
54
|
+
return {
|
|
55
|
+
provider: parsed?.provider === "codex" || parsed?.provider === "claude"
|
|
56
|
+
? parsed.provider
|
|
57
|
+
: engine?.default_provider === "codex" || engine?.default_provider === "claude"
|
|
58
|
+
? engine.default_provider
|
|
59
|
+
: undefined,
|
|
60
|
+
authMethod: parsed?.authMethod === "oauth" || parsed?.authMethod === "api_key"
|
|
61
|
+
? parsed.authMethod
|
|
62
|
+
: engine?.auth_method === "oauth" || engine?.auth_method === "api_key"
|
|
63
|
+
? engine.auth_method
|
|
64
|
+
: undefined,
|
|
65
|
+
slackChannelId: asString(parsed?.slackChannelId) || asString(slack?.channel_id),
|
|
66
|
+
repos: repos.length > 0 ? repos : workspaceRepos,
|
|
67
|
+
rules: rules.length > 0 ? rules : workspaceRules,
|
|
68
|
+
skills: installedSkills.length > 0 ? installedSkills : configSkills,
|
|
69
|
+
gitUserEmail: asString(parsed?.gitUserEmail) || asString(git?.user_email),
|
|
70
|
+
awsRegion: asString(parsed?.awsRegion) || asString(aws?.region),
|
|
71
|
+
awsProfile: asString(parsed?.awsProfile) || asString(aws?.profile),
|
|
72
|
+
enableEfs: asBoolean(parsed?.enableEfs) ?? asBoolean(aws?.enable_efs),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function loadLocalEnvSecrets(envPath) {
|
|
80
|
+
if (!existsSync(envPath)) {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const parsed = parseDotenv(readFileSync(envPath, "utf-8"));
|
|
85
|
+
return {
|
|
86
|
+
slackBotToken: asString(parsed.SLACK_BOT_TOKEN),
|
|
87
|
+
slackAppToken: asString(parsed.SLACK_APP_TOKEN),
|
|
88
|
+
githubToken: asString(parsed.GH_TOKEN),
|
|
89
|
+
claudeOauthToken: asString(parsed.CLAUDE_CODE_OAUTH_TOKEN),
|
|
90
|
+
openAiApiKey: asString(parsed.OPENAI_API_KEY),
|
|
91
|
+
anthropicApiKey: asString(parsed.ANTHROPIC_API_KEY),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export async function loadSavedInstallerState(cwd, options = {}) {
|
|
99
|
+
const statePath = options.statePath || getInstallerStatePath();
|
|
100
|
+
const localYamlPath = options.localYamlPath || path.join(cwd, "citio.yaml");
|
|
101
|
+
const localEnvPath = options.localEnvPath || path.join(cwd, ".env");
|
|
102
|
+
const secretStore = options.secretStore || {
|
|
103
|
+
loadInstallerSecrets,
|
|
104
|
+
saveInstallerSecrets,
|
|
105
|
+
};
|
|
106
|
+
const stateFromAppDir = loadYamlState(statePath);
|
|
107
|
+
const localYamlFallback = loadYamlState(localYamlPath);
|
|
108
|
+
const { secrets, backend } = await secretStore.loadInstallerSecrets();
|
|
109
|
+
const localEnvFallback = loadLocalEnvSecrets(localEnvPath);
|
|
110
|
+
return {
|
|
111
|
+
provider: stateFromAppDir.provider || localYamlFallback.provider,
|
|
112
|
+
authMethod: stateFromAppDir.authMethod || localYamlFallback.authMethod,
|
|
113
|
+
slackChannelId: stateFromAppDir.slackChannelId || localYamlFallback.slackChannelId,
|
|
114
|
+
repos: stateFromAppDir.repos?.length ? stateFromAppDir.repos : (localYamlFallback.repos || []),
|
|
115
|
+
rules: stateFromAppDir.rules?.length ? stateFromAppDir.rules : (localYamlFallback.rules || []),
|
|
116
|
+
skills: stateFromAppDir.skills?.length ? stateFromAppDir.skills : (localYamlFallback.skills || []),
|
|
117
|
+
gitUserEmail: stateFromAppDir.gitUserEmail || localYamlFallback.gitUserEmail,
|
|
118
|
+
awsRegion: stateFromAppDir.awsRegion || localYamlFallback.awsRegion,
|
|
119
|
+
awsProfile: stateFromAppDir.awsProfile || localYamlFallback.awsProfile,
|
|
120
|
+
enableEfs: stateFromAppDir.enableEfs ?? localYamlFallback.enableEfs,
|
|
121
|
+
slackBotToken: secrets.slackBotToken || localEnvFallback.slackBotToken,
|
|
122
|
+
slackAppToken: secrets.slackAppToken || localEnvFallback.slackAppToken,
|
|
123
|
+
githubToken: secrets.githubToken || localEnvFallback.githubToken,
|
|
124
|
+
claudeOauthToken: secrets.claudeOauthToken || localEnvFallback.claudeOauthToken,
|
|
125
|
+
openAiApiKey: secrets.openAiApiKey || localEnvFallback.openAiApiKey,
|
|
126
|
+
anthropicApiKey: secrets.anthropicApiKey || localEnvFallback.anthropicApiKey,
|
|
127
|
+
secretBackend: backend,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export async function saveInstallerState(state, secrets, options = {}) {
|
|
131
|
+
const statePath = options.statePath || getInstallerStatePath();
|
|
132
|
+
const secretStore = options.secretStore || {
|
|
133
|
+
loadInstallerSecrets,
|
|
134
|
+
saveInstallerSecrets,
|
|
135
|
+
};
|
|
136
|
+
const yaml = stringifyYaml({
|
|
137
|
+
provider: state.provider,
|
|
138
|
+
authMethod: state.authMethod,
|
|
139
|
+
slackChannelId: state.slackChannelId,
|
|
140
|
+
repos: state.repos,
|
|
141
|
+
rules: state.rules,
|
|
142
|
+
skills: state.skills,
|
|
143
|
+
gitUserEmail: state.gitUserEmail,
|
|
144
|
+
awsRegion: state.awsRegion,
|
|
145
|
+
awsProfile: state.awsProfile,
|
|
146
|
+
enableEfs: state.enableEfs,
|
|
147
|
+
});
|
|
148
|
+
writeFileSync(statePath, yaml, "utf-8");
|
|
149
|
+
chmodSync(statePath, 0o600);
|
|
150
|
+
return secretStore.saveInstallerSecrets(secrets);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=installer-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer-state.js","sourceRoot":"","sources":["../../src/utils/installer-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-env.d.ts","sourceRoot":"","sources":["../../src/utils/runtime-env.ts"],"names":[],"mappings":"AAWA,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW9E;AAED,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEvD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const TASK_ROLE_ENV_KEYS = [
|
|
2
|
+
"AWS_DEFAULT_REGION",
|
|
3
|
+
"AWS_REGION",
|
|
4
|
+
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
|
|
5
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
|
|
6
|
+
"AWS_CONTAINER_AUTHORIZATION_TOKEN",
|
|
7
|
+
"AWS_ACCESS_KEY_ID",
|
|
8
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
9
|
+
"AWS_SESSION_TOKEN",
|
|
10
|
+
];
|
|
11
|
+
export function pickDefinedEnv(keys) {
|
|
12
|
+
const picked = {};
|
|
13
|
+
for (const key of keys) {
|
|
14
|
+
const value = process.env[key];
|
|
15
|
+
if (value) {
|
|
16
|
+
picked[key] = value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return picked;
|
|
20
|
+
}
|
|
21
|
+
export function getTaskRoleEnv() {
|
|
22
|
+
return pickDefinedEnv(TASK_ROLE_ENV_KEYS);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=runtime-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-env.js","sourceRoot":"","sources":["../../src/utils/runtime-env.ts"],"names":[],"mappings":"AAAA,MAAM,kBAAkB,GAAG;IACzB,oBAAoB;IACpB,YAAY;IACZ,wCAAwC;IACxC,oCAAoC;IACpC,mCAAmC;IACnC,mBAAmB;IACnB,uBAAuB;IACvB,mBAAmB;CACX,CAAC;AAEX,MAAM,UAAU,cAAc,CAAC,IAAuB;IACpD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,cAAc,CAAC,kBAAkB,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface InstallerSecrets {
|
|
2
|
+
slackBotToken?: string;
|
|
3
|
+
slackAppToken?: string;
|
|
4
|
+
githubToken?: string;
|
|
5
|
+
claudeOauthToken?: string;
|
|
6
|
+
openAiApiKey?: string;
|
|
7
|
+
anthropicApiKey?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadInstallerSecrets(): Promise<{
|
|
10
|
+
secrets: InstallerSecrets;
|
|
11
|
+
backend: "keychain" | "file";
|
|
12
|
+
}>;
|
|
13
|
+
export declare function saveInstallerSecrets(secrets: InstallerSecrets): Promise<"keychain" | "file">;
|
|
14
|
+
export interface SecretStore {
|
|
15
|
+
loadInstallerSecrets: typeof loadInstallerSecrets;
|
|
16
|
+
saveInstallerSecrets: typeof saveInstallerSecrets;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=secret-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.d.ts","sourceRoot":"","sources":["../../src/utils/secret-store.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAwDD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAAA;CAAE,CAAC,CAcjH;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,CAiBlG;AAED,MAAM,WAAW,WAAW;IAC1B,oBAAoB,EAAE,OAAO,oBAAoB,CAAC;IAClD,oBAAoB,EAAE,OAAO,oBAAoB,CAAC;CACnD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { chmodSync, existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { getFallbackSecretsPath } from "./app-state.js";
|
|
3
|
+
const SERVICE_NAME = "citio";
|
|
4
|
+
const SECRET_KEYS = [
|
|
5
|
+
"slackBotToken",
|
|
6
|
+
"slackAppToken",
|
|
7
|
+
"githubToken",
|
|
8
|
+
"claudeOauthToken",
|
|
9
|
+
"openAiApiKey",
|
|
10
|
+
"anthropicApiKey",
|
|
11
|
+
];
|
|
12
|
+
const SECRET_ACCOUNT_NAMES = {
|
|
13
|
+
slackBotToken: "slack_bot_token",
|
|
14
|
+
slackAppToken: "slack_app_token",
|
|
15
|
+
githubToken: "github_token",
|
|
16
|
+
claudeOauthToken: "claude_oauth_token",
|
|
17
|
+
openAiApiKey: "openai_api_key",
|
|
18
|
+
anthropicApiKey: "anthropic_api_key",
|
|
19
|
+
};
|
|
20
|
+
async function loadKeytar() {
|
|
21
|
+
try {
|
|
22
|
+
const module = await import("keytar");
|
|
23
|
+
return module.default ?? module;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function loadFallbackSecrets() {
|
|
30
|
+
const secretsPath = getFallbackSecretsPath();
|
|
31
|
+
if (!existsSync(secretsPath)) {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(readFileSync(secretsPath, "utf-8"));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function persistFallbackSecrets(secrets) {
|
|
42
|
+
const secretsPath = getFallbackSecretsPath();
|
|
43
|
+
writeFileSync(secretsPath, JSON.stringify(secrets, null, 2), "utf-8");
|
|
44
|
+
chmodSync(secretsPath, 0o600);
|
|
45
|
+
}
|
|
46
|
+
export async function loadInstallerSecrets() {
|
|
47
|
+
const keytar = await loadKeytar();
|
|
48
|
+
if (keytar) {
|
|
49
|
+
const secrets = {};
|
|
50
|
+
for (const key of SECRET_KEYS) {
|
|
51
|
+
const value = await keytar.getPassword(SERVICE_NAME, SECRET_ACCOUNT_NAMES[key]);
|
|
52
|
+
if (value) {
|
|
53
|
+
secrets[key] = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { secrets, backend: "keychain" };
|
|
57
|
+
}
|
|
58
|
+
return { secrets: loadFallbackSecrets(), backend: "file" };
|
|
59
|
+
}
|
|
60
|
+
export async function saveInstallerSecrets(secrets) {
|
|
61
|
+
const keytar = await loadKeytar();
|
|
62
|
+
if (keytar) {
|
|
63
|
+
for (const key of SECRET_KEYS) {
|
|
64
|
+
const value = secrets[key];
|
|
65
|
+
const account = SECRET_ACCOUNT_NAMES[key];
|
|
66
|
+
if (value) {
|
|
67
|
+
await keytar.setPassword(SERVICE_NAME, account, value);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
await keytar.deletePassword(SERVICE_NAME, account);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return "keychain";
|
|
74
|
+
}
|
|
75
|
+
persistFallbackSecrets(secrets);
|
|
76
|
+
return "file";
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=secret-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../../src/utils/secret-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface SlackManifestCreateResult {
|
|
2
|
+
appId: string;
|
|
3
|
+
oauthAuthorizeUrl: string;
|
|
4
|
+
settingsUrl: string;
|
|
5
|
+
}
|
|
6
|
+
interface SlackManifestOptions {
|
|
7
|
+
appName?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildCitioSlackManifest(options?: SlackManifestOptions): Record<string, unknown>;
|
|
10
|
+
export declare function createCitioSlackApp(configToken: string, options?: SlackManifestOptions): Promise<SlackManifestCreateResult>;
|
|
11
|
+
export declare function openBrowser(url: string): boolean;
|
|
12
|
+
export declare function validateSlackBotToken(token: string | undefined): string | Error | undefined;
|
|
13
|
+
export declare function validateSlackAppToken(token: string | undefined): string | Error | undefined;
|
|
14
|
+
export declare function validateSlackConfigToken(token: string | undefined): string | Error | undefined;
|
|
15
|
+
/** Live-check a saved bot token via auth.test. Returns workspace/bot identity when valid. */
|
|
16
|
+
export declare function testSlackBotToken(token: string): Promise<{
|
|
17
|
+
ok: boolean;
|
|
18
|
+
team?: string;
|
|
19
|
+
botUser?: string;
|
|
20
|
+
}>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=slack-onboarding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-onboarding.d.ts","sourceRoot":"","sources":["../../src/utils/slack-onboarding.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0EnG;AAsDD,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAyBrI;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAgBhD;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAQ3F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAQ3F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAQ9F;AAED,6FAA6F;AAC7F,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAWhH"}
|