Cortex · CHANGELOG.md

This is CHANGELOG.md as @niscorp/cortex 0.1.4 ships it. A coding agent reads it from node_modules. The file itself:

nisc.dev/cortex/CHANGELOG.md

@niscorp/cortex

0.1.4

Patch Changes

  • 1dcccd7: An envelope with a misspelt key is no longer accepted as the agent's data.

    A model may send the payload alone, without { response, data, reasoning } around it, and cortex reads it as the data when it passes the agent's schema. A schema that takes any object passed everything: under z.record(z.string(), z.unknown()) the answer { respnse: 'Done.', data: { id: 7 } } came back as the data, whole, and under an object schema whose fields are all optional it came back as {}. The run finished with the wrong data and no correction.

    The payload alone is now read only when the schema can tell it from an envelope, which is when the schema refuses an object that holds one unknown key. Under any other schema an unknown key is reported to the model, as it is for an agent with no data schema.

    What to change: nothing. An agent whose data schema takes any object (a record, or an object with only optional fields) and whose model sends the payload alone now spends one correction round on it. Prism's mapping agent is one such agent, because any JSON object is a Prism config. A required field in the schema, or z.strictObject, keeps the payload-alone reading.

  • a4ccf0e: The README states thirteen facts about the API that were written only in source comments, and DESIGN.md gives the condition for reading a bare payload.

    The README now says what meta.usage.reported means, what repeatedCalls(n) counts (n + 1 identical calls), that prepareStep's activeTools takes tool names, what transport: 'step' does, the order hooks and gates run in, who receives run-start, that output-partial is best-effort, the three kinds of retry, what a resumed run keeps, the reason on an approval that timed out, how a hand-written delegating tool nests its child's events, and how estimatedTokens is counted.

    No behaviour changed.

    What to change: nothing.

0.1.3

Patch Changes

  • 2756aa7: run.abort(reason) keeps its reason: it is the cause of the aborted result.

    RunHandle.abort is typed (reason?: string) => void and the reason was dropped — it was not on the result, on any event, or anywhere a caller could read it back.

    A run stopped by run.abort('the member closed the tab') now settles with error.cause: 'the member closed the tab', on run.result and on the result the run-end event carries. error.code (aborted) and error.message are unchanged, and run.abort() with no reason gives the result it always gave, with no cause.

    The reason is kept beside the run's signal and never put on it: a tool's ctx.signal still aborts with an AbortError, so a tool — or a fetch it started — that tells an abort by that error sees one as before. A run stopped through the caller's own options.signal is unchanged too; what that signal was aborted with is not read.

    What to change: nothing. If you already pass a reason to run.abort, the aborted result now carries it as error.cause.

  • 0b5a7d6: README and DESIGN describe the loop as it runs. A turn of prose with no envelope in it is corrected without counting against outputRetries, so stepCount is what ends a model that keeps writing prose, and a stopWhen you pass replaces the defaults; outputRetries(n) means n attempts and n − 1 corrections. An invalid answer gets the attempt and a system message appended, not a tool error. A respond sent beside other tool calls is dropped, and output streamed by a step that ends in tool calls is not the answer. Through Signal a call to a tool the agent does not have is read as an attempted answer, so tool-end kind unknown-tool is rare. policy.tools lists take tool ids, not the names the model calls. A tool's output schema types what execute returns and is not applied at runtime. No code changed.

    What to change: nothing for this release. A policy.tools entry written with a tool's name, where its id differs, has never matched: write the id.

  • 4abbfcc: The README says what a tool's input schema may be. The model is sent its JSON Schema, taken from the schema's output side, and a call's arguments are parsed with it twice: by the loop, then again in front of execute. So an input schema validates and does not convert:

    • One with no JSON Schema (a .transform(), a z.date()) fails the run before the model is asked, with code: 'unknown' and Zod's message.
    • One whose output is another kind than its input (z.stringbool()) is described to the model by its output and then refuses what its own first parse produced: the tool never runs.
    • One that changes a value (.overwrite()) changes it twice, while the observation's args hold the value as parsed once.

    Convert inside execute. The README says this under "Errors", and tests hold it. No code changed.

    What to change: nothing.

  • a02a031: The README and DESIGN say which approval id a resumed run answers to. No code changed.

    resumeRun re-asks a pending approval: the resumed run's gates run again for the pending call, and approval-required fires again with a new id. DESIGN called the id "stable" and the README said approvals survive restarts, which read as if the id in the snapshot could be answered on the resumed run. It cannot: resumed.approve(snapshot.pending.approvalId) does nothing — an id a handle did not ask under is ignored — and with no policy.approvalTimeoutMs the run then waits.

    Both documents now say so: answer with the id of the resumed run's own approval-required event, as the README's example already does; snapshot.pending.approvalId names the ask of the run the snapshot was taken from. DESIGN also says that when the gates no longer ask on resume, the pending call simply runs. A test holds the re-ask and its new id.

    What to change: nothing if you answer from the approval-required event. If you kept snapshot.pending.approvalId to answer with after resumeRun, answer with the id of the resumed run's event instead.

  • Updated dependencies [5923e38]

  • Updated dependencies [2815107]

  • Updated dependencies [885bc1e]

  • Updated dependencies [f9f1b26]

  • Updated dependencies [e3e0ff2]

  • Updated dependencies [ed9d7f4]

0.1.2

Patch Changes

  • 06d1531: The README's first run says why it failed. Its install line now names openai, the SDK Signal loads when a model on Groq, OpenAI or OpenRouter is called: without it the quick example's run failed with Missing dependency: openai. And the example prints the reason when a run fails (else console.error(result.error.message)): a failed run returns its reason and does not throw, so with no API key set the example ended in silence, exit code 0. No code changed.

    What to change: nothing.

  • fe30458: Every package exports its package.json, so an app can say which version of a package it runs by reading it from the package:

    import prism from '@niscorp/prism/package.json' with { type: 'json' };
    prism.version; // the version that is installed, not the range that asked for it
    

    Until now the exports map hid it, and the only way to the version was a path into node_modules. check:packages installs the tarballs and reads every package's version this way.

    What to change: nothing. An app that read a version by path can read it by name.

  • Updated dependencies [fe30458]

0.1.1

Patch Changes

  • b67a125: Documentation only: each package's README, reference and design docs checked against its source and corrected — install lines and peers, signatures, defaults, status codes, licenses (loom, signal: Apache-2.0), and API that existed but was not documented.