@gajae-code/coding-agent 0.18.6 → 0.18.8

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 (302) hide show
  1. package/CHANGELOG.md +318 -1
  2. package/dist/types/async/job-manager.d.ts +1 -1
  3. package/dist/types/capability/mcp.d.ts +2 -0
  4. package/dist/types/capability/skill.d.ts +2 -0
  5. package/dist/types/capability/types.d.ts +6 -0
  6. package/dist/types/cli/public-command-errors.d.ts +3 -1
  7. package/dist/types/cli/setup-cli.d.ts +1 -1
  8. package/dist/types/commands/deep-interview.d.ts +3 -0
  9. package/dist/types/config/autorouting-tier-map.d.ts +348 -9
  10. package/dist/types/config/file-lock.d.ts +1 -0
  11. package/dist/types/config/model-bindings-applier.d.ts +2 -0
  12. package/dist/types/config/model-profile-activation.d.ts +11 -3
  13. package/dist/types/config/model-registry.d.ts +4 -9
  14. package/dist/types/config/settings.d.ts +4 -0
  15. package/dist/types/config/skill-settings-defaults.d.ts +2 -0
  16. package/dist/types/cursor-delete-path.d.ts +1 -0
  17. package/dist/types/cursor-mcp-name.d.ts +8 -0
  18. package/dist/types/customization/inventory.d.ts +2 -0
  19. package/dist/types/debug/report-bundle-parent.d.ts +2 -0
  20. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
  21. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
  22. package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
  23. package/dist/types/discovery/helpers.d.ts +8 -3
  24. package/dist/types/export/html/css-color.d.ts +2 -0
  25. package/dist/types/export/html/template.generated.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/types.d.ts +7 -0
  27. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
  28. package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
  29. package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
  30. package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
  31. package/dist/types/extensibility/skill-management.d.ts +3 -1
  32. package/dist/types/extensibility/skills.d.ts +2 -0
  33. package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
  34. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
  35. package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
  36. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
  37. package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
  38. package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
  39. package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
  40. package/dist/types/gjc-runtime/state-writer.d.ts +11 -1
  41. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
  42. package/dist/types/internal-urls/skill-path.d.ts +1 -0
  43. package/dist/types/lsp/workspace-path.d.ts +1 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +7 -0
  45. package/dist/types/modes/components/custom-editor.d.ts +6 -0
  46. package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
  47. package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
  48. package/dist/types/modes/controllers/input-controller.d.ts +9 -0
  49. package/dist/types/modes/interactive-mode.d.ts +1 -0
  50. package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
  51. package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
  52. package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
  53. package/dist/types/progress/collect-project-progress.d.ts +38 -0
  54. package/dist/types/progress/progress-contract.d.ts +154 -0
  55. package/dist/types/progress/progress-snapshot.d.ts +11 -0
  56. package/dist/types/progress/project-progress.d.ts +141 -0
  57. package/dist/types/progress/render-progress.d.ts +28 -0
  58. package/dist/types/runtime-mcp/elicitation.d.ts +12 -0
  59. package/dist/types/runtime-mcp/oauth-public-url.d.ts +1 -0
  60. package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
  61. package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
  62. package/dist/types/runtime-mcp/types.d.ts +6 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +1 -1
  64. package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
  65. package/dist/types/sdk/broker/broker.d.ts +18 -1
  66. package/dist/types/sdk/broker/lifecycle.d.ts +9 -0
  67. package/dist/types/sdk/broker/session-index.d.ts +12 -6
  68. package/dist/types/sdk/broker/task-artifact-owner-validation.d.ts +55 -0
  69. package/dist/types/sdk/bus/index.d.ts +12 -1
  70. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
  71. package/dist/types/sdk/bus/telegram-daemon.d.ts +3 -2
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/host/host.d.ts +6 -0
  74. package/dist/types/sdk/host/query/handlers.d.ts +3 -0
  75. package/dist/types/sdk/index.d.ts +1 -0
  76. package/dist/types/sdk/router/session-router.d.ts +9 -0
  77. package/dist/types/sdk/session-list.d.ts +1 -1
  78. package/dist/types/sdk/session.d.ts +8 -0
  79. package/dist/types/session/agent-session.d.ts +38 -9
  80. package/dist/types/session/artifacts.d.ts +2 -2
  81. package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
  82. package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
  83. package/dist/types/session/internal/managed-session-storage.d.ts +36 -1
  84. package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
  85. package/dist/types/session/internal/task-artifact-owner-access.d.ts +19 -0
  86. package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +11 -0
  87. package/dist/types/session/session-manager.d.ts +31 -5
  88. package/dist/types/session/session-retirement.d.ts +71 -0
  89. package/dist/types/session/session-storage.d.ts +62 -48
  90. package/dist/types/session/session-transcript-header.d.ts +2 -0
  91. package/dist/types/session/task-artifact-owner-codec.d.ts +109 -0
  92. package/dist/types/session/task-artifact-owner-retirement.d.ts +7 -0
  93. package/dist/types/session/task-artifact-owner.d.ts +10 -0
  94. package/dist/types/setup/credential-auto-import.d.ts +1 -1
  95. package/dist/types/setup/credential-import.d.ts +6 -4
  96. package/dist/types/skill-state/active-state.d.ts +38 -0
  97. package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
  98. package/dist/types/task/executor.d.ts +3 -0
  99. package/dist/types/tools/bash-skill-urls.d.ts +1 -1
  100. package/dist/types/tools/index.d.ts +3 -0
  101. package/dist/types/tools/python.d.ts +9 -1
  102. package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
  103. package/dist/types/tools/restricted-cwd.d.ts +1 -0
  104. package/dist/types/tools/todo-write.d.ts +6 -0
  105. package/dist/types/utils/tools-checksum.d.ts +7 -0
  106. package/package.json +7 -7
  107. package/scripts/generate-sdk-operation-inventory.ts +21 -0
  108. package/scripts/resident-memory-bench.ts +174 -20
  109. package/scripts/verify-managed-empty-stop.ts +28 -0
  110. package/src/async/job-manager.ts +228 -122
  111. package/src/capability/index.ts +18 -0
  112. package/src/capability/mcp.ts +2 -0
  113. package/src/capability/skill.ts +2 -0
  114. package/src/capability/types.ts +6 -0
  115. package/src/cli/auth-broker-cli.ts +1 -1
  116. package/src/cli/config-cli.ts +8 -18
  117. package/src/cli/customize-doctor.ts +15 -2
  118. package/src/cli/public-command-errors.ts +21 -1
  119. package/src/cli/setup-cli.ts +4 -4
  120. package/src/cli/skills-cli.ts +5 -0
  121. package/src/cli-main.ts +7 -8
  122. package/src/commands/deep-interview.ts +47 -8
  123. package/src/commands/sdk.ts +140 -29
  124. package/src/config/autorouting-tier-map.ts +117 -7
  125. package/src/config/file-lock.ts +307 -68
  126. package/src/config/mcp-schema.json +4 -0
  127. package/src/config/model-bindings-applier.ts +20 -0
  128. package/src/config/model-profile-activation.ts +240 -46
  129. package/src/config/model-registry.ts +47 -153
  130. package/src/config/settings.ts +44 -4
  131. package/src/config/skill-settings-defaults.ts +7 -0
  132. package/src/coordinator-mcp/policy.ts +3 -2
  133. package/src/cursor-delete-path.ts +10 -0
  134. package/src/cursor-mcp-name.ts +15 -0
  135. package/src/cursor.ts +13 -2
  136. package/src/customization/inventory.ts +3 -0
  137. package/src/debug/report-bundle-parent.ts +22 -0
  138. package/src/debug/report-bundle.ts +3 -0
  139. package/src/debug/system-info.ts +13 -1
  140. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
  141. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
  142. package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
  143. package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
  144. package/src/defaults/gjc-defaults.test.ts +18 -1
  145. package/src/defaults/gjc-defaults.ts +3 -0
  146. package/src/defaults/gjc-skills.generated.ts +58 -36
  147. package/src/discovery/agents.ts +6 -1
  148. package/src/discovery/builtin.ts +10 -0
  149. package/src/discovery/helpers.ts +168 -23
  150. package/src/discovery/mcp-json.ts +6 -0
  151. package/src/discovery/ssh.ts +9 -4
  152. package/src/discovery/substitute-plugin-root.ts +3 -1
  153. package/src/edit/file-read-cache.ts +1 -1
  154. package/src/eval/py/executor.ts +380 -120
  155. package/src/export/html/css-color.ts +9 -0
  156. package/src/export/html/index.ts +5 -4
  157. package/src/export/html/template.generated.ts +1 -1
  158. package/src/extensibility/extensions/runner.ts +4 -0
  159. package/src/extensibility/extensions/types.ts +7 -0
  160. package/src/extensibility/gjc-plugins/runtime-adapters.ts +73 -8
  161. package/src/extensibility/plugins/manager.ts +3 -2
  162. package/src/extensibility/plugins/marketplace/cache.ts +15 -0
  163. package/src/extensibility/plugins/marketplace/manager.ts +11 -3
  164. package/src/extensibility/plugins/plugin-link-path.ts +12 -0
  165. package/src/extensibility/runtime-skill-discovery.ts +20 -2
  166. package/src/extensibility/skill-management.ts +6 -2
  167. package/src/extensibility/skills.ts +6 -1
  168. package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
  169. package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
  170. package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
  171. package/src/gjc-runtime/deep-interview-stage.ts +98 -21
  172. package/src/gjc-runtime/gc-runtime.ts +206 -8
  173. package/src/gjc-runtime/launch-worktree.ts +14 -4
  174. package/src/gjc-runtime/ralplan-runtime.ts +447 -52
  175. package/src/gjc-runtime/state-argv.ts +2 -0
  176. package/src/gjc-runtime/state-migrations.ts +91 -29
  177. package/src/gjc-runtime/state-runtime.ts +3716 -135
  178. package/src/gjc-runtime/state-writer.ts +83 -8
  179. package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
  180. package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
  181. package/src/gjc-runtime/workflow-manifest.ts +54 -21
  182. package/src/harness-control-plane/operate.ts +12 -4
  183. package/src/harness-control-plane/owner.ts +5 -1
  184. package/src/hashline/parser.ts +48 -9
  185. package/src/hashline/recovery.ts +13 -4
  186. package/src/hindsight/config.ts +9 -3
  187. package/src/internal-urls/docs-index.generated.ts +19 -18
  188. package/src/internal-urls/skill-path.ts +19 -0
  189. package/src/internal-urls/skill-protocol.ts +2 -0
  190. package/src/lsp/edits.ts +6 -0
  191. package/src/lsp/workspace-path.ts +51 -0
  192. package/src/main.ts +195 -31
  193. package/src/modes/acp/acp-agent.ts +163 -7
  194. package/src/modes/components/custom-editor.ts +14 -0
  195. package/src/modes/components/customization/customization-dashboard.ts +12 -0
  196. package/src/modes/components/extensions/extension-dashboard.ts +2 -2
  197. package/src/modes/components/extensions/state-manager.ts +15 -5
  198. package/src/modes/components/model-selector.ts +1 -4
  199. package/src/modes/components/provider-onboarding-selector.ts +1 -1
  200. package/src/modes/components/status-line/segments.ts +4 -0
  201. package/src/modes/controllers/event-controller.ts +11 -4
  202. package/src/modes/controllers/input-controller.ts +74 -29
  203. package/src/modes/controllers/runtime-mcp-command-controller.ts +8 -3
  204. package/src/modes/controllers/selector-controller.ts +28 -15
  205. package/src/modes/interactive-mode.ts +4 -0
  206. package/src/modes/runtime-init.ts +4 -0
  207. package/src/modes/utils/abort-message.ts +3 -1
  208. package/src/modes/utils/interrupt-ownership.ts +12 -0
  209. package/src/modes/utils/keybinding-matchers.ts +4 -0
  210. package/src/modes/utils/macos-option-forwarding.ts +80 -0
  211. package/src/progress/collect-project-progress.ts +153 -0
  212. package/src/progress/progress-contract.ts +172 -0
  213. package/src/progress/progress-snapshot.ts +140 -0
  214. package/src/progress/project-progress.ts +446 -0
  215. package/src/progress/render-progress.ts +209 -0
  216. package/src/prompts/system/master-mode.md +1 -0
  217. package/src/prompts/tools/skill-discovery.md +1 -1
  218. package/src/runtime-mcp/client.ts +13 -4
  219. package/src/runtime-mcp/config-writer.ts +10 -6
  220. package/src/runtime-mcp/config.ts +1 -0
  221. package/src/runtime-mcp/elicitation.ts +142 -0
  222. package/src/runtime-mcp/oauth-flow.ts +5 -0
  223. package/src/runtime-mcp/oauth-public-url.ts +8 -0
  224. package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
  225. package/src/runtime-mcp/smithery-registry.ts +22 -3
  226. package/src/runtime-mcp/transports/http.ts +2 -2
  227. package/src/runtime-mcp/types.ts +6 -0
  228. package/src/sdk/acp/adapter.ts +93 -8
  229. package/src/sdk/broker/broker-exit.ts +52 -23
  230. package/src/sdk/broker/broker.ts +83 -7
  231. package/src/sdk/broker/ensure.ts +2 -0
  232. package/src/sdk/broker/lifecycle.ts +820 -73
  233. package/src/sdk/broker/session-index.ts +191 -81
  234. package/src/sdk/broker/task-artifact-owner-validation.ts +259 -0
  235. package/src/sdk/bus/chat-daemon-cli.ts +38 -1
  236. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  237. package/src/sdk/bus/chat-daemon-runtime.ts +3 -0
  238. package/src/sdk/bus/index.ts +241 -46
  239. package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
  240. package/src/sdk/bus/telegram-daemon.ts +4 -2
  241. package/src/sdk/cli/session-cli.ts +17 -3
  242. package/src/sdk/client/client.ts +28 -8
  243. package/src/sdk/host/host.ts +6 -0
  244. package/src/sdk/host/query/handlers.ts +9 -1
  245. package/src/sdk/host/session-runtime.test.ts +2805 -411
  246. package/src/sdk/host/session-runtime.ts +428 -111
  247. package/src/sdk/host/surface-policy.ts +1 -0
  248. package/src/sdk/index.ts +8 -0
  249. package/src/sdk/lifecycle-session.ts +3 -1
  250. package/src/sdk/mcp/server.ts +15 -3
  251. package/src/sdk/prompt-deadline-manager.ts +15 -0
  252. package/src/sdk/protocol/operation-inventory.generated.json +146 -0
  253. package/src/sdk/protocol/operation-registry.ts +9 -2
  254. package/src/sdk/router/session-router.ts +94 -14
  255. package/src/sdk/session-list.ts +1 -0
  256. package/src/sdk/session.ts +81 -38
  257. package/src/session/agent-session.ts +674 -224
  258. package/src/session/artifacts.ts +174 -70
  259. package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
  260. package/src/session/internal/managed-session-scope.ts +3457 -462
  261. package/src/session/internal/managed-session-storage.ts +482 -61
  262. package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
  263. package/src/session/internal/task-artifact-owner-access.ts +245 -0
  264. package/src/session/internal/task-artifact-owner-transcript.ts +614 -0
  265. package/src/session/session-manager.ts +939 -133
  266. package/src/session/session-retirement.ts +714 -0
  267. package/src/session/session-storage.ts +418 -174
  268. package/src/session/session-transcript-header.ts +17 -0
  269. package/src/session/task-artifact-owner-codec.ts +641 -0
  270. package/src/session/task-artifact-owner-retirement.ts +477 -0
  271. package/src/session/task-artifact-owner.ts +289 -0
  272. package/src/setup/credential-auto-import.ts +12 -3
  273. package/src/setup/credential-import.ts +176 -5
  274. package/src/setup/paseo/announce.ts +6 -1
  275. package/src/skill-state/active-state.ts +132 -2
  276. package/src/slash-commands/builtin-registry.ts +39 -9
  277. package/src/slash-commands/helpers/progress-report.ts +23 -0
  278. package/src/stt/setup.ts +3 -5
  279. package/src/task/commands.ts +3 -1
  280. package/src/task/executor.ts +4 -0
  281. package/src/task/index.ts +6 -0
  282. package/src/tools/ask.ts +205 -6
  283. package/src/tools/ast-edit.ts +4 -0
  284. package/src/tools/bash-allowed-prefixes.ts +15 -0
  285. package/src/tools/bash-skill-urls.ts +56 -3
  286. package/src/tools/bash.ts +48 -79
  287. package/src/tools/descriptors.ts +5 -1
  288. package/src/tools/eval.ts +56 -36
  289. package/src/tools/image-gen.ts +1 -1
  290. package/src/tools/index.ts +3 -0
  291. package/src/tools/python.ts +187 -66
  292. package/src/tools/recipe/index.ts +9 -0
  293. package/src/tools/recipe/recipe-guard.ts +19 -0
  294. package/src/tools/restricted-cwd.ts +10 -0
  295. package/src/tools/skill-discovery.ts +5 -0
  296. package/src/tools/skill.ts +28 -1
  297. package/src/tools/todo-write.ts +10 -1
  298. package/src/tools/tool-catalog.generated.ts +1 -1
  299. package/src/tools/write.ts +1 -0
  300. package/src/utils/tools-checksum.ts +34 -0
  301. package/src/utils/tools-manager.ts +24 -6
  302. package/src/web/search/providers/codex.ts +3 -2
@@ -0,0 +1,289 @@
1
+ import * as crypto from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { ArtifactManager } from "./artifacts";
5
+ import { acquireManagedLock, type ManagedSessionDescendantStore } from "./internal/managed-session-storage";
6
+ import {
7
+ locatorFromManifest,
8
+ newSessionRootStore,
9
+ type OwnerManifest,
10
+ openOwnerStore,
11
+ readOwnerManifest,
12
+ } from "./internal/task-artifact-owner-access";
13
+ import type { NativeDirectoryTreeSnapshot } from "./session-storage";
14
+ import {
15
+ assertSafeRelativePath,
16
+ assertSessionRoot,
17
+ OWNER_DIRECTORY,
18
+ OWNER_LOCK_DIRECTORY,
19
+ OWNER_MANIFEST,
20
+ OWNER_SCHEMA_VERSION,
21
+ ownerIdForSession,
22
+ ownerRelativePath,
23
+ parseTaskArtifactOwnerLocator,
24
+ sameTreeContents,
25
+ type TaskArtifactOwnerLocator,
26
+ type TaskArtifactOwnerStorageContext,
27
+ } from "./task-artifact-owner-codec";
28
+
29
+ export interface ManagedTaskArtifactOwner {
30
+ readonly locator: TaskArtifactOwnerLocator;
31
+ readonly manager: ArtifactManager;
32
+ }
33
+
34
+ function makeOwnerManager(ownerStore: ManagedSessionDescendantStore): ArtifactManager {
35
+ return new ArtifactManager(ownerStore);
36
+ }
37
+
38
+ function legacyPathOverlapsOwner(
39
+ sessionsRoot: string,
40
+ sourceRelativePath: string,
41
+ destinationRelativePath: string,
42
+ ): boolean {
43
+ const source = path.resolve(sessionsRoot, sourceRelativePath);
44
+ const destination = path.resolve(sessionsRoot, destinationRelativePath);
45
+ const sourceToDestination = path.relative(source, destination);
46
+ const destinationToSource = path.relative(destination, source);
47
+ return (
48
+ source !== destination &&
49
+ ((!path.isAbsolute(sourceToDestination) &&
50
+ sourceToDestination !== ".." &&
51
+ !sourceToDestination.startsWith(`..${path.sep}`)) ||
52
+ (!path.isAbsolute(destinationToSource) &&
53
+ destinationToSource !== ".." &&
54
+ !destinationToSource.startsWith(`..${path.sep}`)))
55
+ );
56
+ }
57
+
58
+ async function copyLegacyArtifactTree(
59
+ store: ManagedSessionDescendantStore,
60
+ sourceRelativePath: string,
61
+ destinationRelativePath: string,
62
+ sourceSnapshot: NativeDirectoryTreeSnapshot,
63
+ ): Promise<void> {
64
+ for (const entry of sourceSnapshot.entries) {
65
+ if (entry.relativePath === "") continue;
66
+ const destination = path.posix.join(destinationRelativePath, entry.relativePath);
67
+ if (entry.kind === "directory") {
68
+ store.ensureDirectory(destination);
69
+ continue;
70
+ }
71
+ const sourceName = path.posix.join(sourceRelativePath, entry.relativePath);
72
+ const captured = store.readExpected(sourceName);
73
+ if (
74
+ !captured ||
75
+ captured.identity.dev.toString() !== entry.dev ||
76
+ captured.identity.ino.toString() !== entry.ino ||
77
+ String(captured.identity.size) !== entry.size ||
78
+ captured.identity.mtimeNs.toString() !== entry.mtimeNs ||
79
+ captured.identity.ctimeNs.toString() !== entry.ctimeNs ||
80
+ crypto.createHash("sha256").update(captured.bytes).digest("hex") !== entry.sha256
81
+ )
82
+ throw new Error("task_artifact_owner_source_changed");
83
+ await store.publishNoReplace(destination, captured.bytes);
84
+ }
85
+ const sourceAfter = store.captureTree(sourceRelativePath);
86
+ const destinationAfter = store.captureTree(destinationRelativePath);
87
+ if (
88
+ JSON.stringify(sourceAfter) !== JSON.stringify(sourceSnapshot) ||
89
+ !sameTreeContents(sourceSnapshot, destinationAfter)
90
+ )
91
+ throw new Error("task_artifact_owner_copy_mismatch");
92
+ }
93
+
94
+ function taskArtifactOwnerFromStore(
95
+ locator: TaskArtifactOwnerLocator,
96
+ ownerStore: ManagedSessionDescendantStore,
97
+ ): ManagedTaskArtifactOwner {
98
+ return Object.freeze({ locator: Object.freeze({ ...locator }), manager: makeOwnerManager(ownerStore) });
99
+ }
100
+
101
+ interface FailureState {
102
+ failed: boolean;
103
+ value: unknown;
104
+ }
105
+
106
+ function recordFailure(state: FailureState, error: unknown, message: string): void {
107
+ state.value = state.failed ? new AggregateError([state.value, error], message) : error;
108
+ state.failed = true;
109
+ }
110
+
111
+ function closeManagedStore(
112
+ store: ManagedSessionDescendantStore | undefined,
113
+ state: FailureState,
114
+ message: string,
115
+ ): void {
116
+ if (!store) return;
117
+ try {
118
+ store.close();
119
+ } catch (error) {
120
+ recordFailure(state, error, message);
121
+ }
122
+ }
123
+
124
+ function closeReturnedOwner(result: ManagedTaskArtifactOwner | undefined, state: FailureState): void {
125
+ closeManagedStore(result?.manager.getManagedStore(), state, "Closing the task artifact owner also failed.");
126
+ }
127
+
128
+ /** Reopen an owner only beneath the captured managed sessions-root authority. */
129
+ export function restoreManagedTaskArtifactOwner(
130
+ context: TaskArtifactOwnerStorageContext,
131
+ sessionId: string,
132
+ locatorValue: unknown,
133
+ ): ManagedTaskArtifactOwner {
134
+ const locator = parseTaskArtifactOwnerLocator(locatorValue);
135
+ if (!locator) throw new Error("task_artifact_owner_locator_missing");
136
+ const rootStore = newSessionRootStore(context);
137
+ const state: FailureState = { failed: false, value: undefined };
138
+ let result: ManagedTaskArtifactOwner | undefined;
139
+ try {
140
+ const ownerStore = openOwnerStore(context, rootStore, locator, sessionId);
141
+ result = taskArtifactOwnerFromStore(locator, ownerStore);
142
+ } catch (error) {
143
+ recordFailure(state, error, "Restoring the task artifact owner failed.");
144
+ }
145
+ closeManagedStore(rootStore, state, "Restoring the task artifact owner and closing its root store failed.");
146
+ if (state.failed) {
147
+ closeReturnedOwner(result, state);
148
+ throw state.value;
149
+ }
150
+ if (!result) throw new Error("task_artifact_owner_unavailable");
151
+ return result;
152
+ }
153
+
154
+ /** Establish or restore the logical-session owner under the captured managed sessions authority. */
155
+ export async function ensureManagedTaskArtifactOwner(
156
+ context: TaskArtifactOwnerStorageContext,
157
+ sessionId: string,
158
+ locatorValue: unknown,
159
+ legacyArtifactRelativePath?: string,
160
+ ): Promise<ManagedTaskArtifactOwner> {
161
+ assertSessionRoot(context);
162
+ const locator = parseTaskArtifactOwnerLocator(locatorValue);
163
+ const ownerId = locator?.ownerId ?? ownerIdForSession(sessionId);
164
+ if (ownerId !== ownerIdForSession(sessionId)) throw new Error("task_artifact_owner_session_mismatch");
165
+ const lock = await acquireManagedLock(
166
+ path.join(context.sessionsRoot, OWNER_LOCK_DIRECTORY),
167
+ `owner-${ownerId}`,
168
+ context.rootAuthority,
169
+ context.securityPolicy,
170
+ );
171
+
172
+ let result: ManagedTaskArtifactOwner | undefined;
173
+ const state: FailureState = { failed: false, value: undefined };
174
+ try {
175
+ lock.assertOwned();
176
+ if (locator) {
177
+ result = restoreManagedTaskArtifactOwner(context, sessionId, locator);
178
+ } else {
179
+ const rootStore = newSessionRootStore(context);
180
+ let ownerStore: ManagedSessionDescendantStore | undefined;
181
+ try {
182
+ rootStore.verifyRootSecurity();
183
+ const ownerRelative = ownerRelativePath(ownerId);
184
+ const ownerPath = path.join(context.sessionsRoot, ownerRelative);
185
+ let existingDirectory = false;
186
+ try {
187
+ const stat = fs.lstatSync(ownerPath, { bigint: true });
188
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error("task_artifact_owner_replaced");
189
+ existingDirectory = true;
190
+ } catch (error) {
191
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
192
+ }
193
+
194
+ if (existingDirectory) {
195
+ const identity = rootStore.captureDirectoryIdentity(ownerRelative);
196
+ const existingLocator: TaskArtifactOwnerLocator = {
197
+ schemaVersion: OWNER_SCHEMA_VERSION,
198
+ ownerId,
199
+ directoryDev: identity.dev,
200
+ directoryIno: identity.ino,
201
+ };
202
+ const manifest: OwnerManifest = readOwnerManifest(rootStore, existingLocator);
203
+ if (manifest.sessionId !== sessionId) throw new Error("task_artifact_owner_session_mismatch");
204
+ const restoredLocator = locatorFromManifest(manifest);
205
+ const restoredStore = openOwnerStore(context, rootStore, restoredLocator, sessionId);
206
+ result = taskArtifactOwnerFromStore(restoredLocator, restoredStore);
207
+ } else {
208
+ let legacySource: { relativePath: string; snapshot: NativeDirectoryTreeSnapshot } | undefined;
209
+ if (legacyArtifactRelativePath !== undefined) {
210
+ assertSafeRelativePath(legacyArtifactRelativePath);
211
+ if (legacyPathOverlapsOwner(context.sessionsRoot, legacyArtifactRelativePath, ownerRelative))
212
+ throw new Error("task_artifact_owner_legacy_path_overlaps_owner");
213
+ try {
214
+ fs.lstatSync(path.join(context.sessionsRoot, legacyArtifactRelativePath), { bigint: true });
215
+ legacySource = {
216
+ relativePath: legacyArtifactRelativePath,
217
+ snapshot: rootStore.captureTree(legacyArtifactRelativePath),
218
+ };
219
+ } catch (error) {
220
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
221
+ }
222
+ }
223
+
224
+ rootStore.ensureDirectory(OWNER_DIRECTORY);
225
+ const identity = rootStore.ensureDirectory(ownerRelative);
226
+ const createdLocator: TaskArtifactOwnerLocator = {
227
+ schemaVersion: OWNER_SCHEMA_VERSION,
228
+ ownerId,
229
+ directoryDev: identity.dev.toString(),
230
+ directoryIno: identity.ino.toString(),
231
+ };
232
+ ownerStore = rootStore.deriveSubtree(ownerRelative);
233
+ if (legacySource) {
234
+ await copyLegacyArtifactTree(
235
+ rootStore,
236
+ legacySource.relativePath,
237
+ ownerRelative,
238
+ legacySource.snapshot,
239
+ );
240
+ }
241
+ ownerStore.fsyncTree();
242
+ lock.assertOwned();
243
+ await ownerStore.publishNoReplace(
244
+ OWNER_MANIFEST,
245
+ Buffer.from(`${JSON.stringify({ ...createdLocator, sessionId })}\n`, "utf8"),
246
+ );
247
+ const verifiedStore = openOwnerStore(context, rootStore, createdLocator, sessionId);
248
+ try {
249
+ ownerStore.close();
250
+ } catch (error) {
251
+ try {
252
+ verifiedStore.close();
253
+ } catch (closeError) {
254
+ throw new AggregateError(
255
+ [error, closeError],
256
+ "Opening the owner and closing its writer store failed.",
257
+ );
258
+ }
259
+ throw error;
260
+ }
261
+ ownerStore = undefined;
262
+ result = taskArtifactOwnerFromStore(createdLocator, verifiedStore);
263
+ }
264
+ } catch (error) {
265
+ recordFailure(state, error, "Provisioning the task artifact owner failed.");
266
+ }
267
+ closeManagedStore(
268
+ ownerStore,
269
+ state,
270
+ "Provisioning the task artifact owner and closing its writer store failed.",
271
+ );
272
+ closeManagedStore(rootStore, state, "Provisioning the task artifact owner and closing its root store failed.");
273
+ }
274
+ } catch (error) {
275
+ recordFailure(state, error, "Task artifact owner setup failed.");
276
+ }
277
+
278
+ try {
279
+ await lock.release();
280
+ } catch (releaseError) {
281
+ recordFailure(state, releaseError, "Task artifact owner setup and lock release failed.");
282
+ }
283
+ if (state.failed) {
284
+ closeReturnedOwner(result, state);
285
+ throw state.value;
286
+ }
287
+ if (!result) throw new Error("task_artifact_owner_unavailable");
288
+ return result;
289
+ }
@@ -36,7 +36,11 @@ export const CREDENTIAL_AUTO_IMPORT_RETRY_WARNING =
36
36
  export const CREDENTIAL_AUTO_IMPORT_STATE_UNREADABLE_WARNING =
37
37
  "Credential import preference could not be read. External credential discovery was skipped; use /provider to import credentials manually.";
38
38
 
39
- export type CredentialAutoImportSourceLabel = "claude-code-file" | "claude-code-keychain" | "codex-file";
39
+ export type CredentialAutoImportSourceLabel =
40
+ | "claude-code-file"
41
+ | "claude-code-keychain"
42
+ | "codex-file"
43
+ | "kiro-cli-social";
40
44
  export type CredentialAutoImportTrigger = "startup" | "bare-login" | "setup-cli";
41
45
  export type InitialImportResolution = "accepted" | "declined";
42
46
  export type CredentialAutoImportStateProblem =
@@ -259,16 +263,18 @@ export interface CredentialAutoImportResult {
259
263
  globalDiscoveryFailure?: CredentialAutoImportFailure;
260
264
  }
261
265
 
262
- const CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS: readonly ExternalProvider[] = ["anthropic", "openai-codex"];
266
+ const CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS: readonly ExternalProvider[] = ["anthropic", "openai-codex", "kiro"];
263
267
  const CREDENTIAL_AUTO_IMPORT_PROMPT_ORIGINS: readonly CredentialOrigin[] = [
264
268
  "claude-code-file",
265
269
  "claude-code-keychain",
266
270
  "codex-file",
271
+ "kiro-cli-social",
267
272
  ];
268
273
  const CREDENTIAL_AUTO_IMPORT_ORIGIN_LABELS: Record<CredentialOrigin, string> = {
269
274
  "claude-code-file": "Claude Code file",
270
275
  "claude-code-keychain": "Claude Code Keychain",
271
276
  "codex-file": "Codex CLI file",
277
+ "kiro-cli-social": "Kiro CLI social login",
272
278
  };
273
279
  const CREDENTIAL_AUTO_IMPORT_FAILURE_CLASSES = new Set(Object.values(CredentialAutoImportFailureClass));
274
280
 
@@ -413,7 +419,10 @@ export function buildCredentialAutoImportNotice(
413
419
  ...new Set(result.imported.map(c => EXTERNAL_PROVIDER_LABELS[c.provider as ExternalProvider] ?? c.provider)),
414
420
  ];
415
421
  const success = `Imported ${result.imported.length} external OAuth credential(s) into gjc: ${providers.join(", ")}.`;
416
- return `${success}\n${CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING}`;
422
+ const mayRotateExternalRefreshToken = result.imported.some(
423
+ credential => credential.provider === "anthropic" || credential.provider === "openai-codex",
424
+ );
425
+ return mayRotateExternalRefreshToken ? `${success}\n${CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING}` : success;
417
426
  }
418
427
 
419
428
  export function formatCredentialAutoImportResult(result: CredentialAutoImportResult): string[] {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Discover and import existing Claude Code / Codex CLI credentials.
2
+ * Discover and import existing Claude Code, Codex CLI, and Kiro CLI credentials.
3
3
  *
4
4
  * This is the testable core behind `gjc setup credentials` (CLI, primary entry)
5
5
  * and the TUI provider-onboarding "import existing credentials" action. It never
@@ -12,7 +12,10 @@
12
12
  * Keychain (`Claude Code-credentials`), and env vars.
13
13
  * - Codex CLI: `$CODEX_HOME/auth.json` (defaults to `~/.codex/auth.json`;
14
14
  * OAuth `tokens` block or stored `OPENAI_API_KEY`), and env vars.
15
+ * - Kiro CLI social OAuth: `data.sqlite3` in the platform's app-data directory,
16
+ * read-only from `auth_kv` key `kirocli:social:token`.
15
17
  */
18
+ import { Database } from "bun:sqlite";
16
19
  import * as fs from "node:fs/promises";
17
20
  import * as os from "node:os";
18
21
  import * as path from "node:path";
@@ -21,20 +24,22 @@ import { $credentialEnv, isEnoent } from "@gajae-code/utils";
21
24
  import { redactSecret } from "./provider-onboarding";
22
25
 
23
26
  /** gjc provider ids that external credentials map onto. */
24
- export type ExternalProvider = "anthropic" | "openai-codex";
27
+ export type ExternalProvider = "anthropic" | "openai-codex" | "kiro";
25
28
 
26
29
  /** Where a discovered credential came from. */
27
- export type CredentialOrigin = "claude-code-file" | "claude-code-keychain" | "codex-file";
30
+ export type CredentialOrigin = "claude-code-file" | "claude-code-keychain" | "codex-file" | "kiro-cli-social";
28
31
 
29
32
  export const AUTO_IMPORT_OAUTH_PROVIDER_ORIGINS: Record<ExternalProvider, ReadonlySet<CredentialOrigin>> = {
30
33
  anthropic: new Set<CredentialOrigin>(["claude-code-file", "claude-code-keychain"]),
31
34
  "openai-codex": new Set<CredentialOrigin>(["codex-file"]),
35
+ kiro: new Set<CredentialOrigin>(["kiro-cli-social"]),
32
36
  };
33
37
 
34
38
  /** Human labels for providers, used in redacted summaries. */
35
39
  export const EXTERNAL_PROVIDER_LABELS: Record<ExternalProvider, string> = {
36
40
  anthropic: "Claude (Anthropic)",
37
41
  "openai-codex": "Codex (ChatGPT)",
42
+ kiro: "Kiro",
38
43
  };
39
44
 
40
45
  /** A credential that can be safely imported into gjc's store. */
@@ -98,6 +103,8 @@ export interface DiscoveryOptions {
98
103
  * or `null` when no entry exists.
99
104
  */
100
105
  readClaudeKeychain?: () => Promise<string | null>;
106
+ /** Absolute Kiro CLI data.sqlite3 override, primarily for tests and embedders. */
107
+ kiroCliDatabasePath?: string;
101
108
  }
102
109
 
103
110
  export type CredentialUpserter = (provider: string, credential: AuthCredential) => unknown | Promise<unknown>;
@@ -131,6 +138,7 @@ interface CodexAuthFile {
131
138
 
132
139
  const ANTHROPIC_ENV_KEYS = ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"] as const;
133
140
  const OPENAI_ENV_KEYS = ["OPENAI_API_KEY"] as const;
141
+ const KIRO_CLI_SOCIAL_TOKEN_KEY = "kirocli:social:token";
134
142
 
135
143
  // ─── JWT helpers (best-effort identity/expiry extraction) ────────────────────
136
144
 
@@ -368,6 +376,154 @@ async function discoverCodex(home: ResolvedExternalDir, result: CredentialDiscov
368
376
  pushOutcome(result, parseCodexAuth(raw, `Codex CLI (${displayPath})`));
369
377
  }
370
378
 
379
+ interface KiroCliSocialToken {
380
+ access_token?: unknown;
381
+ refresh_token?: unknown;
382
+ expires_at?: unknown;
383
+ profile_arn?: unknown;
384
+ provider?: unknown;
385
+ }
386
+
387
+ function parseKiroCliExpiry(value: unknown): number | undefined {
388
+ if (typeof value === "number" && Number.isFinite(value)) {
389
+ if (value > 1_000_000_000_000) return value;
390
+ if (value > 1_000_000_000) return value * 1000;
391
+ return undefined;
392
+ }
393
+ if (typeof value !== "string" || value.trim().length === 0) return undefined;
394
+ const numericValue = Number(value);
395
+ if (Number.isFinite(numericValue)) return parseKiroCliExpiry(numericValue);
396
+ const parsed = Date.parse(value);
397
+ return Number.isFinite(parsed) ? parsed : undefined;
398
+ }
399
+
400
+ function parseKiroCliSocialToken(raw: string, source: string): ImportableCredential | SkippedCredential {
401
+ let parsed: unknown;
402
+ try {
403
+ parsed = JSON.parse(raw) as KiroCliSocialToken;
404
+ } catch (err) {
405
+ return { origin: "kiro-cli-social", source, reason: sanitizedFailureReason("malformed credential file", err) };
406
+ }
407
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
408
+ return { origin: "kiro-cli-social", source, reason: "unsupported token shape (root is not an object)" };
409
+ }
410
+ const token = parsed as KiroCliSocialToken;
411
+ const access = nonEmptyString(token.access_token);
412
+ const refresh = nonEmptyString(token.refresh_token);
413
+ const profileArn = nonEmptyString(token.profile_arn);
414
+ const provider = nonEmptyString(token.provider);
415
+ if (!access || !refresh || !profileArn || !provider) {
416
+ return { origin: "kiro-cli-social", source, reason: "incomplete Kiro social OAuth token metadata" };
417
+ }
418
+ const expiresAt = parseKiroCliExpiry(token.expires_at);
419
+ const credential: OAuthCredential = {
420
+ type: "oauth",
421
+ access,
422
+ refresh,
423
+ expires: expiresAt ?? Date.now(),
424
+ profileArn,
425
+ };
426
+ return {
427
+ provider: "kiro",
428
+ origin: "kiro-cli-social",
429
+ source,
430
+ kind: "oauth",
431
+ ...(expiresAt === undefined ? {} : { expiresAt }),
432
+ redactedToken: redactSecret(access),
433
+ credential,
434
+ };
435
+ }
436
+
437
+ function resolveKiroCliDatabasePath(
438
+ homeDir: string,
439
+ platform: NodeJS.Platform,
440
+ env: Record<string, string | undefined>,
441
+ ): string {
442
+ if (platform === "darwin") {
443
+ return path.join(homeDir, "Library", "Application Support", "kiro-cli", "data.sqlite3");
444
+ }
445
+ if (platform === "win32") {
446
+ const localAppData = nonEmptyString(env.LOCALAPPDATA);
447
+ const dataDir =
448
+ localAppData && path.isAbsolute(localAppData) ? localAppData : path.join(homeDir, "AppData", "Local");
449
+ return path.join(dataDir, "kiro-cli", "data.sqlite3");
450
+ }
451
+ const xdgDataHome = nonEmptyString(env.XDG_DATA_HOME);
452
+ const dataDir = xdgDataHome && path.isAbsolute(xdgDataHome) ? xdgDataHome : path.join(homeDir, ".local", "share");
453
+ return path.join(dataDir, "kiro-cli", "data.sqlite3");
454
+ }
455
+
456
+ async function discoverKiroCliSocialCredential(
457
+ homeDir: string,
458
+ platform: NodeJS.Platform,
459
+ pathEnv: Record<string, string | undefined>,
460
+ databasePathOverride: string | undefined,
461
+ result: CredentialDiscoveryResult,
462
+ ): Promise<void> {
463
+ const source = "Kiro CLI (social login)";
464
+ if (databasePathOverride && !path.isAbsolute(databasePathOverride)) {
465
+ result.skipped.push({ origin: "kiro-cli-social", source, reason: "Kiro CLI database path must be absolute" });
466
+ return;
467
+ }
468
+ const databasePath = databasePathOverride ?? resolveKiroCliDatabasePath(homeDir, platform, pathEnv);
469
+ let database: Database | undefined;
470
+ try {
471
+ const stat = await fs.stat(databasePath);
472
+ if (!stat.isFile()) {
473
+ result.skipped.push({ origin: "kiro-cli-social", source, reason: "Kiro CLI database is not a regular file" });
474
+ return;
475
+ }
476
+ } catch (err) {
477
+ if (!isEnoent(err)) {
478
+ result.skipped.push({
479
+ origin: "kiro-cli-social",
480
+ source,
481
+ reason: sanitizedFailureReason("unreadable credential file", err),
482
+ });
483
+ }
484
+ return;
485
+ }
486
+
487
+ try {
488
+ database = new Database(databasePath, { readonly: true, create: false, strict: true });
489
+ database.run("PRAGMA busy_timeout = 1000");
490
+ const authTable = database
491
+ .prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?")
492
+ .get("auth_kv");
493
+ if (!authTable) {
494
+ result.skipped.push({ origin: "kiro-cli-social", source, reason: "Kiro CLI database is missing auth_kv" });
495
+ return;
496
+ }
497
+ const row = database.prepare("SELECT value FROM auth_kv WHERE key = ?").get(KIRO_CLI_SOCIAL_TOKEN_KEY) as {
498
+ value?: unknown;
499
+ } | null;
500
+ if (!row) return;
501
+ const value =
502
+ typeof row.value === "string"
503
+ ? row.value
504
+ : row.value instanceof Uint8Array
505
+ ? new TextDecoder().decode(row.value)
506
+ : undefined;
507
+ if (value === undefined) {
508
+ result.skipped.push({
509
+ origin: "kiro-cli-social",
510
+ source,
511
+ reason: "Kiro CLI token value has an unsupported type",
512
+ });
513
+ return;
514
+ }
515
+ pushOutcome(result, parseKiroCliSocialToken(value, source));
516
+ } catch (err) {
517
+ result.skipped.push({
518
+ origin: "kiro-cli-social",
519
+ source,
520
+ reason: sanitizedFailureReason("unreadable credential file", err),
521
+ });
522
+ } finally {
523
+ database?.close();
524
+ }
525
+ }
526
+
371
527
  // ─── Environment hints ───────────────────────────────────────────────────────
372
528
 
373
529
  function discoverEnvironment(env: Record<string, string | undefined>, result: CredentialDiscoveryResult): void {
@@ -421,8 +577,8 @@ function resolveExternalDir(
421
577
  }
422
578
 
423
579
  /**
424
- * Discover Claude Code and Codex CLI credentials across files, the macOS
425
- * Keychain, and environment variables. Never throws for individual unreadable or
580
+ * Discover Claude Code, Codex CLI, and Kiro CLI credentials across their local
581
+ * stores and environment variables. Never throws for individual unreadable or
426
582
  * malformed sources — those land in {@link CredentialDiscoveryResult.skipped}.
427
583
  */
428
584
  export async function discoverExternalCredentials(options: DiscoveryOptions = {}): Promise<CredentialDiscoveryResult> {
@@ -436,11 +592,16 @@ export async function discoverExternalCredentials(options: DiscoveryOptions = {}
436
592
  ? { dir: options.codexHome, display: "$CODEX_HOME" }
437
593
  : resolveExternalDir("CODEX_HOME", options.env, path.join(homeDir, ".codex"), "~/.codex");
438
594
  const result: CredentialDiscoveryResult = { importable: [], skipped: [], environment: [] };
595
+ const kiroPathEnv = options.env ?? {
596
+ LOCALAPPDATA: $credentialEnv("LOCALAPPDATA"),
597
+ XDG_DATA_HOME: $credentialEnv("XDG_DATA_HOME"),
598
+ };
439
599
  await discoverClaudeCode(
440
600
  { configDir: claudeConfigDir, platform, readClaudeKeychain: options.readClaudeKeychain },
441
601
  result,
442
602
  );
443
603
  await discoverCodex(codexHome, result);
604
+ await discoverKiroCliSocialCredential(homeDir, platform, kiroPathEnv, options.kiroCliDatabasePath, result);
444
605
  discoverEnvironment(env, result);
445
606
  return result;
446
607
  }
@@ -487,6 +648,16 @@ function hasAutoImportOAuthProviderOrigin(credential: ImportableCredential): boo
487
648
  }
488
649
 
489
650
  export function isAutoImportOAuthCredential(credential: ImportableCredential, now: number = Date.now()): boolean {
651
+ const refreshableKiroSocialCredential =
652
+ credential.provider === "kiro" &&
653
+ credential.origin === "kiro-cli-social" &&
654
+ credential.kind === "oauth" &&
655
+ credential.credential.type === "oauth" &&
656
+ credential.credential.access.length > 0 &&
657
+ credential.credential.refresh.length > 0 &&
658
+ typeof credential.credential.profileArn === "string" &&
659
+ credential.credential.profileArn.length > 0;
660
+ if (refreshableKiroSocialCredential) return true;
490
661
  return (
491
662
  hasAutoImportOAuthProviderOrigin(credential) &&
492
663
  typeof credential.expiresAt === "number" &&
@@ -152,7 +152,12 @@ export function parseDaemonListen(raw: string): PaseoDaemonTarget | undefined {
152
152
  const withoutQuery = authority.split("?")[0] ?? "";
153
153
  const separator = withoutQuery.lastIndexOf(":");
154
154
  if (separator <= 0) return undefined;
155
- const port = Number(withoutQuery.slice(separator + 1));
155
+ // Digits only, like the bare-port branch above: `Number()` also accepts hex
156
+ // (`0x1A0B`), exponents (`1e3`), decimals and padding, which would probe a
157
+ // different port than the raw spelling handed to `paseo import`.
158
+ const portText = withoutQuery.slice(separator + 1);
159
+ if (!/^\d+$/.test(portText)) return undefined;
160
+ const port = Number(portText);
156
161
  if (!Number.isSafeInteger(port) || port < 1 || port > 65_535) return undefined;
157
162
  const host = withoutQuery.slice(0, separator).replace(/^\[|]$/g, "");
158
163
  return host ? { kind: "tcp", host, port } : undefined;