@factiii/runner 0.11.3 → 0.12.1

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.
@@ -2,7 +2,7 @@
2
2
  "name": "factiii-index-image",
3
3
  "private": true,
4
4
  "dependencies": {
5
- "better-sqlite3": "^11.8.0",
5
+ "better-sqlite3": "^12.11.1",
6
6
  "sqlite-vec": "^0.1.6"
7
7
  }
8
8
  }
package/index/index.js CHANGED
@@ -6915,9 +6915,9 @@ var require_dist = __commonJS({
6915
6915
  }
6916
6916
  });
6917
6917
 
6918
- // ../../node_modules/content-type/index.js
6918
+ // ../../node_modules/@modelcontextprotocol/sdk/node_modules/content-type/index.js
6919
6919
  var require_content_type = __commonJS({
6920
- "../../node_modules/content-type/index.js"(exports2) {
6920
+ "../../node_modules/@modelcontextprotocol/sdk/node_modules/content-type/index.js"(exports2) {
6921
6921
  "use strict";
6922
6922
  var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g;
6923
6923
  var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@factiii/runner",
3
- "version": "0.11.3",
3
+ "version": "0.12.1",
4
4
  "description": "Factiii Runner, run Board AI agents on a machine you control. Pairs with the Factiii web/mobile clients over WebRTC.",
5
5
  "license": "ISC",
6
6
  "keywords": [
@@ -30,6 +30,7 @@
30
30
  "vendor/frpc-linux-arm64",
31
31
  "vendor/frpc-darwin-amd64",
32
32
  "vendor/frpc-darwin-arm64",
33
+ "vendor/tmux-resurrect/",
33
34
  "README.md"
34
35
  ],
35
36
  "scripts": {
@@ -42,8 +43,9 @@
42
43
  "start": "node dist/cli.js",
43
44
  "fetch:frpc": "bash scripts/fetch-frpc.sh",
44
45
  "bundle:index": "pnpm --filter @factiii/index build && rm -rf index && cp -r ../index/image index",
45
- "pack": "node build.mjs && pnpm bundle:index && bash scripts/fetch-frpc.sh && pnpm pack",
46
- "prepublishOnly": "node build.mjs && pnpm bundle:index && bash scripts/fetch-frpc.sh"
46
+ "pack": "node build.mjs && pnpm bundle:index && bash scripts/fetch-frpc.sh && bash scripts/fetch-tmux-resurrect.sh && pnpm pack",
47
+ "prepublishOnly": "node build.mjs && pnpm bundle:index && bash scripts/fetch-frpc.sh && bash scripts/fetch-tmux-resurrect.sh",
48
+ "fetch:resurrect": "bash scripts/fetch-tmux-resurrect.sh"
47
49
  },
48
50
  "dependencies": {
49
51
  "node-datachannel": "^0.12.0"
@@ -0,0 +1 @@
1
+ e87d7d592cac97fa38c12395ebec042c154a1844
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2014 Bruno Sutic
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included
11
+ in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
19
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,13 @@
1
+ # tmux-resurrect (vendored subset)
2
+
3
+ Upstream: <https://github.com/tmux-plugins/tmux-resurrect>
4
+ Version: v4.0.0 (e87d7d5)
5
+ Licence: MIT — see LICENSE.md, Copyright (C) 2014 Bruno Sutic.
6
+
7
+ Unmodified copies of the files the runner executes. Regenerate with
8
+ `apps/runner/scripts/fetch-tmux-resurrect.sh`; do not edit by hand.
9
+
10
+ The runner drives `scripts/save.sh` and `scripts/restore.sh` directly (see
11
+ `shared/all/helpers/board-agent-core/tmux.ts`) rather than through tpm, and
12
+ runs them with `@resurrect-processes false`, so only tab structure and working
13
+ directories come back after a reboot — never the processes that were running.
@@ -0,0 +1 @@
1
+ v4.0.0
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bash
2
+
3
+ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4
+
5
+ PANE_PID="$1"
6
+
7
+ exit_safely_if_empty_ppid() {
8
+ if [ -z "$PANE_PID" ]; then
9
+ exit 0
10
+ fi
11
+ }
12
+
13
+ full_command() {
14
+ ps -ao "ppid command" |
15
+ sed "s/^ *//" |
16
+ grep "^${PANE_PID}" |
17
+ cut -d' ' -f2-
18
+ }
19
+
20
+ main() {
21
+ exit_safely_if_empty_ppid
22
+ full_command
23
+ }
24
+ main
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env bash
2
+
3
+ VERSION="$1"
4
+ UNSUPPORTED_MSG="$2"
5
+
6
+ get_tmux_option() {
7
+ local option=$1
8
+ local default_value=$2
9
+ local option_value=$(tmux show-option -gqv "$option")
10
+ if [ -z "$option_value" ]; then
11
+ echo "$default_value"
12
+ else
13
+ echo "$option_value"
14
+ fi
15
+ }
16
+
17
+ # Ensures a message is displayed for 5 seconds in tmux prompt.
18
+ # Does not override the 'display-time' tmux option.
19
+ display_message() {
20
+ local message="$1"
21
+
22
+ # display_duration defaults to 5 seconds, if not passed as an argument
23
+ if [ "$#" -eq 2 ]; then
24
+ local display_duration="$2"
25
+ else
26
+ local display_duration="5000"
27
+ fi
28
+
29
+ # saves user-set 'display-time' option
30
+ local saved_display_time=$(get_tmux_option "display-time" "750")
31
+
32
+ # sets message display time to 5 seconds
33
+ tmux set-option -gq display-time "$display_duration"
34
+
35
+ # displays message
36
+ tmux display-message "$message"
37
+
38
+ # restores original 'display-time' value
39
+ tmux set-option -gq display-time "$saved_display_time"
40
+ }
41
+
42
+ # this is used to get "clean" integer version number. Examples:
43
+ # `tmux 1.9` => `19`
44
+ # `1.9a` => `19`
45
+ get_digits_from_string() {
46
+ local string="$1"
47
+ local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
48
+ echo "$only_digits"
49
+ }
50
+
51
+ tmux_version_int() {
52
+ local tmux_version_string=$(tmux -V)
53
+ echo "$(get_digits_from_string "$tmux_version_string")"
54
+ }
55
+
56
+ unsupported_version_message() {
57
+ if [ -n "$UNSUPPORTED_MSG" ]; then
58
+ echo "$UNSUPPORTED_MSG"
59
+ else
60
+ echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!"
61
+ fi
62
+ }
63
+
64
+ exit_if_unsupported_version() {
65
+ local current_version="$1"
66
+ local supported_version="$2"
67
+ if [ "$current_version" -lt "$supported_version" ]; then
68
+ display_message "$(unsupported_version_message)"
69
+ exit 1
70
+ fi
71
+ }
72
+
73
+ main() {
74
+ local supported_version_int="$(get_digits_from_string "$VERSION")"
75
+ local current_version_int="$(tmux_version_int)"
76
+ exit_if_unsupported_version "$current_version_int" "$supported_version_int"
77
+ }
78
+ main
@@ -0,0 +1,168 @@
1
+ default_resurrect_dir="$HOME/.tmux/resurrect"
2
+ resurrect_dir_option="@resurrect-dir"
3
+
4
+ SUPPORTED_VERSION="1.9"
5
+ RESURRECT_FILE_PREFIX="tmux_resurrect"
6
+ RESURRECT_FILE_EXTENSION="txt"
7
+ _RESURRECT_DIR=""
8
+ _RESURRECT_FILE_PATH=""
9
+
10
+ d=$'\t'
11
+
12
+ # helper functions
13
+ get_tmux_option() {
14
+ local option="$1"
15
+ local default_value="$2"
16
+ local option_value=$(tmux show-option -gqv "$option")
17
+ if [ -z "$option_value" ]; then
18
+ echo "$default_value"
19
+ else
20
+ echo "$option_value"
21
+ fi
22
+ }
23
+
24
+ # Ensures a message is displayed for 5 seconds in tmux prompt.
25
+ # Does not override the 'display-time' tmux option.
26
+ display_message() {
27
+ local message="$1"
28
+
29
+ # display_duration defaults to 5 seconds, if not passed as an argument
30
+ if [ "$#" -eq 2 ]; then
31
+ local display_duration="$2"
32
+ else
33
+ local display_duration="5000"
34
+ fi
35
+
36
+ # saves user-set 'display-time' option
37
+ local saved_display_time=$(get_tmux_option "display-time" "750")
38
+
39
+ # sets message display time to 5 seconds
40
+ tmux set-option -gq display-time "$display_duration"
41
+
42
+ # displays message
43
+ tmux display-message "$message"
44
+
45
+ # restores original 'display-time' value
46
+ tmux set-option -gq display-time "$saved_display_time"
47
+ }
48
+
49
+
50
+ supported_tmux_version_ok() {
51
+ $CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_VERSION"
52
+ }
53
+
54
+ remove_first_char() {
55
+ echo "$1" | cut -c2-
56
+ }
57
+
58
+ capture_pane_contents_option_on() {
59
+ local option="$(get_tmux_option "$pane_contents_option" "off")"
60
+ [ "$option" == "on" ]
61
+ }
62
+
63
+ files_differ() {
64
+ ! cmp -s "$1" "$2"
65
+ }
66
+
67
+ save_shell_history_option_on() {
68
+ local option_shell="$(get_tmux_option "$shell_history_option" "off")"
69
+ local option_bash="$(get_tmux_option "$bash_history_option" "off")"
70
+
71
+ [ "$option_shell" == "on" ] || [ "$option_bash" == "on" ]
72
+ }
73
+
74
+ get_grouped_sessions() {
75
+ local grouped_sessions_dump="$1"
76
+ export GROUPED_SESSIONS="${d}$(echo "$grouped_sessions_dump" | cut -f2 -d"$d" | tr "\\n" "$d")"
77
+ }
78
+
79
+ is_session_grouped() {
80
+ local session_name="$1"
81
+ [[ "$GROUPED_SESSIONS" == *"${d}${session_name}${d}"* ]]
82
+ }
83
+
84
+ # pane content file helpers
85
+
86
+ pane_contents_create_archive() {
87
+ tar cf - -C "$(resurrect_dir)/save/" ./pane_contents/ |
88
+ gzip > "$(pane_contents_archive_file)"
89
+ }
90
+
91
+ pane_content_files_restore_from_archive() {
92
+ local archive_file="$(pane_contents_archive_file)"
93
+ if [ -f "$archive_file" ]; then
94
+ mkdir -p "$(pane_contents_dir "restore")"
95
+ gzip -d < "$archive_file" |
96
+ tar xf - -C "$(resurrect_dir)/restore/"
97
+ fi
98
+ }
99
+
100
+ # path helpers
101
+
102
+ resurrect_dir() {
103
+ if [ -z "$_RESURRECT_DIR" ]; then
104
+ local path="$(get_tmux_option "$resurrect_dir_option" "$default_resurrect_dir")"
105
+ # expands tilde, $HOME and $HOSTNAME if used in @resurrect-dir
106
+ echo "$path" | sed "s,\$HOME,$HOME,g; s,\$HOSTNAME,$(hostname),g; s,\~,$HOME,g"
107
+ else
108
+ echo "$_RESURRECT_DIR"
109
+ fi
110
+ }
111
+ _RESURRECT_DIR="$(resurrect_dir)"
112
+
113
+ resurrect_file_path() {
114
+ if [ -z "$_RESURRECT_FILE_PATH" ]; then
115
+ local timestamp="$(date +"%Y%m%dT%H%M%S")"
116
+ echo "$(resurrect_dir)/${RESURRECT_FILE_PREFIX}_${timestamp}.${RESURRECT_FILE_EXTENSION}"
117
+ else
118
+ echo "$_RESURRECT_FILE_PATH"
119
+ fi
120
+ }
121
+ _RESURRECT_FILE_PATH="$(resurrect_file_path)"
122
+
123
+ last_resurrect_file() {
124
+ echo "$(resurrect_dir)/last"
125
+ }
126
+
127
+ pane_contents_dir() {
128
+ echo "$(resurrect_dir)/$1/pane_contents/"
129
+ }
130
+
131
+ pane_contents_file() {
132
+ local save_or_restore="$1"
133
+ local pane_id="$2"
134
+ echo "$(pane_contents_dir "$save_or_restore")/pane-${pane_id}"
135
+ }
136
+
137
+ pane_contents_file_exists() {
138
+ local pane_id="$1"
139
+ [ -f "$(pane_contents_file "restore" "$pane_id")" ]
140
+ }
141
+
142
+ pane_contents_archive_file() {
143
+ echo "$(resurrect_dir)/pane_contents.tar.gz"
144
+ }
145
+
146
+ resurrect_history_file() {
147
+ local pane_id="$1"
148
+ local shell_name="$2"
149
+ echo "$(resurrect_dir)/${shell_name}_history-${pane_id}"
150
+ }
151
+
152
+ execute_hook() {
153
+ local kind="$1"
154
+ shift
155
+ local args="" hook=""
156
+
157
+ hook=$(get_tmux_option "$hook_prefix$kind" "")
158
+
159
+ # If there are any args, pass them to the hook (in a way that preserves/copes
160
+ # with spaces and unusual characters.
161
+ if [ "$#" -gt 0 ]; then
162
+ printf -v args "%q " "$@"
163
+ fi
164
+
165
+ if [ -n "$hook" ]; then
166
+ eval "$hook $args"
167
+ fi
168
+ }
@@ -0,0 +1,198 @@
1
+ restore_pane_processes_enabled() {
2
+ local restore_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
3
+ if [ "$restore_processes" == "false" ]; then
4
+ return 1
5
+ else
6
+ return 0
7
+ fi
8
+ }
9
+
10
+ restore_pane_process() {
11
+ local pane_full_command="$1"
12
+ local session_name="$2"
13
+ local window_number="$3"
14
+ local pane_index="$4"
15
+ local dir="$5"
16
+ local command
17
+ if _process_should_be_restored "$pane_full_command" "$session_name" "$window_number" "$pane_index"; then
18
+ tmux switch-client -t "${session_name}:${window_number}"
19
+ tmux select-pane -t "$pane_index"
20
+
21
+ local inline_strategy="$(_get_inline_strategy "$pane_full_command")" # might not be defined
22
+ if [ -n "$inline_strategy" ]; then
23
+ # inline strategy exists
24
+ # check for additional "expansion" of inline strategy, e.g. `vim` to `vim -S`
25
+ if _strategy_exists "$inline_strategy"; then
26
+ local strategy_file="$(_get_strategy_file "$inline_strategy")"
27
+ local inline_strategy="$($strategy_file "$pane_full_command" "$dir")"
28
+ fi
29
+ command="$inline_strategy"
30
+ elif _strategy_exists "$pane_full_command"; then
31
+ local strategy_file="$(_get_strategy_file "$pane_full_command")"
32
+ local strategy_command="$($strategy_file "$pane_full_command" "$dir")"
33
+ command="$strategy_command"
34
+ else
35
+ # just invoke the raw command
36
+ command="$pane_full_command"
37
+ fi
38
+ tmux send-keys -t "${session_name}:${window_number}.${pane_index}" "$command" "C-m"
39
+ fi
40
+ }
41
+
42
+ # private functions below
43
+
44
+ _process_should_be_restored() {
45
+ local pane_full_command="$1"
46
+ local session_name="$2"
47
+ local window_number="$3"
48
+ local pane_index="$4"
49
+ if is_pane_registered_as_existing "$session_name" "$window_number" "$pane_index"; then
50
+ # Scenario where pane existed before restoration, so we're not
51
+ # restoring the proces either.
52
+ return 1
53
+ elif ! pane_exists "$session_name" "$window_number" "$pane_index"; then
54
+ # pane number limit exceeded, pane does not exist
55
+ return 1
56
+ elif _restore_all_processes; then
57
+ return 0
58
+ elif _process_on_the_restore_list "$pane_full_command"; then
59
+ return 0
60
+ else
61
+ return 1
62
+ fi
63
+ }
64
+
65
+ _restore_all_processes() {
66
+ local restore_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
67
+ if [ "$restore_processes" == ":all:" ]; then
68
+ return 0
69
+ else
70
+ return 1
71
+ fi
72
+ }
73
+
74
+ _process_on_the_restore_list() {
75
+ local pane_full_command="$1"
76
+ # TODO: make this work without eval
77
+ eval set $(_restore_list)
78
+ local proc
79
+ local match
80
+ for proc in "$@"; do
81
+ match="$(_get_proc_match_element "$proc")"
82
+ if _proc_matches_full_command "$pane_full_command" "$match"; then
83
+ return 0
84
+ fi
85
+ done
86
+ return 1
87
+ }
88
+
89
+ _proc_matches_full_command() {
90
+ local pane_full_command="$1"
91
+ local match="$2"
92
+ if _proc_starts_with_tildae "$match"; then
93
+ match="$(remove_first_char "$match")"
94
+ # regex matching the command makes sure `$match` string is somewhere in the command string
95
+ if [[ "$pane_full_command" =~ ($match) ]]; then
96
+ return 0
97
+ fi
98
+ else
99
+ # regex matching the command makes sure process is a "word"
100
+ if [[ "$pane_full_command" =~ (^${match} ) ]] || [[ "$pane_full_command" =~ (^${match}$) ]]; then
101
+ return 0
102
+ fi
103
+ fi
104
+ return 1
105
+ }
106
+
107
+ _get_proc_match_element() {
108
+ echo "$1" | sed "s/${inline_strategy_token}.*//"
109
+ }
110
+
111
+ _get_proc_restore_element() {
112
+ echo "$1" | sed "s/.*${inline_strategy_token}//"
113
+ }
114
+
115
+ # given full command: 'ruby /Users/john/bin/my_program arg1 arg2'
116
+ # and inline strategy: '~bin/my_program->my_program *'
117
+ # returns: 'arg1 arg2'
118
+ _get_command_arguments() {
119
+ local pane_full_command="$1"
120
+ local match="$2"
121
+ if _proc_starts_with_tildae "$match"; then
122
+ match="$(remove_first_char "$match")"
123
+ fi
124
+ echo "$pane_full_command" | sed "s,^.*${match}[^ ]* ,,"
125
+ }
126
+
127
+ _get_proc_restore_command() {
128
+ local pane_full_command="$1"
129
+ local proc="$2"
130
+ local match="$3"
131
+ local restore_element="$(_get_proc_restore_element "$proc")"
132
+ if [[ "$restore_element" =~ " ${inline_strategy_arguments_token}" ]]; then
133
+ # replaces "%" with command arguments
134
+ local command_arguments="$(_get_command_arguments "$pane_full_command" "$match")"
135
+ echo "$restore_element" | sed "s/${inline_strategy_arguments_token}/${command_arguments}/"
136
+ else
137
+ echo "$restore_element"
138
+ fi
139
+ }
140
+
141
+ _restore_list() {
142
+ local user_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
143
+ local default_processes="$(get_tmux_option "$default_proc_list_option" "$default_proc_list")"
144
+ if [ -z "$user_processes" ]; then
145
+ # user didn't define any processes
146
+ echo "$default_processes"
147
+ else
148
+ echo "$default_processes $user_processes"
149
+ fi
150
+ }
151
+
152
+ _proc_starts_with_tildae() {
153
+ [[ "$1" =~ (^~) ]]
154
+ }
155
+
156
+ _get_inline_strategy() {
157
+ local pane_full_command="$1"
158
+ # TODO: make this work without eval
159
+ eval set $(_restore_list)
160
+ local proc
161
+ local match
162
+ for proc in "$@"; do
163
+ if [[ "$proc" =~ "$inline_strategy_token" ]]; then
164
+ match="$(_get_proc_match_element "$proc")"
165
+ if _proc_matches_full_command "$pane_full_command" "$match"; then
166
+ echo "$(_get_proc_restore_command "$pane_full_command" "$proc" "$match")"
167
+ fi
168
+ fi
169
+ done
170
+ }
171
+
172
+ _strategy_exists() {
173
+ local pane_full_command="$1"
174
+ local strategy="$(_get_command_strategy "$pane_full_command")"
175
+ if [ -n "$strategy" ]; then # strategy set?
176
+ local strategy_file="$(_get_strategy_file "$pane_full_command")"
177
+ [ -e "$strategy_file" ] # strategy file exists?
178
+ else
179
+ return 1
180
+ fi
181
+ }
182
+
183
+ _get_command_strategy() {
184
+ local pane_full_command="$1"
185
+ local command="$(_just_command "$pane_full_command")"
186
+ get_tmux_option "${restore_process_strategy_option}${command}" ""
187
+ }
188
+
189
+ _just_command() {
190
+ echo "$1" | cut -d' ' -f1
191
+ }
192
+
193
+ _get_strategy_file() {
194
+ local pane_full_command="$1"
195
+ local strategy="$(_get_command_strategy "$pane_full_command")"
196
+ local command="$(_just_command "$pane_full_command")"
197
+ echo "$CURRENT_DIR/../strategies/${command}_${strategy}.sh"
198
+ }