@soku-ai/cli 0.1.0-alpha.18 → 0.1.0-alpha.19

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.
Files changed (37) hide show
  1. package/README.md +33 -22
  2. package/dist/commands/brand-skill.d.ts +23 -0
  3. package/dist/commands/brand-skill.d.ts.map +1 -1
  4. package/dist/commands/brand-skill.js +82 -0
  5. package/dist/commands/brand-skill.js.map +1 -1
  6. package/dist/commands/egress.d.ts.map +1 -1
  7. package/dist/commands/egress.js +66 -1
  8. package/dist/commands/egress.js.map +1 -1
  9. package/dist/commands/generated.d.ts +8 -3
  10. package/dist/commands/generated.d.ts.map +1 -1
  11. package/dist/commands/generated.js +10 -3
  12. package/dist/commands/generated.js.map +1 -1
  13. package/dist/commands/live-surface.d.ts +15 -0
  14. package/dist/commands/live-surface.d.ts.map +1 -0
  15. package/dist/commands/live-surface.js +96 -0
  16. package/dist/commands/live-surface.js.map +1 -0
  17. package/dist/generated/capabilities.json +3535 -774
  18. package/dist/generated/changelog.json +784 -0
  19. package/dist/http/client.d.ts +2 -1
  20. package/dist/http/client.d.ts.map +1 -1
  21. package/dist/http/client.js +14 -5
  22. package/dist/http/client.js.map +1 -1
  23. package/dist/index.js +2 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/output/envelope.d.ts +2 -1
  26. package/dist/output/envelope.d.ts.map +1 -1
  27. package/dist/output/envelope.js +2 -2
  28. package/dist/output/envelope.js.map +1 -1
  29. package/dist/version.d.ts +1 -1
  30. package/dist/version.js +1 -1
  31. package/package.json +4 -3
  32. package/skills/soku/SKILL.md +61 -14
  33. package/skills/soku/agents/openai.yaml +4 -0
  34. package/skills/soku/references/ads-write.md +12 -6
  35. package/skills/soku/references/data-capabilities.md +22 -1
  36. package/skills/soku/references/egress-security.md +19 -0
  37. package/skills/soku/references/skills-updates.md +34 -3
@@ -0,0 +1,96 @@
1
+ /** `soku live open | list | revoke | rotate-credential`
2
+ *
3
+ * A live surface is a link you hand to a person. They open it in their own
4
+ * browser and watch the resource change as you work on it, edit it themselves,
5
+ * and clear the writes that need a human.
6
+ *
7
+ * The approval credential is printed once, by `open` and `rotate-credential`,
8
+ * and never appears in the URL. That separation is the whole point: a link
9
+ * travels — forwarded, pasted, screenshotted — and a credential travelling with
10
+ * it would prove nothing while looking like proof. What gets recorded as
11
+ * "who approved this" depends on it.
12
+ */
13
+ import { apiRequest } from '../http/client.js';
14
+ import { bold, dim, emitSuccess, table } from '../output/envelope.js';
15
+ export function registerLiveSurfaceCommands(program) {
16
+ // `live`, not `live-surfaces`. The page a person opens is at `/live/<handle>`,
17
+ // so that is the word they already have for this; `live-surfaces` is the
18
+ // internal table's name leaking onto the command line. The server route
19
+ // stays `/api/cli/live-surfaces` — it is deployed, and nothing is served by
20
+ // renaming a path nobody types.
21
+ const surfaces = program
22
+ .command('live')
23
+ .description('Hand someone a live link to a canvas you are working on');
24
+ surfaces
25
+ .command('open <resource-id>')
26
+ .description('Open a link for a resource and print it with its approval code')
27
+ .option('--type <type>', "Resource kind (default: 'remix_project')", 'remix_project')
28
+ .option('--read-only', 'Let them watch but not edit')
29
+ .option('--no-approvals', 'Do not issue an approval code for this link')
30
+ .option('--ttl-hours <hours>', 'How long the link stays usable (default 12, max 168)')
31
+ .action(async (resourceId, opts) => {
32
+ const data = await apiRequest('/api/cli/live-surfaces', {
33
+ method: 'POST',
34
+ workspace: true,
35
+ body: {
36
+ resource_type: opts.type,
37
+ resource_id: resourceId,
38
+ writable: !opts.readOnly,
39
+ approvable: opts.approvals,
40
+ ...(opts.ttlHours ? { ttl_hours: Number(opts.ttlHours) } : {}),
41
+ },
42
+ });
43
+ emitSuccess(data, (d) => {
44
+ const lines = [bold('Link ') + d.url];
45
+ if (d.expiresAt)
46
+ lines.push(dim('Expires ') + d.expiresAt);
47
+ if (d.approvalCredential) {
48
+ lines.push('');
49
+ lines.push(bold('Approval code ') + d.approvalCredential);
50
+ // Printed on its own line, away from the URL, because the two must
51
+ // reach the person by different routes.
52
+ lines.push(dim(d.approvalCredentialNote ?? 'Give this to the person, not the link.'));
53
+ }
54
+ return lines.join('\n');
55
+ });
56
+ });
57
+ surfaces
58
+ .command('list <resource-id>')
59
+ .description('Links still open on a resource, so you do not hand out a second one')
60
+ .option('--type <type>', "Resource kind (default: 'remix_project')", 'remix_project')
61
+ .action(async (resourceId, opts) => {
62
+ const query = `?resource_id=${encodeURIComponent(resourceId)}&resource_type=${encodeURIComponent(opts.type)}`;
63
+ const data = await apiRequest(`/api/cli/live-surfaces${query}`, { workspace: true });
64
+ emitSuccess(data, (d) => table(d.surfaces.map((s) => ({
65
+ url: s.url,
66
+ can: s.capabilities.join(','),
67
+ origin: s.origin,
68
+ expires: s.expiresAt ?? '',
69
+ })), [
70
+ { key: 'url', header: 'URL' },
71
+ { key: 'can', header: 'CAN' },
72
+ { key: 'origin', header: 'OPENED BY' },
73
+ { key: 'expires', header: 'EXPIRES' },
74
+ ]));
75
+ });
76
+ surfaces
77
+ .command('revoke <handle>')
78
+ .description('Kill a link. Anyone still holding it loses access immediately')
79
+ .action(async (handle) => {
80
+ emitSuccess(await apiRequest(`/api/cli/live-surfaces/${encodeURIComponent(handle)}`, {
81
+ method: 'DELETE',
82
+ workspace: true,
83
+ }), () => 'Revoked.');
84
+ });
85
+ surfaces
86
+ .command('rotate-credential <handle>')
87
+ .description('Issue a fresh approval code, leaving the link itself alive')
88
+ .action(async (handle) => {
89
+ const data = await apiRequest(`/api/cli/live-surfaces/${encodeURIComponent(handle)}/approval-credential`, { method: 'POST', workspace: true });
90
+ // Rotating is for a code that reached the wrong person. Killing the link
91
+ // as well would cost the right person their work surface for someone
92
+ // else's mistake, so the two are separate commands.
93
+ emitSuccess(data, (d) => bold('New approval code ') + d.approvalCredential);
94
+ });
95
+ }
96
+ //# sourceMappingURL=live-surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-surface.js","sourceRoot":"","sources":["../../src/commands/live-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAiBrE,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC1D,+EAA+E;IAC/E,yEAAyE;IACzE,wEAAwE;IACxE,4EAA4E;IAC5E,gCAAgC;IAChC,MAAM,QAAQ,GAAG,OAAO;SACrB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,yDAAyD,CAAC,CAAA;IAEzE,QAAQ;SACL,OAAO,CAAC,oBAAoB,CAAC;SAC7B,WAAW,CAAC,gEAAgE,CAAC;SAC7E,MAAM,CAAC,eAAe,EAAE,0CAA0C,EAAE,eAAe,CAAC;SACpF,MAAM,CAAC,aAAa,EAAE,6BAA6B,CAAC;SACpD,MAAM,CAAC,gBAAgB,EAAE,6CAA6C,CAAC;SACvE,MAAM,CAAC,qBAAqB,EAAE,sDAAsD,CAAC;SACrF,MAAM,CACL,KAAK,EACH,UAAkB,EAClB,IAAiF,EACjF,EAAE;QACF,MAAM,IAAI,GAAG,MAAM,UAAU,CAAgB,wBAAwB,EAAE;YACrE,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI;YACf,IAAI,EAAE;gBACJ,aAAa,EAAE,IAAI,CAAC,IAAI;gBACxB,WAAW,EAAE,UAAU;gBACvB,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ;gBACxB,UAAU,EAAE,IAAI,CAAC,SAAS;gBAC1B,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/D;SACF,CAAC,CAAA;QACF,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;YACtB,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YACtC,IAAI,CAAC,CAAC,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAA;YAC1D,IAAI,CAAC,CAAC,kBAAkB,EAAE,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACd,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,CAAA;gBAC1D,mEAAmE;gBACnE,wCAAwC;gBACxC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,sBAAsB,IAAI,wCAAwC,CAAC,CAAC,CAAA;YACvF,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC,CAAC,CAAA;IACJ,CAAC,CACF,CAAA;IAEH,QAAQ;SACL,OAAO,CAAC,oBAAoB,CAAC;SAC7B,WAAW,CAAC,qEAAqE,CAAC;SAClF,MAAM,CAAC,eAAe,EAAE,0CAA0C,EAAE,eAAe,CAAC;SACpF,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,IAAsB,EAAE,EAAE;QAC3D,MAAM,KAAK,GAAG,gBAAgB,kBAAkB,CAAC,UAAU,CAAC,kBAAkB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;QAC7G,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,yBAAyB,KAAK,EAAE,EAChC,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAA;QACD,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACtB,KAAK,CACH,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;YAC7B,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,OAAO,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE;SAC3B,CAAC,CAAC,EACH;YACE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;YAC7B,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;YAC7B,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE;YACtC,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE;SACtC,CACF,CACF,CAAA;IACH,CAAC,CAAC,CAAA;IAEJ,QAAQ;SACL,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,+DAA+D,CAAC;SAC5E,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;QAC/B,WAAW,CACT,MAAM,UAAU,CAAC,0BAA0B,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE;YACvE,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,IAAI;SAChB,CAAC,EACF,GAAG,EAAE,CAAC,UAAU,CACjB,CAAA;IACH,CAAC,CAAC,CAAA;IAEJ,QAAQ;SACL,OAAO,CAAC,4BAA4B,CAAC;SACrC,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,0BAA0B,kBAAkB,CAAC,MAAM,CAAC,sBAAsB,EAC1E,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CACpC,CAAA;QACD,yEAAyE;QACzE,qEAAqE;QACrE,oDAAoD;QACpD,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,CAAA;IAC9E,CAAC,CAAC,CAAA;AACN,CAAC"}