@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.
Files changed (82) hide show
  1. package/.dockerignore +8 -0
  2. package/Dockerfile +47 -0
  3. package/LICENSE +21 -0
  4. package/README.md +305 -0
  5. package/citio.example.yaml +43 -0
  6. package/dist/adapters/slack.d.ts +22 -0
  7. package/dist/adapters/slack.d.ts.map +1 -0
  8. package/dist/adapters/slack.js +624 -0
  9. package/dist/adapters/slack.js.map +1 -0
  10. package/dist/cli/init.d.ts +3 -0
  11. package/dist/cli/init.d.ts.map +1 -0
  12. package/dist/cli/init.js +1464 -0
  13. package/dist/cli/init.js.map +1 -0
  14. package/dist/cli/ops.d.ts +13 -0
  15. package/dist/cli/ops.d.ts.map +1 -0
  16. package/dist/cli/ops.js +167 -0
  17. package/dist/cli/ops.js.map +1 -0
  18. package/dist/config/schema.d.ts +81 -0
  19. package/dist/config/schema.d.ts.map +1 -0
  20. package/dist/config/schema.js +65 -0
  21. package/dist/config/schema.js.map +1 -0
  22. package/dist/core/agent-runner.d.ts +38 -0
  23. package/dist/core/agent-runner.d.ts.map +1 -0
  24. package/dist/core/agent-runner.js +531 -0
  25. package/dist/core/agent-runner.js.map +1 -0
  26. package/dist/core/mcp-entry.d.ts +7 -0
  27. package/dist/core/mcp-entry.d.ts.map +1 -0
  28. package/dist/core/mcp-entry.js +390 -0
  29. package/dist/core/mcp-entry.js.map +1 -0
  30. package/dist/core/provider-config.d.ts +2 -0
  31. package/dist/core/provider-config.d.ts.map +1 -0
  32. package/dist/core/provider-config.js +53 -0
  33. package/dist/core/provider-config.js.map +1 -0
  34. package/dist/core/session-manager.d.ts +15 -0
  35. package/dist/core/session-manager.d.ts.map +1 -0
  36. package/dist/core/session-manager.js +78 -0
  37. package/dist/core/session-manager.js.map +1 -0
  38. package/dist/core/skills.d.ts +24 -0
  39. package/dist/core/skills.d.ts.map +1 -0
  40. package/dist/core/skills.js +111 -0
  41. package/dist/core/skills.js.map +1 -0
  42. package/dist/core/workspace.d.ts +13 -0
  43. package/dist/core/workspace.d.ts.map +1 -0
  44. package/dist/core/workspace.js +238 -0
  45. package/dist/core/workspace.js.map +1 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +152 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/utils/app-state.d.ts +5 -0
  51. package/dist/utils/app-state.d.ts.map +1 -0
  52. package/dist/utils/app-state.js +35 -0
  53. package/dist/utils/app-state.js.map +1 -0
  54. package/dist/utils/claude.d.ts +4 -0
  55. package/dist/utils/claude.d.ts.map +1 -0
  56. package/dist/utils/claude.js +65 -0
  57. package/dist/utils/claude.js.map +1 -0
  58. package/dist/utils/codex.d.ts +5 -0
  59. package/dist/utils/codex.d.ts.map +1 -0
  60. package/dist/utils/codex.js +17 -0
  61. package/dist/utils/codex.js.map +1 -0
  62. package/dist/utils/env.d.ts +2 -0
  63. package/dist/utils/env.d.ts.map +1 -0
  64. package/dist/utils/env.js +16 -0
  65. package/dist/utils/env.js.map +1 -0
  66. package/dist/utils/installer-state.d.ts +33 -0
  67. package/dist/utils/installer-state.d.ts.map +1 -0
  68. package/dist/utils/installer-state.js +152 -0
  69. package/dist/utils/installer-state.js.map +1 -0
  70. package/dist/utils/runtime-env.d.ts +3 -0
  71. package/dist/utils/runtime-env.d.ts.map +1 -0
  72. package/dist/utils/runtime-env.js +24 -0
  73. package/dist/utils/runtime-env.js.map +1 -0
  74. package/dist/utils/secret-store.d.ts +18 -0
  75. package/dist/utils/secret-store.d.ts.map +1 -0
  76. package/dist/utils/secret-store.js +78 -0
  77. package/dist/utils/secret-store.js.map +1 -0
  78. package/dist/utils/slack-onboarding.d.ts +22 -0
  79. package/dist/utils/slack-onboarding.d.ts.map +1 -0
  80. package/dist/utils/slack-onboarding.js +205 -0
  81. package/dist/utils/slack-onboarding.js.map +1 -0
  82. 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,2 @@
1
+ export declare function resolveEnvVars(obj: unknown): unknown;
2
+ //# sourceMappingURL=env.d.ts.map
@@ -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,3 @@
1
+ export declare function pickDefinedEnv(keys: readonly string[]): Record<string, string>;
2
+ export declare function getTaskRoleEnv(): Record<string, string>;
3
+ //# sourceMappingURL=runtime-env.d.ts.map
@@ -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"}