@ampcode/plugin 0.0.0-20261005002017-g4854873 → 0.0.0-20261007001957-g339d9e8

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 (3) hide show
  1. package/README.md +5 -0
  2. package/index.d.ts +166 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -13,6 +13,11 @@ Plugins can:
13
13
  - **Show UI** — `ctx.ui.notify(...)`, `ctx.ui.confirm(...)`, `ctx.ui.input(...)`, and `ctx.ui.select(...)`
14
14
  - **Use AI** — `amp.ai.ask(...)` for thread-scoped yes/no classification that defaults to no
15
15
  reasoning unless `{ reasoningEffort }` is set
16
+ - **Decide fast** — `amp.ai.decide(...)`, `amp.ai.choice(...)`, `amp.ai.noul(...)`, and
17
+ `amp.ai.score(...)` for typed decisions with calibrated probabilities and no generated text,
18
+ answered by a decision model (currently TypeSafe's Jev)
19
+ - **Label threads** — `ctx.thread.labels()`, `ctx.thread.addLabels(...)`, and
20
+ `ctx.thread.setLabels(...)` to read and change the current thread's labels
16
21
  - **Upload attachments** — `amp.attachments.upload(...)` to upload image bytes and get back a URL
17
22
  for URL-backed `{ type: 'image', mimeType, url }` tool result blocks, keeping large images out
18
23
  of thread state
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- // sitemap-lastmod: /docs/plugin-api 2026-09-01
1
+ // sitemap-lastmod: /docs/plugin-api 2026-10-06
2
2
 
3
3
  declare module '@ampcode/plugin' {
4
4
  /**
@@ -762,6 +762,109 @@ declare module '@ampcode/plugin' {
762
762
  schema: PluginAIObjectSchema
763
763
  }
764
764
 
765
+ /**
766
+ * Text or JSON accepted wherever a decision takes a state, instructions, or criteria. Objects
767
+ * and arrays are passed to the model as-is.
768
+ */
769
+ export type DecisionInput = string | Record<string, unknown> | unknown[]
770
+
771
+ /** Estimates whether a condition holds for the state. Answers with a probability from 0 to 1. */
772
+ export interface NoulQuestion {
773
+ type: 'noul'
774
+ instructions: DecisionInput
775
+ /** Optional descriptions of what makes the condition true or false. */
776
+ criteria?: { true?: DecisionInput; false?: DecisionInput }
777
+ }
778
+
779
+ /** Rates the state on an ordered scale. `criteria` lists 2–10 levels, lowest first. */
780
+ export interface ScoreQuestion {
781
+ type: 'score'
782
+ instructions: DecisionInput
783
+ criteria: DecisionInput[]
784
+ }
785
+
786
+ /** Chooses one of 2–20 options. `criteria` maps each option to a description or `null`. */
787
+ export interface ChoiceQuestion<Option extends string = string> {
788
+ type: 'choice'
789
+ instructions: DecisionInput
790
+ criteria: Record<Option, DecisionInput | null>
791
+ }
792
+
793
+ export type DecisionQuestion = NoulQuestion | ScoreQuestion | ChoiceQuestion
794
+
795
+ export interface NoulAnswer {
796
+ type: 'noul'
797
+ /** Probability from 0 to 1 that the condition holds. */
798
+ noul: number
799
+ }
800
+
801
+ export interface ScoreAnswer {
802
+ type: 'score'
803
+ /** Probability-weighted score across the levels, from 0 to the number of levels minus one. */
804
+ score: number
805
+ /** Level index (as a string) to the level description. */
806
+ legend: Record<string, string>
807
+ /** Probability of each level index. */
808
+ probabilities: Record<string, number>
809
+ /** Probability of the most likely level. */
810
+ confidence: number
811
+ }
812
+
813
+ export interface ChoiceAnswer<Option extends string = string> {
814
+ type: 'choice'
815
+ choice: Option
816
+ /** Probability of each option. */
817
+ probabilities: Record<Option, number>
818
+ /** Probability of `choice`. */
819
+ confidence: number
820
+ }
821
+
822
+ export type DecisionAnswer = NoulAnswer | ScoreAnswer | ChoiceAnswer
823
+
824
+ /** The answer type returned for a question of type `Q`. */
825
+ export type DecisionAnswerFor<Q extends DecisionQuestion> =
826
+ Q extends ChoiceQuestion<infer Option>
827
+ ? ChoiceAnswer<Option>
828
+ : Q extends ScoreQuestion
829
+ ? ScoreAnswer
830
+ : NoulAnswer
831
+
832
+ /** The state every decision is judged against, and the thread that routes the request. */
833
+ export interface DecisionOptions {
834
+ /** Thread to route the request through. Required outside a thread-bound handler. */
835
+ threadID?: ThreadID
836
+ /** The situation to judge: text, or JSON the model reads as-is. Up to 50,000 characters of text. */
837
+ state: DecisionInput
838
+ }
839
+
840
+ export interface DecisionRequest<
841
+ Q extends Record<string, DecisionQuestion> = Record<string, DecisionQuestion>,
842
+ > extends DecisionOptions {
843
+ /** 1–20 questions, each answered independently against `state`. */
844
+ questions: Q
845
+ }
846
+
847
+ export interface DecisionResult<
848
+ Q extends Record<string, DecisionQuestion> = Record<string, DecisionQuestion>,
849
+ > {
850
+ /**
851
+ * The decision model that answered, such as `jev-1.13.0`. Amp picks the model; record it when
852
+ * you tune thresholds so a model change is visible.
853
+ */
854
+ model: string
855
+ answers: { [K in keyof Q]: DecisionAnswerFor<Q[K]> }
856
+ }
857
+
858
+ /** A single {@link ChoiceQuestion} with its state. */
859
+ export interface ChoiceRequest<Option extends string = string>
860
+ extends DecisionOptions, Omit<ChoiceQuestion<Option>, 'type'> {}
861
+
862
+ /** A single {@link NoulQuestion} with its state. */
863
+ export interface NoulRequest extends DecisionOptions, Omit<NoulQuestion, 'type'> {}
864
+
865
+ /** A single {@link ScoreQuestion} with its state. */
866
+ export interface ScoreRequest extends DecisionOptions, Omit<ScoreQuestion, 'type'> {}
867
+
765
868
  /**
766
869
  * AI capabilities provided to plugins.
767
870
  */
@@ -793,6 +896,47 @@ declare module '@ampcode/plugin' {
793
896
  * @returns Object with result, probability, and reason
794
897
  */
795
898
  ask(question: string, options?: PluginAIAskOptions): Promise<PluginAIAskResult>
899
+
900
+ /**
901
+ * Ask a decision model typed questions about a state. A decision model does not generate
902
+ * text: each answer is a choice, a score, or a yes/no probability (`noul`) with calibrated
903
+ * probabilities, in well under a second and at a small fraction of the cost of
904
+ * {@link PluginAI.generate}. Use it for routing, triage, relevance, and policy checks where
905
+ * the application owns the thresholds and control flow; use {@link PluginAI.generate} when
906
+ * the answer needs reasoning or prose.
907
+ *
908
+ * All questions in one call are answered against the same `state` in one round trip. The
909
+ * answer type of each question is inferred from the request, so `result.answers.route.choice`
910
+ * is typed as the option names you passed. The typed shape is guaranteed; the answer can
911
+ * still be wrong, and adversarial text inside `state` can move it.
912
+ *
913
+ * Amp chooses the underlying model (currently TypeSafe's Jev) and may change it;
914
+ * {@link DecisionResult.model} reports which one answered.
915
+ *
916
+ * Calls are routed through the current thread. Pass `threadID` when calling outside a
917
+ * thread-bound handler.
918
+ */
919
+ decide<Q extends Record<string, DecisionQuestion>>(
920
+ request: DecisionRequest<Q>,
921
+ ): Promise<DecisionResult<Q>>
922
+
923
+ /**
924
+ * Choose one of 2–20 options for a state. Shorthand for {@link PluginAI.decide} with one
925
+ * `choice` question; `answer.choice` is typed as the keys of `criteria`.
926
+ */
927
+ choice<Option extends string>(request: ChoiceRequest<Option>): Promise<ChoiceAnswer<Option>>
928
+
929
+ /**
930
+ * Estimate the probability that a condition holds for a state. Shorthand for
931
+ * {@link PluginAI.decide} with one `noul` question.
932
+ */
933
+ noul(request: NoulRequest): Promise<NoulAnswer>
934
+
935
+ /**
936
+ * Rate a state on an ordered scale of 2–10 levels. Shorthand for {@link PluginAI.decide} with
937
+ * one `score` question.
938
+ */
939
+ score(request: ScoreRequest): Promise<ScoreAnswer>
796
940
  }
797
941
 
798
942
  /**
@@ -1238,6 +1382,27 @@ declare module '@ampcode/plugin' {
1238
1382
  */
1239
1383
  setMultiplayer(options: { ttlSeconds: number | null }): Promise<void>
1240
1384
 
1385
+ /**
1386
+ * Read the thread's labels, sorted alphabetically.
1387
+ */
1388
+ labels(): Promise<string[]>
1389
+
1390
+ /**
1391
+ * Replace the thread's labels and resolve with the resulting labels.
1392
+ *
1393
+ * Labels are lowercased and deduplicated. Each label must be alphanumeric
1394
+ * with hyphens, start with an alphanumeric character, and be at most 32
1395
+ * characters long. A thread holds at most 20 labels. The authenticated user
1396
+ * must be allowed to manage the thread.
1397
+ */
1398
+ setLabels(labels: string[]): Promise<string[]>
1399
+
1400
+ /**
1401
+ * Add labels to the thread, keeping its existing labels, and resolve with
1402
+ * the resulting labels. Same label rules as {@link setLabels}.
1403
+ */
1404
+ addLabels(labels: string[]): Promise<string[]>
1405
+
1241
1406
  /**
1242
1407
  * Read messages from the thread in a stable plugin-facing schema.
1243
1408
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ampcode/plugin",
3
- "version": "0.0.0-20261005002017-g4854873",
3
+ "version": "0.0.0-20261007001957-g339d9e8",
4
4
  "description": "Amp Plugin API",
5
5
  "homepage": "https://ampcode.com/docs/plugin-api",
6
6
  "author": {