@intentic/extension-api 1.18.0 → 1.132.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/dist/api.d.ts.map +1 -1
- package/dist/manifest.d.ts +12 -8
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +2 -0
- package/dist/manifest.js.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/package.json +8 -6
- package/src/api.ts +138 -0
- package/src/facts.ts +34 -0
- package/src/index.ts +6 -0
- package/src/manifest.ts +202 -0
- package/src/permissions.ts +36 -0
- package/src/stream.ts +83 -0
- package/src/version.ts +4 -0
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAM7D,MAAM,WAAW,UAAU;IACvB,OAAO,IAAI,IAAI,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export declare const ViewContributionSchema: z.ZodObject<{
|
|
|
3
3
|
id: z.ZodString;
|
|
4
4
|
label: z.ZodString;
|
|
5
5
|
surface: z.ZodEnum<{
|
|
6
|
-
rail: "rail";
|
|
7
6
|
directory: "directory";
|
|
7
|
+
rail: "rail";
|
|
8
8
|
}>;
|
|
9
9
|
}, z.core.$strip>;
|
|
10
10
|
export type ViewContribution = z.infer<typeof ViewContributionSchema>;
|
|
@@ -12,8 +12,8 @@ export declare const ViewerContributionSchema: z.ZodObject<{
|
|
|
12
12
|
id: z.ZodString;
|
|
13
13
|
extensions: z.ZodArray<z.ZodString>;
|
|
14
14
|
fetch: z.ZodEnum<{
|
|
15
|
-
text: "text";
|
|
16
15
|
blob: "blob";
|
|
16
|
+
text: "text";
|
|
17
17
|
}>;
|
|
18
18
|
}, z.core.$strip>;
|
|
19
19
|
export type ViewerContribution = z.infer<typeof ViewerContributionSchema>;
|
|
@@ -21,15 +21,16 @@ export declare const CommandContributionSchema: z.ZodObject<{
|
|
|
21
21
|
command: z.ZodString;
|
|
22
22
|
title: z.ZodString;
|
|
23
23
|
icon: z.ZodOptional<z.ZodString>;
|
|
24
|
+
keybinding: z.ZodOptional<z.ZodString>;
|
|
24
25
|
}, z.core.$strip>;
|
|
25
26
|
export type CommandContribution = z.infer<typeof CommandContributionSchema>;
|
|
26
27
|
export declare const SettingContributionSchema: z.ZodObject<{
|
|
27
28
|
key: z.ZodString;
|
|
28
29
|
type: z.ZodEnum<{
|
|
29
|
-
string: "string";
|
|
30
|
-
number: "number";
|
|
31
30
|
boolean: "boolean";
|
|
32
31
|
enum: "enum";
|
|
32
|
+
number: "number";
|
|
33
|
+
string: "string";
|
|
33
34
|
}>;
|
|
34
35
|
title: z.ZodString;
|
|
35
36
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -85,6 +86,7 @@ export declare const ConnectorContributionSchema: z.ZodObject<{
|
|
|
85
86
|
catalog: z.ZodObject<{
|
|
86
87
|
name: z.ZodString;
|
|
87
88
|
logo: z.ZodOptional<z.ZodString>;
|
|
89
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
88
90
|
description: z.ZodString;
|
|
89
91
|
category: z.ZodString;
|
|
90
92
|
hint: z.ZodOptional<z.ZodString>;
|
|
@@ -135,30 +137,31 @@ export declare const ExtensionManifestSchema: z.ZodObject<{
|
|
|
135
137
|
id: z.ZodString;
|
|
136
138
|
label: z.ZodString;
|
|
137
139
|
surface: z.ZodEnum<{
|
|
138
|
-
rail: "rail";
|
|
139
140
|
directory: "directory";
|
|
141
|
+
rail: "rail";
|
|
140
142
|
}>;
|
|
141
143
|
}, z.core.$strip>>>;
|
|
142
144
|
viewers: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
143
145
|
id: z.ZodString;
|
|
144
146
|
extensions: z.ZodArray<z.ZodString>;
|
|
145
147
|
fetch: z.ZodEnum<{
|
|
146
|
-
text: "text";
|
|
147
148
|
blob: "blob";
|
|
149
|
+
text: "text";
|
|
148
150
|
}>;
|
|
149
151
|
}, z.core.$strip>>>;
|
|
150
152
|
commands: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
151
153
|
command: z.ZodString;
|
|
152
154
|
title: z.ZodString;
|
|
153
155
|
icon: z.ZodOptional<z.ZodString>;
|
|
156
|
+
keybinding: z.ZodOptional<z.ZodString>;
|
|
154
157
|
}, z.core.$strip>>>;
|
|
155
158
|
settings: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
156
159
|
key: z.ZodString;
|
|
157
160
|
type: z.ZodEnum<{
|
|
158
|
-
string: "string";
|
|
159
|
-
number: "number";
|
|
160
161
|
boolean: "boolean";
|
|
161
162
|
enum: "enum";
|
|
163
|
+
number: "number";
|
|
164
|
+
string: "string";
|
|
162
165
|
}>;
|
|
163
166
|
title: z.ZodString;
|
|
164
167
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -187,6 +190,7 @@ export declare const ExtensionManifestSchema: z.ZodObject<{
|
|
|
187
190
|
catalog: z.ZodObject<{
|
|
188
191
|
name: z.ZodString;
|
|
189
192
|
logo: z.ZodOptional<z.ZodString>;
|
|
193
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
190
194
|
description: z.ZodString;
|
|
191
195
|
category: z.ZodString;
|
|
192
196
|
hint: z.ZodOptional<z.ZodString>;
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,sBAAsB;;;;;;;iBAIjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAMtE,eAAO,MAAM,wBAAwB;;;;;;;iBAInC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAG1E,eAAO,MAAM,yBAAyB
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,sBAAsB;;;;;;;iBAIjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAMtE,eAAO,MAAM,wBAAwB;;;;;;;iBAInC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAG1E,eAAO,MAAM,yBAAyB;;;;;iBASpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAO5E,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;iBAYpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAK5E,eAAO,MAAM,yBAAyB;;;;;;;iBAOpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAK5E,eAAO,MAAM,uBAAuB;;iBAElC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAQxE,eAAO,MAAM,0BAA0B;;;iBAGrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAM9E,eAAO,MAAM,6BAA6B;;iBAKxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAKpF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;iBAU/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAOlE,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2BtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwClC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,eAAO,MAAM,aAAa,aAAc,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,MAAM,CAAC,KAAG,MAAkD,CAAC"}
|
package/dist/manifest.js
CHANGED
|
@@ -13,6 +13,7 @@ export const CommandContributionSchema = z.object({
|
|
|
13
13
|
command: z.string().regex(/^[a-z0-9][a-z0-9-]*(\.[a-z0-9][a-z0-9-]*)+$/),
|
|
14
14
|
title: z.string().min(1),
|
|
15
15
|
icon: z.string().optional(),
|
|
16
|
+
keybinding: z.string().regex(/^\S+$/).optional(),
|
|
16
17
|
});
|
|
17
18
|
export const SettingContributionSchema = z.object({
|
|
18
19
|
key: z.string().regex(/^[a-z0-9][a-zA-Z0-9-]*$/),
|
|
@@ -65,6 +66,7 @@ export const ConnectorContributionSchema = z.object({
|
|
|
65
66
|
catalog: z.object({
|
|
66
67
|
name: z.string().min(1),
|
|
67
68
|
logo: z.string().optional(),
|
|
69
|
+
icon: z.string().optional(),
|
|
68
70
|
description: z.string().min(1),
|
|
69
71
|
category: z.string().min(1),
|
|
70
72
|
hint: z.string().optional(),
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC;IAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACzC,CAAC,CAAC;AAOH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC;IAC5C,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,6CAA6C,CAAC;IACxE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,mBAAmB,gBAAiB,SAAS,MAAM,EAAE,UAAU,MAAM,QAAQ,MAAM,KAAG,OAOlG,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentic/extension-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.132.0",
|
|
4
4
|
"description": "The versioned public API intentic extensions compile against — manifest schema, detection facts and the host API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"directory": "_libs/extension-api"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
|
-
"dist"
|
|
13
|
+
"dist",
|
|
14
|
+
"src"
|
|
14
15
|
],
|
|
15
16
|
"publishConfig": {
|
|
16
17
|
"access": "public",
|
|
@@ -34,15 +35,16 @@
|
|
|
34
35
|
"zod": "4.4.3"
|
|
35
36
|
},
|
|
36
37
|
"peerDependencies": {
|
|
37
|
-
"vue": "
|
|
38
|
+
"vue": "3"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"
|
|
41
|
+
"@types/node": "24.13.2",
|
|
42
|
+
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
41
43
|
"vue": "3.5.39",
|
|
42
44
|
"@intentic/tsconfig": "0.0.0"
|
|
43
45
|
},
|
|
44
46
|
"scripts": {
|
|
45
|
-
"build": "
|
|
46
|
-
"watch": "
|
|
47
|
+
"build": "tsgo",
|
|
48
|
+
"watch": "tsgo --build --watch"
|
|
47
49
|
}
|
|
48
50
|
}
|
package/src/api.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { Component } from "vue";
|
|
2
|
+
import type { CapabilityFacts, RepoFacts } from "./facts.js";
|
|
3
|
+
|
|
4
|
+
/* The host API an extension programs against. There is no ambient global: the implementation arrives as the
|
|
5
|
+
* `activate(api, context)` argument, and everything an extension registers is returned as a Disposable pushed
|
|
6
|
+
* onto context.subscriptions so deactivation can unwind it. */
|
|
7
|
+
|
|
8
|
+
export interface Disposable {
|
|
9
|
+
dispose(): void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// One sidebar element a view contributes: routed at /ext/<viewId>/<key> (the key segment is dropped when it
|
|
13
|
+
// equals the view id — a singleton view links to /ext/<viewId>), rendered by the view's component with
|
|
14
|
+
// `repo` (+ props) bound.
|
|
15
|
+
export interface Activation {
|
|
16
|
+
// Stable per-view key (usually the repo name) — the route segment, so deep links survive reloads.
|
|
17
|
+
readonly key: string;
|
|
18
|
+
readonly title: string;
|
|
19
|
+
// An icon name from the host's icon set; absent ⇒ the rail renders the title's initials.
|
|
20
|
+
readonly icon?: string | undefined;
|
|
21
|
+
// The repo this element is rooted at — the fallback-dedup subject and the component's `repo` prop. Absent
|
|
22
|
+
// for capability-driven elements, which aren't rooted at any repo.
|
|
23
|
+
readonly repo?: string | undefined;
|
|
24
|
+
readonly props?: Record<string, unknown> | undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// A view's runtime registration — for third-party extensions, `id`, `label` and `surface` must match a
|
|
28
|
+
// `contributes.views` entry in the approved manifest or the host refuses the registration.
|
|
29
|
+
export interface ViewRegistration {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
// The view family's human name (distinct from an Activation's per-repo `title`) — labels the directory
|
|
32
|
+
// panel's surface switch when a repo activates several.
|
|
33
|
+
readonly label: string;
|
|
34
|
+
readonly surface: "rail" | "directory";
|
|
35
|
+
// Evidence-based detection over the public facts — one activation per sidebar element. Called on every
|
|
36
|
+
// facts poll; a throwing detect contributes nothing that round.
|
|
37
|
+
readonly detect: (repos: readonly RepoFacts[], capabilities: readonly CapabilityFacts[]) => Activation[];
|
|
38
|
+
// A fallback view's activations are dropped for repos already claimed by a non-fallback one.
|
|
39
|
+
readonly fallback?: true | undefined;
|
|
40
|
+
// Lazily imported root component, rendered with `repo` (+ props) bound.
|
|
41
|
+
readonly view: () => Promise<Component>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// A custom file viewer's runtime registration — `id` must match a `contributes.viewers` entry in the approved
|
|
45
|
+
// manifest (the host reads the file extensions + fetch kind from there). The host resolves an open file to this
|
|
46
|
+
// viewer, fetches its content, and renders `component` with `{ path, text?, blob? }` bound.
|
|
47
|
+
export interface ViewerRegistration {
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly component: () => Promise<Component>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type SettingValue = string | number | boolean;
|
|
53
|
+
|
|
54
|
+
export interface ProcessStatus {
|
|
55
|
+
readonly name: string;
|
|
56
|
+
readonly running: boolean;
|
|
57
|
+
readonly port?: number | undefined;
|
|
58
|
+
readonly previewUrl?: string | undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface IntenticApi {
|
|
62
|
+
// The host's @intentic/extension-api version — what `engines.intentic` was checked against.
|
|
63
|
+
readonly apiVersion: string;
|
|
64
|
+
readonly views: {
|
|
65
|
+
register(view: ViewRegistration): Disposable;
|
|
66
|
+
};
|
|
67
|
+
// Custom file viewers (contributes.viewers) — the host owns the fetch + open-file lifecycle and renders the
|
|
68
|
+
// registered component with the file's content; the extension only renders. See ViewerRegistration.
|
|
69
|
+
readonly viewers: {
|
|
70
|
+
register(viewer: ViewerRegistration): Disposable;
|
|
71
|
+
};
|
|
72
|
+
readonly commands: {
|
|
73
|
+
// `command` must match a `contributes.commands` entry in the approved manifest.
|
|
74
|
+
register(command: string, handler: (...args: unknown[]) => unknown): Disposable;
|
|
75
|
+
execute(command: string, ...args: unknown[]): Promise<unknown>;
|
|
76
|
+
};
|
|
77
|
+
// The extension's own declared settings, persisted daemon-side and shared across the owner's browsers.
|
|
78
|
+
readonly settings: {
|
|
79
|
+
get(key: string): SettingValue | undefined;
|
|
80
|
+
set(key: string, value: SettingValue): Promise<void>;
|
|
81
|
+
onDidChange(listener: (key: string) => void): Disposable;
|
|
82
|
+
};
|
|
83
|
+
// The authenticated transport to the sandbox daemon's routes — auth is injected host-side; an extension
|
|
84
|
+
// never sees tokens. Reach is scoped: request/json are gated by the manifest's `permissions.sandbox`
|
|
85
|
+
// allowlist, so a call to an undeclared method+path throws rather than reaching the whole daemon.
|
|
86
|
+
readonly sandbox: {
|
|
87
|
+
request(path: string, init?: RequestInit): Promise<Response>;
|
|
88
|
+
json<T>(path: string, init?: RequestInit): Promise<T>;
|
|
89
|
+
// Whether the active sandbox is currently reachable — reactive when read inside a computed, so it
|
|
90
|
+
// drives host-provided vue-query `enabled` options.
|
|
91
|
+
reachable(): boolean;
|
|
92
|
+
// A cache key scoped to the ACTIVE sandbox — the required prefix for every host-provided vue-query
|
|
93
|
+
// key, so caches never bleed across a sandbox switch.
|
|
94
|
+
key(...parts: readonly string[]): readonly unknown[];
|
|
95
|
+
// The daemon's base URL (its public tunnel origin), for building externally-shareable URLs like webhook
|
|
96
|
+
// endpoints. Undefined until the sandbox has registered its address. Not needed for `request`/`json`
|
|
97
|
+
// (those take a path and inject auth) — only when the raw origin must be shown to the user.
|
|
98
|
+
origin(): string | undefined;
|
|
99
|
+
};
|
|
100
|
+
readonly workspace: {
|
|
101
|
+
repos(): readonly RepoFacts[];
|
|
102
|
+
capabilities(): readonly CapabilityFacts[];
|
|
103
|
+
onDidChange(listener: () => void): Disposable;
|
|
104
|
+
};
|
|
105
|
+
// The extension's OWN declared background processes — names outside the manifest are refused.
|
|
106
|
+
readonly processes: {
|
|
107
|
+
status(name: string): Promise<ProcessStatus>;
|
|
108
|
+
start(name: string): Promise<void>;
|
|
109
|
+
stop(name: string): Promise<void>;
|
|
110
|
+
};
|
|
111
|
+
// The shell's ONE global terminal panel — extensions aim it at a tmux session (a capability job, a dev
|
|
112
|
+
// server, an agent terminal); the host owns the panel itself.
|
|
113
|
+
readonly terminal: {
|
|
114
|
+
// Open the panel focused on a tmux session (starting/attaching it).
|
|
115
|
+
open(session: string): void;
|
|
116
|
+
// Show or hide the panel without focusing a session.
|
|
117
|
+
setOpen(open: boolean): void;
|
|
118
|
+
};
|
|
119
|
+
// Navigate the shell to an app path (e.g. "/capabilities", "/ext/<view>/<key>").
|
|
120
|
+
readonly navigate: (path: string) => void;
|
|
121
|
+
readonly theme: {
|
|
122
|
+
mode(): "light" | "dark";
|
|
123
|
+
onDidChange(listener: (mode: "light" | "dark") => void): Disposable;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface ExtensionContext {
|
|
128
|
+
readonly extensionId: string;
|
|
129
|
+
// Disposables pushed here are disposed on deactivation, in reverse order.
|
|
130
|
+
readonly subscriptions: Disposable[];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// The shape of the bundle's default export (or its named exports): `activate` runs once after the engines
|
|
134
|
+
// check; `deactivate` runs before the host discards the extension.
|
|
135
|
+
export interface ExtensionModule {
|
|
136
|
+
activate(api: IntenticApi, context: ExtensionContext): void | Promise<void>;
|
|
137
|
+
deactivate?(): void | Promise<void>;
|
|
138
|
+
}
|
package/src/facts.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* The stable DETECTION facts — the subset of the daemon's wire schemas an extension's `detect()` reads to decide
|
|
2
|
+
* when to activate a view. This is deliberately narrow (evidence over identity) so activation logic doesn't
|
|
3
|
+
* couple to the daemon's fuller summaries. It is NOT the data plane: an activated extension reads real data over
|
|
4
|
+
* `api.sandbox.request/json` against the `@intentic/sandbox-contract` schemas — the first-party wire contract,
|
|
5
|
+
* gated per-route by the manifest's `permissions.sandbox` allowlist. (Because every first-party extension is
|
|
6
|
+
* in-repo and compiled together, a wire change there is caught by the compiler and fixed atomically, so there is
|
|
7
|
+
* no separate "stable data API" to promote — only detection is version-stable.) The daemon's own summaries
|
|
8
|
+
* (PanelSummary, CapabilitySummary) are structural supersets and flow into `detect()` unmapped, but only THESE
|
|
9
|
+
* fields are guaranteed to it. Optional fields carry `| undefined` so zod-inferred wire types assign under
|
|
10
|
+
* exactOptionalPropertyTypes. */
|
|
11
|
+
|
|
12
|
+
// Daemon-computed content facts for one discovered repository under /work (`repo` is its root-relative dir) —
|
|
13
|
+
// evidence over identity: a repo is served because of what it CONTAINS (deploy.config.ts, pnpm-workspace.yaml
|
|
14
|
+
// + turbo.json, .intentic/ui), not what it happens to be named.
|
|
15
|
+
export interface RepoFacts {
|
|
16
|
+
readonly repo: string;
|
|
17
|
+
// The workspace role this repo dir occupies; absent for extra clones.
|
|
18
|
+
readonly role?: "intent" | "desired-state" | "app" | undefined;
|
|
19
|
+
// Whether the repo ships a runnable dev server (a package.json `dev` script at operator/ or the root).
|
|
20
|
+
readonly hasPanel: boolean;
|
|
21
|
+
readonly deployConfig: boolean;
|
|
22
|
+
readonly desiredState: boolean;
|
|
23
|
+
readonly directoryUi: boolean;
|
|
24
|
+
readonly monorepo: boolean;
|
|
25
|
+
readonly vitest: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// One connected capability's secret-free echo — `kind` is an open string: new kinds appear without an API bump,
|
|
29
|
+
// and matching on one couples the extension to that kind's continued existence.
|
|
30
|
+
export interface CapabilityFacts {
|
|
31
|
+
readonly id: string;
|
|
32
|
+
readonly kind: string;
|
|
33
|
+
readonly config: Readonly<Record<string, string | number | boolean>>;
|
|
34
|
+
}
|
package/src/index.ts
ADDED
package/src/manifest.ts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/* The extension manifest: `intentic-extension.json` at the extension repo root (deliberately NOT inside
|
|
4
|
+
* .claude-plugin/ — that directory is Claude Code's namespace with its own semantics). The manifest is the
|
|
5
|
+
* approval surface: the install dialog shows exactly these declared contributions before the owner confirms,
|
|
6
|
+
* and the host refuses runtime registrations (views, commands) whose ids the approved manifest never declared. */
|
|
7
|
+
|
|
8
|
+
// A sidebar element family the extension may register at runtime (api.views.register): `rail` = a global
|
|
9
|
+
// left-rail tile routed at /ext/:ext/:key?; `directory` = a per-repo panel opened from the Workspace tree.
|
|
10
|
+
export const ViewContributionSchema = z.object({
|
|
11
|
+
id: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
12
|
+
label: z.string().min(1),
|
|
13
|
+
surface: z.enum(["rail", "directory"]),
|
|
14
|
+
});
|
|
15
|
+
export type ViewContribution = z.infer<typeof ViewContributionSchema>;
|
|
16
|
+
|
|
17
|
+
// A custom file viewer the extension may register at runtime (api.viewers.register): the host resolves an open
|
|
18
|
+
// file to this viewer by extension, fetches its bytes (`fetch: "blob"`) or text (`fetch: "text"`), and renders
|
|
19
|
+
// the registered component with them — the host keeps the fetch + open-file lifecycle; the extension only renders.
|
|
20
|
+
// `extensions` are bare file extensions (no dot), e.g. ["docx"]. This is the non-sidebar contribution point.
|
|
21
|
+
export const ViewerContributionSchema = z.object({
|
|
22
|
+
id: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
23
|
+
extensions: z.array(z.string().regex(/^[a-z0-9]+$/)).min(1),
|
|
24
|
+
fetch: z.enum(["text", "blob"]),
|
|
25
|
+
});
|
|
26
|
+
export type ViewerContribution = z.infer<typeof ViewerContributionSchema>;
|
|
27
|
+
|
|
28
|
+
// A command the extension may register a handler for (api.commands.register); surfaced in the command palette.
|
|
29
|
+
export const CommandContributionSchema = z.object({
|
|
30
|
+
command: z.string().regex(/^[a-z0-9][a-z0-9-]*(\.[a-z0-9][a-z0-9-]*)+$/),
|
|
31
|
+
title: z.string().min(1),
|
|
32
|
+
icon: z.string().optional(),
|
|
33
|
+
// An optional global keyboard shortcut, in the host's chord notation (`Mod`/`Ctrl`/`Shift`/`Alt` + key, e.g.
|
|
34
|
+
// "Mod+Shift+K"; `Mod` = ⌘ on Apple, Ctrl elsewhere). It is DECLARED here so it rides the install dialog's
|
|
35
|
+
// approval surface — a global shortcut is consequential, so like title/icon the manifest value is authoritative
|
|
36
|
+
// and the host binds only what was approved. Whitespace-free; an unparseable chord simply never fires.
|
|
37
|
+
keybinding: z.string().regex(/^\S+$/).optional(),
|
|
38
|
+
});
|
|
39
|
+
export type CommandContribution = z.infer<typeof CommandContributionSchema>;
|
|
40
|
+
|
|
41
|
+
// A typed setting descriptor the host renders schema-driven into the Settings page and persists daemon-side —
|
|
42
|
+
// `enum` lists the choices for type "enum" and is meaningless otherwise. `secret: true` masks the value in the
|
|
43
|
+
// UI and strips it from reads (a set secret round-trips as "still set", never its value). `env` injects the
|
|
44
|
+
// stored value into the agent's shell environment under that name every turn — the way a connector's
|
|
45
|
+
// credential reaches the agent's CLI tools, but declared by the extension.
|
|
46
|
+
export const SettingContributionSchema = z.object({
|
|
47
|
+
key: z.string().regex(/^[a-z0-9][a-zA-Z0-9-]*$/),
|
|
48
|
+
type: z.enum(["boolean", "string", "number", "enum"]),
|
|
49
|
+
title: z.string().min(1),
|
|
50
|
+
description: z.string().optional(),
|
|
51
|
+
default: z.union([z.string(), z.number(), z.boolean()]).optional(),
|
|
52
|
+
enum: z.array(z.string()).optional(),
|
|
53
|
+
secret: z.boolean().optional(),
|
|
54
|
+
env: z
|
|
55
|
+
.string()
|
|
56
|
+
.regex(/^[A-Z][A-Z0-9_]*$/)
|
|
57
|
+
.optional(),
|
|
58
|
+
});
|
|
59
|
+
export type SettingContribution = z.infer<typeof SettingContributionSchema>;
|
|
60
|
+
|
|
61
|
+
// A long-lived background process the daemon runs for the extension (tmux-managed, like panel dev servers).
|
|
62
|
+
// `port: "auto"` assigns a free port injected as PORT; `preview` exposes it on a tunneled preview hostname;
|
|
63
|
+
// `autoStart` launches it on install and daemon boot. `cwd` is relative to the extension checkout.
|
|
64
|
+
export const ProcessContributionSchema = z.object({
|
|
65
|
+
name: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
66
|
+
command: z.string().min(1),
|
|
67
|
+
cwd: z.string().optional(),
|
|
68
|
+
port: z.literal("auto").optional(),
|
|
69
|
+
preview: z.boolean().optional(),
|
|
70
|
+
autoStart: z.boolean().optional(),
|
|
71
|
+
});
|
|
72
|
+
export type ProcessContribution = z.infer<typeof ProcessContributionSchema>;
|
|
73
|
+
|
|
74
|
+
// "This checkout is ALSO a Claude Code plugin": the daemon hands the directory (`path` relative to the
|
|
75
|
+
// checkout; absent ⇒ the checkout root) to the Agent SDK's plugin loader, which reads skills/agents/hooks/
|
|
76
|
+
// commands/.mcp.json each turn — the daemon never parses plugin internals.
|
|
77
|
+
export const AgentContributionSchema = z.object({
|
|
78
|
+
path: z.string().optional(),
|
|
79
|
+
});
|
|
80
|
+
export type AgentContribution = z.infer<typeof AgentContributionSchema>;
|
|
81
|
+
|
|
82
|
+
// A realtime listener the extension's gateway process (contributes.processes) implements: `provider` is the
|
|
83
|
+
// slug its automation triggers fire on (Trigger.provider) and `eventTypes` the kinds those triggers may narrow
|
|
84
|
+
// to (Trigger.eventType). The daemon validates listener automations against these, and serves the gateway a
|
|
85
|
+
// provider-scoped control surface — GET /listeners/<provider>/state to reconcile, POST …/dispatch to wake an
|
|
86
|
+
// automation (optionally holding a turn-stream), …/failure + …/status to report. The daemon holds no provider
|
|
87
|
+
// connection itself; the extension's process does.
|
|
88
|
+
export const ListenerContributionSchema = z.object({
|
|
89
|
+
provider: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
90
|
+
eventTypes: z.array(z.string().regex(/^[a-z0-9][a-z0-9_]*$/)).min(1),
|
|
91
|
+
});
|
|
92
|
+
export type ListenerContribution = z.infer<typeof ListenerContributionSchema>;
|
|
93
|
+
|
|
94
|
+
// A Dockerfile fragment baked into the sandbox image overlay so the extension's tools are present at runtime
|
|
95
|
+
// (a whisper binary, a psql client, …). `fragment` is a checkout-relative path to a file holding ONLY RUN/ENV
|
|
96
|
+
// instructions — the daemon rejects FROM and privileged `# intentic:runtime` directives from extension
|
|
97
|
+
// fragments (those stay daemon-owned), and the owner approves the composed overlay + rebuilds out-of-band.
|
|
98
|
+
export const EnvironmentContributionSchema = z.object({
|
|
99
|
+
fragment: z
|
|
100
|
+
.string()
|
|
101
|
+
.min(1)
|
|
102
|
+
.refine((value) => !value.split("/").includes(".."), { message: "fragment must stay inside the checkout" }),
|
|
103
|
+
});
|
|
104
|
+
export type EnvironmentContribution = z.infer<typeof EnvironmentContributionSchema>;
|
|
105
|
+
|
|
106
|
+
// A field the "+" install dialog renders for a connector's config form (a slug key, a label, secret/optional
|
|
107
|
+
// flags, an optional select, a `when` gate). Mirrors the platform catalog's field shape so the web can render
|
|
108
|
+
// connector cards from installed extensions exactly like core capability cards.
|
|
109
|
+
export const ConnectorFieldSchema = z.object({
|
|
110
|
+
key: z.string().regex(/^[a-zA-Z][a-zA-Z0-9]*$/),
|
|
111
|
+
label: z.string().min(1),
|
|
112
|
+
placeholder: z.string().optional(),
|
|
113
|
+
secret: z.boolean().optional(),
|
|
114
|
+
optional: z.boolean().optional(),
|
|
115
|
+
multiline: z.boolean().optional(),
|
|
116
|
+
default: z.string().optional(),
|
|
117
|
+
options: z.array(z.object({ value: z.string(), label: z.string() })).optional(),
|
|
118
|
+
when: z.object({ key: z.string(), value: z.string() }).optional(),
|
|
119
|
+
});
|
|
120
|
+
export type ConnectorField = z.infer<typeof ConnectorFieldSchema>;
|
|
121
|
+
|
|
122
|
+
// A CLI-tool connector as DATA: the "+" card, the config fields, the env vars the agent's shell gets (value
|
|
123
|
+
// templates over the fields — `${field}` substitutes, `${field:uri}` percent-encodes), the SKILL.md cheatsheet
|
|
124
|
+
// path, and an optional image fragment path (a psql/whisper client). The daemon's cli handler resolves a
|
|
125
|
+
// provider to its spec through the connector registry instead of a hardcoded table, so a connector is one
|
|
126
|
+
// manifest entry + two files, no daemon change.
|
|
127
|
+
export const ConnectorContributionSchema = z.object({
|
|
128
|
+
provider: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
129
|
+
kind: z.literal("cli"),
|
|
130
|
+
catalog: z.object({
|
|
131
|
+
name: z.string().min(1),
|
|
132
|
+
logo: z.string().optional(),
|
|
133
|
+
// An @intentic-app/ui IconName fallback glyph, rendered when no simple-icons `logo` fits the brand.
|
|
134
|
+
icon: z.string().optional(),
|
|
135
|
+
description: z.string().min(1),
|
|
136
|
+
category: z.string().min(1),
|
|
137
|
+
hint: z.string().optional(),
|
|
138
|
+
// The credential-creation walkthrough the install dialog renders (the platform catalog's guide shape).
|
|
139
|
+
guide: z
|
|
140
|
+
.object({
|
|
141
|
+
url: z.string().optional(),
|
|
142
|
+
urlFromField: z.string().optional(),
|
|
143
|
+
path: z.string().optional(),
|
|
144
|
+
linkLabel: z.string().optional(),
|
|
145
|
+
scopes: z.string().optional(),
|
|
146
|
+
steps: z.array(z.string()).optional(),
|
|
147
|
+
})
|
|
148
|
+
.optional(),
|
|
149
|
+
}),
|
|
150
|
+
fields: z.array(ConnectorFieldSchema).min(1),
|
|
151
|
+
env: z.record(z.string().regex(/^[A-Z][A-Z0-9_]*$/), z.string()),
|
|
152
|
+
skill: z.string().min(1),
|
|
153
|
+
fragment: z.string().min(1).optional(),
|
|
154
|
+
});
|
|
155
|
+
export type ConnectorContribution = z.infer<typeof ConnectorContributionSchema>;
|
|
156
|
+
|
|
157
|
+
export const ExtensionManifestSchema = z.object({
|
|
158
|
+
publisher: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
159
|
+
name: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
160
|
+
// The extension's own semver — display/identity only; the installed code identity is the pinned commit sha.
|
|
161
|
+
version: z.string().min(1),
|
|
162
|
+
// Semver range over the host's extension API version (extensionApiVersion) — checked before activation.
|
|
163
|
+
engines: z.object({ intentic: z.string().min(1) }),
|
|
164
|
+
// Repo-relative path of the prebuilt single-file ESM bundle (built with `vue` and `@intentic/extension-api`
|
|
165
|
+
// as externals); absent ⇒ an agent-only extension with no UI entry.
|
|
166
|
+
entry: z
|
|
167
|
+
.string()
|
|
168
|
+
.min(1)
|
|
169
|
+
.refine((value) => !value.split("/").includes(".."), { message: "entry must stay inside the checkout" })
|
|
170
|
+
.optional(),
|
|
171
|
+
// The daemon routes this extension may call through api.sandbox.request/json — each "<METHOD> <path-glob>"
|
|
172
|
+
// where `*` matches one path segment (e.g. "GET /panels", "POST /panels/*/start"). The host refuses any
|
|
173
|
+
// api.sandbox call whose method+path isn't declared here, so an extension's backend reach is explicit and
|
|
174
|
+
// reviewable instead of an ambient client to the whole daemon. Absent ⇒ the extension makes no api.sandbox calls.
|
|
175
|
+
permissions: z.object({ sandbox: z.array(z.string()) }).optional(),
|
|
176
|
+
contributes: z
|
|
177
|
+
.object({
|
|
178
|
+
views: z.array(ViewContributionSchema).optional(),
|
|
179
|
+
viewers: z.array(ViewerContributionSchema).optional(),
|
|
180
|
+
commands: z.array(CommandContributionSchema).optional(),
|
|
181
|
+
settings: z.array(SettingContributionSchema).optional(),
|
|
182
|
+
processes: z.array(ProcessContributionSchema).optional(),
|
|
183
|
+
agent: AgentContributionSchema.optional(),
|
|
184
|
+
environment: EnvironmentContributionSchema.optional(),
|
|
185
|
+
connectors: z.array(ConnectorContributionSchema).optional(),
|
|
186
|
+
listener: ListenerContributionSchema.optional(),
|
|
187
|
+
// A checkout-relative directory of executables the daemon prepends to the AGENT's PATH each turn —
|
|
188
|
+
// how an extension ships a command-line tool for the agent (the CLI-tools path). The files ARE the
|
|
189
|
+
// approved code (they ride the sha-pinned checkout); the daemon only adds the dir to PATH.
|
|
190
|
+
bin: z
|
|
191
|
+
.string()
|
|
192
|
+
.min(1)
|
|
193
|
+
.refine((value) => !value.split("/").includes(".."), { message: "bin must stay inside the checkout" })
|
|
194
|
+
.optional(),
|
|
195
|
+
})
|
|
196
|
+
.optional(),
|
|
197
|
+
});
|
|
198
|
+
export type ExtensionManifest = z.infer<typeof ExtensionManifestSchema>;
|
|
199
|
+
|
|
200
|
+
// The extension's identity everywhere (capability entries, /ext routes, settings namespaces) — derived, never
|
|
201
|
+
// declared, so it can't contradict the publisher/name the install dialog showed.
|
|
202
|
+
export const extensionIdOf = (manifest: Pick<ExtensionManifest, "publisher" | "name">): string => `${manifest.publisher}.${manifest.name}`;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* The sandbox-route permission model. An extension declares in its manifest exactly which daemon routes it may
|
|
2
|
+
* reach through `api.sandbox.request/json`, as "<METHOD> <path-glob>" strings where `*` matches exactly one path
|
|
3
|
+
* segment. The host matches every call against these and refuses an undeclared route — so an extension's backend
|
|
4
|
+
* reach is explicit, diffable, and reviewable rather than an ambient client to the whole daemon. */
|
|
5
|
+
|
|
6
|
+
const escapeRegExp = (literal: string): string => literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7
|
+
|
|
8
|
+
interface CompiledRoute {
|
|
9
|
+
readonly method: string;
|
|
10
|
+
readonly test: (path: string) => boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// "<METHOD> <path-glob>" → a method + an anchored path matcher. Each `*` in the glob matches one path segment
|
|
14
|
+
// ([^/]+); everything else is literal. Throws on a malformed entry so a bad manifest fails loudly at load.
|
|
15
|
+
const compile = (entry: string): CompiledRoute => {
|
|
16
|
+
const spaceIndex = entry.indexOf(" ");
|
|
17
|
+
if (spaceIndex < 0) {
|
|
18
|
+
throw new Error(`invalid sandbox permission "${entry}" — expected "<METHOD> <path-glob>", e.g. "GET /panels"`);
|
|
19
|
+
}
|
|
20
|
+
const method = entry.slice(0, spaceIndex).trim().toUpperCase();
|
|
21
|
+
const glob = entry.slice(spaceIndex + 1).trim();
|
|
22
|
+
const source = `^${glob.split("*").map(escapeRegExp).join("[^/]+")}$`;
|
|
23
|
+
const regex = new RegExp(source);
|
|
24
|
+
return { method, test: (path) => regex.test(path) };
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Whether `method path` is covered by any of the declared permissions. The query string is ignored (routes are
|
|
28
|
+
// matched on path only), and the method is compared case-insensitively.
|
|
29
|
+
export const sandboxRouteAllowed = (permissions: readonly string[], method: string, path: string): boolean => {
|
|
30
|
+
const route = path.split("?")[0] ?? path;
|
|
31
|
+
const wanted = method.toUpperCase();
|
|
32
|
+
return permissions.some((entry) => {
|
|
33
|
+
const compiled = compile(entry);
|
|
34
|
+
return compiled.method === wanted && compiled.test(route);
|
|
35
|
+
});
|
|
36
|
+
};
|
package/src/stream.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* Reading a daemon SSE/ndjson stream — the transport half of `sandbox.request().body`. The daemon emits SSE
|
|
2
|
+
* frames (blank-line separated, each a `data: <JSON>` line, an oRPC event-iterator failure as `event: error`),
|
|
3
|
+
* so consuming a streamed apply/plan/provision means reframing + JSON-parsing. Pure (ReadableStream in, async
|
|
4
|
+
* records out), no deps — extensions bundle it; the shim path never touches it. */
|
|
5
|
+
|
|
6
|
+
// A silent daemon — one that accepts the stream then sends nothing and never closes — would park reader.read()
|
|
7
|
+
// forever, hanging the consumer. A live daemon heartbeats (≤1s) over the stream, so no bytes for this long means
|
|
8
|
+
// the connection is dead: cancel the reader and end the generator instead of waiting indefinitely.
|
|
9
|
+
const SSE_IDLE_MS = 120_000;
|
|
10
|
+
|
|
11
|
+
// Yields each raw SSE frame (the text between blank-line separators), reassembling frames split across chunks.
|
|
12
|
+
// Ends (cancelling the reader) if the daemon goes silent past SSE_IDLE_MS, so a half-open stream can't hang.
|
|
13
|
+
async function* sseFrames(body: ReadableStream<Uint8Array>): AsyncGenerator<string> {
|
|
14
|
+
const reader = body.getReader();
|
|
15
|
+
const decoder = new TextDecoder();
|
|
16
|
+
let buffer = "";
|
|
17
|
+
try {
|
|
18
|
+
for (;;) {
|
|
19
|
+
let timer: ReturnType<typeof setTimeout>;
|
|
20
|
+
const idle = new Promise<"idle">((resolve) => {
|
|
21
|
+
timer = setTimeout(() => resolve("idle"), SSE_IDLE_MS);
|
|
22
|
+
});
|
|
23
|
+
const result = await Promise.race([reader.read(), idle]);
|
|
24
|
+
clearTimeout(timer!);
|
|
25
|
+
if (result === "idle") {
|
|
26
|
+
return; // daemon went silent past the heartbeat window — end rather than hang
|
|
27
|
+
}
|
|
28
|
+
const { done, value } = result;
|
|
29
|
+
if (done) {
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
buffer += decoder.decode(value, { stream: true });
|
|
33
|
+
let separator = buffer.indexOf("\n\n");
|
|
34
|
+
while (separator !== -1) {
|
|
35
|
+
yield buffer.slice(0, separator);
|
|
36
|
+
buffer = buffer.slice(separator + 2);
|
|
37
|
+
separator = buffer.indexOf("\n\n");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} finally {
|
|
41
|
+
await reader.cancel().catch(() => {});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const dataOf = (frame: string): unknown => {
|
|
46
|
+
const line = frame.split("\n").find((entry) => entry.startsWith("data:"));
|
|
47
|
+
if (line === undefined) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const payload = line.slice(5).trim();
|
|
51
|
+
if (payload.length === 0) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(payload);
|
|
56
|
+
} catch {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Reads a daemon stream as parsed ndjson records. An `event: error` frame is normalized to a
|
|
62
|
+
// `{ kind: "error", message }` record so callers surface it and stop even when the daemon couldn't emit its
|
|
63
|
+
// own error line; malformed frames are skipped.
|
|
64
|
+
export async function* readDaemonStream(body: ReadableStream<Uint8Array>): AsyncGenerator<Record<string, unknown>> {
|
|
65
|
+
for await (const frame of sseFrames(body)) {
|
|
66
|
+
const parsed = dataOf(frame);
|
|
67
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const record = parsed as Record<string, unknown>;
|
|
71
|
+
const isError =
|
|
72
|
+
frame
|
|
73
|
+
.split("\n")
|
|
74
|
+
.find((line) => line.startsWith("event:"))
|
|
75
|
+
?.slice(6)
|
|
76
|
+
.trim() === "error";
|
|
77
|
+
if (isError) {
|
|
78
|
+
yield { kind: "error", message: typeof record["message"] === "string" ? record["message"] : "Provisioning failed." };
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
yield record;
|
|
82
|
+
}
|
|
83
|
+
}
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// The extension API's protocol version — the value `engines.intentic` ranges are matched against at load, and
|
|
2
|
+
// the value the host reports as IntenticApi.apiVersion. Bumped ONLY with the published package: additive
|
|
3
|
+
// surface = minor, breaking = major. This package is the one deliberate exception to the repo's no-legacy rule.
|
|
4
|
+
export const extensionApiVersion = "0.2.0";
|