@loomweaver/cli 0.11.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.mjs +64 -11
  2. package/package.json +1 -1
package/dist/main.mjs CHANGED
@@ -837,7 +837,7 @@ function pause(): Promise<void> {
837
837
  }
838
838
 
839
839
  // ../devkit/src/recipes/angular-weaver/agent-files.ts
840
- var AG_UI_ADAPTER_VERSION = "0.11.0";
840
+ var AG_UI_ADAPTER_VERSION = "0.12.1";
841
841
  var AG_UI_PROTOCOL_VERSION = "0.0.x";
842
842
  function connectionFile(w) {
843
843
  return `import { signal } from '@angular/core';
@@ -849,11 +849,6 @@ import {
849
849
  } from '@loomweaver/ag-ui';
850
850
  import type { PluginContext } from '@loomweaver/plugin-sdk';
851
851
 
852
- // Commands an agent may not run on its own word. Each one asks the person at the keyboard first, and
853
- // declining stops it: the workbench never sees the call. This weaver's own command is listed as an
854
- // example \u2014 replace it with the ones that actually cost something.
855
- const CONSEQUENTIAL = new Set(['${w.id}.hello']);
856
-
857
852
  // A factory, not a module-level connection: everything a run needs lives in the closure, so a second
858
853
  // one never shares state with the first.
859
854
  export function ${w.propertyName}Connection(ctx: PluginContext): CommandTools {
@@ -864,11 +859,21 @@ export function ${w.propertyName}Connection(ctx: PluginContext): CommandTools {
864
859
  // deactivate(), so the panel renders an honest empty state either side of that.
865
860
  export const ${w.propertyName}Agent = signal<CommandTools | null>(null);
866
861
 
862
+ // What an agent's word is enough for is the command's own statement, declared where the command is
863
+ // registered and read off the call here. No list of ids lives beside the commands: a list drifts from
864
+ // what it describes, and it cannot speak for a command another plugin registered. Acting on the
865
+ // statement is this weaver's half: the workbench states it and enforces nothing.
867
866
  async function decide(
868
867
  ctx: PluginContext,
869
868
  call: PendingToolCall,
870
869
  ): Promise<ToolDecision> {
871
- if (!CONSEQUENTIAL.has(call.commandId)) {
870
+ if (call.agentConsent === 'never') {
871
+ return {
872
+ decision: 'decline',
873
+ reason: 'an agent may not run this one on its own word.',
874
+ };
875
+ }
876
+ if (call.agentConsent !== 'ask' && call.agentConsent !== 'ask-always') {
872
877
  return { decision: 'run' };
873
878
  }
874
879
  const yes = await ctx.ui.confirm({
@@ -899,7 +904,8 @@ interface Asked {
899
904
  function contextThat(confirms: boolean, ran: Asked[]): PluginContext {
900
905
  return {
901
906
  invocableCommands: () => [
902
- { id: '${w.id}.hello', title: '${w.name} action', description: 'Shows a short message.' },
907
+ // agentConsent travels with the command, which is what the connection reads off the call.
908
+ { id: '${w.id}.hello', title: '${w.name} action', description: 'Shows a short message.', agentConsent: 'ask' },
903
909
  ],
904
910
  invokeCommand: (id: string, args?: CommandArguments) => {
905
911
  ran.push({ id, args });
@@ -1185,6 +1191,11 @@ function commandBlock(w) {
1185
1191
  ` answers: '${w.id}.actionAnswers',`,
1186
1192
  ` shortcut: '${w.features.shortcut}',`,
1187
1193
  " callable: true,",
1194
+ ...w.features.agent ? [
1195
+ " // What an agent's word is enough for. The platform states it and enforces nothing:",
1196
+ " // the asking is the connection's half, which reads this off the call.",
1197
+ " agentConsent: 'ask',"
1198
+ ] : [],
1188
1199
  " run: (_context, args) => {",
1189
1200
  " const tone = toneOf(args?.['tone']);",
1190
1201
  ` ctx.ui.toast({ message: '${w.id}.action', kind: tone });`,
@@ -1832,7 +1843,7 @@ var framePlugin = {
1832
1843
  };
1833
1844
 
1834
1845
  // ../devkit/src/recipes/platform-version.ts
1835
- var PLATFORM_VERSION = "0.11.0";
1846
+ var PLATFORM_VERSION = "0.12.1";
1836
1847
 
1837
1848
  // ../devkit/src/recipes/angular-distribution/amendments.ts
1838
1849
  var DISTRIBUTION_INITIAL_BUDGET = {
@@ -2091,6 +2102,10 @@ function readme2(d) {
2091
2102
  "",
2092
2103
  "A switch takes the **affordance and the gesture**: turning `splitRight` off removes the toolbar",
2093
2104
  "button, the drop edges *and* `mod+\\`, so the capability cannot come back through a second door.",
2105
+ "Two switches are finer, and named for it: `splitRightButton` and `splitDownButton` leave out the",
2106
+ "pane toolbar's split button alone, for a product that offers splitting by dragging a tab to a",
2107
+ "pane's edge. The command and the tab menu's entry are removed by naming them in",
2108
+ "`provideShell({ omit })` instead, so each decision keeps one place.",
2094
2109
  "Fields merge group by group, so name only what you turn off. The groups are `content`,",
2095
2110
  "`sidebar`, `rail`, `workspaces`, `windows` and `commands`; everything is on by default except",
2096
2111
  "`content.escalate`, the unlabelled double-click cycle on a tab.",
@@ -3586,6 +3601,7 @@ function read(ts, file, call) {
3586
3601
  return { ...empty, unreadable: "its id is not a string literal" };
3587
3602
  }
3588
3603
  const callable = properties.get("callable");
3604
+ const consent = properties.get("agentConsent");
3589
3605
  return {
3590
3606
  at: at2,
3591
3607
  id: id.text,
@@ -3593,9 +3609,40 @@ function read(ts, file, call) {
3593
3609
  described: properties.has("description"),
3594
3610
  answers: properties.has("answers"),
3595
3611
  returnsValue: returnsValue(ts, properties.get("run")),
3596
- arguments: readArguments(ts, properties.get("arguments"))
3612
+ arguments: readArguments(ts, properties.get("arguments")),
3613
+ ...consentOf(ts, consent)
3597
3614
  };
3598
3615
  }
3616
+ function consentOf(ts, declared) {
3617
+ const value = unwrapped(ts, declared);
3618
+ return value && ts.isStringLiteral(value) ? { agentConsent: value.text } : {};
3619
+ }
3620
+ function unwrapped(ts, value) {
3621
+ if (!value) {
3622
+ return void 0;
3623
+ }
3624
+ return ts.isAsExpression(value) || ts.isSatisfiesExpression(value) || ts.isParenthesizedExpression(value) ? unwrapped(ts, value.expression) : value;
3625
+ }
3626
+ var STATED = ["allow", "ask", "ask-always", "never"];
3627
+ function consentLine(consent) {
3628
+ switch (consent) {
3629
+ case "allow": {
3630
+ return "says an agent's word is enough to run it.";
3631
+ }
3632
+ case "ask": {
3633
+ return "says the person is asked first; whoever runs it on an agent's behalf does the asking.";
3634
+ }
3635
+ case "ask-always": {
3636
+ return "says the person is asked every time; whoever runs it on an agent's behalf does the asking.";
3637
+ }
3638
+ case "never": {
3639
+ return "says it is not to be run on an agent's word; closing it to other callers is what enforces that.";
3640
+ }
3641
+ default: {
3642
+ return consent === void 0 ? "says nothing about whether an agent's word is enough to run it." : `declares "${consent}" about an agent's word, which is none of ${STATED.join(", ")}, so nothing reads it.`;
3643
+ }
3644
+ }
3645
+ }
3599
3646
  function readArguments(ts, value) {
3600
3647
  if (!value || !ts.isArrayLiteralExpression(value)) {
3601
3648
  return [];
@@ -3699,6 +3746,12 @@ function judge(registration) {
3699
3746
  message: `${id}: offered to an agent, with ${count} described argument${count === 1 ? "" : "s"}${registration.answers ? " and a declared answer" : ""}.`
3700
3747
  });
3701
3748
  }
3749
+ findings.push({
3750
+ level: "info",
3751
+ code: "command.consent",
3752
+ path: at2,
3753
+ message: `${id}: ${consentLine(registration.agentConsent)}`
3754
+ });
3702
3755
  return findings;
3703
3756
  }
3704
3757
 
@@ -4733,7 +4786,7 @@ function replaceSymlinkEntry(absolute) {
4733
4786
  }
4734
4787
 
4735
4788
  // src/lib/run.ts
4736
- var VERSION = "0.11.0";
4789
+ var VERSION = "0.12.1";
4737
4790
  function help() {
4738
4791
  const commands = SCAFFOLDS.map((s) => ` ${s.name.padEnd(16)}${s.summary}`);
4739
4792
  return [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loomweaver/cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "LoomWeaver: open-source plugin platform for Angular workbenches. The scaffolding CLI: generates weavers, distributions and integrations into any project, with no Nx workspace and no checkout required.",
5
5
  "keywords": [
6
6
  "loomweaver",