faces-cli 1.8.3 → 1.8.4

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.
@@ -1261,21 +1261,10 @@
1261
1261
  "restore.js"
1262
1262
  ]
1263
1263
  },
1264
- "chat:chat": {
1264
+ "compile:all": {
1265
1265
  "aliases": [],
1266
- "args": {
1267
- "face_username": {
1268
- "description": "Face alias (alias@model, owner:alias@model for a published face, or a composite formula like \"(a | b)@model\"). Omit when using --formula.",
1269
- "name": "face_username",
1270
- "required": false
1271
- }
1272
- },
1273
- "description": "Chat via a face. Auto-routes to the correct API endpoint based on the model catalog.",
1274
- "examples": [
1275
- "<%= config.bin %> <%= command.id %> socrates -m \"What is virtue?\"",
1276
- "<%= config.bin %> <%= command.id %> \"(socrates | nietzsche)@claude-sonnet-4-6\" -m \"What is virtue?\"",
1277
- "<%= config.bin %> <%= command.id %> --formula \"socrates | nietzsche\" --llm claude-sonnet-4-6 -m \"What is virtue?\""
1278
- ],
1266
+ "args": {},
1267
+ "description": "Compile all uncompiled documents and threads across all faces",
1279
1268
  "flags": {
1280
1269
  "json": {
1281
1270
  "description": "Format output as json.",
@@ -1308,86 +1297,18 @@
1308
1297
  "multiple": false,
1309
1298
  "type": "option"
1310
1299
  },
1311
- "message": {
1312
- "char": "m",
1313
- "description": "User message (repeatable)",
1314
- "name": "message",
1315
- "required": false,
1316
- "hasDynamicHelp": false,
1317
- "multiple": true,
1318
- "type": "option"
1319
- },
1320
- "llm": {
1321
- "description": "LLM override (e.g. gpt-4o-mini, claude-sonnet-4-6)",
1322
- "name": "llm",
1323
- "hasDynamicHelp": false,
1324
- "multiple": false,
1325
- "type": "option"
1326
- },
1327
- "formula": {
1328
- "description": "Compose a run-time composite from your own faces, e.g. \"socrates | nietzsche\" (operators: | & ^ -). Requires --llm. The composite takes the name of its first operand; use face:create --formula for a named, persisted composite.",
1329
- "name": "formula",
1330
- "hasDynamicHelp": false,
1331
- "multiple": false,
1332
- "type": "option"
1333
- },
1334
- "system": {
1335
- "description": "System prompt / instructions",
1336
- "name": "system",
1337
- "hasDynamicHelp": false,
1338
- "multiple": false,
1339
- "type": "option"
1340
- },
1341
- "stream": {
1342
- "description": "Stream the response",
1343
- "name": "stream",
1344
- "allowNo": false,
1345
- "type": "boolean"
1346
- },
1347
- "max-tokens": {
1348
- "description": "Max tokens",
1349
- "name": "max-tokens",
1350
- "hasDynamicHelp": false,
1351
- "multiple": false,
1352
- "type": "option"
1353
- },
1354
- "temperature": {
1355
- "description": "Temperature (0.0-2.0)",
1356
- "name": "temperature",
1357
- "hasDynamicHelp": false,
1358
- "multiple": false,
1359
- "type": "option"
1360
- },
1361
- "file": {
1362
- "description": "Read message from file",
1363
- "name": "file",
1364
- "hasDynamicHelp": false,
1365
- "multiple": false,
1366
- "type": "option"
1367
- },
1368
- "responses": {
1369
- "description": "Force the OpenAI Responses API endpoint (escape hatch; routing is automatic otherwise)",
1370
- "name": "responses",
1371
- "allowNo": false,
1372
- "type": "boolean"
1373
- },
1374
- "medium": {
1375
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1376
- "name": "medium",
1300
+ "timeout": {
1301
+ "description": "Per-item compile timeout in seconds (default: 600)",
1302
+ "name": "timeout",
1303
+ "default": 600,
1377
1304
  "hasDynamicHelp": false,
1378
1305
  "multiple": false,
1379
1306
  "type": "option"
1380
- },
1381
- "oauth-only": {
1382
- "description": "Prevent fallback to paid system key (use OAuth only)",
1383
- "name": "oauth-only",
1384
- "allowNo": false,
1385
- "type": "boolean"
1386
1307
  }
1387
1308
  },
1388
1309
  "hasDynamicHelp": false,
1389
1310
  "hiddenAliases": [],
1390
- "id": "chat:chat",
1311
+ "id": "compile:all",
1391
1312
  "pluginAlias": "faces-cli",
1392
1313
  "pluginName": "faces-cli",
1393
1314
  "pluginType": "core",
@@ -1397,20 +1318,20 @@
1397
1318
  "relativePath": [
1398
1319
  "dist",
1399
1320
  "commands",
1400
- "chat",
1401
- "chat.js"
1321
+ "compile",
1322
+ "all.js"
1402
1323
  ]
1403
1324
  },
1404
- "chat:messages": {
1325
+ "compile:import": {
1405
1326
  "aliases": [],
1406
1327
  "args": {
1407
- "face_model": {
1408
- "description": "Face model (e.g. myface, myface@claude-sonnet-4-6, or head:socrates@claude-sonnet-4-6)",
1409
- "name": "face_model",
1328
+ "face_id": {
1329
+ "description": "Face alias",
1330
+ "name": "face_id",
1410
1331
  "required": true
1411
1332
  }
1412
1333
  },
1413
- "description": "Anthropic Messages API proxy via a face (alias: chat:chat auto-routes Anthropic models here)",
1334
+ "description": "Import a YouTube video into a face via server-side download and transcription",
1414
1335
  "flags": {
1415
1336
  "json": {
1416
1337
  "description": "Format output as json.",
@@ -1443,53 +1364,55 @@
1443
1364
  "multiple": false,
1444
1365
  "type": "option"
1445
1366
  },
1446
- "message": {
1447
- "char": "m",
1448
- "description": "User message (repeatable)",
1449
- "name": "message",
1367
+ "url": {
1368
+ "description": "YouTube URL (youtube.com/watch?v=... or youtu.be/...)",
1369
+ "name": "url",
1450
1370
  "required": true,
1451
1371
  "hasDynamicHelp": false,
1452
- "multiple": true,
1372
+ "multiple": false,
1453
1373
  "type": "option"
1454
1374
  },
1455
- "system": {
1456
- "description": "System prompt",
1457
- "name": "system",
1375
+ "type": {
1376
+ "description": "\"document\" for solo talks, lectures, monologues; \"thread\" for interviews or multi-speaker conversations",
1377
+ "name": "type",
1378
+ "default": "document",
1458
1379
  "hasDynamicHelp": false,
1459
1380
  "multiple": false,
1381
+ "options": [
1382
+ "document",
1383
+ "thread"
1384
+ ],
1460
1385
  "type": "option"
1461
1386
  },
1462
- "stream": {
1463
- "description": "Stream the response",
1464
- "name": "stream",
1465
- "allowNo": false,
1466
- "type": "boolean"
1467
- },
1468
- "max-tokens": {
1469
- "description": "Max tokens",
1470
- "name": "max-tokens",
1471
- "default": 1024,
1387
+ "perspective": {
1388
+ "description": "\"first-person\" if the face is the speaker; \"third-person\" if the video is about the face",
1389
+ "name": "perspective",
1390
+ "default": "third-person",
1472
1391
  "hasDynamicHelp": false,
1473
1392
  "multiple": false,
1393
+ "options": [
1394
+ "first-person",
1395
+ "third-person"
1396
+ ],
1474
1397
  "type": "option"
1475
1398
  },
1476
- "medium": {
1477
- "description": "What sort of writing this is e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1478
- "name": "medium",
1399
+ "face-speaker": {
1400
+ "description": "For --type thread: AssemblyAI speaker label (e.g. \"A\") that corresponds to the face. Defaults to first detected speaker.",
1401
+ "name": "face-speaker",
1479
1402
  "hasDynamicHelp": false,
1480
1403
  "multiple": false,
1481
1404
  "type": "option"
1482
1405
  },
1483
- "oauth-only": {
1484
- "description": "Prevent fallback to paid system key (use OAuth only)",
1485
- "name": "oauth-only",
1406
+ "no-wait": {
1407
+ "description": "Return immediately after import starts (do not poll for transcription). Prints the ID for manual polling.",
1408
+ "name": "no-wait",
1486
1409
  "allowNo": false,
1487
1410
  "type": "boolean"
1488
1411
  }
1489
1412
  },
1490
1413
  "hasDynamicHelp": false,
1491
1414
  "hiddenAliases": [],
1492
- "id": "chat:messages",
1415
+ "id": "compile:import",
1493
1416
  "pluginAlias": "faces-cli",
1494
1417
  "pluginName": "faces-cli",
1495
1418
  "pluginType": "core",
@@ -1499,20 +1422,14 @@
1499
1422
  "relativePath": [
1500
1423
  "dist",
1501
1424
  "commands",
1502
- "chat",
1503
- "messages.js"
1425
+ "compile",
1426
+ "import.js"
1504
1427
  ]
1505
1428
  },
1506
- "chat:responses": {
1429
+ "compile:stats": {
1507
1430
  "aliases": [],
1508
- "args": {
1509
- "face_model": {
1510
- "description": "Face model (e.g. myface, myface@gpt-4o, or head:socrates@gpt-5.4)",
1511
- "name": "face_model",
1512
- "required": true
1513
- }
1514
- },
1515
- "description": "OpenAI Responses API proxy via a face (alias: chat:chat --responses)",
1431
+ "args": {},
1432
+ "description": "Show compilation stats per face",
1516
1433
  "flags": {
1517
1434
  "json": {
1518
1435
  "description": "Format output as json.",
@@ -1544,46 +1461,11 @@
1544
1461
  "hasDynamicHelp": false,
1545
1462
  "multiple": false,
1546
1463
  "type": "option"
1547
- },
1548
- "message": {
1549
- "char": "m",
1550
- "description": "User input message",
1551
- "name": "message",
1552
- "required": true,
1553
- "hasDynamicHelp": false,
1554
- "multiple": false,
1555
- "type": "option"
1556
- },
1557
- "instructions": {
1558
- "description": "System instructions",
1559
- "name": "instructions",
1560
- "hasDynamicHelp": false,
1561
- "multiple": false,
1562
- "type": "option"
1563
- },
1564
- "stream": {
1565
- "description": "Stream the response",
1566
- "name": "stream",
1567
- "allowNo": false,
1568
- "type": "boolean"
1569
- },
1570
- "medium": {
1571
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1572
- "name": "medium",
1573
- "hasDynamicHelp": false,
1574
- "multiple": false,
1575
- "type": "option"
1576
- },
1577
- "oauth-only": {
1578
- "description": "Prevent fallback to paid system key (use OAuth only)",
1579
- "name": "oauth-only",
1580
- "allowNo": false,
1581
- "type": "boolean"
1582
1464
  }
1583
1465
  },
1584
1466
  "hasDynamicHelp": false,
1585
1467
  "hiddenAliases": [],
1586
- "id": "chat:responses",
1468
+ "id": "compile:stats",
1587
1469
  "pluginAlias": "faces-cli",
1588
1470
  "pluginName": "faces-cli",
1589
1471
  "pluginType": "core",
@@ -1593,27 +1475,20 @@
1593
1475
  "relativePath": [
1594
1476
  "dist",
1595
1477
  "commands",
1596
- "chat",
1597
- "responses.js"
1478
+ "compile",
1479
+ "stats.js"
1598
1480
  ]
1599
1481
  },
1600
- "chat:thread": {
1482
+ "compile:upload": {
1601
1483
  "aliases": [],
1602
1484
  "args": {
1603
- "face_username": {
1604
- "description": "Face alias (alias@model, or owner:alias@model for a published face) — required when starting a new thread",
1605
- "name": "face_username",
1606
- "required": false
1485
+ "alias": {
1486
+ "description": "Face alias",
1487
+ "name": "alias",
1488
+ "required": true
1607
1489
  }
1608
1490
  },
1609
- "description": "Multi-turn chat thread. Conversation history is stored under ~/.faces/threads/<id>.json resume any thread later with --id.",
1610
- "examples": [
1611
- "<%= config.bin %> <%= command.id %> socrates -m \"What is justice?\"",
1612
- "<%= config.bin %> <%= command.id %> --id t_abc123 -m \"Say more about that\"",
1613
- "<%= config.bin %> <%= command.id %> --list",
1614
- "<%= config.bin %> <%= command.id %> --id t_abc123 --show",
1615
- "<%= config.bin %> <%= command.id %> --id t_abc123 --delete"
1616
- ],
1491
+ "description": "Upload a file (text/PDF/Word .docx/audio/video) to compile into a face",
1617
1492
  "flags": {
1618
1493
  "json": {
1619
1494
  "description": "Format output as json.",
@@ -1646,97 +1521,62 @@
1646
1521
  "multiple": false,
1647
1522
  "type": "option"
1648
1523
  },
1649
- "id": {
1650
- "description": "Resume an existing thread by id",
1651
- "name": "id",
1524
+ "file": {
1525
+ "description": "File to upload",
1526
+ "name": "file",
1527
+ "required": true,
1652
1528
  "hasDynamicHelp": false,
1653
1529
  "multiple": false,
1654
1530
  "type": "option"
1655
1531
  },
1656
- "message": {
1657
- "char": "m",
1658
- "description": "User message",
1659
- "name": "message",
1532
+ "kind": {
1533
+ "description": "Upload kind: document or thread",
1534
+ "name": "kind",
1535
+ "default": "document",
1660
1536
  "hasDynamicHelp": false,
1661
1537
  "multiple": false,
1538
+ "options": [
1539
+ "document",
1540
+ "thread"
1541
+ ],
1662
1542
  "type": "option"
1663
1543
  },
1664
- "file": {
1665
- "description": "Read message from file",
1666
- "name": "file",
1667
- "hasDynamicHelp": false,
1668
- "multiple": false,
1669
- "type": "option"
1670
- },
1671
- "llm": {
1672
- "description": "LLM override (only honored when starting a new thread)",
1673
- "name": "llm",
1674
- "hasDynamicHelp": false,
1675
- "multiple": false,
1676
- "type": "option"
1677
- },
1678
- "system": {
1679
- "description": "System prompt (only honored when starting a new thread)",
1680
- "name": "system",
1681
- "hasDynamicHelp": false,
1682
- "multiple": false,
1683
- "type": "option"
1684
- },
1685
- "max-tokens": {
1686
- "description": "Max tokens",
1687
- "name": "max-tokens",
1544
+ "perspective": {
1545
+ "description": "Perspective (document only)",
1546
+ "name": "perspective",
1547
+ "default": "third-person",
1688
1548
  "hasDynamicHelp": false,
1689
1549
  "multiple": false,
1550
+ "options": [
1551
+ "first-person",
1552
+ "third-person"
1553
+ ],
1690
1554
  "type": "option"
1691
1555
  },
1692
- "temperature": {
1693
- "description": "Temperature (0.0-2.0, OpenAI/Chat Completions only)",
1694
- "name": "temperature",
1556
+ "medium": {
1557
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not. Only valid with --kind document.",
1558
+ "name": "medium",
1695
1559
  "hasDynamicHelp": false,
1696
1560
  "multiple": false,
1697
1561
  "type": "option"
1698
1562
  },
1699
- "stream": {
1700
- "description": "Stream the response",
1701
- "name": "stream",
1702
- "allowNo": false,
1703
- "type": "boolean"
1704
- },
1705
- "medium": {
1706
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1707
- "name": "medium",
1563
+ "face-speaker": {
1564
+ "description": "Speaker name to map to the face (thread only). If omitted, auto-detected from face name.",
1565
+ "name": "face-speaker",
1708
1566
  "hasDynamicHelp": false,
1709
1567
  "multiple": false,
1710
1568
  "type": "option"
1711
1569
  },
1712
- "oauth-only": {
1713
- "description": "Prevent fallback to paid system key",
1714
- "name": "oauth-only",
1715
- "allowNo": false,
1716
- "type": "boolean"
1717
- },
1718
- "list": {
1719
- "description": "List saved threads",
1720
- "name": "list",
1721
- "allowNo": false,
1722
- "type": "boolean"
1723
- },
1724
- "show": {
1725
- "description": "Show the thread transcript (requires --id)",
1726
- "name": "show",
1727
- "allowNo": false,
1728
- "type": "boolean"
1729
- },
1730
- "delete": {
1731
- "description": "Delete the thread (requires --id)",
1732
- "name": "delete",
1570
+ "no-wait": {
1571
+ "description": "Return immediately after upload (do not poll for transcription). Prints the ID for manual polling.",
1572
+ "name": "no-wait",
1733
1573
  "allowNo": false,
1734
1574
  "type": "boolean"
1735
1575
  }
1736
1576
  },
1737
1577
  "hasDynamicHelp": false,
1738
1578
  "hiddenAliases": [],
1739
- "id": "chat:thread",
1579
+ "id": "compile:upload",
1740
1580
  "pluginAlias": "faces-cli",
1741
1581
  "pluginName": "faces-cli",
1742
1582
  "pluginType": "core",
@@ -1746,14 +1586,14 @@
1746
1586
  "relativePath": [
1747
1587
  "dist",
1748
1588
  "commands",
1749
- "chat",
1750
- "thread.js"
1589
+ "compile",
1590
+ "upload.js"
1751
1591
  ]
1752
1592
  },
1753
- "compile:all": {
1593
+ "config:clear": {
1754
1594
  "aliases": [],
1755
1595
  "args": {},
1756
- "description": "Compile all uncompiled documents and threads across all faces",
1596
+ "description": "Delete all saved credentials and config",
1757
1597
  "flags": {
1758
1598
  "json": {
1759
1599
  "description": "Format output as json.",
@@ -1786,18 +1626,16 @@
1786
1626
  "multiple": false,
1787
1627
  "type": "option"
1788
1628
  },
1789
- "timeout": {
1790
- "description": "Per-item compile timeout in seconds (default: 600)",
1791
- "name": "timeout",
1792
- "default": 600,
1793
- "hasDynamicHelp": false,
1794
- "multiple": false,
1795
- "type": "option"
1629
+ "yes": {
1630
+ "description": "Skip confirmation",
1631
+ "name": "yes",
1632
+ "allowNo": false,
1633
+ "type": "boolean"
1796
1634
  }
1797
1635
  },
1798
1636
  "hasDynamicHelp": false,
1799
1637
  "hiddenAliases": [],
1800
- "id": "compile:all",
1638
+ "id": "config:clear",
1801
1639
  "pluginAlias": "faces-cli",
1802
1640
  "pluginName": "faces-cli",
1803
1641
  "pluginType": "core",
@@ -1807,20 +1645,25 @@
1807
1645
  "relativePath": [
1808
1646
  "dist",
1809
1647
  "commands",
1810
- "compile",
1811
- "all.js"
1648
+ "config",
1649
+ "clear.js"
1812
1650
  ]
1813
1651
  },
1814
- "compile:import": {
1652
+ "config:set": {
1815
1653
  "aliases": [],
1816
1654
  "args": {
1817
- "face_id": {
1818
- "description": "Face alias",
1819
- "name": "face_id",
1655
+ "key": {
1656
+ "description": "Config key",
1657
+ "name": "key",
1658
+ "required": true
1659
+ },
1660
+ "value": {
1661
+ "description": "Config value",
1662
+ "name": "value",
1820
1663
  "required": true
1821
1664
  }
1822
1665
  },
1823
- "description": "Import a YouTube video into a face via server-side download and transcription",
1666
+ "description": "Set a config value (e.g. base_url, api_key, token)",
1824
1667
  "flags": {
1825
1668
  "json": {
1826
1669
  "description": "Format output as json.",
@@ -1852,56 +1695,11 @@
1852
1695
  "hasDynamicHelp": false,
1853
1696
  "multiple": false,
1854
1697
  "type": "option"
1855
- },
1856
- "url": {
1857
- "description": "YouTube URL (youtube.com/watch?v=... or youtu.be/...)",
1858
- "name": "url",
1859
- "required": true,
1860
- "hasDynamicHelp": false,
1861
- "multiple": false,
1862
- "type": "option"
1863
- },
1864
- "type": {
1865
- "description": "\"document\" for solo talks, lectures, monologues; \"thread\" for interviews or multi-speaker conversations",
1866
- "name": "type",
1867
- "default": "document",
1868
- "hasDynamicHelp": false,
1869
- "multiple": false,
1870
- "options": [
1871
- "document",
1872
- "thread"
1873
- ],
1874
- "type": "option"
1875
- },
1876
- "perspective": {
1877
- "description": "\"first-person\" if the face is the speaker; \"third-person\" if the video is about the face",
1878
- "name": "perspective",
1879
- "default": "third-person",
1880
- "hasDynamicHelp": false,
1881
- "multiple": false,
1882
- "options": [
1883
- "first-person",
1884
- "third-person"
1885
- ],
1886
- "type": "option"
1887
- },
1888
- "face-speaker": {
1889
- "description": "For --type thread: AssemblyAI speaker label (e.g. \"A\") that corresponds to the face. Defaults to first detected speaker.",
1890
- "name": "face-speaker",
1891
- "hasDynamicHelp": false,
1892
- "multiple": false,
1893
- "type": "option"
1894
- },
1895
- "no-wait": {
1896
- "description": "Return immediately after import starts (do not poll for transcription). Prints the ID for manual polling.",
1897
- "name": "no-wait",
1898
- "allowNo": false,
1899
- "type": "boolean"
1900
1698
  }
1901
1699
  },
1902
1700
  "hasDynamicHelp": false,
1903
1701
  "hiddenAliases": [],
1904
- "id": "compile:import",
1702
+ "id": "config:set",
1905
1703
  "pluginAlias": "faces-cli",
1906
1704
  "pluginName": "faces-cli",
1907
1705
  "pluginType": "core",
@@ -1911,14 +1709,14 @@
1911
1709
  "relativePath": [
1912
1710
  "dist",
1913
1711
  "commands",
1914
- "compile",
1915
- "import.js"
1712
+ "config",
1713
+ "set.js"
1916
1714
  ]
1917
1715
  },
1918
- "compile:stats": {
1716
+ "config:show": {
1919
1717
  "aliases": [],
1920
1718
  "args": {},
1921
- "description": "Show compilation stats per face",
1719
+ "description": "Print current config (credentials are masked)",
1922
1720
  "flags": {
1923
1721
  "json": {
1924
1722
  "description": "Format output as json.",
@@ -1954,7 +1752,7 @@
1954
1752
  },
1955
1753
  "hasDynamicHelp": false,
1956
1754
  "hiddenAliases": [],
1957
- "id": "compile:stats",
1755
+ "id": "config:show",
1958
1756
  "pluginAlias": "faces-cli",
1959
1757
  "pluginName": "faces-cli",
1960
1758
  "pluginType": "core",
@@ -1964,20 +1762,25 @@
1964
1762
  "relativePath": [
1965
1763
  "dist",
1966
1764
  "commands",
1967
- "compile",
1968
- "stats.js"
1765
+ "config",
1766
+ "show.js"
1969
1767
  ]
1970
1768
  },
1971
- "compile:upload": {
1769
+ "chat:chat": {
1972
1770
  "aliases": [],
1973
1771
  "args": {
1974
- "alias": {
1975
- "description": "Face alias",
1976
- "name": "alias",
1977
- "required": true
1772
+ "face_username": {
1773
+ "description": "Face alias (alias@model, owner:alias@model for a published face, or a composite formula like \"(a | b)@model\"). Omit when using --formula.",
1774
+ "name": "face_username",
1775
+ "required": false
1978
1776
  }
1979
1777
  },
1980
- "description": "Upload a file (text/PDF/Word .docx/audio/video) to compile into a face",
1778
+ "description": "Chat via a face. Auto-routes to the correct API endpoint based on the model catalog.",
1779
+ "examples": [
1780
+ "<%= config.bin %> <%= command.id %> socrates -m \"What is virtue?\"",
1781
+ "<%= config.bin %> <%= command.id %> \"(socrates | nietzsche)@claude-sonnet-4-6\" -m \"What is virtue?\"",
1782
+ "<%= config.bin %> <%= command.id %> --formula \"socrates | nietzsche\" --llm claude-sonnet-4-6 -m \"What is virtue?\""
1783
+ ],
1981
1784
  "flags": {
1982
1785
  "json": {
1983
1786
  "description": "Format output as json.",
@@ -2010,121 +1813,86 @@
2010
1813
  "multiple": false,
2011
1814
  "type": "option"
2012
1815
  },
2013
- "file": {
2014
- "description": "File to upload",
2015
- "name": "file",
2016
- "required": true,
1816
+ "message": {
1817
+ "char": "m",
1818
+ "description": "User message (repeatable)",
1819
+ "name": "message",
1820
+ "required": false,
1821
+ "hasDynamicHelp": false,
1822
+ "multiple": true,
1823
+ "type": "option"
1824
+ },
1825
+ "llm": {
1826
+ "description": "LLM override (e.g. gpt-4o-mini, claude-sonnet-4-6)",
1827
+ "name": "llm",
2017
1828
  "hasDynamicHelp": false,
2018
1829
  "multiple": false,
2019
1830
  "type": "option"
2020
1831
  },
2021
- "kind": {
2022
- "description": "Upload kind: document or thread",
2023
- "name": "kind",
2024
- "default": "document",
1832
+ "formula": {
1833
+ "description": "Compose a run-time composite from your own faces, e.g. \"socrates | nietzsche\" (operators: | & ^ -). Requires --llm. The composite takes the name of its first operand; use face:create --formula for a named, persisted composite.",
1834
+ "name": "formula",
2025
1835
  "hasDynamicHelp": false,
2026
1836
  "multiple": false,
2027
- "options": [
2028
- "document",
2029
- "thread"
2030
- ],
2031
1837
  "type": "option"
2032
1838
  },
2033
- "perspective": {
2034
- "description": "Perspective (document only)",
2035
- "name": "perspective",
2036
- "default": "third-person",
1839
+ "system": {
1840
+ "description": "System prompt / instructions",
1841
+ "name": "system",
2037
1842
  "hasDynamicHelp": false,
2038
1843
  "multiple": false,
2039
- "options": [
2040
- "first-person",
2041
- "third-person"
2042
- ],
2043
1844
  "type": "option"
2044
1845
  },
2045
- "medium": {
2046
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not. Only valid with --kind document.",
2047
- "name": "medium",
1846
+ "stream": {
1847
+ "description": "Stream the response",
1848
+ "name": "stream",
1849
+ "allowNo": false,
1850
+ "type": "boolean"
1851
+ },
1852
+ "max-tokens": {
1853
+ "description": "Max tokens",
1854
+ "name": "max-tokens",
2048
1855
  "hasDynamicHelp": false,
2049
1856
  "multiple": false,
2050
1857
  "type": "option"
2051
1858
  },
2052
- "face-speaker": {
2053
- "description": "Speaker name to map to the face (thread only). If omitted, auto-detected from face name.",
2054
- "name": "face-speaker",
1859
+ "temperature": {
1860
+ "description": "Temperature (0.0-2.0)",
1861
+ "name": "temperature",
2055
1862
  "hasDynamicHelp": false,
2056
1863
  "multiple": false,
2057
1864
  "type": "option"
2058
1865
  },
2059
- "no-wait": {
2060
- "description": "Return immediately after upload (do not poll for transcription). Prints the ID for manual polling.",
2061
- "name": "no-wait",
2062
- "allowNo": false,
2063
- "type": "boolean"
2064
- }
2065
- },
2066
- "hasDynamicHelp": false,
2067
- "hiddenAliases": [],
2068
- "id": "compile:upload",
2069
- "pluginAlias": "faces-cli",
2070
- "pluginName": "faces-cli",
2071
- "pluginType": "core",
2072
- "strict": true,
2073
- "enableJsonFlag": true,
2074
- "isESM": true,
2075
- "relativePath": [
2076
- "dist",
2077
- "commands",
2078
- "compile",
2079
- "upload.js"
2080
- ]
2081
- },
2082
- "config:clear": {
2083
- "aliases": [],
2084
- "args": {},
2085
- "description": "Delete all saved credentials and config",
2086
- "flags": {
2087
- "json": {
2088
- "description": "Format output as json.",
2089
- "helpGroup": "GLOBAL",
2090
- "name": "json",
2091
- "allowNo": false,
2092
- "type": "boolean"
2093
- },
2094
- "base-url": {
2095
- "description": "API base URL",
2096
- "env": "FACES_BASE_URL",
2097
- "name": "base-url",
1866
+ "file": {
1867
+ "description": "Read message from file",
1868
+ "name": "file",
2098
1869
  "hasDynamicHelp": false,
2099
1870
  "multiple": false,
2100
1871
  "type": "option"
2101
1872
  },
2102
- "token": {
2103
- "description": "JWT bearer token",
2104
- "env": "FACES_TOKEN",
2105
- "name": "token",
2106
- "hasDynamicHelp": false,
2107
- "multiple": false,
2108
- "type": "option"
1873
+ "responses": {
1874
+ "description": "Force the OpenAI Responses API endpoint (escape hatch; routing is automatic otherwise)",
1875
+ "name": "responses",
1876
+ "allowNo": false,
1877
+ "type": "boolean"
2109
1878
  },
2110
- "api-key": {
2111
- "description": "API key",
2112
- "env": "FACES_API_KEY",
2113
- "name": "api-key",
1879
+ "medium": {
1880
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1881
+ "name": "medium",
2114
1882
  "hasDynamicHelp": false,
2115
1883
  "multiple": false,
2116
1884
  "type": "option"
2117
1885
  },
2118
- "yes": {
2119
- "description": "Skip confirmation",
2120
- "name": "yes",
1886
+ "oauth-only": {
1887
+ "description": "Prevent fallback to paid system key (use OAuth only)",
1888
+ "name": "oauth-only",
2121
1889
  "allowNo": false,
2122
1890
  "type": "boolean"
2123
1891
  }
2124
1892
  },
2125
1893
  "hasDynamicHelp": false,
2126
1894
  "hiddenAliases": [],
2127
- "id": "config:clear",
1895
+ "id": "chat:chat",
2128
1896
  "pluginAlias": "faces-cli",
2129
1897
  "pluginName": "faces-cli",
2130
1898
  "pluginType": "core",
@@ -2134,25 +1902,20 @@
2134
1902
  "relativePath": [
2135
1903
  "dist",
2136
1904
  "commands",
2137
- "config",
2138
- "clear.js"
1905
+ "chat",
1906
+ "chat.js"
2139
1907
  ]
2140
1908
  },
2141
- "config:set": {
1909
+ "chat:messages": {
2142
1910
  "aliases": [],
2143
1911
  "args": {
2144
- "key": {
2145
- "description": "Config key",
2146
- "name": "key",
2147
- "required": true
2148
- },
2149
- "value": {
2150
- "description": "Config value",
2151
- "name": "value",
1912
+ "face_model": {
1913
+ "description": "Face model (e.g. myface, myface@claude-sonnet-4-6, or head:socrates@claude-sonnet-4-6)",
1914
+ "name": "face_model",
2152
1915
  "required": true
2153
1916
  }
2154
1917
  },
2155
- "description": "Set a config value (e.g. base_url, api_key, token)",
1918
+ "description": "Anthropic Messages API proxy via a face (alias: chat:chat auto-routes Anthropic models here)",
2156
1919
  "flags": {
2157
1920
  "json": {
2158
1921
  "description": "Format output as json.",
@@ -2184,64 +1947,54 @@
2184
1947
  "hasDynamicHelp": false,
2185
1948
  "multiple": false,
2186
1949
  "type": "option"
2187
- }
2188
- },
2189
- "hasDynamicHelp": false,
2190
- "hiddenAliases": [],
2191
- "id": "config:set",
2192
- "pluginAlias": "faces-cli",
2193
- "pluginName": "faces-cli",
2194
- "pluginType": "core",
2195
- "strict": true,
2196
- "enableJsonFlag": true,
2197
- "isESM": true,
2198
- "relativePath": [
2199
- "dist",
2200
- "commands",
2201
- "config",
2202
- "set.js"
2203
- ]
2204
- },
2205
- "config:show": {
2206
- "aliases": [],
2207
- "args": {},
2208
- "description": "Print current config (credentials are masked)",
2209
- "flags": {
2210
- "json": {
2211
- "description": "Format output as json.",
2212
- "helpGroup": "GLOBAL",
2213
- "name": "json",
2214
- "allowNo": false,
2215
- "type": "boolean"
2216
1950
  },
2217
- "base-url": {
2218
- "description": "API base URL",
2219
- "env": "FACES_BASE_URL",
2220
- "name": "base-url",
1951
+ "message": {
1952
+ "char": "m",
1953
+ "description": "User message (repeatable)",
1954
+ "name": "message",
1955
+ "required": true,
1956
+ "hasDynamicHelp": false,
1957
+ "multiple": true,
1958
+ "type": "option"
1959
+ },
1960
+ "system": {
1961
+ "description": "System prompt",
1962
+ "name": "system",
2221
1963
  "hasDynamicHelp": false,
2222
1964
  "multiple": false,
2223
1965
  "type": "option"
2224
1966
  },
2225
- "token": {
2226
- "description": "JWT bearer token",
2227
- "env": "FACES_TOKEN",
2228
- "name": "token",
1967
+ "stream": {
1968
+ "description": "Stream the response",
1969
+ "name": "stream",
1970
+ "allowNo": false,
1971
+ "type": "boolean"
1972
+ },
1973
+ "max-tokens": {
1974
+ "description": "Max tokens",
1975
+ "name": "max-tokens",
1976
+ "default": 1024,
2229
1977
  "hasDynamicHelp": false,
2230
1978
  "multiple": false,
2231
1979
  "type": "option"
2232
1980
  },
2233
- "api-key": {
2234
- "description": "API key",
2235
- "env": "FACES_API_KEY",
2236
- "name": "api-key",
1981
+ "medium": {
1982
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1983
+ "name": "medium",
2237
1984
  "hasDynamicHelp": false,
2238
1985
  "multiple": false,
2239
1986
  "type": "option"
1987
+ },
1988
+ "oauth-only": {
1989
+ "description": "Prevent fallback to paid system key (use OAuth only)",
1990
+ "name": "oauth-only",
1991
+ "allowNo": false,
1992
+ "type": "boolean"
2240
1993
  }
2241
1994
  },
2242
1995
  "hasDynamicHelp": false,
2243
1996
  "hiddenAliases": [],
2244
- "id": "config:show",
1997
+ "id": "chat:messages",
2245
1998
  "pluginAlias": "faces-cli",
2246
1999
  "pluginName": "faces-cli",
2247
2000
  "pluginType": "core",
@@ -2251,14 +2004,20 @@
2251
2004
  "relativePath": [
2252
2005
  "dist",
2253
2006
  "commands",
2254
- "config",
2255
- "show.js"
2007
+ "chat",
2008
+ "messages.js"
2256
2009
  ]
2257
2010
  },
2258
- "keys:create": {
2011
+ "chat:responses": {
2259
2012
  "aliases": [],
2260
- "args": {},
2261
- "description": "Create a new API key (JWT required). The new key is saved to ~/.faces/config.json as api_key by default; pass --no-save to skip.",
2013
+ "args": {
2014
+ "face_model": {
2015
+ "description": "Face model (e.g. myface, myface@gpt-4o, or head:socrates@gpt-5.4)",
2016
+ "name": "face_model",
2017
+ "required": true
2018
+ }
2019
+ },
2020
+ "description": "OpenAI Responses API proxy via a face (alias: chat:chat --responses)",
2262
2021
  "flags": {
2263
2022
  "json": {
2264
2023
  "description": "Format output as json.",
@@ -2291,52 +2050,45 @@
2291
2050
  "multiple": false,
2292
2051
  "type": "option"
2293
2052
  },
2294
- "name": {
2295
- "description": "Key name/label",
2296
- "name": "name",
2053
+ "message": {
2054
+ "char": "m",
2055
+ "description": "User input message",
2056
+ "name": "message",
2297
2057
  "required": true,
2298
2058
  "hasDynamicHelp": false,
2299
2059
  "multiple": false,
2300
2060
  "type": "option"
2301
2061
  },
2302
- "expires-days": {
2303
- "description": "Expiry in days (omit for no expiry)",
2304
- "name": "expires-days",
2305
- "hasDynamicHelp": false,
2306
- "multiple": false,
2307
- "type": "option"
2308
- },
2309
- "budget": {
2310
- "description": "Spend budget in USD",
2311
- "name": "budget",
2062
+ "instructions": {
2063
+ "description": "System instructions",
2064
+ "name": "instructions",
2312
2065
  "hasDynamicHelp": false,
2313
2066
  "multiple": false,
2314
2067
  "type": "option"
2315
2068
  },
2316
- "face": {
2317
- "description": "Allowed face alias (repeatable)",
2318
- "name": "face",
2319
- "hasDynamicHelp": false,
2320
- "multiple": true,
2321
- "type": "option"
2069
+ "stream": {
2070
+ "description": "Stream the response",
2071
+ "name": "stream",
2072
+ "allowNo": false,
2073
+ "type": "boolean"
2322
2074
  },
2323
- "model": {
2324
- "description": "Allowed model name (repeatable)",
2325
- "name": "model",
2075
+ "medium": {
2076
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
2077
+ "name": "medium",
2326
2078
  "hasDynamicHelp": false,
2327
- "multiple": true,
2079
+ "multiple": false,
2328
2080
  "type": "option"
2329
2081
  },
2330
- "save": {
2331
- "description": "Save the new key to ~/.faces/config.json as api_key (default: true; use --no-save to skip)",
2332
- "name": "save",
2333
- "allowNo": true,
2082
+ "oauth-only": {
2083
+ "description": "Prevent fallback to paid system key (use OAuth only)",
2084
+ "name": "oauth-only",
2085
+ "allowNo": false,
2334
2086
  "type": "boolean"
2335
2087
  }
2336
2088
  },
2337
2089
  "hasDynamicHelp": false,
2338
2090
  "hiddenAliases": [],
2339
- "id": "keys:create",
2091
+ "id": "chat:responses",
2340
2092
  "pluginAlias": "faces-cli",
2341
2093
  "pluginName": "faces-cli",
2342
2094
  "pluginType": "core",
@@ -2346,14 +2098,27 @@
2346
2098
  "relativePath": [
2347
2099
  "dist",
2348
2100
  "commands",
2349
- "keys",
2350
- "create.js"
2101
+ "chat",
2102
+ "responses.js"
2351
2103
  ]
2352
2104
  },
2353
- "keys:list": {
2105
+ "chat:thread": {
2354
2106
  "aliases": [],
2355
- "args": {},
2356
- "description": "List all API keys (JWT required)",
2107
+ "args": {
2108
+ "face_username": {
2109
+ "description": "Face alias (alias@model, or owner:alias@model for a published face) — required when starting a new thread",
2110
+ "name": "face_username",
2111
+ "required": false
2112
+ }
2113
+ },
2114
+ "description": "Multi-turn chat thread. Conversation history is stored under ~/.faces/threads/<id>.json — resume any thread later with --id.",
2115
+ "examples": [
2116
+ "<%= config.bin %> <%= command.id %> socrates -m \"What is justice?\"",
2117
+ "<%= config.bin %> <%= command.id %> --id t_abc123 -m \"Say more about that\"",
2118
+ "<%= config.bin %> <%= command.id %> --list",
2119
+ "<%= config.bin %> <%= command.id %> --id t_abc123 --show",
2120
+ "<%= config.bin %> <%= command.id %> --id t_abc123 --delete"
2121
+ ],
2357
2122
  "flags": {
2358
2123
  "json": {
2359
2124
  "description": "Format output as json.",
@@ -2385,155 +2150,98 @@
2385
2150
  "hasDynamicHelp": false,
2386
2151
  "multiple": false,
2387
2152
  "type": "option"
2388
- }
2389
- },
2390
- "hasDynamicHelp": false,
2391
- "hiddenAliases": [],
2392
- "id": "keys:list",
2393
- "pluginAlias": "faces-cli",
2394
- "pluginName": "faces-cli",
2395
- "pluginType": "core",
2396
- "strict": true,
2397
- "enableJsonFlag": true,
2398
- "isESM": true,
2399
- "relativePath": [
2400
- "dist",
2401
- "commands",
2402
- "keys",
2403
- "list.js"
2404
- ]
2405
- },
2406
- "keys:revoke": {
2407
- "aliases": [],
2408
- "args": {
2409
- "key_id": {
2410
- "description": "Key ID",
2411
- "name": "key_id",
2412
- "required": true
2413
- }
2414
- },
2415
- "description": "Revoke an API key (JWT required)",
2416
- "flags": {
2417
- "json": {
2418
- "description": "Format output as json.",
2419
- "helpGroup": "GLOBAL",
2420
- "name": "json",
2421
- "allowNo": false,
2422
- "type": "boolean"
2423
2153
  },
2424
- "base-url": {
2425
- "description": "API base URL",
2426
- "env": "FACES_BASE_URL",
2427
- "name": "base-url",
2154
+ "id": {
2155
+ "description": "Resume an existing thread by id",
2156
+ "name": "id",
2428
2157
  "hasDynamicHelp": false,
2429
2158
  "multiple": false,
2430
2159
  "type": "option"
2431
2160
  },
2432
- "token": {
2433
- "description": "JWT bearer token",
2434
- "env": "FACES_TOKEN",
2435
- "name": "token",
2161
+ "message": {
2162
+ "char": "m",
2163
+ "description": "User message",
2164
+ "name": "message",
2436
2165
  "hasDynamicHelp": false,
2437
2166
  "multiple": false,
2438
2167
  "type": "option"
2439
2168
  },
2440
- "api-key": {
2441
- "description": "API key",
2442
- "env": "FACES_API_KEY",
2443
- "name": "api-key",
2169
+ "file": {
2170
+ "description": "Read message from file",
2171
+ "name": "file",
2444
2172
  "hasDynamicHelp": false,
2445
2173
  "multiple": false,
2446
2174
  "type": "option"
2447
2175
  },
2448
- "yes": {
2449
- "description": "Skip confirmation",
2450
- "name": "yes",
2451
- "allowNo": false,
2452
- "type": "boolean"
2453
- }
2454
- },
2455
- "hasDynamicHelp": false,
2456
- "hiddenAliases": [],
2457
- "id": "keys:revoke",
2458
- "pluginAlias": "faces-cli",
2459
- "pluginName": "faces-cli",
2460
- "pluginType": "core",
2461
- "strict": true,
2462
- "enableJsonFlag": true,
2463
- "isESM": true,
2464
- "relativePath": [
2465
- "dist",
2466
- "commands",
2467
- "keys",
2468
- "revoke.js"
2469
- ]
2470
- },
2471
- "keys:update": {
2472
- "aliases": [],
2473
- "args": {
2474
- "key_id": {
2475
- "description": "Key ID",
2476
- "name": "key_id",
2477
- "required": true
2478
- }
2479
- },
2480
- "description": "Update API key metadata (JWT required)",
2481
- "flags": {
2482
- "json": {
2483
- "description": "Format output as json.",
2484
- "helpGroup": "GLOBAL",
2485
- "name": "json",
2486
- "allowNo": false,
2487
- "type": "boolean"
2488
- },
2489
- "base-url": {
2490
- "description": "API base URL",
2491
- "env": "FACES_BASE_URL",
2492
- "name": "base-url",
2176
+ "llm": {
2177
+ "description": "LLM override (only honored when starting a new thread)",
2178
+ "name": "llm",
2493
2179
  "hasDynamicHelp": false,
2494
2180
  "multiple": false,
2495
2181
  "type": "option"
2496
2182
  },
2497
- "token": {
2498
- "description": "JWT bearer token",
2499
- "env": "FACES_TOKEN",
2500
- "name": "token",
2183
+ "system": {
2184
+ "description": "System prompt (only honored when starting a new thread)",
2185
+ "name": "system",
2501
2186
  "hasDynamicHelp": false,
2502
2187
  "multiple": false,
2503
2188
  "type": "option"
2504
2189
  },
2505
- "api-key": {
2506
- "description": "API key",
2507
- "env": "FACES_API_KEY",
2508
- "name": "api-key",
2190
+ "max-tokens": {
2191
+ "description": "Max tokens",
2192
+ "name": "max-tokens",
2509
2193
  "hasDynamicHelp": false,
2510
2194
  "multiple": false,
2511
2195
  "type": "option"
2512
2196
  },
2513
- "name": {
2514
- "description": "New key name",
2515
- "name": "name",
2197
+ "temperature": {
2198
+ "description": "Temperature (0.0-2.0, OpenAI/Chat Completions only)",
2199
+ "name": "temperature",
2516
2200
  "hasDynamicHelp": false,
2517
2201
  "multiple": false,
2518
2202
  "type": "option"
2519
2203
  },
2520
- "budget": {
2521
- "description": "New spend budget in USD",
2522
- "name": "budget",
2204
+ "stream": {
2205
+ "description": "Stream the response",
2206
+ "name": "stream",
2207
+ "allowNo": false,
2208
+ "type": "boolean"
2209
+ },
2210
+ "medium": {
2211
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
2212
+ "name": "medium",
2523
2213
  "hasDynamicHelp": false,
2524
2214
  "multiple": false,
2525
2215
  "type": "option"
2526
2216
  },
2527
- "reset-spent": {
2528
- "description": "Reset spent amount to zero",
2529
- "name": "reset-spent",
2217
+ "oauth-only": {
2218
+ "description": "Prevent fallback to paid system key",
2219
+ "name": "oauth-only",
2220
+ "allowNo": false,
2221
+ "type": "boolean"
2222
+ },
2223
+ "list": {
2224
+ "description": "List saved threads",
2225
+ "name": "list",
2226
+ "allowNo": false,
2227
+ "type": "boolean"
2228
+ },
2229
+ "show": {
2230
+ "description": "Show the thread transcript (requires --id)",
2231
+ "name": "show",
2232
+ "allowNo": false,
2233
+ "type": "boolean"
2234
+ },
2235
+ "delete": {
2236
+ "description": "Delete the thread (requires --id)",
2237
+ "name": "delete",
2530
2238
  "allowNo": false,
2531
2239
  "type": "boolean"
2532
2240
  }
2533
2241
  },
2534
2242
  "hasDynamicHelp": false,
2535
2243
  "hiddenAliases": [],
2536
- "id": "keys:update",
2244
+ "id": "chat:thread",
2537
2245
  "pluginAlias": "faces-cli",
2538
2246
  "pluginName": "faces-cli",
2539
2247
  "pluginType": "core",
@@ -2543,8 +2251,8 @@
2543
2251
  "relativePath": [
2544
2252
  "dist",
2545
2253
  "commands",
2546
- "keys",
2547
- "update.js"
2254
+ "chat",
2255
+ "thread.js"
2548
2256
  ]
2549
2257
  },
2550
2258
  "face:attributes": {
@@ -2952,30 +2660,270 @@
2952
2660
  "multiple": false,
2953
2661
  "type": "option"
2954
2662
  },
2955
- "profile-addendum-file": {
2956
- "description": "Replace the per-face system prompt from a file.",
2957
- "exclusive": [
2958
- "profile-addendum"
2959
- ],
2960
- "name": "profile-addendum-file",
2663
+ "profile-addendum-file": {
2664
+ "description": "Replace the per-face system prompt from a file.",
2665
+ "exclusive": [
2666
+ "profile-addendum"
2667
+ ],
2668
+ "name": "profile-addendum-file",
2669
+ "hasDynamicHelp": false,
2670
+ "multiple": false,
2671
+ "type": "option"
2672
+ },
2673
+ "clear-profile-addendum": {
2674
+ "description": "Remove the per-face system prompt.",
2675
+ "exclusive": [
2676
+ "profile-addendum",
2677
+ "profile-addendum-file"
2678
+ ],
2679
+ "name": "clear-profile-addendum",
2680
+ "allowNo": false,
2681
+ "type": "boolean"
2682
+ }
2683
+ },
2684
+ "hasDynamicHelp": false,
2685
+ "hiddenAliases": [],
2686
+ "id": "face:edit",
2687
+ "pluginAlias": "faces-cli",
2688
+ "pluginName": "faces-cli",
2689
+ "pluginType": "core",
2690
+ "strict": true,
2691
+ "enableJsonFlag": true,
2692
+ "isESM": true,
2693
+ "relativePath": [
2694
+ "dist",
2695
+ "commands",
2696
+ "face",
2697
+ "edit.js"
2698
+ ]
2699
+ },
2700
+ "face:get": {
2701
+ "aliases": [],
2702
+ "args": {
2703
+ "face_id": {
2704
+ "description": "Face alias",
2705
+ "name": "face_id",
2706
+ "required": true
2707
+ }
2708
+ },
2709
+ "description": "Get details for a face, by alias or owner:alias. A published or shared face is reachable under the same owner:alias address chat uses; it is shown with a note that you do not own it.",
2710
+ "flags": {
2711
+ "json": {
2712
+ "description": "Format output as json.",
2713
+ "helpGroup": "GLOBAL",
2714
+ "name": "json",
2715
+ "allowNo": false,
2716
+ "type": "boolean"
2717
+ },
2718
+ "base-url": {
2719
+ "description": "API base URL",
2720
+ "env": "FACES_BASE_URL",
2721
+ "name": "base-url",
2722
+ "hasDynamicHelp": false,
2723
+ "multiple": false,
2724
+ "type": "option"
2725
+ },
2726
+ "token": {
2727
+ "description": "JWT bearer token",
2728
+ "env": "FACES_TOKEN",
2729
+ "name": "token",
2730
+ "hasDynamicHelp": false,
2731
+ "multiple": false,
2732
+ "type": "option"
2733
+ },
2734
+ "api-key": {
2735
+ "description": "API key",
2736
+ "env": "FACES_API_KEY",
2737
+ "name": "api-key",
2738
+ "hasDynamicHelp": false,
2739
+ "multiple": false,
2740
+ "type": "option"
2741
+ },
2742
+ "include": {
2743
+ "description": "Include extra fields: tags, teams (comma-separated)",
2744
+ "name": "include",
2745
+ "hasDynamicHelp": false,
2746
+ "multiple": false,
2747
+ "type": "option"
2748
+ },
2749
+ "full": {
2750
+ "description": "Print the full profile_addendum instead of a truncated preview",
2751
+ "name": "full",
2752
+ "allowNo": false,
2753
+ "type": "boolean"
2754
+ }
2755
+ },
2756
+ "hasDynamicHelp": false,
2757
+ "hiddenAliases": [],
2758
+ "id": "face:get",
2759
+ "pluginAlias": "faces-cli",
2760
+ "pluginName": "faces-cli",
2761
+ "pluginType": "core",
2762
+ "strict": true,
2763
+ "enableJsonFlag": true,
2764
+ "isESM": true,
2765
+ "relativePath": [
2766
+ "dist",
2767
+ "commands",
2768
+ "face",
2769
+ "get.js"
2770
+ ]
2771
+ },
2772
+ "face:list": {
2773
+ "aliases": [],
2774
+ "args": {},
2775
+ "description": "List faces. By default lists owned faces; use --public to include published faces from other accounts.",
2776
+ "flags": {
2777
+ "json": {
2778
+ "description": "Format output as json.",
2779
+ "helpGroup": "GLOBAL",
2780
+ "name": "json",
2781
+ "allowNo": false,
2782
+ "type": "boolean"
2783
+ },
2784
+ "base-url": {
2785
+ "description": "API base URL",
2786
+ "env": "FACES_BASE_URL",
2787
+ "name": "base-url",
2788
+ "hasDynamicHelp": false,
2789
+ "multiple": false,
2790
+ "type": "option"
2791
+ },
2792
+ "token": {
2793
+ "description": "JWT bearer token",
2794
+ "env": "FACES_TOKEN",
2795
+ "name": "token",
2796
+ "hasDynamicHelp": false,
2797
+ "multiple": false,
2798
+ "type": "option"
2799
+ },
2800
+ "api-key": {
2801
+ "description": "API key",
2802
+ "env": "FACES_API_KEY",
2803
+ "name": "api-key",
2804
+ "hasDynamicHelp": false,
2805
+ "multiple": false,
2806
+ "type": "option"
2807
+ },
2808
+ "tag": {
2809
+ "description": "Filter by tag (repeatable, AND logic)",
2810
+ "name": "tag",
2811
+ "hasDynamicHelp": false,
2812
+ "multiple": true,
2813
+ "type": "option"
2814
+ },
2815
+ "team": {
2816
+ "description": "Filter by team ID (repeatable, OR logic)",
2817
+ "name": "team",
2818
+ "hasDynamicHelp": false,
2819
+ "multiple": true,
2820
+ "type": "option"
2821
+ },
2822
+ "include": {
2823
+ "description": "Include extra fields: tags, teams (comma-separated)",
2824
+ "name": "include",
2825
+ "hasDynamicHelp": false,
2826
+ "multiple": false,
2827
+ "type": "option"
2828
+ },
2829
+ "public": {
2830
+ "description": "Include published faces from other accounts (open to everybody)",
2831
+ "name": "public",
2832
+ "allowNo": false,
2833
+ "type": "boolean"
2834
+ },
2835
+ "shared": {
2836
+ "description": "Include faces other accounts have shared with YOU in particular",
2837
+ "name": "shared",
2838
+ "allowNo": false,
2839
+ "type": "boolean"
2840
+ },
2841
+ "system": {
2842
+ "description": "Show only the curated system faces (published faces owned by 'head')",
2843
+ "name": "system",
2844
+ "allowNo": false,
2845
+ "type": "boolean"
2846
+ },
2847
+ "from-users": {
2848
+ "description": "Only published faces from these owners (repeatable/comma-separated)",
2849
+ "name": "from-users",
2850
+ "hasDynamicHelp": false,
2851
+ "multiple": true,
2852
+ "type": "option"
2853
+ },
2854
+ "not-from-users": {
2855
+ "description": "Exclude published faces from these owners (repeatable/comma-separated)",
2856
+ "name": "not-from-users",
2857
+ "hasDynamicHelp": false,
2858
+ "multiple": true,
2859
+ "type": "option"
2860
+ }
2861
+ },
2862
+ "hasDynamicHelp": false,
2863
+ "hiddenAliases": [],
2864
+ "id": "face:list",
2865
+ "pluginAlias": "faces-cli",
2866
+ "pluginName": "faces-cli",
2867
+ "pluginType": "core",
2868
+ "strict": true,
2869
+ "enableJsonFlag": true,
2870
+ "isESM": true,
2871
+ "relativePath": [
2872
+ "dist",
2873
+ "commands",
2874
+ "face",
2875
+ "list.js"
2876
+ ]
2877
+ },
2878
+ "face:lock": {
2879
+ "aliases": [],
2880
+ "args": {
2881
+ "face_id": {
2882
+ "description": "Face alias",
2883
+ "name": "face_id",
2884
+ "required": true
2885
+ }
2886
+ },
2887
+ "description": "Lock a face (read-only). A locked face still reads and chats normally, but it — and everything it owns (documents, threads, voiceprint) — cannot be changed until unlocked.",
2888
+ "examples": [
2889
+ "<%= config.bin %> <%= command.id %> socrates"
2890
+ ],
2891
+ "flags": {
2892
+ "json": {
2893
+ "description": "Format output as json.",
2894
+ "helpGroup": "GLOBAL",
2895
+ "name": "json",
2896
+ "allowNo": false,
2897
+ "type": "boolean"
2898
+ },
2899
+ "base-url": {
2900
+ "description": "API base URL",
2901
+ "env": "FACES_BASE_URL",
2902
+ "name": "base-url",
2903
+ "hasDynamicHelp": false,
2904
+ "multiple": false,
2905
+ "type": "option"
2906
+ },
2907
+ "token": {
2908
+ "description": "JWT bearer token",
2909
+ "env": "FACES_TOKEN",
2910
+ "name": "token",
2961
2911
  "hasDynamicHelp": false,
2962
2912
  "multiple": false,
2963
2913
  "type": "option"
2964
2914
  },
2965
- "clear-profile-addendum": {
2966
- "description": "Remove the per-face system prompt.",
2967
- "exclusive": [
2968
- "profile-addendum",
2969
- "profile-addendum-file"
2970
- ],
2971
- "name": "clear-profile-addendum",
2972
- "allowNo": false,
2973
- "type": "boolean"
2915
+ "api-key": {
2916
+ "description": "API key",
2917
+ "env": "FACES_API_KEY",
2918
+ "name": "api-key",
2919
+ "hasDynamicHelp": false,
2920
+ "multiple": false,
2921
+ "type": "option"
2974
2922
  }
2975
2923
  },
2976
2924
  "hasDynamicHelp": false,
2977
2925
  "hiddenAliases": [],
2978
- "id": "face:edit",
2926
+ "id": "face:lock",
2979
2927
  "pluginAlias": "faces-cli",
2980
2928
  "pluginName": "faces-cli",
2981
2929
  "pluginType": "core",
@@ -2986,10 +2934,10 @@
2986
2934
  "dist",
2987
2935
  "commands",
2988
2936
  "face",
2989
- "edit.js"
2937
+ "lock.js"
2990
2938
  ]
2991
2939
  },
2992
- "face:get": {
2940
+ "face:neighbors": {
2993
2941
  "aliases": [],
2994
2942
  "args": {
2995
2943
  "face_id": {
@@ -2998,7 +2946,7 @@
2998
2946
  "required": true
2999
2947
  }
3000
2948
  },
3001
- "description": "Get details for a face, by alias or owner:alias. A published or shared face is reachable under the same owner:alias address chat uses; it is shown with a note that you do not own it.",
2949
+ "description": "Find the most similar or dissimilar owned faces to a given face",
3002
2950
  "flags": {
3003
2951
  "json": {
3004
2952
  "description": "Format output as json.",
@@ -3031,23 +2979,38 @@
3031
2979
  "multiple": false,
3032
2980
  "type": "option"
3033
2981
  },
3034
- "include": {
3035
- "description": "Include extra fields: tags, teams (comma-separated)",
3036
- "name": "include",
2982
+ "k": {
2983
+ "description": "Number of results (1–20)",
2984
+ "name": "k",
2985
+ "default": 5,
3037
2986
  "hasDynamicHelp": false,
3038
2987
  "multiple": false,
3039
2988
  "type": "option"
3040
2989
  },
3041
- "full": {
3042
- "description": "Print the full profile_addendum instead of a truncated preview",
3043
- "name": "full",
3044
- "allowNo": false,
3045
- "type": "boolean"
2990
+ "component": {
2991
+ "description": "What to rank on: `face` for overall similarity, or a component position such as 1. Which positions are comparable varies; the API names them if you pick a wrong one.",
2992
+ "name": "component",
2993
+ "default": "face",
2994
+ "hasDynamicHelp": false,
2995
+ "multiple": false,
2996
+ "type": "option"
2997
+ },
2998
+ "direction": {
2999
+ "description": "nearest (most similar) or furthest (most dissimilar)",
3000
+ "name": "direction",
3001
+ "default": "nearest",
3002
+ "hasDynamicHelp": false,
3003
+ "multiple": false,
3004
+ "options": [
3005
+ "nearest",
3006
+ "furthest"
3007
+ ],
3008
+ "type": "option"
3046
3009
  }
3047
3010
  },
3048
3011
  "hasDynamicHelp": false,
3049
3012
  "hiddenAliases": [],
3050
- "id": "face:get",
3013
+ "id": "face:neighbors",
3051
3014
  "pluginAlias": "faces-cli",
3052
3015
  "pluginName": "faces-cli",
3053
3016
  "pluginType": "core",
@@ -3058,13 +3021,22 @@
3058
3021
  "dist",
3059
3022
  "commands",
3060
3023
  "face",
3061
- "get.js"
3024
+ "neighbors.js"
3062
3025
  ]
3063
3026
  },
3064
- "face:list": {
3027
+ "face:publish": {
3065
3028
  "aliases": [],
3066
- "args": {},
3067
- "description": "List faces. By default lists owned faces; use --public to include published faces from other accounts.",
3029
+ "args": {
3030
+ "alias": {
3031
+ "description": "Face alias",
3032
+ "name": "alias",
3033
+ "required": true
3034
+ }
3035
+ },
3036
+ "description": "Publish a face so EVERY account can chat with it. This is a global override: while it is on, everyone can reach the face regardless of who it is shared with. You still pay only to compile it; whoever chats pays for their own inference.",
3037
+ "examples": [
3038
+ "<%= config.bin %> <%= command.id %> alice --yes"
3039
+ ],
3068
3040
  "flags": {
3069
3041
  "json": {
3070
3042
  "description": "Format output as json.",
@@ -3097,63 +3069,16 @@
3097
3069
  "multiple": false,
3098
3070
  "type": "option"
3099
3071
  },
3100
- "tag": {
3101
- "description": "Filter by tag (repeatable, AND logic)",
3102
- "name": "tag",
3103
- "hasDynamicHelp": false,
3104
- "multiple": true,
3105
- "type": "option"
3106
- },
3107
- "team": {
3108
- "description": "Filter by team ID (repeatable, OR logic)",
3109
- "name": "team",
3110
- "hasDynamicHelp": false,
3111
- "multiple": true,
3112
- "type": "option"
3113
- },
3114
- "include": {
3115
- "description": "Include extra fields: tags, teams (comma-separated)",
3116
- "name": "include",
3117
- "hasDynamicHelp": false,
3118
- "multiple": false,
3119
- "type": "option"
3120
- },
3121
- "public": {
3122
- "description": "Include published faces from other accounts (open to everybody)",
3123
- "name": "public",
3124
- "allowNo": false,
3125
- "type": "boolean"
3126
- },
3127
- "shared": {
3128
- "description": "Include faces other accounts have shared with YOU in particular",
3129
- "name": "shared",
3130
- "allowNo": false,
3131
- "type": "boolean"
3132
- },
3133
- "system": {
3134
- "description": "Show only the curated system faces (published faces owned by 'head')",
3135
- "name": "system",
3072
+ "yes": {
3073
+ "description": "Skip confirmation",
3074
+ "name": "yes",
3136
3075
  "allowNo": false,
3137
3076
  "type": "boolean"
3138
- },
3139
- "from-users": {
3140
- "description": "Only published faces from these owners (repeatable/comma-separated)",
3141
- "name": "from-users",
3142
- "hasDynamicHelp": false,
3143
- "multiple": true,
3144
- "type": "option"
3145
- },
3146
- "not-from-users": {
3147
- "description": "Exclude published faces from these owners (repeatable/comma-separated)",
3148
- "name": "not-from-users",
3149
- "hasDynamicHelp": false,
3150
- "multiple": true,
3151
- "type": "option"
3152
3077
  }
3153
3078
  },
3154
3079
  "hasDynamicHelp": false,
3155
3080
  "hiddenAliases": [],
3156
- "id": "face:list",
3081
+ "id": "face:publish",
3157
3082
  "pluginAlias": "faces-cli",
3158
3083
  "pluginName": "faces-cli",
3159
3084
  "pluginType": "core",
@@ -3164,21 +3089,24 @@
3164
3089
  "dist",
3165
3090
  "commands",
3166
3091
  "face",
3167
- "list.js"
3092
+ "publish.js"
3168
3093
  ]
3169
3094
  },
3170
- "face:lock": {
3095
+ "face:share": {
3171
3096
  "aliases": [],
3172
3097
  "args": {
3173
- "face_id": {
3098
+ "alias": {
3174
3099
  "description": "Face alias",
3175
- "name": "face_id",
3100
+ "name": "alias",
3176
3101
  "required": true
3177
3102
  }
3178
3103
  },
3179
- "description": "Lock a face (read-only). A locked face still reads and chats normally, but it and everything it owns (documents, threads, voiceprint) cannot be changed until unlocked.",
3104
+ "description": "Share a face so named accounts can chat with it. Sharing grants chat and nothing else: no reading its documents, no compiling, no re-sharing, and never its profile addendum. --add keeps the current list; --with replaces it.",
3180
3105
  "examples": [
3181
- "<%= config.bin %> <%= command.id %> socrates"
3106
+ "<%= config.bin %> <%= command.id %> alice --list",
3107
+ "<%= config.bin %> <%= command.id %> alice --add dana",
3108
+ "<%= config.bin %> <%= command.id %> alice --with dana --with sam@example.com",
3109
+ "<%= config.bin %> <%= command.id %> alice --none --yes"
3182
3110
  ],
3183
3111
  "flags": {
3184
3112
  "json": {
@@ -3211,11 +3139,55 @@
3211
3139
  "hasDynamicHelp": false,
3212
3140
  "multiple": false,
3213
3141
  "type": "option"
3142
+ },
3143
+ "list": {
3144
+ "description": "Show who the face is shared with, and change nothing",
3145
+ "name": "list",
3146
+ "allowNo": false,
3147
+ "type": "boolean"
3148
+ },
3149
+ "add": {
3150
+ "description": "Add an account, keeping everyone already on the list — username or email (repeatable)",
3151
+ "exclusive": [
3152
+ "with",
3153
+ "none"
3154
+ ],
3155
+ "name": "add",
3156
+ "hasDynamicHelp": false,
3157
+ "multiple": true,
3158
+ "type": "option"
3159
+ },
3160
+ "with": {
3161
+ "description": "Set the list to exactly these accounts, dropping anyone else (repeatable)",
3162
+ "exclusive": [
3163
+ "add",
3164
+ "none"
3165
+ ],
3166
+ "name": "with",
3167
+ "hasDynamicHelp": false,
3168
+ "multiple": true,
3169
+ "type": "option"
3170
+ },
3171
+ "none": {
3172
+ "description": "Revoke everyone",
3173
+ "exclusive": [
3174
+ "add",
3175
+ "with"
3176
+ ],
3177
+ "name": "none",
3178
+ "allowNo": false,
3179
+ "type": "boolean"
3180
+ },
3181
+ "yes": {
3182
+ "description": "Skip the confirmation shown when someone would lose access",
3183
+ "name": "yes",
3184
+ "allowNo": false,
3185
+ "type": "boolean"
3214
3186
  }
3215
3187
  },
3216
3188
  "hasDynamicHelp": false,
3217
3189
  "hiddenAliases": [],
3218
- "id": "face:lock",
3190
+ "id": "face:share",
3219
3191
  "pluginAlias": "faces-cli",
3220
3192
  "pluginName": "faces-cli",
3221
3193
  "pluginType": "core",
@@ -3226,19 +3198,24 @@
3226
3198
  "dist",
3227
3199
  "commands",
3228
3200
  "face",
3229
- "lock.js"
3201
+ "share.js"
3230
3202
  ]
3231
3203
  },
3232
- "face:neighbors": {
3204
+ "face:sources": {
3233
3205
  "aliases": [],
3234
3206
  "args": {
3235
- "face_id": {
3207
+ "alias": {
3236
3208
  "description": "Face alias",
3237
- "name": "face_id",
3209
+ "name": "alias",
3238
3210
  "required": true
3239
3211
  }
3240
3212
  },
3241
- "description": "Find the most similar or dissimilar owned faces to a given face",
3213
+ "description": "List every source compiled into a face: documents and threads together, one row each. Exits 4 if the face does not exist, which is a different answer from a face that has no sources. Content is never printed; read a single source with compile:doc:get or compile:thread:get.",
3214
+ "examples": [
3215
+ "<%= config.bin %> <%= command.id %> alice",
3216
+ "<%= config.bin %> <%= command.id %> alice --type thread",
3217
+ "<%= config.bin %> <%= command.id %> alice --json"
3218
+ ],
3242
3219
  "flags": {
3243
3220
  "json": {
3244
3221
  "description": "Format output as json.",
@@ -3271,38 +3248,74 @@
3271
3248
  "multiple": false,
3272
3249
  "type": "option"
3273
3250
  },
3274
- "k": {
3275
- "description": "Number of results (1–20)",
3276
- "name": "k",
3277
- "default": 5,
3251
+ "type": {
3252
+ "description": "Show only one kind of source",
3253
+ "name": "type",
3254
+ "hasDynamicHelp": false,
3255
+ "multiple": false,
3256
+ "options": [
3257
+ "doc",
3258
+ "thread"
3259
+ ],
3260
+ "type": "option"
3261
+ }
3262
+ },
3263
+ "hasDynamicHelp": false,
3264
+ "hiddenAliases": [],
3265
+ "id": "face:sources",
3266
+ "pluginAlias": "faces-cli",
3267
+ "pluginName": "faces-cli",
3268
+ "pluginType": "core",
3269
+ "strict": true,
3270
+ "enableJsonFlag": true,
3271
+ "isESM": true,
3272
+ "relativePath": [
3273
+ "dist",
3274
+ "commands",
3275
+ "face",
3276
+ "sources.js"
3277
+ ]
3278
+ },
3279
+ "face:stats": {
3280
+ "aliases": [],
3281
+ "args": {},
3282
+ "description": "Compile and chat stats for all owned faces",
3283
+ "flags": {
3284
+ "json": {
3285
+ "description": "Format output as json.",
3286
+ "helpGroup": "GLOBAL",
3287
+ "name": "json",
3288
+ "allowNo": false,
3289
+ "type": "boolean"
3290
+ },
3291
+ "base-url": {
3292
+ "description": "API base URL",
3293
+ "env": "FACES_BASE_URL",
3294
+ "name": "base-url",
3278
3295
  "hasDynamicHelp": false,
3279
3296
  "multiple": false,
3280
3297
  "type": "option"
3281
3298
  },
3282
- "component": {
3283
- "description": "What to rank on: `face` for overall similarity, or a component position such as 1. Which positions are comparable varies; the API names them if you pick a wrong one.",
3284
- "name": "component",
3285
- "default": "face",
3299
+ "token": {
3300
+ "description": "JWT bearer token",
3301
+ "env": "FACES_TOKEN",
3302
+ "name": "token",
3286
3303
  "hasDynamicHelp": false,
3287
3304
  "multiple": false,
3288
3305
  "type": "option"
3289
3306
  },
3290
- "direction": {
3291
- "description": "nearest (most similar) or furthest (most dissimilar)",
3292
- "name": "direction",
3293
- "default": "nearest",
3307
+ "api-key": {
3308
+ "description": "API key",
3309
+ "env": "FACES_API_KEY",
3310
+ "name": "api-key",
3294
3311
  "hasDynamicHelp": false,
3295
3312
  "multiple": false,
3296
- "options": [
3297
- "nearest",
3298
- "furthest"
3299
- ],
3300
3313
  "type": "option"
3301
3314
  }
3302
3315
  },
3303
3316
  "hasDynamicHelp": false,
3304
3317
  "hiddenAliases": [],
3305
- "id": "face:neighbors",
3318
+ "id": "face:stats",
3306
3319
  "pluginAlias": "faces-cli",
3307
3320
  "pluginName": "faces-cli",
3308
3321
  "pluginType": "core",
@@ -3313,10 +3326,10 @@
3313
3326
  "dist",
3314
3327
  "commands",
3315
3328
  "face",
3316
- "neighbors.js"
3329
+ "stats.js"
3317
3330
  ]
3318
3331
  },
3319
- "face:publish": {
3332
+ "face:teams": {
3320
3333
  "aliases": [],
3321
3334
  "args": {
3322
3335
  "alias": {
@@ -3325,10 +3338,7 @@
3325
3338
  "required": true
3326
3339
  }
3327
3340
  },
3328
- "description": "Publish a face so EVERY account can chat with it. This is a global override: while it is on, everyone can reach the face regardless of who it is shared with. You still pay only to compile it; whoever chats pays for their own inference.",
3329
- "examples": [
3330
- "<%= config.bin %> <%= command.id %> alice --yes"
3331
- ],
3341
+ "description": "Set a face's team memberships (replaces all)",
3332
3342
  "flags": {
3333
3343
  "json": {
3334
3344
  "description": "Format output as json.",
@@ -3361,16 +3371,18 @@
3361
3371
  "multiple": false,
3362
3372
  "type": "option"
3363
3373
  },
3364
- "yes": {
3365
- "description": "Skip confirmation",
3366
- "name": "yes",
3367
- "allowNo": false,
3368
- "type": "boolean"
3374
+ "team": {
3375
+ "description": "Team ID (repeatable, replaces all memberships)",
3376
+ "name": "team",
3377
+ "required": true,
3378
+ "hasDynamicHelp": false,
3379
+ "multiple": true,
3380
+ "type": "option"
3369
3381
  }
3370
3382
  },
3371
3383
  "hasDynamicHelp": false,
3372
3384
  "hiddenAliases": [],
3373
- "id": "face:publish",
3385
+ "id": "face:teams",
3374
3386
  "pluginAlias": "faces-cli",
3375
3387
  "pluginName": "faces-cli",
3376
3388
  "pluginType": "core",
@@ -3381,24 +3393,21 @@
3381
3393
  "dist",
3382
3394
  "commands",
3383
3395
  "face",
3384
- "publish.js"
3396
+ "teams.js"
3385
3397
  ]
3386
3398
  },
3387
- "face:share": {
3399
+ "face:unlock": {
3388
3400
  "aliases": [],
3389
3401
  "args": {
3390
- "alias": {
3402
+ "face_id": {
3391
3403
  "description": "Face alias",
3392
- "name": "alias",
3404
+ "name": "face_id",
3393
3405
  "required": true
3394
3406
  }
3395
3407
  },
3396
- "description": "Share a face so named accounts can chat with it. Sharing grants chat and nothing else: no reading its documents, no compiling, no re-sharing, and never its profile addendum. --add keeps the current list; --with replaces it.",
3408
+ "description": "Unlock a face (make it writable again). Thaws the face and everything it owns (documents, threads, voiceprint).",
3397
3409
  "examples": [
3398
- "<%= config.bin %> <%= command.id %> alice --list",
3399
- "<%= config.bin %> <%= command.id %> alice --add dana",
3400
- "<%= config.bin %> <%= command.id %> alice --with dana --with sam@example.com",
3401
- "<%= config.bin %> <%= command.id %> alice --none --yes"
3410
+ "<%= config.bin %> <%= command.id %> socrates"
3402
3411
  ],
3403
3412
  "flags": {
3404
3413
  "json": {
@@ -3431,55 +3440,11 @@
3431
3440
  "hasDynamicHelp": false,
3432
3441
  "multiple": false,
3433
3442
  "type": "option"
3434
- },
3435
- "list": {
3436
- "description": "Show who the face is shared with, and change nothing",
3437
- "name": "list",
3438
- "allowNo": false,
3439
- "type": "boolean"
3440
- },
3441
- "add": {
3442
- "description": "Add an account, keeping everyone already on the list — username or email (repeatable)",
3443
- "exclusive": [
3444
- "with",
3445
- "none"
3446
- ],
3447
- "name": "add",
3448
- "hasDynamicHelp": false,
3449
- "multiple": true,
3450
- "type": "option"
3451
- },
3452
- "with": {
3453
- "description": "Set the list to exactly these accounts, dropping anyone else (repeatable)",
3454
- "exclusive": [
3455
- "add",
3456
- "none"
3457
- ],
3458
- "name": "with",
3459
- "hasDynamicHelp": false,
3460
- "multiple": true,
3461
- "type": "option"
3462
- },
3463
- "none": {
3464
- "description": "Revoke everyone",
3465
- "exclusive": [
3466
- "add",
3467
- "with"
3468
- ],
3469
- "name": "none",
3470
- "allowNo": false,
3471
- "type": "boolean"
3472
- },
3473
- "yes": {
3474
- "description": "Skip the confirmation shown when someone would lose access",
3475
- "name": "yes",
3476
- "allowNo": false,
3477
- "type": "boolean"
3478
3443
  }
3479
3444
  },
3480
3445
  "hasDynamicHelp": false,
3481
3446
  "hiddenAliases": [],
3482
- "id": "face:share",
3447
+ "id": "face:unlock",
3483
3448
  "pluginAlias": "faces-cli",
3484
3449
  "pluginName": "faces-cli",
3485
3450
  "pluginType": "core",
@@ -3490,10 +3455,10 @@
3490
3455
  "dist",
3491
3456
  "commands",
3492
3457
  "face",
3493
- "share.js"
3458
+ "unlock.js"
3494
3459
  ]
3495
3460
  },
3496
- "face:sources": {
3461
+ "face:unpublish": {
3497
3462
  "aliases": [],
3498
3463
  "args": {
3499
3464
  "alias": {
@@ -3502,12 +3467,7 @@
3502
3467
  "required": true
3503
3468
  }
3504
3469
  },
3505
- "description": "List every source compiled into a face: documents and threads together, one row each. Exits 4 if the face does not exist, which is a different answer from a face that has no sources. Content is never printed; read a single source with compile:doc:get or compile:thread:get.",
3506
- "examples": [
3507
- "<%= config.bin %> <%= command.id %> alice",
3508
- "<%= config.bin %> <%= command.id %> alice --type thread",
3509
- "<%= config.bin %> <%= command.id %> alice --json"
3510
- ],
3470
+ "description": "Stop publishing a face. Anyone it is individually shared with keeps their access publishing is an override on top of sharing, not a replacement for it.",
3511
3471
  "flags": {
3512
3472
  "json": {
3513
3473
  "description": "Format output as json.",
@@ -3539,22 +3499,11 @@
3539
3499
  "hasDynamicHelp": false,
3540
3500
  "multiple": false,
3541
3501
  "type": "option"
3542
- },
3543
- "type": {
3544
- "description": "Show only one kind of source",
3545
- "name": "type",
3546
- "hasDynamicHelp": false,
3547
- "multiple": false,
3548
- "options": [
3549
- "doc",
3550
- "thread"
3551
- ],
3552
- "type": "option"
3553
3502
  }
3554
3503
  },
3555
3504
  "hasDynamicHelp": false,
3556
3505
  "hiddenAliases": [],
3557
- "id": "face:sources",
3506
+ "id": "face:unpublish",
3558
3507
  "pluginAlias": "faces-cli",
3559
3508
  "pluginName": "faces-cli",
3560
3509
  "pluginType": "core",
@@ -3565,13 +3514,23 @@
3565
3514
  "dist",
3566
3515
  "commands",
3567
3516
  "face",
3568
- "sources.js"
3517
+ "unpublish.js"
3569
3518
  ]
3570
3519
  },
3571
- "face:stats": {
3520
+ "face:unshare": {
3572
3521
  "aliases": [],
3573
- "args": {},
3574
- "description": "Compile and chat stats for all owned faces",
3522
+ "args": {
3523
+ "alias": {
3524
+ "description": "Face alias",
3525
+ "name": "alias",
3526
+ "required": true
3527
+ }
3528
+ },
3529
+ "description": "Revoke access to a shared face. Takes effect immediately — there is no grace period.",
3530
+ "examples": [
3531
+ "<%= config.bin %> <%= command.id %> alice --from dana --yes",
3532
+ "<%= config.bin %> <%= command.id %> alice --all --yes"
3533
+ ],
3575
3534
  "flags": {
3576
3535
  "json": {
3577
3536
  "description": "Format output as json.",
@@ -3603,11 +3562,36 @@
3603
3562
  "hasDynamicHelp": false,
3604
3563
  "multiple": false,
3605
3564
  "type": "option"
3565
+ },
3566
+ "from": {
3567
+ "description": "Account to revoke (repeatable)",
3568
+ "exclusive": [
3569
+ "all"
3570
+ ],
3571
+ "name": "from",
3572
+ "hasDynamicHelp": false,
3573
+ "multiple": true,
3574
+ "type": "option"
3575
+ },
3576
+ "all": {
3577
+ "description": "Revoke everyone",
3578
+ "exclusive": [
3579
+ "from"
3580
+ ],
3581
+ "name": "all",
3582
+ "allowNo": false,
3583
+ "type": "boolean"
3584
+ },
3585
+ "yes": {
3586
+ "description": "Skip confirmation",
3587
+ "name": "yes",
3588
+ "allowNo": false,
3589
+ "type": "boolean"
3606
3590
  }
3607
3591
  },
3608
3592
  "hasDynamicHelp": false,
3609
3593
  "hiddenAliases": [],
3610
- "id": "face:stats",
3594
+ "id": "face:unshare",
3611
3595
  "pluginAlias": "faces-cli",
3612
3596
  "pluginName": "faces-cli",
3613
3597
  "pluginType": "core",
@@ -3618,19 +3602,13 @@
3618
3602
  "dist",
3619
3603
  "commands",
3620
3604
  "face",
3621
- "stats.js"
3605
+ "unshare.js"
3622
3606
  ]
3623
3607
  },
3624
- "face:teams": {
3608
+ "keys:create": {
3625
3609
  "aliases": [],
3626
- "args": {
3627
- "alias": {
3628
- "description": "Face alias",
3629
- "name": "alias",
3630
- "required": true
3631
- }
3632
- },
3633
- "description": "Set a face's team memberships (replaces all)",
3610
+ "args": {},
3611
+ "description": "Create a new API key (JWT required). The new key is saved to ~/.faces/config.json as api_key by default; pass --no-save to skip.",
3634
3612
  "flags": {
3635
3613
  "json": {
3636
3614
  "description": "Format output as json.",
@@ -3663,18 +3641,52 @@
3663
3641
  "multiple": false,
3664
3642
  "type": "option"
3665
3643
  },
3666
- "team": {
3667
- "description": "Team ID (repeatable, replaces all memberships)",
3668
- "name": "team",
3644
+ "name": {
3645
+ "description": "Key name/label",
3646
+ "name": "name",
3669
3647
  "required": true,
3670
3648
  "hasDynamicHelp": false,
3649
+ "multiple": false,
3650
+ "type": "option"
3651
+ },
3652
+ "expires-days": {
3653
+ "description": "Expiry in days (omit for no expiry)",
3654
+ "name": "expires-days",
3655
+ "hasDynamicHelp": false,
3656
+ "multiple": false,
3657
+ "type": "option"
3658
+ },
3659
+ "budget": {
3660
+ "description": "Spend budget in USD",
3661
+ "name": "budget",
3662
+ "hasDynamicHelp": false,
3663
+ "multiple": false,
3664
+ "type": "option"
3665
+ },
3666
+ "face": {
3667
+ "description": "Allowed face alias (repeatable)",
3668
+ "name": "face",
3669
+ "hasDynamicHelp": false,
3670
+ "multiple": true,
3671
+ "type": "option"
3672
+ },
3673
+ "model": {
3674
+ "description": "Allowed model name (repeatable)",
3675
+ "name": "model",
3676
+ "hasDynamicHelp": false,
3671
3677
  "multiple": true,
3672
3678
  "type": "option"
3679
+ },
3680
+ "save": {
3681
+ "description": "Save the new key to ~/.faces/config.json as api_key (default: true; use --no-save to skip)",
3682
+ "name": "save",
3683
+ "allowNo": true,
3684
+ "type": "boolean"
3673
3685
  }
3674
3686
  },
3675
3687
  "hasDynamicHelp": false,
3676
3688
  "hiddenAliases": [],
3677
- "id": "face:teams",
3689
+ "id": "keys:create",
3678
3690
  "pluginAlias": "faces-cli",
3679
3691
  "pluginName": "faces-cli",
3680
3692
  "pluginType": "core",
@@ -3684,23 +3696,14 @@
3684
3696
  "relativePath": [
3685
3697
  "dist",
3686
3698
  "commands",
3687
- "face",
3688
- "teams.js"
3699
+ "keys",
3700
+ "create.js"
3689
3701
  ]
3690
- },
3691
- "face:unlock": {
3692
- "aliases": [],
3693
- "args": {
3694
- "face_id": {
3695
- "description": "Face alias",
3696
- "name": "face_id",
3697
- "required": true
3698
- }
3699
- },
3700
- "description": "Unlock a face (make it writable again). Thaws the face and everything it owns (documents, threads, voiceprint).",
3701
- "examples": [
3702
- "<%= config.bin %> <%= command.id %> socrates"
3703
- ],
3702
+ },
3703
+ "keys:list": {
3704
+ "aliases": [],
3705
+ "args": {},
3706
+ "description": "List all API keys (JWT required)",
3704
3707
  "flags": {
3705
3708
  "json": {
3706
3709
  "description": "Format output as json.",
@@ -3736,7 +3739,7 @@
3736
3739
  },
3737
3740
  "hasDynamicHelp": false,
3738
3741
  "hiddenAliases": [],
3739
- "id": "face:unlock",
3742
+ "id": "keys:list",
3740
3743
  "pluginAlias": "faces-cli",
3741
3744
  "pluginName": "faces-cli",
3742
3745
  "pluginType": "core",
@@ -3746,20 +3749,20 @@
3746
3749
  "relativePath": [
3747
3750
  "dist",
3748
3751
  "commands",
3749
- "face",
3750
- "unlock.js"
3752
+ "keys",
3753
+ "list.js"
3751
3754
  ]
3752
3755
  },
3753
- "face:unpublish": {
3756
+ "keys:revoke": {
3754
3757
  "aliases": [],
3755
3758
  "args": {
3756
- "alias": {
3757
- "description": "Face alias",
3758
- "name": "alias",
3759
+ "key_id": {
3760
+ "description": "Key ID",
3761
+ "name": "key_id",
3759
3762
  "required": true
3760
3763
  }
3761
3764
  },
3762
- "description": "Stop publishing a face. Anyone it is individually shared with keeps their access — publishing is an override on top of sharing, not a replacement for it.",
3765
+ "description": "Revoke an API key (JWT required)",
3763
3766
  "flags": {
3764
3767
  "json": {
3765
3768
  "description": "Format output as json.",
@@ -3791,11 +3794,17 @@
3791
3794
  "hasDynamicHelp": false,
3792
3795
  "multiple": false,
3793
3796
  "type": "option"
3797
+ },
3798
+ "yes": {
3799
+ "description": "Skip confirmation",
3800
+ "name": "yes",
3801
+ "allowNo": false,
3802
+ "type": "boolean"
3794
3803
  }
3795
3804
  },
3796
3805
  "hasDynamicHelp": false,
3797
3806
  "hiddenAliases": [],
3798
- "id": "face:unpublish",
3807
+ "id": "keys:revoke",
3799
3808
  "pluginAlias": "faces-cli",
3800
3809
  "pluginName": "faces-cli",
3801
3810
  "pluginType": "core",
@@ -3805,24 +3814,20 @@
3805
3814
  "relativePath": [
3806
3815
  "dist",
3807
3816
  "commands",
3808
- "face",
3809
- "unpublish.js"
3817
+ "keys",
3818
+ "revoke.js"
3810
3819
  ]
3811
3820
  },
3812
- "face:unshare": {
3821
+ "keys:update": {
3813
3822
  "aliases": [],
3814
3823
  "args": {
3815
- "alias": {
3816
- "description": "Face alias",
3817
- "name": "alias",
3824
+ "key_id": {
3825
+ "description": "Key ID",
3826
+ "name": "key_id",
3818
3827
  "required": true
3819
3828
  }
3820
3829
  },
3821
- "description": "Revoke access to a shared face. Takes effect immediately — there is no grace period.",
3822
- "examples": [
3823
- "<%= config.bin %> <%= command.id %> alice --from dana --yes",
3824
- "<%= config.bin %> <%= command.id %> alice --all --yes"
3825
- ],
3830
+ "description": "Update API key metadata (JWT required)",
3826
3831
  "flags": {
3827
3832
  "json": {
3828
3833
  "description": "Format output as json.",
@@ -3855,35 +3860,30 @@
3855
3860
  "multiple": false,
3856
3861
  "type": "option"
3857
3862
  },
3858
- "from": {
3859
- "description": "Account to revoke (repeatable)",
3860
- "exclusive": [
3861
- "all"
3862
- ],
3863
- "name": "from",
3863
+ "name": {
3864
+ "description": "New key name",
3865
+ "name": "name",
3864
3866
  "hasDynamicHelp": false,
3865
- "multiple": true,
3867
+ "multiple": false,
3866
3868
  "type": "option"
3867
3869
  },
3868
- "all": {
3869
- "description": "Revoke everyone",
3870
- "exclusive": [
3871
- "from"
3872
- ],
3873
- "name": "all",
3874
- "allowNo": false,
3875
- "type": "boolean"
3870
+ "budget": {
3871
+ "description": "New spend budget in USD",
3872
+ "name": "budget",
3873
+ "hasDynamicHelp": false,
3874
+ "multiple": false,
3875
+ "type": "option"
3876
3876
  },
3877
- "yes": {
3878
- "description": "Skip confirmation",
3879
- "name": "yes",
3877
+ "reset-spent": {
3878
+ "description": "Reset spent amount to zero",
3879
+ "name": "reset-spent",
3880
3880
  "allowNo": false,
3881
3881
  "type": "boolean"
3882
3882
  }
3883
3883
  },
3884
3884
  "hasDynamicHelp": false,
3885
3885
  "hiddenAliases": [],
3886
- "id": "face:unshare",
3886
+ "id": "keys:update",
3887
3887
  "pluginAlias": "faces-cli",
3888
3888
  "pluginName": "faces-cli",
3889
3889
  "pluginType": "core",
@@ -3893,8 +3893,8 @@
3893
3893
  "relativePath": [
3894
3894
  "dist",
3895
3895
  "commands",
3896
- "face",
3897
- "unshare.js"
3896
+ "keys",
3897
+ "update.js"
3898
3898
  ]
3899
3899
  },
3900
3900
  "style:delete": {
@@ -4100,7 +4100,7 @@
4100
4100
  "required": true
4101
4101
  }
4102
4102
  },
4103
- "description": "Go back to the style a face had before the last style:make. A face holds one style per medium, so name which one with --medium when it has more than one. Two versions are kept per medium, so this goes back exactly one step. It changes how the face writes immediately, so it asks first.",
4103
+ "description": "Go back to the style a face had before the last style:make. Two versions are kept per medium, so this is a toggle: running it again returns to where you started. A face holds one style per medium, so name which one with --medium when it has more than one. It changes how the face writes immediately, so it asks first.",
4104
4104
  "examples": [
4105
4105
  "<%= config.bin %> <%= command.id %> alice --yes",
4106
4106
  "<%= config.bin %> <%= command.id %> alice --medium email --yes"
@@ -5148,7 +5148,7 @@
5148
5148
  "index.js"
5149
5149
  ]
5150
5150
  },
5151
- "compile:thread:create": {
5151
+ "compile:doc:create": {
5152
5152
  "aliases": [],
5153
5153
  "args": {
5154
5154
  "face_id": {
@@ -5157,7 +5157,7 @@
5157
5157
  "required": true
5158
5158
  }
5159
5159
  },
5160
- "description": "Start a new thread for a face",
5160
+ "description": "Submit a document to a face",
5161
5161
  "flags": {
5162
5162
  "json": {
5163
5163
  "description": "Format output as json.",
@@ -5191,22 +5191,49 @@
5191
5191
  "type": "option"
5192
5192
  },
5193
5193
  "label": {
5194
- "description": "Thread label",
5194
+ "description": "Document label/title",
5195
5195
  "name": "label",
5196
5196
  "hasDynamicHelp": false,
5197
5197
  "multiple": false,
5198
5198
  "type": "option"
5199
5199
  },
5200
- "oauth-only": {
5201
- "description": "Prevent fallback to paid system key (use OAuth only)",
5202
- "name": "oauth-only",
5203
- "allowNo": false,
5204
- "type": "boolean"
5200
+ "content": {
5201
+ "description": "Inline text content",
5202
+ "name": "content",
5203
+ "hasDynamicHelp": false,
5204
+ "multiple": false,
5205
+ "type": "option"
5206
+ },
5207
+ "file": {
5208
+ "description": "Read content from file",
5209
+ "name": "file",
5210
+ "hasDynamicHelp": false,
5211
+ "multiple": false,
5212
+ "type": "option"
5213
+ },
5214
+ "medium": {
5215
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5216
+ "name": "medium",
5217
+ "hasDynamicHelp": false,
5218
+ "multiple": false,
5219
+ "type": "option"
5220
+ },
5221
+ "perspective": {
5222
+ "description": "Perspective (first-person or third-person)",
5223
+ "name": "perspective",
5224
+ "default": "first-person",
5225
+ "hasDynamicHelp": false,
5226
+ "multiple": false,
5227
+ "options": [
5228
+ "first-person",
5229
+ "third-person"
5230
+ ],
5231
+ "type": "option"
5205
5232
  }
5206
5233
  },
5207
5234
  "hasDynamicHelp": false,
5208
5235
  "hiddenAliases": [],
5209
- "id": "compile:thread:create",
5236
+ "id": "compile:doc:create",
5210
5237
  "pluginAlias": "faces-cli",
5211
5238
  "pluginName": "faces-cli",
5212
5239
  "pluginType": "core",
@@ -5217,20 +5244,20 @@
5217
5244
  "dist",
5218
5245
  "commands",
5219
5246
  "compile",
5220
- "thread",
5247
+ "doc",
5221
5248
  "create.js"
5222
5249
  ]
5223
5250
  },
5224
- "compile:thread:delete": {
5251
+ "compile:doc:delete": {
5225
5252
  "aliases": [],
5226
5253
  "args": {
5227
- "thread_id": {
5228
- "description": "Thread ID",
5229
- "name": "thread_id",
5254
+ "doc_id": {
5255
+ "description": "Document ID",
5256
+ "name": "doc_id",
5230
5257
  "required": true
5231
5258
  }
5232
5259
  },
5233
- "description": "Delete a thread",
5260
+ "description": "Delete a document",
5234
5261
  "flags": {
5235
5262
  "json": {
5236
5263
  "description": "Format output as json.",
@@ -5262,17 +5289,11 @@
5262
5289
  "hasDynamicHelp": false,
5263
5290
  "multiple": false,
5264
5291
  "type": "option"
5265
- },
5266
- "yes": {
5267
- "description": "Skip confirmation",
5268
- "name": "yes",
5269
- "allowNo": false,
5270
- "type": "boolean"
5271
5292
  }
5272
5293
  },
5273
5294
  "hasDynamicHelp": false,
5274
5295
  "hiddenAliases": [],
5275
- "id": "compile:thread:delete",
5296
+ "id": "compile:doc:delete",
5276
5297
  "pluginAlias": "faces-cli",
5277
5298
  "pluginName": "faces-cli",
5278
5299
  "pluginType": "core",
@@ -5283,20 +5304,20 @@
5283
5304
  "dist",
5284
5305
  "commands",
5285
5306
  "compile",
5286
- "thread",
5307
+ "doc",
5287
5308
  "delete.js"
5288
5309
  ]
5289
5310
  },
5290
- "compile:thread:edit": {
5311
+ "compile:doc:edit": {
5291
5312
  "aliases": [],
5292
5313
  "args": {
5293
- "thread_id": {
5294
- "description": "Thread ID",
5295
- "name": "thread_id",
5314
+ "doc_id": {
5315
+ "description": "Document ID",
5316
+ "name": "doc_id",
5296
5317
  "required": true
5297
5318
  }
5298
5319
  },
5299
- "description": "Edit a thread (label and/or reassign face speaker)",
5320
+ "description": "Edit a document (label, content, or perspective)",
5300
5321
  "flags": {
5301
5322
  "json": {
5302
5323
  "description": "Format output as json.",
@@ -5330,23 +5351,48 @@
5330
5351
  "type": "option"
5331
5352
  },
5332
5353
  "label": {
5333
- "description": "New thread label",
5354
+ "description": "New label/title",
5334
5355
  "name": "label",
5335
5356
  "hasDynamicHelp": false,
5336
5357
  "multiple": false,
5337
5358
  "type": "option"
5338
5359
  },
5339
- "face-speaker": {
5340
- "description": "Reassign face speaker: set this speaker to role=user, all others to role=assistant",
5341
- "name": "face-speaker",
5360
+ "content": {
5361
+ "description": "New inline text content",
5362
+ "name": "content",
5363
+ "hasDynamicHelp": false,
5364
+ "multiple": false,
5365
+ "type": "option"
5366
+ },
5367
+ "file": {
5368
+ "description": "Read new content from file",
5369
+ "name": "file",
5342
5370
  "hasDynamicHelp": false,
5343
5371
  "multiple": false,
5344
5372
  "type": "option"
5373
+ },
5374
+ "medium": {
5375
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5376
+ "name": "medium",
5377
+ "hasDynamicHelp": false,
5378
+ "multiple": false,
5379
+ "type": "option"
5380
+ },
5381
+ "perspective": {
5382
+ "description": "Perspective (first-person or third-person)",
5383
+ "name": "perspective",
5384
+ "hasDynamicHelp": false,
5385
+ "multiple": false,
5386
+ "options": [
5387
+ "first-person",
5388
+ "third-person"
5389
+ ],
5390
+ "type": "option"
5345
5391
  }
5346
5392
  },
5347
5393
  "hasDynamicHelp": false,
5348
5394
  "hiddenAliases": [],
5349
- "id": "compile:thread:edit",
5395
+ "id": "compile:doc:edit",
5350
5396
  "pluginAlias": "faces-cli",
5351
5397
  "pluginName": "faces-cli",
5352
5398
  "pluginType": "core",
@@ -5357,20 +5403,20 @@
5357
5403
  "dist",
5358
5404
  "commands",
5359
5405
  "compile",
5360
- "thread",
5406
+ "doc",
5361
5407
  "edit.js"
5362
5408
  ]
5363
5409
  },
5364
- "compile:thread:get": {
5410
+ "compile:doc:get": {
5365
5411
  "aliases": [],
5366
5412
  "args": {
5367
- "thread_id": {
5368
- "description": "Thread ID",
5369
- "name": "thread_id",
5413
+ "doc_id": {
5414
+ "description": "Document ID",
5415
+ "name": "doc_id",
5370
5416
  "required": true
5371
5417
  }
5372
5418
  },
5373
- "description": "Get a thread by ID",
5419
+ "description": "Get a document by ID",
5374
5420
  "flags": {
5375
5421
  "json": {
5376
5422
  "description": "Format output as json.",
@@ -5406,7 +5452,7 @@
5406
5452
  },
5407
5453
  "hasDynamicHelp": false,
5408
5454
  "hiddenAliases": [],
5409
- "id": "compile:thread:get",
5455
+ "id": "compile:doc:get",
5410
5456
  "pluginAlias": "faces-cli",
5411
5457
  "pluginName": "faces-cli",
5412
5458
  "pluginType": "core",
@@ -5417,11 +5463,11 @@
5417
5463
  "dist",
5418
5464
  "commands",
5419
5465
  "compile",
5420
- "thread",
5466
+ "doc",
5421
5467
  "get.js"
5422
5468
  ]
5423
5469
  },
5424
- "compile:thread:list": {
5470
+ "compile:doc": {
5425
5471
  "aliases": [],
5426
5472
  "args": {
5427
5473
  "face_id": {
@@ -5430,7 +5476,11 @@
5430
5476
  "required": true
5431
5477
  }
5432
5478
  },
5433
- "description": "List threads for a face",
5479
+ "description": "Compile one or more documents into a face (create → make in one step). Repeat --file to submit several documents in a single command; each file becomes its own document rather than being concatenated.",
5480
+ "examples": [
5481
+ "<%= config.bin %> <%= command.id %> alice --file notes.txt",
5482
+ "<%= config.bin %> <%= command.id %> alice --file a.txt --file b.txt --file c.txt --no-wait --json"
5483
+ ],
5434
5484
  "flags": {
5435
5485
  "json": {
5436
5486
  "description": "Format output as json.",
@@ -5439,34 +5489,91 @@
5439
5489
  "allowNo": false,
5440
5490
  "type": "boolean"
5441
5491
  },
5442
- "base-url": {
5443
- "description": "API base URL",
5444
- "env": "FACES_BASE_URL",
5445
- "name": "base-url",
5492
+ "base-url": {
5493
+ "description": "API base URL",
5494
+ "env": "FACES_BASE_URL",
5495
+ "name": "base-url",
5496
+ "hasDynamicHelp": false,
5497
+ "multiple": false,
5498
+ "type": "option"
5499
+ },
5500
+ "token": {
5501
+ "description": "JWT bearer token",
5502
+ "env": "FACES_TOKEN",
5503
+ "name": "token",
5504
+ "hasDynamicHelp": false,
5505
+ "multiple": false,
5506
+ "type": "option"
5507
+ },
5508
+ "api-key": {
5509
+ "description": "API key",
5510
+ "env": "FACES_API_KEY",
5511
+ "name": "api-key",
5512
+ "hasDynamicHelp": false,
5513
+ "multiple": false,
5514
+ "type": "option"
5515
+ },
5516
+ "label": {
5517
+ "description": "Document label/title (single document only; with several files each is labelled by its filename)",
5518
+ "name": "label",
5519
+ "hasDynamicHelp": false,
5520
+ "multiple": false,
5521
+ "type": "option"
5522
+ },
5523
+ "content": {
5524
+ "description": "Inline text content",
5525
+ "exclusive": [
5526
+ "file"
5527
+ ],
5528
+ "name": "content",
5529
+ "hasDynamicHelp": false,
5530
+ "multiple": false,
5531
+ "type": "option"
5532
+ },
5533
+ "file": {
5534
+ "description": "Read content from file (repeatable — each file becomes its own document)",
5535
+ "name": "file",
5536
+ "hasDynamicHelp": false,
5537
+ "multiple": true,
5538
+ "type": "option"
5539
+ },
5540
+ "medium": {
5541
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5542
+ "name": "medium",
5446
5543
  "hasDynamicHelp": false,
5447
5544
  "multiple": false,
5448
5545
  "type": "option"
5449
5546
  },
5450
- "token": {
5451
- "description": "JWT bearer token",
5452
- "env": "FACES_TOKEN",
5453
- "name": "token",
5547
+ "perspective": {
5548
+ "description": "Perspective",
5549
+ "name": "perspective",
5550
+ "default": "first-person",
5454
5551
  "hasDynamicHelp": false,
5455
5552
  "multiple": false,
5553
+ "options": [
5554
+ "first-person",
5555
+ "third-person"
5556
+ ],
5456
5557
  "type": "option"
5457
5558
  },
5458
- "api-key": {
5459
- "description": "API key",
5460
- "env": "FACES_API_KEY",
5461
- "name": "api-key",
5559
+ "timeout": {
5560
+ "description": "Compile timeout in seconds, per document (default: 600)",
5561
+ "name": "timeout",
5562
+ "default": 600,
5462
5563
  "hasDynamicHelp": false,
5463
5564
  "multiple": false,
5464
5565
  "type": "option"
5566
+ },
5567
+ "no-wait": {
5568
+ "description": "Create and trigger compilation, then return immediately without polling.",
5569
+ "name": "no-wait",
5570
+ "allowNo": false,
5571
+ "type": "boolean"
5465
5572
  }
5466
5573
  },
5467
5574
  "hasDynamicHelp": false,
5468
5575
  "hiddenAliases": [],
5469
- "id": "compile:thread:list",
5576
+ "id": "compile:doc",
5470
5577
  "pluginAlias": "faces-cli",
5471
5578
  "pluginName": "faces-cli",
5472
5579
  "pluginType": "core",
@@ -5477,20 +5584,20 @@
5477
5584
  "dist",
5478
5585
  "commands",
5479
5586
  "compile",
5480
- "thread",
5481
- "list.js"
5587
+ "doc",
5588
+ "index.js"
5482
5589
  ]
5483
5590
  },
5484
- "compile:thread:make": {
5591
+ "compile:doc:list": {
5485
5592
  "aliases": [],
5486
5593
  "args": {
5487
- "thread_id": {
5488
- "description": "Thread ID",
5489
- "name": "thread_id",
5594
+ "face_id": {
5595
+ "description": "Face alias",
5596
+ "name": "face_id",
5490
5597
  "required": true
5491
5598
  }
5492
5599
  },
5493
- "description": "Compile an existing thread (prepare + sync in one step)",
5600
+ "description": "List documents for a face. Each document's full text is omitted unless --verbose, so a face with a real corpus stays readable. For a table of every source, documents and threads together, use face:sources.",
5494
5601
  "flags": {
5495
5602
  "json": {
5496
5603
  "description": "Format output as json.",
@@ -5523,24 +5630,16 @@
5523
5630
  "multiple": false,
5524
5631
  "type": "option"
5525
5632
  },
5526
- "timeout": {
5527
- "description": "Compile timeout in seconds (default: 600)",
5528
- "name": "timeout",
5529
- "default": 600,
5530
- "hasDynamicHelp": false,
5531
- "multiple": false,
5532
- "type": "option"
5533
- },
5534
- "no-wait": {
5535
- "description": "Return immediately after triggering compilation. Prints the thread ID for manual polling.",
5536
- "name": "no-wait",
5633
+ "verbose": {
5634
+ "description": "Include each document's full text",
5635
+ "name": "verbose",
5537
5636
  "allowNo": false,
5538
5637
  "type": "boolean"
5539
5638
  }
5540
5639
  },
5541
5640
  "hasDynamicHelp": false,
5542
5641
  "hiddenAliases": [],
5543
- "id": "compile:thread:make",
5642
+ "id": "compile:doc:list",
5544
5643
  "pluginAlias": "faces-cli",
5545
5644
  "pluginName": "faces-cli",
5546
5645
  "pluginType": "core",
@@ -5551,20 +5650,20 @@
5551
5650
  "dist",
5552
5651
  "commands",
5553
5652
  "compile",
5554
- "thread",
5555
- "make.js"
5653
+ "doc",
5654
+ "list.js"
5556
5655
  ]
5557
5656
  },
5558
- "compile:thread:message": {
5657
+ "compile:doc:make": {
5559
5658
  "aliases": [],
5560
5659
  "args": {
5561
- "thread_id": {
5562
- "description": "Thread ID",
5563
- "name": "thread_id",
5660
+ "doc_id": {
5661
+ "description": "Document ID",
5662
+ "name": "doc_id",
5564
5663
  "required": true
5565
5664
  }
5566
5665
  },
5567
- "description": "Send a user message to a thread",
5666
+ "description": "Compile an existing document (prepare + sync in one step)",
5568
5667
  "flags": {
5569
5668
  "json": {
5570
5669
  "description": "Format output as json.",
@@ -5597,25 +5696,24 @@
5597
5696
  "multiple": false,
5598
5697
  "type": "option"
5599
5698
  },
5600
- "message": {
5601
- "char": "m",
5602
- "description": "User message to append",
5603
- "name": "message",
5604
- "required": true,
5699
+ "timeout": {
5700
+ "description": "Compile timeout in seconds (default: 600)",
5701
+ "name": "timeout",
5702
+ "default": 600,
5605
5703
  "hasDynamicHelp": false,
5606
5704
  "multiple": false,
5607
5705
  "type": "option"
5608
5706
  },
5609
- "oauth-only": {
5610
- "description": "Prevent fallback to paid system key (use OAuth only)",
5611
- "name": "oauth-only",
5707
+ "no-wait": {
5708
+ "description": "Return immediately after triggering compilation. Prints the document ID for manual polling.",
5709
+ "name": "no-wait",
5612
5710
  "allowNo": false,
5613
5711
  "type": "boolean"
5614
5712
  }
5615
5713
  },
5616
5714
  "hasDynamicHelp": false,
5617
5715
  "hiddenAliases": [],
5618
- "id": "compile:thread:message",
5716
+ "id": "compile:doc:make",
5619
5717
  "pluginAlias": "faces-cli",
5620
5718
  "pluginName": "faces-cli",
5621
5719
  "pluginType": "core",
@@ -5626,20 +5724,20 @@
5626
5724
  "dist",
5627
5725
  "commands",
5628
5726
  "compile",
5629
- "thread",
5630
- "message.js"
5727
+ "doc",
5728
+ "make.js"
5631
5729
  ]
5632
5730
  },
5633
- "compile:thread:pause": {
5731
+ "compile:doc:pause": {
5634
5732
  "aliases": [],
5635
5733
  "args": {
5636
- "thread_id": {
5637
- "description": "Thread ID",
5638
- "name": "thread_id",
5734
+ "doc_id": {
5735
+ "description": "Document ID",
5736
+ "name": "doc_id",
5639
5737
  "required": true
5640
5738
  }
5641
5739
  },
5642
- "description": "Ask a running thread compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
5740
+ "description": "Ask a running document compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
5643
5741
  "flags": {
5644
5742
  "json": {
5645
5743
  "description": "Format output as json.",
@@ -5689,7 +5787,7 @@
5689
5787
  },
5690
5788
  "hasDynamicHelp": false,
5691
5789
  "hiddenAliases": [],
5692
- "id": "compile:thread:pause",
5790
+ "id": "compile:doc:pause",
5693
5791
  "pluginAlias": "faces-cli",
5694
5792
  "pluginName": "faces-cli",
5695
5793
  "pluginType": "core",
@@ -5700,20 +5798,20 @@
5700
5798
  "dist",
5701
5799
  "commands",
5702
5800
  "compile",
5703
- "thread",
5801
+ "doc",
5704
5802
  "pause.js"
5705
5803
  ]
5706
5804
  },
5707
- "compile:thread:reset": {
5805
+ "compile:doc:reset": {
5708
5806
  "aliases": [],
5709
5807
  "args": {
5710
- "thread_id": {
5711
- "description": "Thread ID",
5712
- "name": "thread_id",
5808
+ "doc_id": {
5809
+ "description": "Document ID",
5810
+ "name": "doc_id",
5713
5811
  "required": true
5714
5812
  }
5715
5813
  },
5716
- "description": "Reset thread compilation progress (wipe extraction, keep source messages)",
5814
+ "description": "Reset document compilation progress (wipe extraction, keep content)",
5717
5815
  "flags": {
5718
5816
  "json": {
5719
5817
  "description": "Format output as json.",
@@ -5755,7 +5853,7 @@
5755
5853
  },
5756
5854
  "hasDynamicHelp": false,
5757
5855
  "hiddenAliases": [],
5758
- "id": "compile:thread:reset",
5856
+ "id": "compile:doc:reset",
5759
5857
  "pluginAlias": "faces-cli",
5760
5858
  "pluginName": "faces-cli",
5761
5859
  "pluginType": "core",
@@ -5766,20 +5864,20 @@
5766
5864
  "dist",
5767
5865
  "commands",
5768
5866
  "compile",
5769
- "thread",
5867
+ "doc",
5770
5868
  "reset.js"
5771
5869
  ]
5772
5870
  },
5773
- "compile:thread:sync": {
5871
+ "compile:thread:create": {
5774
5872
  "aliases": [],
5775
5873
  "args": {
5776
- "thread_id": {
5777
- "description": "Thread ID",
5778
- "name": "thread_id",
5874
+ "face_id": {
5875
+ "description": "Face alias",
5876
+ "name": "face_id",
5779
5877
  "required": true
5780
5878
  }
5781
5879
  },
5782
- "description": "Archive and sync a thread into a face",
5880
+ "description": "Start a new thread for a face",
5783
5881
  "flags": {
5784
5882
  "json": {
5785
5883
  "description": "Format output as json.",
@@ -5811,11 +5909,24 @@
5811
5909
  "hasDynamicHelp": false,
5812
5910
  "multiple": false,
5813
5911
  "type": "option"
5912
+ },
5913
+ "label": {
5914
+ "description": "Thread label",
5915
+ "name": "label",
5916
+ "hasDynamicHelp": false,
5917
+ "multiple": false,
5918
+ "type": "option"
5919
+ },
5920
+ "oauth-only": {
5921
+ "description": "Prevent fallback to paid system key (use OAuth only)",
5922
+ "name": "oauth-only",
5923
+ "allowNo": false,
5924
+ "type": "boolean"
5814
5925
  }
5815
5926
  },
5816
5927
  "hasDynamicHelp": false,
5817
5928
  "hiddenAliases": [],
5818
- "id": "compile:thread:sync",
5929
+ "id": "compile:thread:create",
5819
5930
  "pluginAlias": "faces-cli",
5820
5931
  "pluginName": "faces-cli",
5821
5932
  "pluginType": "core",
@@ -5827,19 +5938,19 @@
5827
5938
  "commands",
5828
5939
  "compile",
5829
5940
  "thread",
5830
- "sync.js"
5941
+ "create.js"
5831
5942
  ]
5832
5943
  },
5833
- "compile:doc:create": {
5944
+ "compile:thread:delete": {
5834
5945
  "aliases": [],
5835
5946
  "args": {
5836
- "face_id": {
5837
- "description": "Face alias",
5838
- "name": "face_id",
5947
+ "thread_id": {
5948
+ "description": "Thread ID",
5949
+ "name": "thread_id",
5839
5950
  "required": true
5840
5951
  }
5841
5952
  },
5842
- "description": "Submit a document to a face",
5953
+ "description": "Delete a thread",
5843
5954
  "flags": {
5844
5955
  "json": {
5845
5956
  "description": "Format output as json.",
@@ -5872,50 +5983,16 @@
5872
5983
  "multiple": false,
5873
5984
  "type": "option"
5874
5985
  },
5875
- "label": {
5876
- "description": "Document label/title",
5877
- "name": "label",
5878
- "hasDynamicHelp": false,
5879
- "multiple": false,
5880
- "type": "option"
5881
- },
5882
- "content": {
5883
- "description": "Inline text content",
5884
- "name": "content",
5885
- "hasDynamicHelp": false,
5886
- "multiple": false,
5887
- "type": "option"
5888
- },
5889
- "file": {
5890
- "description": "Read content from file",
5891
- "name": "file",
5892
- "hasDynamicHelp": false,
5893
- "multiple": false,
5894
- "type": "option"
5895
- },
5896
- "medium": {
5897
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5898
- "name": "medium",
5899
- "hasDynamicHelp": false,
5900
- "multiple": false,
5901
- "type": "option"
5902
- },
5903
- "perspective": {
5904
- "description": "Perspective (first-person or third-person)",
5905
- "name": "perspective",
5906
- "default": "first-person",
5907
- "hasDynamicHelp": false,
5908
- "multiple": false,
5909
- "options": [
5910
- "first-person",
5911
- "third-person"
5912
- ],
5913
- "type": "option"
5986
+ "yes": {
5987
+ "description": "Skip confirmation",
5988
+ "name": "yes",
5989
+ "allowNo": false,
5990
+ "type": "boolean"
5914
5991
  }
5915
5992
  },
5916
5993
  "hasDynamicHelp": false,
5917
5994
  "hiddenAliases": [],
5918
- "id": "compile:doc:create",
5995
+ "id": "compile:thread:delete",
5919
5996
  "pluginAlias": "faces-cli",
5920
5997
  "pluginName": "faces-cli",
5921
5998
  "pluginType": "core",
@@ -5926,20 +6003,20 @@
5926
6003
  "dist",
5927
6004
  "commands",
5928
6005
  "compile",
5929
- "doc",
5930
- "create.js"
6006
+ "thread",
6007
+ "delete.js"
5931
6008
  ]
5932
6009
  },
5933
- "compile:doc:delete": {
6010
+ "compile:thread:edit": {
5934
6011
  "aliases": [],
5935
6012
  "args": {
5936
- "doc_id": {
5937
- "description": "Document ID",
5938
- "name": "doc_id",
6013
+ "thread_id": {
6014
+ "description": "Thread ID",
6015
+ "name": "thread_id",
5939
6016
  "required": true
5940
6017
  }
5941
6018
  },
5942
- "description": "Delete a document",
6019
+ "description": "Edit a thread (label and/or reassign face speaker)",
5943
6020
  "flags": {
5944
6021
  "json": {
5945
6022
  "description": "Format output as json.",
@@ -5971,11 +6048,25 @@
5971
6048
  "hasDynamicHelp": false,
5972
6049
  "multiple": false,
5973
6050
  "type": "option"
6051
+ },
6052
+ "label": {
6053
+ "description": "New thread label",
6054
+ "name": "label",
6055
+ "hasDynamicHelp": false,
6056
+ "multiple": false,
6057
+ "type": "option"
6058
+ },
6059
+ "face-speaker": {
6060
+ "description": "Reassign face speaker: set this speaker to role=user, all others to role=assistant",
6061
+ "name": "face-speaker",
6062
+ "hasDynamicHelp": false,
6063
+ "multiple": false,
6064
+ "type": "option"
5974
6065
  }
5975
6066
  },
5976
6067
  "hasDynamicHelp": false,
5977
6068
  "hiddenAliases": [],
5978
- "id": "compile:doc:delete",
6069
+ "id": "compile:thread:edit",
5979
6070
  "pluginAlias": "faces-cli",
5980
6071
  "pluginName": "faces-cli",
5981
6072
  "pluginType": "core",
@@ -5985,21 +6076,21 @@
5985
6076
  "relativePath": [
5986
6077
  "dist",
5987
6078
  "commands",
5988
- "compile",
5989
- "doc",
5990
- "delete.js"
6079
+ "compile",
6080
+ "thread",
6081
+ "edit.js"
5991
6082
  ]
5992
6083
  },
5993
- "compile:doc:edit": {
6084
+ "compile:thread:get": {
5994
6085
  "aliases": [],
5995
6086
  "args": {
5996
- "doc_id": {
5997
- "description": "Document ID",
5998
- "name": "doc_id",
6087
+ "thread_id": {
6088
+ "description": "Thread ID",
6089
+ "name": "thread_id",
5999
6090
  "required": true
6000
6091
  }
6001
6092
  },
6002
- "description": "Edit a document (label, content, or perspective)",
6093
+ "description": "Get a thread by ID",
6003
6094
  "flags": {
6004
6095
  "json": {
6005
6096
  "description": "Format output as json.",
@@ -6031,50 +6122,11 @@
6031
6122
  "hasDynamicHelp": false,
6032
6123
  "multiple": false,
6033
6124
  "type": "option"
6034
- },
6035
- "label": {
6036
- "description": "New label/title",
6037
- "name": "label",
6038
- "hasDynamicHelp": false,
6039
- "multiple": false,
6040
- "type": "option"
6041
- },
6042
- "content": {
6043
- "description": "New inline text content",
6044
- "name": "content",
6045
- "hasDynamicHelp": false,
6046
- "multiple": false,
6047
- "type": "option"
6048
- },
6049
- "file": {
6050
- "description": "Read new content from file",
6051
- "name": "file",
6052
- "hasDynamicHelp": false,
6053
- "multiple": false,
6054
- "type": "option"
6055
- },
6056
- "medium": {
6057
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
6058
- "name": "medium",
6059
- "hasDynamicHelp": false,
6060
- "multiple": false,
6061
- "type": "option"
6062
- },
6063
- "perspective": {
6064
- "description": "Perspective (first-person or third-person)",
6065
- "name": "perspective",
6066
- "hasDynamicHelp": false,
6067
- "multiple": false,
6068
- "options": [
6069
- "first-person",
6070
- "third-person"
6071
- ],
6072
- "type": "option"
6073
6125
  }
6074
6126
  },
6075
6127
  "hasDynamicHelp": false,
6076
6128
  "hiddenAliases": [],
6077
- "id": "compile:doc:edit",
6129
+ "id": "compile:thread:get",
6078
6130
  "pluginAlias": "faces-cli",
6079
6131
  "pluginName": "faces-cli",
6080
6132
  "pluginType": "core",
@@ -6085,20 +6137,20 @@
6085
6137
  "dist",
6086
6138
  "commands",
6087
6139
  "compile",
6088
- "doc",
6089
- "edit.js"
6140
+ "thread",
6141
+ "get.js"
6090
6142
  ]
6091
6143
  },
6092
- "compile:doc:get": {
6144
+ "compile:thread:list": {
6093
6145
  "aliases": [],
6094
6146
  "args": {
6095
- "doc_id": {
6096
- "description": "Document ID",
6097
- "name": "doc_id",
6147
+ "face_id": {
6148
+ "description": "Face alias",
6149
+ "name": "face_id",
6098
6150
  "required": true
6099
6151
  }
6100
6152
  },
6101
- "description": "Get a document by ID",
6153
+ "description": "List threads for a face",
6102
6154
  "flags": {
6103
6155
  "json": {
6104
6156
  "description": "Format output as json.",
@@ -6134,7 +6186,7 @@
6134
6186
  },
6135
6187
  "hasDynamicHelp": false,
6136
6188
  "hiddenAliases": [],
6137
- "id": "compile:doc:get",
6189
+ "id": "compile:thread:list",
6138
6190
  "pluginAlias": "faces-cli",
6139
6191
  "pluginName": "faces-cli",
6140
6192
  "pluginType": "core",
@@ -6145,24 +6197,20 @@
6145
6197
  "dist",
6146
6198
  "commands",
6147
6199
  "compile",
6148
- "doc",
6149
- "get.js"
6200
+ "thread",
6201
+ "list.js"
6150
6202
  ]
6151
6203
  },
6152
- "compile:doc": {
6204
+ "compile:thread:make": {
6153
6205
  "aliases": [],
6154
6206
  "args": {
6155
- "face_id": {
6156
- "description": "Face alias",
6157
- "name": "face_id",
6207
+ "thread_id": {
6208
+ "description": "Thread ID",
6209
+ "name": "thread_id",
6158
6210
  "required": true
6159
6211
  }
6160
6212
  },
6161
- "description": "Compile one or more documents into a face (create make in one step). Repeat --file to submit several documents in a single command; each file becomes its own document rather than being concatenated.",
6162
- "examples": [
6163
- "<%= config.bin %> <%= command.id %> alice --file notes.txt",
6164
- "<%= config.bin %> <%= command.id %> alice --file a.txt --file b.txt --file c.txt --no-wait --json"
6165
- ],
6213
+ "description": "Compile an existing thread (prepare + sync in one step)",
6166
6214
  "flags": {
6167
6215
  "json": {
6168
6216
  "description": "Format output as json.",
@@ -6195,51 +6243,8 @@
6195
6243
  "multiple": false,
6196
6244
  "type": "option"
6197
6245
  },
6198
- "label": {
6199
- "description": "Document label/title (single document only; with several files each is labelled by its filename)",
6200
- "name": "label",
6201
- "hasDynamicHelp": false,
6202
- "multiple": false,
6203
- "type": "option"
6204
- },
6205
- "content": {
6206
- "description": "Inline text content",
6207
- "exclusive": [
6208
- "file"
6209
- ],
6210
- "name": "content",
6211
- "hasDynamicHelp": false,
6212
- "multiple": false,
6213
- "type": "option"
6214
- },
6215
- "file": {
6216
- "description": "Read content from file (repeatable — each file becomes its own document)",
6217
- "name": "file",
6218
- "hasDynamicHelp": false,
6219
- "multiple": true,
6220
- "type": "option"
6221
- },
6222
- "medium": {
6223
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
6224
- "name": "medium",
6225
- "hasDynamicHelp": false,
6226
- "multiple": false,
6227
- "type": "option"
6228
- },
6229
- "perspective": {
6230
- "description": "Perspective",
6231
- "name": "perspective",
6232
- "default": "first-person",
6233
- "hasDynamicHelp": false,
6234
- "multiple": false,
6235
- "options": [
6236
- "first-person",
6237
- "third-person"
6238
- ],
6239
- "type": "option"
6240
- },
6241
6246
  "timeout": {
6242
- "description": "Compile timeout in seconds, per document (default: 600)",
6247
+ "description": "Compile timeout in seconds (default: 600)",
6243
6248
  "name": "timeout",
6244
6249
  "default": 600,
6245
6250
  "hasDynamicHelp": false,
@@ -6247,7 +6252,7 @@
6247
6252
  "type": "option"
6248
6253
  },
6249
6254
  "no-wait": {
6250
- "description": "Create and trigger compilation, then return immediately without polling.",
6255
+ "description": "Return immediately after triggering compilation. Prints the thread ID for manual polling.",
6251
6256
  "name": "no-wait",
6252
6257
  "allowNo": false,
6253
6258
  "type": "boolean"
@@ -6255,7 +6260,7 @@
6255
6260
  },
6256
6261
  "hasDynamicHelp": false,
6257
6262
  "hiddenAliases": [],
6258
- "id": "compile:doc",
6263
+ "id": "compile:thread:make",
6259
6264
  "pluginAlias": "faces-cli",
6260
6265
  "pluginName": "faces-cli",
6261
6266
  "pluginType": "core",
@@ -6266,20 +6271,20 @@
6266
6271
  "dist",
6267
6272
  "commands",
6268
6273
  "compile",
6269
- "doc",
6270
- "index.js"
6274
+ "thread",
6275
+ "make.js"
6271
6276
  ]
6272
6277
  },
6273
- "compile:doc:list": {
6278
+ "compile:thread:message": {
6274
6279
  "aliases": [],
6275
6280
  "args": {
6276
- "face_id": {
6277
- "description": "Face alias",
6278
- "name": "face_id",
6281
+ "thread_id": {
6282
+ "description": "Thread ID",
6283
+ "name": "thread_id",
6279
6284
  "required": true
6280
6285
  }
6281
6286
  },
6282
- "description": "List documents for a face. Each document's full text is omitted unless --verbose, so a face with a real corpus stays readable. For a table of every source, documents and threads together, use face:sources.",
6287
+ "description": "Send a user message to a thread",
6283
6288
  "flags": {
6284
6289
  "json": {
6285
6290
  "description": "Format output as json.",
@@ -6312,16 +6317,25 @@
6312
6317
  "multiple": false,
6313
6318
  "type": "option"
6314
6319
  },
6315
- "verbose": {
6316
- "description": "Include each document's full text",
6317
- "name": "verbose",
6320
+ "message": {
6321
+ "char": "m",
6322
+ "description": "User message to append",
6323
+ "name": "message",
6324
+ "required": true,
6325
+ "hasDynamicHelp": false,
6326
+ "multiple": false,
6327
+ "type": "option"
6328
+ },
6329
+ "oauth-only": {
6330
+ "description": "Prevent fallback to paid system key (use OAuth only)",
6331
+ "name": "oauth-only",
6318
6332
  "allowNo": false,
6319
6333
  "type": "boolean"
6320
6334
  }
6321
6335
  },
6322
6336
  "hasDynamicHelp": false,
6323
6337
  "hiddenAliases": [],
6324
- "id": "compile:doc:list",
6338
+ "id": "compile:thread:message",
6325
6339
  "pluginAlias": "faces-cli",
6326
6340
  "pluginName": "faces-cli",
6327
6341
  "pluginType": "core",
@@ -6332,20 +6346,20 @@
6332
6346
  "dist",
6333
6347
  "commands",
6334
6348
  "compile",
6335
- "doc",
6336
- "list.js"
6349
+ "thread",
6350
+ "message.js"
6337
6351
  ]
6338
6352
  },
6339
- "compile:doc:make": {
6353
+ "compile:thread:pause": {
6340
6354
  "aliases": [],
6341
6355
  "args": {
6342
- "doc_id": {
6343
- "description": "Document ID",
6344
- "name": "doc_id",
6356
+ "thread_id": {
6357
+ "description": "Thread ID",
6358
+ "name": "thread_id",
6345
6359
  "required": true
6346
6360
  }
6347
6361
  },
6348
- "description": "Compile an existing document (prepare + sync in one step)",
6362
+ "description": "Ask a running thread compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
6349
6363
  "flags": {
6350
6364
  "json": {
6351
6365
  "description": "Format output as json.",
@@ -6378,24 +6392,24 @@
6378
6392
  "multiple": false,
6379
6393
  "type": "option"
6380
6394
  },
6395
+ "no-wait": {
6396
+ "description": "Return as soon as the pause is accepted, without waiting for the compile to stop.",
6397
+ "name": "no-wait",
6398
+ "allowNo": false,
6399
+ "type": "boolean"
6400
+ },
6381
6401
  "timeout": {
6382
- "description": "Compile timeout in seconds (default: 600)",
6402
+ "description": "Seconds to wait for the compile to stop (default: 60)",
6383
6403
  "name": "timeout",
6384
- "default": 600,
6404
+ "default": 60,
6385
6405
  "hasDynamicHelp": false,
6386
6406
  "multiple": false,
6387
6407
  "type": "option"
6388
- },
6389
- "no-wait": {
6390
- "description": "Return immediately after triggering compilation. Prints the document ID for manual polling.",
6391
- "name": "no-wait",
6392
- "allowNo": false,
6393
- "type": "boolean"
6394
6408
  }
6395
6409
  },
6396
6410
  "hasDynamicHelp": false,
6397
6411
  "hiddenAliases": [],
6398
- "id": "compile:doc:make",
6412
+ "id": "compile:thread:pause",
6399
6413
  "pluginAlias": "faces-cli",
6400
6414
  "pluginName": "faces-cli",
6401
6415
  "pluginType": "core",
@@ -6406,20 +6420,20 @@
6406
6420
  "dist",
6407
6421
  "commands",
6408
6422
  "compile",
6409
- "doc",
6410
- "make.js"
6423
+ "thread",
6424
+ "pause.js"
6411
6425
  ]
6412
6426
  },
6413
- "compile:doc:pause": {
6427
+ "compile:thread:reset": {
6414
6428
  "aliases": [],
6415
6429
  "args": {
6416
- "doc_id": {
6417
- "description": "Document ID",
6418
- "name": "doc_id",
6430
+ "thread_id": {
6431
+ "description": "Thread ID",
6432
+ "name": "thread_id",
6419
6433
  "required": true
6420
6434
  }
6421
6435
  },
6422
- "description": "Ask a running document compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
6436
+ "description": "Reset thread compilation progress (wipe extraction, keep source messages)",
6423
6437
  "flags": {
6424
6438
  "json": {
6425
6439
  "description": "Format output as json.",
@@ -6452,24 +6466,16 @@
6452
6466
  "multiple": false,
6453
6467
  "type": "option"
6454
6468
  },
6455
- "no-wait": {
6456
- "description": "Return as soon as the pause is accepted, without waiting for the compile to stop.",
6457
- "name": "no-wait",
6469
+ "yes": {
6470
+ "description": "Skip confirmation",
6471
+ "name": "yes",
6458
6472
  "allowNo": false,
6459
6473
  "type": "boolean"
6460
- },
6461
- "timeout": {
6462
- "description": "Seconds to wait for the compile to stop (default: 60)",
6463
- "name": "timeout",
6464
- "default": 60,
6465
- "hasDynamicHelp": false,
6466
- "multiple": false,
6467
- "type": "option"
6468
6474
  }
6469
6475
  },
6470
6476
  "hasDynamicHelp": false,
6471
6477
  "hiddenAliases": [],
6472
- "id": "compile:doc:pause",
6478
+ "id": "compile:thread:reset",
6473
6479
  "pluginAlias": "faces-cli",
6474
6480
  "pluginName": "faces-cli",
6475
6481
  "pluginType": "core",
@@ -6480,20 +6486,20 @@
6480
6486
  "dist",
6481
6487
  "commands",
6482
6488
  "compile",
6483
- "doc",
6484
- "pause.js"
6489
+ "thread",
6490
+ "reset.js"
6485
6491
  ]
6486
6492
  },
6487
- "compile:doc:reset": {
6493
+ "compile:thread:sync": {
6488
6494
  "aliases": [],
6489
6495
  "args": {
6490
- "doc_id": {
6491
- "description": "Document ID",
6492
- "name": "doc_id",
6496
+ "thread_id": {
6497
+ "description": "Thread ID",
6498
+ "name": "thread_id",
6493
6499
  "required": true
6494
6500
  }
6495
6501
  },
6496
- "description": "Reset document compilation progress (wipe extraction, keep content)",
6502
+ "description": "Archive and sync a thread into a face",
6497
6503
  "flags": {
6498
6504
  "json": {
6499
6505
  "description": "Format output as json.",
@@ -6525,17 +6531,11 @@
6525
6531
  "hasDynamicHelp": false,
6526
6532
  "multiple": false,
6527
6533
  "type": "option"
6528
- },
6529
- "yes": {
6530
- "description": "Skip confirmation",
6531
- "name": "yes",
6532
- "allowNo": false,
6533
- "type": "boolean"
6534
6534
  }
6535
6535
  },
6536
6536
  "hasDynamicHelp": false,
6537
6537
  "hiddenAliases": [],
6538
- "id": "compile:doc:reset",
6538
+ "id": "compile:thread:sync",
6539
6539
  "pluginAlias": "faces-cli",
6540
6540
  "pluginName": "faces-cli",
6541
6541
  "pluginType": "core",
@@ -6546,8 +6546,8 @@
6546
6546
  "dist",
6547
6547
  "commands",
6548
6548
  "compile",
6549
- "doc",
6550
- "reset.js"
6549
+ "thread",
6550
+ "sync.js"
6551
6551
  ]
6552
6552
  },
6553
6553
  "face:tag:add": {
@@ -7127,5 +7127,5 @@
7127
7127
  ]
7128
7128
  }
7129
7129
  },
7130
- "version": "1.8.3"
7130
+ "version": "1.8.4"
7131
7131
  }