ente-cli 0.4.71 → 0.4.73

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
@@ -423,3 +423,24 @@ JSON failures use stdout `{ "error": { "message": "..." } }` with a nonzero
423
423
  exit. REST status and structured error fields survive. Check the exit before
424
424
  parsing; see [Retrieve bounded context](playbooks/retrieve-bounded-context.md).
425
425
  The unsupported `entity show` spelling gives a targeted `entity get` correction.
426
+
427
+ ### Granted incident diagnostics
428
+
429
+ `ente diagnostics page --source toolMessages --since <epoch-ms> --until <epoch-ms> --profile ente-operator --json`
430
+ reads fixed global content-free aggregates using the existing bound agent REST
431
+ credential. Access is off unless a current human platform admin explicitly grants
432
+ this exact owned Personal agent diagnostics with expiry. Installation grants no
433
+ access. No grant/revoke or arbitrary admin executor is exposed to agents.
434
+
435
+ Sources/flags match `health page`: toolMessages, threads with `--status
436
+ idle|running|error`, recordings with its processing status; `--limit` 1–100,
437
+ `--cursor`, and `--stale-after-ms` 60000–86400000. Keep source/since/until fixed
438
+ across pages. Results put aggregates and continuation under `data.page`, with
439
+ window/observation/coverage alongside. Read every page before claiming complete
440
+ counts; terminal recording history excludes missing progress timestamps. No
441
+ message bodies or customer identifiers. The legacy `health page` remains a
442
+ separate human-admin JWT surface and never serves as a fallback.
443
+
444
+ Diagnostics is unavailable inside Ente-hosted chats, recordings and automations.
445
+ Use the external operator command. Whole-history panel sharing does not grant
446
+ access to diagnostics, and diagnostic reads do not append to chat history.
package/dist/SKILL.md CHANGED
@@ -157,6 +157,8 @@ ente query "QM system export" [--space <name>] [--entity <name>] [--since <epoch
157
157
  # Entities
158
158
  ente entity list [--query <text>] [--type person|org|project|topic|place|object] [--space <name>] [--limit 50] [--archived] [--json]
159
159
  ente entity create "Jane Doe" --type person [--pin "Acme Corp"] [--share-parents --parent-space-grant-fingerprint <token>] [--alias "JD"] [--attr email=jane@acme.com] [--tag vip] [--description "CTO at Acme"] [--json]
160
+ ente entity create "Leistungsphase 1" --type topic --space "Studio" --parent "Building A" --exclusive-parent [--json]
161
+ ente entity duplicate <name-or-id> --space <space> [--name "New project"] [--include-exclusive-children] [--json]
160
162
  ente entity get "Jane Doe" [--json]
161
163
  ente entity update "Jane Doe" [--name "Jane A. Doe"] [--alias-add "Jane"] [--alias-remove "JD"] [--attr role=CEO] [--tag vip] [--description "…"] [--json]
162
164
  ente entity rename "Lorey Georg" "Georg Lorey" # change display name
@@ -523,6 +525,12 @@ Optional schedules accept `intervalHours: 1 | 24` and
523
525
  Published threads are native, durable, read-only activities. Their messages
524
526
  appear individually in the timeline; graph content reads include bounded email
525
527
  blocks. Use existing activity controls to correct thread space/owners.
528
+ ## Entity creation and duplication
529
+
530
+ Entity duplication copies the type, name, description, email addresses and icon into the selected source space. It never copies activities or existing parents. `--include-exclusive-children` recursively recreates exclusive branches already in that space with exact child names, order and aggregation settings. Shared and archived children are excluded. The operation fails atomically above 100 entities including the root. Use parent context or an ID to distinguish same-named phases across projects.
531
+
532
+ `entity create --parent` atomically creates and attaches a child. Add `--exclusive-parent` to restrict it to that parent. The parent must already belong to the destination space; this path never shares it or its ancestors. Resolve same-named phases by parent context or ID. Do not combine `--parent` with `--pin`; `--pin` retains the older separate-link behavior.
533
+
526
534
  ## Reviewed space changes
527
535
 
528
536
  `ente space change COMMAND --json` supports `prepare`, `status`, `items`,
@@ -583,3 +591,26 @@ assignees and preserves humans. `--clear-agent-assignees` removes the agent assi
583
591
  Assignment requires the agent to have write access in the task space; it grants no access.
584
592
 
585
593
  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.
594
+
595
+ ## Explicit incident diagnostics
596
+
597
+ Use `ente diagnostics page --source toolMessages --since <epoch-ms> --until
598
+ <epoch-ms> --profile <bound-profile> --json` only within the requested incident.
599
+ A current human platform admin must explicitly grant the exact owned Personal
600
+ agent read-only global health aggregates with expiry in its agent editor. An
601
+ admin owner, company billing role, settings delegation or mailbox grant alone
602
+ is insufficient. Do not grant or renew access yourself, change credentials, or
603
+ fall back to `health page` after denial. Installation enables no grant.
604
+
605
+ Source/window flags match `health page`; rows 1–100, read budget 1 MiB, tool-message
606
+ and terminal recording windows at most 7 days. Active recordings require `since=0`;
607
+ terminal recordings require positive since and exclude legacy missing timestamps.
608
+ Responses contain window/observation/coverage and `data.page` aggregates. Continue
609
+ with `--cursor <data.page.continueCursor>` while `isDone=false`, keeping the
610
+ window/source fixed. Only sum completed pages; partial/unavailable is not zero
611
+ failures. These live state pages are not an atomic or immutable incident history.
612
+ No customer bodies, arbitrary account lookup, settings writes or mailbox retries.
613
+
614
+ Diagnostics is unavailable inside Ente-hosted chats, recordings and automations.
615
+ Use the external operator command. Whole-history panel sharing does not grant
616
+ access to diagnostics, and diagnostic reads do not append to chat history.
package/dist/cli.mjs CHANGED
@@ -3800,7 +3800,7 @@ async function runCli(cli2, argv, context) {
3800
3800
  }
3801
3801
 
3802
3802
  // ente/version.ts
3803
- var VERSION = "0.4.71";
3803
+ var VERSION = "0.4.73";
3804
3804
 
3805
3805
  // ente/branding.ts
3806
3806
  var NPM_REGISTRY = "https://registry.npmjs.org";
@@ -4275,6 +4275,9 @@ var EnteClient = class _EnteClient {
4275
4275
  body
4276
4276
  );
4277
4277
  }
4278
+ diagnostics(body) {
4279
+ return this.rest.post("/api/external/agent/diagnostics", body);
4280
+ }
4278
4281
  agentTasks(body) {
4279
4282
  return this.rest.post("/api/external/agent/tasks", body);
4280
4283
  }
@@ -11248,6 +11251,10 @@ var AuthProfiles = class extends BaseCommand {
11248
11251
  };
11249
11252
  var AUTH_COMMANDS = [AuthLogin, AuthPair, AuthStatus, AuthLogout, AuthProfiles];
11250
11253
 
11254
+ // ../packages/shared/src/entity-duplication.ts
11255
+ var MAX_DUPLICATED_ENTITIES = 100;
11256
+ var ENTITY_DUPLICATION_DESCRIPTION = `Duplicate an entity shell in a selected space it already belongs to. Copies type, name, description, email addresses and icon, without activities or existing parent links. Optionally recreates exclusive child branches in that same space with exact child names, order and aggregation settings. Shared and archived children are excluded. At most ${MAX_DUPLICATED_ENTITIES} entities including the root; oversized copies fail atomically.`;
11257
+
11251
11258
  // ../packages/shared/src/entity-types.ts
11252
11259
  var ENTITY_TYPE_VALUES = [
11253
11260
  "person",
@@ -11730,6 +11737,7 @@ var PinsList = class extends ProfileCommand {
11730
11737
  var PINS_COMMANDS = [PinsList];
11731
11738
 
11732
11739
  // ente/commands/entity.ts
11740
+ var entitiesDuplicate = makeFunctionReference("entities:duplicate");
11733
11741
  var entitiesCreate = makeFunctionReference("entities:create");
11734
11742
  var entitiesFindById = makeFunctionReference(
11735
11743
  "entities:findById"
@@ -11784,6 +11792,26 @@ function toActivityView(rich) {
11784
11792
  shortId: rich.shortId
11785
11793
  };
11786
11794
  }
11795
+ var EntityDuplicate = class extends ProfileCommand {
11796
+ static paths = [["entity", "duplicate"]];
11797
+ static usage = Command.Usage({ category: "Entity", description: `Duplicate a shell without activities; optionally copy exclusive child branches (up to ${MAX_DUPLICATED_ENTITIES} entities)` });
11798
+ nameOrId = options_exports.String();
11799
+ space = options_exports.String("--space", { required: true, description: "Source and destination space (name or ID)" });
11800
+ name = options_exports.String("--name", { description: "Root copy name; children keep their exact names" });
11801
+ includeExclusiveChildren = options_exports.Boolean("--include-exclusive-children", false, { description: "Copy nested exclusive children in the selected space" });
11802
+ async run() {
11803
+ const caller = await resolveCaller();
11804
+ const entityId = await resolveEntityC(caller, this.nameOrId);
11805
+ const spaceId = await resolveSpaceByNameC(caller, this.space);
11806
+ const data = await caller.mutation(entitiesDuplicate, {
11807
+ entityId,
11808
+ spaceId,
11809
+ name: this.name,
11810
+ includeExclusiveChildren: this.includeExclusiveChildren
11811
+ });
11812
+ this.emitText({ data }, () => `Duplicated ${data.duplicatedCount} entities (${data.entityId})`);
11813
+ }
11814
+ };
11787
11815
  var EntityList = class extends ClientCommand {
11788
11816
  static paths = [["entity", "list"]];
11789
11817
  static usage = Command.Usage({ category: "Entity", description: "List or search entities" });
@@ -11810,6 +11838,8 @@ var EntityCreate = class extends ProfileCommand {
11810
11838
  name = options_exports.String();
11811
11839
  type = options_exports.String("--type", { required: true, description: `Entity type (${ENTITY_TYPE_VALUES.join(", ")})` });
11812
11840
  space = options_exports.String("--space", { required: true, description: "Space to create in (name or ID)" });
11841
+ parent = options_exports.String("--parent", { description: "Create and attach to this parent atomically (name or ID)" });
11842
+ exclusiveParent = options_exports.Boolean("--exclusive-parent", false, { description: "Restrict the new child to --parent" });
11813
11843
  pin = options_exports.Array("--pin", { description: "Pin to other entities (resolved by name)" });
11814
11844
  shareParents = options_exports.Boolean("--share-parents", false, {
11815
11845
  description: "Share pinned parents and ancestors into this entity's space when required"
@@ -11824,11 +11854,15 @@ var EntityCreate = class extends ProfileCommand {
11824
11854
  async run() {
11825
11855
  const caller = await resolveCaller();
11826
11856
  const spaceId = await resolveSpaceByNameC(caller, this.space);
11857
+ if (this.exclusiveParent && !this.parent) throw new Error("--exclusive-parent requires --parent.");
11858
+ if (this.parent && this.pin?.length) throw new Error("Use --parent for atomic child creation, or --pin for legacy parent linking, not both.");
11859
+ const parentEntityId = this.parent ? await resolveEntityC(caller, this.parent) : void 0;
11827
11860
  const attributes = parseAttrs(this.attr);
11828
11861
  const entityId = await caller.mutation(entitiesCreate, {
11829
11862
  spaceId,
11830
11863
  name: this.name,
11831
- type: this.type
11864
+ type: this.type,
11865
+ ...parentEntityId ? { parentEntityId, exclusiveParent: this.exclusiveParent } : {}
11832
11866
  });
11833
11867
  if (this.alias) for (const a of this.alias) await caller.mutation(entitiesAddAlias, { id: entityId, alias: a });
11834
11868
  if (this.tag) for (const t of this.tag) await caller.mutation(entitiesAddTag, { id: entityId, tag: t });
@@ -12274,6 +12308,7 @@ var ENTITY_COMMANDS = [
12274
12308
  EntityShowCorrection,
12275
12309
  EntityList,
12276
12310
  EntityCreate,
12311
+ EntityDuplicate,
12277
12312
  EntityGet,
12278
12313
  EntityUpdate,
12279
12314
  EntityRename,
@@ -13974,11 +14009,15 @@ var ListShow = class extends ClientCommand {
13974
14009
  };
13975
14010
  var LIST_COMMANDS = [ListCreate, ListAdd, ListColumnAdd, ListColumnRemove, ListShow];
13976
14011
 
14012
+ // ente/diagnosticContract.ts
14013
+ var DIAGNOSTICS_LIMITS = { rows: 100, bytes: 1048576, windowMs: 6048e5, cursorChars: 8192, grantHours: 24 };
14014
+
13977
14015
  // ente/commands/health.ts
13978
14016
  var healthPage = makeFunctionReference("admin/health:page");
13979
- var HealthRead = class extends ProfileCommand {
14017
+ var HealthRead = class extends ClientCommand {
13980
14018
  static paths = [["health", "page"]];
13981
14019
  static usage = Command.Usage({ category: "Admin", description: "Read one content-free operational health page (global admin only)" });
14020
+ agentDiagnostics = false;
13982
14021
  source = options_exports.String("--source", { required: true });
13983
14022
  status = options_exports.String("--status");
13984
14023
  since = options_exports.String("--since", { required: true, description: "Inclusive epoch milliseconds (use 0 for active jobs; positive window for terminal recordings)" });
@@ -13994,18 +14033,25 @@ var HealthRead = class extends ProfileCommand {
13994
14033
  } else if (this.source === "recordings" && ["pending", "transcribing", "structuring", "reflecting", "done", "error"].includes(this.status ?? "")) {
13995
14034
  source = { kind: "recordings", status: this.status };
13996
14035
  } else throw new Error("Use toolMessages without --status, threads with idle/running/error, or recordings with a processing status.");
13997
- const data = await (await resolveCaller()).query(healthPage, {
14036
+ const args = {
13998
14037
  source,
13999
14038
  since: Number(this.since),
14000
14039
  until: Number(this.until),
14001
14040
  staleAfterMs: Number(this.staleAfter),
14002
14041
  limit: Number(this.limit),
14003
14042
  cursor: this.cursor ?? null
14004
- });
14043
+ };
14044
+ if (![args.since, args.until, args.staleAfterMs, args.limit].every(Number.isSafeInteger) || args.since < 0 || args.until <= args.since || args.staleAfterMs < 6e4 || args.staleAfterMs > 864e5 || args.limit < 1 || args.limit > DIAGNOSTICS_LIMITS.rows || (args.cursor?.length ?? 0) > DIAGNOSTICS_LIMITS.cursorChars || source.kind === "recordings" && !["done", "error"].includes(source.status) && args.since !== 0 || source.kind === "recordings" && ["done", "error"].includes(source.status) && args.since === 0 || (source.kind === "toolMessages" || source.kind === "recordings" && ["done", "error"].includes(source.status)) && args.until - args.since > DIAGNOSTICS_LIMITS.windowMs) throw new Error("Invalid diagnostics window or limits");
14045
+ const data = this.agentDiagnostics ? (await this.client().diagnostics({ operation: "health", ...args })).data : await (await resolveCaller()).query(healthPage, args);
14005
14046
  this.emitText({ data }, () => JSON.stringify(data, null, 2));
14006
14047
  }
14007
14048
  };
14008
- var HEALTH_COMMANDS = [HealthRead];
14049
+ var AgentDiagnosticsRead = class extends HealthRead {
14050
+ static paths = [["diagnostics", "page"]];
14051
+ static usage = Command.Usage({ category: "Diagnostics", description: "Read one explicitly granted content-free health page as the bound personal agent", details: "Default denied. A current human platform admin must grant this exact owned agent read-only diagnostics with expiry. No production grant is enabled by installing or upgrading the CLI. Keep source/window fixed across cursors. Counts are partial until every page has been read; terminal recordings exclude legacy missing timestamps." });
14052
+ agentDiagnostics = true;
14053
+ };
14054
+ var HEALTH_COMMANDS = [HealthRead, AgentDiagnosticsRead];
14009
14055
 
14010
14056
  // ente/commands/users.ts
14011
14057
  var MANAGED_PLANS = ["free", "sponsored", "company_managed", "own_models"];
@@ -15981,7 +16027,7 @@ Commands:
15981
16027
  ente search <query> Fuzzy search entities
15982
16028
  ente ask <question> Natural-language answer (AI synthesis + citations)
15983
16029
  ente query <question> Deterministic evidence retrieval (no synthesis)
15984
- ente entity create|get|update|rename|archive|restore|pin|unpin
16030
+ ente entity create|get|update|duplicate|rename|archive|restore|pin|unpin
15985
16031
  ente entity list [--archived]
15986
16032
  ente pins list <entity> List pins for an entity
15987
16033
  ente task list|get|create|update|done|assign|unassign|set-assignees|clear-assignees
@@ -16012,6 +16058,10 @@ Run \`ente guide <topic>\` for deep dives: entities, tasks, activities, search,
16012
16058
  Create an entity when its identity or relationships will be useful later.
16013
16059
 
16014
16060
  Creating entities:
16061
+ ente entity create "Leistungsphase 1" --type topic --space "Studio" --parent "Building A" --exclusive-parent
16062
+ Creates and attaches an exclusive child atomically; the parent must already be in that space.
16063
+ ente entity duplicate "Building A" --space "Studio" --name "Building B" --include-exclusive-children
16064
+ Copies shells and exclusive child branches without activities (maximum 100 entities).
16015
16065
  ente entity create "Jane Doe" --type person --pin "Acme Corp" --alias "JD"
16016
16066
  # Add --share-parents when the parent is not already in the new entity's space.
16017
16067