agent-bios 0.13.0 → 0.14.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.
@@ -1,3 +1,10 @@
1
+ # Alias expansion is OFF while this file is parsed and restored to what it was at the
2
+ # end: zsh expands aliases at parse time, inside function bodies too, so an alias named
3
+ # `builtin`, `command`, or `claude` that exists when this file is sourced would be baked
4
+ # into the functions below and the real binary never reached.
5
+ [[ -o aliases ]] && _agent_launch_aliases_were=1 || _agent_launch_aliases_were=0
6
+ setopt no_aliases
7
+
1
8
  # Interactive zero-argument entrypoints use agent-launch. Every argument-bearing
2
9
  # or non-TTY call skips profile projection; Claude retains its direct-path
3
10
  # permission-bypass default.
@@ -31,13 +38,109 @@ _agent_launch_dispatch() {
31
38
  fi
32
39
  }
33
40
 
34
- unalias codex 2>/dev/null
35
- unalias claude 2>/dev/null
41
+ # The entrypoints are (re)defined from one place so the reassert below installs the
42
+ # same thing the initial source did. The top-level unalias stays: zsh expands aliases
43
+ # while PARSING the function below, so an alias named `claude` that exists when this
44
+ # file is sourced would turn its `claude() {` into a parse error and leave the alias in
45
+ # control. The inner unalias handles an alias that arrives later, at reassert time.
46
+ # `no_err_return`: a missing alias makes `unalias` return 1, and under ERR_RETURN that
47
+ # would end the function before either entrypoint is defined.
48
+ unalias codex 2>/dev/null || :
49
+ unalias claude 2>/dev/null || :
50
+ _agent_launch_define() {
51
+ setopt localoptions no_err_return no_err_exit
52
+ unalias codex 2>/dev/null
53
+ unalias claude 2>/dev/null
54
+ codex() { _agent_launch_dispatch codex "$@"; }
55
+ claude() { _agent_launch_dispatch claude "$@"; }
56
+ return 0
57
+ }
58
+ _agent_launch_define
59
+
60
+ # Reassert the entrypoints right before each command runs. "Last definer wins" is
61
+ # the shell's rule, and a terminal or tool that defines `claude` after the rc files
62
+ # (cmux does, on its first precmd — deliberately, "in case user startup replaced
63
+ # them") would otherwise win in silence: bare `claude` skips the preflight while
64
+ # `codex` keeps working. preexec runs after every precmd, whatever the registration
65
+ # order, so for a prompt-hook shadower the check is the last word at the only moment
66
+ # that matters. Two things it does not do, on purpose: it does not fight a hook that
67
+ # runs after it in preexec (that tool wins; the shadow log names it), and it cannot
68
+ # repair the command already parsed when the shadow is an alias — aliases expand at
69
+ # parse time, so an alias shadow is repaired from the next command on. The downstream
70
+ # stays `builtin command <host>`, so a tool that also owns a PATH shim (cmux) keeps its
71
+ # own injection.
72
+ #
73
+ # Ownership is byte-equality with the body captured at source time, never a marker
74
+ # string: a foreign function that quotes the marker would otherwise pass as ours.
75
+ zmodload -i zsh/parameter 2>/dev/null
76
+ typeset -gA _agent_launch_body _agent_launch_shadow_noted
77
+ _agent_launch_body[claude]="${functions[claude]}"
78
+ _agent_launch_body[codex]="${functions[codex]}"
36
79
 
37
- codex() {
38
- _agent_launch_dispatch codex "$@"
80
+ # Evidence, not repair: one line per host per shell, into the state dir agent-bios
81
+ # already owns — what `agent-bios status`/`verify` read. Never creates the dir (no
82
+ # install, no log). The "noted" flag is set only after the append succeeded, so a
83
+ # directory that cannot be written is retried on the next command instead of being
84
+ # recorded as "no shadowing observed". Tabs and newlines are stripped from every field
85
+ # so a hostile TERM_PROGRAM or function body cannot forge a second row.
86
+ _agent_launch_note_shadow() {
87
+ setopt localoptions extendedglob noksharrays no_err_return no_err_exit
88
+ local host="$1" foreign="$2" state="$HOME/.local/share/agent-bios" first prog stamp
89
+ [[ -n "${_agent_launch_shadow_noted[$host]-}" || ! -d "$state" ]] && return 0
90
+ # Only a regular, non-symlinked file is evidence: a log pointing at /dev/null would
91
+ # take the write, set the flag, and keep nothing.
92
+ [[ -e "$state/shell-shadow.log" && ( -L "$state/shell-shadow.log" || ! -f "$state/shell-shadow.log" ) ]] && return 0
93
+ first="${foreign%%$'\n'*}"
94
+ first="${first##[[:space:]]#}"
95
+ first="${first//[[:cntrl:]]/ }"
96
+ prog="${TERM_PROGRAM:-unknown}"
97
+ prog="${prog//[[:cntrl:]]/ }"
98
+ # `builtin command`: a shell function named `date` must not write this field.
99
+ stamp="$(builtin command date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null)"
100
+ stamp="${stamp//[[:cntrl:]]/ }"
101
+ # `builtin printf`: a shell function named printf could report success and write nothing.
102
+ if builtin printf '%s\t%s\t%s\t%s\n' "${stamp:-<unknown>}" "$host" "$prog" \
103
+ "${first:-<undefined>}" >> "$state/shell-shadow.log" 2>/dev/null; then
104
+ _agent_launch_shadow_noted[$host]=1
105
+ fi
106
+ return 0
39
107
  }
40
108
 
41
- claude() {
42
- _agent_launch_dispatch claude "$@"
109
+ _agent_launch_reassert() {
110
+ setopt localoptions noksharrays no_err_return no_err_exit
111
+ local host foreign entry
112
+ local -a shadowed
113
+ for host in claude codex; do
114
+ foreign=""
115
+ # Existence, not non-emptiness: `alias claude=''` is a shadow that erases the command
116
+ # word. Global aliases live in $galiases, not $aliases; `unalias` removes either.
117
+ if (( ${+aliases[$host]} )); then
118
+ foreign="alias $host=${aliases[$host]}"
119
+ elif (( ${+galiases[$host]} )); then
120
+ foreign="alias -g $host=${galiases[$host]}"
121
+ elif [[ "${functions[$host]-}" != "${_agent_launch_body[$host]}" ]]; then
122
+ foreign="${functions[$host]-<undefined>}"
123
+ fi
124
+ [[ -n "$foreign" ]] && shadowed+=("${host}"$'\t'"${foreign}")
125
+ done
126
+ (( $#shadowed )) || return 0
127
+ # Repair first, then record: a failure to write evidence must never leave the
128
+ # foreign definition in place for the command about to run.
129
+ _agent_launch_define
130
+ for entry in "${shadowed[@]}"; do
131
+ _agent_launch_note_shadow "${entry%%$'\t'*}" "${entry#*$'\t'}"
132
+ done
133
+ return 0
43
134
  }
135
+ # Registered on precmd as well: a tool that redefines the names in a preexec that runs
136
+ # after ours wins for that command, but its definition is still in place when the next
137
+ # prompt is drawn — precmd is where that shadow is observed and logged, so "recorded, not
138
+ # fought" holds for the case the preexec pass cannot see.
139
+ autoload -Uz add-zsh-hook
140
+ add-zsh-hook -d preexec _agent_launch_reassert 2>/dev/null
141
+ add-zsh-hook -d precmd _agent_launch_reassert 2>/dev/null
142
+ add-zsh-hook preexec _agent_launch_reassert
143
+ add-zsh-hook precmd _agent_launch_reassert
144
+
145
+ (( _agent_launch_aliases_were )) && setopt aliases
146
+ unset _agent_launch_aliases_were