@gajae-code/coding-agent 0.18.5 → 0.18.6

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 (91) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/types/cli-commands.d.ts +10 -0
  3. package/dist/types/cli-ordinary.d.ts +13 -0
  4. package/dist/types/cli.d.ts +12 -3
  5. package/dist/types/commands/contribution-prep.d.ts +0 -3
  6. package/dist/types/commands/sdk.d.ts +3 -0
  7. package/dist/types/commands/update.d.ts +1 -0
  8. package/dist/types/config/model-profile-activation.d.ts +19 -0
  9. package/dist/types/coordinator-mcp/session-reaper.d.ts +5 -0
  10. package/dist/types/edit/modes/replace.d.ts +3 -3
  11. package/dist/types/edit/streaming.d.ts +2 -2
  12. package/dist/types/exec/bash-shell-supervisor.d.ts +12 -0
  13. package/dist/types/sdk/broker/discovery.d.ts +8 -0
  14. package/dist/types/sdk/broker/ensure.d.ts +1 -0
  15. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +4 -0
  16. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  17. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
  18. package/dist/types/sdk/bus/telegram-daemon.d.ts +1 -0
  19. package/dist/types/sdk/cli/diagnostics-cli.d.ts +18 -0
  20. package/dist/types/sdk/diagnostics/observe-broker.d.ts +185 -0
  21. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  22. package/dist/types/sdk/index.d.ts +1 -0
  23. package/dist/types/sdk/router/session-router.d.ts +2 -0
  24. package/dist/types/sdk/session.d.ts +13 -0
  25. package/dist/types/session/agent-session.d.ts +5 -1
  26. package/dist/types/tools/ask-contract.d.ts +75 -254
  27. package/dist/types/tools/bash.d.ts +1 -1
  28. package/package.json +7 -7
  29. package/scripts/build-sdk-package-smoke.ts +5 -0
  30. package/src/cli/public-command-entry.ts +5 -0
  31. package/src/cli/ssh-cli.ts +6 -3
  32. package/src/cli/web-search-cli.ts +9 -3
  33. package/src/cli-commands.ts +14 -0
  34. package/src/cli-ordinary.ts +197 -0
  35. package/src/cli.ts +25 -182
  36. package/src/commands/contribution-prep.ts +1 -3
  37. package/src/commands/sdk.ts +59 -0
  38. package/src/commands/update.ts +15 -1
  39. package/src/config/file-lock.ts +91 -2
  40. package/src/config/model-profile-activation.ts +70 -4
  41. package/src/config/model-profile-contract.ts +4 -1
  42. package/src/config/model-profiles.ts +23 -31
  43. package/src/config/model-resolver.ts +9 -1
  44. package/src/coordinator-mcp/event-webhook.ts +19 -14
  45. package/src/coordinator-mcp/policy.ts +14 -4
  46. package/src/coordinator-mcp/server.ts +142 -7
  47. package/src/coordinator-mcp/session-reaper.ts +9 -1
  48. package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
  49. package/src/edit/modes/replace.ts +6 -6
  50. package/src/edit/streaming.ts +15 -15
  51. package/src/exec/bash-shell-supervisor.ts +60 -3
  52. package/src/internal-urls/docs-index.generated.ts +10 -9
  53. package/src/memories/index.ts +8 -2
  54. package/src/modes/acp/acp-agent.ts +649 -367
  55. package/src/modes/components/tool-execution.ts +1 -1
  56. package/src/prompts/tools/ask.md +2 -0
  57. package/src/sdk/broker/broker.ts +46 -0
  58. package/src/sdk/broker/daemon-entry.ts +67 -6
  59. package/src/sdk/broker/discovery.ts +8 -0
  60. package/src/sdk/broker/ensure.ts +156 -20
  61. package/src/sdk/broker/lifecycle-ledger.ts +110 -12
  62. package/src/sdk/broker/lifecycle.ts +225 -341
  63. package/src/sdk/broker/runtime.ts +5 -1
  64. package/src/sdk/broker/transport.ts +5 -1
  65. package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
  66. package/src/sdk/bus/telegram-daemon-control.ts +15 -12
  67. package/src/sdk/bus/telegram-daemon.ts +34 -1
  68. package/src/sdk/cli/diagnostics-cli.ts +247 -0
  69. package/src/sdk/diagnostics/observe-broker.ts +654 -0
  70. package/src/sdk/host/control/dispatch.ts +52 -4
  71. package/src/sdk/host/control/operations.ts +1 -1
  72. package/src/sdk/host/session-runtime.test.ts +40 -2
  73. package/src/sdk/host/session-runtime.ts +13 -5
  74. package/src/sdk/index.ts +1 -0
  75. package/src/sdk/lifecycle-session.ts +1 -0
  76. package/src/sdk/protocol/operation-registry.ts +1 -1
  77. package/src/sdk/router/session-router.ts +7 -1
  78. package/src/sdk/session.ts +37 -8
  79. package/src/session/agent-session.ts +114 -39
  80. package/src/session/blob-store.ts +78 -33
  81. package/src/session/internal/managed-session-storage.ts +96 -3
  82. package/src/setup/hermes/templates/operator-instructions.v1.md +19 -1
  83. package/src/setup/hermes-setup.ts +4 -1
  84. package/src/slash-commands/builtin-registry.ts +8 -5
  85. package/src/tools/ask-contract.test.ts +76 -1
  86. package/src/tools/ask-contract.ts +57 -6
  87. package/src/tools/ask.ts +16 -7
  88. package/src/tools/bash.ts +38 -29
  89. package/src/tools/descriptors.test.ts +29 -0
  90. package/src/tools/tool-catalog.generated.ts +7 -4
  91. package/src/web/search/index.ts +2 -2
@@ -1111,7 +1111,11 @@ export declare class AgentSession {
1111
1111
  get sessionWorkLease(): SessionWorkLease;
1112
1112
  /** Stable resource ownership identifier for the active prompt run. */
1113
1113
  get activePromptHandle(): string | undefined;
1114
- /** All messages including custom types like BashExecutionMessage */
1114
+ /**
1115
+ * All messages including custom types like BashExecutionMessage. Request-scoped
1116
+ * ephemeral copies are retained only in `agent.state.messages` to keep the provider
1117
+ * cache prefix stable; they are never part of this public view.
1118
+ */
1115
1119
  get messages(): AgentMessage[];
1116
1120
  get transcriptPromptGeneration(): number;
1117
1121
  static restoreFromMemoryGuardCheckpoint(input: AgentSessionMemoryGuardRestoreInput): Promise<AgentMemoryGuardRestoreResult>;
@@ -267,133 +267,6 @@ export declare const topologyAskSchema: z.ZodObject<{
267
267
  }, z.core.$strip>>;
268
268
  multi: z.ZodOptional<z.ZodBoolean>;
269
269
  recommended: z.ZodOptional<z.ZodNumber>;
270
- deepInterview: z.ZodOptional<z.ZodType<{
271
- round_id?: string | undefined;
272
- ambiguity: number;
273
- confused_terms?: string[] | undefined;
274
- references?: {
275
- reference_id: string;
276
- label: string;
277
- origin: string;
278
- url?: string | undefined;
279
- excerpt?: string | undefined;
280
- }[] | undefined;
281
- round: number;
282
- component: "review-topology";
283
- dimension: "topology";
284
- intent_contract: {
285
- items: {
286
- id: string;
287
- category: "artifact" | "constraint" | "integration" | "surface";
288
- statement: string;
289
- }[];
290
- confirmation_options: string[];
291
- };
292
- } | {
293
- round_id?: string | undefined;
294
- component: string;
295
- dimension: string;
296
- ambiguity: number;
297
- confused_terms?: string[] | undefined;
298
- references?: {
299
- reference_id: string;
300
- label: string;
301
- origin: string;
302
- url?: string | undefined;
303
- excerpt?: string | undefined;
304
- }[] | undefined;
305
- round: number;
306
- } | {
307
- round_id?: string | undefined;
308
- component: string;
309
- dimension: string;
310
- ambiguity: number;
311
- confused_terms?: string[] | undefined;
312
- references?: {
313
- reference_id: string;
314
- label: string;
315
- origin: string;
316
- url?: string | undefined;
317
- excerpt?: string | undefined;
318
- }[] | undefined;
319
- round: number;
320
- intent_review: {
321
- observed_items: {
322
- id: string;
323
- category: "artifact" | "constraint" | "integration" | "surface";
324
- statement: string;
325
- }[];
326
- supporting_substitutions: {
327
- removed_id: string;
328
- replacement_ids: string[];
329
- rationale: string;
330
- }[];
331
- approval_options: string[];
332
- };
333
- }, unknown, z.core.$ZodTypeInternals<{
334
- round_id?: string | undefined;
335
- ambiguity: number;
336
- confused_terms?: string[] | undefined;
337
- references?: {
338
- reference_id: string;
339
- label: string;
340
- origin: string;
341
- url?: string | undefined;
342
- excerpt?: string | undefined;
343
- }[] | undefined;
344
- round: number;
345
- component: "review-topology";
346
- dimension: "topology";
347
- intent_contract: {
348
- items: {
349
- id: string;
350
- category: "artifact" | "constraint" | "integration" | "surface";
351
- statement: string;
352
- }[];
353
- confirmation_options: string[];
354
- };
355
- } | {
356
- round_id?: string | undefined;
357
- component: string;
358
- dimension: string;
359
- ambiguity: number;
360
- confused_terms?: string[] | undefined;
361
- references?: {
362
- reference_id: string;
363
- label: string;
364
- origin: string;
365
- url?: string | undefined;
366
- excerpt?: string | undefined;
367
- }[] | undefined;
368
- round: number;
369
- } | {
370
- round_id?: string | undefined;
371
- component: string;
372
- dimension: string;
373
- ambiguity: number;
374
- confused_terms?: string[] | undefined;
375
- references?: {
376
- reference_id: string;
377
- label: string;
378
- origin: string;
379
- url?: string | undefined;
380
- excerpt?: string | undefined;
381
- }[] | undefined;
382
- round: number;
383
- intent_review: {
384
- observed_items: {
385
- id: string;
386
- category: "artifact" | "constraint" | "integration" | "surface";
387
- statement: string;
388
- }[];
389
- supporting_substitutions: {
390
- removed_id: string;
391
- replacement_ids: string[];
392
- rationale: string;
393
- }[];
394
- approval_options: string[];
395
- };
396
- }, unknown>>>;
397
270
  workflowGate: z.ZodOptional<z.ZodObject<{
398
271
  stage: z.ZodEnum<{
399
272
  "deep-interview": "deep-interview";
@@ -406,6 +279,34 @@ export declare const topologyAskSchema: z.ZodObject<{
406
279
  question: "question";
407
280
  }>;
408
281
  }, z.core.$strip>>;
282
+ deepInterview: z.ZodObject<{
283
+ round_id: z.ZodOptional<z.ZodString>;
284
+ ambiguity: z.ZodNumber;
285
+ confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
286
+ references: z.ZodOptional<z.ZodArray<z.ZodObject<{
287
+ reference_id: z.ZodString;
288
+ label: z.ZodString;
289
+ origin: z.ZodString;
290
+ url: z.ZodOptional<z.ZodString>;
291
+ excerpt: z.ZodOptional<z.ZodString>;
292
+ }, z.core.$strict>>>;
293
+ round: z.ZodNumber;
294
+ component: z.ZodLiteral<"review-topology">;
295
+ dimension: z.ZodLiteral<"topology">;
296
+ intent_contract: z.ZodObject<{
297
+ items: z.ZodArray<z.ZodObject<{
298
+ id: z.ZodString;
299
+ category: z.ZodEnum<{
300
+ artifact: "artifact";
301
+ constraint: "constraint";
302
+ integration: "integration";
303
+ surface: "surface";
304
+ }>;
305
+ statement: z.ZodString;
306
+ }, z.core.$strict>>;
307
+ confirmation_options: z.ZodArray<z.ZodString>;
308
+ }, z.core.$strict>;
309
+ }, z.core.$strict>;
409
310
  }, z.core.$strip>>;
410
311
  }, z.core.$strip>;
411
312
  export declare const postTopologyAskSchema: z.ZodObject<{
@@ -417,133 +318,6 @@ export declare const postTopologyAskSchema: z.ZodObject<{
417
318
  }, z.core.$strip>>;
418
319
  multi: z.ZodOptional<z.ZodBoolean>;
419
320
  recommended: z.ZodOptional<z.ZodNumber>;
420
- deepInterview: z.ZodOptional<z.ZodType<{
421
- round_id?: string | undefined;
422
- ambiguity: number;
423
- confused_terms?: string[] | undefined;
424
- references?: {
425
- reference_id: string;
426
- label: string;
427
- origin: string;
428
- url?: string | undefined;
429
- excerpt?: string | undefined;
430
- }[] | undefined;
431
- round: number;
432
- component: "review-topology";
433
- dimension: "topology";
434
- intent_contract: {
435
- items: {
436
- id: string;
437
- category: "artifact" | "constraint" | "integration" | "surface";
438
- statement: string;
439
- }[];
440
- confirmation_options: string[];
441
- };
442
- } | {
443
- round_id?: string | undefined;
444
- component: string;
445
- dimension: string;
446
- ambiguity: number;
447
- confused_terms?: string[] | undefined;
448
- references?: {
449
- reference_id: string;
450
- label: string;
451
- origin: string;
452
- url?: string | undefined;
453
- excerpt?: string | undefined;
454
- }[] | undefined;
455
- round: number;
456
- } | {
457
- round_id?: string | undefined;
458
- component: string;
459
- dimension: string;
460
- ambiguity: number;
461
- confused_terms?: string[] | undefined;
462
- references?: {
463
- reference_id: string;
464
- label: string;
465
- origin: string;
466
- url?: string | undefined;
467
- excerpt?: string | undefined;
468
- }[] | undefined;
469
- round: number;
470
- intent_review: {
471
- observed_items: {
472
- id: string;
473
- category: "artifact" | "constraint" | "integration" | "surface";
474
- statement: string;
475
- }[];
476
- supporting_substitutions: {
477
- removed_id: string;
478
- replacement_ids: string[];
479
- rationale: string;
480
- }[];
481
- approval_options: string[];
482
- };
483
- }, unknown, z.core.$ZodTypeInternals<{
484
- round_id?: string | undefined;
485
- ambiguity: number;
486
- confused_terms?: string[] | undefined;
487
- references?: {
488
- reference_id: string;
489
- label: string;
490
- origin: string;
491
- url?: string | undefined;
492
- excerpt?: string | undefined;
493
- }[] | undefined;
494
- round: number;
495
- component: "review-topology";
496
- dimension: "topology";
497
- intent_contract: {
498
- items: {
499
- id: string;
500
- category: "artifact" | "constraint" | "integration" | "surface";
501
- statement: string;
502
- }[];
503
- confirmation_options: string[];
504
- };
505
- } | {
506
- round_id?: string | undefined;
507
- component: string;
508
- dimension: string;
509
- ambiguity: number;
510
- confused_terms?: string[] | undefined;
511
- references?: {
512
- reference_id: string;
513
- label: string;
514
- origin: string;
515
- url?: string | undefined;
516
- excerpt?: string | undefined;
517
- }[] | undefined;
518
- round: number;
519
- } | {
520
- round_id?: string | undefined;
521
- component: string;
522
- dimension: string;
523
- ambiguity: number;
524
- confused_terms?: string[] | undefined;
525
- references?: {
526
- reference_id: string;
527
- label: string;
528
- origin: string;
529
- url?: string | undefined;
530
- excerpt?: string | undefined;
531
- }[] | undefined;
532
- round: number;
533
- intent_review: {
534
- observed_items: {
535
- id: string;
536
- category: "artifact" | "constraint" | "integration" | "surface";
537
- statement: string;
538
- }[];
539
- supporting_substitutions: {
540
- removed_id: string;
541
- replacement_ids: string[];
542
- rationale: string;
543
- }[];
544
- approval_options: string[];
545
- };
546
- }, unknown>>>;
547
321
  workflowGate: z.ZodOptional<z.ZodObject<{
548
322
  stage: z.ZodEnum<{
549
323
  "deep-interview": "deep-interview";
@@ -556,6 +330,53 @@ export declare const postTopologyAskSchema: z.ZodObject<{
556
330
  question: "question";
557
331
  }>;
558
332
  }, z.core.$strip>>;
333
+ deepInterview: z.ZodUnion<readonly [z.ZodObject<{
334
+ round_id: z.ZodOptional<z.ZodString>;
335
+ component: z.ZodString;
336
+ dimension: z.ZodString;
337
+ ambiguity: z.ZodNumber;
338
+ confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
339
+ references: z.ZodOptional<z.ZodArray<z.ZodObject<{
340
+ reference_id: z.ZodString;
341
+ label: z.ZodString;
342
+ origin: z.ZodString;
343
+ url: z.ZodOptional<z.ZodString>;
344
+ excerpt: z.ZodOptional<z.ZodString>;
345
+ }, z.core.$strict>>>;
346
+ round: z.ZodNumber;
347
+ }, z.core.$strict>, z.ZodObject<{
348
+ round_id: z.ZodOptional<z.ZodString>;
349
+ component: z.ZodString;
350
+ dimension: z.ZodString;
351
+ ambiguity: z.ZodNumber;
352
+ confused_terms: z.ZodOptional<z.ZodArray<z.ZodString>>;
353
+ references: z.ZodOptional<z.ZodArray<z.ZodObject<{
354
+ reference_id: z.ZodString;
355
+ label: z.ZodString;
356
+ origin: z.ZodString;
357
+ url: z.ZodOptional<z.ZodString>;
358
+ excerpt: z.ZodOptional<z.ZodString>;
359
+ }, z.core.$strict>>>;
360
+ round: z.ZodNumber;
361
+ intent_review: z.ZodObject<{
362
+ observed_items: z.ZodArray<z.ZodObject<{
363
+ id: z.ZodString;
364
+ category: z.ZodEnum<{
365
+ artifact: "artifact";
366
+ constraint: "constraint";
367
+ integration: "integration";
368
+ surface: "surface";
369
+ }>;
370
+ statement: z.ZodString;
371
+ }, z.core.$strict>>;
372
+ supporting_substitutions: z.ZodArray<z.ZodObject<{
373
+ removed_id: z.ZodString;
374
+ replacement_ids: z.ZodArray<z.ZodString>;
375
+ rationale: z.ZodString;
376
+ }, z.core.$strict>>;
377
+ approval_options: z.ZodArray<z.ZodString>;
378
+ }, z.core.$strict>;
379
+ }, z.core.$strict>]>;
559
380
  }, z.core.$strip>>;
560
381
  }, z.core.$strip>;
561
382
  export declare const ordinaryAskSchema: z.ZodObject<{
@@ -10,7 +10,7 @@ import type { ToolSession } from ".";
10
10
  import { type OutputMeta } from "./output-meta";
11
11
  export { STEER_FOLD_GRACE_MS, steerFoldReasonLine } from "./steer-fold";
12
12
  export declare const BASH_DEFAULT_PREVIEW_LINES = 10;
13
- export declare const MANAGED_OWNER_BASH_ENV: readonly ["GJC_TMUX_OWNER_STATE_DIR", "GJC_TMUX_OWNER_GENERATION", "GJC_MANAGED_OWNER_RUN_ID", "GJC_MANAGED_OWNER_INCARNATION", "GJC_MANAGED_OWNER_CHILD_TOKEN", "GJC_MANAGED_OWNER_PREDECESSOR_TOKEN", "GJC_MANAGED_OWNER_PREDECESSOR_GENERATION", "GJC_MANAGED_OWNER_PREDECESSOR_RUN_ID", "GJC_MANAGED_OWNER_PREDECESSOR_INCARNATION", "GJC_MANAGED_OWNER_TRANSCRIPT_PATH", "GJC_TMUX_OWNER_SERVER_KEY", "GJC_TMUX_LAUNCHED"];
13
+ export declare const MANAGED_OWNER_BASH_ENV: readonly ["GJC_TMUX_OWNER_STATE_DIR", "GJC_TMUX_OWNER_GENERATION", "GJC_MANAGED_OWNER_RUN_ID", "GJC_MANAGED_OWNER_INCARNATION", "GJC_MANAGED_OWNER_CHILD_TOKEN", "GJC_MANAGED_OWNER_COMMAND_JSON", "GJC_MANAGED_OWNER_REDACT_COMMAND", "GJC_MANAGED_OWNER_PREDECESSOR_TOKEN", "GJC_MANAGED_OWNER_PREDECESSOR_GENERATION", "GJC_MANAGED_OWNER_PREDECESSOR_RUN_ID", "GJC_MANAGED_OWNER_PREDECESSOR_INCARNATION", "GJC_MANAGED_OWNER_TRANSCRIPT_PATH", "GJC_TMUX_OWNER_SERVER_KEY", "GJC_TMUX_LAUNCHED"];
14
14
  export type BashOriginalArtifactSaveResult = BashArtifactSaveResult;
15
15
  /**
16
16
  * Lift a leading `cd <dir> &&` into the tool cwd only when `<dir>` is exactly
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/coding-agent",
4
- "version": "0.18.5",
4
+ "version": "0.18.6",
5
5
  "description": "Gajae Code CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://gajae-code.com",
7
7
  "author": "Yeachan-Heo and Gajae Code Contributors",
@@ -57,12 +57,12 @@
57
57
  "@agentclientprotocol/sdk": "1.3.0",
58
58
  "@babel/parser": "^7.29.3",
59
59
  "@mozilla/readability": "^0.6.0",
60
- "@gajae-code/stats": "0.18.5",
61
- "@gajae-code/agent-core": "0.18.5",
62
- "@gajae-code/ai": "0.18.5",
63
- "@gajae-code/natives": "0.18.5",
64
- "@gajae-code/tui": "0.18.5",
65
- "@gajae-code/utils": "0.18.5",
60
+ "@gajae-code/stats": "0.18.6",
61
+ "@gajae-code/agent-core": "0.18.6",
62
+ "@gajae-code/ai": "0.18.6",
63
+ "@gajae-code/natives": "0.18.6",
64
+ "@gajae-code/tui": "0.18.6",
65
+ "@gajae-code/utils": "0.18.6",
66
66
  "@puppeteer/browsers": "^2.13.0",
67
67
  "@types/turndown": "5.0.6",
68
68
  "@xterm/headless": "^6.0.0",
@@ -12,6 +12,7 @@ const tuiPackageDir = path.resolve(packageDir, "../tui");
12
12
  const nativesPackageDir = path.resolve(packageDir, "../natives");
13
13
  const linuxX64PackageDir = path.resolve(packageDir, "../natives-linux-x64");
14
14
  const utilsPackageDir = path.resolve(packageDir, "../utils");
15
+ const statsPackageDir = path.resolve(packageDir, "../stats");
15
16
  const manifestsDir = path.join(packageDir, "test/manifests");
16
17
  // v2 intentionally removes eager concrete-tool exports to preserve the SDK cold boundary.
17
18
  const baselineVersion = 2;
@@ -51,6 +52,7 @@ async function runSmoke(): Promise<Surface> {
51
52
  const nativesTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], nativesPackageDir);
52
53
  const linuxX64Tarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], stagedLinuxX64Dir);
53
54
  const utilsTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], utilsPackageDir);
55
+ const statsTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], statsPackageDir);
54
56
  const codingAgentTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], packageDir);
55
57
  const agentTarballPath = path.isAbsolute(agentTarball) ? agentTarball : path.join(agentPackageDir, agentTarball);
56
58
  const aiTarballPath = path.isAbsolute(aiTarball) ? aiTarball : path.join(aiPackageDir, aiTarball);
@@ -62,6 +64,7 @@ async function runSmoke(): Promise<Surface> {
62
64
  ? linuxX64Tarball
63
65
  : path.join(stagedLinuxX64Dir, linuxX64Tarball);
64
66
  const utilsTarballPath = path.isAbsolute(utilsTarball) ? utilsTarball : path.join(utilsPackageDir, utilsTarball);
67
+ const statsTarballPath = path.isAbsolute(statsTarball) ? statsTarball : path.join(statsPackageDir, statsTarball);
65
68
  const codingAgentTarballPath = path.isAbsolute(codingAgentTarball)
66
69
  ? codingAgentTarball
67
70
  : path.join(packageDir, codingAgentTarball);
@@ -79,6 +82,7 @@ async function runSmoke(): Promise<Surface> {
79
82
  "@gajae-code/natives": `file:${nativesTarballPath}`,
80
83
  "@gajae-code/natives-linux-x64": `file:${linuxX64TarballPath}`,
81
84
  "@gajae-code/utils": `file:${utilsTarballPath}`,
85
+ "@gajae-code/stats": `file:${statsTarballPath}`,
82
86
  },
83
87
  overrides: {
84
88
  "@gajae-code/agent-core": `file:${agentTarballPath}`,
@@ -87,6 +91,7 @@ async function runSmoke(): Promise<Surface> {
87
91
  "@gajae-code/natives": `file:${nativesTarballPath}`,
88
92
  "@gajae-code/natives-linux-x64": `file:${linuxX64TarballPath}`,
89
93
  "@gajae-code/utils": `file:${utilsTarballPath}`,
94
+ "@gajae-code/stats": `file:${statsTarballPath}`,
90
95
  },
91
96
  },
92
97
  null,
@@ -288,6 +288,11 @@ export function isSdkInternalArgv(argv: readonly string[]): boolean {
288
288
  return (
289
289
  (argv[0] === "session-host-internal" && argv.length === 1) ||
290
290
  (argv[0] === "broker-internal" &&
291
+ argv.length === 3 &&
292
+ argv[1] === "--agent-dir" &&
293
+ typeof argv[2] === "string" &&
294
+ isSafeSdkInternalAgentDir(argv[2])) ||
295
+ (argv[0] === "broker-trampoline-internal" &&
291
296
  argv.length === 3 &&
292
297
  argv[1] === "--agent-dir" &&
293
298
  typeof argv[2] === "string" &&
@@ -74,9 +74,12 @@ async function handleAdd(cmd: SSHCommandArgs): Promise<void> {
74
74
  return;
75
75
  }
76
76
 
77
- // Validate port if provided
77
+ // Validate port if provided. `Number.parseInt` accepts trailing garbage
78
+ // (parseInt("22oops") === 22, parseInt("2222.5") === 2222), so require
79
+ // the whole token to be digits before parsing.
80
+ let port: number | undefined;
78
81
  if (cmd.flags.port !== undefined) {
79
- const port = Number.parseInt(cmd.flags.port, 10);
82
+ port = /^\d+$/.test(cmd.flags.port) ? Number.parseInt(cmd.flags.port, 10) : Number.NaN;
80
83
  if (Number.isNaN(port) || port < 1 || port > 65535) {
81
84
  process.stdout.write(chalk.red("Error: Port must be an integer between 1 and 65535\n"));
82
85
  process.exitCode = 1;
@@ -86,7 +89,7 @@ async function handleAdd(cmd: SSHCommandArgs): Promise<void> {
86
89
 
87
90
  const hostConfig: SSHHostConfig = { host };
88
91
  if (cmd.flags.user) hostConfig.username = cmd.flags.user;
89
- if (cmd.flags.port) hostConfig.port = Number.parseInt(cmd.flags.port, 10);
92
+ if (port !== undefined) hostConfig.port = port;
90
93
  if (cmd.flags.key) hostConfig.keyPath = cmd.flags.key;
91
94
  if (cmd.flags.desc) hostConfig.description = cmd.flags.desc;
92
95
  if (cmd.flags.compat) hostConfig.compat = true;
@@ -95,7 +95,10 @@ export function parseSearchArgs(args: string[]): SearchCommandArgs | undefined {
95
95
  result.recency = value() as SearchCommandArgs["recency"];
96
96
  consumeSeparateValue();
97
97
  } else if (arg === "--limit" || arg === "-l") {
98
- result.limit = Number.parseInt(value(), 10);
98
+ const raw = value();
99
+ // `Number.parseInt` accepts trailing garbage ("5x" -> 5); leave
100
+ // anything that is not plain digits as NaN so it is rejected below.
101
+ result.limit = /^\d+$/.test(raw) ? Number.parseInt(raw, 10) : Number.NaN;
99
102
  consumeSeparateValue();
100
103
  } else if (arg === "--xai-mode") {
101
104
  result.xaiSearchMode = value() as SearchCommandArgs["xaiSearchMode"];
@@ -164,8 +167,11 @@ export async function runSearchCommand(cmd: SearchCommandArgs): Promise<void> {
164
167
  process.exit(1);
165
168
  }
166
169
 
167
- if (cmd.limit !== undefined && Number.isNaN(cmd.limit)) {
168
- process.stderr.write(`${chalk.red("Error: --limit must be a number")}\n`);
170
+ // `Flags.integer` accepts `0` and negative values; providers forward them
171
+ // as `num_results` and several slice sources with them (`slice(0, -3)`
172
+ // silently drops the last three results).
173
+ if (cmd.limit !== undefined && (!Number.isSafeInteger(cmd.limit) || cmd.limit < 1)) {
174
+ process.stderr.write(`${chalk.red("Error: --limit must be a positive integer")}\n`);
169
175
  process.exit(1);
170
176
  }
171
177
 
@@ -0,0 +1,14 @@
1
+ import type { CommandEntry } from "@gajae-code/utils/cli";
2
+
3
+ /**
4
+ * Public-family hooks kept available for private-worker tests without loading the
5
+ * full registry.
6
+ *
7
+ * This is the single shared array: the inert entry (`cli.ts`) and the ordinary
8
+ * dispatcher (`cli-ordinary.ts`) both re-export THIS object, so a test that
9
+ * mutates or injects an entry keeps affecting the dispatcher.
10
+ */
11
+ export const commands: CommandEntry[] = [
12
+ { name: "sdk", load: () => import("./commands/sdk").then(module => module.default) },
13
+ { name: "daemon", load: () => import("./commands/daemon").then(module => module.default) },
14
+ ];