lighthouse-cli 0.16.0__py3-none-any.whl

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 (49) hide show
  1. lighthouse/__init__.py +6 -0
  2. lighthouse/__main__.py +9 -0
  3. lighthouse/commands/__init__.py +0 -0
  4. lighthouse/commands/agents.py +310 -0
  5. lighthouse/commands/builds.py +85 -0
  6. lighthouse/commands/collectors.py +147 -0
  7. lighthouse/commands/connect.py +717 -0
  8. lighthouse/commands/connections.py +201 -0
  9. lighthouse/commands/evals.py +198 -0
  10. lighthouse/commands/kb.py +224 -0
  11. lighthouse/commands/language.py +56 -0
  12. lighthouse/commands/limits.py +61 -0
  13. lighthouse/commands/login.py +207 -0
  14. lighthouse/commands/models.py +61 -0
  15. lighthouse/commands/runs.py +157 -0
  16. lighthouse/commands/spend.py +84 -0
  17. lighthouse/commands/stack.py +103 -0
  18. lighthouse/commands/terms.py +50 -0
  19. lighthouse/commands/whoami.py +80 -0
  20. lighthouse/config.py +141 -0
  21. lighthouse/credentials.py +233 -0
  22. lighthouse/device.py +124 -0
  23. lighthouse/exits.py +78 -0
  24. lighthouse/flags.py +61 -0
  25. lighthouse/http.py +355 -0
  26. lighthouse/i18n.py +250 -0
  27. lighthouse/locales/ar.json +343 -0
  28. lighthouse/locales/de.json +343 -0
  29. lighthouse/locales/en.json +343 -0
  30. lighthouse/locales/es.json +343 -0
  31. lighthouse/locales/fr.json +343 -0
  32. lighthouse/locales/ga.json +343 -0
  33. lighthouse/locales/it.json +343 -0
  34. lighthouse/locales/ja.json +343 -0
  35. lighthouse/locales/nl.json +343 -0
  36. lighthouse/locales/pt.json +343 -0
  37. lighthouse/locales/zh-Hans.json +343 -0
  38. lighthouse/locales/zh-Hant.json +343 -0
  39. lighthouse/main.py +229 -0
  40. lighthouse/out.py +169 -0
  41. lighthouse/py.typed +0 -0
  42. lighthouse/sealing.py +448 -0
  43. lighthouse_cli-0.16.0.dist-info/METADATA +23 -0
  44. lighthouse_cli-0.16.0.dist-info/RECORD +49 -0
  45. lighthouse_cli-0.16.0.dist-info/WHEEL +5 -0
  46. lighthouse_cli-0.16.0.dist-info/entry_points.txt +2 -0
  47. lighthouse_cli-0.16.0.dist-info/licenses/LICENSE +202 -0
  48. lighthouse_cli-0.16.0.dist-info/licenses/NOTICE +2 -0
  49. lighthouse_cli-0.16.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,343 @@
1
+ {
2
+ "_comment": "zh-Hant: machine-drafted, pending native review.",
3
+ "main.description": "命令列版 LightHouse™:登入、連線你的環境、部署代理程式、檢視執行記錄並瞭解成本。",
4
+ "main.epilog": "退出碼:0 成功,1 失敗,2 用法錯誤,3 未登入,4 無許可權,5 稍後重試,7 需要人工處理。LightHouse 和 Octy 是 Atlantic Agentic Labs 的商標。文件:https://docs.atlanticagenticlabs.com/cli/",
5
+ "out.error": "錯誤",
6
+ "out.warning": "警告",
7
+ "out.nothing": "(無)",
8
+ "confirm.suffix": "[y/N]",
9
+ "confirm.yes": "y,yes,是",
10
+ "note.stopped": "已停止",
11
+ "note.waiting_for_approval": "等待批准中…",
12
+ "prompt.open_browser": "按 Enter 開啟瀏覽器,或按 Ctrl-C 停止…",
13
+ "prompt.revoke_token": "撤銷權杖 {token}?",
14
+ "err.not_signed_in": "未登入",
15
+ "err.not_signed_in_for": "未登入 {host}",
16
+ "hint.login": "請執行 `lighthouse login`",
17
+ "hint.login_again": "請再次執行 `lighthouse login`",
18
+ "err.needs_a_person": "{what}需要有人在鍵盤前操作",
19
+ "hint.needs_a_person": "請去掉 --no-input 再執行,或在命令列上設定該值",
20
+ "err.no_host": "未設定租用戶主機",
21
+ "hint.no_host": "請傳入 --host <tenant-id>.atlanticagenticlabs.com,設定 LIGHTHOUSE_HOST,或執行一次 `lighthouse login --host …`",
22
+ "err.bad_host": "{given} 不是有效的主機名",
23
+ "hint.bad_host": "請使用租用戶 id 或門戶的主機名",
24
+ "err.bad_config": "無法讀取 {path}:{error}",
25
+ "hint.bad_config": "請修復它,或刪除後重新執行 `lighthouse login`",
26
+ "err.pairing_expired": "配對碼在獲批之前已過期",
27
+ "err.sign_in_declined": "該登入在門戶中被拒絕",
28
+ "err.no_terminal": "沒有可用於詢問的終端",
29
+ "hint.no_terminal": "請傳入 --yes 以開啟瀏覽器,或傳入 --no-browser",
30
+ "err.timeout": "{method} {path} 超時",
31
+ "err.unreachable": "無法連線 {host}:{error}",
32
+ "hint.unreachable": "請檢查主機名和你的網路",
33
+ "err.not_json": "{method} {path}:服務返回的內容不是 JSON",
34
+ "err.exhausted": "{method} {path} 未成功",
35
+ "err.service_answered": "服務返回了 {status}",
36
+ "hint.scope_required": "請使用所需的範圍重新登入,例如 `lighthouse login --scope \"telemetry:read agents:read {scope}\"`",
37
+ "err.access_state_wrong": "有誤,或無權訪問此租用戶",
38
+ "err.access_state_missing": "缺失",
39
+ "err.access_stopped": "請求在到達 LightHouse 之前被 Cloudflare Access 攔截:Access 服務權杖{state}",
40
+ "hint.access_stopped": "請將 {id} 和 {secret} 設定為該租用戶的 Access 服務權杖(或向 `lighthouse login` 傳入 --access-client-id)",
41
+ "err.machine_key_refused": "{env} 中的機器金鑰被拒絕:它可能已被撤銷,或屬於其他租用戶",
42
+ "hint.machine_key_refused": "請檢視門戶中的“金鑰”頁面;機器金鑰不會重新整理,也不會按時間過期",
43
+ "err.delegated_token_refused": "{env} 中的委派權杖已過期或已被撤銷。委派權杖(lhat-...)有效期為八小時,在流水線中不會重新整理",
44
+ "hint.delegated_token_refused": "對於 CI,請在門戶的“金鑰”頁面建立機器金鑰(aalcp-...),並將其與該租用戶的 Access 服務權杖一起放入 {env}",
45
+ "err.access_token_incomplete": "Cloudflare Access 服務權杖只設定了一半:缺少 {missing}",
46
+ "hint.access_token_incomplete": "請同時設定 {id} 和 {secret}",
47
+ "err.access_secret_empty": "已指定 --access-client-secret-stdin,但標準輸入為空",
48
+ "err.access_id_missing": "已讀取 Access 金鑰,但沒有與之配套的 id",
49
+ "hint.access_id_missing": "請傳入 --access-client-id 或設定 {id}",
50
+ "err.access_secret_missing": "--access-client-id 需要配套的金鑰",
51
+ "hint.access_secret_missing": "請透過管道傳給 --access-client-secret-stdin,或設定 {secret}。它絕不能作為命令列引數",
52
+ "err.machine_key_no_tokens": "機器金鑰沒有可列出或撤銷的委派權杖",
53
+ "hint.machine_key_no_tokens": "請在門戶的“金鑰”頁面撤銷機器金鑰;`lighthouse tokens` 用於使用者登入所用的委派權杖",
54
+ "err.not_revoked": "未撤銷",
55
+ "err.no_tokens_to_list": "此憑據沒有可列出的委派權杖",
56
+ "err.unsupported_language": "不支援語言 {lang}",
57
+ "hint.unsupported_language": "請使用以下之一:{tags}",
58
+ "err.language_both": "請指定語言或 --clear,不能同時使用",
59
+ "login.pairing_code": "你的配對碼是:{code}",
60
+ "login.approve_at": "請在 {url} 批准",
61
+ "login.asking_for": "請求的範圍:{scope}",
62
+ "login.signed_in": "已以 {email}({role})身份登入 {tenant}。",
63
+ "login.scopes": "範圍:{scopes}",
64
+ "login.no_scopes": "(無)",
65
+ "login.in_keychain": "權杖儲存在作業系統鑰匙串中,不在任何檔案裡",
66
+ "login.access_kept": "Cloudflare Access 服務權杖也一併儲存在那裡",
67
+ "logout.nothing_stored": "{host}:未儲存任何內容",
68
+ "logout.revoked": "{host}:已撤銷並清除",
69
+ "logout.forgotten": "{host}:已在本地清除;它會在伺服器端自行過期",
70
+ "logout.could_not_revoke": "{host}:無法在伺服器端撤銷({error});仍在本地清除",
71
+ "tokens.revoked": "已撤銷 {token}",
72
+ "whoami.all_reach": "(此角色可訪問的全部範圍)",
73
+ "whoami.machine_key": "機器金鑰",
74
+ "whoami.delegated_token": "委派權杖",
75
+ "whoami.never_by_time": "不會按時間過期",
76
+ "whoami.note_machine_key": "機器金鑰不會重新整理,也不會按時間過期;請在門戶的“金鑰”頁面撤銷",
77
+ "whoami.note_delegated_token": "委派權杖八小時後過期,在 LIGHTHOUSE_TOKEN 下不會重新整理;CI 請使用門戶“金鑰”頁面中的機器金鑰(aalcp-...)",
78
+ "help.host": "租用戶的主機名或 id",
79
+ "help.as_json": "在標準輸出上只輸出一份 JSON 文件,不含其他內容",
80
+ "help.quiet": "不輸出說明文字",
81
+ "help.no_input": "絕不向人詢問任何內容;改為以 7 退出",
82
+ "help.yes": "對所有確認都回答是",
83
+ "help.timeout": "單個請求的超時秒數",
84
+ "help.lang": "使用的語言:en、fr、de、es、it、pt、nl、ga、ja、zh-Hans、zh-Hant、ar(預設:你的設定,然後是 LANG)",
85
+ "help.login._help": "透過瀏覽器使用裝置碼登入",
86
+ "help.logout._help": "撤銷本機的權杖並清除",
87
+ "help.tokens._help": "你的委派權杖,以及撤銷其中一個",
88
+ "help.whoami._help": "此 CLI 以誰的身份登入,以及可訪問的範圍",
89
+ "help.connect._help": "為此租用戶開啟提供商自己的批准頁面",
90
+ "help.connections._help": "你的連線的同步計劃、設定計劃,或立即同步",
91
+ "help.collectors._help": "向 Atlantic 申請採集器,並跟進你的申請",
92
+ "help.models._help": "模型庫及其證據評分",
93
+ "help.kb._help": "知識庫、其時效性,以及向其中攝取資料",
94
+ "help.agents._help": "列出、檢視、產生骨架、部署和復原代理程式",
95
+ "help.builds._help": "用代理程式構建器構建的代理程式,以及各自所在位置",
96
+ "help.evals._help": "評估結果,以及執行評估集",
97
+ "help.runs._help": "目前正在執行的內容,以及已執行的記錄",
98
+ "help.spend._help": "已花費的金額、趨勢走向,以及節省的金額",
99
+ "help.limits._help": "目前生效的支出限額,以及引擎是否已應用",
100
+ "help.terms._help": "此租用戶目前生效的商務條款",
101
+ "help.stack._help": "獲取我的技術棧:在你所選位置執行 LightHouse 的檔案",
102
+ "help.language._help": "你的語言,以及可選的語言",
103
+ "help.login.scope": "要請求的範圍,以空格分隔(預設:telemetry:read agents:read)",
104
+ "help.login.no_browser": "列印 URL,而不是開啟瀏覽器",
105
+ "help.login.name": "此次登入在門戶和審計日誌中的描述",
106
+ "help.login.access_client_id": "租用戶的 Cloudflare Access 服務權杖 id,隨登入一併儲存(金鑰:--access-client-secret-stdin)",
107
+ "help.login.access_secret_stdin": "從標準輸入的一行讀取 Access 服務權杖金鑰",
108
+ "help.logout.every": "清除所有主機,而不僅是目前主機",
109
+ "help.tokens.revoke": "按 id 撤銷你自己的一個權杖",
110
+ "help.whoami.profiles": "同時列出本機上已登入的所有主機",
111
+ "help.connect.provider": "要連線的提供商;`list`(或留空)可列出全部",
112
+ "help.connect.family": "與 list 搭配:某個系列(google、microsoft、oracle、crm、...)",
113
+ "help.connect.kind": "與 list 搭配:其存放的內容(crm、mail、service-desk、...)",
114
+ "help.connect.search": "與 list 搭配:在名稱、系列、型別或描述中查詢的詞語(“email”可找到 Mail,“tickets”可找到 Service desk)",
115
+ "help.connect.state": "與 list 搭配:僅顯示處於此狀態的聯結器",
116
+ "help.connect.no_browser": "列印批准 URL,而不是開啟它",
117
+ "help.connect.reuse_local": "提議複用本機上已有的登入(會先詢問)",
118
+ "help.connect.every": "未指定提供商時:同時列出即將推出的",
119
+ "help.connect.credential_stdin": "以你自己的身份連線現有權杖,從標準輸入讀取(需要 `cloudflared access login https://<host>`)",
120
+ "help.connect.access": "與 --credential-stdin 搭配:read(預設)或 read_write",
121
+ "help.connect.target": "與 --credential-stdin 搭配:連線指向的目標(organisation=...、instance_url=...、site=...);可重複使用",
122
+ "help.connect.deployment": "與 --credential-stdin 搭配:保管憑據的部署,適用於租用戶有多個部署的情況",
123
+ "help.connect.deployment_key": "與 --credential-stdin 搭配:固定部署的公鑰(base64 或 PEM,按你的基礎設施所列印的格式);權杖只會封裝給由該金鑰簽名的封裝金鑰(或 LIGHTHOUSE_DEPLOYMENT_KEY)",
124
+ "help.connections.list._help": "所有連線、其同步計劃和下次同步(預設)",
125
+ "help.connections.schedule._help": "設定連線的同步頻率(client_admin,以你自己的身份)",
126
+ "help.connections.sync._help": "立即同步一個連線(client_admin,以你自己的身份)",
127
+ "help.connections.schedule.connection": "連線的 id,cx-...",
128
+ "help.connections.schedule.mode": "off、every_15m、hourly、working_hours 或 daily",
129
+ "help.connections.schedule.at": "與 --mode daily 搭配:時間,24 小時制 HH:MM",
130
+ "help.connections.schedule.tz": "與 working_hours 或 daily 搭配:時區,例如 Europe/London",
131
+ "help.connections.schedule.card": "來源,<pack>:<card>,適用於部署報告多個來源的情況",
132
+ "help.connections.schedule.deployment": "部署,適用於來源在多個部署中執行的情況",
133
+ "help.connections.schedule.reason": "原因,用於審計日誌",
134
+ "help.connections.sync.connection": "連線的 id,cx-...",
135
+ "help.connections.sync.card": "來源,<pack>:<card>,適用於部署報告多個來源的情況",
136
+ "help.connections.sync.deployment": "部署,適用於來源在多個部署中執行的情況",
137
+ "help.connections.sync.reason": "原因,用於審計日誌",
138
+ "help.collectors.requests._help": "你的租用戶的採集器申請及其階段(預設)",
139
+ "help.collectors.request._help": "向 Atlantic 申請採集器(handler 或 client_admin)",
140
+ "help.collectors.request.vendor": "系統的廠商,例如 'Invented CRM'",
141
+ "help.collectors.request.product": "產品,例如 'Sales Suite'",
142
+ "help.collectors.request.reads": "它應讀取什麼",
143
+ "help.collectors.request.cloud": "你的部署執行在哪裡",
144
+ "help.collectors.request.kind": "它讀取的型別,用 slug 表示:crm、tickets、wiki、...",
145
+ "help.collectors.request.access": "read(預設)或 read_write",
146
+ "help.collectors.request.urgency": "low、normal(預設)或 high",
147
+ "help.collectors.request.docs_url": "廠商的公開 API 文件,https://",
148
+ "help.models.task": "為相容性而接受;服務不會按任務對庫排序,因此此項不起任何作用",
149
+ "help.models.provider": "僅此提供商的模型",
150
+ "help.kb.list._help": "所有知識庫(預設)",
151
+ "help.kb.show._help": "單個知識庫",
152
+ "help.kb.ingest._help": "立即將一個連線同步到知識庫(以你自己的身份)",
153
+ "help.kb.upload._help": "將檔案直接上傳到你的部署自己的儲存",
154
+ "help.kb.show.index": "索引的名稱",
155
+ "help.kb.ingest.source": "連線 id(cx-...)或聯結器:github、gitlab、confluence、jira、gdrive…",
156
+ "help.kb.ingest.repo": "按標籤或目標將聯結器限定到一個連線,例如 owner/name",
157
+ "help.kb.ingest.reason": "原因,用於審計日誌",
158
+ "help.kb.ingest.wait": "等待同步完成",
159
+ "help.kb.ingest.wait_timeout": "最多等待的秒數(預設 1800);之後以 5 退出",
160
+ "help.kb.upload.file": "檔案:.md、.txt、.csv、.pdf、.docx、.pptx、.xlsx…",
161
+ "help.kb.upload.deployment": "哪個部署,適用於你有多個部署的情況",
162
+ "help.agents.list._help": "所有代理程式(預設)",
163
+ "help.agents.show._help": "單個代理程式的配置和最近的執行記錄",
164
+ "help.agents.init._help": "在目前目錄產生 agent.toml 骨架",
165
+ "help.agents.logs._help": "代理程式的執行記錄,以及單次執行的步驟",
166
+ "help.agents.deploy._help": "將代理程式的某個已釋出版本設為目前版本(deploy 範圍)",
167
+ "help.agents.rollback._help": "回到較早的已釋出版本(deploy 範圍)",
168
+ "help.agents.show.agent": "pack:card,例如 research:summary",
169
+ "help.agents.init.name": "代理程式的名稱",
170
+ "help.agents.init.file": "寫入位置",
171
+ "help.agents.init.force": "覆蓋已有檔案",
172
+ "help.agents.logs.status": "僅顯示此狀態的執行",
173
+ "help.agents.logs.trace": "改為顯示單次執行的 span",
174
+ "help.agents.deploy.agent": "pack:card,例如 research:summary",
175
+ "help.agents.deploy.version": "要設為目前版本的已釋出版本",
176
+ "help.agents.deploy.deployment": "部署,適用於租用戶有多個部署的情況",
177
+ "help.agents.deploy.reason": "原因,用於審計日誌",
178
+ "help.agents.deploy.wait": "等待部署響應(如果在等待批准,則等待決定)",
179
+ "help.agents.deploy.wait_timeout": "最多等待的秒數(預設 900);之後以 5 退出",
180
+ "help.agents.rollback.agent": "pack:card",
181
+ "help.agents.rollback.to": "要回到的版本(預設:目前版本之前最後一個透過其關卡的版本)",
182
+ "help.agents.rollback.deployment": "部署,適用於租用戶有多個部署的情況",
183
+ "help.agents.rollback.reason": "原因,用於審計日誌",
184
+ "help.agents.rollback.wait": "等待部署響應(如果在等待批准,則等待決定)",
185
+ "help.agents.rollback.wait_timeout": "最多等待的秒數(預設 900);之後以 5 退出",
186
+ "help.builds.status": "僅顯示處於此步驟的提案,例如 publish_requested",
187
+ "help.builds.show._help": "單個提案,含其評分和預估成本",
188
+ "help.builds.show.proposal": "提案的 id(32 個十六進位制字元)",
189
+ "help.evals.list._help": "最新結果(預設)",
190
+ "help.evals.run._help": "在支出上限下執行一次代理程式的評估",
191
+ "help.evals.list.fail_below": "如果任一行的指標低於此值或沒有該指標,則以 1 退出",
192
+ "help.evals.list.metric": "--fail-below 從每行的 `metrics` 中讀取的指標(預設:f1)",
193
+ "help.evals.run.agent": "pack:card,例如 research:summary",
194
+ "help.evals.run.cap": "此次執行最多可花費的金額,以美元計",
195
+ "help.evals.run.eval_set": "一個評估集(其評估卡片的 id)",
196
+ "help.evals.run.deployment": "部署,適用於租用戶有多個部署的情況",
197
+ "help.evals.run.reason": "原因,用於審計日誌",
198
+ "help.evals.run.wait": "等待評估結果,並據此設定關卡",
199
+ "help.evals.run.wait_timeout": "最多等待的秒數(預設 1800);之後以 5 退出",
200
+ "help.evals.run.fail_below": "與 --wait 搭配:如果新行的指標低於此值或缺失,則以 1 退出",
201
+ "help.evals.run.metric": "--fail-below 讀取的指標(預設:f1)",
202
+ "help.runs.list._help": "最近的執行(預設)",
203
+ "help.runs.show._help": "單次執行",
204
+ "help.runs.tail._help": "跟蹤實時執行",
205
+ "help.runs.show.run": "其 run_id_hash",
206
+ "help.runs.show.as_map": "執行圖:每個步驟、模型呼叫和檢索",
207
+ "help.runs.tail.interval": "兩次輪詢之間的秒數",
208
+ "help.runs.tail.once": "取一次快照,然後停止",
209
+ "help.runs.tail.duration": "經過此秒數後停止",
210
+ "help.runs.tail.deployment": "僅此部署的執行",
211
+ "help.runs.tail.fail_on_stall": "如果有執行停滯,則以 1 退出",
212
+ "help.spend.by": "如何分組",
213
+ "help.spend.month": "YYYY-MM;預設為目前月份",
214
+ "help.spend.forecast": "同時顯示對照上限的月末預測",
215
+ "help.spend.savings": "同時顯示預估節省額總覽",
216
+ "help.limits.scope": "僅此範圍型別的限額",
217
+ "help.terms.term": "按鍵名檢視單項條款",
218
+ "help.stack.cloud": "aws、azure、gcp 或 onprem(預設:所選的那個)",
219
+ "help.stack.region": "區域(預設:所選的那個)",
220
+ "help.stack.profile": "always_on 或 ephemeral(預設:所選的那個)",
221
+ "help.stack.deployment": "這些檔案對應你的哪個活躍部署",
222
+ "help.stack.out": "將所有檔案寫入此目錄",
223
+ "help.stack.force": "覆蓋該技術棧指定的、此處已存在的檔案",
224
+ "help.language.list_all": "僅列出可選的語言",
225
+ "label.agent": "代理程式",
226
+ "label.pack": "包",
227
+ "label.state": "狀態",
228
+ "label.models": "模型",
229
+ "label.runs_month": "執行(月)",
230
+ "label.estimated_cost": "預估成本",
231
+ "label.version": "版本",
232
+ "label.status": "狀態",
233
+ "label.command": "命令",
234
+ "label.span": "span",
235
+ "label.kind": "型別",
236
+ "label.starts_at_ms": "開始於(毫秒)",
237
+ "label.took_ms": "耗時(毫秒)",
238
+ "label.run": "執行",
239
+ "label.started": "開始時間",
240
+ "label.attempts": "嘗試次數",
241
+ "label.trigger": "觸發器",
242
+ "label.proposal": "提案",
243
+ "label.evaluation": "評估",
244
+ "label.estimated_month": "預估 / 月",
245
+ "label.deployment": "部署",
246
+ "label.template": "模板",
247
+ "label.problems": "問題",
248
+ "label.retrieval": "檢索",
249
+ "label.estimated_per_run": "每次執行預估",
250
+ "label.estimated_per_month": "每月預估",
251
+ "label.request": "申請",
252
+ "label.collector": "採集器",
253
+ "label.stage": "階段",
254
+ "label.issue": "工單",
255
+ "label.clients_asking": "申請的客戶數",
256
+ "label.asked": "申請時間",
257
+ "label.provider": "提供商",
258
+ "label.what": "內容",
259
+ "label.family": "系列",
260
+ "label.read_only_scopes": "只讀範圍",
261
+ "label.approve_at": "批准地址",
262
+ "label.sent_to_your_own_store": "傳送到你自己的儲存",
263
+ "label.access": "訪問",
264
+ "label.connection": "連線",
265
+ "label.connected": "已連線",
266
+ "label.syncing": "同步中",
267
+ "label.last_sync": "上次同步",
268
+ "label.connector": "聯結器",
269
+ "label.schedule": "計劃",
270
+ "label.next_sync": "下次同步",
271
+ "label.asked_for": "請求的內容",
272
+ "label.suite": "套件",
273
+ "label.passed": "透過",
274
+ "label.metrics": "指標",
275
+ "label.measured": "測量於",
276
+ "label.cap": "上限",
277
+ "label.index": "索引",
278
+ "label.documents": "文件",
279
+ "label.chunks": "分塊",
280
+ "label.last_refreshed": "上次重新整理",
281
+ "label.health": "健康",
282
+ "label.backend": "後端",
283
+ "label.knowledge_base": "知識庫",
284
+ "label.uploaded": "已上傳",
285
+ "label.bytes": "位元組",
286
+ "label.indexed": "已索引",
287
+ "label.tag": "標籤",
288
+ "label.language": "語言",
289
+ "label.your_language": "你的語言",
290
+ "label.your_organisation_s": "你的組織的",
291
+ "label.in_use_now": "目前使用",
292
+ "label.scope": "範圍",
293
+ "label.period": "週期",
294
+ "label.spent": "已花費",
295
+ "label.used": "已用 %",
296
+ "label.alerts_at": "提醒閾值 %",
297
+ "label.applied_by": "應用方",
298
+ "label.token": "權杖",
299
+ "label.client": "客戶",
300
+ "label.scopes": "範圍",
301
+ "label.issued": "簽發時間",
302
+ "label.expires": "到期",
303
+ "label.last_used": "上次使用",
304
+ "label.step": "步驟",
305
+ "label.tokens_in_out": "詞元 入/出",
306
+ "label.elapsed": "已用時間",
307
+ "label.calls": "呼叫",
308
+ "label.input_tokens": "輸入詞元",
309
+ "label.output_tokens": "輸出詞元",
310
+ "label.cost_usd": "成本(美元)",
311
+ "label.managed_charge": "託管費用",
312
+ "label.month": "月份",
313
+ "label.total_cost_usd": "總成本(美元)",
314
+ "label.shown_in": "顯示幣種",
315
+ "label.projected_month_end_estimated": "月末預測(預估)",
316
+ "label.likely_range_estimated": "可能區間(預估)",
317
+ "label.against_the_cap": "對照上限",
318
+ "label.estimated_saving_this_month": "本月預估節省",
319
+ "label.in_words": "通俗說明",
320
+ "label.where": "位置",
321
+ "label.profile": "配置檔案",
322
+ "label.infrastructure": "基礎設施",
323
+ "label.written_to": "寫入到",
324
+ "label.file": "檔案",
325
+ "label.written": "已寫入",
326
+ "label.term": "條款",
327
+ "label.meaning": "含義",
328
+ "label.set_by": "設定方",
329
+ "label.direction": "方向",
330
+ "label.in_force_from": "生效日期",
331
+ "label.tenant": "租用戶",
332
+ "label.host": "主機",
333
+ "label.person": "人員",
334
+ "label.role": "角色",
335
+ "label.signed_in_with": "登入方式",
336
+ "label.credential_from": "憑據來源",
337
+ "label.credential_kind": "憑據型別",
338
+ "label.model": "模型",
339
+ "label.evals": "評估",
340
+ "label.calls_month": "呼叫(月)",
341
+ "label.input_m": "輸入 /M",
342
+ "label.output_m": "輸出 /M"
343
+ }
lighthouse/main.py ADDED
@@ -0,0 +1,229 @@
1
+ # Copyright 2026 Atlantic Agentic Labs. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ """`lighthouse`: the argument parser, the dispatcher and the exit code.
4
+
5
+ Every command is a function in `lighthouse.commands`, registered in `COMMANDS`
6
+ below with the subparser that configures it. Each one takes a `Context` and
7
+ returns a JSON-serialisable document; `main` prints it under `--json` or lets
8
+ the command's own `show` render it for a person. That split is why the golden
9
+ test can assert on the whole of `--json` for every command at once: no command
10
+ formats its own JSON.
11
+
12
+ Global options, accepted before or after the subcommand:
13
+
14
+ --host HOST the tenant (config.py explains how it is resolved)
15
+ --json one JSON document on standard output, nothing else
16
+ --quiet no prose; refusals still go to standard error
17
+ --no-input never ask a person anything; exit 7 if it would have to
18
+ --yes answer yes to every confirmation
19
+ --timeout N seconds for one request (connect, read and write each)
20
+ --lang TAG the language to speak (i18n.py: en, fr, de, es, it, pt, nl, ga, ja, zh-Hans, zh-Hant, ar)
21
+ --version
22
+
23
+ `main(argv)` returns the exit code and prints nothing that is not asked for, so
24
+ the tests drive it directly; `run()` is the console script and calls `sys.exit`.
25
+ """
26
+ from __future__ import annotations
27
+
28
+ import argparse
29
+ import logging
30
+ import os
31
+ import sys
32
+ from dataclasses import dataclass, field
33
+ from collections.abc import Callable
34
+ from pathlib import Path
35
+ from typing import Any, TextIO
36
+
37
+ from lighthouse import __version__, exits
38
+ from lighthouse import flags, i18n
39
+ from lighthouse.config import Config
40
+ from lighthouse.credentials import Store
41
+ from lighthouse.exits import CliError
42
+ from lighthouse.http import Client
43
+ from lighthouse.i18n import t
44
+ from lighthouse.out import Out
45
+
46
+ log = logging.getLogger(__name__)
47
+
48
+
49
+ @dataclass
50
+ class Context:
51
+ """Everything a command may use, and nothing global. The tests build one of
52
+ these, so no command reads `os.environ` or `sys.argv` for itself."""
53
+ args: argparse.Namespace
54
+ out: Out
55
+ config: Config
56
+ store: Store
57
+ env: dict[str, str] = field(default_factory=dict)
58
+ transport: Any = None
59
+ sleep: Any = None
60
+ opener: Any = None
61
+ reader: Any = None
62
+ stdin: TextIO | None = None
63
+ _client: Client | None = None
64
+
65
+ @property
66
+ def host(self) -> str:
67
+ return self.config.host_for(getattr(self.args, "host", None), self.env)
68
+
69
+ def client(self, *, anonymous: bool = False) -> Client:
70
+ """A client for the resolved host. `anonymous` for the routes that take
71
+ no credential (the device-code request and the token endpoint)."""
72
+ if self._client is None:
73
+ host = self.host
74
+ credential = None if anonymous else self.store.require(host)
75
+ self._client = self.new_client(host, credential)
76
+ return self._client
77
+
78
+ def new_client(self, host: str, credential: Any, *,
79
+ access: tuple[str, str] | None = None,
80
+ session: str | None = None) -> Client:
81
+ """A client with this run's `--timeout` applied. Every client in the
82
+ program is made here, so the flag cannot be forgotten by one command."""
83
+ return Client(host, credential, store=self.store, transport=self.transport,
84
+ sleep=self.sleep, timeout=getattr(self.args, "timeout", None),
85
+ access=access, session=session)
86
+
87
+ def confirm(self, question: str) -> bool:
88
+ """Ask, unless `--yes`. Under `--no-input` an unanswered question is
89
+ exit 7, never a silent yes: a CI run must not approve anything by
90
+ default."""
91
+ if getattr(self.args, "yes", False):
92
+ return True
93
+ if getattr(self.args, "no_input", False) or not sys.stdin.isatty():
94
+ raise exits.NeedsAPerson(question)
95
+ answer = (self.reader or input)(f"{question} {t('confirm.suffix')} ").strip().lower()
96
+ return answer in {"y", "yes", *i18n.yes_answers()}
97
+
98
+
99
+ Handler = Callable[[Context], Any]
100
+ Shower = Callable[[Out, Any], None]
101
+
102
+
103
+ @dataclass(frozen=True)
104
+ class Command:
105
+ name: str
106
+ help: str
107
+ configure: Callable[[argparse.ArgumentParser], None]
108
+ handler: Handler
109
+ show: Shower
110
+ anonymous: bool = False
111
+
112
+
113
+ def commands() -> dict[str, Command]:
114
+ """Imported here rather than at module scope so `lighthouse --version`
115
+ costs one import, not twelve."""
116
+ from lighthouse.commands import (
117
+ agents,
118
+ builds,
119
+ collectors,
120
+ connect,
121
+ connections,
122
+ evals,
123
+ kb,
124
+ language,
125
+ limits,
126
+ login,
127
+ models,
128
+ runs,
129
+ spend,
130
+ stack,
131
+ terms,
132
+ whoami,
133
+ )
134
+ out: dict[str, Command] = {}
135
+ for module in (login, whoami, connect, connections, collectors, models, kb, agents, builds, evals,
136
+ runs, spend, limits, terms, stack, language):
137
+ for command in module.COMMANDS:
138
+ out[command.name] = command
139
+ return out
140
+
141
+
142
+ def parser(registry: dict[str, Command]) -> argparse.ArgumentParser:
143
+ """The root parser and one subparser per command.
144
+
145
+ The global options come from `flags.py`, which explains why they are
146
+ declared twice and what `SUPPRESS` is for. Each command's own
147
+ `configure` attaches `flags.inherited()` to any subparser of its own, so
148
+ `--json` works at every depth.
149
+ """
150
+ ap = argparse.ArgumentParser(
151
+ prog="lighthouse", add_help=True,
152
+ description=t("main.description"), epilog=t("main.epilog"))
153
+ ap.add_argument("--version", action="version", version=f"lighthouse {__version__}")
154
+
155
+ flags.add(ap, suppress=False)
156
+ common = flags.inherited()
157
+ subs = ap.add_subparsers(dest="command", metavar="<command>")
158
+ for command in registry.values():
159
+ sub = subs.add_parser(command.name, parents=[common], help=command.help,
160
+ description=command.help)
161
+ command.configure(sub)
162
+ return i18n.localise(ap)
163
+
164
+
165
+ def main(argv: list[str] | None = None, *, env: dict[str, str] | None = None,
166
+ stdout: TextIO | None = None, stderr: TextIO | None = None,
167
+ store: Store | None = None, config: Config | None = None,
168
+ transport: Any = None, sleep: Any = None, opener: Any = None,
169
+ reader: Any = None, isatty: bool | None = None,
170
+ stdin: TextIO | None = None) -> int:
171
+ env = env if env is not None else dict(os.environ)
172
+ argv = list(sys.argv[1:] if argv is None else argv)
173
+ # The language first: the parser's own help has to be in it (i18n.py).
174
+ try:
175
+ config = config if config is not None else Config.load(env)
176
+ known: str | None = config.host_for(None, env)
177
+ config_dir: Path | None = config.path.parent
178
+ except CliError:
179
+ known, config_dir = None, None
180
+ i18n.use(i18n.choose(argv, env, config_dir, known))
181
+ registry = commands()
182
+ ap = parser(registry)
183
+ try:
184
+ args = ap.parse_args(argv)
185
+ except SystemExit as e: # argparse's own --help and errors
186
+ return int(e.code or 0)
187
+ out = Out(as_json=bool(args.as_json), quiet=bool(args.quiet), stdout=stdout,
188
+ stderr=stderr, env=env, isatty=isatty)
189
+ if args.lang is not None and i18n.normalise(args.lang) is None:
190
+ refusal = CliError(t("err.unsupported_language", lang=args.lang), code=exits.USAGE,
191
+ error="usage", hint=t("hint.unsupported_language", tags=", ".join(i18n.TAGS)))
192
+ if out.as_json:
193
+ out.json(refusal.body())
194
+ else:
195
+ out.fail(refusal.message, hint=refusal.hint)
196
+ return refusal.code
197
+ if not args.command:
198
+ ap.print_help(file=out.stderr)
199
+ return exits.USAGE
200
+ command = registry[args.command]
201
+ context = Context(args=args, out=out,
202
+ config=config if config is not None else Config.load(env),
203
+ store=store if store is not None else Store(env=env),
204
+ env=env, transport=transport, sleep=sleep, opener=opener, reader=reader,
205
+ stdin=stdin)
206
+ try:
207
+ body = command.handler(context)
208
+ except CliError as e:
209
+ if out.as_json:
210
+ out.json(e.body())
211
+ else:
212
+ out.fail(e.message, hint=e.hint)
213
+ return e.code
214
+ except KeyboardInterrupt: # pragma: no cover - a person's Ctrl-C
215
+ out.note(t("note.stopped"))
216
+ return 130
217
+ finally:
218
+ if context._client is not None:
219
+ context._client.close()
220
+ if out.as_json:
221
+ if not out.streamed:
222
+ out.json(body if isinstance(body, dict) else {"ok": True, "result": body})
223
+ else:
224
+ command.show(out, body)
225
+ return exits.OK
226
+
227
+
228
+ def run() -> None: # pragma: no cover - the console script
229
+ sys.exit(main())