@appmind/core 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/actions.d.ts +40 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +32 -0
- package/dist/actions.js.map +1 -0
- package/dist/appmind.d.ts +112 -0
- package/dist/appmind.d.ts.map +1 -0
- package/dist/appmind.js +311 -0
- package/dist/appmind.js.map +1 -0
- package/dist/context.d.ts +36 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +91 -0
- package/dist/context.js.map +1 -0
- package/dist/events.d.ts +41 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +28 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/model.d.ts +44 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +3 -0
- package/dist/model.js.map +1 -0
- package/dist/runtime.d.ts +45 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +113 -0
- package/dist/runtime.js.map +1 -0
- package/dist/storage.d.ts +22 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +21 -0
- package/dist/storage.js.map +1 -0
- package/package.json +28 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AppMind contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @appmind/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AppMind core runtime: agent orchestration, UI context, action registry, and provider interfaces.
|
|
4
|
+
|
|
5
|
+
Part of [AppMind](https://github.com/dmitripoli/appmind) — a local-first, drop-in AI copilot for web apps. See the main README for setup and concepts.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @appmind/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
License: MIT
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AppMindContext } from "./context.js";
|
|
2
|
+
export type ActionRisk = "read" | "low" | "medium" | "high";
|
|
3
|
+
/**
|
|
4
|
+
* An operation the application explicitly exposes to the AI (PRD §32–34).
|
|
5
|
+
* The model may only ever request registered actions; it can never execute
|
|
6
|
+
* application code directly.
|
|
7
|
+
*/
|
|
8
|
+
export interface AppMindAction<TInput = unknown, TResult = unknown> {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
/**
|
|
12
|
+
* A JSON-schema-like description of the parameters. Bring your own validator
|
|
13
|
+
* (e.g. a zod schema exposes `.parse`); AppMind treats it as opaque here and
|
|
14
|
+
* only requires the shape to be describable to the model.
|
|
15
|
+
*/
|
|
16
|
+
parameters?: unknown;
|
|
17
|
+
risk?: ActionRisk;
|
|
18
|
+
requiresConfirmation?: boolean;
|
|
19
|
+
/** Hide the action from the model when it isn't applicable to the context. */
|
|
20
|
+
isAvailable?: (context: AppMindContext) => boolean;
|
|
21
|
+
execute: (input: TInput, context: AppMindContext) => Promise<TResult>;
|
|
22
|
+
}
|
|
23
|
+
/** A validated, model-requested action awaiting execution/confirmation. */
|
|
24
|
+
export interface PendingAction {
|
|
25
|
+
name: string;
|
|
26
|
+
input: unknown;
|
|
27
|
+
risk: ActionRisk;
|
|
28
|
+
requiresConfirmation: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare class ActionRegistry {
|
|
31
|
+
private actions;
|
|
32
|
+
register(action: AppMindAction<any, any>): () => void;
|
|
33
|
+
unregister(name: string): void;
|
|
34
|
+
get(name: string): AppMindAction<any, any> | undefined;
|
|
35
|
+
/** Only the actions currently applicable to the context (PRD §37). */
|
|
36
|
+
available(context: AppMindContext): AppMindAction<any, any>[];
|
|
37
|
+
/** Confirmation policy: destructive/high-risk always confirms (PRD §34–35). */
|
|
38
|
+
static needsConfirmation(action: AppMindAction<any, any>): boolean;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5D;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IACnD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA8C;IAE7D,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,MAAM,IAAI;IAUrD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS;IAItD,sEAAsE;IACtE,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;IAI7D,+EAA+E;IAC/E,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,OAAO;CAInE"}
|
package/dist/actions.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export class ActionRegistry {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.actions = new Map();
|
|
4
|
+
}
|
|
5
|
+
register(action) {
|
|
6
|
+
this.actions.set(action.name, action);
|
|
7
|
+
// Only remove what *this* call registered: a stale disposer (e.g. React
|
|
8
|
+
// StrictMode's discarded first effect, or an MCP connection torn down after
|
|
9
|
+
// a reconnect) must not delete a newer registration under the same name.
|
|
10
|
+
return () => {
|
|
11
|
+
if (this.actions.get(action.name) === action)
|
|
12
|
+
this.actions.delete(action.name);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
unregister(name) {
|
|
16
|
+
this.actions.delete(name);
|
|
17
|
+
}
|
|
18
|
+
get(name) {
|
|
19
|
+
return this.actions.get(name);
|
|
20
|
+
}
|
|
21
|
+
/** Only the actions currently applicable to the context (PRD §37). */
|
|
22
|
+
available(context) {
|
|
23
|
+
return [...this.actions.values()].filter((a) => !a.isAvailable || a.isAvailable(context));
|
|
24
|
+
}
|
|
25
|
+
/** Confirmation policy: destructive/high-risk always confirms (PRD §34–35). */
|
|
26
|
+
static needsConfirmation(action) {
|
|
27
|
+
if (action.requiresConfirmation !== undefined)
|
|
28
|
+
return action.requiresConfirmation;
|
|
29
|
+
return action.risk === "high" || action.risk === "medium";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAiCA,MAAM,OAAO,cAAc;IAA3B;QACU,YAAO,GAAG,IAAI,GAAG,EAAmC,CAAC;IA8B/D,CAAC;IA5BC,QAAQ,CAAC,MAA+B;QACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,wEAAwE;QACxE,4EAA4E;QAC5E,yEAAyE;QACzE,OAAO,GAAG,EAAE;YACV,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,MAAM;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjF,CAAC,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,sEAAsE;IACtE,SAAS,CAAC,OAAuB;QAC/B,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,+EAA+E;IAC/E,MAAM,CAAC,iBAAiB,CAAC,MAA+B;QACtD,IAAI,MAAM,CAAC,oBAAoB,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC,oBAAoB,CAAC;QAClF,OAAO,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC;IAC5D,CAAC;CACF"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { type Embedder, type KnowledgeIndex, type RetrievalResult, type RetrievalWeights } from "@appmind/knowledge";
|
|
2
|
+
import { type AppMindAction, type PendingAction } from "./actions.js";
|
|
3
|
+
import { type AppMindContext } from "./context.js";
|
|
4
|
+
import { type AppMindEvents, type EventName } from "./events.js";
|
|
5
|
+
import type { AppMindModelProvider, ChatMessage, ModelLocation } from "./model.js";
|
|
6
|
+
import { type AppMindStorage } from "./storage.js";
|
|
7
|
+
import { type PromptBudget } from "./runtime.js";
|
|
8
|
+
export interface AppMindConfig {
|
|
9
|
+
knowledge: {
|
|
10
|
+
manifest: string;
|
|
11
|
+
index?: never;
|
|
12
|
+
} | {
|
|
13
|
+
index: KnowledgeIndex;
|
|
14
|
+
manifest?: never;
|
|
15
|
+
};
|
|
16
|
+
model?: AppMindModelProvider;
|
|
17
|
+
storage?: AppMindStorage;
|
|
18
|
+
/**
|
|
19
|
+
* Query embedder. If omitted, one is derived from the loaded manifest's
|
|
20
|
+
* `embeddingModel` so the runtime query vectors automatically match the index.
|
|
21
|
+
*/
|
|
22
|
+
embedder?: Embedder;
|
|
23
|
+
retrieval?: {
|
|
24
|
+
topK?: number;
|
|
25
|
+
weights?: Partial<RetrievalWeights>;
|
|
26
|
+
};
|
|
27
|
+
/** Prompt token budget (defaults target a small ~4K-context local model). */
|
|
28
|
+
prompt?: Partial<PromptBudget>;
|
|
29
|
+
/**
|
|
30
|
+
* Called before executing an action that requires confirmation (PRD §35).
|
|
31
|
+
* Must resolve true to proceed. If omitted, confirmation-required actions are
|
|
32
|
+
* denied by default (fail closed).
|
|
33
|
+
*/
|
|
34
|
+
onConfirm?: (pending: PendingAction) => Promise<boolean>;
|
|
35
|
+
/** How to fetch remote resources (manifest/index). Defaults to global fetch. */
|
|
36
|
+
fetch?: typeof fetch;
|
|
37
|
+
}
|
|
38
|
+
/** High-level events streamed from a chat turn. */
|
|
39
|
+
export type ChatEvent = {
|
|
40
|
+
type: "sources";
|
|
41
|
+
sources: RetrievalResult[];
|
|
42
|
+
} | {
|
|
43
|
+
type: "text";
|
|
44
|
+
delta: string;
|
|
45
|
+
} | {
|
|
46
|
+
type: "action_pending";
|
|
47
|
+
action: PendingAction;
|
|
48
|
+
} | {
|
|
49
|
+
type: "action_result";
|
|
50
|
+
name: string;
|
|
51
|
+
ok: boolean;
|
|
52
|
+
result?: unknown;
|
|
53
|
+
error?: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: "location";
|
|
56
|
+
location: ModelLocation;
|
|
57
|
+
} | {
|
|
58
|
+
type: "done";
|
|
59
|
+
} | {
|
|
60
|
+
type: "error";
|
|
61
|
+
error: string;
|
|
62
|
+
};
|
|
63
|
+
export interface ChatOptions {
|
|
64
|
+
history?: ChatMessage[];
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}
|
|
67
|
+
export declare class AppMind {
|
|
68
|
+
private readonly config;
|
|
69
|
+
private readonly ctx;
|
|
70
|
+
private readonly registry;
|
|
71
|
+
private readonly emitter;
|
|
72
|
+
private readonly storage;
|
|
73
|
+
private readonly fetchFn;
|
|
74
|
+
private index;
|
|
75
|
+
private embedder;
|
|
76
|
+
private started;
|
|
77
|
+
private confirmHandler;
|
|
78
|
+
constructor(config: AppMindConfig);
|
|
79
|
+
/**
|
|
80
|
+
* Set/replace the confirmation handler at runtime. The React provider uses
|
|
81
|
+
* this to drive its confirmation UI. Returns a disposer that restores the
|
|
82
|
+
* previous handler.
|
|
83
|
+
*/
|
|
84
|
+
setConfirmationHandler(handler: (pending: PendingAction) => Promise<boolean>): () => void;
|
|
85
|
+
/** Load the knowledge index (from cache or CDN) and initialize the model. */
|
|
86
|
+
start(): Promise<void>;
|
|
87
|
+
setContext(context: AppMindContext): void;
|
|
88
|
+
mergeContext(patch: Partial<AppMindContext>): void;
|
|
89
|
+
getContext(): AppMindContext;
|
|
90
|
+
registerAction<TInput, TResult>(action: AppMindAction<TInput, TResult>): () => void;
|
|
91
|
+
search(query: string, options?: {
|
|
92
|
+
limit?: number;
|
|
93
|
+
}): Promise<RetrievalResult[]>;
|
|
94
|
+
chat(message: string, options?: ChatOptions): AsyncIterable<ChatEvent>;
|
|
95
|
+
/**
|
|
96
|
+
* One follow-up generation that answers the user from an action's result.
|
|
97
|
+
* No tools are offered (and any tool call is ignored), so it can't loop. The
|
|
98
|
+
* result goes in as a plain user-role message — portable across providers
|
|
99
|
+
* that lack native tool-result messages.
|
|
100
|
+
*/
|
|
101
|
+
private answerFromResult;
|
|
102
|
+
private runAction;
|
|
103
|
+
/** Which engine the next chat turn will use (PRD §54 privacy API). */
|
|
104
|
+
modelLocation(): ModelLocation | undefined;
|
|
105
|
+
connectMCP(_config: {
|
|
106
|
+
endpoint: string;
|
|
107
|
+
}): never;
|
|
108
|
+
on<K extends EventName>(name: K, handler: (payload: AppMindEvents[K]) => void): () => void;
|
|
109
|
+
dispose(): Promise<void>;
|
|
110
|
+
private loadIndex;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=appmind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appmind.d.ts","sourceRoot":"","sources":["../src/appmind.ts"],"names":[],"mappings":"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"}
|
package/dist/appmind.js
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { assertEmbedderCompatible, createEmbedder, CURRENT_INDEX_SCHEMA, retrieve, } from "@appmind/knowledge";
|
|
2
|
+
import { ActionRegistry } from "./actions.js";
|
|
3
|
+
import { ContextStore } from "./context.js";
|
|
4
|
+
import { Emitter } from "./events.js";
|
|
5
|
+
import { MemoryStorage } from "./storage.js";
|
|
6
|
+
import { buildSystemPrompt, DEFAULT_PROMPT_BUDGET, estimateTokens, parseToolCallFromText, toToolSpecs, windowHistory, } from "./runtime.js";
|
|
7
|
+
export class AppMind {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.ctx = new ContextStore();
|
|
10
|
+
this.registry = new ActionRegistry();
|
|
11
|
+
this.emitter = new Emitter();
|
|
12
|
+
this.started = false;
|
|
13
|
+
this.config = config;
|
|
14
|
+
this.storage = config.storage ?? new MemoryStorage();
|
|
15
|
+
// Wrap (don't reference) the global fetch: a bare `globalThis.fetch` called
|
|
16
|
+
// as a method throws "Illegal invocation" because it loses its Window `this`.
|
|
17
|
+
this.fetchFn = config.fetch ?? ((input, init) => globalThis.fetch(input, init));
|
|
18
|
+
this.confirmHandler = config.onConfirm;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Set/replace the confirmation handler at runtime. The React provider uses
|
|
22
|
+
* this to drive its confirmation UI. Returns a disposer that restores the
|
|
23
|
+
* previous handler.
|
|
24
|
+
*/
|
|
25
|
+
setConfirmationHandler(handler) {
|
|
26
|
+
const prev = this.confirmHandler;
|
|
27
|
+
this.confirmHandler = handler;
|
|
28
|
+
return () => {
|
|
29
|
+
this.confirmHandler = prev;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Load the knowledge index (from cache or CDN) and initialize the model. */
|
|
33
|
+
async start() {
|
|
34
|
+
if (this.started)
|
|
35
|
+
return;
|
|
36
|
+
this.index = await this.loadIndex();
|
|
37
|
+
// Guard against an index format this runtime can't read (PRD §25).
|
|
38
|
+
const schema = this.index.manifest.schemaVersion ?? 1;
|
|
39
|
+
if (schema > CURRENT_INDEX_SCHEMA) {
|
|
40
|
+
throw new Error(`AppMind index schema v${schema} is newer than this runtime supports (v${CURRENT_INDEX_SCHEMA}). Upgrade @appmind/core.`);
|
|
41
|
+
}
|
|
42
|
+
// Derive the query embedder from the manifest unless the app supplied one,
|
|
43
|
+
// guaranteeing the query vector space matches the index's document vectors.
|
|
44
|
+
this.embedder =
|
|
45
|
+
this.config.embedder ??
|
|
46
|
+
createEmbedder({
|
|
47
|
+
id: this.index.manifest.embeddingModel,
|
|
48
|
+
dimensions: this.index.manifest.dimensions,
|
|
49
|
+
});
|
|
50
|
+
// Fail closed if a supplied embedder doesn't match the index's vector space.
|
|
51
|
+
assertEmbedderCompatible(this.index.manifest, this.embedder);
|
|
52
|
+
if (this.config.model) {
|
|
53
|
+
this.emitter.emit("model_loading", { provider: this.config.model.id });
|
|
54
|
+
await this.config.model.initialize();
|
|
55
|
+
this.emitter.emit("model_ready", {
|
|
56
|
+
provider: this.config.model.id,
|
|
57
|
+
location: this.config.model.location(),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
this.started = true;
|
|
61
|
+
this.emitter.emit("initialized", undefined);
|
|
62
|
+
}
|
|
63
|
+
// --- Context (PRD §29) ---
|
|
64
|
+
setContext(context) {
|
|
65
|
+
this.ctx.set(context);
|
|
66
|
+
}
|
|
67
|
+
mergeContext(patch) {
|
|
68
|
+
this.ctx.merge(patch);
|
|
69
|
+
}
|
|
70
|
+
getContext() {
|
|
71
|
+
return this.ctx.get();
|
|
72
|
+
}
|
|
73
|
+
// --- Actions (PRD §32) ---
|
|
74
|
+
registerAction(action) {
|
|
75
|
+
return this.registry.register(action);
|
|
76
|
+
}
|
|
77
|
+
// --- Knowledge search (PRD §28) ---
|
|
78
|
+
async search(query, options = {}) {
|
|
79
|
+
if (!this.index || !this.embedder)
|
|
80
|
+
throw new Error("AppMind not started: call start() first.");
|
|
81
|
+
const started = now();
|
|
82
|
+
const queryEmbedding = await this.embedder.embed(query);
|
|
83
|
+
const results = retrieve(queryEmbedding, query, this.index.chunks, {
|
|
84
|
+
limit: options.limit ?? this.config.retrieval?.topK ?? 5,
|
|
85
|
+
weights: this.config.retrieval?.weights,
|
|
86
|
+
context: {
|
|
87
|
+
route: this.ctx.get().route,
|
|
88
|
+
resourceType: this.ctx.get().resource?.type,
|
|
89
|
+
keywords: this.ctx.keywords(),
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
this.emitter.emit("retrieval", { count: results.length, latencyMs: now() - started });
|
|
93
|
+
return results;
|
|
94
|
+
}
|
|
95
|
+
// --- Chat / agent runtime (PRD §39) ---
|
|
96
|
+
async *chat(message, options = {}) {
|
|
97
|
+
if (!this.config.model) {
|
|
98
|
+
yield { type: "error", error: "No model provider configured." };
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!this.index) {
|
|
102
|
+
yield { type: "error", error: "AppMind not started: call start() first." };
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.emitter.emit("query", { text: message });
|
|
106
|
+
// 1. Retrieve relevant knowledge + expose only applicable actions.
|
|
107
|
+
const sources = await this.search(message, {
|
|
108
|
+
limit: this.config.retrieval?.topK ?? 5,
|
|
109
|
+
});
|
|
110
|
+
yield { type: "sources", sources };
|
|
111
|
+
const actions = this.registry.available(this.ctx.get());
|
|
112
|
+
// Budget the prompt: window history, then fill knowledge with the remainder.
|
|
113
|
+
const budget = { ...DEFAULT_PROMPT_BUDGET, ...this.config.prompt };
|
|
114
|
+
const history = windowHistory(options.history ?? [], budget.maxHistoryTurns);
|
|
115
|
+
const usedTokens = estimateTokens(message) + history.reduce((s, m) => s + estimateTokens(m.content), 0);
|
|
116
|
+
const system = buildSystemPrompt(this.ctx.toPromptBlock(), sources, actions, {
|
|
117
|
+
budget: this.config.prompt,
|
|
118
|
+
usedTokens,
|
|
119
|
+
});
|
|
120
|
+
const model = this.config.model;
|
|
121
|
+
yield { type: "location", location: model.location() };
|
|
122
|
+
this.emitter.emit("generation", { location: model.location() });
|
|
123
|
+
// 2. Generate. Accumulate text to detect text-encoded tool calls.
|
|
124
|
+
let fullText = "";
|
|
125
|
+
let structuredTool;
|
|
126
|
+
try {
|
|
127
|
+
for await (const ev of model.generate({
|
|
128
|
+
system,
|
|
129
|
+
messages: [...history, { role: "user", content: message }],
|
|
130
|
+
tools: toToolSpecs(actions),
|
|
131
|
+
signal: options.signal,
|
|
132
|
+
})) {
|
|
133
|
+
if (ev.type === "text") {
|
|
134
|
+
fullText += ev.delta;
|
|
135
|
+
yield { type: "text", delta: ev.delta };
|
|
136
|
+
}
|
|
137
|
+
else if (ev.type === "tool_call") {
|
|
138
|
+
structuredTool = { name: ev.name, arguments: ev.arguments };
|
|
139
|
+
}
|
|
140
|
+
else if (ev.type === "error") {
|
|
141
|
+
this.emitter.emit("error", { error: ev.error });
|
|
142
|
+
yield { type: "error", error: ev.error };
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
149
|
+
this.emitter.emit("error", { error });
|
|
150
|
+
yield { type: "error", error };
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// 3. Resolve a tool call. A structured tool_call is trusted; a tool call
|
|
154
|
+
// merely parsed out of the text is honored ONLY when it names a real
|
|
155
|
+
// registered action — otherwise it's a hallucination and we keep the
|
|
156
|
+
// model's text as the answer.
|
|
157
|
+
let toolCall = structuredTool;
|
|
158
|
+
if (!toolCall) {
|
|
159
|
+
const parsed = parseToolCallFromText(fullText);
|
|
160
|
+
if (parsed && this.registry.get(parsed.name))
|
|
161
|
+
toolCall = parsed;
|
|
162
|
+
}
|
|
163
|
+
if (toolCall) {
|
|
164
|
+
let result;
|
|
165
|
+
for await (const ev of this.runAction(toolCall.name, toolCall.arguments)) {
|
|
166
|
+
if (ev.type === "action_result")
|
|
167
|
+
result = ev;
|
|
168
|
+
yield ev;
|
|
169
|
+
}
|
|
170
|
+
// 4. Hand a successful result back to the model for one answer turn, so
|
|
171
|
+
// "what's the ARV?" ends with the number, not just "✓ completed".
|
|
172
|
+
if (result?.ok) {
|
|
173
|
+
yield* this.answerFromResult(model, system, [...history, { role: "user", content: message }], toolCall, result.result, options.signal);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
yield { type: "done" };
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* One follow-up generation that answers the user from an action's result.
|
|
180
|
+
* No tools are offered (and any tool call is ignored), so it can't loop. The
|
|
181
|
+
* result goes in as a plain user-role message — portable across providers
|
|
182
|
+
* that lack native tool-result messages.
|
|
183
|
+
*/
|
|
184
|
+
async *answerFromResult(model, system, messages, call, result, signal) {
|
|
185
|
+
const serialized = truncate(typeof result === "string" ? result : JSON.stringify(result ?? null), MAX_RESULT_CHARS);
|
|
186
|
+
let first = true;
|
|
187
|
+
try {
|
|
188
|
+
for await (const ev of model.generate({
|
|
189
|
+
system,
|
|
190
|
+
messages: [
|
|
191
|
+
...messages,
|
|
192
|
+
{ role: "assistant", content: `Called ${call.name} with ${JSON.stringify(call.arguments ?? {})}.` },
|
|
193
|
+
{
|
|
194
|
+
role: "user",
|
|
195
|
+
content: `Result of ${call.name}:\n${serialized}\n\n` +
|
|
196
|
+
"Answer my previous question using this result. Do not call any action.",
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
tools: [],
|
|
200
|
+
signal,
|
|
201
|
+
})) {
|
|
202
|
+
if (ev.type === "text") {
|
|
203
|
+
yield { type: "text", delta: first ? `\n\n${ev.delta.trimStart()}` : ev.delta };
|
|
204
|
+
first = false;
|
|
205
|
+
}
|
|
206
|
+
else if (ev.type === "error") {
|
|
207
|
+
this.emitter.emit("error", { error: ev.error });
|
|
208
|
+
return; // the action already succeeded; a missing summary isn't fatal
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
this.emitter.emit("error", { error: err instanceof Error ? err.message : String(err) });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async *runAction(name, input) {
|
|
217
|
+
const action = this.registry.get(name);
|
|
218
|
+
if (!action) {
|
|
219
|
+
// Hallucinated action — reject silently at the model, surface to app (PRD §65).
|
|
220
|
+
yield { type: "action_result", name, ok: false, error: `Unknown action: ${name}` };
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (action.isAvailable && !action.isAvailable(this.ctx.get())) {
|
|
224
|
+
yield { type: "action_result", name, ok: false, error: "Action not available in context." };
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const pending = {
|
|
228
|
+
name,
|
|
229
|
+
input,
|
|
230
|
+
risk: action.risk ?? "low",
|
|
231
|
+
requiresConfirmation: ActionRegistry.needsConfirmation(action),
|
|
232
|
+
};
|
|
233
|
+
this.emitter.emit("action_proposed", { name });
|
|
234
|
+
if (pending.requiresConfirmation) {
|
|
235
|
+
yield { type: "action_pending", action: pending };
|
|
236
|
+
const approved = this.confirmHandler ? await this.confirmHandler(pending) : false;
|
|
237
|
+
if (!approved) {
|
|
238
|
+
yield { type: "action_result", name, ok: false, error: "Not confirmed." };
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
this.emitter.emit("action_confirmed", { name });
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const result = await action.execute(input, this.ctx.get());
|
|
245
|
+
this.emitter.emit("action_executed", { name, ok: true });
|
|
246
|
+
yield { type: "action_result", name, ok: true, result };
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
250
|
+
this.emitter.emit("action_executed", { name, ok: false });
|
|
251
|
+
yield { type: "action_result", name, ok: false, error };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/** Which engine the next chat turn will use (PRD §54 privacy API). */
|
|
255
|
+
modelLocation() {
|
|
256
|
+
return this.config.model?.location();
|
|
257
|
+
}
|
|
258
|
+
connectMCP(_config) {
|
|
259
|
+
// MCP lives in the opt-in @appmind/mcp package to keep core dependency-free
|
|
260
|
+
// (PRD §38). It normalizes MCP tools into this action registry via the public
|
|
261
|
+
// registerAction() API.
|
|
262
|
+
throw new Error('MCP is provided by @appmind/mcp — call `connectMcp(mind, { endpoint })` from that package instead of mind.connectMCP().');
|
|
263
|
+
}
|
|
264
|
+
on(name, handler) {
|
|
265
|
+
return this.emitter.on(name, handler);
|
|
266
|
+
}
|
|
267
|
+
async dispose() {
|
|
268
|
+
await this.config.model?.dispose();
|
|
269
|
+
this.started = false;
|
|
270
|
+
}
|
|
271
|
+
// --- internals ---
|
|
272
|
+
async loadIndex() {
|
|
273
|
+
if ("index" in this.config.knowledge && this.config.knowledge.index) {
|
|
274
|
+
const idx = this.config.knowledge.index;
|
|
275
|
+
await this.storage.putIndex(idx);
|
|
276
|
+
return idx;
|
|
277
|
+
}
|
|
278
|
+
const manifestUrl = this.config.knowledge.manifest;
|
|
279
|
+
const manifest = (await (await this.fetchFn(manifestUrl)).json());
|
|
280
|
+
const stored = await this.storage.getStoredVersion();
|
|
281
|
+
if (stored === manifest.version) {
|
|
282
|
+
const cached = await this.storage.getIndex(manifest.version);
|
|
283
|
+
if (cached)
|
|
284
|
+
return cached;
|
|
285
|
+
}
|
|
286
|
+
// Resolve the index path relative to the manifest URL.
|
|
287
|
+
const indexUrl = new URL(manifest.index, toAbsolute(manifestUrl)).toString();
|
|
288
|
+
const chunks = (await (await this.fetchFn(indexUrl)).json());
|
|
289
|
+
const index = { manifest, chunks };
|
|
290
|
+
// Compatibility guard: build-time and runtime embedders must match (PRD §25).
|
|
291
|
+
// The built-in embedder is keyed by dimensions; a real embedder should also
|
|
292
|
+
// compare manifest.embeddingModel against the runtime model id.
|
|
293
|
+
await this.storage.putIndex(index);
|
|
294
|
+
return index;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function toAbsolute(url) {
|
|
298
|
+
if (/^https?:\/\//.test(url))
|
|
299
|
+
return url;
|
|
300
|
+
const base = typeof location !== "undefined" ? location.href : "http://localhost/";
|
|
301
|
+
return new URL(url, base).toString();
|
|
302
|
+
}
|
|
303
|
+
function now() {
|
|
304
|
+
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
305
|
+
}
|
|
306
|
+
/** Cap on an action result fed back to the model (keeps the follow-up prompt small). */
|
|
307
|
+
const MAX_RESULT_CHARS = 4000;
|
|
308
|
+
function truncate(s, max) {
|
|
309
|
+
return s.length > max ? `${s.slice(0, max)}… [truncated]` : s;
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=appmind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appmind.js","sourceRoot":"","sources":["../src/appmind.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured, app-provided description of what the user currently sees (PRD §29–31).
|
|
3
|
+
* AppMind never scrapes the DOM by default — the app pushes semantic state here.
|
|
4
|
+
*/
|
|
5
|
+
export interface AppMindContext {
|
|
6
|
+
route?: string;
|
|
7
|
+
page?: {
|
|
8
|
+
type?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
};
|
|
11
|
+
resource?: {
|
|
12
|
+
type?: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
};
|
|
16
|
+
/** Arbitrary visible field values / form state for the current view. */
|
|
17
|
+
visibleState?: Record<string, unknown>;
|
|
18
|
+
/** Coarse global scope: org, plan, permissions, feature flags. */
|
|
19
|
+
global?: Record<string, unknown>;
|
|
20
|
+
/** Frontend permission hints — NOT authoritative (PRD §36). */
|
|
21
|
+
permissions?: string[];
|
|
22
|
+
}
|
|
23
|
+
/** Holds the current context and notifies listeners on change. */
|
|
24
|
+
export declare class ContextStore {
|
|
25
|
+
private context;
|
|
26
|
+
private listeners;
|
|
27
|
+
get(): AppMindContext;
|
|
28
|
+
set(next: AppMindContext): void;
|
|
29
|
+
merge(patch: Partial<AppMindContext>): void;
|
|
30
|
+
subscribe(listener: (ctx: AppMindContext) => void): () => void;
|
|
31
|
+
/** Derive lightweight keyword signals from the context for retrieval biasing. */
|
|
32
|
+
keywords(): string[];
|
|
33
|
+
/** Human-readable block for the model prompt (PRD §40). */
|
|
34
|
+
toPromptBlock(): string;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,kEAAkE;AAClE,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,SAAS,CAA4C;IAE7D,GAAG,IAAI,cAAc;IAIrB,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAK/B,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAI3C,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI;IAK9D,iFAAiF;IACjF,QAAQ,IAAI,MAAM,EAAE;IAoBpB,2DAA2D;IAC3D,aAAa,IAAI,MAAM;CAkCxB"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** Holds the current context and notifies listeners on change. */
|
|
2
|
+
export class ContextStore {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.context = {};
|
|
5
|
+
this.listeners = new Set();
|
|
6
|
+
}
|
|
7
|
+
get() {
|
|
8
|
+
return this.context;
|
|
9
|
+
}
|
|
10
|
+
set(next) {
|
|
11
|
+
this.context = next;
|
|
12
|
+
for (const l of this.listeners)
|
|
13
|
+
l(next);
|
|
14
|
+
}
|
|
15
|
+
merge(patch) {
|
|
16
|
+
this.set({ ...this.context, ...patch });
|
|
17
|
+
}
|
|
18
|
+
subscribe(listener) {
|
|
19
|
+
this.listeners.add(listener);
|
|
20
|
+
return () => this.listeners.delete(listener);
|
|
21
|
+
}
|
|
22
|
+
/** Derive lightweight keyword signals from the context for retrieval biasing. */
|
|
23
|
+
keywords() {
|
|
24
|
+
const c = this.context;
|
|
25
|
+
const words = [];
|
|
26
|
+
if (c.route)
|
|
27
|
+
words.push(...c.route.split(/[/\-_]/));
|
|
28
|
+
if (c.page?.title)
|
|
29
|
+
words.push(...c.page.title.split(/\s+/));
|
|
30
|
+
if (c.page?.type)
|
|
31
|
+
words.push(c.page.type);
|
|
32
|
+
if (c.resource?.name)
|
|
33
|
+
words.push(...c.resource.name.split(/\s+/));
|
|
34
|
+
if (c.resource?.type)
|
|
35
|
+
words.push(c.resource.type);
|
|
36
|
+
if (c.resource?.id)
|
|
37
|
+
words.push(c.resource.id);
|
|
38
|
+
for (const bag of [c.visibleState, c.global]) {
|
|
39
|
+
if (!bag)
|
|
40
|
+
continue;
|
|
41
|
+
for (const [k, v] of Object.entries(bag)) {
|
|
42
|
+
words.push(k);
|
|
43
|
+
if (typeof v === "string")
|
|
44
|
+
words.push(v);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (c.permissions)
|
|
48
|
+
words.push(...c.permissions);
|
|
49
|
+
return words.map((w) => w.toLowerCase()).filter((w) => w.length > 1);
|
|
50
|
+
}
|
|
51
|
+
/** Human-readable block for the model prompt (PRD §40). */
|
|
52
|
+
toPromptBlock() {
|
|
53
|
+
const c = this.context;
|
|
54
|
+
const lines = ["APPLICATION CONTEXT"];
|
|
55
|
+
if (c.route)
|
|
56
|
+
lines.push(`Route: ${c.route}`);
|
|
57
|
+
if (c.page?.title || c.page?.type) {
|
|
58
|
+
lines.push(`Page: ${c.page.title ?? c.page.type}`);
|
|
59
|
+
}
|
|
60
|
+
if (c.resource) {
|
|
61
|
+
// Always surface the id when there is one: actions/tools usually need it,
|
|
62
|
+
// and a display name alone leaves the model guessing (it passes the name).
|
|
63
|
+
const meta = [c.resource.type, c.resource.id && `id: ${c.resource.id}`].filter(Boolean);
|
|
64
|
+
lines.push(`Resource: ${c.resource.name ?? c.resource.id ?? ""}${meta.length ? ` (${meta.join(", ")})` : ""}`);
|
|
65
|
+
}
|
|
66
|
+
if (c.visibleState && Object.keys(c.visibleState).length > 0) {
|
|
67
|
+
lines.push("Visible state:");
|
|
68
|
+
for (const [k, v] of Object.entries(c.visibleState)) {
|
|
69
|
+
lines.push(` ${k}: ${formatValue(v)}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (c.global && Object.keys(c.global).length > 0) {
|
|
73
|
+
lines.push("Global:");
|
|
74
|
+
for (const [k, v] of Object.entries(c.global)) {
|
|
75
|
+
lines.push(` ${k}: ${formatValue(v)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (c.permissions && c.permissions.length > 0) {
|
|
79
|
+
lines.push(`Permissions: ${c.permissions.join(", ")}`);
|
|
80
|
+
}
|
|
81
|
+
return lines.join("\n");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function formatValue(v) {
|
|
85
|
+
if (v === null || v === undefined)
|
|
86
|
+
return "—";
|
|
87
|
+
if (typeof v === "object")
|
|
88
|
+
return JSON.stringify(v);
|
|
89
|
+
return String(v);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Optional telemetry/lifecycle events (PRD §55). */
|
|
2
|
+
export interface AppMindEvents {
|
|
3
|
+
initialized: void;
|
|
4
|
+
model_loading: {
|
|
5
|
+
provider: string;
|
|
6
|
+
};
|
|
7
|
+
model_ready: {
|
|
8
|
+
provider: string;
|
|
9
|
+
location: "local" | "remote";
|
|
10
|
+
};
|
|
11
|
+
query: {
|
|
12
|
+
text: string;
|
|
13
|
+
};
|
|
14
|
+
retrieval: {
|
|
15
|
+
count: number;
|
|
16
|
+
latencyMs: number;
|
|
17
|
+
};
|
|
18
|
+
generation: {
|
|
19
|
+
location: "local" | "remote";
|
|
20
|
+
};
|
|
21
|
+
action_proposed: {
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
action_confirmed: {
|
|
25
|
+
name: string;
|
|
26
|
+
};
|
|
27
|
+
action_executed: {
|
|
28
|
+
name: string;
|
|
29
|
+
ok: boolean;
|
|
30
|
+
};
|
|
31
|
+
error: {
|
|
32
|
+
error: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export type EventName = keyof AppMindEvents;
|
|
36
|
+
export declare class Emitter {
|
|
37
|
+
private handlers;
|
|
38
|
+
on<K extends EventName>(name: K, handler: (payload: AppMindEvents[K]) => void): () => void;
|
|
39
|
+
emit<K extends EventName>(name: K, payload: AppMindEvents[K]): void;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,IAAI,CAAC;IAClB,aAAa,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,CAAC;IAChE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,UAAU,EAAE;QAAE,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,CAAC;IAC7C,eAAe,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,gBAAgB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,eAAe,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1B;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC;AAE5C,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAqD;IAErE,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAU1F,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;CAWpE"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class Emitter {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.handlers = new Map();
|
|
4
|
+
}
|
|
5
|
+
on(name, handler) {
|
|
6
|
+
let set = this.handlers.get(name);
|
|
7
|
+
if (!set) {
|
|
8
|
+
set = new Set();
|
|
9
|
+
this.handlers.set(name, set);
|
|
10
|
+
}
|
|
11
|
+
set.add(handler);
|
|
12
|
+
return () => set.delete(handler);
|
|
13
|
+
}
|
|
14
|
+
emit(name, payload) {
|
|
15
|
+
const set = this.handlers.get(name);
|
|
16
|
+
if (!set)
|
|
17
|
+
return;
|
|
18
|
+
for (const h of set) {
|
|
19
|
+
try {
|
|
20
|
+
h(payload);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
/* listener errors must not break the runtime */
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAgBA,MAAM,OAAO,OAAO;IAApB;QACU,aAAQ,GAAG,IAAI,GAAG,EAA0C,CAAC;IAuBvE,CAAC;IArBC,EAAE,CAAsB,IAAO,EAAE,OAA4C;QAC3E,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,OAAiC,CAAC,CAAC;QAC3C,OAAO,GAAG,EAAE,CAAC,GAAI,CAAC,MAAM,CAAC,OAAiC,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,CAAsB,IAAO,EAAE,OAAyB;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC;gBACH,CAAC,CAAC,OAAO,CAAC,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACP,gDAAgD;YAClD,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { AppMind } from "./appmind.js";
|
|
2
|
+
export type { AppMindConfig, ChatEvent, ChatOptions } from "./appmind.js";
|
|
3
|
+
export type { AppMindContext } from "./context.js";
|
|
4
|
+
export { ContextStore } from "./context.js";
|
|
5
|
+
export { ActionRegistry, type AppMindAction, type ActionRisk, type PendingAction, } from "./actions.js";
|
|
6
|
+
export type { AppMindModelProvider, ChatMessage, GenerationEvent, GenerationRequest, ModelLocation, ToolSpec, } from "./model.js";
|
|
7
|
+
export { MemoryStorage, type AppMindStorage } from "./storage.js";
|
|
8
|
+
export type { AppMindEvents, EventName } from "./events.js";
|
|
9
|
+
export { buildSystemPrompt, parseToolCallFromText, estimateTokens, windowHistory, DEFAULT_PROMPT_BUDGET, type PromptBudget, } from "./runtime.js";
|
|
10
|
+
export type { KnowledgeChunk, KnowledgeIndex, KnowledgeManifest, RetrievalResult, Embedder, EmbedderSpec, } from "@appmind/knowledge";
|
|
11
|
+
export { createEmbedder, createDefaultEmbedder, assertEmbedderCompatible, embedText, PlaceholderEmbedder, TransformersEmbedder, PLACEHOLDER_EMBEDDER_ID, CURRENT_INDEX_SCHEMA, } from "@appmind/knowledge";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1E,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,QAAQ,EACR,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,SAAS,EACT,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { AppMind } from "./appmind.js";
|
|
2
|
+
export { ContextStore } from "./context.js";
|
|
3
|
+
export { ActionRegistry, } from "./actions.js";
|
|
4
|
+
export { MemoryStorage } from "./storage.js";
|
|
5
|
+
export { buildSystemPrompt, parseToolCallFromText, estimateTokens, windowHistory, DEFAULT_PROMPT_BUDGET, } from "./runtime.js";
|
|
6
|
+
export { createEmbedder, createDefaultEmbedder, assertEmbedderCompatible, embedText, PlaceholderEmbedder, TransformersEmbedder, PLACEHOLDER_EMBEDDER_ID, CURRENT_INDEX_SCHEMA, } from "@appmind/knowledge";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,cAAc,GAIf,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,aAAa,EAAuB,MAAM,cAAc,CAAC;AAElE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,qBAAqB,GAEtB,MAAM,cAAc,CAAC;AAWtB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,SAAS,EACT,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC"}
|
package/dist/model.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Model provider interface (PRD §17). Implementations live in @appmind/model. */
|
|
2
|
+
export interface ChatMessage {
|
|
3
|
+
role: "system" | "user" | "assistant";
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
/** A tool/action description handed to the model. */
|
|
7
|
+
export interface ToolSpec {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
parameters?: unknown;
|
|
11
|
+
}
|
|
12
|
+
export interface GenerationRequest {
|
|
13
|
+
messages: ChatMessage[];
|
|
14
|
+
tools?: ToolSpec[];
|
|
15
|
+
/** Rendered application-context + knowledge block for the system prompt. */
|
|
16
|
+
system?: string;
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}
|
|
19
|
+
export type GenerationEvent = {
|
|
20
|
+
type: "text";
|
|
21
|
+
delta: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: "tool_call";
|
|
24
|
+
name: string;
|
|
25
|
+
arguments: unknown;
|
|
26
|
+
} | {
|
|
27
|
+
type: "error";
|
|
28
|
+
error: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: "done";
|
|
31
|
+
};
|
|
32
|
+
/** Where a given generation actually ran — surfaced to the app (PRD §54). */
|
|
33
|
+
export type ModelLocation = "local" | "remote";
|
|
34
|
+
export interface AppMindModelProvider {
|
|
35
|
+
/** Human-readable id, e.g. "remote:anthropic" or "local:webllm". */
|
|
36
|
+
readonly id: string;
|
|
37
|
+
initialize(): Promise<void>;
|
|
38
|
+
/** Where this provider runs inference, once initialized. */
|
|
39
|
+
location(): ModelLocation;
|
|
40
|
+
supportsTools(): boolean;
|
|
41
|
+
generate(request: GenerationRequest): AsyncIterable<GenerationEvent>;
|
|
42
|
+
dispose(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAElF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,6EAA6E;AAC7E,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/C,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,IAAI,aAAa,CAAC;IAC1B,aAAa,IAAI,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;IACrE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B"}
|
package/dist/model.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,kFAAkF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { RetrievalResult } from "@appmind/knowledge";
|
|
2
|
+
import type { AppMindAction } from "./actions.js";
|
|
3
|
+
import type { ChatMessage, ToolSpec } from "./model.js";
|
|
4
|
+
/**
|
|
5
|
+
* Rough token estimate (~4 chars/token, matching the chunker's heuristic).
|
|
6
|
+
* Deliberately approximate — a real tokenizer is deferred (see plan §1.4).
|
|
7
|
+
*/
|
|
8
|
+
export declare function estimateTokens(text: string): number;
|
|
9
|
+
export interface PromptBudget {
|
|
10
|
+
/** Total token budget the prompt should target (default: small-model ~4K ctx). */
|
|
11
|
+
maxTokens: number;
|
|
12
|
+
/** Tokens reserved for the model's output. */
|
|
13
|
+
reservedOutputTokens: number;
|
|
14
|
+
/** Hard cap on characters kept from any single knowledge chunk. */
|
|
15
|
+
perChunkCharCap: number;
|
|
16
|
+
/** Max prior turns of conversation to keep. */
|
|
17
|
+
maxHistoryTurns: number;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEFAULT_PROMPT_BUDGET: PromptBudget;
|
|
20
|
+
/**
|
|
21
|
+
* Assemble the structured system prompt (PRD §40) within a token budget.
|
|
22
|
+
*
|
|
23
|
+
* Fill priority: system instructions → application context → top-ranked
|
|
24
|
+
* knowledge (drop lowest-ranked / truncate per chunk until it fits) → available
|
|
25
|
+
* actions. History and the user message are budgeted separately in the messages
|
|
26
|
+
* array; the caller passes the tokens those consume as `usedTokens`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildSystemPrompt(contextBlock: string, knowledge: RetrievalResult[], actions: AppMindAction[], options?: {
|
|
29
|
+
budget?: Partial<PromptBudget>;
|
|
30
|
+
usedTokens?: number;
|
|
31
|
+
}): string;
|
|
32
|
+
export declare function toToolSpecs(actions: AppMindAction[]): ToolSpec[];
|
|
33
|
+
/**
|
|
34
|
+
* Best-effort extraction of a tool call from a plain-text model response, for
|
|
35
|
+
* providers that don't emit structured tool_call events. Looks for a JSON
|
|
36
|
+
* object containing a "tool" key.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseToolCallFromText(text: string): {
|
|
39
|
+
name: string;
|
|
40
|
+
arguments: unknown;
|
|
41
|
+
} | undefined;
|
|
42
|
+
/** Keep only the last `maxTurns` messages of history (a turn = one message). */
|
|
43
|
+
export declare function windowHistory(history: ChatMessage[], maxTurns: number): ChatMessage[];
|
|
44
|
+
export declare function toChatMessages(history: ChatMessage[], userMessage: string, maxTurns?: number): ChatMessage[];
|
|
45
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAExD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mEAAmE;IACnE,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,qBAAqB,EAAE,YAKnC,CAAC;AAkBF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,eAAe,EAAE,EAC5B,OAAO,EAAE,aAAa,EAAE,EACxB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpE,MAAM,CA+CR;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,QAAQ,EAAE,CAMhE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAYlD;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAGrF;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,EAAE,EACtB,WAAW,EAAE,MAAM,EACnB,QAAQ,SAAwC,GAC/C,WAAW,EAAE,CAEf"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rough token estimate (~4 chars/token, matching the chunker's heuristic).
|
|
3
|
+
* Deliberately approximate — a real tokenizer is deferred (see plan §1.4).
|
|
4
|
+
*/
|
|
5
|
+
export function estimateTokens(text) {
|
|
6
|
+
return Math.ceil(text.length / 4);
|
|
7
|
+
}
|
|
8
|
+
export const DEFAULT_PROMPT_BUDGET = {
|
|
9
|
+
maxTokens: 4096,
|
|
10
|
+
reservedOutputTokens: 1024,
|
|
11
|
+
perChunkCharCap: 1200,
|
|
12
|
+
maxHistoryTurns: 6,
|
|
13
|
+
};
|
|
14
|
+
const BASE_INSTRUCTIONS = [
|
|
15
|
+
"SYSTEM INSTRUCTIONS",
|
|
16
|
+
"You are AppMind, an assistant embedded inside a web application.",
|
|
17
|
+
"Answer the user's question directly and concisely using the APPLICATION CONTEXT",
|
|
18
|
+
"and RELEVANT PRODUCT KNOWLEDGE below. If the knowledge does not cover the",
|
|
19
|
+
"question, say so briefly. Do not invent facts, and do not output JSON.",
|
|
20
|
+
].join("\n");
|
|
21
|
+
const TOOL_INSTRUCTIONS = [
|
|
22
|
+
"You can also perform actions, but ONLY when the user explicitly asks you to do",
|
|
23
|
+
"one of the AVAILABLE ACTIONS listed below. To perform one, reply with ONLY a",
|
|
24
|
+
'JSON object {"tool":"<name>","arguments":{...}} where <name> is exactly one of',
|
|
25
|
+
"the AVAILABLE ACTIONS — never invent an action name. For any informational or",
|
|
26
|
+
"factual question, answer in plain language and do NOT output JSON.",
|
|
27
|
+
].join("\n");
|
|
28
|
+
/**
|
|
29
|
+
* Assemble the structured system prompt (PRD §40) within a token budget.
|
|
30
|
+
*
|
|
31
|
+
* Fill priority: system instructions → application context → top-ranked
|
|
32
|
+
* knowledge (drop lowest-ranked / truncate per chunk until it fits) → available
|
|
33
|
+
* actions. History and the user message are budgeted separately in the messages
|
|
34
|
+
* array; the caller passes the tokens those consume as `usedTokens`.
|
|
35
|
+
*/
|
|
36
|
+
export function buildSystemPrompt(contextBlock, knowledge, actions, options = {}) {
|
|
37
|
+
const budget = { ...DEFAULT_PROMPT_BUDGET, ...options.budget };
|
|
38
|
+
const usedTokens = options.usedTokens ?? 0;
|
|
39
|
+
// Only mention tools/JSON when actions are actually available, so the model
|
|
40
|
+
// doesn't hallucinate a tool call for a plain informational question.
|
|
41
|
+
const instructions = actions.length > 0 ? `${BASE_INSTRUCTIONS}\n\n${TOOL_INSTRUCTIONS}` : BASE_INSTRUCTIONS;
|
|
42
|
+
const parts = [instructions];
|
|
43
|
+
let spent = estimateTokens(instructions) + usedTokens;
|
|
44
|
+
const ceiling = budget.maxTokens - budget.reservedOutputTokens;
|
|
45
|
+
// Application context is high priority — always included (it's small).
|
|
46
|
+
if (contextBlock.trim()) {
|
|
47
|
+
parts.push(contextBlock);
|
|
48
|
+
spent += estimateTokens(contextBlock);
|
|
49
|
+
}
|
|
50
|
+
// Available actions are essential for tool calling — reserve them before knowledge.
|
|
51
|
+
const actionsBlock = actions.length > 0
|
|
52
|
+
? `AVAILABLE ACTIONS\n${actions.map((a) => `- ${a.name}: ${a.description}`).join("\n")}`
|
|
53
|
+
: "";
|
|
54
|
+
const actionsTokens = actionsBlock ? estimateTokens(actionsBlock) : 0;
|
|
55
|
+
// Fill knowledge with whatever budget remains after reserving actions.
|
|
56
|
+
const knowledgeCeiling = ceiling - actionsTokens;
|
|
57
|
+
const included = [];
|
|
58
|
+
for (let i = 0; i < knowledge.length; i++) {
|
|
59
|
+
const r = knowledge[i];
|
|
60
|
+
const content = r.content.length > budget.perChunkCharCap
|
|
61
|
+
? r.content.slice(0, budget.perChunkCharCap) + "…"
|
|
62
|
+
: r.content;
|
|
63
|
+
const block = `[${i + 1}] ${r.title}${r.section ? ` — ${r.section}` : ""}\n${content}`;
|
|
64
|
+
const blockTokens = estimateTokens(block);
|
|
65
|
+
if (spent + blockTokens > knowledgeCeiling)
|
|
66
|
+
break; // drop remaining lower-ranked chunks
|
|
67
|
+
included.push(block);
|
|
68
|
+
spent += blockTokens;
|
|
69
|
+
}
|
|
70
|
+
if (included.length > 0) {
|
|
71
|
+
parts.push(`RELEVANT PRODUCT KNOWLEDGE\n${included.join("\n\n")}`);
|
|
72
|
+
}
|
|
73
|
+
if (actionsBlock)
|
|
74
|
+
parts.push(actionsBlock);
|
|
75
|
+
return parts.join("\n\n");
|
|
76
|
+
}
|
|
77
|
+
export function toToolSpecs(actions) {
|
|
78
|
+
return actions.map((a) => ({
|
|
79
|
+
name: a.name,
|
|
80
|
+
description: a.description,
|
|
81
|
+
parameters: a.parameters,
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Best-effort extraction of a tool call from a plain-text model response, for
|
|
86
|
+
* providers that don't emit structured tool_call events. Looks for a JSON
|
|
87
|
+
* object containing a "tool" key.
|
|
88
|
+
*/
|
|
89
|
+
export function parseToolCallFromText(text) {
|
|
90
|
+
const match = text.match(/\{[\s\S]*"tool"[\s\S]*\}/);
|
|
91
|
+
if (!match)
|
|
92
|
+
return undefined;
|
|
93
|
+
try {
|
|
94
|
+
const parsed = JSON.parse(match[0]);
|
|
95
|
+
if (typeof parsed.tool === "string") {
|
|
96
|
+
return { name: parsed.tool, arguments: parsed.arguments ?? {} };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
/* not a tool call */
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
/** Keep only the last `maxTurns` messages of history (a turn = one message). */
|
|
105
|
+
export function windowHistory(history, maxTurns) {
|
|
106
|
+
if (history.length <= maxTurns)
|
|
107
|
+
return history;
|
|
108
|
+
return history.slice(history.length - maxTurns);
|
|
109
|
+
}
|
|
110
|
+
export function toChatMessages(history, userMessage, maxTurns = DEFAULT_PROMPT_BUDGET.maxHistoryTurns) {
|
|
111
|
+
return [...windowHistory(history, maxTurns), { role: "user", content: userMessage }];
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAaD,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,SAAS,EAAE,IAAI;IACf,oBAAoB,EAAE,IAAI;IAC1B,eAAe,EAAE,IAAI;IACrB,eAAe,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,iBAAiB,GAAG;IACxB,qBAAqB;IACrB,kEAAkE;IAClE,iFAAiF;IACjF,2EAA2E;IAC3E,wEAAwE;CACzE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,iBAAiB,GAAG;IACxB,gFAAgF;IAChF,8EAA8E;IAC9E,gFAAgF;IAChF,+EAA+E;IAC/E,oEAAoE;CACrE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,YAAoB,EACpB,SAA4B,EAC5B,OAAwB,EACxB,UAAmE,EAAE;IAErE,MAAM,MAAM,GAAG,EAAE,GAAG,qBAAqB,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC;IAE3C,4EAA4E;IAC5E,sEAAsE;IACtE,MAAM,YAAY,GAChB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,iBAAiB,OAAO,iBAAiB,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC;IAC1F,MAAM,KAAK,GAAa,CAAC,YAAY,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,cAAc,CAAC,YAAY,CAAC,GAAG,UAAU,CAAC;IACtD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,oBAAoB,CAAC;IAE/D,uEAAuE;IACvE,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,IAAI,cAAc,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;IAED,oFAAoF;IACpF,MAAM,YAAY,GAChB,OAAO,CAAC,MAAM,GAAG,CAAC;QAChB,CAAC,CAAC,sBAAsB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACxF,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,aAAa,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtE,uEAAuE;IACvE,MAAM,gBAAgB,GAAG,OAAO,GAAG,aAAa,CAAC;IACjD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;QACxB,MAAM,OAAO,GACX,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,eAAe;YACvC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,eAAe,CAAC,GAAG,GAAG;YAClD,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC;QACvF,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,KAAK,GAAG,WAAW,GAAG,gBAAgB;YAAE,MAAM,CAAC,qCAAqC;QACxF,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,KAAK,IAAI,WAAW,CAAC;IACvB,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,+BAA+B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,YAAY;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAE3C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAwB;IAClD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;KACzB,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAY;IAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACrD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAA2C,CAAC;QAC9E,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QAClE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,OAAsB,EAAE,QAAgB;IACpE,IAAI,OAAO,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC;IAC/C,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAsB,EACtB,WAAmB,EACnB,QAAQ,GAAG,qBAAqB,CAAC,eAAe;IAEhD,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;AACvF,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { KnowledgeIndex } from "@appmind/knowledge";
|
|
2
|
+
/**
|
|
3
|
+
* Persistence interface for the local knowledge index (PRD §24).
|
|
4
|
+
* MVP adapter is IndexedDB (@appmind/storage-indexeddb); an in-memory
|
|
5
|
+
* fallback ships here for SSR/Node.
|
|
6
|
+
*/
|
|
7
|
+
export interface AppMindStorage {
|
|
8
|
+
getIndex(version: string): Promise<KnowledgeIndex | undefined>;
|
|
9
|
+
putIndex(index: KnowledgeIndex): Promise<void>;
|
|
10
|
+
getStoredVersion(): Promise<string | undefined>;
|
|
11
|
+
clear(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
/** Volatile fallback — never persists. Used on the server / when no adapter is set. */
|
|
14
|
+
export declare class MemoryStorage implements AppMindStorage {
|
|
15
|
+
private indexes;
|
|
16
|
+
private latest;
|
|
17
|
+
getIndex(version: string): Promise<KnowledgeIndex | undefined>;
|
|
18
|
+
putIndex(index: KnowledgeIndex): Promise<void>;
|
|
19
|
+
getStoredVersion(): Promise<string | undefined>;
|
|
20
|
+
clear(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IAC/D,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAChD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,uFAAuF;AACvF,qBAAa,aAAc,YAAW,cAAc;IAClD,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,MAAM,CAAqB;IAE7B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAG9D,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAG/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Volatile fallback — never persists. Used on the server / when no adapter is set. */
|
|
2
|
+
export class MemoryStorage {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.indexes = new Map();
|
|
5
|
+
}
|
|
6
|
+
async getIndex(version) {
|
|
7
|
+
return this.indexes.get(version);
|
|
8
|
+
}
|
|
9
|
+
async putIndex(index) {
|
|
10
|
+
this.indexes.set(index.manifest.version, index);
|
|
11
|
+
this.latest = index.manifest.version;
|
|
12
|
+
}
|
|
13
|
+
async getStoredVersion() {
|
|
14
|
+
return this.latest;
|
|
15
|
+
}
|
|
16
|
+
async clear() {
|
|
17
|
+
this.indexes.clear();
|
|
18
|
+
this.latest = undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAcA,uFAAuF;AACvF,MAAM,OAAO,aAAa;IAA1B;QACU,YAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAiBtD,CAAC;IAdC,KAAK,CAAC,QAAQ,CAAC,OAAe;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,KAAK,CAAC,QAAQ,CAAC,KAAqB;QAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;IACvC,CAAC;IACD,KAAK,CAAC,gBAAgB;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IACD,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC1B,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appmind/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AppMind core runtime: agent orchestration, UI context, action registry, and provider interfaces.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@appmind/knowledge": "0.1.0"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/dmitripoli/appmind#readme",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/dmitripoli/appmind/issues"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc -b"
|
|
30
|
+
}
|
|
6
31
|
}
|