negotium 0.5.6 → 0.5.8

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.
@@ -85,6 +85,31 @@ function sharedToolsPartial(): string {
85
85
  return _sharedToolsPartial;
86
86
  }
87
87
 
88
+ /** The "Tool notes" bullets that name a capability-gated tool. They used to sit
89
+ * in `_shared-tools.md` unconditionally, so a default-deny room — Telegram,
90
+ * headless, any node turn the caller did not mint the capability for — was told
91
+ * to "use the visual tool below" when no such tool was registered and no such
92
+ * section followed. Rendering them from the same flags that gate the tools
93
+ * keeps the prompt and the tool list from disagreeing.
94
+ *
95
+ * Appended to the end of the preceding line rather than occupying one of its
96
+ * own, so the empty case leaves no blank line in the bullet list. */
97
+ function capabilityToolNotes(opts: { visualTools?: boolean; fileDeliveryTools?: boolean }): string {
98
+ const notes = [
99
+ ...(opts.fileDeliveryTools
100
+ ? [
101
+ "- Sending files: use the file-delivery tool; never emit deprecated `[FILE:/absolute/path]` tags. Prefer ASCII names and richer formats (PDF over plain `.txt`).",
102
+ ]
103
+ : []),
104
+ ...(opts.visualTools
105
+ ? [
106
+ "- Visual output (HTML/CSS, dashboards, charts, tables): use the visual tool below instead of pasting large HTML into chat.",
107
+ ]
108
+ : []),
109
+ ];
110
+ return notes.length ? `\n${notes.join("\n")}` : "";
111
+ }
112
+
88
113
  function topicSystemPromptTemplate(): string {
89
114
  if (_topicSystemPromptTemplate === null) {
90
115
  _topicSystemPromptTemplate = loadSessionPrompt(
@@ -499,6 +524,7 @@ export function createPromptBuilders(host: PromptBuilderHost = {}): PromptBuilde
499
524
  // {{UPLOADS_DIR}}, which the later keys in this same pass then resolve.
500
525
  const templateVars: Record<string, string> = {
501
526
  SHARED_TOOLS: sharedToolsPartial(),
527
+ CAPABILITY_TOOL_NOTES: capabilityToolNotes(opts),
502
528
  AI_LABEL: opts.aiLabel,
503
529
  TOPIC_TITLE: opts.topicTitle,
504
530
  WORKSPACE_CWD: opts.workspaceCwd,
@@ -5,9 +5,7 @@ Working directory "{{WORKSPACE_CWD}}" (put temp files in `tmp/`). Create files h
5
5
  Attachments live under "{{UPLOADS_DIR}}" and persist across turns. You MUST open any file named in an `[Attached file: <name> at path: <absolute path>]` line before answering — images via the View tool (absolute image_path), other files via Read. Never claim a file is missing when such a line is present.
6
6
 
7
7
  ## Tool notes
8
- Use a tool only when it is actually available; otherwise say so instead of pretending.
9
- - Sending files: use the file-delivery tool; never emit deprecated `[FILE:/absolute/path]` tags. Prefer ASCII names and richer formats (PDF over plain `.txt`).
10
- - Visual output (HTML/CSS, dashboards, charts, tables): use the visual tool below instead of pasting large HTML into chat.
8
+ Use a tool only when it is actually available; otherwise say so instead of pretending.{{CAPABILITY_TOOL_NOTES}}
11
9
  - Voice: user voice arrives transcribed; fix misheard proper nouns from context.
12
10
  - Skills: when a task looks unfamiliar, slow, or error-prone, `skill_query` first; save or update a reusable solution with `skill_save`.
13
11
  - Memory: when a Memory section is injected, use it for past context; `wiki_query` for deeper recall.
@@ -658,6 +658,35 @@ export interface AiTurnExecutionOptions {
658
658
  from?: string;
659
659
  }
660
660
 
661
+ /**
662
+ * A turn that came from an adapter states its own capabilities. One that did not
663
+ * — `triggerTopicAiTurn` for tell/ask, cron, subagent reports, and config-change
664
+ * auto-continue — inherits what the room's adapter last granted. Without this a
665
+ * scheduled job or a resumed turn runs in an Otium room with no `show_html`,
666
+ * even though the panel that would render it is right there.
667
+ *
668
+ * Absence, not `false`, is what defers: an adapter that says `false` keeps
669
+ * saying no, so a host that stopped rendering a surface is not overridden by the
670
+ * grant it left behind. A room no adapter has ever granted stays default-deny.
671
+ *
672
+ * Exported so the inheritance can be asserted directly. It is the half of this
673
+ * feature that a storage test cannot reach, and the half that decides whether a
674
+ * cron job in a mapped room can draw anything.
675
+ */
676
+ export function resolveTurnToolCapabilities(
677
+ topicId: string,
678
+ params: { visualTools?: boolean; fileDeliveryTools?: boolean },
679
+ ): { visualTools: boolean; fileDeliveryTools: boolean } {
680
+ const granted =
681
+ params.visualTools === undefined || params.fileDeliveryTools === undefined
682
+ ? getTopicToolCapabilities(topicId)
683
+ : null;
684
+ return {
685
+ visualTools: params.visualTools ?? granted?.visualTools ?? false,
686
+ fileDeliveryTools: params.fileDeliveryTools ?? granted?.fileDeliveryTools ?? false,
687
+ };
688
+ }
689
+
661
690
  export interface StartAiTurnParams extends AiTurnExecutionOptions {
662
691
  topic: AiTurnTopic;
663
692
  userId: string;
@@ -959,19 +988,7 @@ export function startAiTurn(params: StartAiTurnParams): string | null {
959
988
  const cwd = params.cwd;
960
989
  const sessionName = params.sessionName ?? topic.title;
961
990
  const sessionType = params.sessionType;
962
- // A turn that came from an adapter states its own capabilities. One that did
963
- // not — `triggerTopicAiTurn` for tell/ask, cron, subagent reports, and
964
- // config-change auto-continue — inherits what the room's adapter last
965
- // granted. Without this a scheduled job or a resumed turn runs in an Otium
966
- // room with no `show_html`, even though the panel that would render it is
967
- // right there. Absence, not `false`, is what defers: an adapter that says
968
- // `false` keeps saying no.
969
- const grantedForTopic =
970
- params.visualTools === undefined || params.fileDeliveryTools === undefined
971
- ? getTopicToolCapabilities(topicId)
972
- : null;
973
- const visualTools = params.visualTools ?? grantedForTopic?.visualTools ?? false;
974
- const fileDeliveryTools = params.fileDeliveryTools ?? grantedForTopic?.fileDeliveryTools ?? false;
991
+ const { visualTools, fileDeliveryTools } = resolveTurnToolCapabilities(topicId, params);
975
992
  const onSessionId = params.onSessionId;
976
993
  const onSessionReset = params.onSessionReset;
977
994
  const bridgeSessionFromHistory = params.bridgeSessionFromHistory === true;
@@ -1 +1 @@
1
- export const NEGOTIUM_VERSION = "0.5.6";
1
+ export const NEGOTIUM_VERSION = "0.5.8";
@@ -149,6 +149,28 @@ export interface AiTurnExecutionOptions {
149
149
  /** Internal source marker, e.g. FROM_AUTO_CONTINUE for config-change resumes. */
150
150
  from?: string;
151
151
  }
152
+ /**
153
+ * A turn that came from an adapter states its own capabilities. One that did not
154
+ * — `triggerTopicAiTurn` for tell/ask, cron, subagent reports, and config-change
155
+ * auto-continue — inherits what the room's adapter last granted. Without this a
156
+ * scheduled job or a resumed turn runs in an Otium room with no `show_html`,
157
+ * even though the panel that would render it is right there.
158
+ *
159
+ * Absence, not `false`, is what defers: an adapter that says `false` keeps
160
+ * saying no, so a host that stopped rendering a surface is not overridden by the
161
+ * grant it left behind. A room no adapter has ever granted stays default-deny.
162
+ *
163
+ * Exported so the inheritance can be asserted directly. It is the half of this
164
+ * feature that a storage test cannot reach, and the half that decides whether a
165
+ * cron job in a mapped room can draw anything.
166
+ */
167
+ export declare function resolveTurnToolCapabilities(topicId: string, params: {
168
+ visualTools?: boolean;
169
+ fileDeliveryTools?: boolean;
170
+ }): {
171
+ visualTools: boolean;
172
+ fileDeliveryTools: boolean;
173
+ };
152
174
  export interface StartAiTurnParams extends AiTurnExecutionOptions {
153
175
  topic: AiTurnTopic;
154
176
  userId: string;
@@ -1 +1 @@
1
- export declare const NEGOTIUM_VERSION = "0.5.6";
1
+ export declare const NEGOTIUM_VERSION = "0.5.8";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "negotium",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "type": "module",
5
5
  "description": "Install the Negotium multi-agent runtime and CLI with one package",
6
6
  "license": "Apache-2.0",