pi-widget-host 0.3.6 → 0.3.11
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/CHANGELOG.md +25 -7
- package/README.md +2 -0
- package/docs/README.md +2 -2
- package/docs/protocol.md +62 -0
- package/docs/provider-example.md +13 -0
- package/extensions/index.ts +14 -0
- package/lib/demo-provider.ts +3 -16
- package/lib/policy.ts +30 -17
- package/package.json +65 -65
package/CHANGELOG.md
CHANGED
|
@@ -4,18 +4,39 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project follows semantic versioning.
|
|
6
6
|
|
|
7
|
+
## [0.3.11] - 2026-09-27
|
|
8
|
+
|
|
9
|
+
- chore: periodic patch bump after 7+ days without npm publish
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
All notable changes to this project will be documented in this file.
|
|
16
|
+
|
|
17
|
+
This project follows semantic versioning.
|
|
18
|
+
## [0.3.10] - 2026-09-28
|
|
19
|
+
|
|
20
|
+
- chore: periodic patch bump after 7+ days without npm publish
|
|
21
|
+
## [0.3.9] - 2026-09-28
|
|
22
|
+
|
|
23
|
+
- chore: periodic patch bump after 7+ days without npm publish
|
|
24
|
+
## [0.3.8] - 2026-09-28
|
|
25
|
+
|
|
26
|
+
- chore: periodic patch bump after 7+ days without npm publish
|
|
27
|
+
## [0.3.7] - 2026-09-28
|
|
28
|
+
|
|
29
|
+
- chore: periodic patch bump after 7+ days without npm publish
|
|
7
30
|
## [0.3.6] - 2026-08-22
|
|
8
31
|
|
|
9
32
|
### Changed
|
|
10
33
|
|
|
11
34
|
- Merge the 2026-08-22 managed OSS dependency and maintenance PR batch.
|
|
12
|
-
|
|
13
35
|
## [0.3.5] - 2026-08-04
|
|
14
36
|
|
|
15
37
|
### Changed
|
|
16
38
|
|
|
17
39
|
- Bump package version for the Discord release webhook verification.
|
|
18
|
-
|
|
19
40
|
## [0.3.4] - 2026-07-21
|
|
20
41
|
|
|
21
42
|
### Added
|
|
@@ -26,26 +47,22 @@ This project follows semantic versioning.
|
|
|
26
47
|
|
|
27
48
|
- CONTRIBUTING release instructions now match the auto-release and publish workflow (no `follow-tags`).
|
|
28
49
|
- Dependency updates for `pi-widget-core` and development tooling.
|
|
29
|
-
|
|
30
50
|
## [0.3.3] - 2026-07-04
|
|
31
51
|
|
|
32
52
|
### Added
|
|
33
53
|
|
|
34
54
|
- Buy Me a Coffee sponsor button to README and native GitHub funding link via `.github/FUNDING.yml`.
|
|
35
|
-
|
|
36
55
|
## [0.3.2] - 2026-06-26
|
|
37
56
|
|
|
38
57
|
### Fixed
|
|
39
58
|
|
|
40
59
|
- npm Trusted Publishing publish retry after registry configuration fix (no functional changes from 0.3.1).
|
|
41
|
-
|
|
42
60
|
## [0.3.1] - 2026-06-25
|
|
43
61
|
|
|
44
62
|
### Changed
|
|
45
63
|
|
|
46
64
|
- README install and development guidance now matches the current Pi OSS template baseline, including project-local install, `pi -e npm:pi-widget-host`, and `npm run pack:check` (`npm pack --dry-run`) validation in the public docs flow.
|
|
47
65
|
- `Package contents` now lists the actual shipped paths instead of unused template resource directories.
|
|
48
|
-
|
|
49
66
|
## [0.3.0] - 2026-06-24
|
|
50
67
|
|
|
51
68
|
### Added
|
|
@@ -56,7 +73,6 @@ This project follows semantic versioning.
|
|
|
56
73
|
### Changed
|
|
57
74
|
|
|
58
75
|
- Minor semver bump marking the completed Host-only MVP: event boost, known tags, registry protocol, and demo-provider dogfooding path.
|
|
59
|
-
|
|
60
76
|
## [0.2.0] - 2026-06-15
|
|
61
77
|
|
|
62
78
|
### Added
|
|
@@ -71,3 +87,5 @@ This project follows semantic versioning.
|
|
|
71
87
|
### Changed
|
|
72
88
|
|
|
73
89
|
- Replaced template placeholders and removed template-only skill, prompt, and theme resources.
|
|
90
|
+
## Unreleased
|
|
91
|
+
|
package/README.md
CHANGED
|
@@ -99,6 +99,8 @@ Future provider packages can publish to the host without importing this package
|
|
|
99
99
|
|
|
100
100
|
See [`docs/protocol.md`](docs/protocol.md) and the copy-paste [`minimal provider example`](docs/provider-example.md).
|
|
101
101
|
|
|
102
|
+
Preset time blocks (`morning`, `day`, `evening`, `night`) follow the host machine's local hour with no timezone override — see [Limitations](docs/protocol.md#limitations) for how this affects presets such as `focus-day` and `night-owl`.
|
|
103
|
+
|
|
102
104
|
## Built-in demo provider
|
|
103
105
|
|
|
104
106
|
The built-in demo provider exists to prove the host loop first:
|
package/docs/README.md
CHANGED
|
@@ -7,8 +7,8 @@ Entry point for `pi-widget-host` maintainer and provider-author docs.
|
|
|
7
7
|
| Doc | Purpose |
|
|
8
8
|
|---|---|
|
|
9
9
|
| [`config.md`](config.md) | `HostConfig` field contract, defaults, and `normalizeConfig` coercion rules. |
|
|
10
|
-
| [`protocol.md`](protocol.md) | Registry protocol reference (`globalThis`, required fields, tags, TTL). |
|
|
11
|
-
| [`provider-example.md`](provider-example.md) | Minimal copy-paste provider that publishes through the registry. |
|
|
10
|
+
| [`protocol.md`](protocol.md) | Registry protocol reference (`globalThis`, required fields, tags, TTL). Includes [time-block timezone limitations](protocol.md#limitations) and [scheduling examples](protocol.md#scheduling-examples-local-hour-assumptions). |
|
|
11
|
+
| [`provider-example.md`](provider-example.md) | Minimal copy-paste provider that publishes through the registry. Notes [timezone assumptions](provider-example.md#timezone-assumptions) for `updatedAt` vs preset time blocks. |
|
|
12
12
|
| [`release.md`](release.md) | npm Trusted Publishing workflow and CI release automation. |
|
|
13
13
|
|
|
14
14
|
## Maintenance context
|
package/docs/protocol.md
CHANGED
|
@@ -51,3 +51,65 @@ type WidgetHostRegistry = {
|
|
|
51
51
|
- `ttlMs` + `updatedAt` drive stale exclusion
|
|
52
52
|
- providers render final lines themselves; the host only picks a winner
|
|
53
53
|
- the host can mute providers from config without uninstalling the package
|
|
54
|
+
|
|
55
|
+
## Limitations
|
|
56
|
+
|
|
57
|
+
### Time blocks use the host's local timezone
|
|
58
|
+
|
|
59
|
+
Policy evaluation calls `detectTimeBlock(now)` in `lib/policy.ts`, which reads `now.getHours()` — the **host machine's local hour** in the process timezone. There is no `HostConfig` field or environment variable to override the timezone or shift block boundaries.
|
|
60
|
+
|
|
61
|
+
Block boundaries (local hour, inclusive start / exclusive end unless noted):
|
|
62
|
+
|
|
63
|
+
| Block | Local hour range |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `morning` | 05:00–10:59 |
|
|
66
|
+
| `day` | 11:00–16:59 |
|
|
67
|
+
| `evening` | 17:00–21:59 |
|
|
68
|
+
| `night` | 22:00–04:59 |
|
|
69
|
+
|
|
70
|
+
Because presets are keyed by these blocks, the same `presetId` can behave differently on machines in different timezones or when the OS timezone changes. For example:
|
|
71
|
+
|
|
72
|
+
- **`focus-day`** keeps the shared slot active during `morning`, `day`, and `evening`, but stays **silent at `night`**. A provider that looks "blocked" at 23:00 UTC may still be eligible at 23:00 JST on a Tokyo-local host.
|
|
73
|
+
- **`night-owl`** stays **silent during `morning` and `day`**, then allows the slot in `evening` and `night`. Travel or remote machines can flip eligibility without any config change.
|
|
74
|
+
|
|
75
|
+
When debugging provider priority or preset behavior, check the host's local time and current block before assuming a config bug.
|
|
76
|
+
|
|
77
|
+
### Scheduling examples (local hour assumptions)
|
|
78
|
+
|
|
79
|
+
The examples below mirror `tests/time-block-policy.test.ts`. Each `Date` is constructed with the host's **local** calendar fields (`new Date(year, month, day, hour, …)`), so the resulting time block follows the machine timezone, not UTC.
|
|
80
|
+
|
|
81
|
+
**Example 1 — `night-owl` stays silent during work hours**
|
|
82
|
+
|
|
83
|
+
With `presetId: "night-owl"` and one eligible demo provider:
|
|
84
|
+
|
|
85
|
+
| Local time on host | `detectTimeBlock` | Widget slot |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| 07:00 | `morning` | silent |
|
|
88
|
+
| 13:00 | `day` | silent |
|
|
89
|
+
| 19:00 | `evening` | active |
|
|
90
|
+
| 23:00 | `night` | active |
|
|
91
|
+
|
|
92
|
+
The same saved preset can look "broken" when you compare against UTC. At **23:00 UTC** on a UTC host the block is `night` and the slot is active; on a **Tokyo-local host** that instant is **08:00 JST** (`morning`), so `night-owl` correctly stays silent.
|
|
93
|
+
|
|
94
|
+
**Example 2 — `focus-day` vs `always-demo` at local night**
|
|
95
|
+
|
|
96
|
+
At **23:30 local** with one eligible provider:
|
|
97
|
+
|
|
98
|
+
- `always-demo` — slot stays active (`night` block is allowed).
|
|
99
|
+
- `focus-day` — slot is silent (`night` block sets `allowedProviderIds: []`).
|
|
100
|
+
|
|
101
|
+
**Example 3 — TTL refresh scheduling is UTC-based**
|
|
102
|
+
|
|
103
|
+
Stale exclusion and the host's stale-TTL `setTimeout` use `updatedAt` (ISO-8601 UTC) plus `ttlMs`. That path does **not** read local hour boundaries:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
registry.set({
|
|
107
|
+
providerId: "example.stale-check",
|
|
108
|
+
available: true,
|
|
109
|
+
lines: ["hello"],
|
|
110
|
+
updatedAt: new Date().toISOString(), // UTC instant
|
|
111
|
+
ttlMs: 90_000,
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
A provider published at `2026-06-15T12:00:00.000Z` with `ttlMs: 60_000` goes stale at `12:01:00Z` on every host, regardless of preset or local time block. Do not mix this TTL clock with preset time-block scheduling when debugging.
|
package/docs/provider-example.md
CHANGED
|
@@ -33,3 +33,16 @@ registry?.set({
|
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Required fields are `providerId`, `available`, `lines`, and `updatedAt`. Optional fields such as `priority`, `tags`, `mode`, and `ttlMs` help the host choose between eligible providers. See [`protocol.md`](protocol.md) for the full registry shape and host selection notes.
|
|
36
|
+
|
|
37
|
+
## Timezone assumptions
|
|
38
|
+
|
|
39
|
+
Two different clocks appear in this example:
|
|
40
|
+
|
|
41
|
+
| Field / mechanism | Time basis | Used for |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `updatedAt` (`toISOString()`) | UTC instant | stale exclusion and stale-TTL refresh scheduling |
|
|
44
|
+
| Preset time blocks (`morning`, `day`, …) | Host machine local hour | when a saved preset allows or silences the shared slot |
|
|
45
|
+
|
|
46
|
+
`new Date().toISOString()` in the snippet above is correct for TTL bookkeeping. It does **not** pin the provider to a local time block — the host evaluates blocks separately via `detectTimeBlock(now)` when applying preset policy.
|
|
47
|
+
|
|
48
|
+
Tags cannot gate availability: the host scores `tags` only against the current block's `preferredTags` (plus the `playing-now` / `matchday` event boost) to adjust `effectivePriority`. Eligibility still depends on registry state (`available`, `lines`, stale TTL, host mutes) and the preset's `allowedProviderIds`. If your provider must appear only during certain local hours, enforce that in your own publish loop; the host will still classify the current block from the **process local timezone**. See [Limitations — scheduling examples](protocol.md#scheduling-examples-local-hour-assumptions) for preset walkthroughs (`focus-day`, `night-owl`) and a UTC-vs-local debugging scenario.
|
package/extensions/index.ts
CHANGED
|
@@ -258,3 +258,17 @@ export default function widgetHostExtension(pi: ExtensionAPI) {
|
|
|
258
258
|
},
|
|
259
259
|
});
|
|
260
260
|
}
|
|
261
|
+
|
|
262
|
+
export function resetHostExtensionStateForTests(): void {
|
|
263
|
+
clearStaleTimer();
|
|
264
|
+
registryDispose?.();
|
|
265
|
+
registryDispose = undefined;
|
|
266
|
+
stopDemoProviderHeartbeat();
|
|
267
|
+
uiBridge = undefined;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export function isRegistryWatcherActiveForTests(): boolean {
|
|
271
|
+
return registryDispose !== undefined;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export { ensureRegistryWatcher, refreshHostWidget };
|
package/lib/demo-provider.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createProviderRuntime, type ProviderRuntime } from "pi-widget-core/provider";
|
|
2
2
|
import { readHostConfig } from "./config.ts";
|
|
3
|
-
import { detectTimeBlock } from "./policy.ts";
|
|
3
|
+
import { DEFAULT_PRESET_ID, detectTimeBlock, getBlockPreferredTags, getPreset } from "./policy.ts";
|
|
4
4
|
import { DEMO_PROVIDER_ID, type HostConfig, type ProviderEntry } from "./types.ts";
|
|
5
5
|
|
|
6
6
|
const HEARTBEAT_MS = 30_000;
|
|
@@ -14,20 +14,6 @@ function ensureRuntime(): ProviderRuntime {
|
|
|
14
14
|
return runtime;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
function baseTagsForBlock(block: ReturnType<typeof detectTimeBlock>): string[] {
|
|
18
|
-
switch (block) {
|
|
19
|
-
case "morning":
|
|
20
|
-
return ["music", "idle"];
|
|
21
|
-
case "day":
|
|
22
|
-
return ["sports", "idle"];
|
|
23
|
-
case "evening":
|
|
24
|
-
return ["music", "sports"];
|
|
25
|
-
case "night":
|
|
26
|
-
default:
|
|
27
|
-
return ["idle", "music"];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
17
|
function readEventTags(): string[] {
|
|
32
18
|
const tags: string[] = [];
|
|
33
19
|
if (["1", "true", "yes"].includes(String(process.env.PI_WIDGET_HOST_DEMO_PLAYING_NOW ?? "").toLowerCase())) {
|
|
@@ -41,7 +27,8 @@ function readEventTags(): string[] {
|
|
|
41
27
|
|
|
42
28
|
export function buildDemoProviderEntry(config: HostConfig, now = new Date()): ProviderEntry {
|
|
43
29
|
const block = detectTimeBlock(now);
|
|
44
|
-
const
|
|
30
|
+
const preferredTags = getBlockPreferredTags(getPreset(DEFAULT_PRESET_ID), block);
|
|
31
|
+
const tags = [...new Set([...preferredTags, ...readEventTags()])];
|
|
45
32
|
|
|
46
33
|
return {
|
|
47
34
|
providerId: DEMO_PROVIDER_ID,
|
package/lib/policy.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type HostConfig, type HostTimeBlock, type KnownHostTag, type PolicyEval
|
|
|
2
2
|
|
|
3
3
|
export const DEFAULT_PRESET_ID = "always-demo";
|
|
4
4
|
export const KNOWN_HOST_TAGS: readonly KnownHostTag[] = ["music", "sports", "playing-now", "matchday", "idle"] as const;
|
|
5
|
+
const KNOWN_HOST_TAG_SET = new Set<string>(KNOWN_HOST_TAGS);
|
|
5
6
|
|
|
6
7
|
export const PRESET_OPTIONS: readonly PolicyPreset[] = [
|
|
7
8
|
{
|
|
@@ -39,8 +40,14 @@ export const PRESET_OPTIONS: readonly PolicyPreset[] = [
|
|
|
39
40
|
},
|
|
40
41
|
];
|
|
41
42
|
|
|
43
|
+
const PRESET_BY_ID = new Map(PRESET_OPTIONS.map((preset) => [preset.id, preset]));
|
|
44
|
+
|
|
42
45
|
export function getPreset(id: string | undefined): PolicyPreset {
|
|
43
|
-
return
|
|
46
|
+
return PRESET_BY_ID.get(id ?? DEFAULT_PRESET_ID) ?? PRESET_OPTIONS[0]!;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function getBlockPreferredTags(preset: PolicyPreset, block: HostTimeBlock): readonly KnownHostTag[] {
|
|
50
|
+
return preset.blocks[block].preferredTags ?? [];
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
export function detectTimeBlock(now = new Date()): HostTimeBlock {
|
|
@@ -63,29 +70,32 @@ export function isEntryStale(entry: Pick<ProviderEntry, "updatedAt" | "ttlMs">,
|
|
|
63
70
|
return typeof remaining === "number" ? remaining <= 0 : false;
|
|
64
71
|
}
|
|
65
72
|
|
|
66
|
-
function tagScore(knownTags: KnownHostTag
|
|
73
|
+
function tagScore(knownTags: ReadonlySet<KnownHostTag>, preferredTags: readonly KnownHostTag[] | undefined): number {
|
|
67
74
|
if (!preferredTags || preferredTags.length === 0) return 0;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
let best = 0;
|
|
76
|
+
for (let index = 0; index < preferredTags.length; index++) {
|
|
77
|
+
const tag = preferredTags[index]!;
|
|
78
|
+
if (!knownTags.has(tag)) continue;
|
|
79
|
+
best = Math.max(best, Math.max(40 - index * 10, 10));
|
|
80
|
+
}
|
|
81
|
+
return best;
|
|
72
82
|
}
|
|
73
83
|
|
|
74
|
-
function eventBoost(knownTags: KnownHostTag
|
|
84
|
+
function eventBoost(knownTags: ReadonlySet<KnownHostTag>): number {
|
|
75
85
|
let boost = 0;
|
|
76
|
-
if (knownTags.
|
|
77
|
-
if (knownTags.
|
|
86
|
+
if (knownTags.has("playing-now")) boost += 100;
|
|
87
|
+
if (knownTags.has("matchday")) boost += 80;
|
|
78
88
|
return boost;
|
|
79
89
|
}
|
|
80
90
|
|
|
81
|
-
function normalizeKnownTags(tags: string[] | undefined): KnownHostTag
|
|
91
|
+
function normalizeKnownTags(tags: string[] | undefined): Set<KnownHostTag> {
|
|
82
92
|
const known = new Set<KnownHostTag>();
|
|
83
93
|
for (const tag of tags ?? []) {
|
|
84
|
-
if (
|
|
94
|
+
if (KNOWN_HOST_TAG_SET.has(tag)) {
|
|
85
95
|
known.add(tag as KnownHostTag);
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
|
-
return
|
|
98
|
+
return known;
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
export function describePreset(preset: PolicyPreset): string {
|
|
@@ -103,13 +113,16 @@ export function evaluateProviderEntries(entries: readonly ProviderEntry[], confi
|
|
|
103
113
|
const preset = getPreset(config.presetId);
|
|
104
114
|
const timeBlock = detectTimeBlock(now);
|
|
105
115
|
const blockPolicy = preset.blocks[timeBlock];
|
|
116
|
+
const mutedProviderIds = new Set(config.mutedProviderIds);
|
|
117
|
+
const allowedProviderIds =
|
|
118
|
+
blockPolicy.allowedProviderIds === undefined ? undefined : new Set(blockPolicy.allowedProviderIds);
|
|
106
119
|
|
|
107
120
|
const providerStates = entries.map<ProviderState>((entry) => {
|
|
108
|
-
const
|
|
109
|
-
const isMuted =
|
|
121
|
+
const knownTagSet = normalizeKnownTags(entry.tags);
|
|
122
|
+
const isMuted = mutedProviderIds.has(entry.providerId);
|
|
110
123
|
const isStale = isEntryStale(entry, now);
|
|
111
124
|
const hasLines = Array.isArray(entry.lines) && entry.lines.length > 0;
|
|
112
|
-
const isAllowed =
|
|
125
|
+
const isAllowed = allowedProviderIds === undefined || allowedProviderIds.has(entry.providerId);
|
|
113
126
|
const reasons: string[] = [];
|
|
114
127
|
|
|
115
128
|
if (!entry.available) reasons.push("provider reported unavailable");
|
|
@@ -118,7 +131,7 @@ export function evaluateProviderEntries(entries: readonly ProviderEntry[], confi
|
|
|
118
131
|
if (isMuted) reasons.push("muted in host config");
|
|
119
132
|
if (isStale) reasons.push("stale ttl");
|
|
120
133
|
|
|
121
|
-
const effectivePriority = (entry.priority ?? 0) + tagScore(
|
|
134
|
+
const effectivePriority = (entry.priority ?? 0) + tagScore(knownTagSet, blockPolicy.preferredTags) + eventBoost(knownTagSet);
|
|
122
135
|
|
|
123
136
|
let effectiveStatus: ProviderState["effectiveStatus"] = "eligible";
|
|
124
137
|
if (isMuted) {
|
|
@@ -133,7 +146,7 @@ export function evaluateProviderEntries(entries: readonly ProviderEntry[], confi
|
|
|
133
146
|
...entry,
|
|
134
147
|
effectivePriority,
|
|
135
148
|
effectiveStatus,
|
|
136
|
-
knownTags,
|
|
149
|
+
knownTags: [...knownTagSet],
|
|
137
150
|
reasons,
|
|
138
151
|
isMuted,
|
|
139
152
|
isStale,
|
package/package.json
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-widget-host",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Host package for managing one shared Pi widget slot across multiple providers with preset policies and a built-in demo provider.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"author": "Keisu",
|
|
8
|
-
"keywords": [
|
|
9
|
-
"pi-package",
|
|
10
|
-
"pi-extension",
|
|
11
|
-
"widget",
|
|
12
|
-
"host",
|
|
13
|
-
"display-policy"
|
|
14
|
-
],
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/eiei114/pi-widget-host.git"
|
|
18
|
-
},
|
|
19
|
-
"bugs": {
|
|
20
|
-
"url": "https://github.com/eiei114/pi-widget-host/issues"
|
|
21
|
-
},
|
|
22
|
-
"homepage": "https://github.com/eiei114/pi-widget-host#readme",
|
|
23
|
-
"files": [
|
|
24
|
-
"extensions/",
|
|
25
|
-
"lib/",
|
|
26
|
-
"docs/",
|
|
27
|
-
"README.md",
|
|
28
|
-
"LICENSE",
|
|
29
|
-
"CHANGELOG.md"
|
|
30
|
-
],
|
|
31
|
-
"scripts": {
|
|
32
|
-
"typecheck": "tsc --noEmit",
|
|
33
|
-
"test": "node --import tsx --test tests/*.test.ts",
|
|
34
|
-
"ci": "npm run typecheck && npm test && npm run pack:check",
|
|
35
|
-
"pack:check": "npm pack --dry-run"
|
|
36
|
-
},
|
|
37
|
-
"engines": {
|
|
38
|
-
"node": ">=20"
|
|
39
|
-
},
|
|
40
|
-
"pi": {
|
|
41
|
-
"extensions": [
|
|
42
|
-
"./extensions/index.ts"
|
|
43
|
-
]
|
|
44
|
-
},
|
|
45
|
-
"publishConfig": {
|
|
46
|
-
"access": "public"
|
|
47
|
-
},
|
|
48
|
-
"dependencies": {
|
|
49
|
-
"pi-widget-core": "^0.1.
|
|
50
|
-
},
|
|
51
|
-
"peerDependencies": {
|
|
52
|
-
"@earendil-works/pi-coding-agent": "*"
|
|
53
|
-
},
|
|
54
|
-
"peerDependenciesMeta": {
|
|
55
|
-
"@earendil-works/pi-coding-agent": {
|
|
56
|
-
"optional": true
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
"devDependencies": {
|
|
60
|
-
"@earendil-works/pi-coding-agent": "latest",
|
|
61
|
-
"@types/node": "^26.0.0",
|
|
62
|
-
"tsx": "^4.20.6",
|
|
63
|
-
"typescript": "^7.0.2"
|
|
64
|
-
}
|
|
65
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-widget-host",
|
|
3
|
+
"version": "0.3.11",
|
|
4
|
+
"description": "Host package for managing one shared Pi widget slot across multiple providers with preset policies and a built-in demo provider.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Keisu",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"pi-package",
|
|
10
|
+
"pi-extension",
|
|
11
|
+
"widget",
|
|
12
|
+
"host",
|
|
13
|
+
"display-policy"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/eiei114/pi-widget-host.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/eiei114/pi-widget-host/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/eiei114/pi-widget-host#readme",
|
|
23
|
+
"files": [
|
|
24
|
+
"extensions/",
|
|
25
|
+
"lib/",
|
|
26
|
+
"docs/",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"CHANGELOG.md"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"test": "node --import tsx --test tests/*.test.ts",
|
|
34
|
+
"ci": "npm run typecheck && npm test && npm run pack:check",
|
|
35
|
+
"pack:check": "npm pack --dry-run"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20"
|
|
39
|
+
},
|
|
40
|
+
"pi": {
|
|
41
|
+
"extensions": [
|
|
42
|
+
"./extensions/index.ts"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"pi-widget-core": "^0.1.4"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"@earendil-works/pi-coding-agent": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@earendil-works/pi-coding-agent": "latest",
|
|
61
|
+
"@types/node": "^26.0.0",
|
|
62
|
+
"tsx": "^4.20.6",
|
|
63
|
+
"typescript": "^7.0.2"
|
|
64
|
+
}
|
|
65
|
+
}
|