edge-pi-cli 0.1.1

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 (117) hide show
  1. package/dist/auth/anthropic-oauth.d.ts +10 -0
  2. package/dist/auth/anthropic-oauth.d.ts.map +1 -0
  3. package/dist/auth/anthropic-oauth.js +97 -0
  4. package/dist/auth/anthropic-oauth.js.map +1 -0
  5. package/dist/auth/auth-storage.d.ts +46 -0
  6. package/dist/auth/auth-storage.d.ts.map +1 -0
  7. package/dist/auth/auth-storage.js +213 -0
  8. package/dist/auth/auth-storage.js.map +1 -0
  9. package/dist/auth/github-copilot-oauth.d.ts +8 -0
  10. package/dist/auth/github-copilot-oauth.d.ts.map +1 -0
  11. package/dist/auth/github-copilot-oauth.js +131 -0
  12. package/dist/auth/github-copilot-oauth.js.map +1 -0
  13. package/dist/auth/index.d.ts +6 -0
  14. package/dist/auth/index.d.ts.map +1 -0
  15. package/dist/auth/index.js +5 -0
  16. package/dist/auth/index.js.map +1 -0
  17. package/dist/auth/openai-codex-oauth.d.ts +8 -0
  18. package/dist/auth/openai-codex-oauth.d.ts.map +1 -0
  19. package/dist/auth/openai-codex-oauth.js +131 -0
  20. package/dist/auth/openai-codex-oauth.js.map +1 -0
  21. package/dist/auth/types.d.ts +41 -0
  22. package/dist/auth/types.d.ts.map +1 -0
  23. package/dist/auth/types.js +5 -0
  24. package/dist/auth/types.js.map +1 -0
  25. package/dist/cli/args.d.ts +35 -0
  26. package/dist/cli/args.d.ts.map +1 -0
  27. package/dist/cli/args.js +191 -0
  28. package/dist/cli/args.js.map +1 -0
  29. package/dist/cli.d.ts +3 -0
  30. package/dist/cli.d.ts.map +1 -0
  31. package/dist/cli.js +8 -0
  32. package/dist/cli.js.map +1 -0
  33. package/dist/context.d.ts +16 -0
  34. package/dist/context.d.ts.map +1 -0
  35. package/dist/context.js +38 -0
  36. package/dist/context.js.map +1 -0
  37. package/dist/main.d.ts +8 -0
  38. package/dist/main.d.ts.map +1 -0
  39. package/dist/main.js +313 -0
  40. package/dist/main.js.map +1 -0
  41. package/dist/model-factory.d.ts +45 -0
  42. package/dist/model-factory.d.ts.map +1 -0
  43. package/dist/model-factory.js +175 -0
  44. package/dist/model-factory.js.map +1 -0
  45. package/dist/modes/interactive/bash-helpers.d.ts +31 -0
  46. package/dist/modes/interactive/bash-helpers.d.ts.map +1 -0
  47. package/dist/modes/interactive/bash-helpers.js +68 -0
  48. package/dist/modes/interactive/bash-helpers.js.map +1 -0
  49. package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
  50. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  51. package/dist/modes/interactive/components/assistant-message.js +54 -0
  52. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  53. package/dist/modes/interactive/components/bash-execution.d.ts +18 -0
  54. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  55. package/dist/modes/interactive/components/bash-execution.js +77 -0
  56. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  57. package/dist/modes/interactive/components/compaction-summary.d.ts +18 -0
  58. package/dist/modes/interactive/components/compaction-summary.d.ts.map +1 -0
  59. package/dist/modes/interactive/components/compaction-summary.js +45 -0
  60. package/dist/modes/interactive/components/compaction-summary.js.map +1 -0
  61. package/dist/modes/interactive/components/footer.d.ts +20 -0
  62. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  63. package/dist/modes/interactive/components/footer.js +82 -0
  64. package/dist/modes/interactive/components/footer.js.map +1 -0
  65. package/dist/modes/interactive/components/tool-execution.d.ts +30 -0
  66. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  67. package/dist/modes/interactive/components/tool-execution.js +133 -0
  68. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  69. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  70. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  71. package/dist/modes/interactive/components/user-message.js +17 -0
  72. package/dist/modes/interactive/components/user-message.js.map +1 -0
  73. package/dist/modes/interactive/interactive-mode.d.ts +49 -0
  74. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  75. package/dist/modes/interactive/interactive-mode.js +1397 -0
  76. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  77. package/dist/modes/interactive/theme.d.ts +26 -0
  78. package/dist/modes/interactive/theme.d.ts.map +1 -0
  79. package/dist/modes/interactive/theme.js +64 -0
  80. package/dist/modes/interactive/theme.js.map +1 -0
  81. package/dist/modes/interactive-mode.d.ts +5 -0
  82. package/dist/modes/interactive-mode.d.ts.map +1 -0
  83. package/dist/modes/interactive-mode.js +5 -0
  84. package/dist/modes/interactive-mode.js.map +1 -0
  85. package/dist/modes/print-mode.d.ts +20 -0
  86. package/dist/modes/print-mode.d.ts.map +1 -0
  87. package/dist/modes/print-mode.js +56 -0
  88. package/dist/modes/print-mode.js.map +1 -0
  89. package/dist/prompts.d.ts +53 -0
  90. package/dist/prompts.d.ts.map +1 -0
  91. package/dist/prompts.js +132 -0
  92. package/dist/prompts.js.map +1 -0
  93. package/dist/settings.d.ts +34 -0
  94. package/dist/settings.d.ts.map +1 -0
  95. package/dist/settings.js +73 -0
  96. package/dist/settings.js.map +1 -0
  97. package/dist/skills.d.ts +51 -0
  98. package/dist/skills.d.ts.map +1 -0
  99. package/dist/skills.js +304 -0
  100. package/dist/skills.js.map +1 -0
  101. package/dist/utils/bash-executor.d.ts +32 -0
  102. package/dist/utils/bash-executor.d.ts.map +1 -0
  103. package/dist/utils/bash-executor.js +166 -0
  104. package/dist/utils/bash-executor.js.map +1 -0
  105. package/dist/utils/clipboard-image.d.ts +24 -0
  106. package/dist/utils/clipboard-image.d.ts.map +1 -0
  107. package/dist/utils/clipboard-image.js +211 -0
  108. package/dist/utils/clipboard-image.js.map +1 -0
  109. package/dist/utils/find-fd.d.ts +12 -0
  110. package/dist/utils/find-fd.d.ts.map +1 -0
  111. package/dist/utils/find-fd.js +33 -0
  112. package/dist/utils/find-fd.js.map +1 -0
  113. package/dist/utils/frontmatter.d.ts +7 -0
  114. package/dist/utils/frontmatter.d.ts.map +1 -0
  115. package/dist/utils/frontmatter.js +25 -0
  116. package/dist/utils/frontmatter.js.map +1 -0
  117. package/package.json +39 -0
@@ -0,0 +1,5 @@
1
+ export { anthropicOAuthProvider, isAnthropicOAuthToken } from "./anthropic-oauth.js";
2
+ export { AuthStorage } from "./auth-storage.js";
3
+ export { githubCopilotOAuthProvider } from "./github-copilot-oauth.js";
4
+ export { openaiCodexOAuthProvider } from "./openai-codex-oauth.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC","sourcesContent":["export { anthropicOAuthProvider, isAnthropicOAuthToken } from \"./anthropic-oauth.js\";\nexport { AuthStorage } from \"./auth-storage.js\";\nexport { githubCopilotOAuthProvider } from \"./github-copilot-oauth.js\";\nexport { openaiCodexOAuthProvider } from \"./openai-codex-oauth.js\";\nexport type {\n\tApiKeyCredential,\n\tAuthCredential,\n\tAuthStorageData,\n\tOAuthCredentials,\n\tOAuthLoginCallbacks,\n\tOAuthProviderInterface,\n} from \"./types.js\";\n"]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * OpenAI Codex OAuth provider implementation.
3
+ * Uses the OpenAI Device Code flow for ChatGPT subscription authentication.
4
+ */
5
+ import type { OAuthProviderInterface } from "./types.js";
6
+ /** The built-in OpenAI Codex OAuth provider. */
7
+ export declare const openaiCodexOAuthProvider: OAuthProviderInterface;
8
+ //# sourceMappingURL=openai-codex-oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-codex-oauth.d.ts","sourceRoot":"","sources":["../../src/auth/openai-codex-oauth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAyC,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAoKhG,gDAAgD;AAChD,eAAO,MAAM,wBAAwB,EAAE,sBAMtC,CAAC","sourcesContent":["/**\n * OpenAI Codex OAuth provider implementation.\n * Uses the OpenAI Device Code flow for ChatGPT subscription authentication.\n */\n\nimport type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from \"./types.js\";\n\nconst CLIENT_ID = \"app_EMoamEEZ73f0CkXaXp7hrann\";\nconst ISSUER = \"https://auth.openai.com\";\nconst USERCODE_URL = `${ISSUER}/api/accounts/deviceauth/usercode`;\nconst DEVICE_TOKEN_URL = `${ISSUER}/api/accounts/deviceauth/token`;\nconst TOKEN_URL = `${ISSUER}/oauth/token`;\nconst VERIFICATION_URL = `${ISSUER}/codex/device`;\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(new Error(\"Login cancelled\"));\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(resolve, ms);\n\t\tsignal?.addEventListener(\n\t\t\t\"abort\",\n\t\t\t() => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(new Error(\"Login cancelled\"));\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n\nasync function loginOpenAICodex(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n\t// Step 1: Request device code\n\tconst userCodeResponse = await fetch(USERCODE_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({ client_id: CLIENT_ID }),\n\t});\n\n\tif (!userCodeResponse.ok) {\n\t\tthrow new Error(`Device code request failed: ${await userCodeResponse.text()}`);\n\t}\n\n\tconst userCodeData = (await userCodeResponse.json()) as {\n\t\tdevice_auth_id: string;\n\t\tuser_code: string;\n\t\tinterval: string | number;\n\t};\n\n\tconst interval = (Number(userCodeData.interval) || 5) * 1000;\n\n\t// Step 2: Show verification URL and user code\n\tcallbacks.onAuth({\n\t\turl: VERIFICATION_URL,\n\t\tinstructions: `Enter code: ${userCodeData.user_code}`,\n\t});\n\n\tcallbacks.onProgress?.(\"Waiting for browser authentication...\");\n\n\t// Step 3: Poll for authorization code\n\tconst maxWait = 15 * 60 * 1000;\n\tconst expiresAt = Date.now() + maxWait;\n\tlet authorizationCode: string | undefined;\n\tlet codeVerifier: string | undefined;\n\n\twhile (Date.now() < expiresAt) {\n\t\tawait sleep(interval, callbacks.signal);\n\n\t\tconst pollResponse = await fetch(DEVICE_TOKEN_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tdevice_auth_id: userCodeData.device_auth_id,\n\t\t\t\tuser_code: userCodeData.user_code,\n\t\t\t}),\n\t\t});\n\n\t\tif (pollResponse.ok) {\n\t\t\tconst data = (await pollResponse.json()) as {\n\t\t\t\tauthorization_code: string;\n\t\t\t\tcode_challenge: string;\n\t\t\t\tcode_verifier: string;\n\t\t\t};\n\t\t\tauthorizationCode = data.authorization_code;\n\t\t\tcodeVerifier = data.code_verifier;\n\t\t\tbreak;\n\t\t}\n\n\t\t// 403/404 = authorization pending, keep polling\n\t\tif (pollResponse.status === 403 || pollResponse.status === 404) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tthrow new Error(`Device auth failed with status ${pollResponse.status}`);\n\t}\n\n\tif (!authorizationCode || !codeVerifier) {\n\t\tthrow new Error(\"Device code expired. Please try again.\");\n\t}\n\n\tcallbacks.onProgress?.(\"Exchanging code for tokens...\");\n\n\t// Step 4: Exchange authorization code for tokens\n\tconst redirectUri = `${ISSUER}/deviceauth/callback`;\n\tconst tokenResponse = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode: authorizationCode,\n\t\t\tredirect_uri: redirectUri,\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tcode_verifier: codeVerifier,\n\t\t}).toString(),\n\t});\n\n\tif (!tokenResponse.ok) {\n\t\tthrow new Error(`Token exchange failed: ${await tokenResponse.text()}`);\n\t}\n\n\tconst tokens = (await tokenResponse.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\tid_token: string;\n\t};\n\n\treturn {\n\t\trefresh: tokens.refresh_token,\n\t\taccess: tokens.access_token,\n\t\texpires: Date.now() + 8 * 24 * 60 * 60 * 1000,\n\t};\n}\n\nasync function refreshOpenAICodexToken(credentials: OAuthCredentials): Promise<OAuthCredentials> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\trefresh_token: credentials.refresh,\n\t\t\tscope: \"openid profile email\",\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Token refresh failed: ${await response.text()}`);\n\t}\n\n\tconst data = (await response.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\tid_token: string;\n\t};\n\n\treturn {\n\t\trefresh: data.refresh_token,\n\t\taccess: data.access_token,\n\t\texpires: Date.now() + 8 * 24 * 60 * 60 * 1000,\n\t};\n}\n\n/** The built-in OpenAI Codex OAuth provider. */\nexport const openaiCodexOAuthProvider: OAuthProviderInterface = {\n\tid: \"openai-codex\",\n\tname: \"OpenAI (ChatGPT Plus/Pro)\",\n\tlogin: loginOpenAICodex,\n\trefreshToken: refreshOpenAICodexToken,\n\tgetApiKey: (cred) => cred.access,\n};\n"]}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * OpenAI Codex OAuth provider implementation.
3
+ * Uses the OpenAI Device Code flow for ChatGPT subscription authentication.
4
+ */
5
+ const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
6
+ const ISSUER = "https://auth.openai.com";
7
+ const USERCODE_URL = `${ISSUER}/api/accounts/deviceauth/usercode`;
8
+ const DEVICE_TOKEN_URL = `${ISSUER}/api/accounts/deviceauth/token`;
9
+ const TOKEN_URL = `${ISSUER}/oauth/token`;
10
+ const VERIFICATION_URL = `${ISSUER}/codex/device`;
11
+ function sleep(ms, signal) {
12
+ return new Promise((resolve, reject) => {
13
+ if (signal?.aborted) {
14
+ reject(new Error("Login cancelled"));
15
+ return;
16
+ }
17
+ const timer = setTimeout(resolve, ms);
18
+ signal?.addEventListener("abort", () => {
19
+ clearTimeout(timer);
20
+ reject(new Error("Login cancelled"));
21
+ }, { once: true });
22
+ });
23
+ }
24
+ async function loginOpenAICodex(callbacks) {
25
+ // Step 1: Request device code
26
+ const userCodeResponse = await fetch(USERCODE_URL, {
27
+ method: "POST",
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ Accept: "application/json",
31
+ },
32
+ body: JSON.stringify({ client_id: CLIENT_ID }),
33
+ });
34
+ if (!userCodeResponse.ok) {
35
+ throw new Error(`Device code request failed: ${await userCodeResponse.text()}`);
36
+ }
37
+ const userCodeData = (await userCodeResponse.json());
38
+ const interval = (Number(userCodeData.interval) || 5) * 1000;
39
+ // Step 2: Show verification URL and user code
40
+ callbacks.onAuth({
41
+ url: VERIFICATION_URL,
42
+ instructions: `Enter code: ${userCodeData.user_code}`,
43
+ });
44
+ callbacks.onProgress?.("Waiting for browser authentication...");
45
+ // Step 3: Poll for authorization code
46
+ const maxWait = 15 * 60 * 1000;
47
+ const expiresAt = Date.now() + maxWait;
48
+ let authorizationCode;
49
+ let codeVerifier;
50
+ while (Date.now() < expiresAt) {
51
+ await sleep(interval, callbacks.signal);
52
+ const pollResponse = await fetch(DEVICE_TOKEN_URL, {
53
+ method: "POST",
54
+ headers: {
55
+ "Content-Type": "application/json",
56
+ Accept: "application/json",
57
+ },
58
+ body: JSON.stringify({
59
+ device_auth_id: userCodeData.device_auth_id,
60
+ user_code: userCodeData.user_code,
61
+ }),
62
+ });
63
+ if (pollResponse.ok) {
64
+ const data = (await pollResponse.json());
65
+ authorizationCode = data.authorization_code;
66
+ codeVerifier = data.code_verifier;
67
+ break;
68
+ }
69
+ // 403/404 = authorization pending, keep polling
70
+ if (pollResponse.status === 403 || pollResponse.status === 404) {
71
+ continue;
72
+ }
73
+ throw new Error(`Device auth failed with status ${pollResponse.status}`);
74
+ }
75
+ if (!authorizationCode || !codeVerifier) {
76
+ throw new Error("Device code expired. Please try again.");
77
+ }
78
+ callbacks.onProgress?.("Exchanging code for tokens...");
79
+ // Step 4: Exchange authorization code for tokens
80
+ const redirectUri = `${ISSUER}/deviceauth/callback`;
81
+ const tokenResponse = await fetch(TOKEN_URL, {
82
+ method: "POST",
83
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
84
+ body: new URLSearchParams({
85
+ grant_type: "authorization_code",
86
+ code: authorizationCode,
87
+ redirect_uri: redirectUri,
88
+ client_id: CLIENT_ID,
89
+ code_verifier: codeVerifier,
90
+ }).toString(),
91
+ });
92
+ if (!tokenResponse.ok) {
93
+ throw new Error(`Token exchange failed: ${await tokenResponse.text()}`);
94
+ }
95
+ const tokens = (await tokenResponse.json());
96
+ return {
97
+ refresh: tokens.refresh_token,
98
+ access: tokens.access_token,
99
+ expires: Date.now() + 8 * 24 * 60 * 60 * 1000,
100
+ };
101
+ }
102
+ async function refreshOpenAICodexToken(credentials) {
103
+ const response = await fetch(TOKEN_URL, {
104
+ method: "POST",
105
+ headers: { "Content-Type": "application/json" },
106
+ body: JSON.stringify({
107
+ client_id: CLIENT_ID,
108
+ grant_type: "refresh_token",
109
+ refresh_token: credentials.refresh,
110
+ scope: "openid profile email",
111
+ }),
112
+ });
113
+ if (!response.ok) {
114
+ throw new Error(`Token refresh failed: ${await response.text()}`);
115
+ }
116
+ const data = (await response.json());
117
+ return {
118
+ refresh: data.refresh_token,
119
+ access: data.access_token,
120
+ expires: Date.now() + 8 * 24 * 60 * 60 * 1000,
121
+ };
122
+ }
123
+ /** The built-in OpenAI Codex OAuth provider. */
124
+ export const openaiCodexOAuthProvider = {
125
+ id: "openai-codex",
126
+ name: "OpenAI (ChatGPT Plus/Pro)",
127
+ login: loginOpenAICodex,
128
+ refreshToken: refreshOpenAICodexToken,
129
+ getApiKey: (cred) => cred.access,
130
+ };
131
+ //# sourceMappingURL=openai-codex-oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-codex-oauth.js","sourceRoot":"","sources":["../../src/auth/openai-codex-oauth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OpenAI Codex OAuth provider implementation.\n * Uses the OpenAI Device Code flow for ChatGPT subscription authentication.\n */\n\nimport type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from \"./types.js\";\n\nconst CLIENT_ID = \"app_EMoamEEZ73f0CkXaXp7hrann\";\nconst ISSUER = \"https://auth.openai.com\";\nconst USERCODE_URL = `${ISSUER}/api/accounts/deviceauth/usercode`;\nconst DEVICE_TOKEN_URL = `${ISSUER}/api/accounts/deviceauth/token`;\nconst TOKEN_URL = `${ISSUER}/oauth/token`;\nconst VERIFICATION_URL = `${ISSUER}/codex/device`;\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(new Error(\"Login cancelled\"));\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(resolve, ms);\n\t\tsignal?.addEventListener(\n\t\t\t\"abort\",\n\t\t\t() => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(new Error(\"Login cancelled\"));\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n\nasync function loginOpenAICodex(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n\t// Step 1: Request device code\n\tconst userCodeResponse = await fetch(USERCODE_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({ client_id: CLIENT_ID }),\n\t});\n\n\tif (!userCodeResponse.ok) {\n\t\tthrow new Error(`Device code request failed: ${await userCodeResponse.text()}`);\n\t}\n\n\tconst userCodeData = (await userCodeResponse.json()) as {\n\t\tdevice_auth_id: string;\n\t\tuser_code: string;\n\t\tinterval: string | number;\n\t};\n\n\tconst interval = (Number(userCodeData.interval) || 5) * 1000;\n\n\t// Step 2: Show verification URL and user code\n\tcallbacks.onAuth({\n\t\turl: VERIFICATION_URL,\n\t\tinstructions: `Enter code: ${userCodeData.user_code}`,\n\t});\n\n\tcallbacks.onProgress?.(\"Waiting for browser authentication...\");\n\n\t// Step 3: Poll for authorization code\n\tconst maxWait = 15 * 60 * 1000;\n\tconst expiresAt = Date.now() + maxWait;\n\tlet authorizationCode: string | undefined;\n\tlet codeVerifier: string | undefined;\n\n\twhile (Date.now() < expiresAt) {\n\t\tawait sleep(interval, callbacks.signal);\n\n\t\tconst pollResponse = await fetch(DEVICE_TOKEN_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tdevice_auth_id: userCodeData.device_auth_id,\n\t\t\t\tuser_code: userCodeData.user_code,\n\t\t\t}),\n\t\t});\n\n\t\tif (pollResponse.ok) {\n\t\t\tconst data = (await pollResponse.json()) as {\n\t\t\t\tauthorization_code: string;\n\t\t\t\tcode_challenge: string;\n\t\t\t\tcode_verifier: string;\n\t\t\t};\n\t\t\tauthorizationCode = data.authorization_code;\n\t\t\tcodeVerifier = data.code_verifier;\n\t\t\tbreak;\n\t\t}\n\n\t\t// 403/404 = authorization pending, keep polling\n\t\tif (pollResponse.status === 403 || pollResponse.status === 404) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tthrow new Error(`Device auth failed with status ${pollResponse.status}`);\n\t}\n\n\tif (!authorizationCode || !codeVerifier) {\n\t\tthrow new Error(\"Device code expired. Please try again.\");\n\t}\n\n\tcallbacks.onProgress?.(\"Exchanging code for tokens...\");\n\n\t// Step 4: Exchange authorization code for tokens\n\tconst redirectUri = `${ISSUER}/deviceauth/callback`;\n\tconst tokenResponse = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\tbody: new URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode: authorizationCode,\n\t\t\tredirect_uri: redirectUri,\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tcode_verifier: codeVerifier,\n\t\t}).toString(),\n\t});\n\n\tif (!tokenResponse.ok) {\n\t\tthrow new Error(`Token exchange failed: ${await tokenResponse.text()}`);\n\t}\n\n\tconst tokens = (await tokenResponse.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\tid_token: string;\n\t};\n\n\treturn {\n\t\trefresh: tokens.refresh_token,\n\t\taccess: tokens.access_token,\n\t\texpires: Date.now() + 8 * 24 * 60 * 60 * 1000,\n\t};\n}\n\nasync function refreshOpenAICodexToken(credentials: OAuthCredentials): Promise<OAuthCredentials> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\trefresh_token: credentials.refresh,\n\t\t\tscope: \"openid profile email\",\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Token refresh failed: ${await response.text()}`);\n\t}\n\n\tconst data = (await response.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\tid_token: string;\n\t};\n\n\treturn {\n\t\trefresh: data.refresh_token,\n\t\taccess: data.access_token,\n\t\texpires: Date.now() + 8 * 24 * 60 * 60 * 1000,\n\t};\n}\n\n/** The built-in OpenAI Codex OAuth provider. */\nexport const openaiCodexOAuthProvider: OAuthProviderInterface = {\n\tid: \"openai-codex\",\n\tname: \"OpenAI (ChatGPT Plus/Pro)\",\n\tlogin: loginOpenAICodex,\n\trefreshToken: refreshOpenAICodexToken,\n\tgetApiKey: (cred) => cred.access,\n};\n"]}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * OAuth types for edge-pi-cli authentication.
3
+ */
4
+ export interface OAuthCredentials {
5
+ refresh: string;
6
+ access: string;
7
+ expires: number;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface OAuthAuthInfo {
11
+ url: string;
12
+ instructions?: string;
13
+ }
14
+ export interface OAuthPrompt {
15
+ message: string;
16
+ placeholder?: string;
17
+ allowEmpty?: boolean;
18
+ }
19
+ export interface OAuthLoginCallbacks {
20
+ onAuth: (info: OAuthAuthInfo) => void;
21
+ onPrompt: (prompt: OAuthPrompt) => Promise<string>;
22
+ onProgress?: (message: string) => void;
23
+ signal?: AbortSignal;
24
+ }
25
+ export interface OAuthProviderInterface {
26
+ readonly id: string;
27
+ readonly name: string;
28
+ login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
29
+ refreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials>;
30
+ getApiKey(credentials: OAuthCredentials): string;
31
+ }
32
+ export type ApiKeyCredential = {
33
+ type: "api_key";
34
+ key: string;
35
+ };
36
+ export type OAuthCredential = {
37
+ type: "oauth";
38
+ } & OAuthCredentials;
39
+ export type AuthCredential = ApiKeyCredential | OAuthCredential;
40
+ export type AuthStorageData = Record<string, AuthCredential>;
41
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjE,YAAY,CAAC,WAAW,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvE,SAAS,CAAC,WAAW,EAAE,gBAAgB,GAAG,MAAM,CAAC;CACjD;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAC;CACd,GAAG,gBAAgB,CAAC;AAErB,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC","sourcesContent":["/**\n * OAuth types for edge-pi-cli authentication.\n */\n\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\nexport interface OAuthAuthInfo {\n\turl: string;\n\tinstructions?: string;\n}\n\nexport interface OAuthPrompt {\n\tmessage: string;\n\tplaceholder?: string;\n\tallowEmpty?: boolean;\n}\n\nexport interface OAuthLoginCallbacks {\n\tonAuth: (info: OAuthAuthInfo) => void;\n\tonPrompt: (prompt: OAuthPrompt) => Promise<string>;\n\tonProgress?: (message: string) => void;\n\tsignal?: AbortSignal;\n}\n\nexport interface OAuthProviderInterface {\n\treadonly id: string;\n\treadonly name: string;\n\tlogin(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;\n\trefreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials>;\n\tgetApiKey(credentials: OAuthCredentials): string;\n}\n\nexport type ApiKeyCredential = {\n\ttype: \"api_key\";\n\tkey: string;\n};\n\nexport type OAuthCredential = {\n\ttype: \"oauth\";\n} & OAuthCredentials;\n\nexport type AuthCredential = ApiKeyCredential | OAuthCredential;\n\nexport type AuthStorageData = Record<string, AuthCredential>;\n"]}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * OAuth types for edge-pi-cli authentication.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;GAEG","sourcesContent":["/**\n * OAuth types for edge-pi-cli authentication.\n */\n\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\nexport interface OAuthAuthInfo {\n\turl: string;\n\tinstructions?: string;\n}\n\nexport interface OAuthPrompt {\n\tmessage: string;\n\tplaceholder?: string;\n\tallowEmpty?: boolean;\n}\n\nexport interface OAuthLoginCallbacks {\n\tonAuth: (info: OAuthAuthInfo) => void;\n\tonPrompt: (prompt: OAuthPrompt) => Promise<string>;\n\tonProgress?: (message: string) => void;\n\tsignal?: AbortSignal;\n}\n\nexport interface OAuthProviderInterface {\n\treadonly id: string;\n\treadonly name: string;\n\tlogin(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;\n\trefreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials>;\n\tgetApiKey(credentials: OAuthCredentials): string;\n}\n\nexport type ApiKeyCredential = {\n\ttype: \"api_key\";\n\tkey: string;\n};\n\nexport type OAuthCredential = {\n\ttype: \"oauth\";\n} & OAuthCredentials;\n\nexport type AuthCredential = ApiKeyCredential | OAuthCredential;\n\nexport type AuthStorageData = Record<string, AuthCredential>;\n"]}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * CLI argument parsing for edge-pi-cli.
3
+ *
4
+ * Simplified from the original CLI - no RPC, no extensions.
5
+ */
6
+ import type { ThinkingLevel } from "edge-pi";
7
+ export type Mode = "text" | "json";
8
+ export interface Args {
9
+ provider?: string;
10
+ model?: string;
11
+ apiKey?: string;
12
+ systemPrompt?: string;
13
+ appendSystemPrompt?: string;
14
+ thinking?: ThinkingLevel;
15
+ continue?: boolean;
16
+ resume?: boolean;
17
+ help?: boolean;
18
+ version?: boolean;
19
+ listModels?: boolean;
20
+ mode?: Mode;
21
+ noSession?: boolean;
22
+ session?: string;
23
+ sessionDir?: string;
24
+ toolSet?: "coding" | "readonly" | "all";
25
+ noSkills?: boolean;
26
+ skills?: string[];
27
+ print?: boolean;
28
+ verbose?: boolean;
29
+ messages: string[];
30
+ fileArgs: string[];
31
+ }
32
+ export declare function parseArgs(args: string[]): Args;
33
+ export declare function printHelp(): void;
34
+ export declare function printModels(): void;
35
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7C,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAInC,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,KAAK,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA2E9C;AAED,wBAAgB,SAAS,IAAI,IAAI,CAoEhC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAuBlC","sourcesContent":["/**\n * CLI argument parsing for edge-pi-cli.\n *\n * Simplified from the original CLI - no RPC, no extensions.\n */\n\nimport chalk from \"chalk\";\nimport type { ThinkingLevel } from \"edge-pi\";\nimport { getLatestModels, listProviders } from \"../model-factory.js\";\n\nexport type Mode = \"text\" | \"json\";\n\nconst VALID_THINKING_LEVELS = new Set([\"off\", \"minimal\", \"low\", \"medium\", \"high\"]);\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string;\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tlistModels?: boolean;\n\tmode?: Mode;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionDir?: string;\n\ttoolSet?: \"coding\" | \"readonly\" | \"all\";\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tprint?: boolean;\n\tverbose?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n}\n\nexport function parseArgs(args: string[]): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\tresult.listModels = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = args[++i];\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--tools\" && i + 1 < args.length) {\n\t\t\tconst toolSet = args[++i];\n\t\t\tif (toolSet === \"coding\" || toolSet === \"readonly\" || toolSet === \"all\") {\n\t\t\t\tresult.toolSet = toolSet;\n\t\t\t} else {\n\t\t\t\tconsole.error(chalk.yellow(`Warning: Invalid tool set \"${toolSet}\". Valid values: coding, readonly, all`));\n\t\t\t}\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (VALID_THINKING_LEVELS.has(level)) {\n\t\t\t\tresult.thinking = level as ThinkingLevel;\n\t\t\t} else {\n\t\t\t\tconsole.error(\n\t\t\t\t\tchalk.yellow(\n\t\t\t\t\t\t`Warning: Invalid thinking level \"${level}\". Valid values: ${[...VALID_THINKING_LEVELS].join(\", \")}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1));\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(): void {\n\tconsole.log(`${chalk.bold(\"epi\")} - CLI for the edge-pi coding agent SDK\n\n${chalk.bold(\"Usage:\")}\n epi [options] [@files...] [messages...]\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (${listProviders().join(\", \")})\n --model <id> Model ID (auto-detected from provider)\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> Override the system prompt\n --append-system-prompt <text> Append text to the system prompt\n --mode <mode> Output mode: text (default) or json\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select and resume a previous session\n --session <path> Use specific session file\n --session-dir <dir> Directory for session storage\n --no-session Don't save session (ephemeral)\n --tools <set> Tool set: coding (default), readonly, or all\n --thinking <level> Thinking level: off, minimal, low, medium, high\n --skill <path> Load a skill file or directory (repeatable)\n --no-skills Disable skill discovery and loading\n --verbose Verbose output\n --list-models List latest supported models\n --help, -h Show this help\n --version, -v Show version number\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n epi\n\n # Interactive mode with initial prompt\n epi \"List all .ts files in src/\"\n\n # Include files in initial message\n epi @prompt.md \"Refactor this\"\n\n # Non-interactive mode (process and exit)\n epi -p \"List all .ts files in src/\"\n\n # Continue previous session\n epi --continue \"What did we discuss?\"\n\n # Resume a previous session (interactive picker)\n epi --resume\n\n # Use specific latest models\n epi --provider anthropic --model claude-opus-4-6\n epi --provider openai --model gpt-5.3\n epi --provider openai-codex --model gpt-5.3-codex\n epi --provider google --model gemini-3-flash\n epi --provider github-copilot --model claude-sonnet-4.5\n\n # Read-only tools\n epi --tools readonly -p \"Review the code in src/\"\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY Anthropic Claude API key\n OPENAI_API_KEY OpenAI GPT API key\n GEMINI_API_KEY Google Gemini API key\n COPILOT_GITHUB_TOKEN GitHub Copilot token (or GH_TOKEN / GITHUB_TOKEN)\n\n${chalk.bold(\"Tool Sets:\")}\n coding read, bash, edit, write (default)\n readonly read, grep, find, ls\n all read, bash, edit, write, grep, find, ls\n`);\n}\n\nexport function printModels(): void {\n\tconst latestModels = getLatestModels();\n\n\tconsole.log(`${chalk.bold(\"Latest Supported Models:\")}\\n`);\n\n\tfor (const [provider, models] of Object.entries(latestModels)) {\n\t\tconsole.log(`${chalk.bold(provider.toUpperCase())}:`);\n\t\tfor (const model of models) {\n\t\t\tconsole.log(` ${model}`);\n\t\t}\n\t\tconsole.log();\n\t}\n\n\tconsole.log(`${chalk.bold(\"Usage:\")}\n epi --provider <provider> --model <model> [message...]\n\n${chalk.bold(\"Examples:\")}\n epi --provider anthropic --model claude-opus-4-6 \"Hello\"\n epi --provider openai --model gpt-5.3 \"Hello\"\n epi --provider openai-codex --model gpt-5.3-codex \"Hello\"\n epi --provider google --model gemini-3-flash \"Hello\"\n epi --provider github-copilot --model claude-sonnet-4.5 \"Hello\"\n`);\n}\n"]}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * CLI argument parsing for edge-pi-cli.
3
+ *
4
+ * Simplified from the original CLI - no RPC, no extensions.
5
+ */
6
+ import chalk from "chalk";
7
+ import { getLatestModels, listProviders } from "../model-factory.js";
8
+ const VALID_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high"]);
9
+ export function parseArgs(args) {
10
+ const result = {
11
+ messages: [],
12
+ fileArgs: [],
13
+ };
14
+ for (let i = 0; i < args.length; i++) {
15
+ const arg = args[i];
16
+ if (arg === "--help" || arg === "-h") {
17
+ result.help = true;
18
+ }
19
+ else if (arg === "--version" || arg === "-v") {
20
+ result.version = true;
21
+ }
22
+ else if (arg === "--list-models") {
23
+ result.listModels = true;
24
+ }
25
+ else if (arg === "--mode" && i + 1 < args.length) {
26
+ const mode = args[++i];
27
+ if (mode === "text" || mode === "json") {
28
+ result.mode = mode;
29
+ }
30
+ }
31
+ else if (arg === "--continue" || arg === "-c") {
32
+ result.continue = true;
33
+ }
34
+ else if (arg === "--resume" || arg === "-r") {
35
+ result.resume = true;
36
+ }
37
+ else if (arg === "--provider" && i + 1 < args.length) {
38
+ result.provider = args[++i];
39
+ }
40
+ else if (arg === "--model" && i + 1 < args.length) {
41
+ result.model = args[++i];
42
+ }
43
+ else if (arg === "--api-key" && i + 1 < args.length) {
44
+ result.apiKey = args[++i];
45
+ }
46
+ else if (arg === "--system-prompt" && i + 1 < args.length) {
47
+ result.systemPrompt = args[++i];
48
+ }
49
+ else if (arg === "--append-system-prompt" && i + 1 < args.length) {
50
+ result.appendSystemPrompt = args[++i];
51
+ }
52
+ else if (arg === "--no-session") {
53
+ result.noSession = true;
54
+ }
55
+ else if (arg === "--session" && i + 1 < args.length) {
56
+ result.session = args[++i];
57
+ }
58
+ else if (arg === "--session-dir" && i + 1 < args.length) {
59
+ result.sessionDir = args[++i];
60
+ }
61
+ else if (arg === "--tools" && i + 1 < args.length) {
62
+ const toolSet = args[++i];
63
+ if (toolSet === "coding" || toolSet === "readonly" || toolSet === "all") {
64
+ result.toolSet = toolSet;
65
+ }
66
+ else {
67
+ console.error(chalk.yellow(`Warning: Invalid tool set "${toolSet}". Valid values: coding, readonly, all`));
68
+ }
69
+ }
70
+ else if (arg === "--thinking" && i + 1 < args.length) {
71
+ const level = args[++i];
72
+ if (VALID_THINKING_LEVELS.has(level)) {
73
+ result.thinking = level;
74
+ }
75
+ else {
76
+ console.error(chalk.yellow(`Warning: Invalid thinking level "${level}". Valid values: ${[...VALID_THINKING_LEVELS].join(", ")}`));
77
+ }
78
+ }
79
+ else if (arg === "--print" || arg === "-p") {
80
+ result.print = true;
81
+ }
82
+ else if (arg === "--skill" && i + 1 < args.length) {
83
+ result.skills = result.skills ?? [];
84
+ result.skills.push(args[++i]);
85
+ }
86
+ else if (arg === "--no-skills") {
87
+ result.noSkills = true;
88
+ }
89
+ else if (arg === "--verbose") {
90
+ result.verbose = true;
91
+ }
92
+ else if (arg.startsWith("@")) {
93
+ result.fileArgs.push(arg.slice(1));
94
+ }
95
+ else if (!arg.startsWith("-")) {
96
+ result.messages.push(arg);
97
+ }
98
+ }
99
+ return result;
100
+ }
101
+ export function printHelp() {
102
+ console.log(`${chalk.bold("epi")} - CLI for the edge-pi coding agent SDK
103
+
104
+ ${chalk.bold("Usage:")}
105
+ epi [options] [@files...] [messages...]
106
+
107
+ ${chalk.bold("Options:")}
108
+ --provider <name> Provider name (${listProviders().join(", ")})
109
+ --model <id> Model ID (auto-detected from provider)
110
+ --api-key <key> API key (defaults to env vars)
111
+ --system-prompt <text> Override the system prompt
112
+ --append-system-prompt <text> Append text to the system prompt
113
+ --mode <mode> Output mode: text (default) or json
114
+ --print, -p Non-interactive mode: process prompt and exit
115
+ --continue, -c Continue previous session
116
+ --resume, -r Select and resume a previous session
117
+ --session <path> Use specific session file
118
+ --session-dir <dir> Directory for session storage
119
+ --no-session Don't save session (ephemeral)
120
+ --tools <set> Tool set: coding (default), readonly, or all
121
+ --thinking <level> Thinking level: off, minimal, low, medium, high
122
+ --skill <path> Load a skill file or directory (repeatable)
123
+ --no-skills Disable skill discovery and loading
124
+ --verbose Verbose output
125
+ --list-models List latest supported models
126
+ --help, -h Show this help
127
+ --version, -v Show version number
128
+
129
+ ${chalk.bold("Examples:")}
130
+ # Interactive mode
131
+ epi
132
+
133
+ # Interactive mode with initial prompt
134
+ epi "List all .ts files in src/"
135
+
136
+ # Include files in initial message
137
+ epi @prompt.md "Refactor this"
138
+
139
+ # Non-interactive mode (process and exit)
140
+ epi -p "List all .ts files in src/"
141
+
142
+ # Continue previous session
143
+ epi --continue "What did we discuss?"
144
+
145
+ # Resume a previous session (interactive picker)
146
+ epi --resume
147
+
148
+ # Use specific latest models
149
+ epi --provider anthropic --model claude-opus-4-6
150
+ epi --provider openai --model gpt-5.3
151
+ epi --provider openai-codex --model gpt-5.3-codex
152
+ epi --provider google --model gemini-3-flash
153
+ epi --provider github-copilot --model claude-sonnet-4.5
154
+
155
+ # Read-only tools
156
+ epi --tools readonly -p "Review the code in src/"
157
+
158
+ ${chalk.bold("Environment Variables:")}
159
+ ANTHROPIC_API_KEY Anthropic Claude API key
160
+ OPENAI_API_KEY OpenAI GPT API key
161
+ GEMINI_API_KEY Google Gemini API key
162
+ COPILOT_GITHUB_TOKEN GitHub Copilot token (or GH_TOKEN / GITHUB_TOKEN)
163
+
164
+ ${chalk.bold("Tool Sets:")}
165
+ coding read, bash, edit, write (default)
166
+ readonly read, grep, find, ls
167
+ all read, bash, edit, write, grep, find, ls
168
+ `);
169
+ }
170
+ export function printModels() {
171
+ const latestModels = getLatestModels();
172
+ console.log(`${chalk.bold("Latest Supported Models:")}\n`);
173
+ for (const [provider, models] of Object.entries(latestModels)) {
174
+ console.log(`${chalk.bold(provider.toUpperCase())}:`);
175
+ for (const model of models) {
176
+ console.log(` ${model}`);
177
+ }
178
+ console.log();
179
+ }
180
+ console.log(`${chalk.bold("Usage:")}
181
+ epi --provider <provider> --model <model> [message...]
182
+
183
+ ${chalk.bold("Examples:")}
184
+ epi --provider anthropic --model claude-opus-4-6 "Hello"
185
+ epi --provider openai --model gpt-5.3 "Hello"
186
+ epi --provider openai-codex --model gpt-5.3-codex "Hello"
187
+ epi --provider google --model gemini-3-flash "Hello"
188
+ epi --provider github-copilot --model claude-sonnet-4.5 "Hello"
189
+ `);
190
+ }
191
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CLI argument parsing for edge-pi-cli.\n *\n * Simplified from the original CLI - no RPC, no extensions.\n */\n\nimport chalk from \"chalk\";\nimport type { ThinkingLevel } from \"edge-pi\";\nimport { getLatestModels, listProviders } from \"../model-factory.js\";\n\nexport type Mode = \"text\" | \"json\";\n\nconst VALID_THINKING_LEVELS = new Set([\"off\", \"minimal\", \"low\", \"medium\", \"high\"]);\n\nexport interface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tappendSystemPrompt?: string;\n\tthinking?: ThinkingLevel;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tlistModels?: boolean;\n\tmode?: Mode;\n\tnoSession?: boolean;\n\tsession?: string;\n\tsessionDir?: string;\n\ttoolSet?: \"coding\" | \"readonly\" | \"all\";\n\tnoSkills?: boolean;\n\tskills?: string[];\n\tprint?: boolean;\n\tverbose?: boolean;\n\tmessages: string[];\n\tfileArgs: string[];\n}\n\nexport function parseArgs(args: string[]): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t\tfileArgs: [],\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--version\" || arg === \"-v\") {\n\t\t\tresult.version = true;\n\t\t} else if (arg === \"--list-models\") {\n\t\t\tresult.listModels = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--append-system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.appendSystemPrompt = args[++i];\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (arg === \"--session-dir\" && i + 1 < args.length) {\n\t\t\tresult.sessionDir = args[++i];\n\t\t} else if (arg === \"--tools\" && i + 1 < args.length) {\n\t\t\tconst toolSet = args[++i];\n\t\t\tif (toolSet === \"coding\" || toolSet === \"readonly\" || toolSet === \"all\") {\n\t\t\t\tresult.toolSet = toolSet;\n\t\t\t} else {\n\t\t\t\tconsole.error(chalk.yellow(`Warning: Invalid tool set \"${toolSet}\". Valid values: coding, readonly, all`));\n\t\t\t}\n\t\t} else if (arg === \"--thinking\" && i + 1 < args.length) {\n\t\t\tconst level = args[++i];\n\t\t\tif (VALID_THINKING_LEVELS.has(level)) {\n\t\t\t\tresult.thinking = level as ThinkingLevel;\n\t\t\t} else {\n\t\t\t\tconsole.error(\n\t\t\t\t\tchalk.yellow(\n\t\t\t\t\t\t`Warning: Invalid thinking level \"${level}\". Valid values: ${[...VALID_THINKING_LEVELS].join(\", \")}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (arg === \"--print\" || arg === \"-p\") {\n\t\t\tresult.print = true;\n\t\t} else if (arg === \"--skill\" && i + 1 < args.length) {\n\t\t\tresult.skills = result.skills ?? [];\n\t\t\tresult.skills.push(args[++i]);\n\t\t} else if (arg === \"--no-skills\") {\n\t\t\tresult.noSkills = true;\n\t\t} else if (arg === \"--verbose\") {\n\t\t\tresult.verbose = true;\n\t\t} else if (arg.startsWith(\"@\")) {\n\t\t\tresult.fileArgs.push(arg.slice(1));\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function printHelp(): void {\n\tconsole.log(`${chalk.bold(\"epi\")} - CLI for the edge-pi coding agent SDK\n\n${chalk.bold(\"Usage:\")}\n epi [options] [@files...] [messages...]\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (${listProviders().join(\", \")})\n --model <id> Model ID (auto-detected from provider)\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> Override the system prompt\n --append-system-prompt <text> Append text to the system prompt\n --mode <mode> Output mode: text (default) or json\n --print, -p Non-interactive mode: process prompt and exit\n --continue, -c Continue previous session\n --resume, -r Select and resume a previous session\n --session <path> Use specific session file\n --session-dir <dir> Directory for session storage\n --no-session Don't save session (ephemeral)\n --tools <set> Tool set: coding (default), readonly, or all\n --thinking <level> Thinking level: off, minimal, low, medium, high\n --skill <path> Load a skill file or directory (repeatable)\n --no-skills Disable skill discovery and loading\n --verbose Verbose output\n --list-models List latest supported models\n --help, -h Show this help\n --version, -v Show version number\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode\n epi\n\n # Interactive mode with initial prompt\n epi \"List all .ts files in src/\"\n\n # Include files in initial message\n epi @prompt.md \"Refactor this\"\n\n # Non-interactive mode (process and exit)\n epi -p \"List all .ts files in src/\"\n\n # Continue previous session\n epi --continue \"What did we discuss?\"\n\n # Resume a previous session (interactive picker)\n epi --resume\n\n # Use specific latest models\n epi --provider anthropic --model claude-opus-4-6\n epi --provider openai --model gpt-5.3\n epi --provider openai-codex --model gpt-5.3-codex\n epi --provider google --model gemini-3-flash\n epi --provider github-copilot --model claude-sonnet-4.5\n\n # Read-only tools\n epi --tools readonly -p \"Review the code in src/\"\n\n${chalk.bold(\"Environment Variables:\")}\n ANTHROPIC_API_KEY Anthropic Claude API key\n OPENAI_API_KEY OpenAI GPT API key\n GEMINI_API_KEY Google Gemini API key\n COPILOT_GITHUB_TOKEN GitHub Copilot token (or GH_TOKEN / GITHUB_TOKEN)\n\n${chalk.bold(\"Tool Sets:\")}\n coding read, bash, edit, write (default)\n readonly read, grep, find, ls\n all read, bash, edit, write, grep, find, ls\n`);\n}\n\nexport function printModels(): void {\n\tconst latestModels = getLatestModels();\n\n\tconsole.log(`${chalk.bold(\"Latest Supported Models:\")}\\n`);\n\n\tfor (const [provider, models] of Object.entries(latestModels)) {\n\t\tconsole.log(`${chalk.bold(provider.toUpperCase())}:`);\n\t\tfor (const model of models) {\n\t\t\tconsole.log(` ${model}`);\n\t\t}\n\t\tconsole.log();\n\t}\n\n\tconsole.log(`${chalk.bold(\"Usage:\")}\n epi --provider <provider> --model <model> [message...]\n\n${chalk.bold(\"Examples:\")}\n epi --provider anthropic --model claude-opus-4-6 \"Hello\"\n epi --provider openai --model gpt-5.3 \"Hello\"\n epi --provider openai-codex --model gpt-5.3-codex \"Hello\"\n epi --provider google --model gemini-3-flash \"Hello\"\n epi --provider github-copilot --model claude-sonnet-4.5 \"Hello\"\n`);\n}\n"]}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for the edge-pi coding agent.\n */\nprocess.title = \"epi\";\n\nimport { main } from \"./main.js\";\n\nmain(process.argv.slice(2));\n"]}
package/dist/cli.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for the edge-pi coding agent.
4
+ */
5
+ process.title = "epi";
6
+ import { main } from "./main.js";
7
+ main(process.argv.slice(2));
8
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG;AACH,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;AAEtB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for the edge-pi coding agent.\n */\nprocess.title = \"epi\";\n\nimport { main } from \"./main.js\";\n\nmain(process.argv.slice(2));\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Context file loading for the system prompt.
3
+ *
4
+ * Loads AGENTS.md files from the current working directory and parent
5
+ * directories, following the convention from the coding-agent.
6
+ */
7
+ export interface ContextFile {
8
+ path: string;
9
+ content: string;
10
+ }
11
+ /**
12
+ * Load AGENTS.md context files by walking up from `cwd` to the filesystem root.
13
+ * Files closer to the root are returned first (broadest context first).
14
+ */
15
+ export declare function loadContextFiles(cwd: string): ContextFile[];
16
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE,CAyB3D","sourcesContent":["/**\n * Context file loading for the system prompt.\n *\n * Loads AGENTS.md files from the current working directory and parent\n * directories, following the convention from the coding-agent.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport interface ContextFile {\n\tpath: string;\n\tcontent: string;\n}\n\n/**\n * Load AGENTS.md context files by walking up from `cwd` to the filesystem root.\n * Files closer to the root are returned first (broadest context first).\n */\nexport function loadContextFiles(cwd: string): ContextFile[] {\n\tconst files: ContextFile[] = [];\n\tlet dir = resolve(cwd);\n\n\twhile (true) {\n\t\tconst agentsFile = join(dir, \"AGENTS.md\");\n\t\tif (existsSync(agentsFile)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(agentsFile, \"utf-8\").trim();\n\t\t\t\tif (content) {\n\t\t\t\t\tfiles.push({ path: agentsFile, content });\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// skip unreadable files\n\t\t\t}\n\t\t}\n\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break; // reached root\n\t\tdir = parent;\n\t}\n\n\t// Reverse so broadest context (root) comes first\n\tfiles.reverse();\n\treturn files;\n}\n"]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Context file loading for the system prompt.
3
+ *
4
+ * Loads AGENTS.md files from the current working directory and parent
5
+ * directories, following the convention from the coding-agent.
6
+ */
7
+ import { existsSync, readFileSync } from "node:fs";
8
+ import { dirname, join, resolve } from "node:path";
9
+ /**
10
+ * Load AGENTS.md context files by walking up from `cwd` to the filesystem root.
11
+ * Files closer to the root are returned first (broadest context first).
12
+ */
13
+ export function loadContextFiles(cwd) {
14
+ const files = [];
15
+ let dir = resolve(cwd);
16
+ while (true) {
17
+ const agentsFile = join(dir, "AGENTS.md");
18
+ if (existsSync(agentsFile)) {
19
+ try {
20
+ const content = readFileSync(agentsFile, "utf-8").trim();
21
+ if (content) {
22
+ files.push({ path: agentsFile, content });
23
+ }
24
+ }
25
+ catch {
26
+ // skip unreadable files
27
+ }
28
+ }
29
+ const parent = dirname(dir);
30
+ if (parent === dir)
31
+ break; // reached root
32
+ dir = parent;
33
+ }
34
+ // Reverse so broadest context (root) comes first
35
+ files.reverse();
36
+ return files;
37
+ }
38
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOnD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAiB;IAC5D,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEvB,OAAO,IAAI,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAC1C,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACJ,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzD,IAAI,OAAO,EAAE,CAAC;oBACb,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC3C,CAAC;YACF,CAAC;YAAC,MAAM,CAAC;gBACR,wBAAwB;YACzB,CAAC;QACF,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM,CAAC,eAAe;QAC1C,GAAG,GAAG,MAAM,CAAC;IACd,CAAC;IAED,iDAAiD;IACjD,KAAK,CAAC,OAAO,EAAE,CAAC;IAChB,OAAO,KAAK,CAAC;AAAA,CACb","sourcesContent":["/**\n * Context file loading for the system prompt.\n *\n * Loads AGENTS.md files from the current working directory and parent\n * directories, following the convention from the coding-agent.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport interface ContextFile {\n\tpath: string;\n\tcontent: string;\n}\n\n/**\n * Load AGENTS.md context files by walking up from `cwd` to the filesystem root.\n * Files closer to the root are returned first (broadest context first).\n */\nexport function loadContextFiles(cwd: string): ContextFile[] {\n\tconst files: ContextFile[] = [];\n\tlet dir = resolve(cwd);\n\n\twhile (true) {\n\t\tconst agentsFile = join(dir, \"AGENTS.md\");\n\t\tif (existsSync(agentsFile)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(agentsFile, \"utf-8\").trim();\n\t\t\t\tif (content) {\n\t\t\t\t\tfiles.push({ path: agentsFile, content });\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// skip unreadable files\n\t\t\t}\n\t\t}\n\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break; // reached root\n\t\tdir = parent;\n\t}\n\n\t// Reverse so broadest context (root) comes first\n\tfiles.reverse();\n\treturn files;\n}\n"]}
package/dist/main.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Main entry point for the edge-pi CLI.
3
+ *
4
+ * Handles argument parsing, model creation, skill loading,
5
+ * session management, auth, and mode dispatch.
6
+ */
7
+ export declare function main(args: string[]): Promise<void>;
8
+ //# sourceMappingURL=main.d.ts.map