@pellux/goodvibes-agent 1.5.7 → 1.5.8
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 +9 -3
- package/README.md +1 -1
- package/dist/package/main.js +28 -89
- package/package.json +1 -1
- package/src/agent/memory-prompt.ts +3 -3
- package/src/agent/operator-actions.ts +1 -1
- package/src/agent/prompt-context-receipts.ts +3 -3
- package/src/agent/session-registration.ts +1 -1
- package/src/agent/vibe-file.ts +5 -5
- package/src/cli/local-library-command-shared.ts +1 -1
- package/src/cli/memory-command.ts +9 -6
- package/src/cli/resume-relaunch-notice.ts +1 -1
- package/src/cli/tui-startup.ts +1 -1
- package/src/config/credential-status.ts +1 -1
- package/src/config/index.ts +1 -1
- package/src/config/secrets.ts +1 -1
- package/src/core/conversation-rendering.ts +2 -2
- package/src/core/system-message-noise.ts +3 -3
- package/src/core/thinking-overlay.ts +1 -1
- package/src/input/agent-workspace-basic-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-basic-command-editors.ts +1 -1
- package/src/input/agent-workspace-calendar-connect-editor.ts +1 -1
- package/src/input/agent-workspace-calendar-oauth-editor.ts +1 -1
- package/src/input/agent-workspace-calendar-subscribe-editor.ts +1 -1
- package/src/input/agent-workspace-command-editor-engine.ts +2 -2
- package/src/input/agent-workspace-direct-editor-submission.ts +1 -1
- package/src/input/agent-workspace-email-connect-editor.ts +1 -1
- package/src/input/agent-workspace-live-counters.ts +1 -1
- package/src/input/agent-workspace-settings.ts +1 -1
- package/src/input/agent-workspace-snapshot-builders.ts +2 -2
- package/src/input/agent-workspace-snapshot-config.ts +1 -1
- package/src/input/agent-workspace-snapshot.ts +9 -9
- package/src/input/agent-workspace-types.ts +4 -4
- package/src/input/agent-workspace.ts +1 -1
- package/src/input/commands/calendar-connect-runtime.ts +1 -1
- package/src/input/commands/calendar-subscription-runtime.ts +2 -2
- package/src/input/commands/operator-actions-runtime.ts +1 -1
- package/src/input/commands/session-content.ts +1 -1
- package/src/input/commands/session-workflow.ts +1 -1
- package/src/input/feed-context-factory.ts +4 -4
- package/src/input/handler-feed.ts +9 -9
- package/src/input/handler.ts +1 -1
- package/src/input/panel-paste-flood-guard.ts +3 -3
- package/src/input/settings-modal.ts +1 -1
- package/src/main.ts +4 -4
- package/src/renderer/agent-workspace-context-lines.ts +1 -1
- package/src/renderer/startup-theme-probe.ts +1 -1
- package/src/renderer/status-glyphs.ts +2 -2
- package/src/renderer/terminal-bg-probe.ts +1 -1
- package/src/renderer/terminal-escapes.ts +3 -2
- package/src/renderer/theme-mode-config.ts +2 -2
- package/src/renderer/theme.ts +4 -4
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/ui-factory.ts +1 -1
- package/src/renderer/ui-primitives.ts +2 -2
- package/src/runtime/bootstrap-core.ts +2 -2
- package/src/runtime/bootstrap.ts +3 -3
- package/src/runtime/calendar-boot-refresh.ts +1 -1
- package/src/runtime/lan-scan-consent.ts +1 -1
- package/src/runtime/services.ts +7 -7
- package/src/runtime/terminal-output-guard.ts +1 -1
- package/src/runtime/ui-services.ts +1 -1
- package/src/shell/agent-workspace-fullscreen.ts +1 -1
- package/src/shell/terminal-focus-mode.ts +9 -9
- package/src/shell/ui-openers.ts +1 -1
- package/src/tools/agent-harness-operator-methods.ts +1 -1
- package/src/tools/agent-harness-personal-ops-discovery.ts +2 -2
- package/src/tools/agent-harness-personal-ops-lanes.ts +1 -1
- package/src/tools/agent-harness-personal-ops-types.ts +1 -1
- package/src/tools/agent-harness-prompt-context.ts +3 -3
- package/src/tools/agent-local-registry-memory.ts +1 -1
- package/src/tools/agent-operator-method-tool.ts +1 -1
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Product-facing release notes for GoodVibes Agent.
|
|
4
4
|
|
|
5
|
+
## 1.5.8 - 2026-07-06
|
|
6
|
+
|
|
7
|
+
- The `memory` CLI command (`goodvibes-agent memory ...`) now writes to the same shared cross-surface memory store that the runtime, the terminal UI, and the SDK already read and write. Previously the CLI opened its own private database, so a memory added from the CLI was invisible everywhere else; a memory added from the CLI is now visible in the Agent runtime, the TUI, and the SDK, and vice versa.
|
|
8
|
+
- Memory records written by older CLI versions are not lost: the runtime's existing startup memory merge already reads from the exact path the old CLI wrote to, so those older records are folded into the shared store automatically the next time the runtime starts. No manual migration step is needed.
|
|
9
|
+
- Documentation and code-comment hygiene: internal planning shorthand was replaced with plain language in comments, test names, and past changelog entries. No behavior change.
|
|
10
|
+
|
|
5
11
|
## 1.5.7 - 2026-07-06
|
|
6
12
|
|
|
7
|
-
- v1.5.7 is a patch on the 1.5 line that
|
|
8
|
-
- Adopted the platform's shared credential-status read
|
|
9
|
-
- Completed the memory-unification boot follow-ups
|
|
13
|
+
- v1.5.7 is a patch on the 1.5 line that completes the platform-SDK adoption started in 1.5.6. The fullscreen Agent workspace, Agent-local behavior, isolated Agent Knowledge, connected-host operator integration, and explicit side-effect boundaries all stay in force; the bundled 1.0.0 GoodVibes platform SDK is unchanged.
|
|
14
|
+
- Adopted the platform's shared credential-status read. When the Agent acts as a client of a connected GoodVibes host, it now reads credential *status* — whether each shared-store credential is configured and usable — over the daemon's `credentials.get` route, and renders it honestly: a host with no shared credential store, an older host that does not serve the route yet, or an unreachable host all report a plain "status unavailable" reason. It never shows a fabricated "configured" and never carries a secret value over the wire. Secret *resolution* for provider auth is unchanged and stays local; API keys remain environment-only and are never persisted.
|
|
15
|
+
- Completed the memory-unification boot follow-ups. At startup the Agent now folds any legacy per-surface memory into the single cross-surface store and shows the fold report (nothing is silently dropped), migrates existing VIBE.md personality files into durable persona records exactly once — guarded by a persisted marker so the same file is never re-imported into near-duplicate records — and builds the VIBE prompt as a projection of those persona records. The projection preserves the precedence rule verbatim: these vibe instructions are followed only when they do not conflict with explicit user instructions, safety policy, tool contracts, confirmation requirements, or secret-handling rules.
|
|
10
16
|
- No change to your conversations, skills, routines, or operator confirmation gates beyond the visibility and memory adoption above.
|
|
11
17
|
|
|
12
18
|
## 1.5.6 - 2026-07-06
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# GoodVibes Agent
|
|
2
2
|
|
|
3
3
|
[](https://opensource.org/licenses/MIT)
|
|
4
|
-
[](#install)
|
|
5
5
|
|
|
6
6
|
GoodVibes Agent is the installable autonomous operator assistant for GoodVibes. It keeps the existing terminal renderer and workspace bones, but the product goal is different from a vibecoding harness: the user should experience one assistant that can chat, plan, remember, research, schedule, send, generate, run visible agents, and operate the GoodVibes daemon contract with clear confirmation gates.
|
|
7
7
|
|
package/dist/package/main.js
CHANGED
|
@@ -459642,23 +459642,6 @@ function createSchema2(db) {
|
|
|
459642
459642
|
`);
|
|
459643
459643
|
db.run(`CREATE INDEX IF NOT EXISTS idx_knowledge_schedules_job_id ON knowledge_schedules(job_id)`);
|
|
459644
459644
|
}
|
|
459645
|
-
function getKnowledgeSchemaStatements() {
|
|
459646
|
-
const statements = [];
|
|
459647
|
-
createSchema2({
|
|
459648
|
-
run(sql) {
|
|
459649
|
-
const normalized = sql.trim();
|
|
459650
|
-
if (normalized.length > 0)
|
|
459651
|
-
statements.push(normalized);
|
|
459652
|
-
}
|
|
459653
|
-
});
|
|
459654
|
-
return statements;
|
|
459655
|
-
}
|
|
459656
|
-
function renderKnowledgeSchemaSql() {
|
|
459657
|
-
return `${getKnowledgeSchemaStatements().map((statement) => statement.endsWith(";") ? statement : `${statement};`).join(`
|
|
459658
|
-
|
|
459659
|
-
`)}
|
|
459660
|
-
`;
|
|
459661
|
-
}
|
|
459662
459645
|
function rowObject(columns, values2) {
|
|
459663
459646
|
return Object.fromEntries(columns.map((column, index) => [column, values2[index]]));
|
|
459664
459647
|
}
|
|
@@ -772974,9 +772957,6 @@ var init_ingest = __esm(() => {
|
|
|
772974
772957
|
// node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/browser-history/index.js
|
|
772975
772958
|
var init_browser_history = __esm(() => {
|
|
772976
772959
|
init_ingest();
|
|
772977
|
-
init_discover();
|
|
772978
|
-
init_readers();
|
|
772979
|
-
init_paths2();
|
|
772980
772960
|
});
|
|
772981
772961
|
|
|
772982
772962
|
// node_modules/graphql/jsutils/devAssert.mjs
|
|
@@ -790559,7 +790539,6 @@ var init_semantic = __esm(() => {
|
|
|
790559
790539
|
init_llm();
|
|
790560
790540
|
init_gap_repair();
|
|
790561
790541
|
init_service4();
|
|
790562
|
-
init_self_improvement();
|
|
790563
790542
|
});
|
|
790564
790543
|
|
|
790565
790544
|
// node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/home-graph/helpers.js
|
|
@@ -794528,40 +794507,8 @@ var init_map_view = __esm(() => {
|
|
|
794528
794507
|
});
|
|
794529
794508
|
|
|
794530
794509
|
// node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/home-graph/types.js
|
|
794531
|
-
var
|
|
794510
|
+
var HOME_GRAPH_CAPABILITIES;
|
|
794532
794511
|
var init_types15 = __esm(() => {
|
|
794533
|
-
HOME_GRAPH_NODE_KINDS = [
|
|
794534
|
-
"ha_home",
|
|
794535
|
-
"ha_entity",
|
|
794536
|
-
"ha_device",
|
|
794537
|
-
"ha_area",
|
|
794538
|
-
"ha_automation",
|
|
794539
|
-
"ha_script",
|
|
794540
|
-
"ha_scene",
|
|
794541
|
-
"ha_label",
|
|
794542
|
-
"ha_integration",
|
|
794543
|
-
"ha_room",
|
|
794544
|
-
"ha_device_passport",
|
|
794545
|
-
"ha_maintenance_item",
|
|
794546
|
-
"ha_troubleshooting_case",
|
|
794547
|
-
"ha_purchase",
|
|
794548
|
-
"ha_network_node"
|
|
794549
|
-
];
|
|
794550
|
-
HOME_GRAPH_RELATIONS = [
|
|
794551
|
-
"controls",
|
|
794552
|
-
"located_in",
|
|
794553
|
-
"belongs_to_device",
|
|
794554
|
-
"has_manual",
|
|
794555
|
-
"has_receipt",
|
|
794556
|
-
"has_warranty",
|
|
794557
|
-
"has_issue",
|
|
794558
|
-
"fixed_by",
|
|
794559
|
-
"uses_battery",
|
|
794560
|
-
"connected_via",
|
|
794561
|
-
"part_of_network",
|
|
794562
|
-
"mentioned_by",
|
|
794563
|
-
"source_for"
|
|
794564
|
-
];
|
|
794565
794512
|
HOME_GRAPH_CAPABILITIES = [
|
|
794566
794513
|
"knowledge-space-isolation",
|
|
794567
794514
|
"snapshot-sync",
|
|
@@ -795968,7 +795915,6 @@ var init_service5 = __esm(() => {
|
|
|
795968
795915
|
var init_home_graph = __esm(() => {
|
|
795969
795916
|
init_service5();
|
|
795970
795917
|
init_extension();
|
|
795971
|
-
init_types15();
|
|
795972
795918
|
});
|
|
795973
795919
|
|
|
795974
795920
|
// node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/store-refinement.js
|
|
@@ -798359,14 +798305,10 @@ var init_service6 = __esm(() => {
|
|
|
798359
798305
|
var init_project_planning = __esm(() => {
|
|
798360
798306
|
init_service6();
|
|
798361
798307
|
init_helpers3();
|
|
798362
|
-
init_readiness();
|
|
798363
798308
|
});
|
|
798364
798309
|
|
|
798365
798310
|
// node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/persistence.js
|
|
798366
|
-
var init_persistence =
|
|
798367
|
-
init_store_schema();
|
|
798368
|
-
init_store_load();
|
|
798369
|
-
});
|
|
798311
|
+
var init_persistence = () => {};
|
|
798370
798312
|
|
|
798371
798313
|
// node_modules/@pellux/goodvibes-sdk/dist/platform/knowledge/projections.js
|
|
798372
798314
|
class KnowledgeProjectionService {
|
|
@@ -801871,21 +801813,21 @@ var init_service7 = __esm(() => {
|
|
|
801871
801813
|
var exports_knowledge = {};
|
|
801872
801814
|
__export(exports_knowledge, {
|
|
801873
801815
|
withKnowledgeSpace: () => withKnowledgeSpace,
|
|
801874
|
-
uniqKnowledgeValues: () =>
|
|
801875
|
-
stabilizeKnowledgeText: () =>
|
|
801876
|
-
runKnowledgeSemanticSelfImprovement: () =>
|
|
801816
|
+
uniqKnowledgeValues: () => uniq3,
|
|
801817
|
+
stabilizeKnowledgeText: () => stableText2,
|
|
801818
|
+
runKnowledgeSemanticSelfImprovement: () => runKnowledgeSemanticSelfImprovement2,
|
|
801877
801819
|
resolveProjectPlanningSpace: () => resolveProjectPlanningSpace,
|
|
801878
|
-
resolveKnowledgeDbPathFromControlPlaneDir: () =>
|
|
801820
|
+
resolveKnowledgeDbPathFromControlPlaneDir: () => resolveKnowledgeDbPathFromControlPlaneDir2,
|
|
801879
801821
|
renderPacket: () => renderPacket,
|
|
801880
801822
|
renderKnowledgeSchemaSql: () => renderKnowledgeSchemaSql,
|
|
801881
801823
|
renderKnowledgeMap: () => renderKnowledgeMap,
|
|
801882
801824
|
readKnowledgeSearchText: () => readKnowledgeSearchText,
|
|
801883
|
-
readBrowserKnowledgeProfile: () =>
|
|
801825
|
+
readBrowserKnowledgeProfile: () => readBrowserKnowledgeProfile2,
|
|
801884
801826
|
projectPlanningSourceId: () => projectPlanningSourceId,
|
|
801885
801827
|
projectPlanningProjectIdFromPath: () => projectPlanningProjectIdFromPath,
|
|
801886
801828
|
projectPlanningCanonicalUri: () => projectPlanningCanonicalUri,
|
|
801887
801829
|
projectKnowledgeSpaceId: () => projectKnowledgeSpaceId,
|
|
801888
|
-
parseKnowledgeJsonValue: () =>
|
|
801830
|
+
parseKnowledgeJsonValue: () => parseJsonValue2,
|
|
801889
801831
|
normalizeProjectId: () => normalizeProjectId,
|
|
801890
801832
|
normalizeKnowledgeSpaceId: () => normalizeKnowledgeSpaceId,
|
|
801891
801833
|
normalizeHomeAssistantInstallationId: () => normalizeHomeAssistantInstallationId,
|
|
@@ -801893,12 +801835,12 @@ __export(exports_knowledge, {
|
|
|
801893
801835
|
materializeGeneratedKnowledgeProjection: () => materializeGeneratedKnowledgeProjection,
|
|
801894
801836
|
looksLikeRawPdfPayload: () => looksLikeRawPdfPayload,
|
|
801895
801837
|
looksBinaryLikeText: () => looksBinaryLikeText,
|
|
801896
|
-
loadKnowledgeStoreSnapshot: () =>
|
|
801838
|
+
loadKnowledgeStoreSnapshot: () => loadKnowledgeStoreSnapshot2,
|
|
801897
801839
|
listGeneratedKnowledgePages: () => listGeneratedKnowledgePages,
|
|
801898
|
-
listBrowserKinds: () =>
|
|
801840
|
+
listBrowserKinds: () => listBrowserKinds2,
|
|
801899
801841
|
knowledgeSpaceMetadata: () => knowledgeSpaceMetadata,
|
|
801900
801842
|
knowledgePageSourceWeight: () => knowledgePageSourceWeight,
|
|
801901
|
-
knowledgeNowMs: () =>
|
|
801843
|
+
knowledgeNowMs: () => nowMs2,
|
|
801902
801844
|
knowledgeExtractionNeedsRefresh: () => knowledgeExtractionNeedsRefresh,
|
|
801903
801845
|
isUsefulKnowledgePageSourceCandidate: () => isUsefulKnowledgePageSourceCandidate,
|
|
801904
801846
|
isUsefulKnowledgePageSource: () => isUsefulKnowledgePageSource,
|
|
@@ -801918,12 +801860,12 @@ __export(exports_knowledge, {
|
|
|
801918
801860
|
generatedKnowledgeSourceId: () => generatedKnowledgeSourceId,
|
|
801919
801861
|
generatedKnowledgeCanonicalUri: () => generatedKnowledgeCanonicalUri,
|
|
801920
801862
|
extractKnowledgeArtifact: () => extractKnowledgeArtifact,
|
|
801921
|
-
evaluateProjectPlanningReadiness: () =>
|
|
801922
|
-
discoverBrowserKnowledgeProfiles: () =>
|
|
801863
|
+
evaluateProjectPlanningReadiness: () => evaluateProjectPlanningReadiness2,
|
|
801864
|
+
discoverBrowserKnowledgeProfiles: () => discoverBrowserKnowledgeProfiles2,
|
|
801923
801865
|
createWebKnowledgeGapRepairer: () => createWebKnowledgeGapRepairer,
|
|
801924
801866
|
createProviderBackedKnowledgeSemanticLlm: () => createProviderBackedKnowledgeSemanticLlm,
|
|
801925
801867
|
createMemoryApi: () => createMemoryApi,
|
|
801926
|
-
createKnowledgeSchema: () =>
|
|
801868
|
+
createKnowledgeSchema: () => createSchema3,
|
|
801927
801869
|
createKnowledgeApi: () => createKnowledgeApi,
|
|
801928
801870
|
createDefaultKnowledgeConnectorRegistry: () => createDefaultKnowledgeConnectorRegistry,
|
|
801929
801871
|
compareKnowledgePageSources: () => compareKnowledgePageSources,
|
|
@@ -804387,7 +804329,7 @@ var init_delivery_manager = __esm(() => {
|
|
|
804387
804329
|
});
|
|
804388
804330
|
|
|
804389
804331
|
// node_modules/@pellux/goodvibes-sdk/dist/platform/automation/scheduler-capacity.js
|
|
804390
|
-
function computeSchedulerCapacity(slotsTotal, runs,
|
|
804332
|
+
function computeSchedulerCapacity(slotsTotal, runs, nowMs3 = Date.now()) {
|
|
804391
804333
|
let slotsInUse = 0;
|
|
804392
804334
|
const queuedRuns = [];
|
|
804393
804335
|
for (const run7 of runs) {
|
|
@@ -804397,7 +804339,7 @@ function computeSchedulerCapacity(slotsTotal, runs, nowMs2 = Date.now()) {
|
|
|
804397
804339
|
queuedRuns.push(run7);
|
|
804398
804340
|
}
|
|
804399
804341
|
const queueDepth = queuedRuns.length;
|
|
804400
|
-
const oldestQueuedAgeMs = queueDepth > 0 ?
|
|
804342
|
+
const oldestQueuedAgeMs = queueDepth > 0 ? nowMs3 - Math.min(...queuedRuns.map((r6) => r6.queuedAt)) : null;
|
|
804401
804343
|
return { slotsTotal, slotsInUse, queueDepth, oldestQueuedAgeMs };
|
|
804402
804344
|
}
|
|
804403
804345
|
|
|
@@ -830785,7 +830727,7 @@ var createStyledCell = (char, overrides = {}) => ({
|
|
|
830785
830727
|
// src/version.ts
|
|
830786
830728
|
import { readFileSync } from "fs";
|
|
830787
830729
|
import { join } from "path";
|
|
830788
|
-
var _version = "1.5.
|
|
830730
|
+
var _version = "1.5.8";
|
|
830789
830731
|
try {
|
|
830790
830732
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
|
|
830791
830733
|
_version = typeof pkg.version === "string" ? pkg.version : _version;
|
|
@@ -855898,7 +855840,7 @@ var WORK_PLAN_STATUSES = [
|
|
|
855898
855840
|
"failed",
|
|
855899
855841
|
"cancelled"
|
|
855900
855842
|
];
|
|
855901
|
-
function
|
|
855843
|
+
function nowMs3() {
|
|
855902
855844
|
return Date.now();
|
|
855903
855845
|
}
|
|
855904
855846
|
function isObject4(value) {
|
|
@@ -856004,7 +855946,7 @@ class WorkPlanStore {
|
|
|
856004
855946
|
if (!normalizedTitle)
|
|
856005
855947
|
throw new Error("Work plan item title is required.");
|
|
856006
855948
|
const plan = this.readPlan();
|
|
856007
|
-
const time4 =
|
|
855949
|
+
const time4 = nowMs3();
|
|
856008
855950
|
const item = {
|
|
856009
855951
|
id: createItemId(),
|
|
856010
855952
|
title: normalizedTitle,
|
|
@@ -856028,7 +855970,7 @@ class WorkPlanStore {
|
|
|
856028
855970
|
updateItem(idOrPrefix, patch2) {
|
|
856029
855971
|
const plan = this.readPlan();
|
|
856030
855972
|
const item = this.resolveItem(plan, idOrPrefix);
|
|
856031
|
-
const time4 =
|
|
855973
|
+
const time4 = nowMs3();
|
|
856032
855974
|
const nextStatus = patch2.status ?? item.status;
|
|
856033
855975
|
const next = this.pruneItem({
|
|
856034
855976
|
...item,
|
|
@@ -856061,7 +856003,7 @@ class WorkPlanStore {
|
|
|
856061
856003
|
removeItem(idOrPrefix) {
|
|
856062
856004
|
const plan = this.readPlan();
|
|
856063
856005
|
const item = this.resolveItem(plan, idOrPrefix);
|
|
856064
|
-
const time4 =
|
|
856006
|
+
const time4 = nowMs3();
|
|
856065
856007
|
const remaining = plan.items.filter((candidate) => candidate.id !== item.id);
|
|
856066
856008
|
this.writePlan({
|
|
856067
856009
|
...plan,
|
|
@@ -856081,7 +856023,7 @@ class WorkPlanStore {
|
|
|
856081
856023
|
...plan,
|
|
856082
856024
|
items: remaining,
|
|
856083
856025
|
activeItemId: remaining[0]?.id,
|
|
856084
|
-
updatedAt:
|
|
856026
|
+
updatedAt: nowMs3()
|
|
856085
856027
|
});
|
|
856086
856028
|
return removed;
|
|
856087
856029
|
}
|
|
@@ -856120,7 +856062,7 @@ class WorkPlanStore {
|
|
|
856120
856062
|
const parsed = JSON.parse(raw);
|
|
856121
856063
|
if (!isObject4(parsed))
|
|
856122
856064
|
return this.createEmptyPlan();
|
|
856123
|
-
const time4 =
|
|
856065
|
+
const time4 = nowMs3();
|
|
856124
856066
|
const createdAt = typeof parsed.createdAt === "number" ? parsed.createdAt : time4;
|
|
856125
856067
|
const updatedAt = typeof parsed.updatedAt === "number" ? parsed.updatedAt : createdAt;
|
|
856126
856068
|
const items = Array.isArray(parsed.items) ? parsed.items.map((item) => normalizeItem(item, createdAt)).filter((item) => item !== null) : [];
|
|
@@ -856139,7 +856081,7 @@ class WorkPlanStore {
|
|
|
856139
856081
|
};
|
|
856140
856082
|
}
|
|
856141
856083
|
createEmptyPlan() {
|
|
856142
|
-
const time4 =
|
|
856084
|
+
const time4 = nowMs3();
|
|
856143
856085
|
return {
|
|
856144
856086
|
id: createPlanId(this.options.projectId, this.options.projectRoot),
|
|
856145
856087
|
projectId: this.options.projectId,
|
|
@@ -901803,9 +901745,9 @@ Run goodvibes-agent skills discover to inspect available skill files.`, 1);
|
|
|
901803
901745
|
}
|
|
901804
901746
|
|
|
901805
901747
|
// src/cli/memory-command.ts
|
|
901748
|
+
init_state();
|
|
901806
901749
|
import { mkdirSync as mkdirSync83, readFileSync as readFileSync105, writeFileSync as writeFileSync72 } from "fs";
|
|
901807
901750
|
import { dirname as dirname80, resolve as resolve43 } from "path";
|
|
901808
|
-
init_state();
|
|
901809
901751
|
var VALID_CLASSES2 = ["decision", "constraint", "incident", "pattern", "fact", "risk", "runbook", "architecture", "ownership"];
|
|
901810
901752
|
var VALID_SCOPES4 = ["session", "project", "team"];
|
|
901811
901753
|
var VALID_REVIEW_STATES3 = ["fresh", "reviewed", "stale", "contradicted"];
|
|
@@ -901939,10 +901881,7 @@ function timestamp(value) {
|
|
|
901939
901881
|
return new Date(value).toISOString().slice(0, 19).replace("T", " ");
|
|
901940
901882
|
}
|
|
901941
901883
|
function memoryDbPath(runtime2) {
|
|
901942
|
-
return
|
|
901943
|
-
workingDirectory: runtime2.workingDirectory,
|
|
901944
|
-
homeDirectory: runtime2.homeDirectory
|
|
901945
|
-
}).resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "memory.sqlite");
|
|
901884
|
+
return resolveCanonicalMemoryDbPath(runtime2.homeDirectory);
|
|
901946
901885
|
}
|
|
901947
901886
|
async function withMemory(runtime2, fn) {
|
|
901948
901887
|
const path7 = memoryDbPath(runtime2);
|
|
@@ -967711,8 +967650,8 @@ function formatDigestTime(at, from = Date.now()) {
|
|
|
967711
967650
|
return `yesterday ${time4}`;
|
|
967712
967651
|
return `${d4.toLocaleDateString(undefined, { month: "short", day: "numeric" })} ${time4}`;
|
|
967713
967652
|
}
|
|
967714
|
-
function formatRelativeTime(targetMs,
|
|
967715
|
-
const diffMs = targetMs -
|
|
967653
|
+
function formatRelativeTime(targetMs, nowMs4 = Date.now()) {
|
|
967654
|
+
const diffMs = targetMs - nowMs4;
|
|
967716
967655
|
if (diffMs <= 0)
|
|
967717
967656
|
return "soon";
|
|
967718
967657
|
const diffMin = Math.round(diffMs / 60000);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
|
|
6
6
|
"type": "module",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MemoryRecord, MemoryRegistry, MemoryVectorStats } from '@pellux/goodvibes-sdk/platform/state';
|
|
2
|
-
//
|
|
2
|
+
// The recall-honesty floor + eligibility receipt now live in the SDK as
|
|
3
3
|
// the ONE cross-surface contract (memory-recall-contract.ts) instead of being defined
|
|
4
4
|
// per surface. This file re-exports them unchanged so every existing agent consumer
|
|
5
5
|
// keeps importing from './memory-prompt.ts', while the SDK is the single source of the
|
|
@@ -32,9 +32,9 @@ function formatMemoryLine(record: MemoryRecord): string {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* Per-turn semantic ranking of an already-eligible memory set
|
|
35
|
+
* Per-turn semantic ranking of an already-eligible memory set.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
37
|
+
* Eligibility (confidence + reviewState + provenance) shipped as the hard trust
|
|
38
38
|
* gate but had no per-turn query to rank WITHIN that eligible set — records were only
|
|
39
39
|
* ever ordered by stored confidence/recency, regardless of whether they had anything to
|
|
40
40
|
* do with what the user actually just asked. `rankMemoryForTurn` never touches the gate
|
|
@@ -103,7 +103,7 @@ export const OPERATOR_ACTIONS: Record<OperatorActionId, OperatorActionDescriptor
|
|
|
103
103
|
pathTemplate: '/api/automation/jobs/{jobId}/run',
|
|
104
104
|
targetField: 'jobId',
|
|
105
105
|
},
|
|
106
|
-
//
|
|
106
|
+
// automation.jobs.pause/resume were retired (redundant with
|
|
107
107
|
// disable/enable — same {id,enabled} output, same semantics). The
|
|
108
108
|
// user-facing "pause"/"resume" verb is unchanged; only the wire action +
|
|
109
109
|
// path moved to the canonical disable/enable methods.
|
|
@@ -140,7 +140,7 @@ function receiptSegment(input: Omit<PromptContextReceiptSegment, 'approxTokens'>
|
|
|
140
140
|
|
|
141
141
|
function buildRuntimePromptReceiptSegments(input: RuntimePromptCompositionInput): readonly PromptContextReceiptSegment[] {
|
|
142
142
|
const vibe = discoverVibeFiles(input.shellPaths);
|
|
143
|
-
//
|
|
143
|
+
// The VIBE prompt is a PROJECTION of persona/constraint records, not a
|
|
144
144
|
// re-read of the files (discoverVibeFiles above stays for the file-discovery receipt).
|
|
145
145
|
const vibePrompt = buildVibeProjectionPrompt(input.memoryRegistry) ?? '';
|
|
146
146
|
const projectContext = discoverProjectContextFiles(input.shellPaths);
|
|
@@ -234,7 +234,7 @@ function buildRuntimePromptReceiptSegments(input: RuntimePromptCompositionInput)
|
|
|
234
234
|
suppressedCount: suppressedMemory.length,
|
|
235
235
|
promptChars: memoryPrompt.length,
|
|
236
236
|
promptText: memoryPrompt,
|
|
237
|
-
// Honest degrade note
|
|
237
|
+
// Honest degrade note: when per-turn relevance scoring did not
|
|
238
238
|
// run — no active-turn text, semantic index unavailable, or no vector match —
|
|
239
239
|
// say so instead of silently presenting the fallback confidence/recency order as
|
|
240
240
|
// if it were a relevance ranking.
|
|
@@ -245,7 +245,7 @@ function buildRuntimePromptReceiptSegments(input: RuntimePromptCompositionInput)
|
|
|
245
245
|
class: record.cls,
|
|
246
246
|
confidence: record.confidence,
|
|
247
247
|
reason: describeMemoryPromptEligibility(record).reason,
|
|
248
|
-
// Per-turn relevance
|
|
248
|
+
// Per-turn relevance: honest wording, only present when actually scored.
|
|
249
249
|
// F7a: the raw percent is paired with a qualitative band (see relevanceBand)
|
|
250
250
|
// so a genuinely-lower-but-real score like "28%" doesn't read as noise.
|
|
251
251
|
...(memoryRanking.scored ? { relevance: `relevance to this turn: ${memoryRanking.relevanceById.get(record.id) ?? 0}% (${relevanceBand(memoryRanking.relevanceById.get(record.id) ?? 0)})` } : {}),
|
|
@@ -86,7 +86,7 @@ export interface SessionRecordSummary {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
* Honest outcome discriminator. 'still_closed' is the
|
|
89
|
+
* Honest outcome discriminator. 'still_closed' is the heartbeat-resurrection
|
|
90
90
|
* guard: a 200 that carries conflict:{status:'closed'} with reopened:false MUST NOT
|
|
91
91
|
* be read as 'registered' or 'reopened'.
|
|
92
92
|
*/
|
package/src/agent/vibe-file.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ShellPathService } from '@/runtime/index.ts';
|
|
|
5
5
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
6
6
|
import { assertNoSecretLikeText } from './persona-registry.ts';
|
|
7
7
|
import { parseMarkdownFrontmatter, stripMarkdownFrontmatter } from './markdown-frontmatter.ts';
|
|
8
|
-
//
|
|
8
|
+
// VIBE.md is now a PROJECTION of persona/constraint records in the
|
|
9
9
|
// canonical memory store, not a separate source of truth. renderVibeProjection emits
|
|
10
10
|
// the same '## VIBE.md' block from those records (caveat preserved); the file is
|
|
11
11
|
// demoted to an import/export FORMAT folded in via vibeBodyToConstraintOptions.
|
|
@@ -213,7 +213,7 @@ export function buildVibePrompt(shellPaths: AgentVibePaths): string | null {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/**
|
|
216
|
-
*
|
|
216
|
+
* The VIBE.md prompt block as a PROJECTION of persona/constraint records.
|
|
217
217
|
*
|
|
218
218
|
* This is the store-sourced replacement for buildVibePrompt (which reads the file
|
|
219
219
|
* directly). It renders the same '## GoodVibes Agent VIBE.md' block — including the
|
|
@@ -226,7 +226,7 @@ export function buildVibeProjectionPrompt(memoryRecords: { getAll(): readonly Me
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
|
-
*
|
|
229
|
+
* Fold discovered VIBE.md files into the store as persona/constraint
|
|
230
230
|
* records — the file demoted to an IMPORT FORMAT. Each bullet becomes one record so a
|
|
231
231
|
* later single-record edit changes exactly one projected line. Secret-like content is
|
|
232
232
|
* already rejected by discoverVibeFiles (readVibeCandidate → assertNoSecretLikeText),
|
|
@@ -257,7 +257,7 @@ export async function importVibeFilesIntoMemory(
|
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
/**
|
|
260
|
-
*
|
|
260
|
+
* The persisted marker that makes the VIBE.md → memory import a strictly
|
|
261
261
|
* ONE-TIME migration. Keyed by absolute file path → content hash, so importing the same
|
|
262
262
|
* VIBE.md twice is a no-op (re-import would create near-duplicate persona records), while
|
|
263
263
|
* a NEW project's VIBE.md still migrates exactly once. Mirrors the sessions.spine-folded
|
|
@@ -300,7 +300,7 @@ function hashVibeBody(body: string): string {
|
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
/**
|
|
303
|
-
*
|
|
303
|
+
* Fold discovered VIBE.md files into persona/constraint records ONCE.
|
|
304
304
|
* Guarded by a persisted path→hash marker so it never re-imports the same file (which
|
|
305
305
|
* would create near-duplicate persona records). Called at boot AFTER memoryStore.init().
|
|
306
306
|
* Returns the number of records created this run (0 when everything is already migrated).
|
|
@@ -7,7 +7,7 @@ import type { CliCommandRuntime } from './management.ts';
|
|
|
7
7
|
/**
|
|
8
8
|
* Shared prelude for the Agent-local library CLI commands (personas, skills,
|
|
9
9
|
* skill bundles): option parsing, success/failure envelopes, and registry
|
|
10
|
-
* accessors. Split out of local-library-command.ts (
|
|
10
|
+
* accessors. Split out of local-library-command.ts (the file
|
|
11
11
|
* cleanly contained three independent command handlers glued together) so
|
|
12
12
|
* personas-command.ts, skills-command.ts, and skill-bundle-command.ts can
|
|
13
13
|
* share one option-parsing/output prelude without duplicating it.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, resolve } from 'node:path';
|
|
3
|
-
import { createShellPathService } from '@/runtime/index.ts';
|
|
4
3
|
import {
|
|
5
4
|
MemoryEmbeddingProviderRegistry,
|
|
6
5
|
MemoryRegistry,
|
|
7
6
|
MemoryStore,
|
|
7
|
+
resolveCanonicalMemoryDbPath,
|
|
8
8
|
type MemoryBundle,
|
|
9
9
|
type MemoryClass,
|
|
10
10
|
type MemoryLink,
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
} from '@pellux/goodvibes-sdk/platform/state';
|
|
19
19
|
import { assertNoSecretLikeMemoryText } from '../agent/memory-safety.ts';
|
|
20
20
|
import { formatAgentRecordReference, formatAgentRecordReviewState } from '../agent/record-labels.ts';
|
|
21
|
-
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
22
21
|
import type { CliCommandOutput } from './types.ts';
|
|
23
22
|
import type { CliCommandRuntime } from './management.ts';
|
|
24
23
|
|
|
@@ -196,11 +195,15 @@ function timestamp(value: number): string {
|
|
|
196
195
|
return new Date(value).toISOString().slice(0, 19).replace('T', ' ');
|
|
197
196
|
}
|
|
198
197
|
|
|
198
|
+
// The CLI no longer opens a private per-surface agent/memory.sqlite. It opens the
|
|
199
|
+
// ONE canonical cross-surface store (~/.goodvibes/shared/memory.sqlite) so a memory
|
|
200
|
+
// added via `goodvibes-agent memory add` is visible to the runtime, the TUI, and the
|
|
201
|
+
// SDK — and vice-versa. The old CLI-written store is folded into the canonical store
|
|
202
|
+
// (loss-free, idempotent) by the runtime's foldAgentLegacyMemory at boot, since that
|
|
203
|
+
// fold already sources shellPaths.resolveUserPath('agent', 'memory.sqlite') — the exact
|
|
204
|
+
// path this function used to write to.
|
|
199
205
|
function memoryDbPath(runtime: CliCommandRuntime): string {
|
|
200
|
-
return
|
|
201
|
-
workingDirectory: runtime.workingDirectory,
|
|
202
|
-
homeDirectory: runtime.homeDirectory,
|
|
203
|
-
}).resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'memory.sqlite');
|
|
206
|
+
return resolveCanonicalMemoryDbPath(runtime.homeDirectory);
|
|
204
207
|
}
|
|
205
208
|
|
|
206
209
|
async function withMemory<T>(runtime: CliCommandRuntime, fn: (context: MemoryContext) => Promise<T> | T): Promise<T> {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SessionManager } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* RESUME-ON-RELAUNCH
|
|
4
|
+
* RESUME-ON-RELAUNCH.
|
|
5
5
|
*
|
|
6
6
|
* The dogfood finding: relaunching the agent after a normal (non-crash) exit
|
|
7
7
|
* silently starts fresh with no offer or notice about the prior session — the
|
package/src/cli/tui-startup.ts
CHANGED
|
@@ -116,7 +116,7 @@ export function applyInitialTuiCliState(options: {
|
|
|
116
116
|
// Normal relaunch: onboarding is done and the user didn't ask for
|
|
117
117
|
// onboarding or an explicit `sessions resume`. Surface an honest,
|
|
118
118
|
// non-blocking resume affordance instead of silently starting fresh
|
|
119
|
-
// (
|
|
119
|
+
// (a dogfood finding) — never auto-resume, declining is
|
|
120
120
|
// frictionless (just start typing).
|
|
121
121
|
surfaceResumeRelaunchNotice({
|
|
122
122
|
getLastSessionPointer: () => readLastSessionPointer({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* credential-status.ts — client-side, secret-FREE credential STATUS read.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* When GoodVibes Agent acts as a CLIENT of an adopted
|
|
5
5
|
* external daemon, it reads credential *status* (configured / usable) from the
|
|
6
6
|
* daemon's shared store over the wire — the `credentials.get` operator method
|
|
7
7
|
* (GET /config/credentials, admin + read:config). It NEVER receives raw secret
|
package/src/config/index.ts
CHANGED
|
@@ -56,7 +56,7 @@ export function getConfiguredSystemPrompt(configManager: Pick<ConfigManager, 'ge
|
|
|
56
56
|
|
|
57
57
|
export { getConfiguredApiKeys, resolveApiKeys } from '@pellux/goodvibes-sdk/platform/config';
|
|
58
58
|
|
|
59
|
-
//
|
|
59
|
+
// The daemon-client credential STATUS read (secret-free, honest-degrade).
|
|
60
60
|
// Value reads above stay local/env; only the status VISIBILITY path moves to the daemon.
|
|
61
61
|
export {
|
|
62
62
|
deriveCredentialAvailability,
|
package/src/config/secrets.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import { isSecretRefInput } from '@pellux/goodvibes-sdk/platform/config';
|
|
17
17
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from './surface.ts';
|
|
18
18
|
|
|
19
|
-
//
|
|
19
|
+
// Host-vs-client split: this SecretsManager is the LOCAL-HOST
|
|
20
20
|
// read path — pinned to GOODVIBES_AGENT_SURFACE_ROOT, it resolves secret VALUES from the
|
|
21
21
|
// surface store/env for provider auth, unchanged. When the Agent acts as a CLIENT of an
|
|
22
22
|
// adopted external daemon, credential *status* (configured/usable — never bytes) is read
|
|
@@ -123,8 +123,8 @@ export function renderConversationAssistantMessage(
|
|
|
123
123
|
// `numWidth=6` (fits 999,999 lines, but wastes 3-4 gutter columns on typical
|
|
124
124
|
// messages) or rendering the numbered output into a scratch buffer and trimming.
|
|
125
125
|
// Neither is clearly better than the current two-pass measurement approach.
|
|
126
|
-
//
|
|
127
|
-
// numbers are enabled" was inaccurate:
|
|
126
|
+
// An earlier commit message's claim that this "eliminates double-parse when line
|
|
127
|
+
// numbers are enabled" was inaccurate: that commit eliminated the legacy
|
|
128
128
|
// `renderMarkdown()` duplicate used for code-block line-number mode ('code').
|
|
129
129
|
// The 'all' mode double-call is a deliberate design choice and remains unchanged.
|
|
130
130
|
const measureWidth = showAllLineNumbers ? width : 0;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Ported from the TUI (src/core/system-message-noise.ts). The TUI regexes are
|
|
10
10
|
* kept VERBATIM (provider-replay fold / agents-snapshot drop / stale-replay
|
|
11
11
|
* drop); the only agent-specific addition is the `[Terminal] Captured …` rule
|
|
12
|
-
* (
|
|
12
|
+
* (the stdout-capture leak). Dropped noise is
|
|
13
13
|
* drop-from-the-feed, NOT delete: the captured-write detail stays reachable via
|
|
14
14
|
* the activity log (the terminal-output guard logs each intercept + the count).
|
|
15
15
|
*/
|
|
@@ -46,7 +46,7 @@ const REPLAY_CHAIN_RE = /WRFC chain (\S+) transitioned .* waiting for action/;
|
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Matches the terminal-output guard's aggregate captured-write notice
|
|
49
|
-
* (
|
|
49
|
+
* (agent-specific). First-run plumbing writes a burst of direct stdout
|
|
50
50
|
* that the guard intercepts and would otherwise summarize into the Recent feed;
|
|
51
51
|
* the count stays reachable in the activity log, so the feed copy is dropped.
|
|
52
52
|
*/
|
|
@@ -57,7 +57,7 @@ const TERMINAL_CAPTURED_RE = /^\[Terminal\] Captured \d+ direct /;
|
|
|
57
57
|
* lookup, so it is trivially testable.
|
|
58
58
|
*/
|
|
59
59
|
export function classifyNoise(message: string, deps: NoiseGateDeps): NoiseVerdict {
|
|
60
|
-
//
|
|
60
|
+
// Agent-specific — the terminal-output guard's aggregate captured-write notice.
|
|
61
61
|
// Kept out of the Recent feed; the detail stays in the activity log.
|
|
62
62
|
if (TERMINAL_CAPTURED_RE.test(message)) {
|
|
63
63
|
return DROP;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* thinking-overlay.ts
|
|
2
|
+
* thinking-overlay.ts — the thinking-indicator overlay + its honest
|
|
3
3
|
* stall clock, extracted from main.ts's render loop.
|
|
4
4
|
*
|
|
5
5
|
* The SDK orchestrator surfaces no lastDeltaAtMs / reconnect signal directly, so
|
|
@@ -42,7 +42,7 @@ function unconfirmed(editor: AgentWorkspaceLocalEditor, message: string, status:
|
|
|
42
42
|
/**
|
|
43
43
|
* The submission data table for the kinds this module builds itself (delegate-task and
|
|
44
44
|
* workplan/notify/secret/profile kinds keep dispatching to their own sibling submission
|
|
45
|
-
* modules below, unchanged).
|
|
45
|
+
* modules below, unchanged). Split out of the single ~570-line
|
|
46
46
|
* `buildAgentWorkspaceBasicCommandEditorSubmission` if-chain, mirroring the
|
|
47
47
|
* construction-side split in agent-workspace-basic-command-editors.ts.
|
|
48
48
|
*/
|
|
@@ -127,7 +127,7 @@ function modelPinUnpinSpec(kind: AgentWorkspaceBasicOwnCommandEditorKind): Agent
|
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
129
|
* The field-spec data table for the kinds this module builds itself (the rest are
|
|
130
|
-
* delegated to sibling domain modules above).
|
|
130
|
+
* delegated to sibling domain modules above). Split out of the single
|
|
131
131
|
* ~600-line `createAgentWorkspaceBasicCommandEditor` if-chain into a data table, the
|
|
132
132
|
* same shape used by every other agent-workspace command-editor domain.
|
|
133
133
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Calendar connect card
|
|
2
|
+
* Calendar connect card — promotes the "Calendar workflows" workspace
|
|
3
3
|
* card from a dead guidance card into a real, dispatchable action.
|
|
4
4
|
*
|
|
5
5
|
* GROUNDED: unlike email, there is no external calendar account/CalDAV
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Calendar OAuth advanced-credentials wizard
|
|
2
|
+
* Calendar OAuth advanced-credentials wizard.
|
|
3
3
|
*
|
|
4
4
|
* The DEFAULT connect experience needs no card at all: `/calendar connect google`
|
|
5
5
|
* (or `outlook`) uses the bundled project client id + PKCE and opens the browser.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Calendar subscribe wizard
|
|
2
|
+
* Calendar subscribe wizard — the "Calendar workflows" card's real
|
|
3
3
|
* connect flow. Subscribes to an external calendar by its iCalendar feed URL
|
|
4
4
|
* (Google "secret address", Outlook published .ics, or any .ics URL), READ-ONLY.
|
|
5
5
|
*
|