synu.fish

  1# SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2#
  3# SPDX-License-Identifier: Unlicense
  4
  5function synu --description "Universal agent wrapper with Synthetic API quota tracking"
  6    # If no arguments, just print the quota
  7    if test (count $argv) -lt 1
  8        set -l quota (_synu_get_quota)
  9        if test $status -ne 0
 10            echo "Error: Could not fetch quota" >&2
 11            return 1
 12        end
 13        set -l requests (echo "$quota" | cut -d' ' -f1)
 14        set -l limit (echo "$quota" | cut -d' ' -f2)
 15        set -l remaining (math "$limit - $requests")
 16        set -l percent_used (math -s0 "$requests * 100 / $limit")
 17        printf "Usage: "
 18        if test $percent_used -lt 33
 19            set_color -b green black
 20        else if test $percent_used -lt 67
 21            set_color -b yellow black
 22        else
 23            set_color -b red black
 24        end
 25        printf " %s%% " $percent_used
 26        set_color normal
 27        printf " (%s/%s remaining)\n" $remaining $limit
 28        return 0
 29    end
 30
 31    # Check for interactive mode: synu i <agent> [args...]
 32    if test "$argv[1]" = "i"
 33        if test (count $argv) -lt 2
 34            echo "Error: Interactive mode requires an agent name" >&2
 35            echo "Usage: synu i <agent> [args...]" >&2
 36            return 1
 37        end
 38
 39        set -l agent $argv[2]
 40        set -l agent_args $argv[3..-1]
 41
 42        # Source agent definition if it exists
 43        set -l agent_file (status dirname)/_synu_agents/$agent.fish
 44        if test -f "$agent_file"
 45            source $agent_file
 46        end
 47
 48        # Check for interactive function
 49        if not functions -q _synu_agent_{$agent}_interactive
 50            echo "Error: Agent '$agent' does not support interactive mode" >&2
 51            return 1
 52        end
 53
 54        # Get flags from interactive selection
 55        set -l interactive_flags (_synu_agent_{$agent}_interactive)
 56        set -l interactive_status $status
 57        if test $interactive_status -ne 0
 58            return $interactive_status
 59        end
 60
 61        # Recursively call synu with selected flags
 62        synu $agent $interactive_flags $agent_args
 63        return $status
 64    end
 65
 66    # Extract agent name (first argument) and remaining args
 67    set -l agent $argv[1]
 68    set -l agent_args $argv[2..-1]
 69
 70    # Source agent definition if it exists
 71    set -l agent_file (status dirname)/_synu_agents/$agent.fish
 72    if test -f "$agent_file"
 73        source $agent_file
 74    end
 75
 76    # Check if agent has a configuration function
 77    if functions -q _synu_agent_{$agent}_configure
 78        # Get flag specification
 79        set -l flag_spec (_synu_agent_{$agent}_flags)
 80
 81        # Parse flags using agent's spec, ignoring unknown flags for passthrough
 82        # We need to capture which flags were set to pass to configure
 83        set -l parsed_args
 84        if test -n "$flag_spec"
 85            # Parse with --ignore-unknown so agent-native flags pass through
 86            # @fish-lsp-disable-next-line 4004
 87            argparse --ignore-unknown $flag_spec -- $agent_args
 88            or return 1
 89
 90            # argv now contains non-flag args after argparse
 91            set agent_args $argv
 92
 93            # Rebuild the flag arguments to pass to configure
 94            # Check each possible flag and add if set
 95            for flag in L/large l/light o/opus s/sonnet H/haiku a/agent m/model
 96                set -l long_flag (string split '/' $flag)[2]
 97                set -l var_name _flag_$long_flag
 98                if set -q $var_name
 99                    set parsed_args $parsed_args --$long_flag=$$var_name
100                end
101            end
102        end
103
104        # Configure the agent environment
105        _synu_agent_{$agent}_configure $parsed_args
106        or return 1
107    end
108
109    # Check if agent provides extra CLI arguments (for agents that don't use env vars)
110    set -l extra_args
111    if functions -q _synu_agent_{$agent}_args
112        set extra_args (_synu_agent_{$agent}_args)
113    end
114
115    # Fetch quota before agent execution
116    set -l quota_before (_synu_get_quota)
117    if test $status -ne 0
118        # If quota fetch fails, still execute the agent but warn
119        echo "Warning: Could not fetch quota before execution" >&2
120        # Set default values if quota fetch fails
121        set -l quota_before "0 0"
122    end
123
124    # Parse pre-execution quota values
125    set -l requests_before (echo "$quota_before" | cut -d' ' -f1)
126    set -l limit (echo "$quota_before" | cut -d' ' -f2)
127
128    # Execute the agent with all arguments passed through unchanged
129    # Use 'command' to bypass function recursion and call the actual binary
130    # extra_args contains agent-specific CLI flags (e.g., -m for opencode)
131    command $agent $extra_args $agent_args
132    set -l exit_status $status
133
134    # Clean up environment variables set by agent
135    if functions -q _synu_agent_{$agent}_env_vars
136        for var in (_synu_agent_{$agent}_env_vars)
137            set -e $var
138        end
139    end
140
141    # Fetch quota after agent execution
142    set -l quota_after (_synu_get_quota)
143    if test $status -ne 0
144        # If quota fetch fails, still exit but warn
145        echo "Warning: Could not fetch quota after execution" >&2
146        return $exit_status
147    end
148
149    # Parse post-execution quota values
150    set -l requests_after (echo "$quota_after" | cut -d' ' -f1)
151    # Note: limit is the same before and after, using pre-execution value
152
153    # Calculate session usage: final_requests - initial_requests
154    set -l session_usage (math "$requests_after - $requests_before")
155
156    # Calculate remaining quota: limit - requests_after
157    set -l remaining (math "$limit - $requests_after")
158
159    # Calculate percentage used: (requests_after * 100) / limit
160    set -l percent_used (math -s0 "$requests_after * 100 / $limit")
161
162    # Display session usage and remaining quota with color
163    # Force a newline first for proper separation from agent output
164    printf "\n"
165    printf "Session: %s requests\n" $session_usage
166    printf "Overall: "
167
168    # Determine color based on usage percentage
169    # Green: <33%, Yellow: 33-66%, Red: >66%
170    if test $percent_used -lt 33
171        set_color -b green black
172    else if test $percent_used -lt 67
173        set_color -b yellow black
174    else
175        set_color -b red black
176    end
177    printf " %s%% " $percent_used
178    set_color normal
179    printf " (%s/%s remaining)\n" $remaining $limit
180
181    return $exit_status
182end