taias 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -128,59 +128,10 @@ const affordances = await taias.resolve({ toolName: "scan_repo" });
128
128
  - `ctx.toolName` - The name of the tool being called
129
129
 
130
130
  **Returns:** `Affordances | null`
131
- - Returns `{ advice: string }` with auto-generated advice if a matching step is found
131
+ - Returns an `Affordances` object with `advice` (and more) if a matching step is found
132
132
  - Returns `null` if no step matches or handler returns null
133
133
 
134
- ## Types
135
-
136
- <details>
137
- <summary>View all types</summary>
138
-
139
- ```ts
140
- type TaiasContext = {
141
- toolName: string;
142
- };
143
-
144
- type StepDecision = {
145
- nextTool: string;
146
- };
147
-
148
- type Affordances = {
149
- advice: string;
150
- };
151
-
152
- type StepHandler = (
153
- ctx: TaiasContext
154
- ) => StepDecision | null | Promise<StepDecision | null>;
155
-
156
- type FlowStep = {
157
- toolName: string;
158
- handler: StepHandler;
159
- };
160
-
161
- type FlowDefinition = {
162
- id: string;
163
- steps: Array<FlowStep>;
164
- };
165
-
166
- interface FlowBuilder {
167
- step(toolName: string, handler: StepHandler): void;
168
- }
169
-
170
- type TaiasOptions = {
171
- flow: FlowDefinition;
172
- devMode?: boolean;
173
- onMissingStep?: (ctx: TaiasContext) => void;
174
- };
175
-
176
- interface Taias {
177
- resolve(ctx: TaiasContext): Affordances | null | Promise<Affordances | null>;
178
- }
179
- ```
180
-
181
- </details>
182
-
183
- See the [full documentation](https://taias.xyz/docs) for more details.
134
+ See the [full documentation](https://taias.xyz/docs) for complete API reference and types.
184
135
 
185
136
  ## Dev Mode
186
137
 
@@ -191,7 +142,7 @@ When `devMode: true`, Taias performs additional validation:
191
142
 
192
143
  1. **Duplicate toolName detection** — Throws an error if a flow defines the same tool name twice:
193
144
  ```
194
- Taias: Duplicate step for tool 'scan_repo' in flow 'onboard_repo'. V1 supports one handler per tool.
145
+ Taias: Duplicate step for tool 'scan_repo' in flow 'onboard_repo'. Only one handler per tool is supported.
195
146
  ```
196
147
 
197
148
  2. **Empty nextTool warning** — Logs a warning if a handler returns empty nextTool:
package/dist/index.cjs CHANGED
@@ -21,7 +21,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  createTaias: () => createTaias,
24
- defineFlow: () => defineFlow
24
+ defineAffordances: () => defineAffordances,
25
+ defineFlow: () => defineFlow,
26
+ mergeAffordances: () => mergeAffordances
25
27
  });
26
28
  module.exports = __toCommonJS(index_exports);
27
29
 
@@ -40,51 +42,160 @@ function defineFlow(flowId, builder) {
40
42
  };
41
43
  }
42
44
 
45
+ // src/uiAffordances/types.ts
46
+ function normalizeBinding(input) {
47
+ if ("toolName" in input) return { key: "nextTool", value: input.toolName };
48
+ return { key: input.key, value: input.value };
49
+ }
50
+ function makeBindingKey(slot, binding) {
51
+ return `${slot}::${binding.key}::${binding.value}`;
52
+ }
53
+
54
+ // src/uiAffordances/indexing.ts
55
+ function buildRegistryIndex(registry) {
56
+ const byBindingKey = /* @__PURE__ */ new Map();
57
+ if (!registry) return { byBindingKey };
58
+ for (const h of registry.handles) {
59
+ byBindingKey.set(makeBindingKey(h.slot, h.bindsTo), h);
60
+ }
61
+ return { byBindingKey };
62
+ }
63
+
64
+ // src/uiAffordances/select.ts
65
+ var DEFAULT_SLOT_MATCH = {
66
+ primaryCta: "nextTool",
67
+ secondaryCta: "nextTool",
68
+ widgetVariant: "nextTool"
69
+ };
70
+ function selectUiAffordances(decision, index, opts = {}) {
71
+ const slotMatch = { ...DEFAULT_SLOT_MATCH, ...opts.slotMatch ?? {} };
72
+ const devMode = !!opts.devMode;
73
+ const warn = opts.onWarn ?? (() => {
74
+ });
75
+ const selections = {};
76
+ const slots = Object.keys(DEFAULT_SLOT_MATCH);
77
+ for (const slot of slots) {
78
+ const field = slotMatch[slot];
79
+ const value = decision[field];
80
+ if (!value) continue;
81
+ const k = makeBindingKey(slot, { key: field, value });
82
+ const handle = index.byBindingKey.get(k);
83
+ if (!handle) {
84
+ if (devMode) warn(`[Taias] No affordance for slot "${slot}" when ${field}="${value}"`);
85
+ continue;
86
+ }
87
+ selections[slot] = { handleId: handle.handleId, bindsTo: handle.bindsTo };
88
+ }
89
+ return selections;
90
+ }
91
+
43
92
  // src/createTaias.ts
44
93
  function generateAdvice(nextTool) {
45
94
  return `FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE ${nextTool} TOOL NEXT!!!!!`;
46
95
  }
47
96
  function createTaias(options) {
48
- const { flow, devMode = false, onMissingStep } = options;
97
+ const {
98
+ flow,
99
+ affordances,
100
+ slotMatch,
101
+ devMode = false,
102
+ onMissingStep,
103
+ onWarn
104
+ } = options;
105
+ const warn = onWarn ?? ((msg) => console.warn(msg));
49
106
  if (devMode) {
50
107
  const seenTools = /* @__PURE__ */ new Set();
51
108
  for (const step of flow.steps) {
52
109
  if (seenTools.has(step.toolName)) {
53
110
  throw new Error(
54
- `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. V1 supports one handler per tool.`
111
+ `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. Only one handler per tool is supported.`
55
112
  );
56
113
  }
57
114
  seenTools.add(step.toolName);
58
115
  }
59
116
  }
60
- const stepMap = new Map(
61
- flow.steps.map((step) => [step.toolName, step.handler])
62
- );
117
+ const stepMap = new Map(flow.steps.map((step) => [step.toolName, step.handler]));
118
+ const registryIndex = buildRegistryIndex(affordances);
63
119
  return {
64
120
  async resolve(ctx) {
65
121
  const handler = stepMap.get(ctx.toolName);
66
122
  if (!handler) {
67
- if (onMissingStep) {
68
- onMissingStep(ctx);
69
- }
123
+ onMissingStep?.(ctx);
70
124
  return null;
71
125
  }
72
126
  const result = await handler(ctx);
73
- if (!result) {
74
- return null;
75
- }
127
+ if (!result) return null;
76
128
  if (devMode && result.nextTool === "") {
77
- console.warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);
129
+ warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);
78
130
  }
131
+ const decision = {
132
+ nextTool: result.nextTool
133
+ };
134
+ const selections = selectUiAffordances(decision, registryIndex, {
135
+ devMode,
136
+ onWarn: warn,
137
+ slotMatch
138
+ });
79
139
  return {
80
- advice: generateAdvice(result.nextTool)
140
+ advice: generateAdvice(result.nextTool),
141
+ decision,
142
+ selections
81
143
  };
82
144
  }
83
145
  };
84
146
  }
147
+
148
+ // src/uiAffordances/defineAffordances.ts
149
+ function defineAffordances(builder) {
150
+ const handles = [];
151
+ const push = (slot, handleId, bindsTo) => {
152
+ handles.push({
153
+ slot,
154
+ handleId,
155
+ bindsTo: normalizeBinding(bindsTo)
156
+ });
157
+ };
158
+ const registrar = {
159
+ primaryCta: (handleId, bindsTo) => push("primaryCta", handleId, bindsTo),
160
+ secondaryCta: (handleId, bindsTo) => push("secondaryCta", handleId, bindsTo),
161
+ widgetVariant: (handleId, bindsTo) => push("widgetVariant", handleId, bindsTo)
162
+ };
163
+ builder(registrar);
164
+ return { handles };
165
+ }
166
+
167
+ // src/uiAffordances/mergeAffordances.ts
168
+ function mergeAffordances(registries, opts = {}) {
169
+ const devMode = !!opts.devMode;
170
+ const warn = opts.onWarn ?? (() => {
171
+ });
172
+ const merged = { handles: registries.flatMap((r) => r.handles) };
173
+ if (!devMode) return merged;
174
+ const seenHandleIds = /* @__PURE__ */ new Set();
175
+ for (const h of merged.handles) {
176
+ if (seenHandleIds.has(h.handleId)) {
177
+ throw new Error(`[Taias] Duplicate handleId "${h.handleId}"`);
178
+ }
179
+ seenHandleIds.add(h.handleId);
180
+ }
181
+ const seenTriples = /* @__PURE__ */ new Set();
182
+ for (const h of merged.handles) {
183
+ const k = makeBindingKey(h.slot, h.bindsTo);
184
+ if (seenTriples.has(k)) {
185
+ throw new Error(
186
+ `[Taias] Ambiguous affordance: slot "${h.slot}" has multiple handles bound to (${h.bindsTo.key}="${h.bindsTo.value}")`
187
+ );
188
+ }
189
+ seenTriples.add(k);
190
+ }
191
+ warn(`[Taias] Loaded ${merged.handles.length} UI affordance handles`);
192
+ return merged;
193
+ }
85
194
  // Annotate the CommonJS export names for ESM import in node:
86
195
  0 && (module.exports = {
87
196
  createTaias,
88
- defineFlow
197
+ defineAffordances,
198
+ defineFlow,
199
+ mergeAffordances
89
200
  });
90
201
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/flow.ts","../src/createTaias.ts"],"sourcesContent":["// Main exports\nexport { defineFlow } from \"./flow\";\nexport { createTaias } from \"./createTaias\";\n\n// Type exports\nexport type {\n TaiasContext,\n StepDecision,\n Affordances,\n StepHandler,\n FlowStep,\n FlowDefinition,\n FlowBuilder,\n TaiasOptions,\n Taias,\n} from \"./types\";\n","import type { FlowBuilder, FlowDefinition, FlowStep, StepHandler } from \"./types\";\n\n/**\n * Define a flow with its steps.\n *\n * @param flowId - Unique identifier for the flow\n * @param builder - Callback that receives a FlowBuilder to define steps\n * @returns A FlowDefinition object\n *\n * @example\n * ```ts\n * const onboardRepoFlow = defineFlow(\"onboard_repo\", (flow) => {\n * flow.step(\"scan_repo\", (ctx) => ({\n * nextTool: \"configure_app\",\n * }));\n * });\n * ```\n */\nexport function defineFlow(\n flowId: string,\n builder: (flow: FlowBuilder) => void\n): FlowDefinition {\n const steps: FlowStep[] = [];\n\n const flowBuilder: FlowBuilder = {\n step(toolName: string, handler: StepHandler): void {\n steps.push({ toolName, handler });\n },\n };\n\n builder(flowBuilder);\n\n return {\n id: flowId,\n steps,\n };\n}\n\n","import type { Affordances, Taias, TaiasContext, TaiasOptions } from \"./types\";\n\n/**\n * Generate advice text for a given next tool.\n */\nfunction generateAdvice(nextTool: string): string {\n return `FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE ${nextTool} TOOL NEXT!!!!!`;\n}\n\n/**\n * Create a Taias instance from a single flow.\n *\n * @param options - Configuration options\n * @returns A Taias instance with a resolve method\n *\n * @example\n * ```ts\n * const taias = createTaias({\n * flow: onboardRepoFlow,\n * devMode: process.env.NODE_ENV !== \"production\",\n * });\n *\n * const decision = await taias.resolve({ toolName: \"scan_repo\" });\n * // decision.advice → \"FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE configure_app TOOL NEXT!!!!!\"\n * ```\n */\nexport function createTaias(options: TaiasOptions): Taias {\n const { flow, devMode = false, onMissingStep } = options;\n\n // Dev mode: Check for duplicate toolNames\n if (devMode) {\n const seenTools = new Set<string>();\n for (const step of flow.steps) {\n if (seenTools.has(step.toolName)) {\n throw new Error(\n `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. V1 supports one handler per tool.`\n );\n }\n seenTools.add(step.toolName);\n }\n }\n\n // Build a lookup map for efficient resolution\n const stepMap = new Map(\n flow.steps.map((step) => [step.toolName, step.handler])\n );\n\n return {\n async resolve(ctx: TaiasContext): Promise<Affordances | null> {\n const handler = stepMap.get(ctx.toolName);\n\n if (!handler) {\n if (onMissingStep) {\n onMissingStep(ctx);\n }\n return null;\n }\n\n const result = await handler(ctx);\n\n if (!result) {\n return null;\n }\n\n // Dev mode: Warn if nextTool is empty\n if (devMode && result.nextTool === \"\") {\n console.warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);\n }\n\n // Auto-generate the advice text\n return {\n advice: generateAdvice(result.nextTool),\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACkBO,SAAS,WACd,QACA,SACgB;AAChB,QAAM,QAAoB,CAAC;AAE3B,QAAM,cAA2B;AAAA,IAC/B,KAAK,UAAkB,SAA4B;AACjD,YAAM,KAAK,EAAE,UAAU,QAAQ,CAAC;AAAA,IAClC;AAAA,EACF;AAEA,UAAQ,WAAW;AAEnB,SAAO;AAAA,IACL,IAAI;AAAA,IACJ;AAAA,EACF;AACF;;;AC/BA,SAAS,eAAe,UAA0B;AAChD,SAAO,0DAA0D,QAAQ;AAC3E;AAmBO,SAAS,YAAY,SAA8B;AACxD,QAAM,EAAE,MAAM,UAAU,OAAO,cAAc,IAAI;AAGjD,MAAI,SAAS;AACX,UAAM,YAAY,oBAAI,IAAY;AAClC,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,UAAU,IAAI,KAAK,QAAQ,GAAG;AAChC,cAAM,IAAI;AAAA,UACR,mCAAmC,KAAK,QAAQ,cAAc,KAAK,EAAE;AAAA,QACvE;AAAA,MACF;AACA,gBAAU,IAAI,KAAK,QAAQ;AAAA,IAC7B;AAAA,EACF;AAGA,QAAM,UAAU,IAAI;AAAA,IAClB,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,UAAU,KAAK,OAAO,CAAC;AAAA,EACxD;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ,KAAgD;AAC5D,YAAM,UAAU,QAAQ,IAAI,IAAI,QAAQ;AAExC,UAAI,CAAC,SAAS;AACZ,YAAI,eAAe;AACjB,wBAAc,GAAG;AAAA,QACnB;AACA,eAAO;AAAA,MACT;AAEA,YAAM,SAAS,MAAM,QAAQ,GAAG;AAEhC,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,MACT;AAGA,UAAI,WAAW,OAAO,aAAa,IAAI;AACrC,gBAAQ,KAAK,6BAA6B,IAAI,QAAQ,aAAa;AAAA,MACrE;AAGA,aAAO;AAAA,QACL,QAAQ,eAAe,OAAO,QAAQ;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/flow.ts","../src/uiAffordances/types.ts","../src/uiAffordances/indexing.ts","../src/uiAffordances/select.ts","../src/createTaias.ts","../src/uiAffordances/defineAffordances.ts","../src/uiAffordances/mergeAffordances.ts"],"sourcesContent":["// Main exports\nexport { defineFlow } from \"./flow\";\nexport { createTaias } from \"./createTaias\";\n\n// UI affordances exports\nexport { defineAffordances } from \"./uiAffordances/defineAffordances\";\nexport { mergeAffordances } from \"./uiAffordances/mergeAffordances\";\nexport type {\n CanonicalSlot,\n Binding,\n BindingInput,\n HandleRegistration,\n Selection,\n UiSelections,\n AffordanceRegistry,\n SlotMatch,\n} from \"./uiAffordances/types\";\n\n// Core + flow type exports\nexport type {\n Decision, // moved to core\n TaiasContext,\n StepDecision,\n Affordances,\n StepHandler,\n FlowStep,\n FlowDefinition,\n FlowBuilder,\n TaiasOptions,\n Taias,\n} from \"./types\";\n","import type { FlowBuilder, FlowDefinition, FlowStep, StepHandler } from \"./types\";\n\n/**\n * Define a flow with its steps.\n *\n * @param flowId - Unique identifier for the flow\n * @param builder - Callback that receives a FlowBuilder to define steps\n * @returns A FlowDefinition object\n *\n * @example\n * ```ts\n * const onboardRepoFlow = defineFlow(\"onboard_repo\", (flow) => {\n * flow.step(\"scan_repo\", (ctx) => ({\n * nextTool: \"configure_app\",\n * }));\n * });\n * ```\n */\nexport function defineFlow(\n flowId: string,\n builder: (flow: FlowBuilder) => void\n): FlowDefinition {\n const steps: FlowStep[] = [];\n\n const flowBuilder: FlowBuilder = {\n step(toolName: string, handler: StepHandler): void {\n steps.push({ toolName, handler });\n },\n };\n\n builder(flowBuilder);\n\n return {\n id: flowId,\n steps,\n };\n}\n\n","export type CanonicalSlot = \"primaryCta\" | \"secondaryCta\" | \"widgetVariant\";\n\nexport type Binding = {\n key: string;\n value: string;\n};\n\n/**\n * Input format for registering affordance bindings.\n * - { toolName } is shorthand for { key: \"nextTool\", value: toolName }\n * - { key, value } is the generalized form for custom bindings\n */\nexport type BindingInput = { toolName: string } | { key: string; value: string };\n\nexport type HandleRegistration = {\n slot: CanonicalSlot;\n handleId: string;\n bindsTo: Binding;\n};\n\nexport type Selection = {\n handleId: string;\n bindsTo: Binding;\n};\n\nexport type UiSelections = Partial<Record<CanonicalSlot, Selection>>;\n\nexport type AffordanceRegistry = {\n handles: HandleRegistration[];\n};\n\nexport type SlotMatch = Partial<Record<CanonicalSlot, string>>;\n\nexport function normalizeBinding(input: BindingInput): Binding {\n if (\"toolName\" in input) return { key: \"nextTool\", value: input.toolName };\n return { key: input.key, value: input.value };\n}\n\nexport function makeBindingKey(slot: CanonicalSlot, binding: Binding): string {\n return `${slot}::${binding.key}::${binding.value}`;\n}\n","import type { AffordanceRegistry, HandleRegistration } from \"./types\";\nimport { makeBindingKey } from \"./types\";\n\nexport type RegistryIndex = {\n byBindingKey: Map<string, HandleRegistration>;\n};\n\nexport function buildRegistryIndex(registry?: AffordanceRegistry): RegistryIndex {\n const byBindingKey = new Map<string, HandleRegistration>();\n\n if (!registry) return { byBindingKey };\n\n for (const h of registry.handles) {\n byBindingKey.set(makeBindingKey(h.slot, h.bindsTo), h);\n }\n\n return { byBindingKey };\n}\n","import type { Decision } from \"../types\";\nimport type { CanonicalSlot, SlotMatch, UiSelections } from \"./types\";\nimport type { RegistryIndex } from \"./indexing\";\nimport { makeBindingKey } from \"./types\";\n\nconst DEFAULT_SLOT_MATCH: Required<Record<CanonicalSlot, string>> = {\n primaryCta: \"nextTool\",\n secondaryCta: \"nextTool\",\n widgetVariant: \"nextTool\",\n};\n\nexport type SelectOptions = {\n slotMatch?: SlotMatch;\n devMode?: boolean;\n onWarn?: (msg: string) => void;\n};\n\nexport function selectUiAffordances(\n decision: Decision,\n index: RegistryIndex,\n opts: SelectOptions = {}\n): UiSelections {\n const slotMatch = { ...DEFAULT_SLOT_MATCH, ...(opts.slotMatch ?? {}) };\n const devMode = !!opts.devMode;\n const warn = opts.onWarn ?? (() => {});\n\n const selections: UiSelections = {};\n const slots = Object.keys(DEFAULT_SLOT_MATCH) as CanonicalSlot[];\n\n for (const slot of slots) {\n const field = slotMatch[slot];\n const value = decision[field];\n if (!value) continue;\n\n const k = makeBindingKey(slot, { key: field, value });\n const handle = index.byBindingKey.get(k);\n\n if (!handle) {\n if (devMode) warn(`[Taias] No affordance for slot \"${slot}\" when ${field}=\"${value}\"`);\n continue;\n }\n\n selections[slot] = { handleId: handle.handleId, bindsTo: handle.bindsTo };\n }\n\n return selections;\n}\n","import type { Affordances, Taias, TaiasContext, TaiasOptions, Decision } from \"./types\";\nimport { buildRegistryIndex } from \"./uiAffordances/indexing\";\nimport { selectUiAffordances } from \"./uiAffordances/select\";\n\n/**\n * Generate advice text for a given next tool.\n */\nfunction generateAdvice(nextTool: string): string {\n return `FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE ${nextTool} TOOL NEXT!!!!!`;\n}\n\n/**\n * createTaias constructs a decision engine.\n *\n * Taias resolves tool context into a generalized Decision object,\n * and then manifests that decision into concrete affordances:\n *\n * - LLM guidance (advice)\n * - UI affordance selections\n *\n * Flow logic determines *what should happen next*.\n * UI affordances determine *how that decision appears in the interface*.\n *\n * This file is the boundary where:\n *\n * Inputs → Decision → Manifestations\n *\n * are unified into a single resolve() call.\n */\nexport function createTaias(options: TaiasOptions): Taias {\n const {\n flow,\n affordances,\n slotMatch,\n devMode = false,\n onMissingStep,\n onWarn,\n } = options;\n\n const warn = onWarn ?? ((msg: string) => console.warn(msg));\n\n // Dev mode: Check for duplicate toolNames\n if (devMode) {\n const seenTools = new Set<string>();\n for (const step of flow.steps) {\n if (seenTools.has(step.toolName)) {\n throw new Error(\n `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. Only one handler per tool is supported.`\n );\n }\n seenTools.add(step.toolName);\n }\n }\n\n // Build a lookup map for efficient resolution\n const stepMap = new Map(flow.steps.map((step) => [step.toolName, step.handler]));\n\n // Build affordance index once (if provided)\n const registryIndex = buildRegistryIndex(affordances);\n\n return {\n async resolve(ctx: TaiasContext): Promise<Affordances | null> {\n const handler = stepMap.get(ctx.toolName);\n\n if (!handler) {\n onMissingStep?.(ctx);\n return null;\n }\n\n const result = await handler(ctx);\n if (!result) return null;\n\n if (devMode && result.nextTool === \"\") {\n warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);\n }\n\n // Build decision object from flow result\n const decision: Decision = {\n nextTool: result.nextTool,\n };\n\n // Compute UI selections (may be empty if no registry passed)\n const selections = selectUiAffordances(decision, registryIndex, {\n devMode,\n onWarn: warn,\n slotMatch,\n });\n\n return {\n advice: generateAdvice(result.nextTool),\n decision,\n selections,\n };\n },\n };\n}\n","import type {\n AffordanceRegistry,\n BindingInput,\n CanonicalSlot,\n HandleRegistration,\n } from \"./types\";\n import { normalizeBinding } from \"./types\";\n \n type RegistrarFn = (handleId: string, bindsTo: BindingInput) => void;\n \n export interface AffordanceRegistrar {\n primaryCta: RegistrarFn;\n secondaryCta: RegistrarFn;\n widgetVariant: RegistrarFn;\n }\n \n export function defineAffordances(builder: (r: AffordanceRegistrar) => void): AffordanceRegistry {\n const handles: HandleRegistration[] = [];\n \n const push = (slot: CanonicalSlot, handleId: string, bindsTo: BindingInput) => {\n handles.push({\n slot,\n handleId,\n bindsTo: normalizeBinding(bindsTo),\n });\n };\n \n const registrar: AffordanceRegistrar = {\n primaryCta: (handleId, bindsTo) => push(\"primaryCta\", handleId, bindsTo),\n secondaryCta: (handleId, bindsTo) => push(\"secondaryCta\", handleId, bindsTo),\n widgetVariant: (handleId, bindsTo) => push(\"widgetVariant\", handleId, bindsTo),\n };\n \n builder(registrar);\n return { handles };\n }\n ","import type { AffordanceRegistry } from \"./types\";\nimport { makeBindingKey } from \"./types\";\n\nexport type MergeAffordancesOptions = {\n devMode?: boolean;\n onWarn?: (msg: string) => void;\n};\n\nexport function mergeAffordances(\n registries: AffordanceRegistry[],\n opts: MergeAffordancesOptions = {}\n): AffordanceRegistry {\n const devMode = !!opts.devMode;\n const warn = opts.onWarn ?? (() => {});\n\n const merged: AffordanceRegistry = { handles: registries.flatMap((r) => r.handles) };\n\n if (!devMode) return merged;\n\n // Check for duplicate handleIds\n const seenHandleIds = new Set<string>();\n for (const h of merged.handles) {\n if (seenHandleIds.has(h.handleId)) {\n throw new Error(`[Taias] Duplicate handleId \"${h.handleId}\"`);\n }\n seenHandleIds.add(h.handleId);\n }\n\n // Check for ambiguous bindings (same slot + key + value)\n const seenTriples = new Set<string>();\n for (const h of merged.handles) {\n const k = makeBindingKey(h.slot, h.bindsTo);\n if (seenTriples.has(k)) {\n throw new Error(\n `[Taias] Ambiguous affordance: slot \"${h.slot}\" has multiple handles bound to (${h.bindsTo.key}=\"${h.bindsTo.value}\")`\n );\n }\n seenTriples.add(k);\n }\n\n warn(`[Taias] Loaded ${merged.handles.length} UI affordance handles`);\n return merged;\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,3 +1,39 @@
1
+ type CanonicalSlot = "primaryCta" | "secondaryCta" | "widgetVariant";
2
+ type Binding = {
3
+ key: string;
4
+ value: string;
5
+ };
6
+ /**
7
+ * Input format for registering affordance bindings.
8
+ * - { toolName } is shorthand for { key: "nextTool", value: toolName }
9
+ * - { key, value } is the generalized form for custom bindings
10
+ */
11
+ type BindingInput = {
12
+ toolName: string;
13
+ } | {
14
+ key: string;
15
+ value: string;
16
+ };
17
+ type HandleRegistration = {
18
+ slot: CanonicalSlot;
19
+ handleId: string;
20
+ bindsTo: Binding;
21
+ };
22
+ type Selection = {
23
+ handleId: string;
24
+ bindsTo: Binding;
25
+ };
26
+ type UiSelections = Partial<Record<CanonicalSlot, Selection>>;
27
+ type AffordanceRegistry = {
28
+ handles: HandleRegistration[];
29
+ };
30
+ type SlotMatch = Partial<Record<CanonicalSlot, string>>;
31
+
32
+ /**
33
+ * Generalized decision object.
34
+ * Currently uses decision.nextTool. The structure supports additional keys.
35
+ */
36
+ type Decision = Record<string, string | undefined>;
1
37
  /**
2
38
  * Context passed to a step handler.
3
39
  */
@@ -11,10 +47,15 @@ type StepDecision = {
11
47
  nextTool: string;
12
48
  };
13
49
  /**
14
- * Affordances returned by resolve() with auto-generated advice text.
50
+ * Affordances returned by resolve():
51
+ * - advice: LLM guidance text
52
+ * - decision: generalized decision object (currently includes nextTool)
53
+ * - selections: UI affordance selections (may be empty)
15
54
  */
16
55
  type Affordances = {
17
56
  advice: string;
57
+ decision: Decision;
58
+ selections: UiSelections;
18
59
  };
19
60
  /**
20
61
  * Handler function for a flow step.
@@ -46,8 +87,11 @@ interface FlowBuilder {
46
87
  */
47
88
  type TaiasOptions = {
48
89
  flow: FlowDefinition;
90
+ affordances?: AffordanceRegistry;
91
+ slotMatch?: SlotMatch;
49
92
  devMode?: boolean;
50
93
  onMissingStep?: (ctx: TaiasContext) => void;
94
+ onWarn?: (msg: string) => void;
51
95
  };
52
96
  /**
53
97
  * The Taias instance interface.
@@ -75,22 +119,37 @@ interface Taias {
75
119
  declare function defineFlow(flowId: string, builder: (flow: FlowBuilder) => void): FlowDefinition;
76
120
 
77
121
  /**
78
- * Create a Taias instance from a single flow.
122
+ * createTaias constructs a decision engine.
79
123
  *
80
- * @param options - Configuration options
81
- * @returns A Taias instance with a resolve method
124
+ * Taias resolves tool context into a generalized Decision object,
125
+ * and then manifests that decision into concrete affordances:
82
126
  *
83
- * @example
84
- * ```ts
85
- * const taias = createTaias({
86
- * flow: onboardRepoFlow,
87
- * devMode: process.env.NODE_ENV !== "production",
88
- * });
127
+ * - LLM guidance (advice)
128
+ * - UI affordance selections
89
129
  *
90
- * const decision = await taias.resolve({ toolName: "scan_repo" });
91
- * // decision.advice "FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE configure_app TOOL NEXT!!!!!"
92
- * ```
130
+ * Flow logic determines *what should happen next*.
131
+ * UI affordances determine *how that decision appears in the interface*.
132
+ *
133
+ * This file is the boundary where:
134
+ *
135
+ * Inputs → Decision → Manifestations
136
+ *
137
+ * are unified into a single resolve() call.
93
138
  */
94
139
  declare function createTaias(options: TaiasOptions): Taias;
95
140
 
96
- export { type Affordances, type FlowBuilder, type FlowDefinition, type FlowStep, type StepDecision, type StepHandler, type Taias, type TaiasContext, type TaiasOptions, createTaias, defineFlow };
141
+ type RegistrarFn = (handleId: string, bindsTo: BindingInput) => void;
142
+ interface AffordanceRegistrar {
143
+ primaryCta: RegistrarFn;
144
+ secondaryCta: RegistrarFn;
145
+ widgetVariant: RegistrarFn;
146
+ }
147
+ declare function defineAffordances(builder: (r: AffordanceRegistrar) => void): AffordanceRegistry;
148
+
149
+ type MergeAffordancesOptions = {
150
+ devMode?: boolean;
151
+ onWarn?: (msg: string) => void;
152
+ };
153
+ declare function mergeAffordances(registries: AffordanceRegistry[], opts?: MergeAffordancesOptions): AffordanceRegistry;
154
+
155
+ export { type AffordanceRegistry, type Affordances, type Binding, type BindingInput, type CanonicalSlot, type Decision, type FlowBuilder, type FlowDefinition, type FlowStep, type HandleRegistration, type Selection, type SlotMatch, type StepDecision, type StepHandler, type Taias, type TaiasContext, type TaiasOptions, type UiSelections, createTaias, defineAffordances, defineFlow, mergeAffordances };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,39 @@
1
+ type CanonicalSlot = "primaryCta" | "secondaryCta" | "widgetVariant";
2
+ type Binding = {
3
+ key: string;
4
+ value: string;
5
+ };
6
+ /**
7
+ * Input format for registering affordance bindings.
8
+ * - { toolName } is shorthand for { key: "nextTool", value: toolName }
9
+ * - { key, value } is the generalized form for custom bindings
10
+ */
11
+ type BindingInput = {
12
+ toolName: string;
13
+ } | {
14
+ key: string;
15
+ value: string;
16
+ };
17
+ type HandleRegistration = {
18
+ slot: CanonicalSlot;
19
+ handleId: string;
20
+ bindsTo: Binding;
21
+ };
22
+ type Selection = {
23
+ handleId: string;
24
+ bindsTo: Binding;
25
+ };
26
+ type UiSelections = Partial<Record<CanonicalSlot, Selection>>;
27
+ type AffordanceRegistry = {
28
+ handles: HandleRegistration[];
29
+ };
30
+ type SlotMatch = Partial<Record<CanonicalSlot, string>>;
31
+
32
+ /**
33
+ * Generalized decision object.
34
+ * Currently uses decision.nextTool. The structure supports additional keys.
35
+ */
36
+ type Decision = Record<string, string | undefined>;
1
37
  /**
2
38
  * Context passed to a step handler.
3
39
  */
@@ -11,10 +47,15 @@ type StepDecision = {
11
47
  nextTool: string;
12
48
  };
13
49
  /**
14
- * Affordances returned by resolve() with auto-generated advice text.
50
+ * Affordances returned by resolve():
51
+ * - advice: LLM guidance text
52
+ * - decision: generalized decision object (currently includes nextTool)
53
+ * - selections: UI affordance selections (may be empty)
15
54
  */
16
55
  type Affordances = {
17
56
  advice: string;
57
+ decision: Decision;
58
+ selections: UiSelections;
18
59
  };
19
60
  /**
20
61
  * Handler function for a flow step.
@@ -46,8 +87,11 @@ interface FlowBuilder {
46
87
  */
47
88
  type TaiasOptions = {
48
89
  flow: FlowDefinition;
90
+ affordances?: AffordanceRegistry;
91
+ slotMatch?: SlotMatch;
49
92
  devMode?: boolean;
50
93
  onMissingStep?: (ctx: TaiasContext) => void;
94
+ onWarn?: (msg: string) => void;
51
95
  };
52
96
  /**
53
97
  * The Taias instance interface.
@@ -75,22 +119,37 @@ interface Taias {
75
119
  declare function defineFlow(flowId: string, builder: (flow: FlowBuilder) => void): FlowDefinition;
76
120
 
77
121
  /**
78
- * Create a Taias instance from a single flow.
122
+ * createTaias constructs a decision engine.
79
123
  *
80
- * @param options - Configuration options
81
- * @returns A Taias instance with a resolve method
124
+ * Taias resolves tool context into a generalized Decision object,
125
+ * and then manifests that decision into concrete affordances:
82
126
  *
83
- * @example
84
- * ```ts
85
- * const taias = createTaias({
86
- * flow: onboardRepoFlow,
87
- * devMode: process.env.NODE_ENV !== "production",
88
- * });
127
+ * - LLM guidance (advice)
128
+ * - UI affordance selections
89
129
  *
90
- * const decision = await taias.resolve({ toolName: "scan_repo" });
91
- * // decision.advice "FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE configure_app TOOL NEXT!!!!!"
92
- * ```
130
+ * Flow logic determines *what should happen next*.
131
+ * UI affordances determine *how that decision appears in the interface*.
132
+ *
133
+ * This file is the boundary where:
134
+ *
135
+ * Inputs → Decision → Manifestations
136
+ *
137
+ * are unified into a single resolve() call.
93
138
  */
94
139
  declare function createTaias(options: TaiasOptions): Taias;
95
140
 
96
- export { type Affordances, type FlowBuilder, type FlowDefinition, type FlowStep, type StepDecision, type StepHandler, type Taias, type TaiasContext, type TaiasOptions, createTaias, defineFlow };
141
+ type RegistrarFn = (handleId: string, bindsTo: BindingInput) => void;
142
+ interface AffordanceRegistrar {
143
+ primaryCta: RegistrarFn;
144
+ secondaryCta: RegistrarFn;
145
+ widgetVariant: RegistrarFn;
146
+ }
147
+ declare function defineAffordances(builder: (r: AffordanceRegistrar) => void): AffordanceRegistry;
148
+
149
+ type MergeAffordancesOptions = {
150
+ devMode?: boolean;
151
+ onWarn?: (msg: string) => void;
152
+ };
153
+ declare function mergeAffordances(registries: AffordanceRegistry[], opts?: MergeAffordancesOptions): AffordanceRegistry;
154
+
155
+ export { type AffordanceRegistry, type Affordances, type Binding, type BindingInput, type CanonicalSlot, type Decision, type FlowBuilder, type FlowDefinition, type FlowStep, type HandleRegistration, type Selection, type SlotMatch, type StepDecision, type StepHandler, type Taias, type TaiasContext, type TaiasOptions, type UiSelections, createTaias, defineAffordances, defineFlow, mergeAffordances };
package/dist/index.js CHANGED
@@ -13,50 +13,159 @@ function defineFlow(flowId, builder) {
13
13
  };
14
14
  }
15
15
 
16
+ // src/uiAffordances/types.ts
17
+ function normalizeBinding(input) {
18
+ if ("toolName" in input) return { key: "nextTool", value: input.toolName };
19
+ return { key: input.key, value: input.value };
20
+ }
21
+ function makeBindingKey(slot, binding) {
22
+ return `${slot}::${binding.key}::${binding.value}`;
23
+ }
24
+
25
+ // src/uiAffordances/indexing.ts
26
+ function buildRegistryIndex(registry) {
27
+ const byBindingKey = /* @__PURE__ */ new Map();
28
+ if (!registry) return { byBindingKey };
29
+ for (const h of registry.handles) {
30
+ byBindingKey.set(makeBindingKey(h.slot, h.bindsTo), h);
31
+ }
32
+ return { byBindingKey };
33
+ }
34
+
35
+ // src/uiAffordances/select.ts
36
+ var DEFAULT_SLOT_MATCH = {
37
+ primaryCta: "nextTool",
38
+ secondaryCta: "nextTool",
39
+ widgetVariant: "nextTool"
40
+ };
41
+ function selectUiAffordances(decision, index, opts = {}) {
42
+ const slotMatch = { ...DEFAULT_SLOT_MATCH, ...opts.slotMatch ?? {} };
43
+ const devMode = !!opts.devMode;
44
+ const warn = opts.onWarn ?? (() => {
45
+ });
46
+ const selections = {};
47
+ const slots = Object.keys(DEFAULT_SLOT_MATCH);
48
+ for (const slot of slots) {
49
+ const field = slotMatch[slot];
50
+ const value = decision[field];
51
+ if (!value) continue;
52
+ const k = makeBindingKey(slot, { key: field, value });
53
+ const handle = index.byBindingKey.get(k);
54
+ if (!handle) {
55
+ if (devMode) warn(`[Taias] No affordance for slot "${slot}" when ${field}="${value}"`);
56
+ continue;
57
+ }
58
+ selections[slot] = { handleId: handle.handleId, bindsTo: handle.bindsTo };
59
+ }
60
+ return selections;
61
+ }
62
+
16
63
  // src/createTaias.ts
17
64
  function generateAdvice(nextTool) {
18
65
  return `FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE ${nextTool} TOOL NEXT!!!!!`;
19
66
  }
20
67
  function createTaias(options) {
21
- const { flow, devMode = false, onMissingStep } = options;
68
+ const {
69
+ flow,
70
+ affordances,
71
+ slotMatch,
72
+ devMode = false,
73
+ onMissingStep,
74
+ onWarn
75
+ } = options;
76
+ const warn = onWarn ?? ((msg) => console.warn(msg));
22
77
  if (devMode) {
23
78
  const seenTools = /* @__PURE__ */ new Set();
24
79
  for (const step of flow.steps) {
25
80
  if (seenTools.has(step.toolName)) {
26
81
  throw new Error(
27
- `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. V1 supports one handler per tool.`
82
+ `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. Only one handler per tool is supported.`
28
83
  );
29
84
  }
30
85
  seenTools.add(step.toolName);
31
86
  }
32
87
  }
33
- const stepMap = new Map(
34
- flow.steps.map((step) => [step.toolName, step.handler])
35
- );
88
+ const stepMap = new Map(flow.steps.map((step) => [step.toolName, step.handler]));
89
+ const registryIndex = buildRegistryIndex(affordances);
36
90
  return {
37
91
  async resolve(ctx) {
38
92
  const handler = stepMap.get(ctx.toolName);
39
93
  if (!handler) {
40
- if (onMissingStep) {
41
- onMissingStep(ctx);
42
- }
94
+ onMissingStep?.(ctx);
43
95
  return null;
44
96
  }
45
97
  const result = await handler(ctx);
46
- if (!result) {
47
- return null;
48
- }
98
+ if (!result) return null;
49
99
  if (devMode && result.nextTool === "") {
50
- console.warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);
100
+ warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);
51
101
  }
102
+ const decision = {
103
+ nextTool: result.nextTool
104
+ };
105
+ const selections = selectUiAffordances(decision, registryIndex, {
106
+ devMode,
107
+ onWarn: warn,
108
+ slotMatch
109
+ });
52
110
  return {
53
- advice: generateAdvice(result.nextTool)
111
+ advice: generateAdvice(result.nextTool),
112
+ decision,
113
+ selections
54
114
  };
55
115
  }
56
116
  };
57
117
  }
118
+
119
+ // src/uiAffordances/defineAffordances.ts
120
+ function defineAffordances(builder) {
121
+ const handles = [];
122
+ const push = (slot, handleId, bindsTo) => {
123
+ handles.push({
124
+ slot,
125
+ handleId,
126
+ bindsTo: normalizeBinding(bindsTo)
127
+ });
128
+ };
129
+ const registrar = {
130
+ primaryCta: (handleId, bindsTo) => push("primaryCta", handleId, bindsTo),
131
+ secondaryCta: (handleId, bindsTo) => push("secondaryCta", handleId, bindsTo),
132
+ widgetVariant: (handleId, bindsTo) => push("widgetVariant", handleId, bindsTo)
133
+ };
134
+ builder(registrar);
135
+ return { handles };
136
+ }
137
+
138
+ // src/uiAffordances/mergeAffordances.ts
139
+ function mergeAffordances(registries, opts = {}) {
140
+ const devMode = !!opts.devMode;
141
+ const warn = opts.onWarn ?? (() => {
142
+ });
143
+ const merged = { handles: registries.flatMap((r) => r.handles) };
144
+ if (!devMode) return merged;
145
+ const seenHandleIds = /* @__PURE__ */ new Set();
146
+ for (const h of merged.handles) {
147
+ if (seenHandleIds.has(h.handleId)) {
148
+ throw new Error(`[Taias] Duplicate handleId "${h.handleId}"`);
149
+ }
150
+ seenHandleIds.add(h.handleId);
151
+ }
152
+ const seenTriples = /* @__PURE__ */ new Set();
153
+ for (const h of merged.handles) {
154
+ const k = makeBindingKey(h.slot, h.bindsTo);
155
+ if (seenTriples.has(k)) {
156
+ throw new Error(
157
+ `[Taias] Ambiguous affordance: slot "${h.slot}" has multiple handles bound to (${h.bindsTo.key}="${h.bindsTo.value}")`
158
+ );
159
+ }
160
+ seenTriples.add(k);
161
+ }
162
+ warn(`[Taias] Loaded ${merged.handles.length} UI affordance handles`);
163
+ return merged;
164
+ }
58
165
  export {
59
166
  createTaias,
60
- defineFlow
167
+ defineAffordances,
168
+ defineFlow,
169
+ mergeAffordances
61
170
  };
62
171
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/flow.ts","../src/createTaias.ts"],"sourcesContent":["import type { FlowBuilder, FlowDefinition, FlowStep, StepHandler } from \"./types\";\n\n/**\n * Define a flow with its steps.\n *\n * @param flowId - Unique identifier for the flow\n * @param builder - Callback that receives a FlowBuilder to define steps\n * @returns A FlowDefinition object\n *\n * @example\n * ```ts\n * const onboardRepoFlow = defineFlow(\"onboard_repo\", (flow) => {\n * flow.step(\"scan_repo\", (ctx) => ({\n * nextTool: \"configure_app\",\n * }));\n * });\n * ```\n */\nexport function defineFlow(\n flowId: string,\n builder: (flow: FlowBuilder) => void\n): FlowDefinition {\n const steps: FlowStep[] = [];\n\n const flowBuilder: FlowBuilder = {\n step(toolName: string, handler: StepHandler): void {\n steps.push({ toolName, handler });\n },\n };\n\n builder(flowBuilder);\n\n return {\n id: flowId,\n steps,\n };\n}\n\n","import type { Affordances, Taias, TaiasContext, TaiasOptions } from \"./types\";\n\n/**\n * Generate advice text for a given next tool.\n */\nfunction generateAdvice(nextTool: string): string {\n return `FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE ${nextTool} TOOL NEXT!!!!!`;\n}\n\n/**\n * Create a Taias instance from a single flow.\n *\n * @param options - Configuration options\n * @returns A Taias instance with a resolve method\n *\n * @example\n * ```ts\n * const taias = createTaias({\n * flow: onboardRepoFlow,\n * devMode: process.env.NODE_ENV !== \"production\",\n * });\n *\n * const decision = await taias.resolve({ toolName: \"scan_repo\" });\n * // decision.advice → \"FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE configure_app TOOL NEXT!!!!!\"\n * ```\n */\nexport function createTaias(options: TaiasOptions): Taias {\n const { flow, devMode = false, onMissingStep } = options;\n\n // Dev mode: Check for duplicate toolNames\n if (devMode) {\n const seenTools = new Set<string>();\n for (const step of flow.steps) {\n if (seenTools.has(step.toolName)) {\n throw new Error(\n `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. V1 supports one handler per tool.`\n );\n }\n seenTools.add(step.toolName);\n }\n }\n\n // Build a lookup map for efficient resolution\n const stepMap = new Map(\n flow.steps.map((step) => [step.toolName, step.handler])\n );\n\n return {\n async resolve(ctx: TaiasContext): Promise<Affordances | null> {\n const handler = stepMap.get(ctx.toolName);\n\n if (!handler) {\n if (onMissingStep) {\n onMissingStep(ctx);\n }\n return null;\n }\n\n const result = await handler(ctx);\n\n if (!result) {\n return null;\n }\n\n // Dev mode: Warn if nextTool is empty\n if (devMode && result.nextTool === \"\") {\n console.warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);\n }\n\n // Auto-generate the advice text\n return {\n advice: generateAdvice(result.nextTool),\n };\n },\n };\n}\n"],"mappings":";AAkBO,SAAS,WACd,QACA,SACgB;AAChB,QAAM,QAAoB,CAAC;AAE3B,QAAM,cAA2B;AAAA,IAC/B,KAAK,UAAkB,SAA4B;AACjD,YAAM,KAAK,EAAE,UAAU,QAAQ,CAAC;AAAA,IAClC;AAAA,EACF;AAEA,UAAQ,WAAW;AAEnB,SAAO;AAAA,IACL,IAAI;AAAA,IACJ;AAAA,EACF;AACF;;;AC/BA,SAAS,eAAe,UAA0B;AAChD,SAAO,0DAA0D,QAAQ;AAC3E;AAmBO,SAAS,YAAY,SAA8B;AACxD,QAAM,EAAE,MAAM,UAAU,OAAO,cAAc,IAAI;AAGjD,MAAI,SAAS;AACX,UAAM,YAAY,oBAAI,IAAY;AAClC,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,UAAU,IAAI,KAAK,QAAQ,GAAG;AAChC,cAAM,IAAI;AAAA,UACR,mCAAmC,KAAK,QAAQ,cAAc,KAAK,EAAE;AAAA,QACvE;AAAA,MACF;AACA,gBAAU,IAAI,KAAK,QAAQ;AAAA,IAC7B;AAAA,EACF;AAGA,QAAM,UAAU,IAAI;AAAA,IAClB,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,UAAU,KAAK,OAAO,CAAC;AAAA,EACxD;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ,KAAgD;AAC5D,YAAM,UAAU,QAAQ,IAAI,IAAI,QAAQ;AAExC,UAAI,CAAC,SAAS;AACZ,YAAI,eAAe;AACjB,wBAAc,GAAG;AAAA,QACnB;AACA,eAAO;AAAA,MACT;AAEA,YAAM,SAAS,MAAM,QAAQ,GAAG;AAEhC,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,MACT;AAGA,UAAI,WAAW,OAAO,aAAa,IAAI;AACrC,gBAAQ,KAAK,6BAA6B,IAAI,QAAQ,aAAa;AAAA,MACrE;AAGA,aAAO;AAAA,QACL,QAAQ,eAAe,OAAO,QAAQ;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/flow.ts","../src/uiAffordances/types.ts","../src/uiAffordances/indexing.ts","../src/uiAffordances/select.ts","../src/createTaias.ts","../src/uiAffordances/defineAffordances.ts","../src/uiAffordances/mergeAffordances.ts"],"sourcesContent":["import type { FlowBuilder, FlowDefinition, FlowStep, StepHandler } from \"./types\";\n\n/**\n * Define a flow with its steps.\n *\n * @param flowId - Unique identifier for the flow\n * @param builder - Callback that receives a FlowBuilder to define steps\n * @returns A FlowDefinition object\n *\n * @example\n * ```ts\n * const onboardRepoFlow = defineFlow(\"onboard_repo\", (flow) => {\n * flow.step(\"scan_repo\", (ctx) => ({\n * nextTool: \"configure_app\",\n * }));\n * });\n * ```\n */\nexport function defineFlow(\n flowId: string,\n builder: (flow: FlowBuilder) => void\n): FlowDefinition {\n const steps: FlowStep[] = [];\n\n const flowBuilder: FlowBuilder = {\n step(toolName: string, handler: StepHandler): void {\n steps.push({ toolName, handler });\n },\n };\n\n builder(flowBuilder);\n\n return {\n id: flowId,\n steps,\n };\n}\n\n","export type CanonicalSlot = \"primaryCta\" | \"secondaryCta\" | \"widgetVariant\";\n\nexport type Binding = {\n key: string;\n value: string;\n};\n\n/**\n * Input format for registering affordance bindings.\n * - { toolName } is shorthand for { key: \"nextTool\", value: toolName }\n * - { key, value } is the generalized form for custom bindings\n */\nexport type BindingInput = { toolName: string } | { key: string; value: string };\n\nexport type HandleRegistration = {\n slot: CanonicalSlot;\n handleId: string;\n bindsTo: Binding;\n};\n\nexport type Selection = {\n handleId: string;\n bindsTo: Binding;\n};\n\nexport type UiSelections = Partial<Record<CanonicalSlot, Selection>>;\n\nexport type AffordanceRegistry = {\n handles: HandleRegistration[];\n};\n\nexport type SlotMatch = Partial<Record<CanonicalSlot, string>>;\n\nexport function normalizeBinding(input: BindingInput): Binding {\n if (\"toolName\" in input) return { key: \"nextTool\", value: input.toolName };\n return { key: input.key, value: input.value };\n}\n\nexport function makeBindingKey(slot: CanonicalSlot, binding: Binding): string {\n return `${slot}::${binding.key}::${binding.value}`;\n}\n","import type { AffordanceRegistry, HandleRegistration } from \"./types\";\nimport { makeBindingKey } from \"./types\";\n\nexport type RegistryIndex = {\n byBindingKey: Map<string, HandleRegistration>;\n};\n\nexport function buildRegistryIndex(registry?: AffordanceRegistry): RegistryIndex {\n const byBindingKey = new Map<string, HandleRegistration>();\n\n if (!registry) return { byBindingKey };\n\n for (const h of registry.handles) {\n byBindingKey.set(makeBindingKey(h.slot, h.bindsTo), h);\n }\n\n return { byBindingKey };\n}\n","import type { Decision } from \"../types\";\nimport type { CanonicalSlot, SlotMatch, UiSelections } from \"./types\";\nimport type { RegistryIndex } from \"./indexing\";\nimport { makeBindingKey } from \"./types\";\n\nconst DEFAULT_SLOT_MATCH: Required<Record<CanonicalSlot, string>> = {\n primaryCta: \"nextTool\",\n secondaryCta: \"nextTool\",\n widgetVariant: \"nextTool\",\n};\n\nexport type SelectOptions = {\n slotMatch?: SlotMatch;\n devMode?: boolean;\n onWarn?: (msg: string) => void;\n};\n\nexport function selectUiAffordances(\n decision: Decision,\n index: RegistryIndex,\n opts: SelectOptions = {}\n): UiSelections {\n const slotMatch = { ...DEFAULT_SLOT_MATCH, ...(opts.slotMatch ?? {}) };\n const devMode = !!opts.devMode;\n const warn = opts.onWarn ?? (() => {});\n\n const selections: UiSelections = {};\n const slots = Object.keys(DEFAULT_SLOT_MATCH) as CanonicalSlot[];\n\n for (const slot of slots) {\n const field = slotMatch[slot];\n const value = decision[field];\n if (!value) continue;\n\n const k = makeBindingKey(slot, { key: field, value });\n const handle = index.byBindingKey.get(k);\n\n if (!handle) {\n if (devMode) warn(`[Taias] No affordance for slot \"${slot}\" when ${field}=\"${value}\"`);\n continue;\n }\n\n selections[slot] = { handleId: handle.handleId, bindsTo: handle.bindsTo };\n }\n\n return selections;\n}\n","import type { Affordances, Taias, TaiasContext, TaiasOptions, Decision } from \"./types\";\nimport { buildRegistryIndex } from \"./uiAffordances/indexing\";\nimport { selectUiAffordances } from \"./uiAffordances/select\";\n\n/**\n * Generate advice text for a given next tool.\n */\nfunction generateAdvice(nextTool: string): string {\n return `FOR THE BEST USER EXPERIENCE, TELL THE USER TO USE THE ${nextTool} TOOL NEXT!!!!!`;\n}\n\n/**\n * createTaias constructs a decision engine.\n *\n * Taias resolves tool context into a generalized Decision object,\n * and then manifests that decision into concrete affordances:\n *\n * - LLM guidance (advice)\n * - UI affordance selections\n *\n * Flow logic determines *what should happen next*.\n * UI affordances determine *how that decision appears in the interface*.\n *\n * This file is the boundary where:\n *\n * Inputs → Decision → Manifestations\n *\n * are unified into a single resolve() call.\n */\nexport function createTaias(options: TaiasOptions): Taias {\n const {\n flow,\n affordances,\n slotMatch,\n devMode = false,\n onMissingStep,\n onWarn,\n } = options;\n\n const warn = onWarn ?? ((msg: string) => console.warn(msg));\n\n // Dev mode: Check for duplicate toolNames\n if (devMode) {\n const seenTools = new Set<string>();\n for (const step of flow.steps) {\n if (seenTools.has(step.toolName)) {\n throw new Error(\n `Taias: Duplicate step for tool '${step.toolName}' in flow '${flow.id}'. Only one handler per tool is supported.`\n );\n }\n seenTools.add(step.toolName);\n }\n }\n\n // Build a lookup map for efficient resolution\n const stepMap = new Map(flow.steps.map((step) => [step.toolName, step.handler]));\n\n // Build affordance index once (if provided)\n const registryIndex = buildRegistryIndex(affordances);\n\n return {\n async resolve(ctx: TaiasContext): Promise<Affordances | null> {\n const handler = stepMap.get(ctx.toolName);\n\n if (!handler) {\n onMissingStep?.(ctx);\n return null;\n }\n\n const result = await handler(ctx);\n if (!result) return null;\n\n if (devMode && result.nextTool === \"\") {\n warn(`Taias: nextTool for tool '${ctx.toolName}' is empty.`);\n }\n\n // Build decision object from flow result\n const decision: Decision = {\n nextTool: result.nextTool,\n };\n\n // Compute UI selections (may be empty if no registry passed)\n const selections = selectUiAffordances(decision, registryIndex, {\n devMode,\n onWarn: warn,\n slotMatch,\n });\n\n return {\n advice: generateAdvice(result.nextTool),\n decision,\n selections,\n };\n },\n };\n}\n","import type {\n AffordanceRegistry,\n BindingInput,\n CanonicalSlot,\n HandleRegistration,\n } from \"./types\";\n import { normalizeBinding } from \"./types\";\n \n type RegistrarFn = (handleId: string, bindsTo: BindingInput) => void;\n \n export interface AffordanceRegistrar {\n primaryCta: RegistrarFn;\n secondaryCta: RegistrarFn;\n widgetVariant: RegistrarFn;\n }\n \n export function defineAffordances(builder: (r: AffordanceRegistrar) => void): AffordanceRegistry {\n const handles: HandleRegistration[] = [];\n \n const push = (slot: CanonicalSlot, handleId: string, bindsTo: BindingInput) => {\n handles.push({\n slot,\n handleId,\n bindsTo: normalizeBinding(bindsTo),\n });\n };\n \n const registrar: AffordanceRegistrar = {\n primaryCta: (handleId, bindsTo) => push(\"primaryCta\", handleId, bindsTo),\n secondaryCta: (handleId, bindsTo) => push(\"secondaryCta\", handleId, bindsTo),\n widgetVariant: (handleId, bindsTo) => push(\"widgetVariant\", handleId, bindsTo),\n };\n \n builder(registrar);\n return { handles };\n }\n ","import type { AffordanceRegistry } from \"./types\";\nimport { makeBindingKey } from \"./types\";\n\nexport type MergeAffordancesOptions = {\n devMode?: boolean;\n onWarn?: (msg: string) => void;\n};\n\nexport function mergeAffordances(\n registries: AffordanceRegistry[],\n opts: MergeAffordancesOptions = {}\n): AffordanceRegistry {\n const devMode = !!opts.devMode;\n const warn = opts.onWarn ?? (() => {});\n\n const merged: AffordanceRegistry = { handles: registries.flatMap((r) => r.handles) };\n\n if (!devMode) return merged;\n\n // Check for duplicate handleIds\n const seenHandleIds = new Set<string>();\n for (const h of merged.handles) {\n if (seenHandleIds.has(h.handleId)) {\n throw new Error(`[Taias] Duplicate handleId \"${h.handleId}\"`);\n }\n seenHandleIds.add(h.handleId);\n }\n\n // Check for ambiguous bindings (same slot + key + value)\n const seenTriples = new Set<string>();\n for (const h of merged.handles) {\n const k = makeBindingKey(h.slot, h.bindsTo);\n if (seenTriples.has(k)) {\n throw new Error(\n `[Taias] Ambiguous affordance: slot \"${h.slot}\" has multiple handles bound to (${h.bindsTo.key}=\"${h.bindsTo.value}\")`\n );\n }\n seenTriples.add(k);\n }\n\n warn(`[Taias] Loaded ${merged.handles.length} UI affordance handles`);\n return merged;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taias",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "Taias - Give your MCP server an opinion, guide your users to achieve outcomes",
6
6
  "license": "Apache-2.0",