@staff0rd/assist 0.515.0 → 0.516.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.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.515.0",
9
+ version: "0.516.1",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -1964,9 +1964,6 @@ function stageAndCommit(files, message3) {
1964
1964
  return commitStaged(message3);
1965
1965
  }
1966
1966
 
1967
- // src/commands/sessions/summarise/iterateUserMessages.ts
1968
- import * as fs from "fs";
1969
-
1970
1967
  // src/commands/sessions/summarise/parseUserLine.ts
1971
1968
  function parseUserLine(line) {
1972
1969
  let entry;
@@ -1992,21 +1989,27 @@ function parseUserLine(line) {
1992
1989
  };
1993
1990
  }
1994
1991
 
1995
- // src/commands/sessions/summarise/iterateUserMessages.ts
1996
- function* iterateUserMessages(filePath, maxBytes = 65536) {
1997
- let content;
1992
+ // src/commands/sessions/summarise/readTranscriptHead.ts
1993
+ import * as fs from "fs";
1994
+ function readTranscriptHead(filePath, maxBytes = 65536) {
1998
1995
  try {
1999
1996
  const fd = fs.openSync(filePath, "r");
2000
1997
  try {
2001
1998
  const buf = Buffer.alloc(maxBytes);
2002
1999
  const bytesRead = fs.readSync(fd, buf, 0, buf.length, 0);
2003
- content = buf.toString("utf8", 0, bytesRead);
2000
+ return buf.toString("utf8", 0, bytesRead);
2004
2001
  } finally {
2005
2002
  fs.closeSync(fd);
2006
2003
  }
2007
2004
  } catch {
2008
- return;
2005
+ return void 0;
2009
2006
  }
2007
+ }
2008
+
2009
+ // src/commands/sessions/summarise/iterateUserMessages.ts
2010
+ function* iterateUserMessages(filePath, maxBytes = 65536) {
2011
+ const content = readTranscriptHead(filePath, maxBytes);
2012
+ if (content === void 0) return;
2010
2013
  for (const line of content.split("\n")) {
2011
2014
  if (!line) continue;
2012
2015
  const entry = parseUserLine(line);
@@ -30329,9 +30332,17 @@ var ISSUE_KEY = /^[A-Z][A-Z0-9]+-\d+$/;
30329
30332
  var HASH_NUMBER = /^#\d+$/;
30330
30333
  var ASSIST_ITEM_ID = /^a[0-9a-f]{2,}$/;
30331
30334
  function isReferenceOnlyPrompt(prompt) {
30332
- const tokens = prompt.trim().split(/\s+/).filter(Boolean);
30335
+ const tokens = tokenise(prompt);
30333
30336
  if (tokens.length === 0) return false;
30334
- return tokens.some(isTrackerUrl) || tokens.every(isReference);
30337
+ return tokens.some(isTrackerUrl) || isBareReferencePrompt(prompt);
30338
+ }
30339
+ function isBareReferencePrompt(prompt) {
30340
+ const tokens = tokenise(prompt);
30341
+ if (tokens.length === 0) return false;
30342
+ return tokens.every(isReference);
30343
+ }
30344
+ function tokenise(prompt) {
30345
+ return prompt.trim().split(/\s+/).filter(Boolean);
30335
30346
  }
30336
30347
  function isReference(token) {
30337
30348
  return isTrackerUrl(token) || ISSUE_KEY.test(token) || HASH_NUMBER.test(token) || ASSIST_ITEM_ID.test(token);
@@ -30903,6 +30914,88 @@ async function reconcileTranscriptStatus(session, onStatusChange) {
30903
30914
  onStatusChange(session, derived);
30904
30915
  }
30905
30916
 
30917
+ // src/commands/sessions/shared/toolTarget.ts
30918
+ function toolTarget(input) {
30919
+ if (!input || typeof input !== "object") return "";
30920
+ const i = input;
30921
+ const str = (v) => typeof v === "string" ? v : "";
30922
+ const target = str(i.file_path) || str(i.path) || str(i.notebook_path) || str(i.command) || str(i.pattern) || str(i.url) || str(i.query) || str(i.description) || str(i.prompt);
30923
+ return target.replace(/\s+/g, " ").trim().slice(0, 120);
30924
+ }
30925
+
30926
+ // src/commands/sessions/shared/entryMessages.ts
30927
+ function entryMessages(entry) {
30928
+ const content = entry.message?.content;
30929
+ if (entry.type === "user") return userMessages(content);
30930
+ if (entry.type === "assistant") return assistantMessages(content);
30931
+ return [];
30932
+ }
30933
+ function userMessages(content) {
30934
+ if (typeof content === "string") return text16("user", cleanUserText(content));
30935
+ if (!Array.isArray(content)) return [];
30936
+ return content.filter((c) => c.type === "text").flatMap((c) => text16("user", cleanUserText(c.text ?? "")));
30937
+ }
30938
+ function assistantMessages(content) {
30939
+ if (typeof content === "string") return text16("assistant", content.trim());
30940
+ if (!Array.isArray(content)) return [];
30941
+ return content.flatMap((c) => assistantItem(c));
30942
+ }
30943
+ function assistantItem(c) {
30944
+ if (c.type === "text") return text16("assistant", (c.text ?? "").trim());
30945
+ if (c.type === "tool_use")
30946
+ return [
30947
+ {
30948
+ role: "tool",
30949
+ tool: typeof c.name === "string" ? c.name : "tool",
30950
+ target: toolTarget(c.input)
30951
+ }
30952
+ ];
30953
+ return [];
30954
+ }
30955
+ function text16(role, value) {
30956
+ return value ? [{ role, text: value }] : [];
30957
+ }
30958
+ function cleanUserText(value) {
30959
+ return value.replace(/<command-[^>]*>[\s\S]*?<\/command-[^>]*>/g, "").replace(/<local-command-[^>]*>[\s\S]*?<\/local-command-[^>]*>/g, "").trim();
30960
+ }
30961
+
30962
+ // src/commands/sessions/summarise/extractContextAfterReference.ts
30963
+ var MIN_CONTEXT_CHARS = 120;
30964
+ var MAX_CONTEXT_CHARS = 800;
30965
+ function extractContextAfterReference(filePath) {
30966
+ const head = readTranscriptHead(filePath);
30967
+ if (head === void 0) return void 0;
30968
+ const parts = [];
30969
+ let length = 0;
30970
+ for (const text17 of conversationText(head)) {
30971
+ if (parts.length === 0 && isBareReferencePrompt(text17)) continue;
30972
+ parts.push(text17);
30973
+ length += text17.length;
30974
+ if (length >= MAX_CONTEXT_CHARS) break;
30975
+ }
30976
+ if (length < MIN_CONTEXT_CHARS) return void 0;
30977
+ return parts.join("\n").slice(0, MAX_CONTEXT_CHARS);
30978
+ }
30979
+ function* conversationText(head) {
30980
+ for (const line of head.split("\n")) {
30981
+ if (!line) continue;
30982
+ const entry = parseEntry(line);
30983
+ if (!entry || entry.isSidechain || entry.isMeta) continue;
30984
+ for (const message3 of entryMessages(entry)) {
30985
+ if (message3.role === "tool") continue;
30986
+ const text17 = message3.text.trim();
30987
+ if (text17) yield text17;
30988
+ }
30989
+ }
30990
+ }
30991
+ function parseEntry(line) {
30992
+ try {
30993
+ return JSON.parse(line);
30994
+ } catch {
30995
+ return void 0;
30996
+ }
30997
+ }
30998
+
30906
30999
  // src/commands/sessions/summarise/extractFirstUserMessage.ts
30907
31000
  function extractFirstUserMessage(filePath) {
30908
31001
  for (const text17 of iterateUserMessages(filePath)) {
@@ -30918,17 +31011,25 @@ function truncate3(text17, maxChars = 500) {
30918
31011
 
30919
31012
  // src/commands/sessions/daemon/startTranscriptTitleGeneration.ts
30920
31013
  function startTranscriptTitleGeneration(session, notify2) {
30921
- if (session.commandType !== "claude") return;
30922
31014
  if (session.generatedTitle || session.titleGenerationStarted) return;
30923
- if (session.initialPrompt?.trim()) return;
31015
+ const source = titleSource(session);
31016
+ if (!source) return;
30924
31017
  const filePath = transcriptPath(session);
30925
31018
  if (!filePath) return;
30926
- const firstMessage = extractFirstUserMessage(filePath);
30927
- if (!firstMessage) return;
31019
+ const context = source === "after-reference" ? extractContextAfterReference(filePath) : extractFirstUserMessage(filePath);
31020
+ if (!context) return;
30928
31021
  daemonLog(
30929
- `session ${session.id} deriving title from first transcript message`
31022
+ source === "after-reference" ? `session ${session.id} deriving title from transcript context after the reference` : `session ${session.id} deriving title from first transcript message`
30930
31023
  );
30931
- runSessionTitleGeneration(session, firstMessage, notify2);
31024
+ runSessionTitleGeneration(session, context, notify2);
31025
+ }
31026
+ function titleSource(session) {
31027
+ if (session.commandType === "claude")
31028
+ return session.initialPrompt?.trim() ? void 0 : "first-message";
31029
+ if (session.activity?.itemName) return void 0;
31030
+ const prompt = sessionTitlePrompt(session);
31031
+ if (!prompt || !isReferenceOnlyPrompt(prompt)) return void 0;
31032
+ return "after-reference";
30932
31033
  }
30933
31034
  function transcriptPath(session) {
30934
31035
  if (session.transcriptPath) return session.transcriptPath;
@@ -33408,53 +33509,6 @@ function handleSetStatus(client, m, d) {
33408
33509
 
33409
33510
  // src/commands/sessions/shared/parseTranscript.ts
33410
33511
  import * as fs39 from "fs";
33411
-
33412
- // src/commands/sessions/shared/toolTarget.ts
33413
- function toolTarget(input) {
33414
- if (!input || typeof input !== "object") return "";
33415
- const i = input;
33416
- const str = (v) => typeof v === "string" ? v : "";
33417
- const target = str(i.file_path) || str(i.path) || str(i.notebook_path) || str(i.command) || str(i.pattern) || str(i.url) || str(i.query) || str(i.description) || str(i.prompt);
33418
- return target.replace(/\s+/g, " ").trim().slice(0, 120);
33419
- }
33420
-
33421
- // src/commands/sessions/shared/entryMessages.ts
33422
- function entryMessages(entry) {
33423
- const content = entry.message?.content;
33424
- if (entry.type === "user") return userMessages(content);
33425
- if (entry.type === "assistant") return assistantMessages(content);
33426
- return [];
33427
- }
33428
- function userMessages(content) {
33429
- if (typeof content === "string") return text16("user", cleanUserText(content));
33430
- if (!Array.isArray(content)) return [];
33431
- return content.filter((c) => c.type === "text").flatMap((c) => text16("user", cleanUserText(c.text ?? "")));
33432
- }
33433
- function assistantMessages(content) {
33434
- if (typeof content === "string") return text16("assistant", content.trim());
33435
- if (!Array.isArray(content)) return [];
33436
- return content.flatMap((c) => assistantItem(c));
33437
- }
33438
- function assistantItem(c) {
33439
- if (c.type === "text") return text16("assistant", (c.text ?? "").trim());
33440
- if (c.type === "tool_use")
33441
- return [
33442
- {
33443
- role: "tool",
33444
- tool: typeof c.name === "string" ? c.name : "tool",
33445
- target: toolTarget(c.input)
33446
- }
33447
- ];
33448
- return [];
33449
- }
33450
- function text16(role, value) {
33451
- return value ? [{ role, text: value }] : [];
33452
- }
33453
- function cleanUserText(value) {
33454
- return value.replace(/<command-[^>]*>[\s\S]*?<\/command-[^>]*>/g, "").replace(/<local-command-[^>]*>[\s\S]*?<\/local-command-[^>]*>/g, "").trim();
33455
- }
33456
-
33457
- // src/commands/sessions/shared/parseTranscript.ts
33458
33512
  async function parseTranscript(sessionId) {
33459
33513
  const filePath = await findSessionJsonlPath(sessionId);
33460
33514
  if (!filePath) return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.515.0",
3
+ "version": "0.516.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {