@ai-gui/core 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +31 -1
- package/dist/index.d.cts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +31 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -507,6 +507,12 @@ var CardRegistry = class {
|
|
|
507
507
|
getRender(type) {
|
|
508
508
|
return this.cards.get(type)?.render;
|
|
509
509
|
}
|
|
510
|
+
get(type) {
|
|
511
|
+
return this.cards.get(type);
|
|
512
|
+
}
|
|
513
|
+
list() {
|
|
514
|
+
return [...this.cards.values()];
|
|
515
|
+
}
|
|
510
516
|
parse(type, rawJson) {
|
|
511
517
|
const def = this.cards.get(type);
|
|
512
518
|
const { data, complete } = parsePartialJSON(rawJson);
|
|
@@ -1175,6 +1181,10 @@ var ActionRuntime = class {
|
|
|
1175
1181
|
hasAction(type) {
|
|
1176
1182
|
return !this.destroyed && this.registry.has(type);
|
|
1177
1183
|
}
|
|
1184
|
+
/** List registered action names without exposing executable definitions. */
|
|
1185
|
+
listActionTypes() {
|
|
1186
|
+
return this.destroyed ? [] : Object.freeze(this.registry.list().map((action) => action.type));
|
|
1187
|
+
}
|
|
1178
1188
|
subscribe(listener) {
|
|
1179
1189
|
if (this.destroyed) return () => {};
|
|
1180
1190
|
this.listeners.add(listener);
|
|
@@ -1986,6 +1996,23 @@ var Renderer = class {
|
|
|
1986
1996
|
if (this.sanitize !== false) this.sanitizeNodesWithDebug(next.nodes);
|
|
1987
1997
|
}
|
|
1988
1998
|
const nextAst = next.nodes;
|
|
1999
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
2000
|
+
if (!plugin.onASTCommit) continue;
|
|
2001
|
+
try {
|
|
2002
|
+
plugin.onASTCommit(nextAst, {
|
|
2003
|
+
generation: this.generation,
|
|
2004
|
+
emitDebug: (type, data = {}) => this.debug.emit(type, {
|
|
2005
|
+
plugin: plugin.name,
|
|
2006
|
+
...data
|
|
2007
|
+
})
|
|
2008
|
+
});
|
|
2009
|
+
} catch (error) {
|
|
2010
|
+
if (debug) this.debug.emit("plugin-commit-failed", {
|
|
2011
|
+
plugin: plugin.name,
|
|
2012
|
+
error
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
1989
2016
|
const diffStarted = debug ? now() : 0;
|
|
1990
2017
|
const patches = diffAst(this.prevAst, nextAst);
|
|
1991
2018
|
const diffDurationMs = debug ? now() - diffStarted : 0;
|
|
@@ -2196,7 +2223,10 @@ function buildSystemPrompt(options = {}) {
|
|
|
2196
2223
|
if (options.base) parts.push(options.base);
|
|
2197
2224
|
const cardSpec = options.registry?.toPromptSpec();
|
|
2198
2225
|
if (cardSpec) parts.push(cardSpec);
|
|
2199
|
-
for (const
|
|
2226
|
+
for (const plugin of options.plugins ?? []) {
|
|
2227
|
+
const spec = typeof plugin.promptSpec === "function" ? plugin.promptSpec() : plugin.promptSpec;
|
|
2228
|
+
if (spec) parts.push(spec);
|
|
2229
|
+
}
|
|
2200
2230
|
return parts.join("\n\n");
|
|
2201
2231
|
}
|
|
2202
2232
|
|
package/dist/index.d.cts
CHANGED
|
@@ -153,9 +153,24 @@ type RenderOutput = {
|
|
|
153
153
|
data: unknown;
|
|
154
154
|
} | {
|
|
155
155
|
kind: "mount";
|
|
156
|
-
mount: (el: HTMLElement) => void | (() => void);
|
|
156
|
+
mount: (el: HTMLElement, context: RenderMountContext) => void | (() => void);
|
|
157
157
|
};
|
|
158
|
+
interface MountCardSlotRequest {
|
|
159
|
+
type: string;
|
|
160
|
+
data: unknown;
|
|
161
|
+
}
|
|
162
|
+
interface MountedCardSlot {
|
|
163
|
+
update(data: unknown): void;
|
|
164
|
+
destroy(): void;
|
|
165
|
+
}
|
|
166
|
+
interface RenderMountContext {
|
|
167
|
+
mountCard?: (host: HTMLElement, request: MountCardSlotRequest) => MountedCardSlot | undefined;
|
|
168
|
+
}
|
|
158
169
|
type NodeRenderer = (node: ASTNode) => RenderOutput | Promise<RenderOutput>;
|
|
170
|
+
interface PluginCommitContext {
|
|
171
|
+
readonly generation: number;
|
|
172
|
+
emitDebug(type: string, data?: Record<string, unknown>): void;
|
|
173
|
+
}
|
|
159
174
|
type KnownJSONSchemaType = "object" | "array" | "string" | "number" | "integer" | "boolean" | "null";
|
|
160
175
|
interface JSONSchema {
|
|
161
176
|
type?: KnownJSONSchemaType | (string & {});
|
|
@@ -188,9 +203,11 @@ interface AIGuiPlugin {
|
|
|
188
203
|
cards?: CardDef[];
|
|
189
204
|
nodeRenderers?: Record<string, NodeRenderer>;
|
|
190
205
|
isBlockComplete?: (nodeType: string, raw: string) => boolean;
|
|
206
|
+
/** Runs synchronously after the AST is finalized and before patches are dispatched. */
|
|
207
|
+
onASTCommit?: (nodes: readonly ASTNode[], context: PluginCommitContext) => void;
|
|
191
208
|
css?: string;
|
|
192
209
|
/** LLM-facing guidance describing this plugin's fence syntax. */
|
|
193
|
-
promptSpec?: string;
|
|
210
|
+
promptSpec?: string | (() => string);
|
|
194
211
|
}
|
|
195
212
|
interface RendererOptions extends DebugOptions {
|
|
196
213
|
registry?: CardRegistry;
|
|
@@ -218,6 +235,8 @@ declare class CardRegistry {
|
|
|
218
235
|
register(def: CardDef): void;
|
|
219
236
|
has(type: string): boolean;
|
|
220
237
|
getRender(type: string): unknown;
|
|
238
|
+
get(type: string): Readonly<CardDef> | undefined;
|
|
239
|
+
list(): Readonly<CardDef>[];
|
|
221
240
|
parse(type: string, rawJson: string): CardParseResult;
|
|
222
241
|
validate(type: string, data: unknown): boolean;
|
|
223
242
|
private validateDefinition;
|
|
@@ -453,6 +472,8 @@ declare class ActionRuntime {
|
|
|
453
472
|
getState(key: string): ActionState;
|
|
454
473
|
/** Check the runtime allowlist without exposing executable action definitions. */
|
|
455
474
|
hasAction(type: string): boolean;
|
|
475
|
+
/** List registered action names without exposing executable definitions. */
|
|
476
|
+
listActionTypes(): readonly string[];
|
|
456
477
|
subscribe(listener: ActionStateListener): () => void;
|
|
457
478
|
subscribeDebug(listener: DebugEventListener): () => void;
|
|
458
479
|
cancel(key: string): boolean;
|
|
@@ -673,4 +694,4 @@ declare function mockModelStream(events: Iterable<ModelStreamEvent> | AsyncItera
|
|
|
673
694
|
declare function readableBytes(chunks: Iterable<string | Uint8Array> | AsyncIterable<string | Uint8Array>): ReadableStream<Uint8Array>;
|
|
674
695
|
|
|
675
696
|
//#endregion
|
|
676
|
-
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, ModelStreamEvent, NodeRenderer, ParseResult, ParserOptions, PartialJSONResult, Patch, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SourceBlock, StreamParseOptions, StreamRouter, Usage, applyPatches, buildSystemPrompt, collectNodeRenderers, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, getActionKey, getIdleActionState, isCardPatchResult, jsonLines, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, safeDebugValue, sanitizeHtml, textLines, validateJSONSchema };
|
|
697
|
+
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, ModelStreamEvent, MountCardSlotRequest, MountedCardSlot, NodeRenderer, ParseResult, ParserOptions, PartialJSONResult, Patch, PluginCommitContext, RenderMountContext, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SourceBlock, StreamParseOptions, StreamRouter, Usage, applyPatches, buildSystemPrompt, collectNodeRenderers, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, getActionKey, getIdleActionState, isCardPatchResult, jsonLines, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, safeDebugValue, sanitizeHtml, textLines, validateJSONSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -153,9 +153,24 @@ type RenderOutput = {
|
|
|
153
153
|
data: unknown;
|
|
154
154
|
} | {
|
|
155
155
|
kind: "mount";
|
|
156
|
-
mount: (el: HTMLElement) => void | (() => void);
|
|
156
|
+
mount: (el: HTMLElement, context: RenderMountContext) => void | (() => void);
|
|
157
157
|
};
|
|
158
|
+
interface MountCardSlotRequest {
|
|
159
|
+
type: string;
|
|
160
|
+
data: unknown;
|
|
161
|
+
}
|
|
162
|
+
interface MountedCardSlot {
|
|
163
|
+
update(data: unknown): void;
|
|
164
|
+
destroy(): void;
|
|
165
|
+
}
|
|
166
|
+
interface RenderMountContext {
|
|
167
|
+
mountCard?: (host: HTMLElement, request: MountCardSlotRequest) => MountedCardSlot | undefined;
|
|
168
|
+
}
|
|
158
169
|
type NodeRenderer = (node: ASTNode) => RenderOutput | Promise<RenderOutput>;
|
|
170
|
+
interface PluginCommitContext {
|
|
171
|
+
readonly generation: number;
|
|
172
|
+
emitDebug(type: string, data?: Record<string, unknown>): void;
|
|
173
|
+
}
|
|
159
174
|
type KnownJSONSchemaType = "object" | "array" | "string" | "number" | "integer" | "boolean" | "null";
|
|
160
175
|
interface JSONSchema {
|
|
161
176
|
type?: KnownJSONSchemaType | (string & {});
|
|
@@ -188,9 +203,11 @@ interface AIGuiPlugin {
|
|
|
188
203
|
cards?: CardDef[];
|
|
189
204
|
nodeRenderers?: Record<string, NodeRenderer>;
|
|
190
205
|
isBlockComplete?: (nodeType: string, raw: string) => boolean;
|
|
206
|
+
/** Runs synchronously after the AST is finalized and before patches are dispatched. */
|
|
207
|
+
onASTCommit?: (nodes: readonly ASTNode[], context: PluginCommitContext) => void;
|
|
191
208
|
css?: string;
|
|
192
209
|
/** LLM-facing guidance describing this plugin's fence syntax. */
|
|
193
|
-
promptSpec?: string;
|
|
210
|
+
promptSpec?: string | (() => string);
|
|
194
211
|
}
|
|
195
212
|
interface RendererOptions extends DebugOptions {
|
|
196
213
|
registry?: CardRegistry;
|
|
@@ -218,6 +235,8 @@ declare class CardRegistry {
|
|
|
218
235
|
register(def: CardDef): void;
|
|
219
236
|
has(type: string): boolean;
|
|
220
237
|
getRender(type: string): unknown;
|
|
238
|
+
get(type: string): Readonly<CardDef> | undefined;
|
|
239
|
+
list(): Readonly<CardDef>[];
|
|
221
240
|
parse(type: string, rawJson: string): CardParseResult;
|
|
222
241
|
validate(type: string, data: unknown): boolean;
|
|
223
242
|
private validateDefinition;
|
|
@@ -453,6 +472,8 @@ declare class ActionRuntime {
|
|
|
453
472
|
getState(key: string): ActionState;
|
|
454
473
|
/** Check the runtime allowlist without exposing executable action definitions. */
|
|
455
474
|
hasAction(type: string): boolean;
|
|
475
|
+
/** List registered action names without exposing executable definitions. */
|
|
476
|
+
listActionTypes(): readonly string[];
|
|
456
477
|
subscribe(listener: ActionStateListener): () => void;
|
|
457
478
|
subscribeDebug(listener: DebugEventListener): () => void;
|
|
458
479
|
cancel(key: string): boolean;
|
|
@@ -673,4 +694,4 @@ declare function mockModelStream(events: Iterable<ModelStreamEvent> | AsyncItera
|
|
|
673
694
|
declare function readableBytes(chunks: Iterable<string | Uint8Array> | AsyncIterable<string | Uint8Array>): ReadableStream<Uint8Array>;
|
|
674
695
|
|
|
675
696
|
//#endregion
|
|
676
|
-
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, ModelStreamEvent, NodeRenderer, ParseResult, ParserOptions, PartialJSONResult, Patch, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SourceBlock, StreamParseOptions, StreamRouter, Usage, applyPatches, buildSystemPrompt, collectNodeRenderers, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, getActionKey, getIdleActionState, isCardPatchResult, jsonLines, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, safeDebugValue, sanitizeHtml, textLines, validateJSONSchema };
|
|
697
|
+
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, ModelStreamEvent, MountCardSlotRequest, MountedCardSlot, NodeRenderer, ParseResult, ParserOptions, PartialJSONResult, Patch, PluginCommitContext, RenderMountContext, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SourceBlock, StreamParseOptions, StreamRouter, Usage, applyPatches, buildSystemPrompt, collectNodeRenderers, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, getActionKey, getIdleActionState, isCardPatchResult, jsonLines, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, safeDebugValue, sanitizeHtml, textLines, validateJSONSchema };
|
package/dist/index.js
CHANGED
|
@@ -483,6 +483,12 @@ var CardRegistry = class {
|
|
|
483
483
|
getRender(type) {
|
|
484
484
|
return this.cards.get(type)?.render;
|
|
485
485
|
}
|
|
486
|
+
get(type) {
|
|
487
|
+
return this.cards.get(type);
|
|
488
|
+
}
|
|
489
|
+
list() {
|
|
490
|
+
return [...this.cards.values()];
|
|
491
|
+
}
|
|
486
492
|
parse(type, rawJson) {
|
|
487
493
|
const def = this.cards.get(type);
|
|
488
494
|
const { data, complete } = parsePartialJSON(rawJson);
|
|
@@ -1151,6 +1157,10 @@ var ActionRuntime = class {
|
|
|
1151
1157
|
hasAction(type) {
|
|
1152
1158
|
return !this.destroyed && this.registry.has(type);
|
|
1153
1159
|
}
|
|
1160
|
+
/** List registered action names without exposing executable definitions. */
|
|
1161
|
+
listActionTypes() {
|
|
1162
|
+
return this.destroyed ? [] : Object.freeze(this.registry.list().map((action) => action.type));
|
|
1163
|
+
}
|
|
1154
1164
|
subscribe(listener) {
|
|
1155
1165
|
if (this.destroyed) return () => {};
|
|
1156
1166
|
this.listeners.add(listener);
|
|
@@ -1962,6 +1972,23 @@ var Renderer = class {
|
|
|
1962
1972
|
if (this.sanitize !== false) this.sanitizeNodesWithDebug(next.nodes);
|
|
1963
1973
|
}
|
|
1964
1974
|
const nextAst = next.nodes;
|
|
1975
|
+
for (const plugin of this.options.plugins ?? []) {
|
|
1976
|
+
if (!plugin.onASTCommit) continue;
|
|
1977
|
+
try {
|
|
1978
|
+
plugin.onASTCommit(nextAst, {
|
|
1979
|
+
generation: this.generation,
|
|
1980
|
+
emitDebug: (type, data = {}) => this.debug.emit(type, {
|
|
1981
|
+
plugin: plugin.name,
|
|
1982
|
+
...data
|
|
1983
|
+
})
|
|
1984
|
+
});
|
|
1985
|
+
} catch (error) {
|
|
1986
|
+
if (debug) this.debug.emit("plugin-commit-failed", {
|
|
1987
|
+
plugin: plugin.name,
|
|
1988
|
+
error
|
|
1989
|
+
});
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1965
1992
|
const diffStarted = debug ? now() : 0;
|
|
1966
1993
|
const patches = diffAst(this.prevAst, nextAst);
|
|
1967
1994
|
const diffDurationMs = debug ? now() - diffStarted : 0;
|
|
@@ -2172,7 +2199,10 @@ function buildSystemPrompt(options = {}) {
|
|
|
2172
2199
|
if (options.base) parts.push(options.base);
|
|
2173
2200
|
const cardSpec = options.registry?.toPromptSpec();
|
|
2174
2201
|
if (cardSpec) parts.push(cardSpec);
|
|
2175
|
-
for (const
|
|
2202
|
+
for (const plugin of options.plugins ?? []) {
|
|
2203
|
+
const spec = typeof plugin.promptSpec === "function" ? plugin.promptSpec() : plugin.promptSpec;
|
|
2204
|
+
if (spec) parts.push(spec);
|
|
2205
|
+
}
|
|
2176
2206
|
return parts.join("\n\n");
|
|
2177
2207
|
}
|
|
2178
2208
|
|
package/package.json
CHANGED