praxis-agent 0.35.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +20 -2
  2. package/dist/application/background-agent-manager.d.ts +16 -6
  3. package/dist/application/background-agent-manager.js +139 -97
  4. package/dist/application/context-engine.d.ts +56 -0
  5. package/dist/application/context-engine.js +129 -0
  6. package/dist/application/durable-follow-up.d.ts +14 -0
  7. package/dist/application/durable-follow-up.js +52 -0
  8. package/dist/application/native-session-transcript.d.ts +72 -0
  9. package/dist/application/native-session-transcript.js +351 -0
  10. package/dist/application/native-sidechain-transcript.d.ts +34 -0
  11. package/dist/application/native-sidechain-transcript.js +156 -0
  12. package/dist/application/session-service.d.ts +23 -4
  13. package/dist/application/session-service.js +1130 -494
  14. package/dist/application/subagent-service.d.ts +5 -1
  15. package/dist/application/subagent-service.js +749 -320
  16. package/dist/application/team-agent-runtime.d.ts +29 -0
  17. package/dist/application/team-agent-runtime.js +169 -0
  18. package/dist/application/team-capability.d.ts +27 -0
  19. package/dist/application/team-capability.js +41 -0
  20. package/dist/application/team-lead-operations.d.ts +38 -0
  21. package/dist/application/team-lead-operations.js +155 -0
  22. package/dist/application/team-mailbox.d.ts +54 -0
  23. package/dist/application/team-mailbox.js +196 -0
  24. package/dist/application/team-manager.d.ts +113 -0
  25. package/dist/application/team-manager.js +681 -0
  26. package/dist/application/team-workspace.d.ts +29 -0
  27. package/dist/application/team-workspace.js +197 -0
  28. package/dist/application/top-level-agent-manager.d.ts +1 -0
  29. package/dist/application/top-level-agent-manager.js +1025 -403
  30. package/dist/application/transcript-projection.d.ts +35 -0
  31. package/dist/application/transcript-projection.js +139 -0
  32. package/dist/application/turn-lifecycle.d.ts +2 -0
  33. package/dist/application/turn-memory-coordinator.d.ts +43 -0
  34. package/dist/application/turn-memory-coordinator.js +98 -0
  35. package/dist/cli/agents-dashboard.js +10 -5
  36. package/dist/cli/interactive.d.ts +7 -0
  37. package/dist/cli/interactive.js +645 -334
  38. package/dist/cli/tui/claude-style.d.ts +8 -25
  39. package/dist/cli/tui/claude-style.js +299 -277
  40. package/dist/cli/tui/decision-surface-model.d.ts +71 -0
  41. package/dist/cli/tui/decision-surface-model.js +131 -0
  42. package/dist/cli/tui/decision-surface.d.ts +7 -0
  43. package/dist/cli/tui/decision-surface.js +41 -0
  44. package/dist/cli/tui/help-surface-model.d.ts +68 -0
  45. package/dist/cli/tui/help-surface-model.js +131 -0
  46. package/dist/cli/tui/mcp-panel.js +1 -2
  47. package/dist/cli/tui/permission-surface-model.d.ts +195 -0
  48. package/dist/cli/tui/permission-surface-model.js +360 -0
  49. package/dist/cli/tui/permission-surface.d.ts +7 -0
  50. package/dist/cli/tui/permission-surface.js +69 -0
  51. package/dist/cli/tui/presentation-environment.d.ts +32 -0
  52. package/dist/cli/tui/presentation-environment.js +149 -0
  53. package/dist/cli/tui/task-panel.js +10 -1
  54. package/dist/cli/tui/theme.d.ts +46 -3
  55. package/dist/cli/tui/theme.js +414 -56
  56. package/dist/cli/tui/tool-permission.js +16 -8
  57. package/dist/cli/tui/transcript-presentation.d.ts +19 -1
  58. package/dist/cli/tui/transcript-presentation.js +26 -6
  59. package/dist/cli/tui/transcript-viewport.d.ts +18 -0
  60. package/dist/cli/tui/transcript-viewport.js +517 -111
  61. package/dist/cli/tui/transcript-window-model.d.ts +108 -0
  62. package/dist/cli/tui/transcript-window-model.js +772 -0
  63. package/dist/cli/tui/tui-interaction-router.d.ts +78 -0
  64. package/dist/cli/tui/tui-interaction-router.js +127 -0
  65. package/dist/cli/tui/tui-screen-model.d.ts +114 -0
  66. package/dist/cli/tui/tui-screen-model.js +210 -0
  67. package/dist/cli/tui/tui-view-model.d.ts +2 -49
  68. package/dist/cli/tui/tui-view-model.js +1 -68
  69. package/dist/cli-runtime.d.ts +4 -2
  70. package/dist/cli-runtime.js +397 -32
  71. package/dist/compatibility/claude/transcript-codec.js +6 -0
  72. package/dist/core/agent-orchestration.d.ts +31 -0
  73. package/dist/core/agent-orchestration.js +235 -0
  74. package/dist/core/permission-policy.d.ts +4 -0
  75. package/dist/core/permission-policy.js +21 -0
  76. package/dist/core/runtime.d.ts +6 -0
  77. package/dist/core/runtime.js +20 -2
  78. package/dist/core/team-mailbox.d.ts +54 -0
  79. package/dist/core/team-mailbox.js +212 -0
  80. package/dist/core/team-ownership.d.ts +84 -0
  81. package/dist/core/team-ownership.js +505 -0
  82. package/dist/core/tool-execution-scheduler.js +6 -1
  83. package/dist/core/transcript-event.d.ts +5 -1
  84. package/dist/core/transcript-event.js +12 -0
  85. package/dist/persistence/claude-job-store.d.ts +58 -0
  86. package/dist/persistence/claude-job-store.js +483 -1
  87. package/dist/persistence/claude-transcript-store.d.ts +2 -1
  88. package/dist/persistence/claude-transcript-store.js +2 -10
  89. package/dist/persistence/native-team-mailbox.d.ts +68 -0
  90. package/dist/persistence/native-team-mailbox.js +542 -0
  91. package/dist/persistence/native-team-store.d.ts +34 -0
  92. package/dist/persistence/native-team-store.js +257 -0
  93. package/dist/persistence/native-transcript-reader.d.ts +53 -0
  94. package/dist/persistence/native-transcript-reader.js +283 -0
  95. package/dist/persistence/native-transcript-store.d.ts +69 -0
  96. package/dist/persistence/native-transcript-store.js +321 -0
  97. package/dist/persistence/subagent-lifecycle-store.d.ts +41 -8
  98. package/dist/persistence/subagent-lifecycle-store.js +373 -146
  99. package/dist/persistence/transcript-file-append.d.ts +2 -0
  100. package/dist/persistence/transcript-file-append.js +10 -0
  101. package/dist/platform/exclusive-file-lease.d.ts +3 -0
  102. package/dist/platform/exclusive-file-lease.js +3 -0
  103. package/dist/tools/claude-capabilities.d.ts +4 -0
  104. package/dist/tools/claude-capabilities.js +18 -2
  105. package/dist/tools/team-lead-tools.d.ts +19 -0
  106. package/dist/tools/team-lead-tools.js +479 -0
  107. package/dist/tools/team-member-tools.d.ts +21 -0
  108. package/dist/tools/team-member-tools.js +259 -0
  109. package/package.json +1 -1
  110. package/dist/cli/tui/fullscreen-renderer.d.ts +0 -14
  111. package/dist/cli/tui/fullscreen-renderer.js +0 -13
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { type ForkResult, type ManualCompactResult, type ManualCompactSelection, type RewindPoint, type SessionForkCheckpoint, type SessionInspection, type SessionRunResult, type SessionSummary, type SideQuestionForkResult, type SideQuestionResult } from './application/session-service.js';
3
+ import type { TeamLeadOperations } from './application/team-lead-operations.js';
3
4
  import type { ClaudeSessionCostSnapshot } from './application/session-cost-tracker.js';
4
5
  import { type AgentColorName, type AgentColorSelection } from './compatibility/claude/agent-color.js';
5
- import type { ClaudeDisplayTranscriptItem } from './compatibility/claude/projection.js';
6
+ import type { TranscriptDisplayItem } from './application/transcript-projection.js';
6
7
  import { type DataPlane } from './persistence/data-plane.js';
7
8
  import { type ModelDocument, type ModelImage, type ModelProvider, type ModelToolCall, type PermissionApproval, type PermissionDecision, type ToolRegistry, type RuntimeEventSink } from './core/runtime.js';
8
9
  import type { InteractiveResumeOptions, InteractiveServiceFactory } from './cli/interactive.js';
@@ -28,6 +29,7 @@ export interface CliIO {
28
29
  readStdinLines?: () => AsyncIterable<string | Uint8Array>;
29
30
  }
30
31
  interface SessionCommands {
32
+ teamLeadOperations?: TeamLeadOperations;
31
33
  toolRegistry?: ToolRegistry;
32
34
  run(prompt: string, signal?: AbortSignal, sessionId?: string, name?: string, images?: readonly ModelImage[], documents?: readonly ModelDocument[]): Promise<SessionRunResult>;
33
35
  resume(sessionId: string, prompt: string, signal?: AbortSignal, name?: string, images?: readonly ModelImage[], documents?: readonly ModelDocument[]): Promise<SessionRunResult>;
@@ -60,7 +62,7 @@ interface SessionCommands {
60
62
  registerResumePath?(path: string): Promise<SessionSummary>;
61
63
  inspect(sessionId: string): Promise<SessionInspection>;
62
64
  export(sessionId: string): Promise<Buffer>;
63
- transcript?(sessionId: string): Promise<ClaudeDisplayTranscriptItem[]>;
65
+ transcript?(sessionId: string): Promise<TranscriptDisplayItem[]>;
64
66
  costSnapshot?(sessionId: string): Promise<ClaudeSessionCostSnapshot>;
65
67
  compact?(sessionId: string, signal?: AbortSignal, selection?: ManualCompactSelection): Promise<ManualCompactResult>;
66
68
  rename?(sessionId: string, name: string): Promise<void>;
@@ -26,6 +26,7 @@ import { loadClaudeReleaseNotes } from './cli/tui/release-notes.js';
26
26
  import { canonicalClaudeCostModelName, formatCostSummary, } from './cli/tui/cost-summary.js';
27
27
  import { projectTuiHooks, } from './cli/tui/hook-settings.js';
28
28
  import { DEFAULT_CLI_CONTROLS, resolveCliControls } from './cli/controls.js';
29
+ import { PRAXIS_TEAM_TOOLS, resolveClaudeToolCapabilities, } from './tools/claude-capabilities.js';
29
30
  import { applyRuntimeSettingDefaults, loadRuntimeSettings, runtimeSettingsSystemPrompt, } from './cli/tui/runtime-settings.js';
30
31
  import { createCliDebugSink } from './cli/debug.js';
31
32
  import { ClaudePermissionResolver, } from './permissions/claude-permission-resolver.js';
@@ -160,6 +161,7 @@ Usage:
160
161
  praxis attach <agent-id>
161
162
  praxis logs <agent-id>
162
163
  praxis stop <agent-id>
164
+ praxis team <create|resume|list|accept|stop> ...
163
165
  praxis mcp <list|get|add|add-json|remove|reset-project-choices|login|logout|serve> ...
164
166
  praxis auto-mode <config|defaults|critique>
165
167
  praxis plugin|plugins <details|list|install|uninstall|enable|disable|update|init|prune|tag|validate|marketplace> ...
@@ -738,6 +740,15 @@ Options:
738
740
  --json Output a machine-readable result
739
741
  -h, --help Show help
740
742
  `;
743
+ const TEAM_HELP = `Usage: praxis team <command>
744
+
745
+ Commands:
746
+ create <manifest.json> --lead-session-id <id> [--json]
747
+ resume <team-id> --lead-session-id <id> [--json]
748
+ list [--json]
749
+ accept <team-id> <task-id> --lead-session-id <id> [--generation <n>] [--decision accepted|rejected] [--json]
750
+ stop <team-id> --lead-session-id <id> [--drain-ms <ms>] [--json]
751
+ `;
741
752
  export { parseContextEnvironment, parseProviderEnvironment };
742
753
  const consoleIO = {
743
754
  stdout: (message) => process.stdout.write(message),
@@ -788,6 +799,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
788
799
  const cwd = requestedCwd ?? process.cwd();
789
800
  const workspace = new WorkspaceContext(cwd);
790
801
  const dataPlane = controls.dataPlane ?? resolveDataPlane(runtimeEnvironment);
802
+ const experimentalNativeTranscriptWrites = /^(?:1|true|yes|on)$/iu.test((runtimeEnvironment.PRAXIS_EXPERIMENTAL_NATIVE_TRANSCRIPT_WRITES ?? '').trim());
791
803
  const configRoot = resolveDataPlaneRoot({
792
804
  dataPlane,
793
805
  ...(requestedConfigRoot === undefined ? {} : { root: requestedConfigRoot }),
@@ -812,6 +824,41 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
812
824
  ? {}
813
825
  : { permissionMode: interactivePermissionMode }),
814
826
  }, cwd);
827
+ if (experimentalNativeTranscriptWrites) {
828
+ const incompatible = [
829
+ ['dataPlane', dataPlane !== 'native'],
830
+ ['sessionPersistence', cli.sessionPersistence === false],
831
+ ['interactive', interactive],
832
+ ['simpleMode', !simpleMode],
833
+ ['sessionKind', sessionKind !== undefined],
834
+ ['name', cli.name !== undefined],
835
+ [
836
+ 'worktree',
837
+ cli.worktreeRequested === true || cli.worktreeName !== undefined,
838
+ ],
839
+ ['addDirectories', cli.additionalDirectories.length > 0],
840
+ ['fileResources', cli.fileResources.length > 0],
841
+ ['settings', cli.additionalSettings !== undefined],
842
+ ['settingSources', cli.settingSources !== undefined],
843
+ ['pluginDirectories', cli.pluginDirectories.length > 0],
844
+ ['pluginUrls', cli.pluginUrls.length > 0],
845
+ ['agent', agent !== undefined || cli.inlineAgents.length > 0],
846
+ ['mcp', cli.mcpConfigs.length > 0 || cli.strictMcpConfig],
847
+ [
848
+ 'checkpointing',
849
+ cli.rewindFiles !== undefined ||
850
+ /^(?:1|true|yes|on)$/iu.test((runtimeEnvironment.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING ?? '').trim()),
851
+ ],
852
+ [
853
+ 'teams',
854
+ /^(?:1|true|yes|on)$/iu.test((runtimeEnvironment.PRAXIS_ENABLE_TEAMS ?? '').trim()),
855
+ ],
856
+ ];
857
+ const active = incompatible.find(([, enabled]) => enabled);
858
+ if (active) {
859
+ throw new Error(`experimental native transcript writes incompatible with ${active[0]}`);
860
+ }
861
+ }
815
862
  const debug = cli.debug !== undefined || cli.debugFile !== undefined
816
863
  ? createCliDebugSink(eventSink, {
817
864
  cwd,
@@ -878,6 +925,9 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
878
925
  const options = {
879
926
  configRoot,
880
927
  dataPlane,
928
+ ...(experimentalNativeTranscriptWrites
929
+ ? { experimentalNativeTranscriptWrites: true }
930
+ : {}),
881
931
  cwd,
882
932
  claudeVersion,
883
933
  eventSink: runtimeEventSink,
@@ -901,10 +951,14 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
901
951
  : { maxBudgetUsd: cli.maxBudgetUsd }),
902
952
  pricing: ModelPricingRegistry.fromEnvironment(runtimeEnvironment.PRAXIS_PRICING_JSON),
903
953
  collectMetrics: true,
904
- ...(sessionMemoryProviderFactory ? { sessionMemoryProviderFactory } : {}),
905
- ...(sessionKind === undefined ? {} : { sessionKind }),
906
- workspace,
907
- ...(cli.worktreeRequested
954
+ ...(!experimentalNativeTranscriptWrites && sessionMemoryProviderFactory
955
+ ? { sessionMemoryProviderFactory }
956
+ : {}),
957
+ ...(!experimentalNativeTranscriptWrites && sessionKind !== undefined
958
+ ? { sessionKind }
959
+ : {}),
960
+ ...(!experimentalNativeTranscriptWrites ? { workspace } : {}),
961
+ ...(!experimentalNativeTranscriptWrites && cli.worktreeRequested
908
962
  ? {
909
963
  initialWorktree: true,
910
964
  ...(cli.worktreeName === undefined
@@ -912,7 +966,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
912
966
  : { initialWorktreeName: cli.worktreeName }),
913
967
  }
914
968
  : {}),
915
- ...(cli.fileResources.length > 0
969
+ ...(!experimentalNativeTranscriptWrites && cli.fileResources.length > 0
916
970
  ? {
917
971
  fileResources: cli.fileResources,
918
972
  fileResourceConfig: {
@@ -1375,6 +1429,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1375
1429
  'ScheduleWakeup',
1376
1430
  ];
1377
1431
  const workflowToolNames = ['Workflow'];
1432
+ const teamToolNames = PRAXIS_TEAM_TOOLS;
1378
1433
  const worktreeToolNames = ['EnterWorktree', 'ExitWorktree'];
1379
1434
  const interactiveToolNames = [
1380
1435
  'AskUserQuestion',
@@ -1403,6 +1458,18 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1403
1458
  cli.tools.includes('default') ||
1404
1459
  cli.tools.includes(name)) &&
1405
1460
  !cli.disallowedTools.includes(name));
1461
+ const teamEnabled = resolveClaudeToolCapabilities({
1462
+ role: 'main',
1463
+ interactive,
1464
+ simpleMode,
1465
+ env: runtimeEnvironment,
1466
+ }).has('TeamCreate');
1467
+ const selectedTeamTools = teamToolNames.filter((name) => teamEnabled &&
1468
+ !simpleMode &&
1469
+ (cli.tools === undefined ||
1470
+ cli.tools.includes('default') ||
1471
+ cli.tools.includes(name)) &&
1472
+ !cli.disallowedTools.includes(name));
1406
1473
  const selectedWorktreeTools = worktreeToolNames.filter((name) => !simpleMode &&
1407
1474
  (cli.tools === undefined ||
1408
1475
  cli.tools.includes('default') ||
@@ -1431,6 +1498,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1431
1498
  !taskToolNames.includes(name) &&
1432
1499
  !scheduledToolNames.includes(name) &&
1433
1500
  !workflowToolNames.includes(name) &&
1501
+ !teamToolNames.includes(name) &&
1434
1502
  !worktreeToolNames.includes(name) &&
1435
1503
  !interactiveToolNames.includes(name) &&
1436
1504
  (!simpleMode || (name !== 'WebFetch' && name !== 'WebSearch')));
@@ -1484,6 +1552,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1484
1552
  ...selectedTaskRuntimeTools,
1485
1553
  ...selectedScheduledTools,
1486
1554
  ...selectedWorkflowTools,
1555
+ ...selectedTeamTools,
1487
1556
  ...selectedWorktreeTools,
1488
1557
  ...selectedInteractiveTools,
1489
1558
  ...(enableSubagents ? selectedAgentTools : []),
@@ -1518,6 +1587,50 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1518
1587
  : {}),
1519
1588
  ...(simpleMode ? { bare: true } : {}),
1520
1589
  });
1590
+ const teamModules = teamEnabled
1591
+ ? await Promise.all([
1592
+ import('./application/team-capability.js'),
1593
+ import('./application/team-agent-runtime.js'),
1594
+ import('./application/team-lead-operations.js'),
1595
+ import('./tools/team-lead-tools.js'),
1596
+ ])
1597
+ : undefined;
1598
+ const teamCapability = teamModules
1599
+ ? new teamModules[0].LocalTeamCapability({
1600
+ nativeRoot: resolveDataPlaneRoot({
1601
+ dataPlane: 'native',
1602
+ environment: runtimeEnvironment,
1603
+ }),
1604
+ cwd: () => workspace.cwd(),
1605
+ maxConcurrent: teamModules[0].DEFAULT_LOCAL_TEAM_CONCURRENCY,
1606
+ baseTools: filteredTools,
1607
+ permissions,
1608
+ createRuntime: () => new teamModules[1].ClaudeTeamAgentRuntime({
1609
+ nativeRoot: resolveDataPlaneRoot({
1610
+ dataPlane: 'native',
1611
+ environment: runtimeEnvironment,
1612
+ }),
1613
+ configRoot,
1614
+ claudeVersion,
1615
+ provider: hostedToolProvider,
1616
+ ...(extensions ? { extensions } : {}),
1617
+ ...(permissionApprover
1618
+ ? { approveTool: permissionApprover }
1619
+ : {}),
1620
+ ...(hooks ? { hooks } : {}),
1621
+ ...(contextAssembler ? { contextAssembler } : {}),
1622
+ ...(providerForModel ? { providerForModel } : {}),
1623
+ permissionResolverForMode,
1624
+ eventSink: runtimeEventSink,
1625
+ }),
1626
+ })
1627
+ : undefined;
1628
+ const teamLeadOperations = teamCapability && teamModules
1629
+ ? new teamModules[2].TeamLeadOperations(teamCapability)
1630
+ : undefined;
1631
+ const teamLeadToolRegistryFactory = teamModules
1632
+ ? (base, operations, sessionId, names) => new teamModules[3].TeamLeadToolRegistry(base, operations, sessionId, names)
1633
+ : undefined;
1521
1634
  const service = new ClaudeSessionService({
1522
1635
  ...options,
1523
1636
  provider: hostedToolProvider,
@@ -1525,7 +1638,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1525
1638
  ...(providerForMainModel ? { providerForMainModel } : {}),
1526
1639
  tools: filteredTools,
1527
1640
  toolCapabilityEnvironment: runtimeEnvironment,
1528
- mcp: mcpTools,
1641
+ ...(!experimentalNativeTranscriptWrites ? { mcp: mcpTools } : {}),
1529
1642
  permissions,
1530
1643
  permissionResolverForMode,
1531
1644
  permissionMode: cli.dangerouslySkipPermissions
@@ -1537,41 +1650,72 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1537
1650
  dataPlane,
1538
1651
  updates,
1539
1652
  }),
1540
- extensions,
1541
- enableSubagents,
1542
- subagentToolNames: routedSubagentTools,
1543
- taskToolNames: selectedTaskRuntimeTools,
1544
- scheduledToolNames: selectedScheduledTools,
1545
- enableDynamicWakeups: interactive,
1546
- enableWorkflows: selectedWorkflowTools.length > 0,
1653
+ ...(experimentalNativeTranscriptWrites
1654
+ ? {}
1655
+ : {
1656
+ extensions,
1657
+ enableSubagents,
1658
+ subagentToolNames: routedSubagentTools,
1659
+ taskToolNames: selectedTaskRuntimeTools,
1660
+ scheduledToolNames: selectedScheduledTools,
1661
+ teamToolNames: selectedTeamTools,
1662
+ enableDynamicWakeups: interactive,
1663
+ enableWorkflows: selectedWorkflowTools.length > 0,
1664
+ }),
1547
1665
  emitToolUseSummaries,
1548
- enableWorktrees: cli.worktreeRequested || selectedWorktreeTools.length > 0,
1549
- worktreeToolNames: selectedWorktreeTools,
1550
- ...(runtimeSettings
1551
- ? { worktreeBaseRef: runtimeSettings.worktreeBaseRef }
1666
+ ...(!experimentalNativeTranscriptWrites
1667
+ ? {
1668
+ enableWorktrees: cli.worktreeRequested || selectedWorktreeTools.length > 0,
1669
+ worktreeToolNames: selectedWorktreeTools,
1670
+ ...(runtimeSettings
1671
+ ? { worktreeBaseRef: runtimeSettings.worktreeBaseRef }
1672
+ : {}),
1673
+ ...(interactiveTools ? { interactiveTools } : {}),
1674
+ ...(hooks ? { hooks } : {}),
1675
+ ...(selectedMainAgent ? { agent: selectedMainAgent } : {}),
1676
+ ...(memoryDirectory
1677
+ ? { projectMemoryDirectory: memoryDirectory }
1678
+ : {}),
1679
+ ...(projectMemoryRecall ? { projectMemoryRecall } : {}),
1680
+ ...(projectMemoryExtraction ? { projectMemoryExtraction } : {}),
1681
+ }
1552
1682
  : {}),
1553
- ...(interactiveTools ? { interactiveTools } : {}),
1554
- ...(hooks ? { hooks } : {}),
1555
- ...(selectedMainAgent ? { agent: selectedMainAgent } : {}),
1556
- ...(memoryDirectory ? { projectMemoryDirectory: memoryDirectory } : {}),
1557
- ...(projectMemoryRecall ? { projectMemoryRecall } : {}),
1558
- ...(projectMemoryExtraction ? { projectMemoryExtraction } : {}),
1559
1683
  contextAssembler,
1560
- conditionalRuleResolver: new ClaudeConditionalRuleResolver({
1561
- loadResources: loadContextResources,
1562
- }),
1684
+ ...(!experimentalNativeTranscriptWrites
1685
+ ? {
1686
+ conditionalRuleResolver: new ClaudeConditionalRuleResolver({
1687
+ loadResources: loadContextResources,
1688
+ }),
1689
+ }
1690
+ : {}),
1563
1691
  ...('contextReserveTokens' in context
1564
1692
  ? { contextReserveTokens: context.contextReserveTokens }
1565
1693
  : {}),
1566
1694
  ...(permissionApprover ? { approveTool: permissionApprover } : {}),
1567
1695
  ...(approveRecovery ? { approveRecovery } : {}),
1568
- fileCheckpointing: runtimeEnvironment.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING ===
1569
- 'true' || runtimeSettings?.checkpoints === true,
1696
+ ...(!experimentalNativeTranscriptWrites
1697
+ ? {
1698
+ fileCheckpointing: runtimeEnvironment.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING ===
1699
+ 'true' || runtimeSettings?.checkpoints === true,
1700
+ }
1701
+ : {}),
1570
1702
  autoCompact: runtimeSettings?.autoCompact ?? true,
1571
- fileRewindRoots: [
1572
- ...cli.additionalDirectories,
1573
- ...(memoryDirectory ? [memoryDirectory] : []),
1574
- ],
1703
+ ...(!experimentalNativeTranscriptWrites
1704
+ ? {
1705
+ fileRewindRoots: [
1706
+ ...cli.additionalDirectories,
1707
+ ...(memoryDirectory ? [memoryDirectory] : []),
1708
+ ],
1709
+ }
1710
+ : {}),
1711
+ ...(!experimentalNativeTranscriptWrites && teamLeadOperations
1712
+ ? {
1713
+ teamLeadOperations,
1714
+ ...(teamLeadToolRegistryFactory
1715
+ ? { teamLeadToolRegistryFactory }
1716
+ : {}),
1717
+ }
1718
+ : {}),
1575
1719
  });
1576
1720
  const toolNames = [
1577
1721
  ...filteredTools.definitions().map((definition) => definition.name),
@@ -1584,6 +1728,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1584
1728
  ...selectedWorktreeTools,
1585
1729
  ...selectedInteractiveTools,
1586
1730
  ...(enableSubagents ? selectedAgentTools : []),
1731
+ ...selectedTeamTools,
1587
1732
  ];
1588
1733
  const runtimeInfo = {
1589
1734
  cwd: workspace.cwd(),
@@ -1619,6 +1764,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
1619
1764
  : filteredTools;
1620
1765
  let pendingResumeSessionAt = cli.resumeSessionAt;
1621
1766
  return {
1767
+ ...(teamLeadOperations ? { teamLeadOperations } : {}),
1622
1768
  toolRegistry,
1623
1769
  run: (prompt, signal, sessionId, name, images, documents) => service.run(prompt, signal, sessionId, name ?? cli.name, images, documents),
1624
1770
  resume: (sessionId, prompt, signal, name, images, documents) => {
@@ -4015,6 +4161,7 @@ function printCommandHelp(argv, io) {
4015
4161
  'auto-mode',
4016
4162
  'project',
4017
4163
  'import',
4164
+ 'team',
4018
4165
  ].includes(value));
4019
4166
  if (commandIndex < 0)
4020
4167
  return false;
@@ -4102,8 +4249,217 @@ function printCommandHelp(argv, io) {
4102
4249
  io.stdout(IMPORT_HELP);
4103
4250
  return true;
4104
4251
  }
4252
+ if (command === 'team') {
4253
+ if (!hasHelpFlag)
4254
+ return false;
4255
+ io.stdout(TEAM_HELP);
4256
+ return true;
4257
+ }
4105
4258
  return false;
4106
4259
  }
4260
+ function parseTeamCommand(args) {
4261
+ if (args[0] !== 'team')
4262
+ throw new Error('Invalid Team command');
4263
+ const command = args[1];
4264
+ if (!command || command === 'help')
4265
+ throw new Error(TEAM_HELP.trim());
4266
+ if (!['create', 'resume', 'list', 'accept', 'stop'].includes(command))
4267
+ throw new Error(`Unsupported Team command: ${command}`);
4268
+ const operands = [];
4269
+ let json = false;
4270
+ let leadSessionId;
4271
+ let generation;
4272
+ let decision = 'accepted';
4273
+ let drainMs;
4274
+ const seen = new Set();
4275
+ const optionValue = (index, option) => {
4276
+ const value = args[index + 1];
4277
+ if (value === undefined || value.startsWith('--'))
4278
+ throw new Error(`${option} requires a value`);
4279
+ if (seen.has(option))
4280
+ throw new Error(`${option} may only be specified once`);
4281
+ seen.add(option);
4282
+ return value;
4283
+ };
4284
+ for (let index = 2; index < args.length; index += 1) {
4285
+ const value = args[index];
4286
+ if (value === '--json') {
4287
+ if (json)
4288
+ throw new Error('--json may only be specified once');
4289
+ json = true;
4290
+ }
4291
+ else if (value === '--lead-session-id') {
4292
+ leadSessionId = optionValue(index, value);
4293
+ index += 1;
4294
+ }
4295
+ else if (value === '--generation') {
4296
+ const raw = optionValue(index, value);
4297
+ if (!/^\d+$/.test(raw))
4298
+ throw new Error('Invalid generation');
4299
+ generation = Number(raw);
4300
+ if (!Number.isSafeInteger(generation))
4301
+ throw new Error('Invalid generation');
4302
+ index += 1;
4303
+ }
4304
+ else if (value === '--decision') {
4305
+ const raw = optionValue(index, value);
4306
+ if (raw !== 'accepted' && raw !== 'rejected')
4307
+ throw new Error('Invalid decision');
4308
+ decision = raw;
4309
+ index += 1;
4310
+ }
4311
+ else if (value === '--drain-ms') {
4312
+ const raw = optionValue(index, value);
4313
+ if (!/^\d+(?:\.\d+)?$/.test(raw))
4314
+ throw new Error('Invalid drain-ms');
4315
+ drainMs = Number(raw);
4316
+ if (!Number.isFinite(drainMs) || drainMs < 0 || drainMs > 600000)
4317
+ throw new Error('Invalid drain-ms');
4318
+ index += 1;
4319
+ }
4320
+ else if (value.startsWith('-')) {
4321
+ throw new Error(`Unknown Team option: ${value}`);
4322
+ }
4323
+ else
4324
+ operands.push(value);
4325
+ }
4326
+ const requireLead = () => {
4327
+ if (!leadSessionId)
4328
+ throw new Error('--lead-session-id requires a value');
4329
+ return leadSessionId;
4330
+ };
4331
+ const rejectOptions = (allowed) => {
4332
+ for (const option of seen) {
4333
+ if (!allowed.includes(option))
4334
+ throw new Error(`${option} is not valid for team ${command}`);
4335
+ }
4336
+ };
4337
+ if (command === 'create') {
4338
+ rejectOptions(['--lead-session-id']);
4339
+ if (operands.length !== 1)
4340
+ throw new Error('create requires a manifest path');
4341
+ return {
4342
+ command,
4343
+ manifest: operands[0],
4344
+ leadSessionId: requireLead(),
4345
+ json,
4346
+ };
4347
+ }
4348
+ if (command === 'list') {
4349
+ rejectOptions([]);
4350
+ if (operands.length !== 0)
4351
+ throw new Error('Invalid list options');
4352
+ return { command, json };
4353
+ }
4354
+ if (command === 'resume') {
4355
+ rejectOptions(['--lead-session-id']);
4356
+ if (operands.length !== 1)
4357
+ throw new Error('resume requires a team ID');
4358
+ return {
4359
+ command,
4360
+ teamId: operands[0],
4361
+ leadSessionId: requireLead(),
4362
+ json,
4363
+ };
4364
+ }
4365
+ if (command === 'accept') {
4366
+ rejectOptions(['--lead-session-id', '--generation', '--decision']);
4367
+ if (operands.length !== 2)
4368
+ throw new Error('accept requires team ID and task ID');
4369
+ return {
4370
+ command,
4371
+ teamId: operands[0],
4372
+ taskId: operands[1],
4373
+ leadSessionId: requireLead(),
4374
+ ...(generation === undefined ? {} : { generation }),
4375
+ decision,
4376
+ json,
4377
+ };
4378
+ }
4379
+ rejectOptions(['--lead-session-id', '--drain-ms']);
4380
+ if (operands.length !== 1)
4381
+ throw new Error('stop requires a team ID');
4382
+ return {
4383
+ command: 'stop',
4384
+ teamId: operands[0],
4385
+ leadSessionId: requireLead(),
4386
+ ...(drainMs === undefined ? {} : { drainMs }),
4387
+ json,
4388
+ };
4389
+ }
4390
+ function teamEnabled(environment) {
4391
+ return /^(1|true|yes|on)$/i.test((environment.PRAXIS_ENABLE_TEAMS ?? '').trim());
4392
+ }
4393
+ async function executeTeamCommand(args, io, dependencies, signal) {
4394
+ const parsed = parseTeamCommand(args);
4395
+ if (!teamEnabled(process.env))
4396
+ throw new Error('Experimental Team capability is disabled; set PRAXIS_ENABLE_TEAMS=true');
4397
+ const nativeControls = {
4398
+ ...DEFAULT_CLI_CONTROLS,
4399
+ dataPlane: 'native',
4400
+ };
4401
+ const service = await dependencies.createService({
4402
+ eventSink: () => undefined,
4403
+ requireProvider: parsed.command !== 'list',
4404
+ exposeToolRegistry: true,
4405
+ controls: nativeControls,
4406
+ configRoot: resolveDataPlaneRoot({ dataPlane: 'native' }),
4407
+ providerEnvironment: process.env,
4408
+ ...(signal ? { signal } : {}),
4409
+ });
4410
+ try {
4411
+ const operations = service.teamLeadOperations;
4412
+ if (!operations)
4413
+ throw new Error('Team lead operations are unavailable');
4414
+ if (parsed.command === 'list') {
4415
+ const teams = await operations.list();
4416
+ if (parsed.json)
4417
+ writeJson(io, { teams });
4418
+ else
4419
+ io.stdout(`${teams.map((team) => team.teamId).join('\n')}${teams.length ? '\n' : ''}`);
4420
+ return 0;
4421
+ }
4422
+ let snapshot;
4423
+ if (parsed.command === 'create') {
4424
+ const raw = await readFile(parsed.manifest, 'utf8');
4425
+ const value = JSON.parse(raw);
4426
+ if (!value || typeof value !== 'object' || Array.isArray(value))
4427
+ throw new Error('Team manifest must be an object');
4428
+ const request = value;
4429
+ snapshot = await operations.create(request, parsed.leadSessionId);
4430
+ snapshot = await operations.detach(request.teamId, parsed.leadSessionId);
4431
+ }
4432
+ else if (parsed.command === 'resume') {
4433
+ snapshot = await operations.resume(parsed.teamId, parsed.leadSessionId);
4434
+ snapshot = await operations.detach(parsed.teamId, parsed.leadSessionId);
4435
+ }
4436
+ else if (parsed.command === 'accept') {
4437
+ snapshot = await operations.accept({
4438
+ teamId: parsed.teamId,
4439
+ taskId: parsed.taskId,
4440
+ ...(parsed.generation === undefined
4441
+ ? {}
4442
+ : { generation: parsed.generation }),
4443
+ decision: parsed.decision,
4444
+ }, parsed.leadSessionId);
4445
+ snapshot = await operations.detach(parsed.teamId, parsed.leadSessionId);
4446
+ }
4447
+ else {
4448
+ snapshot = await operations.stop({
4449
+ teamId: parsed.teamId,
4450
+ ...(parsed.drainMs === undefined ? {} : { drainMs: parsed.drainMs }),
4451
+ }, parsed.leadSessionId);
4452
+ }
4453
+ if (parsed.json)
4454
+ writeJson(io, { team: snapshot });
4455
+ else
4456
+ io.stdout(`${snapshot.teamId}\n`);
4457
+ return 0;
4458
+ }
4459
+ finally {
4460
+ await service.close?.();
4461
+ }
4462
+ }
4107
4463
  function extractSpecialDataPlane(argv) {
4108
4464
  const args = [];
4109
4465
  let dataPlane;
@@ -4133,6 +4489,7 @@ function extractSpecialDataPlane(argv) {
4133
4489
  }
4134
4490
  function specialCommandIndex(argv) {
4135
4491
  const commands = new Set([
4492
+ 'team',
4136
4493
  'plugin',
4137
4494
  'plugins',
4138
4495
  'project',
@@ -4187,6 +4544,14 @@ async function execute(argv, io, dependencies, signal) {
4187
4544
  return dependencies.runInteractive(signal ? { signal } : {});
4188
4545
  }
4189
4546
  const commandIndex = specialCommandIndex(argv);
4547
+ if (commandIndex >= 0 &&
4548
+ argv[commandIndex] === 'team' &&
4549
+ !argv.includes('--help') &&
4550
+ !argv.includes('-h')) {
4551
+ if (argv.some((value) => value === '--data-plane' || value.startsWith('--data-plane=')))
4552
+ throw new Error('Team commands are native-only; --data-plane is not supported');
4553
+ return executeTeamCommand(argv.slice(commandIndex), io, dependencies, signal);
4554
+ }
4190
4555
  const specialPrefix = commandIndex > 0 &&
4191
4556
  (argv[commandIndex] === 'plugin' || argv[commandIndex] === 'plugins')
4192
4557
  ? parseCliInvocation([...argv.slice(0, commandIndex), '__probe__'])
@@ -477,6 +477,12 @@ export class ClaudeTranscriptCodec {
477
477
  },
478
478
  };
479
479
  }
480
+ else if (event.kind === 'tool-execution-started') {
481
+ return {
482
+ ok: false,
483
+ issue: diagnostic('unsupported-event', 'Claude transcripts do not support native tool execution markers', 0, null, { eventKind: event.kind }),
484
+ };
485
+ }
480
486
  else
481
487
  try {
482
488
  entry = {
@@ -0,0 +1,31 @@
1
+ /** Provider- and persistence-independent lifecycle contract for one Agent. */
2
+ export type LifecycleState = 'queued' | 'running' | 'waiting' | 'completed' | 'failed' | 'cancelling' | 'cancelled' | 'orphaned';
3
+ export type LifecycleAcceptance = 'pending' | 'accepted' | 'rejected';
4
+ export interface LifecycleOwner {
5
+ readonly token: string;
6
+ readonly pid: number;
7
+ readonly acquiredAt: string;
8
+ }
9
+ export interface AgentLifecycleSnapshot {
10
+ readonly generation: number;
11
+ readonly revision: number;
12
+ readonly state: LifecycleState;
13
+ readonly owner: LifecycleOwner | null;
14
+ readonly previousOwnerToken: string | null;
15
+ readonly terminalAt: string | null;
16
+ readonly acceptance: LifecycleAcceptance;
17
+ }
18
+ export declare const TERMINAL_LIFECYCLE_STATES: readonly ["completed", "failed", "cancelled", "orphaned"];
19
+ export declare function isTerminalLifecycleState(state: LifecycleState): state is 'completed' | 'failed' | 'cancelled' | 'orphaned';
20
+ /** The single invariant parser used by every lifecycle mutation and store. */
21
+ export declare function parseAgentLifecycleSnapshot(value: unknown): AgentLifecycleSnapshot;
22
+ export declare function createAgentLifecycle(owner: LifecycleOwner, generation?: number): AgentLifecycleSnapshot;
23
+ export declare function transitionLifecycle(current: AgentLifecycleSnapshot, nextState: LifecycleState, ownerToken: string, terminalAt?: string): AgentLifecycleSnapshot;
24
+ /** Rotate a queued execution owner during a planned parent-to-worker handoff. */
25
+ export declare function transferLifecycleOwner(current: AgentLifecycleSnapshot, currentOwnerToken: string, nextOwner: LifecycleOwner): AgentLifecycleSnapshot;
26
+ export declare function continueLifecycle(current: AgentLifecycleSnapshot, owner: LifecycleOwner): AgentLifecycleSnapshot;
27
+ export declare function recoverLifecycle(current: AgentLifecycleSnapshot, owner: LifecycleOwner): AgentLifecycleSnapshot;
28
+ /** Adapter-proven owner loss is intentionally separate from ordinary transitions. */
29
+ export declare function markLifecycleOrphaned(current: AgentLifecycleSnapshot, ownerToken: string, terminalAt?: string): AgentLifecycleSnapshot;
30
+ export declare function acceptLifecycle(current: AgentLifecycleSnapshot, generation?: number, acceptance?: Exclude<LifecycleAcceptance, 'pending'>): AgentLifecycleSnapshot;
31
+ //# sourceMappingURL=agent-orchestration.d.ts.map