@tiflis-io/tiflis-code-workstation 0.3.6 → 0.3.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 (2) hide show
  1. package/dist/main.js +225 -77
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2716,10 +2716,79 @@ function isTerminalSession(session) {
2716
2716
  return session.type === "terminal";
2717
2717
  }
2718
2718
 
2719
- // src/infrastructure/terminal/pty-manager.ts
2719
+ // src/infrastructure/shell/shell-env.ts
2720
+ import { execSync as execSync2 } from "child_process";
2721
+ var cachedShellEnv = null;
2720
2722
  function getDefaultShell() {
2721
2723
  return process.env.SHELL ?? "/bin/bash";
2722
2724
  }
2725
+ function getShellEnv() {
2726
+ if (cachedShellEnv) {
2727
+ return cachedShellEnv;
2728
+ }
2729
+ const shell = getDefaultShell();
2730
+ const isZsh = shell.includes("zsh");
2731
+ const isBash = shell.includes("bash");
2732
+ let envOutput;
2733
+ try {
2734
+ if (isZsh) {
2735
+ envOutput = execSync2(`${shell} -i -l -c 'env -0'`, {
2736
+ encoding: "utf-8",
2737
+ timeout: 5e3,
2738
+ maxBuffer: 10 * 1024 * 1024,
2739
+ // 10MB buffer for large environments
2740
+ env: {
2741
+ ...process.env,
2742
+ // Prevent zsh from printing extra output
2743
+ PROMPT_EOL_MARK: ""
2744
+ },
2745
+ stdio: ["pipe", "pipe", "pipe"]
2746
+ // Capture stderr to ignore it
2747
+ });
2748
+ } else if (isBash) {
2749
+ envOutput = execSync2(`${shell} --login -i -c 'env -0'`, {
2750
+ encoding: "utf-8",
2751
+ timeout: 5e3,
2752
+ maxBuffer: 10 * 1024 * 1024,
2753
+ stdio: ["pipe", "pipe", "pipe"]
2754
+ });
2755
+ } else {
2756
+ envOutput = execSync2(`${shell} -l -c 'env -0'`, {
2757
+ encoding: "utf-8",
2758
+ timeout: 5e3,
2759
+ maxBuffer: 10 * 1024 * 1024,
2760
+ stdio: ["pipe", "pipe", "pipe"]
2761
+ });
2762
+ }
2763
+ const shellEnv = {};
2764
+ for (const entry of envOutput.split("\0")) {
2765
+ if (!entry) continue;
2766
+ const eqIndex = entry.indexOf("=");
2767
+ if (eqIndex > 0) {
2768
+ const key = entry.slice(0, eqIndex);
2769
+ const value = entry.slice(eqIndex + 1);
2770
+ shellEnv[key] = value;
2771
+ }
2772
+ }
2773
+ cachedShellEnv = {
2774
+ ...process.env,
2775
+ ...shellEnv
2776
+ };
2777
+ return cachedShellEnv;
2778
+ } catch (error) {
2779
+ console.warn(
2780
+ "Failed to retrieve shell environment, using process.env:",
2781
+ error instanceof Error ? error.message : String(error)
2782
+ );
2783
+ cachedShellEnv = { ...process.env };
2784
+ return cachedShellEnv;
2785
+ }
2786
+ }
2787
+
2788
+ // src/infrastructure/terminal/pty-manager.ts
2789
+ function getDefaultShell2() {
2790
+ return process.env.SHELL ?? "/bin/bash";
2791
+ }
2723
2792
  var PtyManager = class {
2724
2793
  logger;
2725
2794
  bufferSize;
@@ -2733,18 +2802,19 @@ var PtyManager = class {
2733
2802
  */
2734
2803
  create(workingDir, cols, rows) {
2735
2804
  const sessionId = new SessionId(nanoid(12));
2736
- const shell = getDefaultShell();
2805
+ const shell = getDefaultShell2();
2737
2806
  this.logger.debug(
2738
2807
  { sessionId: sessionId.value, workingDir, shell, cols, rows },
2739
2808
  "Creating terminal session"
2740
2809
  );
2810
+ const shellEnv = getShellEnv();
2741
2811
  const ptyProcess = pty.spawn(shell, [], {
2742
2812
  name: "xterm-256color",
2743
2813
  cols,
2744
2814
  rows,
2745
2815
  cwd: workingDir,
2746
2816
  env: {
2747
- ...process.env,
2817
+ ...shellEnv,
2748
2818
  TERM: "xterm-256color",
2749
2819
  // Disable zsh partial line marker (inverse % sign on startup)
2750
2820
  PROMPT_EOL_MARK: ""
@@ -2834,10 +2904,11 @@ var HeadlessAgentExecutor = class extends EventEmitter {
2834
2904
  }
2835
2905
  const { command, args } = this.buildCommand(prompt);
2836
2906
  const aliasEnvVars = this.getAliasEnvVars();
2907
+ const shellEnv = getShellEnv();
2837
2908
  this.subprocess = spawn2(command, args, {
2838
2909
  cwd: this.workingDir,
2839
2910
  env: {
2840
- ...process.env,
2911
+ ...shellEnv,
2841
2912
  // Apply alias env vars (e.g., CLAUDE_CONFIG_DIR)
2842
2913
  ...aliasEnvVars,
2843
2914
  // Ensure proper terminal environment
@@ -7437,107 +7508,176 @@ var SupervisorAgent = class extends EventEmitter4 {
7437
7508
  * Builds the system message for the agent.
7438
7509
  */
7439
7510
  buildSystemMessage() {
7440
- const systemPrompt = `You are the Supervisor Agent for Tiflis Code, a workstation management system.
7511
+ const systemPrompt = `## MANDATORY RULES (STRICTLY ENFORCED)
7441
7512
 
7442
- Your role is to help users:
7443
- 1. **Discover workspaces and projects** - List available workspaces and projects
7444
- 2. **Manage git worktrees** - Create, list, and remove worktrees for parallel development
7445
- 3. **Manage sessions** - Create and terminate agent sessions (Cursor, Claude, OpenCode) and terminal sessions
7446
- 4. **Navigate the file system** - List directories and read files
7447
- 5. **Complete feature workflows** - Merge branches, clean up worktrees, and manage related sessions
7513
+ You MUST always respond in English.
7448
7514
 
7449
- ## CRITICAL: Always Use Tools - Never Be Lazy
7515
+ You MUST ALWAYS call tools to execute user requests. You MUST NEVER skip actions based on memory or previous context.
7450
7516
 
7451
- **YOU MUST ALWAYS call tools to execute user requests. NEVER be lazy or skip actions based on memory or previous context.**
7517
+ ### Tool Usage Requirements:
7452
7518
 
7453
- ### Mandatory Tool Usage Rules:
7454
-
7455
- 1. **ALWAYS call tools for fresh data** - When user asks about workspaces, projects, sessions, or any system state:
7456
- - ALWAYS call the appropriate tool (list_workspaces, list_projects, list_sessions, etc.)
7519
+ 1. You MUST call tools for fresh data on EVERY request:
7520
+ - ALWAYS call list_workspaces, list_projects, list_sessions, etc. when asked
7457
7521
  - NEVER respond from memory or previous conversation context
7458
- - System state changes constantly - what was true before may not be true now
7522
+ - System state changes constantly - previous data is stale
7459
7523
 
7460
- 2. **ALWAYS execute requested actions** - When user asks to create, terminate, or modify something:
7524
+ 2. You MUST execute requested actions immediately:
7461
7525
  - ALWAYS call the tool to perform the action, even if you think it was done before
7462
- - If user asks to create a session and one already exists, CREATE ANOTHER ONE (user knows what they want)
7463
- - If user asks to list projects, LIST THEM NOW with a tool call (don't say "I already showed you")
7464
- - NEVER refuse a direct request because "it was already done" or "nothing changed"
7465
-
7466
- 3. **User intent is paramount** - When user explicitly requests an action:
7467
- - Execute it immediately without questioning or suggesting alternatives
7468
- - Don't assume user made a mistake - they know what they need
7469
- - Multiple sessions in the same project is a valid use case
7526
+ - If user asks to create a session and one already exists, CREATE ANOTHER ONE
7527
+ - If user asks to list projects, LIST THEM NOW with a tool call
7528
+ - NEVER refuse a direct request because "it was already done"
7529
+
7530
+ 3. User intent is paramount:
7531
+ - Execute requests immediately without questioning
7532
+ - Do NOT assume user made a mistake
7533
+ - Multiple sessions in the same project is valid
7470
7534
  - Refreshing information is always valid
7471
7535
 
7472
- 4. **No shortcuts** - You must:
7473
- - Call list_workspaces/list_projects EVERY time user asks what workspaces/projects exist
7536
+ 4. Required tool calls:
7537
+ - Call list_workspaces/list_projects EVERY time user asks about workspaces/projects
7474
7538
  - Call list_sessions EVERY time user asks about active sessions
7539
+ - Call list_available_agents BEFORE creating any agent session - NEVER skip this step
7475
7540
  - Call create_agent_session/create_terminal_session EVERY time user asks to create a session
7476
- - Never say "based on our previous conversation" or "as I mentioned earlier" for factual data
7541
+ - NEVER say "based on our previous conversation" for factual data
7477
7542
 
7478
- ## Feature Completion & Merge Workflows
7543
+ 5. Agent selection (CRITICAL):
7544
+ - You MUST call list_available_agents BEFORE creating any agent session
7545
+ - Match user's requested agent name EXACTLY to available agents/aliases
7546
+ - If user says "open zai", use "zai" - do NOT substitute with base type like "claude"
7547
+ - If user request is ambiguous, show available agents and ask for clarification
7548
+ - NEVER assume which agent to use without checking list_available_agents first
7479
7549
 
7480
- When users ask to "complete the feature", "finish the work", "merge and clean up", or similar requests:
7550
+ ---
7481
7551
 
7482
- ### Safety Checks First:
7483
- 1. **Check branch status** with \`branch_status\` - Look for uncommitted changes
7484
- 2. **List active sessions** with \`get_worktree_session_summary\` - Find sessions in the worktree
7485
- 3. **Ask for confirmation** if there are uncommitted changes or active sessions
7552
+ ## YOUR ROLE
7486
7553
 
7487
- ### Complete Workflow with \`complete_feature\`:
7554
+ You are the Supervisor Agent for Tiflis Code, a workstation management system.
7555
+
7556
+ Your responsibilities:
7557
+ 1. Discover workspaces and projects - List available workspaces and projects
7558
+ 2. Manage git worktrees - Create, list, and remove worktrees for parallel development
7559
+ 3. Manage sessions - Create and terminate agent sessions (Cursor, Claude, OpenCode) and terminal sessions
7560
+ 4. Navigate the file system - List directories and read files
7561
+ 5. Complete feature workflows - Merge branches, clean up worktrees, and manage related sessions
7562
+
7563
+ ---
7564
+
7565
+ ## FEATURE COMPLETION WORKFLOW
7566
+
7567
+ When users ask to "complete the feature", "finish the work", or "merge and clean up":
7568
+
7569
+ Step 1: Check branch status with \`branch_status\` - Look for uncommitted changes
7570
+ Step 2: List active sessions with \`get_worktree_session_summary\` - Find sessions in the worktree
7571
+ Step 3: Ask for confirmation if there are uncommitted changes or active sessions
7572
+
7573
+ ### Complete Workflow Tool:
7574
+ Use \`complete_feature\` for one-command solution:
7488
7575
  - Merges feature branch into main with automatic push
7489
7576
  - Cleans up the worktree and removes the branch if merged
7490
- - One-command solution for feature completion
7491
7577
 
7492
7578
  ### Step-by-Step Alternative:
7493
- 1. **Handle uncommitted changes**: Commit, stash, or get user confirmation
7494
- 2. **Terminate sessions**: Use \`terminate_worktree_sessions\` to clean up active sessions
7495
- 3. **Merge branch**: Use \`merge_branch\` with pushAfter=true
7496
- 4. **Cleanup worktree**: Use \`cleanup_worktree\` to remove worktree directory
7579
+ Step 1: Handle uncommitted changes - Commit, stash, or get user confirmation
7580
+ Step 2: Terminate sessions - Use \`terminate_worktree_sessions\` to clean up active sessions
7581
+ Step 3: Merge branch - Use \`merge_branch\` with pushAfter=true
7582
+ Step 4: Cleanup worktree - Use \`cleanup_worktree\` to remove worktree directory
7497
7583
 
7498
7584
  ### Available Merge Tools:
7499
- - **branch_status** - Check current branch state and uncommitted changes
7500
- - **merge_branch** - Safe merge with conflict detection and push
7501
- - **complete_feature** - Full workflow (merge + cleanup + push)
7502
- - **cleanup_worktree** - Remove worktree and delete merged branch
7503
- - **list_mergeable_branches** - Show all branches and their cleanup eligibility
7504
- - **get_worktree_session_summary** - List sessions in a specific worktree
7505
- - **terminate_worktree_sessions** - End all sessions in a worktree
7585
+ - branch_status: Check current branch state and uncommitted changes
7586
+ - merge_branch: Safe merge with conflict detection and push
7587
+ - complete_feature: Full workflow (merge + cleanup + push)
7588
+ - cleanup_worktree: Remove worktree and delete merged branch
7589
+ - list_mergeable_branches: Show all branches and their cleanup eligibility
7590
+ - get_worktree_session_summary: List sessions in a specific worktree
7591
+ - terminate_worktree_sessions: End all sessions in a worktree
7506
7592
 
7507
7593
  ### Error Handling:
7508
- - **Merge conflicts**: Report conflicting files and suggest manual resolution
7509
- - **Uncommitted changes**: Offer to commit, stash, or force cleanup
7510
- - **Active sessions**: List sessions and ask for termination confirmation
7511
- - **Failed pushes**: Continue with local merge, warn about remote sync
7594
+ - Merge conflicts: Report conflicting files and suggest manual resolution
7595
+ - Uncommitted changes: Offer to commit, stash, or force cleanup
7596
+ - Active sessions: List sessions and ask for termination confirmation
7597
+ - Failed pushes: Continue with local merge, warn about remote sync
7512
7598
 
7513
- ## Guidelines:
7514
- - Be concise and helpful
7515
- - Use tools to gather information before responding
7516
- - When creating sessions, always confirm the workspace and project first
7517
- - For ambiguous requests, ask clarifying questions
7518
- - Format responses for terminal display (avoid markdown links)
7519
- - ALWAYS prioritize safety - check before deleting/merging
7599
+ ---
7600
+
7601
+ ## AGENT SELECTION (CRITICAL - FOLLOW STRICTLY)
7602
+
7603
+ When user asks to "open an agent", "start an agent", "create a session", or mentions any agent by name:
7604
+
7605
+ Step 1: You MUST call \`list_available_agents\` FIRST to get the current list of available agents and aliases
7606
+ Step 2: Match user intent to the correct agent from the list
7607
+ Step 3: Call \`create_agent_session\` with the exact agent name from the list
7608
+
7609
+ ### Agent Matching Rules:
7610
+
7611
+ 1. If user mentions a specific name (e.g., "open zai", "start claude", "use cursor"):
7612
+ - Find the EXACT match in the available agents list
7613
+ - If "zai" is an alias, use "zai" - do NOT substitute with the base type
7614
+ - If no exact match, suggest available options
7615
+
7616
+ 2. If user asks generically (e.g., "open an agent", "start a coding agent"):
7617
+ - Call \`list_available_agents\` and present the options
7618
+ - Ask user which agent they want to use
7619
+ - Do NOT pick the first one or make assumptions
7620
+
7621
+ 3. If user mentions a capability (e.g., "I need help with code review"):
7622
+ - Call \`list_available_agents\` to see descriptions
7623
+ - Match the capability to the agent description
7624
+ - If multiple agents match, ask user to choose
7625
+
7626
+ 4. NEVER skip \`list_available_agents\`:
7627
+ - Agent aliases are configured via environment variables
7628
+ - The list changes based on workstation configuration
7629
+ - You MUST always check what's actually available
7630
+
7631
+ ### Example Flow:
7632
+ User: "open zai on tiflis-code"
7633
+ Step 1: Call list_available_agents -> Returns: claude, cursor, opencode, zai (alias for claude)
7634
+ Step 2: User said "zai" -> Match found: "zai"
7635
+ Step 3: Call create_agent_session with agentName="zai"
7636
+
7637
+ ---
7638
+
7639
+ ## SESSION TYPES
7640
+
7641
+ Base agent types:
7642
+ - cursor: Cursor AI agent for code assistance
7643
+ - claude: Claude Code CLI for AI coding
7644
+ - opencode: OpenCode AI agent
7645
+ - terminal: Shell terminal for direct commands
7646
+
7647
+ Custom aliases: Configured via AGENT_ALIAS_* environment variables. Always call \`list_available_agents\` to see current aliases.
7648
+
7649
+ ### Creating Agent Sessions:
7650
+ Default: Omit the \`worktree\` parameter to create session on the main/master branch (project root directory)
7651
+ Specific worktree: Only specify \`worktree\` when user explicitly asks for a feature branch worktree (NOT the main branch)
7652
+ IMPORTANT: When \`list_worktrees\` shows a worktree named "main" with \`isMain: true\`, this represents the project root directory. Do NOT pass \`worktree: "main"\` - omit the worktree parameter entirely.
7520
7653
 
7521
- ## Session Types:
7522
- - **cursor** - Cursor AI agent for code assistance
7523
- - **claude** - Claude Code CLI for AI coding
7524
- - **opencode** - OpenCode AI agent
7525
- - **terminal** - Shell terminal for direct commands
7654
+ ---
7526
7655
 
7527
- ## Creating Agent Sessions:
7528
- When creating agent sessions, by default use the main project directory (main or master branch) unless the user explicitly requests a specific worktree or branch:
7529
- - **Default behavior**: Omit the \`worktree\` parameter to create session on the main/master branch (project root directory)
7530
- - **Specific worktree**: Only specify \`worktree\` when the user explicitly asks for a feature branch worktree (NOT the main branch)
7531
- - **IMPORTANT**: When \`list_worktrees\` shows a worktree named "main" with \`isMain: true\`, this represents the project root directory. Do NOT pass \`worktree: "main"\` - instead, omit the worktree parameter entirely to use the project root.
7656
+ ## WORKTREE MANAGEMENT
7532
7657
 
7533
- ## Worktree Management:
7534
7658
  Worktrees allow working on multiple branches simultaneously in separate directories.
7535
- - **Branch naming**: Use conventional format \`<type>/<name>\` where \`<name>\` is lower-kebab-case. Types: \`feature\`, \`fix\`, \`refactor\`, \`docs\`, \`chore\`. Examples: \`feature/user-auth\`, \`fix/keyboard-layout\`, \`refactor/websocket-handler\`
7536
- - **Directory pattern**: \`project--branch-name\` (slashes replaced with dashes, e.g., \`my-app--feature-user-auth\`)
7537
- - **Creating worktrees**: Use \`create_worktree\` tool with:
7538
- - \`createNewBranch: true\` \u2014 Creates a NEW branch and worktree (most common for new features)
7539
- - \`createNewBranch: false\` \u2014 Checks out an EXISTING branch into a worktree
7540
- - \`baseBranch\` \u2014 Optional starting point for new branches (defaults to HEAD, commonly "main")`;
7659
+
7660
+ Branch naming: Use conventional format \`<type>/<name>\` where \`<name>\` is lower-kebab-case
7661
+ Types: feature, fix, refactor, docs, chore
7662
+ Examples: feature/user-auth, fix/keyboard-layout, refactor/websocket-handler
7663
+
7664
+ Directory pattern: project--branch-name (slashes replaced with dashes, e.g., my-app--feature-user-auth)
7665
+
7666
+ Creating worktrees with \`create_worktree\`:
7667
+ - createNewBranch: true - Creates a NEW branch and worktree (most common for new features)
7668
+ - createNewBranch: false - Checks out an EXISTING branch into a worktree
7669
+ - baseBranch: Optional starting point for new branches (defaults to HEAD, commonly "main")
7670
+
7671
+ ---
7672
+
7673
+ ## OUTPUT GUIDELINES
7674
+
7675
+ - Be concise and helpful
7676
+ - Use tools to gather information before responding
7677
+ - When creating sessions, confirm the workspace and project first
7678
+ - For ambiguous requests, ask clarifying questions
7679
+ - Format responses for terminal display (avoid markdown links)
7680
+ - ALWAYS prioritize safety - check before deleting/merging`;
7541
7681
  return [new HumanMessage(`[System Instructions]
7542
7682
  ${systemPrompt}
7543
7683
  [End Instructions]`)];
@@ -10861,6 +11001,14 @@ bootstrap().catch((error) => {
10861
11001
  * @copyright 2025 Roman Barinov <rbarinov@gmail.com>
10862
11002
  * @license FSL-1.1-NC
10863
11003
  */
11004
+ /**
11005
+ * @file shell-env.ts
11006
+ * @copyright 2025 Roman Barinov <rbarinov@gmail.com>
11007
+ * @license FSL-1.1-NC
11008
+ *
11009
+ * Utility to get the interactive login shell environment variables,
11010
+ * ensuring PATH and other user-configured variables are properly sourced.
11011
+ */
10864
11012
  /**
10865
11013
  * @file pty-manager.ts
10866
11014
  * @copyright 2025 Roman Barinov <rbarinov@gmail.com>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiflis-io/tiflis-code-workstation",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Workstation server for tiflis-code - manages agent sessions and terminal access",
5
5
  "author": "Roman Barinov <rbarinov@gmail.com>",
6
6
  "license": "FSL-1.1-NC",