ente-cli 0.4.61 → 0.4.63

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
@@ -131,7 +131,7 @@ Every command supports `--json`. Run `ente --help` or `ente <group> --help`.
131
131
  |---|---|
132
132
  | `auth` | `pair`, `login`, `status`, `logout`, `profiles` |
133
133
  | `entity` | `list`, `create`, `get`, `update` (`--name`, `--tag`, `--description`), `rename`, `archive`, `restore` (`--share-parents` plus the returned grant fingerprint), `pin` (`--role`, optional confirmed parent grants), `unpin`, `add-to-space`, `remove-from-space` (`--remove-from-activities` optional) |
134
- | `activity` | `list`, `create`, `search`, `get`, `update`, `delete`, `restore`, `message add`, `attachment upload` |
134
+ | `activity` | `list`, `create`, `search`, `get`, `transcript` (`--grep`, `--context`), `update`, `delete`, `restore`, `message add`, `attachment upload` |
135
135
  | `agenda` | `create-point`, `link-task` |
136
136
  | `task` | `list`, `get`, `create`, `update`, `done`, `assign`, `unassign`, `set-assignees`, `clear-assignees` |
137
137
  | `pins` | `list` |
@@ -367,3 +367,5 @@ Task assignment accepts multiple agents alongside humans. Use repeatable
367
367
  space and title arguments, or `ente activity update <activityId> --agent-assignee <agentId>`.
368
368
  Updating replaces agent assignees and preserves human assignees. Use
369
369
  `--clear-agent-assignees` to remove them. Only active agents with write access qualify.
370
+
371
+ Scheduled runs also accept `runCondition: "new_chats"`: skip model execution unless this agent has new manual or recording chats since its previous scheduled check. Scheduled/reflection chats do not trigger it; explicit Run now bypasses the condition.
package/dist/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: m:ente-cli
3
3
  description: "Cli: drives the ente CRM and knowledge graph over its Convex API as the signed-in user — entities (people, organisations, projects, topics, places, objects), activities (notes, calls, meetings, tasks), relationships, spaces, full-text and AI-backed search, agent threads and mail, plus Excalidraw canvas prototypes. Use when context about a person, an organisation or a meeting has to be stored, looked up or updated from the shell. Not for splitting shared costs, which is schnorrer-cli."
4
- when_to_use: "Remembering what was said in a call or meeting; looking up open tasks, deadlines or follow-ups for a person or project; creating or renaming an entity and pinning it to a parent; linking an activity to several entities or moving it between spaces; asking a question over the whole graph and getting citations; reviewing the voice-recording prompt or debugging a failed recording; sending a notification mail or an agent-inbox reply; posting to the in-app feedback board; managing Excalidraw canvas HTML prototypes on an entity board."
4
+ when_to_use: "Remembering what was said in a call or meeting, including reading or searching the transcript of the recording behind an activity; looking up open tasks, deadlines or follow-ups for a person or project; creating or renaming an entity and pinning it to a parent; linking an activity to several entities or moving it between spaces; asking a question over the whole graph and getting citations; reviewing the voice-recording prompt or debugging a failed recording; sending a notification mail or an agent-inbox reply; posting to the in-app feedback board; managing Excalidraw canvas HTML prototypes on an entity board."
5
5
  metadata:
6
6
  short-description: Relationship memory through ente
7
7
  ---
@@ -132,6 +132,7 @@ ente activity list [--entity "Jane"] [--type note|conversation|meeting|call|mess
132
132
  ente activity create --type meeting --title "Call with Jane" --entity "Jane Doe" --entity "Acme Corp" --space "Work" [--content "…"] [--content-file ./notes.md] [--auto-link --entity-space-grant-fingerprint <token>] [--json]
133
133
  ente activity search "quarterly review" [--entity "Acme"] [--type meeting] [--limit 10] [--json]
134
134
  ente activity get <activityId> [--json] # complete detail: body, full nested agenda, messages/replies, entities, attachments
135
+ ente activity transcript <activityId> [--grep "Preis"] [--context 2] [--recording <id>] [--json] # transcript of the recording behind it
135
136
  ente activity update <activityId> [--title "…"] [--content "…"] [--entity-add "Bob"] [--entity-remove "Carol"] [--agent-assignee <agentId> ... | --clear-agent-assignees] [--json]
136
137
  ente activity content read <activityId> [--cursor <cursor> --expected-version <version>] [--max-blocks 20] [--max-characters 12000] [--json]
137
138
  ente activity content edit <activityId> --expected-version <version> --operations-file ./operations.json [--json]
@@ -285,6 +286,30 @@ board is already dense. The create result includes `reviewPath`. Update and dele
285
286
  read and fail on a concurrent human edit. These remote scene changes sync into open boards, but do
286
287
  not enter another browser's local undo stack.
287
288
 
289
+ ### Recording transcripts — check them when something is unclear
290
+
291
+ Activities, notes and summaries made from a recording keep only what the
292
+ recording agent chose to keep. **When a note, summary, task or meeting record is
293
+ unclear, contradictory or lacks a detail you need (an amount, a date, who said
294
+ what, the reason for a decision), deliberately read the transcript before you
295
+ answer or act** — do not guess from the summary.
296
+
297
+ ```bash
298
+ ente activity transcript <activityId> # every recording that created or changed it, full transcript
299
+ ente activity transcript <activityId> --grep "Rechnung" --context 3 # only the passages around a term
300
+ ```
301
+
302
+ - Finds recordings through the agent runs that created or changed the activity; an
303
+ activity made by hand, or by a recording processed outside Ente, has none.
304
+ - Your own recordings are always readable. Another member's recording is readable
305
+ only when **everything it wrote** (activities, entities, agenda points, pins) lies
306
+ in spaces you are a member of, and your agent key may read those spaces. Otherwise
307
+ it is listed with the reason (`outside_reader_spaces`, `untraceable_tool` for mail,
308
+ calendar or space moves, `processing`, …) and no text.
309
+ - `--grep` matches case-insensitively by sentence or line. `--json` returns per
310
+ recording either `transcript`, or with `--grep` `transcript: null` plus `matches`
311
+ (lists of passages). At most the 5 newest recordings are listed.
312
+
288
313
  ### Recording (voice) pipeline
289
314
 
290
315
  ```bash
@@ -371,6 +396,7 @@ ente feedback status <feedbackId> <status> # move to a board colum
371
396
  5. **Operate** — entity/activity/task CRUD (prefer `--json` for parsing).
372
397
  6. **Link precisely** — link independently central entities, prefer specific children, and omit ancestors that are implied by hierarchy.
373
398
  7. **Confirm** — re-run the relevant list/get after writes to verify.
399
+ 8. **Unclear? Read the source** — if an activity from a recording leaves a question open, run `ente activity transcript <activityId> --grep <term>` before answering.
374
400
 
375
401
  ---
376
402
 
@@ -480,3 +506,5 @@ Assign agents to tasks with repeatable `activity create --agent-assignee <agentI
480
506
  `activity update <activityId> --agent-assignee <agentId>`. Updating replaces only agent
481
507
  assignees and preserves humans. `--clear-agent-assignees` removes the agent assignments.
482
508
  Assignment requires the agent to have write access in the task space; it grants no access.
509
+
510
+ Scheduled runs also accept `runCondition: "new_chats"`: skip model execution unless this agent has new manual or recording chats since its previous scheduled check. Scheduled/reflection chats do not trigger it; explicit Run now bypasses the condition.
package/dist/cli.mjs CHANGED
@@ -3711,7 +3711,7 @@ function warn(opts, latest) {
3711
3711
  }
3712
3712
 
3713
3713
  // ente/version.ts
3714
- var VERSION = "0.4.61";
3714
+ var VERSION = "0.4.63";
3715
3715
 
3716
3716
  // ente/branding.ts
3717
3717
  var NPM_REGISTRY = "https://registry.npmjs.org";
@@ -13013,6 +13013,96 @@ var ACTIVITY_COMMANDS = [
13013
13013
  ActivityAttachmentUpload
13014
13014
  ];
13015
13015
 
13016
+ // ente/commands/activityTranscript.ts
13017
+ var listForActivity = makeFunctionReference(
13018
+ "recordingTranscripts:listForActivity"
13019
+ );
13020
+ var getForActivity = makeFunctionReference("recordingTranscripts:getForActivity");
13021
+ var WITHHELD_TEXT = {
13022
+ processing: "still being processed",
13023
+ external_recipient: "processed by an external recipient, so its writes cannot be traced",
13024
+ no_traceable_writes: "its writes cannot be traced",
13025
+ untraceable_tool: "it used a tool whose effect cannot be traced",
13026
+ outside_reader_spaces: "it also wrote into spaces you are not a member of",
13027
+ too_large: "too many runs or messages to check"
13028
+ };
13029
+ function transcriptPassages(transcript) {
13030
+ return transcript.split(/\n+|(?<=[.!?])\s+/u).map((passage) => passage.trim()).filter((passage) => passage.length > 0);
13031
+ }
13032
+ function grepTranscript(transcript, term, context) {
13033
+ const passages = transcriptPassages(transcript);
13034
+ const needle = term.toLocaleLowerCase();
13035
+ const windows = [];
13036
+ passages.forEach((passage, index) => {
13037
+ if (!passage.toLocaleLowerCase().includes(needle)) return;
13038
+ const start = Math.max(0, index - context);
13039
+ const end = Math.min(passages.length - 1, index + context);
13040
+ const last = windows.at(-1);
13041
+ if (last && start <= last[1] + 1) last[1] = end;
13042
+ else windows.push([start, end]);
13043
+ });
13044
+ return windows.map(([start, end]) => passages.slice(start, end + 1));
13045
+ }
13046
+ function heading(summary) {
13047
+ const date = new Date(summary.createdAt).toLocaleString("de-DE", { timeZone: "Europe/Berlin" });
13048
+ const who = summary.own ? "you" : summary.createdByName ?? "another member";
13049
+ return `Recording ${summary.recordingId} \xB7 ${summary.title ?? "untitled"} \xB7 ${date} \xB7 by ${who} \xB7 ${summary.operations.join("/")} this activity`;
13050
+ }
13051
+ var ActivityTranscript = class extends ProfileCommand {
13052
+ static paths = [["activity", "transcript"]];
13053
+ static usage = Command.Usage({
13054
+ category: "Activity",
13055
+ description: "Read or search the transcript of the recording behind an activity",
13056
+ details: `
13057
+ Lists the recordings whose processing created or changed the activity and prints their
13058
+ transcripts. Use it whenever a note, summary or task is unclear or lacks detail: the
13059
+ transcript holds what the recording agent left out.
13060
+
13061
+ You can read your own recordings. Another member's recording is readable only when
13062
+ everything it wrote is in spaces you are a member of; otherwise it is listed with the reason.
13063
+ `,
13064
+ examples: [
13065
+ ["Print the transcript", "ente activity transcript <activityId>"],
13066
+ ["Find what was said about a price", "ente activity transcript <activityId> --grep Preis --context 3"]
13067
+ ]
13068
+ });
13069
+ activityId = options_exports.String({ required: true, name: "activityId" });
13070
+ recording = options_exports.String("--recording", { description: "Only this recording ID" });
13071
+ grep = options_exports.String("--grep", { description: "Print only passages containing this text (case-insensitive)" });
13072
+ contextPassages = options_exports.String("--context", "2", { description: "Passages around each --grep hit (default 2)" });
13073
+ async run() {
13074
+ const context = Number(this.contextPassages);
13075
+ if (!/^\d+$/u.test(this.contextPassages)) throw new Error("--context must be a whole number \u2265 0");
13076
+ if (this.grep !== void 0 && this.grep.trim() === "") throw new Error("--grep needs a search term");
13077
+ const caller = await resolveCaller();
13078
+ const summaries = (await caller.query(listForActivity, { activityId: this.activityId })).filter((summary) => !this.recording || summary.recordingId === this.recording);
13079
+ if (this.recording && summaries.length === 0) {
13080
+ throw new Error(`Recording ${this.recording} did not create or change activity ${this.activityId}`);
13081
+ }
13082
+ const results = [];
13083
+ for (const summary of summaries) {
13084
+ const transcript = summary.readable ? (await caller.query(getForActivity, { activityId: this.activityId, recordingId: summary.recordingId })).transcript : null;
13085
+ const matches = transcript !== null && this.grep !== void 0 ? grepTranscript(transcript, this.grep, context) : void 0;
13086
+ results.push({ ...summary, transcript: matches === void 0 ? transcript : null, ...matches ? { matches } : {} });
13087
+ }
13088
+ this.emitText({ data: results }, () => {
13089
+ if (results.length === 0) return "No recording created or changed this activity.";
13090
+ return results.map((result) => {
13091
+ const lines = [heading(result)];
13092
+ if (!result.readable) {
13093
+ lines.push(`Transcript withheld: ${WITHHELD_TEXT[result.withheldReason ?? "no_traceable_writes"]}${result.withheldDetail ? ` (${result.withheldDetail})` : ""}.`);
13094
+ } else if (result.matches) {
13095
+ lines.push(result.matches.length === 0 ? `No passage mentions "${this.grep}".` : result.matches.map((passages) => passages.join(" ")).join("\n\u2026\n"));
13096
+ } else {
13097
+ lines.push(result.transcript ?? "No transcript yet.");
13098
+ }
13099
+ return lines.join("\n");
13100
+ }).join("\n\n");
13101
+ });
13102
+ }
13103
+ };
13104
+ var ACTIVITY_TRANSCRIPT_COMMANDS = [ActivityTranscript];
13105
+
13016
13106
  // ente/deadline.ts
13017
13107
  var DEFAULT_HOUR = 22;
13018
13108
  var DEFAULT_MINUTE = 0;
@@ -15058,8 +15148,9 @@ function renderAgentConfiguration(agent) {
15058
15148
  ];
15059
15149
  for (const schedule of agent.schedules) {
15060
15150
  const time = schedule.timeMinutes === void 0 ? schedule.scheduleType : `${String(Math.floor(schedule.timeMinutes / 60)).padStart(2, "0")}:${String(schedule.timeMinutes % 60).padStart(2, "0")} ${schedule.timezone ?? ""}`.trim();
15151
+ const condition = schedule.runCondition ?? schedule.mailPurpose;
15061
15152
  lines.push(
15062
- ` ${schedule.enabled ? "enabled" : "disabled"} ${time} ${schedule.prompt} ${schedule.automationId}`
15153
+ ` ${schedule.enabled ? "enabled" : "disabled"} ${time} ${schedule.prompt} ${schedule.automationId}${condition ? ` condition=${condition}` : ""}`
15063
15154
  );
15064
15155
  }
15065
15156
  return lines.join("\n");
@@ -15757,6 +15848,7 @@ Commands:
15757
15848
  ente notification send Email your own Ente account (text, HTML, and images)
15758
15849
  ente activity create|list|get|update|delete|restore
15759
15850
  ente activity content read|edit
15851
+ ente activity transcript <activityId> [--grep <text>] Transcript behind an activity \u2014 read it when a note or summary is unclear
15760
15852
  ente agenda create-point|link-task
15761
15853
  ente activity message add <activityId> --content "..."
15762
15854
  ente activity attachment upload <activityId> <file>
@@ -16836,6 +16928,7 @@ for (const Cmd of [
16836
16928
  ...AUTH_COMMANDS,
16837
16929
  ...ENTITY_COMMANDS,
16838
16930
  ...ACTIVITY_COMMANDS,
16931
+ ...ACTIVITY_TRANSCRIPT_COMMANDS,
16839
16932
  ...TASK_COMMANDS,
16840
16933
  ...LIST_COMMANDS,
16841
16934
  ...USERS_COMMANDS,