@qearlyao/familiar 0.1.1 → 0.1.2

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.
package/README.md CHANGED
@@ -30,7 +30,13 @@ irm https://raw.githubusercontent.com/qearlyao/familiar/main/scripts/install.ps1
30
30
  ```
31
31
 
32
32
  The installer checks Node/npm, installs Familiar globally, and initializes
33
- `~/.familiar` when no workspace exists yet.
33
+ or refreshes missing default files in `~/.familiar`.
34
+
35
+ Installer options:
36
+
37
+ - macOS/Linux: `--workspace <path>`, `--with-browser`, `--install-browser-deps`, `--skip-init`, `--package <spec>`.
38
+ - Windows PowerShell: `-Workspace <path>`, `-WithBrowser`, `-InstallBrowserDeps`, `-SkipInit`, `-Package <spec>`, `-BrowserHarnessDir <path>`.
39
+ - `--package` / `-Package` installs the exact npm package spec you provide. Use trusted specs only.
34
40
 
35
41
  Manual npm install:
36
42
 
@@ -171,7 +177,8 @@ Windows PowerShell:
171
177
  & ([scriptblock]::Create((irm https://raw.githubusercontent.com/qearlyao/familiar/main/scripts/install.ps1))) -WithBrowser
172
178
  ```
173
179
 
174
- - `--with-browser` installs OpenCLI with npm and browser-harness from its upstream repo with `uv`; it requires `git`, `uv`, and Python 3.11+.
180
+ - `--with-browser` / `-WithBrowser` installs OpenCLI with npm and browser-harness from its upstream repo with `uv`; it requires `git`, `uv`, and Python 3.11+.
181
+ - If `uv` or Python 3.11+ is missing, the installer asks whether to install the missing browser dependency. Use `--install-browser-deps` / `-InstallBrowserDeps` for non-interactive installs.
175
182
  - `browser-harness` is best for attaching to your already-running Chrome via CDP.
176
183
  - OpenCLI is best for site adapters, owned sessions, and unattended Browser Bridge flows.
177
184
  - OpenCLI: [jackwener/OpenCLI](https://github.com/jackwener/OpenCLI)
package/dist/agent.js CHANGED
@@ -415,16 +415,6 @@ export async function createFamiliarAgent(config, settings, memoryService, optio
415
415
  session.agent.state.tools = createFamiliarTools(config, session.mediaSink, () => session.referenceAttachments, memoryService);
416
416
  session.agent.state.thinkingLevel = session.thinkingLevel;
417
417
  };
418
- const refreshSession = (session, sessionKey) => {
419
- const { model } = resolveChannelModel(sessionKey);
420
- const thinkingLevel = resolveChannelThinkingLevel(sessionKey, model).value;
421
- session.model = model;
422
- session.thinkingLevel = thinkingLevel;
423
- session.agent.state.systemPrompt = systemPrompt;
424
- session.agent.state.model = model;
425
- session.agent.state.thinkingLevel = thinkingLevel;
426
- session.agent.state.tools = createFamiliarTools(config, session.mediaSink, () => session.referenceAttachments, memoryService);
427
- };
428
418
  const prepareReload = async () => {
429
419
  const nextConfig = (await options.reloadConfig?.()) ?? config;
430
420
  const nextPersona = await loadPersona(nextConfig);
package/dist/cli.js CHANGED
@@ -136,7 +136,9 @@ async function runDaemon(workspaceInput) {
136
136
  setTimeout(() => void stop(75), RESTART_EXIT_DELAY_MS);
137
137
  return "Restart requested. If Familiar is managed by launchd/systemd, it should come back automatically; otherwise run familiar run again.";
138
138
  };
139
- discordDaemon = await startDiscordDaemon(config, familiarAgent, settings, memoryService, { restart: requestRestart });
139
+ discordDaemon = await startDiscordDaemon(config, familiarAgent, settings, memoryService, {
140
+ restart: requestRestart,
141
+ });
140
142
  webDaemon = await startWebDaemon(config, familiarAgent, discordDaemon, { restart: requestRestart });
141
143
  console.log(`familiar running for workspace ${config.workspacePath}`);
142
144
  console.log("agent sessions are created per channel");
@@ -91,7 +91,9 @@ export function startWorkspaceHotReload(options) {
91
91
  (basename(dirPath) === SKILLS_DIR || relative(workspacePath, dirPath).startsWith(`${SKILLS_DIR}${sep}`))) {
92
92
  void refreshSkillWatchers();
93
93
  }
94
- if (!filename || shouldReloadForPath(workspacePath, changedPath) || shouldReloadForPath(workspacePath, dirPath)) {
94
+ if (!filename ||
95
+ shouldReloadForPath(workspacePath, changedPath) ||
96
+ shouldReloadForPath(workspacePath, dirPath)) {
95
97
  scheduleReload(relative(workspacePath, changedPath) || relative(workspacePath, dirPath) || ".");
96
98
  }
97
99
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qearlyao/familiar",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -3,6 +3,7 @@ param(
3
3
  [string]$Package = "@qearlyao/familiar@latest",
4
4
  [string]$BrowserHarnessDir = (Join-Path (Join-Path $HOME "Developer") "browser-harness"),
5
5
  [switch]$WithBrowser,
6
+ [switch]$InstallBrowserDeps,
6
7
  [switch]$SkipInit
7
8
  )
8
9
 
@@ -14,6 +15,47 @@ function Require-Command($Name) {
14
15
  }
15
16
  }
16
17
 
18
+ function Update-BrowserDepPath {
19
+ $candidates = @((Join-Path $HOME ".local\bin"), (Join-Path $HOME ".cargo\bin"))
20
+ foreach ($candidate in $candidates) {
21
+ if ((Test-Path $candidate) -and (($env:PATH -split [IO.Path]::PathSeparator) -notcontains $candidate)) {
22
+ $env:PATH = "$candidate$([IO.Path]::PathSeparator)$env:PATH"
23
+ }
24
+ }
25
+ }
26
+
27
+ function Confirm-BrowserDepInstall($Message) {
28
+ if ($InstallBrowserDeps) {
29
+ return $true
30
+ }
31
+ try {
32
+ $answer = Read-Host "$Message Install it now? [y/N]"
33
+ return $answer -match '^(y|yes)$'
34
+ } catch {
35
+ return $false
36
+ }
37
+ }
38
+
39
+ function Install-Uv {
40
+ Write-Host "Installing uv for browser-harness..."
41
+ irm https://astral.sh/uv/install.ps1 | iex
42
+ Update-BrowserDepPath
43
+ if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
44
+ throw "uv installer finished, but uv is not on PATH. Open a new terminal or add $HOME\.local\bin to PATH."
45
+ }
46
+ }
47
+
48
+ function Ensure-Uv {
49
+ if (Get-Command uv -ErrorAction SilentlyContinue) {
50
+ return
51
+ }
52
+ if (Confirm-BrowserDepInstall "uv is required for browser-harness but was not found.") {
53
+ Install-Uv
54
+ return
55
+ }
56
+ throw "Missing required command: uv. Rerun with -WithBrowser -InstallBrowserDeps to install uv and Python 3.11 automatically."
57
+ }
58
+
17
59
  function Test-Python311($Command, $PythonArgs = @()) {
18
60
  & $Command @PythonArgs -c "import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else 1)" *> $null
19
61
  return $LASTEXITCODE -eq 0
@@ -32,15 +74,31 @@ function Resolve-Python311 {
32
74
  if ($py -and (Test-Python311 $py.Source @("-3.11"))) {
33
75
  return @{ Command = $py.Source; Args = @("-3.11"); UvPython = "3.11" }
34
76
  }
35
- throw "browser-harness requires Python 3.11 or newer. Install Python 3.11+ and rerun with -WithBrowser."
77
+ return $null
78
+ }
79
+
80
+ function Ensure-Python311 {
81
+ $python311 = Resolve-Python311
82
+ if ($python311) {
83
+ return $python311
84
+ }
85
+ if (Confirm-BrowserDepInstall "Python 3.11+ is required for browser-harness but was not found.") {
86
+ Write-Host "Installing Python 3.11 with uv for browser-harness..."
87
+ & uv python install 3.11
88
+ if ($LASTEXITCODE -ne 0) {
89
+ throw "Python 3.11 install failed."
90
+ }
91
+ return @{ Command = "uv"; Args = @("python", "find", "3.11"); UvPython = "3.11" }
92
+ }
93
+ throw "browser-harness requires Python 3.11 or newer. Rerun with -WithBrowser -InstallBrowserDeps to install uv-managed Python 3.11 automatically."
36
94
  }
37
95
 
38
96
  Require-Command node
39
97
  Require-Command npm
40
98
  if ($WithBrowser) {
41
99
  Require-Command git
42
- Require-Command uv
43
- $Python311 = Resolve-Python311
100
+ Ensure-Uv
101
+ $Python311 = Ensure-Python311
44
102
  }
45
103
 
46
104
  $nodeVersion = (& node -p "process.versions.node").Trim()
@@ -105,15 +163,10 @@ if (-not (Get-Command familiar -ErrorAction SilentlyContinue)) {
105
163
  }
106
164
 
107
165
  if (-not $SkipInit) {
108
- $configPath = Join-Path $Workspace "config.toml"
109
- if (Test-Path $configPath) {
110
- Write-Host "Workspace already exists at $Workspace; leaving files unchanged."
111
- } else {
112
- Write-Host "Initializing workspace at $Workspace..."
113
- & familiar init $Workspace
114
- if ($LASTEXITCODE -ne 0) {
115
- throw "familiar init failed."
116
- }
166
+ Write-Host "Initializing or refreshing workspace defaults at $Workspace..."
167
+ & familiar init $Workspace
168
+ if ($LASTEXITCODE -ne 0) {
169
+ throw "familiar init failed."
117
170
  }
118
171
  }
119
172
 
@@ -5,6 +5,7 @@ PACKAGE="@qearlyao/familiar@latest"
5
5
  WORKSPACE="${HOME}/.familiar"
6
6
  BROWSER_HARNESS_DIR="${HOME}/Developer/browser-harness"
7
7
  WITH_BROWSER=0
8
+ INSTALL_BROWSER_DEPS=0
8
9
  SKIP_INIT=0
9
10
 
10
11
  usage() {
@@ -14,6 +15,8 @@ Usage: install.sh [options]
14
15
  Options:
15
16
  --workspace <path> Workspace path to initialize. Defaults to ~/.familiar.
16
17
  --with-browser Also install optional OpenCLI and browser-harness helpers.
18
+ --install-browser-deps
19
+ With --with-browser, install missing uv/Python 3.11 browser deps without prompting.
17
20
  --skip-init Install familiar but do not run familiar init.
18
21
  --package <spec> npm package spec to install. Defaults to @qearlyao/familiar@latest.
19
22
  Advanced: installs the exact npm spec provided; use trusted specs only.
@@ -35,6 +38,10 @@ while [ "$#" -gt 0 ]; do
35
38
  WITH_BROWSER=1
36
39
  shift
37
40
  ;;
41
+ --install-browser-deps)
42
+ INSTALL_BROWSER_DEPS=1
43
+ shift
44
+ ;;
38
45
  --skip-init)
39
46
  SKIP_INIT=1
40
47
  shift
@@ -66,6 +73,63 @@ need_command() {
66
73
  fi
67
74
  }
68
75
 
76
+ refresh_browser_dep_path() {
77
+ for candidate in "${HOME}/.local/bin" "${HOME}/.cargo/bin"; do
78
+ if [ -d "$candidate" ]; then
79
+ case ":${PATH}:" in
80
+ *":${candidate}:"*) ;;
81
+ *) PATH="${candidate}:${PATH}" ;;
82
+ esac
83
+ fi
84
+ done
85
+ export PATH
86
+ }
87
+
88
+ confirm_browser_dep_install() {
89
+ if [ "$INSTALL_BROWSER_DEPS" -eq 1 ]; then
90
+ return 0
91
+ fi
92
+ if [ -r /dev/tty ] && [ -w /dev/tty ]; then
93
+ printf "%s Install it now? [y/N] " "$1" >/dev/tty
94
+ read -r answer </dev/tty || answer=""
95
+ case "$answer" in
96
+ y | Y | yes | YES) return 0 ;;
97
+ esac
98
+ fi
99
+ return 1
100
+ }
101
+
102
+ install_uv() {
103
+ echo "Installing uv for browser-harness..."
104
+ if command -v curl >/dev/null 2>&1; then
105
+ curl -LsSf https://astral.sh/uv/install.sh | sh
106
+ elif command -v wget >/dev/null 2>&1; then
107
+ wget -qO- https://astral.sh/uv/install.sh | sh
108
+ else
109
+ echo "Missing curl or wget, which is required to install uv automatically." >&2
110
+ echo "Install uv manually from https://docs.astral.sh/uv/ and rerun with --with-browser." >&2
111
+ exit 1
112
+ fi
113
+ refresh_browser_dep_path
114
+ if ! command -v uv >/dev/null 2>&1; then
115
+ echo "uv installer finished, but uv is not on PATH. Open a new terminal or add ~/.local/bin to PATH." >&2
116
+ exit 1
117
+ fi
118
+ }
119
+
120
+ ensure_uv() {
121
+ if command -v uv >/dev/null 2>&1; then
122
+ return 0
123
+ fi
124
+ if confirm_browser_dep_install "uv is required for browser-harness but was not found."; then
125
+ install_uv
126
+ return 0
127
+ fi
128
+ echo "Missing required command: uv" >&2
129
+ echo "Rerun with --with-browser --install-browser-deps to install uv and Python 3.11 automatically." >&2
130
+ exit 1
131
+ }
132
+
69
133
  find_python() {
70
134
  PYTHON_PATH=""
71
135
  for candidate in python3 python; do
@@ -77,7 +141,21 @@ find_python() {
77
141
  fi
78
142
  fi
79
143
  done
80
- echo "browser-harness requires Python 3.11 or newer. Install Python 3.11+ and rerun with --with-browser." >&2
144
+ return 1
145
+ }
146
+
147
+ ensure_python() {
148
+ if find_python; then
149
+ return 0
150
+ fi
151
+ if confirm_browser_dep_install "Python 3.11+ is required for browser-harness but was not found."; then
152
+ echo "Installing Python 3.11 with uv for browser-harness..."
153
+ uv python install 3.11
154
+ PYTHON_PATH="3.11"
155
+ return 0
156
+ fi
157
+ echo "browser-harness requires Python 3.11 or newer." >&2
158
+ echo "Rerun with --with-browser --install-browser-deps to install uv-managed Python 3.11 automatically." >&2
81
159
  exit 1
82
160
  }
83
161
 
@@ -85,8 +163,8 @@ need_command node
85
163
  need_command npm
86
164
  if [ "$WITH_BROWSER" -eq 1 ]; then
87
165
  need_command git
88
- need_command uv
89
- find_python
166
+ ensure_uv
167
+ ensure_python
90
168
  fi
91
169
 
92
170
  NODE_VERSION="$(node -p "process.versions.node")"
@@ -127,12 +205,8 @@ if ! command -v familiar >/dev/null 2>&1; then
127
205
  fi
128
206
 
129
207
  if [ "$SKIP_INIT" -eq 0 ]; then
130
- if [ -f "${WORKSPACE}/config.toml" ]; then
131
- echo "Workspace already exists at ${WORKSPACE}; leaving files unchanged."
132
- else
133
- echo "Initializing workspace at ${WORKSPACE}..."
134
- familiar init "$WORKSPACE"
135
- fi
208
+ echo "Initializing or refreshing workspace defaults at ${WORKSPACE}..."
209
+ familiar init "$WORKSPACE"
136
210
  fi
137
211
 
138
212
  cat <<EOF