friend-assistant 0.1.68 → 0.1.69

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/dist/BUILD.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "friend-assistant",
3
- "version": "0.1.68",
4
- "builtAt": "2026-11-06T16:47:34.719Z"
3
+ "version": "0.1.69",
4
+ "builtAt": "2026-11-06T17:44:37.926Z"
5
5
  }
package/dist/friend.mjs CHANGED
@@ -18489,7 +18489,7 @@ function startStatsFeed(opts) {
18489
18489
 
18490
18490
  // ../server/src/provider/claude-code/provider.ts
18491
18491
  import { createHash as createHash12 } from "node:crypto";
18492
- import { chmodSync as chmodSync7, existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync13, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "node:fs";
18492
+ import { chmodSync as chmodSync7, existsSync as existsSync20, mkdirSync as mkdirSync14, readdirSync as readdirSync7, readFileSync as readFileSync13, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "node:fs";
18493
18493
  import { join as join23 } from "node:path";
18494
18494
 
18495
18495
  // ../server/src/provider/claude-code/limits.ts
@@ -18822,6 +18822,7 @@ ${item.stderr}`;
18822
18822
  this.bridge.setTools(req.tools);
18823
18823
  }
18824
18824
  const resume = conv.guest ? null : conv.sessionId;
18825
+ const systemFile = this.writeSystem(req.system);
18825
18826
  const model3 = this.opts.model ?? "sonnet";
18826
18827
  const web = !conv.guest && !!this.opts.webSearch;
18827
18828
  const args = [
@@ -18841,8 +18842,8 @@ ${item.stderr}`;
18841
18842
  web ? "WebSearch" : "",
18842
18843
  "--setting-sources",
18843
18844
  "local",
18844
- "--system-prompt",
18845
- req.system,
18845
+ "--system-prompt-file",
18846
+ systemFile,
18846
18847
  ...conv.guest ? ["--no-session-persistence"] : ["--mcp-config", join23(this.home, "mcp.json"), "--allowedTools", [...web ? ["WebSearch"] : [], ...req.tools.map((t) => `mcp__friend__${encodeToolName(t.name)}`)].join(","), ...resume ? ["--resume", resume] : []]
18847
18848
  ];
18848
18849
  const proc = new ClaudeProc(
@@ -18865,6 +18866,25 @@ ${item.stderr}`;
18865
18866
  conv.hasContext = !!resume;
18866
18867
  conv.gotEvent = false;
18867
18868
  }
18869
+ systemCount = 0;
18870
+ swept = false;
18871
+ /** Writes the instructions for one Claude process to a file of its own and returns its path. Old ones are cleared when Friend starts. */
18872
+ writeSystem(text4) {
18873
+ if (!this.swept) {
18874
+ this.swept = true;
18875
+ try {
18876
+ for (const f of readdirSync7(this.home)) if (/^system-\d+\.txt$/.test(f)) rmSync11(join23(this.home, f), { force: true });
18877
+ } catch {
18878
+ }
18879
+ }
18880
+ const file = join23(this.home, `system-${++this.systemCount}.txt`);
18881
+ writeFileSync15(file, text4);
18882
+ try {
18883
+ chmodSync7(file, 384);
18884
+ } catch {
18885
+ }
18886
+ return file;
18887
+ }
18868
18888
  endGuest(conv) {
18869
18889
  if (!conv.proc) return;
18870
18890
  this.guests.delete(conv.proc);
@@ -20223,7 +20243,7 @@ function currentSelf() {
20223
20243
  // ../server/src/system/npm.ts
20224
20244
  import { spawn as spawn9 } from "node:child_process";
20225
20245
  var PACKAGE = "friend-assistant";
20226
- var runningVersion = () => true ? "0.1.68" : "development";
20246
+ var runningVersion = () => true ? "0.1.69" : "development";
20227
20247
  async function npmLatest(fetchFn = fetch, timeoutMs = 1e4) {
20228
20248
  try {
20229
20249
  const res = await fetchFn(`https://registry.npmjs.org/${PACKAGE}/latest`, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(timeoutMs) });
@@ -23151,7 +23171,7 @@ import { resolve as resolve9 } from "node:path";
23151
23171
  import { WebSocket as WebSocket4 } from "ws";
23152
23172
 
23153
23173
  // ../agent-cli/src/tools/fs.ts
23154
- import { closeSync, mkdirSync as mkdirSync18, openSync, readSync, readdirSync as readdirSync7, statSync as statSync7, writeFileSync as writeFileSync19 } from "node:fs";
23174
+ import { closeSync, mkdirSync as mkdirSync18, openSync, readSync, readdirSync as readdirSync8, statSync as statSync7, writeFileSync as writeFileSync19 } from "node:fs";
23155
23175
  import { dirname as dirname9, join as join26 } from "node:path";
23156
23176
 
23157
23177
  // ../agent-cli/src/tools/roots.ts
@@ -23209,7 +23229,7 @@ function fsList(args, ctx) {
23209
23229
  const g = guard(args.path, ctx);
23210
23230
  if ("error" in g) return { ok: false, error: g.error };
23211
23231
  try {
23212
- const entries = readdirSync7(g.abs, { withFileTypes: true });
23232
+ const entries = readdirSync8(g.abs, { withFileTypes: true });
23213
23233
  const lines = entries.slice(0, MAX_ENTRIES).map((e) => {
23214
23234
  if (e.isDirectory()) return `[dir] ${e.name}`;
23215
23235
  let size = 0;
@@ -24144,7 +24164,7 @@ async function memoryCommand(args, io2) {
24144
24164
  }
24145
24165
 
24146
24166
  // ../agent-cli/src/commands/plugin.ts
24147
- import { existsSync as existsSync27, readdirSync as readdirSync8, statSync as statSync8 } from "node:fs";
24167
+ import { existsSync as existsSync27, readdirSync as readdirSync9, statSync as statSync8 } from "node:fs";
24148
24168
  import { dirname as dirname12, join as join30, resolve as resolve10 } from "node:path";
24149
24169
  import { fileURLToPath as fileURLToPath5 } from "node:url";
24150
24170
  var USAGE2 = "Usage: friend plugin catalog | list | install <name|folder> [--yes] | enable <id> | disable <id> | remove <id>";
@@ -24159,7 +24179,7 @@ async function pluginCommand(args, io2, deps = {}) {
24159
24179
  const flags = rest.filter((a) => a.startsWith("--"));
24160
24180
  const arg = rest.find((a) => !a.startsWith("--"));
24161
24181
  if (sub === "catalog") {
24162
- const dirs = existsSync27(catalogDir) ? readdirSync8(catalogDir).filter((d) => statSync8(join30(catalogDir, d)).isDirectory()) : [];
24182
+ const dirs = existsSync27(catalogDir) ? readdirSync9(catalogDir).filter((d) => statSync8(join30(catalogDir, d)).isDirectory()) : [];
24163
24183
  if (dirs.length === 0) io2.out("The catalog is empty.");
24164
24184
  for (const d of dirs.sort()) {
24165
24185
  const r = inspectPlugin(join30(catalogDir, d));
@@ -25510,7 +25530,7 @@ import { appendFileSync } from "node:fs";
25510
25530
  import { join as join34 } from "node:path";
25511
25531
  var PACKAGE2 = "friend-assistant";
25512
25532
  var real2 = {
25513
- current: () => true ? "0.1.68" : "development",
25533
+ current: () => true ? "0.1.69" : "development",
25514
25534
  latest: () => new Promise((resolve13) => {
25515
25535
  const child = crossSpawn5("npm", ["view", PACKAGE2, "version", "--prefer-online"], { stdio: ["ignore", "pipe", "ignore"] });
25516
25536
  let out = "";
@@ -25828,7 +25848,7 @@ async function run(argv, io2) {
25828
25848
  case "version":
25829
25849
  case "--version":
25830
25850
  case "-v":
25831
- io2.out(true ? "0.1.68" : "development");
25851
+ io2.out(true ? "0.1.69" : "development");
25832
25852
  return 0;
25833
25853
  case "lan":
25834
25854
  return await lanCommand(rest, io2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "friend-assistant",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "A self-hosted personal AI assistant for your own PC: a full-screen stage, voice, tools with your approval, and your Claude subscription or a local model.",
5
5
  "keywords": ["ai", "assistant", "jarvis", "voice", "claude", "ollama", "mcp", "self-hosted"],
6
6
  "license": "UNLICENSED",