StillMade AIDeveloper docs
Browse documentation · SDK 0.1.0

Universal requirement resolver

How StillMade fills Block inputs from upstream outputs, project context and user answers.

Universal requirement resolver

The public SDK exports createUniversalResolver(), the same implementation used by the Project Type composer, runtime input resolution and native explanations. The older block-platform/universal-resolver.js import reexports this engine.

Interactive JavaScript user requests

The Node SDK host may explicitly provide runPackageAsync(..., {requestFromUser}). An isolated Block can return StillMade.requestFromUser('name') for a missing, optional, non-context input whose contract allows user answers. Check StillMade.resolveRequirement('name').resolved first. The SDK resumes the code from its beginning with the validated answer in input.name; this is a cooperative return, not a Promise or an in-sandbox host callback. Avoid emitting outputs before returning the request. Other inputs remain unchanged.

Both worker boundaries validate the exact declared question and answer. Questions cannot collect credentials, overwrite existing values, widen permissions, or call providers. At most 20 questions are allowed. The Node worker pauses its cumulative five-second execution allowance while waiting, with a five-minute answer deadline; the guest's cumulative CPU and memory limits remain in force. Cancellation ends the run. Successful results include userAnswers for the host to persist alongside execution provenance. Hosts without the callback fail closed.

The application browser runner enables this bridge for individual non-batch JavaScript Step runs. It rechecks project identity, edit access, source admission, and the captured input snapshot around each question. Reviewed answers become semantic user values and contribute to the accepted run's input digest and output dependencies. Other browser callers must explicitly supply both a question handler and a current-project guard; otherwise interactive requests remain unavailable. Browser execution pauses its cumulative worker allowance during a bounded question wait, without expanding the guest CPU allowance. Batch questions, automatic in-run Chat, and shared credit accounting remain unfinished.

Interactive connected local runs now also forward user requests for JavaScript Steps with stop-on-error, bounded retry, or approval-before-retry policies, including connected media batches. The workflow runner independently validates each question, captures the reviewed answer, and requires the executor to return exactly those answers. The accepted input digest includes them, and retained results restore/revalidate optional answers without opening dialogs or rerunning completed Steps. Connected job deadlines still apply; fallback/recovery policies and unattended runs do not enable these questions. Retries receive previously reviewed answers as existing inputs instead of asking again. Each attempt may return only answers newly reviewed during that attempt; the workflow retains the aggregate and binds it to the successful result. Late replies from an ended attempt cannot change the retained answer set.

Connected batch questions name the current source asset and version. Answers are scoped to that target's run and do not silently carry into the next target. Resume validation binds them to the full source snapshot as well as the package, workflow, and effective inputs. Standalone single-Step batch previews also enable questions. Each preview keeps its own reviewed answers and input fingerprint. Using a result rechecks source, settings and answers, then registers the selected answers and outputs as the adopted single-Step result. Previews alone do not overwrite saved answers or advance saved Block memory.

Structured collections use a one-element schema array, such as schema: [{word: 'string', start: 'number', end: 'number'}] on an object[] contract. That schema describes every item, not a tuple or a fixed-length value. It also works inside object fields. Validation and connection compatibility check each item's required fields; plain object[] cannot promise those fields. The input dialog collects structured list items using their declared fields.

Built-in connection adapters also support ordered lists when both endpoints are scalar types with list variants. Each list adapter pins the scalar adapter version, converts at most 100 items, checks each item, and requires all context grants before conversion. A failed item rejects the entire conversion; no partial list is emitted. List-to-scalar flattening, implicit Block fan-out, and nested lists are not inferred. For example, text[] with meaning narration_script can supply script[] with the same meaning through list-text-to-script-v1 version 1. These are local data conversions, not separately billed provider calls or general workflow batches.

js
import {createUniversalResolver,input} from './packages/block-sdk/index.js';

const requirement=input({
  key:'company',type:'object',semantic:'company_profile',required:true,
  description:'Company information',schema:{name:'string'},sources:['project']
});
const resolver=createUniversalResolver();
const options={values:[{
  id:'company-profile',revision:1,type:'object',semantic:'company_profile',
  value:{name:'Morning Bakery'},source:{kind:'project'},permissions:[]
}]};
const explanation=resolver.inspect(requirement,options);
const resolved=await resolver.resolve(requirement,options);

inspect and explain return the selected source, reason and candidates. listCandidates returns priority-ordered alternatives. resolve checks actual values and returns source/dependency metadata. A required unresolved input stays unresolved; a pending callback can return one clarification question.

Pass an explicit semantic registry and versioned adapter registry when needed. The host may supply canDerive, requestFromChat and requestFromUser callbacks. No callback is provided automatically. Permission and freshness filtering applies to context passed to those callbacks; source/schema validation still applies to their results. Use stable record IDs and revisions for executable values. Plan mode can inspect declarations that do not yet contain a value; resolve always requires materialized values or an answer callback.

Callbacks receive isolated copies. Final resolution rechecks dependency freshness after waiting for an answer and rejects expired sources or missing revisions. The host must still detect edits to the underlying project while resolving; a copied context snapshot does not subscribe to storage changes.

This is a trusted-host/authoring library, not a new guest API or permission grant. It does not fetch project data, mutate projects, run Blocks, approve purchases, authorize credentials, or enforce a provider spending budget. Hosts must retain their existing scoped storage, sandbox, approval, cancellation and shared-budget boundaries around integrations. Do not register arbitrary creator code as a host callback. Download assembly includes this module, but generated download artifacts must be rebuilt separately.

Custom meanings and connection checks

Pass the same explicit semantics registry to the universal resolver and to compatible, connectionCompatibility, validateConnectionAdapter and adaptConnectionValue. The optional argument is {semantics}; adapter calls retain their existing permission, context and exact-version pin options. Inheritance widens only meaning compatibility, never physical types, schemas, permissions or adapter versions. Without a registry, only the standard semantic relationships apply. No process-global registry is mutated by these calls.

The application composition helpers accept the same scoped registry for audits, automatic connection selection, explicit source selection and recommendation checks. Store reusable definitions in manifest.semantics:

js
semantics: [{
  name: 'creator.example.spoken_copy',
  description: 'Words to read aloud.',
  parents: ['narration_script']
}]

Each Block may declare up to 64 namespaced meanings, eight parents per meaning and 500 description characters. Definitions cannot override unnamespaced standard meanings. Duplicate names within a Block, cycles, and conflicting parent sets across selected versions are rejected. Matching definitions may be shared. The source and release digest includes these declarations; changing a published definition requires a new release, not editing an immutable version.

semanticRegistryForManifests(manifests) reconstructs a scoped registry from saved contracts. Composer audits and local workflow execution load these package definitions automatically. Connected execution captures their exact snapshot in the execution-plan digest. Explicit injected registries are still ephemeral; only package declarations survive save/reopen. Guest access to arbitrary project context, generated adapter execution and automatic metered Chat derivation are separate integrations, not permissions granted by declaring a meaning.

Direct structured answers

The application's reviewed-answer dialogs collect required schema fields with typed controls, leaving optional fields unasked and preserving existing optional answers during edits. Unstructured objects offer named details with text, number, yes/no, nested-detail, list and empty-value choices. Object and JSON lists support adding, editing and removing items without requiring JSON syntax. Primitive schemas on JSON inputs choose the corresponding typed question.

These dialogs serve the existing lazy user resolver, shared-default editor and connected preview samples. They capture the contract and previous answer before waiting, validate the final value and return nothing on cancellation. Collection is bounded to 20 recursive questions, 60 menu choices, 20 detailed list items or object fields, and the existing 8,000-character scalar/simple-list limits. Larger answers still need the appropriate settings editor. Source permissions and credential restrictions remain enforced by the calling resolver; these controls do not create new runtime authority or automatically invoke Chat.

Single-Step and connected-run missing-answer collection use the same universal resolver for allowed defaults and user callbacks. A permitted default is selected before asking; it is not recorded as a user answer. Retained reviewed answers remain explicit replay inputs. Contract, supplied-input and retained-answer snapshots are captured before waiting, and callbacks cannot claim dependencies on unavailable context. Existing host scope checks still reject edits to the real project during collection. This does not enable automatic paid Chat calls.

Versioned document conversions

The shared connection registry includes csv-file-to-table@1, text-to-script@1 and script-to-text@1. Visual/native composition, explicit connection pins and semantic context resolution use the same descriptors.

CSV files must be single inline .csv files declared with the csv meaning; the result has the table meaning and {columns, rows} schema. Archives, remote media and malformed CSV are rejected. The existing CSV limits and string-preserving parser apply; cell contents are never executed.

Script conversions preserve semantic compatibility and exact words. Wrapping adds only {schemaVersion: 1, text}; unwrapping requires readable text and does not carry other script metadata into the text output. Neither conversion turns research notes into narration or invents additional required fields. Candidate checks validate actual values when present. Version pins, source policy, inherited permissions and provenance remain enforced. These are deterministic built-ins, not arbitrary multi-hop or creator-code adapters.

Conditional SDK Steps

Existing Step conditions support greater-than, at-least, less-than and at-most in addition to presence and equality comparisons. Numeric thresholds must be finite numbers; missing values, strings and booleans do not satisfy a numeric comparison. Safe field paths and existing default handling still apply. The builder and native set_condition control share setProjectTypeCondition; use null to remove a condition. Native Step inspection includes its condition.

These conditions retain the existing false-case behavior: pass the primary input unchanged to a single compatible output. They do not create general branches, invent outputs, enable hosted-workspace conditions or grant execution approval.

Reviewed Chat suggestions share canSuggestRequirement eligibility across the application and server. Supported information includes scalar text/numbers/ booleans, script documents, objects, JSON and their supported lists. Host-bound context, credential-sensitive inputs and inputs excluding Chat remain ineligible. The server captures the notes and requirement before waiting and validates the returned value before issuing matching provenance. This remains a reviewed suggestion, not automatic workflow dispatch or a budget authorization.

Saved-project source updates

Project Type connections use the Block's declared input and output contracts, including Blocks a creator adds later. A reviewed source change updates that project's binding and marks affected results stale; it does not run a Block. An explicit affected-Step update can then reuse a current saved upstream value. The runner pins that value before dispatch and records its producer placement, output port and run ID in the receiving run's captured input identities. The pin is checked again during execution, so a changed upstream result requires a fresh review. Text and structured input contents are not copied into this identity record; inspect the authorized value separately when needed.

Recommendation execution evidence

The hosted completion signal uses server-owned, terminal production capability runs for an exact public release digest over 30 days. It excludes creator self-use, suspended accounts, revoked releases, previews, cancellation and unresolved remote work. At least five terminal runs from three users are needed; each user contributes at most 20 recent runs per release. A smoothed completion adjustment between minus two and plus two points supplements, but cannot replace, capability coverage and connection validation. Creator-supplied quality numbers are not used.

This signal measures terminal execution completion, not generated-content quality, local execution reliability or resistance to coordinated account abuse. Missing evidence contributes no adjustment and does not mean failure. A measured completion rate below one half lowers ranking rather than earning a bonus; a rate of one half is neutral. The response reports signal availability and the number of measured releases. Cost, latency and creator reputation remain unmeasured ranking signals.

Visual recommendation Details explains these limits and measured-Block coverage. Native recommendation inspection includes the same signal availability and warnings, alongside per-proposal score explanations.

Guest workspace patch proposals

JavaScript Blocks can call StillMade.patchProject(outputKey, {field, title, after}) to emit a reviewed workspace-edit proposal. Declare a workspace-edit output, a matching context input, and both context.<field>.read and workspace.<field>.propose permissions. The helper obtains before from the original host-supplied context snapshot, not the guest's mutable input. It returns no value and uses the ordinary output collector: emit each output once and do not also return an output object.

This method does not apply an edit, save a project, grant permissions or call the host from the sandbox. Final outputs pass the existing workspace-edit and permission validators; the host's review and stale-document checks still decide whether a proposal can be applied. Only existing workspace-edit fields are supported, not arbitrary project fields or credentials. Guest Chat/user request bridges and broader project mutation remain separate unfinished integrations.

Bounded adapter paths

Creator-owned conversion Blocks

When two admitted Blocks declare incompatible inputs and outputs, the Project Type builder can search saved Blocks for a real intermediate Step. Find converter Blocks inspects each candidate's versioned ports and source policy; it does not run the candidate or infer that its result is correct. Choosing one embeds the exact package version and creates two ordinary typed connections. The connected runner executes the intermediate Block through its declared runtime and validates its output before the receiver runs. Saved-project Flow can search converter packages already embedded in that Project Type and review the migration before adding an instance. This route preserves each Block's own implementation and does not install a creator's transform in the trusted host.

The on-demand search discovers paths of up to three intermediate Blocks with bounded exploration. Longer routes can still be composed as ordinary Steps. New Marketplace package search from an existing project and full native/hosted acceptance are still required for general interoperability. A source preview in the search is never presented as a converter's unrun output.

Trusted resolver callers can opt into maxAdapterHops: 2 or 3. The default remains one for compatibility with existing saved connection pins. Registries expose findPaths(source, requirement, options) and applyPath([{id, version}, ...], source, requirement, options). Search uses contract compatibility without executing transforms, examines at most 512 edges and returns at most 16 paths. inspect reports searchTruncated when those limits prevent an exhaustive search.

Execution preflights the complete chain's permissions and contracts, validates each intermediate result, preserves the original source's freshness and returns provenance containing every conversion pin plus the original source revision. These are trusted registered adapters, not creator-code execution authority. Saving and executing chain pins in the visual/native application is not yet integrated; existing connection paths remain unchanged.